def test_query_hello(self): connection = create_autospec(Connection) connection.read.return_value = b'\x51\x00\x00\xa0\x00\x00\x9d\x4b\x01\x00\xd8\x19' protocol = Protocol(connection) self.assertEqual(b'\x01\0', protocol.query(Range(0xa000, 1))) connection.write.assert_called_once_with( b'\x51\x00\x00\xa0\x00\x00\x9d\x4b')
def test_read_retry(self): connection = create_autospec(Connection) connection.read.side_effect = [ b'\x51', b'\x00\x00', b'\xa0', b'\x00', b'\x00', b'\x9d\x4b\x01\x00', b'\xd8', b'\x19', ] protocol = Protocol(connection) self.assertEqual(b'\x01\0', protocol.query(Range(0xa000, 1))) connection.read.assert_has_calls([ call(12), call(11), call(9), call(8), call(7), call(6), call(2), call(1), ]) connection.write.assert_called_once_with( b'\x51\x00\x00\xa0\x00\x00\x9d\x4b')
def test_query_invalid_crc_response(self): response = b'12345678901234567890123456' connection = create_autospec(Connection) connection.read.return_value = response protocol = Protocol(connection) with self.assertRaises(ValidationException) as context: protocol.query(Range(0xa000, 8)) self.assertEqual('Incorrect CRC (0x958a)', context.exception.args[0])
def test_query_hash(self): sent = b'Q\x07\x00\x00\x1f\x00\xcfb' read = b"Q\x07\x00\x00\x1f\x00\xcfbz\xb2\x9f\xdeh\x1a\xe0\xb1\'\'\x08\x8f\x80\xc4\xba\x8b\xa0@" connection = create_autospec(Connection) connection.read.return_value = read protocol = Protocol(connection) self.assertEqual( b'z\xb2\x9f\xdeh\x1a\xe0\xb1\'\'\x08\x8f\x80\xc4\xba\x8b', protocol.query(Range(0x1f0000, 8))) connection.write.assert_called_once_with(sent)
def test_login_default_password(self): password = b"Selectronic SP PRO" login_hash_sent = b'Q\x07\x00\x00\x1f\x00\xcfb' login_hash_read = b"Q\x07\x00\x00\x1f\x00\xcfbz\xb2\x9f\xdeh\x1a\xe0\xb1\'\'\x08\x8f\x80\xc4\xba\x8b\xa0@" login_challenge = b'W\x07\x00\x00\x1f\x005z\xb6\xd16\x04\x08\x0c\x87\xce\x81\xc1\x82\xc6o\xa5\xfb5w\xaa' login_status_sent = b'Q\x00\x10\x00\x1f\x00\xb2\x91' login_status_read = b'Q\x00\x10\x00\x1f\x00\xb2\x91\x01\x00\xd8\x19' connection = create_autospec(Connection) connection.read.side_effect = [ login_hash_read, login_challenge, login_status_read, ] protocol = Protocol(connection, password) protocol.login() connection.write.assert_has_calls([ call(login_hash_sent), call(login_challenge), call(login_status_sent), ])
def test_query_short_response(self): connection = create_autospec(Connection) connection.read.side_effect = [ b'123456', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', ] protocol = Protocol(connection) with self.assertRaises(BufferError) as context: protocol.query(Range(0xa000, 9)) self.assertEqual('Expected 28 bytes, but only able to read 6', context.exception.args[0])
def test_login_alternative_password(self): password = b"foo" login_hash_sent = b'Q\x07\x00\x00\x1f\x00\xcfb' login_hash_read = b'Q\x07\x00\x00\x1f\x00\xcfb\xb7\n\xd7\x15\xab\xccl;{\x96\xf3\x98\xf0z\xbf\x12\x02E' login_challenge = b'W\x07\x00\x00\x1f\x005z\xa2\xf1\xdf\xfd\xbaA\xa1\xedD\x12\x82\xe7O\x8d\x15_\xc0\x8b' login_status_sent = b'Q\x00\x10\x00\x1f\x00\xb2\x91' login_status_read = b'Q\x00\x10\x00\x1f\x00\xb2\x91\x01\x00\xd8\x19' connection = create_autospec(Connection) connection.read.side_effect = [ login_hash_read, login_challenge, login_status_read, ] protocol = Protocol(connection, password) protocol.login() connection.write.assert_has_calls([ call(login_hash_sent), call(login_challenge), call(login_status_sent), ])
def test_login_failed(self): password = b"Selectronic SP PRO" login_hash_sent = b'Q\x07\x00\x00\x1f\x00\xcfb' login_hash_read = b"Q\x07\x00\x00\x1f\x00\xcfbz\xb2\x9f\xdeh\x1a\xe0\xb1\'\'\x08\x8f\x80\xc4\xba\x8b\xa0@" login_challenge = b'W\x07\x00\x00\x1f\x005z\xb6\xd16\x04\x08\x0c\x87\xce\x81\xc1\x82\xc6o\xa5\xfb5w\xaa' login_status_sent = b'Q\x00\x10\x00\x1f\x00\xb2\x91' login_status_read = b'Q\x00\x10\x00\x1f\x00\xb2\x91\x00\x00\x00\x00' connection = create_autospec(Connection) connection.read.side_effect = [ login_hash_read, login_challenge, login_status_read, ] protocol = Protocol(connection, password) with self.assertRaises(ValidationException) as context: protocol.login() self.assertEqual('Login failed', context.exception.args[0]) connection.write.assert_has_calls([ call(login_hash_sent), call(login_challenge), call(login_status_sent), ])
def run(args): protocol = Protocol(connection.create()) protocol.login() # Before 0xa001 we don't get anything back start = 0xa001 # How much to get at a time fetch_words = 0x100 line_words = 0x10 # When to stop end = 0xa301 print( ' 1 2 3 4 5 6 7 8 9 a b c d e f 0' ) for address in range(start, end, fetch_words): memory = protocol.query(Range(address, fetch_words)) for offset in range(0, fetch_words, line_words): start_bytes = offset * 2 end_bytes = (offset + line_words) * 2 sub_memory = memory[start_bytes:end_bytes] hex_memory = binascii.hexlify(sub_memory) hex_address = binascii.hexlify(struct.pack(">H", address + offset)) print(b''.join([b'0x', hex_address, b' ', hex_memory]).decode('utf-8'))
class Proxy: def __init__(self): self.__protocol = Protocol(connection.create()) self.__buffer = bytearray() self.__serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) def bind(self, address, port): self.__serversocket.bind((address, port)) # become a server socket self.__serversocket.listen(5) while True: logging.info("Waiting for TCP connection on %s:%d" % (address, port)) self.wait_connection() def wait_connection(self): (clientsocket, address) = self.__serversocket.accept() self.handle_connection(clientsocket) def handle_connection(self, socket): logging.info("Got connection") while True: self.wait_message(socket) def wait_message(self, socket): while (len(self.__buffer) < 2): self.__buffer.extend(socket.recv(1)) wl = Request.calculate_message_length(self.__buffer) while len(self.__buffer) < wl: self.__buffer.extend(socket.recv(1)) msg = self.__buffer[0:wl] self.__buffer = self.__buffer[wl:] req = Request(msg) logging.debug("request: %s" % req) res = self.__protocol.send(req) msg = res.get_message() logging.debug("response: %s" % bytes(msg)) socket.sendall(msg)
def __init__(self): self.__protocol = Protocol(connection.create()) self.__buffer = bytearray() self.__serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def __init__(self, protocol: Protocol = None): self.__protocol = protocol or Protocol()