def __init__(self, client, server): super(ProxyPair, self).__init__() self.client = client self.server = server log.debug("C: <CONNECT> {} -> {}".format(self.client.address, self.server.address)) log.debug("C: <BOLT> {}".format(h(self.forward_bytes(client, server, 4)))) log.debug("C: <VERSION> {}".format(h(self.forward_bytes(client, server, 16)))) raw_bolt_version = self.forward_bytes(server, client, 4) bolt_version, = raw_unpack(UINT_32, raw_bolt_version) self.client.bolt_version = self.server.bolt_version = bolt_version log.debug("S: <VERSION> {}".format(h(raw_bolt_version))) self.client_messages = {v: k for k, v in CLIENT[self.client.bolt_version].items()} self.server_messages = {v: k for k, v in SERVER[self.server.bolt_version].items()}
def send_bytes(self, sock, data): try: sock.sendall(data) except OSError: log.error("S: <GONE>") raise SystemExit(EXIT_OFF_SCRIPT) else: return h(data)
def test_mixed_list(self): self.assertEqual( h(pack([1, True, 3.14, "fünf"])), '94:01:C3:C1:40:09:1E:B8:51:EB:85:1F:85:66:C3:BC:6E:66')
def test_string(self): self.assertEqual(h(pack("Übergröße")), '8C:C3:9C:62:65:72:67:72:C3:B6:C3:9F:65')
def test_boolean(self): self.assertEqual(h(pack(False)), 'C2')
def test_float(self): self.assertEqual(h(pack(6.283185307179586)), 'C1:40:19:21:FB:54:44:2D:18')
def test_integer(self): self.assertEqual(h(pack(1)), '01') self.assertEqual(h(pack(1234)), 'C9:04:D2')
def handle_request(self, sock): v = self.peers[sock].bolt_version chunked_data = b"" message_data = b"" chunk_size = -1 debug = [] while chunk_size != 0: chunk_header = sock.recv(2) if len(chunk_header) == 0: self.stop() return chunked_data += chunk_header chunk_size, = raw_unpack(UINT_16, chunk_header) if chunk_size > 0: chunk = sock.recv(chunk_size) chunked_data += chunk message_data += chunk else: chunk = b"" debug.append(" [%s] %s" % (h(chunk_header), h(chunk))) request = unpack(message_data) if self.script.match_request(request): # explicitly matched log.debug("C: %s", message_repr(v, request)) elif self.script.match_auto_request(request): # auto matched log.debug("C! %s", message_repr(v, request)) else: # not matched if self.script.lines: expected = message_repr(v, self.script.lines[0].message) else: expected = "END OF SCRIPT" log.debug("C: %s", message_repr(v, request)) log.error("Message mismatch (expected <%s>, " "received <%s>)", expected, message_repr(v, request)) self.stop() raise SystemExit(EXIT_OFF_SCRIPT) responses = self.script.match_responses() if not responses and self.script.match_auto_request(request): # These are hard-coded and therefore not very future-proof. if request.tag in (CLIENT[v].get("HELLO"), CLIENT[v].get("INIT")): responses = [ Structure( SERVER[v]["SUCCESS"], {"server": server_agents.get(v, "Neo4j/9.99.999")}) ] elif request.tag == CLIENT[v].get("GOODBYE"): log.debug("S: <EXIT>") self.stop() raise SystemExit(EXIT_OK) elif request.tag == CLIENT[v]["RUN"]: responses = [Structure(SERVER[v]["SUCCESS"], {"fields": []})] else: responses = [Structure(SERVER[v]["SUCCESS"], {})] for response in responses: if isinstance(response, Structure): data = pack(response) self.send_chunk(sock, data) self.send_chunk(sock) log.debug( "S: %s", message_repr(v, Structure(response.tag, *response.fields))) elif isinstance(response, ExitCommand): self.stop() raise SystemExit(EXIT_OK) else: raise RuntimeError("Unknown response type %r" % (response, ))