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 _handle_pkt(self, pkt): if isinstance(pkt, messages.msg_version): self.ver_pkt = pkt self.last_useful = time.time() return messages.msg_verack() elif isinstance(pkt, messages.msg_ping): return messages.msg_pong(nonce=pkt.nonce) elif isinstance(pkt, messages.msg_verack): self.verack_received = True self.last_useful = time.time() return None elif isinstance(pkt, messages.msg_addr): if len(pkt.addrs) > 10: self._handle_addr(pkt) return False # disconnect, we got what we wanted else: return None # usually either forwarded or self-announcement, neither is useful elif isinstance(pkt, (messages.msg_getheaders, messages.msg_inv, messages.msg_alert, messages.msg_getblocks)): pass # irrelevant but common, don't want to spam log else: log.debug(f'other pkt from -> {self.ip}: {pkt}') if self.pkt_count > 6 and not self.getaddr_sent: self.getaddr_sent = True # some clients advertise their own address first, and only then seem to properly react to getaddr # and sometimes it seems to be unrelated to that, so just wait a few packets, then it usually # works, except for clients that just don't reply at all, which also happens # (which is why we have last_useful to expire connections that don't yield addresses in reasonable time) return messages.msg_getaddr() return None
def listen_until_addresses(self): """Implements the Bitcoin protocol, sending info until it gets an addr message""" # Try to get addresses self.my_socket.send(msg_getaddr().to_bytes()) while not self._process_message(): # TODO set timeout or something for multiple addr messages pass self.my_socket.close()
def send_getaddr(self): self.send_message(msg_getaddr())
def got_message(self, message): gevent.sleep() if self.last_sent + 30 * 60 < time.time(): self.send_message(messages.msg_ping(self.ver_send)) self.log.debug("recv %s" % repr(message)) if message.command == "version": self.ver_send = min(self.params.PROTO_VERSION, message.nVersion) if self.ver_send < self.params.MIN_PROTO_VERSION: self.log.info("Obsolete version %d, closing" % (self.ver_send,)) self.handle_close() return if (self.ver_send >= self.params.NOBLKS_VERSION_START and self.ver_send <= self.params.NOBLKS_VERSION_END): self.getblocks_ok = False self.remote_height = message.nStartingHeight self.send_message(messages.msg_verack(self.ver_send)) if self.ver_send >= self.params.CADDR_TIME_VERSION: self.send_message(messages.msg_getaddr(self.ver_send)) self.request_latest() self.client_version = message.strSubVer elif message.command == "verack": self.ver_recv = self.ver_send if self.ver_send >= self.params.MEMPOOL_GD_VERSION: self.send_message(messages.msg_mempool()) elif message.command == "ping": if self.ver_send > self.params.BIP0031_VERSION: self.send_message(messages.msg_pong(self.ver_send)) elif message.command == "addr": self.peermgr.new_addrs(message.addrs) elif message.command == "inv": # special message sent to kick getblocks if (len(message.inv) == 1 and message.inv[0].type == messages.MSG_BLOCK and self.chaindb.haveblock(message.inv[0].hash, True)): self.request_latest(False) return want = messages.msg_getdata(self.ver_send) for i in message.inv: if i.type == 1: want.inv.append(i) elif i.type == 2: want.inv.append(i) if len(want.inv): self.send_message(want) elif message.command == "tx": if self.chaindb.tx_is_orphan(message.tx): self.log.info( "MemPool: Ignoring orphan TX {}" .format(message.tx.GetHash().encode('hex'))) elif not self.chaindb.tx_signed(message.tx, None, True): self.log.info( "MemPool: Ignoring failed-sig TX {}" .format(message.tx.GetHash().encode('hex'))) else: self.mempool.add(message.tx) elif message.command == "block": self.chaindb.putblock(message.block) self.last_block_rx = time.time() elif message.command == "headers": self.chaindb.putblock(message.block) self.last_block_rx = time.time() elif message.command == "getdata": self.getdata(message) elif message.command == "getblocks": self.getblocks(message) elif message.command == "getheaders": self.getheaders(message) elif message.command == "getaddr": msg = messages.msg_addr() msg.addrs = self.peermgr.random_addrs() self.send_message(msg) elif message.command == "mempool": msg = messages.msg_inv() for k in self.mempool.pool.iterkeys(): inv = net.CInv() inv.type = messages.MSG_TX inv.hash = k msg.inv.append(inv) if len(msg.inv) == 50000: break self.send_message(msg) # if we haven't seen a 'block' message in a little while, # and we're still not caught up, send another getblocks last_blkmsg = time.time() - self.last_block_rx if last_blkmsg > 5: self.request_latest()
def got_message(self, message): gevent.sleep() if self.last_sent + 30 * 60 < time.time(): self.send_message(msg_ping(self.ver_send)) if verbose_recvmsg(message): self.log.info("recv %s" % repr(message)) if message.command == b"version": self.ver_send = min(PROTO_VERSION, message.nVersion) if self.ver_send < MIN_PROTO_VERSION: self.log.info("Obsolete version %d, closing" % (self.ver_send, )) self.handle_close() return self.remote_height = message.nStartingHeight self.send_message(msg_verack(self.ver_send)) if self.ver_send >= CADDR_TIME_VERSION: self.send_message(msg_getaddr(self.ver_send)) # self.send_getblocks() elif message.command == b'ping': if self.ver_send > BIP0031_VERSION: self.send_message(msg_pong(self.ver_send)) elif message.command == b"verack": self.ver_recv = self.ver_send self.send_message(msg_addr()) self.send_getaddr() elif message.command == b"inv": # special message sent to kick getblocks # if (len(message.inv) == 1 and # message.inv[0].type == MSG_BLOCK and # self.chaindb.haveblock(message.inv[0].hash, True)): # self.send_getblocks(False) # return want = msg_getdata(self.ver_send) for i in message.inv: if i.type == 1: want.inv.append(i) elif i.type == 2: want.inv.append(i) self.last_want = i.hash if len(want.inv): self.send_message(want) # elif message.command == b"block": # bhash = b2lx(message.block.GetHash()) # self.chaindb.putblock(message.block) # self.last_block_rx = time.time() # if self.last_want == 0: # gevent.spawn(self.send_getblocks) # elif bhash == b2lx(self.last_want): # gevent.spawn(self.send_getblocks) elif message.command == b"addr": self.peermgr.new_addrs(message.addrs) for addr in message.addrs: self.peermgr.add(addr.ip, addr.port) elif message.command == b'getheaders': self.send_message(msg_headers())
def got_message(self, message): gevent.sleep() if self.last_sent + 30 * 60 < time.time(): self.send_message(messages.msg_ping(self.ver_send)) self.log.debug("recv %s" % repr(message)) if message.command == "version": self.ver_send = min(self.params.PROTO_VERSION, message.nVersion) if self.ver_send < self.params.MIN_PROTO_VERSION: self.log.info("Obsolete version %d, closing" % (self.ver_send, )) self.handle_close() return if (self.ver_send >= self.params.NOBLKS_VERSION_START and self.ver_send <= self.params.NOBLKS_VERSION_END): self.getblocks_ok = False self.remote_height = message.nStartingHeight self.send_message(messages.msg_verack(self.ver_send)) if self.ver_send >= self.params.CADDR_TIME_VERSION: self.send_message(messages.msg_getaddr(self.ver_send)) self.request_latest() self.client_version = message.strSubVer elif message.command == "verack": self.ver_recv = self.ver_send if self.ver_send >= self.params.MEMPOOL_GD_VERSION: self.send_message(messages.msg_mempool()) elif message.command == "ping": if self.ver_send > self.params.BIP0031_VERSION: self.send_message(messages.msg_pong(self.ver_send)) elif message.command == "addr": self.peermgr.new_addrs(message.addrs) elif message.command == "inv": # special message sent to kick getblocks if (len(message.inv) == 1 and message.inv[0].type == messages.MSG_BLOCK and self.chaindb.haveblock(message.inv[0].hash, True)): self.request_latest(False) return want = messages.msg_getdata(self.ver_send) for i in message.inv: if i.type == 1: want.inv.append(i) elif i.type == 2: want.inv.append(i) if len(want.inv): self.send_message(want) elif message.command == "tx": if self.chaindb.tx_is_orphan(message.tx): self.log.info("MemPool: Ignoring orphan TX {}".format( message.tx.GetHash().encode('hex'))) elif not self.chaindb.tx_signed(message.tx, None, True): self.log.info("MemPool: Ignoring failed-sig TX {}".format( message.tx.GetHash().encode('hex'))) else: self.mempool.add(message.tx) elif message.command == "block": self.chaindb.putblock(message.block) self.last_block_rx = time.time() elif message.command == "headers": self.chaindb.putblock(message.block) self.last_block_rx = time.time() elif message.command == "getdata": self.getdata(message) elif message.command == "getblocks": self.getblocks(message) elif message.command == "getheaders": self.getheaders(message) elif message.command == "getaddr": msg = messages.msg_addr() msg.addrs = self.peermgr.random_addrs() self.send_message(msg) elif message.command == "mempool": msg = messages.msg_inv() for k in self.mempool.pool.iterkeys(): inv = net.CInv() inv.type = messages.MSG_TX inv.hash = k msg.inv.append(inv) if len(msg.inv) == 50000: break self.send_message(msg) # if we haven't seen a 'block' message in a little while, # and we're still not caught up, send another getblocks last_blkmsg = time.time() - self.last_block_rx if last_blkmsg > 5: self.request_latest()