def messageHandler(self, sSocket): serverAddr= sSocket.getpeername()[0] serverPort=sSocket.getpeername()[1] sSocket.send(messages.version_pkt(MY_IP, serverAddr,serverPort).to_bytes()) while True: dataReceived = sSocket.recv(1024) if not dataReceived: #will close the socket break; msg = MsgSerializable().from_bytes(dataReceived) print('on_new_server') print('received ',msg) if isinstance(msg,msg_version): self.outbound_connections.add(serverAddr) sSocket.send(msg_verack().to_bytes()) print('sent verack') sSocket.send(msg_getaddr().to_bytes()) print('sent msg_getaddr') if isinstance(msg,msg_addr): for peer in msg.addrs: if peer.ip not in self.outbound_connections and peer.ip != MY_IP: print('new peer found'+peer.ip) t = threading.Thread(target=self.connect,args=(peer.ip, peer.port)) t.start() time.sleep(SLEEP_TIME) sSocket.close()
def messageHandler(self, clientsocket, addr): while True: dataReceived = clientsocket.recv(1024) if not dataReceived: #will close the socket break; msg = MsgSerializable().from_bytes(dataReceived) print('received ',msg) print( isinstance(msg,msg_version)) if isinstance(msg,msg_version): clientsocket.send(msg_verack().to_bytes()) self.inbound_connections.add(addr[0]) print('sent verack') clientsocket.send( messages.version_pkt(MY_IP, addr[0],self.port).to_bytes() ) print('sent version_pkt') if isinstance(msg,msg_getaddr): perrAddrs = [] for peer in self.inbound_connections: perrAddr = CAddress() perrAddr.port=self.port perrAddr.nTime = int(time.time()) perrAddr.ip = peer perrAddrs.append(perrAddr) rMsg= msg_addr() rMsg.addrs = perrAddrs print(rMsg) clientsocket.send(rMsg.to_bytes()) print('sent msg_addr') time.sleep(SLEEP_TIME) clientsocket.close()
def capture_messages(self, expected_message_types: list, timeout: int = 20, buf_size: int = 1024, ignore_empty: bool = False) -> list: deadline = time() + timeout found = [] partial_message = None while expected_message_types and time() < deadline: try: received_data = self.connection.recv(buf_size) if partial_message: received_data = partial_message + received_data except socket.timeout: continue if not received_data: sleep(0.1) continue for raw_message in self.split_message(received_data): try: message = MsgSerializable.from_bytes(raw_message) except (SerializationError, SerializationTruncationError, ValueError): partial_message = raw_message continue partial_message = None if not message: # unknown message type, skipping continue msg_type = type(message) if msg_type is msg_ping: logger.debug('Got ping, sending pong.') self.send_pong(message) elif msg_type is msg_version: logger.debug('Saving version') self.protocol_version = message if msg_type in expected_message_types: found.append(message) expected_message_types.remove(msg_type) logger.debug('Found %s, %s more to catch', msg_type.command.upper(), len(expected_message_types)) if not expected_message_types: return found if not ignore_empty: logger.error('Not all messages could be captured')
def _handle_recv(self): while True: try: msg = MsgSerializable.stream_deserialize( self.conn.makefile(mode='r'), protover=self.protover) except Exception as e: msg = e if not self._stopflag.is_set(): print("Peer connection closed unexpectedly.") break finally: self.recvq.put(msg)
def _process_message(self, **kwargs): msg = MsgSerializable.stream_deserialize(Wrapper(self.my_socket)) if msg.command == b"version": # TODO conglomerate these message strings into a dictionary # Send Verack # print('version: ', msg.strSubVer, msg.nVersion) self.my_socket.send( msg_verack().to_bytes() ) return "version" elif msg.command == b"verack": # print("verack: ", msg) return "verack" elif msg.command == b"inv": pass # print("inv: ", msg.inv) # print(dir(msg)) # print(type(msg.inv)) elif msg.command == b"ping": # print("ping: ", msg) self.my_socket.send(msg_pong(msg.nonce).to_bytes()) elif msg.command == b"getheaders": pass # print("getheaders received ") elif msg.command == b"addr": # TODO this needs multi-message support # print("addr: size ", len(msg.addrs)) for address in msg.addrs: node = Link(address.ip, address.port) self.results.add(node) return True elif msg.command == b"getdata": # print("getdata: ", msg.inv) if 'transaction' not in kwargs: return False the_tx = kwargs['transaction'] for request in msg.inv: if request.hash == the_tx.GetHash(): print(threading.current_thread().name,"sending tx: ", self.link) # new message to send transaction to_send = msg_tx() to_send.tx = the_tx self.my_socket.send(to_send.to_bytes()) # print("SENT OUR PC BRO TRANSACTION") return "donedone" else: pass # print("something else: ", msg.command, msg) return False
def process_data(self): while True: if len(self.recvbuf) < 4: return if self.recvbuf[:4] != self.netmagic.MESSAGE_START: raise ValueError("got garbage %s" % repr(self.recvbuf)) if len(self.recvbuf) < 4 + 12 + 4 + 4: return msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0] if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen: return message = self.recvbuf[:4+12+4+4+msglen] self.recvbuf = self.recvbuf[4+12+4+4+msglen:] f = BytesIO(message) try: msg = MsgSerializable.stream_deserialize(f) except ValueError: raise ValueError("invalid deserialization %s" % repr(self.recvbuf)) # noqa if msg is None: return self.got_message(msg)
def process_data(self): while True: if len(self.recvbuf) < 4: return if self.recvbuf[:4] != self.netmagic.MESSAGE_START: raise ValueError("got garbage %s" % repr(self.recvbuf)) if len(self.recvbuf) < 4 + 12 + 4 + 4: return msglen = struct.unpack("<i", self.recvbuf[4 + 12:4 + 12 + 4])[0] if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen: return message = self.recvbuf[:4 + 12 + 4 + 4 + msglen] self.recvbuf = self.recvbuf[4 + 12 + 4 + 4 + msglen:] f = BytesIO(message) try: msg = MsgSerializable.stream_deserialize(f) except ValueError: raise ValueError("invalid deserialization %s" % repr(self.recvbuf)) # noqa if msg is None: return self.got_message(msg)
def getblock(self, blkhash) -> CBlock: # block = self.blk_cache.get(blkhash) # if block is not None: # return block ser_hash = b2lx(blkhash) try: # Lookup the block index, seek in the file fpos = self.db.get(('blocks:'+ser_hash).encode()) fpos = struct.unpack('i', fpos)[0] self.blk_read.seek(fpos) # read and decode "block" msg msg = MsgSerializable.stream_deserialize(self.blk_read) if msg is None: return None block = msg.block except KeyError: return None # self.blk_cache.put(blkhash, block) return block
def run(self): while self.stop_client != True: # Read and store the data from the socket data = self.socket.recv(64) self.buffer.write(data) try: # Go at the beginning of the buffer self.buffer.seek(0) # Deserialize the message message = MsgSerializable().stream_deserialize(self.buffer) # Reset the buffer remaining = self.buffer.read() self.buffer = BytesIO() self.buffer.write(remaining) # Call handle function if message is not None: handle_func_name = "handle_" + message.command.decode( "utf-8") handle_func = getattr(self, handle_func_name, None) if handle_func: handle_func(message) except SerializationTruncationError: # Read more data from the socket pass
def test_read_msg_verack(self): f = BytesIO(self.verackbytes) m = MsgSerializable.stream_deserialize(f) self.assertEqual(m.command, msg_verack.command)
def test_fail_invalid_message(self): bad_verack_bytes = b'\xf8' + self.verackbytes[1:] f = BytesIO(bad_verack_bytes) with self.assertRaises(ValueError): MsgSerializable.stream_deserialize(f)
def run(self): try: self.s.connect((self.addr.ip, self.addr.port)) version_pkt(self.addr.ip, self.addr.port).stream_serialize(self.s) except Exception as e: print(e) print("{}, {}: Version handshake failed with {}:{}".format(datetime.datetime.now(), self.name, self.addr.ip, self.addr.port)) self._stop_request.set() # Make sure we dont send an addr or inv straight away self.lastaddr = time.time() self.lastinv = time.time() while not self._stop_request.is_set(): # Send at most one of these three if time.time() - self.lastping > PING_INTERVAL: msg_ping(random.getrandbits(64)).stream_serialize(self.s) self.lastping = time.time() elif time.time() - self.lastaddr > ADDR_INTERVAL: out = msg_addr() # Grab 10 random addresses with address_lock: random_addresses = random.sample(addresses, min(10, len(addresses))) for address in random_addresses: caddr = CAddress() # Lie a bit caddr.nTime = int(time.time()) - random.randrange(300) caddr.nServices = address.services caddr.port = address.port caddr.ip = address.ip out.addrs.append(caddr) out.stream_serialize(self.s) self.lastaddr = time.time() elif time.time() - self.lastinv > INV_INTERVAL: out = msg_inv() out_inv = CInv() out_inv.type = BLOCK_TYPE out_inv.hash = guess_latest_block() out.inv = [out_inv] out.stream_serialize(self.s) self.lastinv = time.time() try: msg = MsgSerializable.stream_deserialize(self.s) t = time.time() if isinstance(msg, msg_version): msg_verack().stream_serialize(self.s) elif isinstance(msg, msg_verack): print("{}, {}: Version handshake complete".format(datetime.datetime.now(), self.name)) elif isinstance(msg, msg_ping): result = push({ "me": { "ip": my_ipv4, "port": my_port }, "time": t, "type": "ping", "peer": { "ip": self.addr.ip, "port": self.addr.port }, "last": { "ping": self.lastping, "inv": self.lastinv, "addr": self.lastaddr }, "raw": base64.b64encode(msg.to_bytes()).decode('utf-8'), "data": msg.nonce }) msg_pong(nonce=msg.nonce).stream_serialize(self.s) elif isinstance(msg, msg_pong): result = push({ "me": { "ip": my_ipv4, "port": my_port }, "time": t, "type": "pong", "peer": { "ip": self.addr.ip, "port": self.addr.port }, "last": { "ping": self.lastping, "inv": self.lastinv, "addr": self.lastaddr }, "raw": base64.b64encode(msg.to_bytes()).decode('utf-8'), "data": msg.nonce }) elif isinstance(msg, msg_getheaders): pass elif isinstance(msg, msg_alert): pass elif isinstance(msg, msg_inv): if any(item.type == BLOCK_TYPE for item in msg.inv): result = push({ "me": { "ip": my_ipv4, "port": my_port }, "time": t, "type": "inv", "peer": { "ip": self.addr.ip, "port": self.addr.port }, "last": { "ping": self.lastping, "inv": self.lastinv, "addr": self.lastaddr }, "raw": base64.b64encode(msg.to_bytes()).decode('utf-8'), "data": [ { "type": "block" if item.type == BLOCK_TYPE else "tx", "hash": b2lx(item.hash) } for item in msg.inv ] }) for inv in msg.inv: if inv.type == BLOCK_TYPE: append_latest_block(inv.hash) elif isinstance(msg, msg_addr): discover_new_addresses(msg.addrs) else: print("{}, {}: Unhandled message type: {}".format(datetime.datetime.now(), self.name, msg.command.decode('utf-8'))) except socket.timeout: continue except SerializationTruncationError: print("{}, {}: **************** Socket closed. ****************".format(datetime.datetime.now(), self.name)) break self.s.close() print("{}, {}: Stopped.".format(datetime.datetime.now(), self.name))
def send_pkt(self, pkt: MsgSerializable): self.sock.send(pkt.to_bytes())
def capture_messages(self, expected_message_types: list, timeout: int = 20, buf_size: int = 1024, ignore_empty: bool = False) -> list: ''' Method for receiving messages from network nodes. Args: expected_message_types (list): list of message types to search for timeout (int): timeout for waiting for messages buf_size (int): buffer size that is going to be used for receiving messages ignore_empty (bool): flag for ignoring errors if the message that we're looking for wasn't found. Eg. this flag can be set to True when looking for reject messages because the absence of the reject message is not an error. Returns: list, None: list of received messages or None if none or not all expected message types were found Example: >>> from bitcoin.messages import msg_verack, msg_version >>> network.capture_messages([msg_version, msg_verack]) ''' deadline = time() + timeout found = [] partial_message = None while expected_message_types and time() < deadline: try: received_data = self.connection.recv(buf_size) if partial_message: received_data = partial_message + received_data except socket.timeout: continue if not received_data: sleep(0.1) continue for raw_message in self.split_message(received_data): try: message = MsgSerializable.from_bytes(raw_message) except (SerializationError, SerializationTruncationError, ValueError): partial_message = raw_message continue partial_message = None if not message: # unknown message type, skipping continue msg_type = type(message) if msg_type is msg_ping: logger.debug('Got ping, sending pong.') self.send_pong(message) elif msg_type is msg_version: logger.debug('Saving version') self.protocol_version = message if msg_type in expected_message_types: found.append(message) expected_message_types.remove(msg_type) logger.debug('Found %s, %s more to catch', msg_type.command.upper(), len(expected_message_types)) if not expected_message_types: return found if not ignore_empty: logger.error('Not all messages could be captured')