async def on_connect(self, peer: ws.WSChiaConnection): if ( peer.is_outbound is False and peer.peer_server_port is not None and peer.connection_type is NodeType.FULL_NODE and self.server._local_type is NodeType.FULL_NODE and self.address_manager is not None ): timestamped_peer_info = TimestampedPeerInfo( peer.peer_host, peer.peer_server_port, uint64(int(time.time())), ) await self.address_manager.add_to_new_table([timestamped_peer_info], peer.get_peer_info(), 0) if self.relay_queue is not None: self.relay_queue.put_nowait((timestamped_peer_info, 1)) if ( peer.is_outbound and peer.peer_server_port is not None and peer.connection_type is NodeType.FULL_NODE and self.server._local_type is NodeType.FULL_NODE and self.address_manager is not None ): msg = make_msg(ProtocolMessageTypes.request_peers, full_node_protocol.RequestPeers()) await peer.send_message(msg)
async def respond_peers(self, request: introducer_protocol.RespondPeers, peer: WSChiaConnection): if not self.wallet_node.has_full_node(): await self.wallet_node.wallet_peers.respond_peers(request, peer.get_peer_info(), False) else: await self.wallet_node.wallet_peers.ensure_is_closed() if peer is not None and peer.connection_type is NodeType.INTRODUCER: await peer.close()
async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection): if not self.wallet_node.has_full_node(): self.log.info(f"Wallet received {len(request.peer_list)} peers.") await self.wallet_node.wallet_peers.respond_peers( request, peer.get_peer_info(), True) else: self.log.info( f"Wallet received {len(request.peer_list)} peers, but ignoring, since we have a full node." ) await self.wallet_node.wallet_peers.ensure_is_closed() return None
async def update_peer_timestamp_on_message(self, peer: ws.WSChiaConnection): if (peer.is_outbound and peer.peer_server_port is not None and peer.connection_type is NodeType.FULL_NODE and self.server._local_type is NodeType.FULL_NODE and self.address_manager is not None): peer_info = peer.get_peer_info() if peer_info.host not in self.connection_time_pretest: self.connection_time_pretest[peer_info.host] = time.time() if time.time() - self.connection_time_pretest[ peer_info.host] > 600: self.connection_time_pretest[peer_info.host] = time.time() await self.address_manager.connect(peer_info)
async def incoming_connection(self, request): if request.remote in self.banned_peers and time.time( ) < self.banned_peers[request.remote]: self.log.warning( f"Peer {request.remote} is banned, refusing connection") return None ws = web.WebSocketResponse(max_msg_size=50 * 1024 * 1024) await ws.prepare(request) close_event = asyncio.Event() cert_bytes = request.transport._ssl_protocol._extra[ "ssl_object"].getpeercert(True) der_cert = x509.load_der_x509_certificate(cert_bytes) peer_id = bytes32(der_cert.fingerprint(hashes.SHA256())) if peer_id == self.node_id: return ws connection: Optional[WSChiaConnection] = None try: connection = WSChiaConnection( self._local_type, ws, self._port, self.log, False, False, request.remote, self.incoming_messages, self.connection_closed, peer_id, self._inbound_rate_limit_percent, self._outbound_rate_limit_percent, close_event, ) handshake = await connection.perform_handshake( self._network_id, protocol_version, self._port, self._local_type, ) assert handshake is True # Limit inbound connections to config's specifications. if not self.accept_inbound_connections(connection.connection_type): self.log.info( f"Not accepting inbound connection: {connection.get_peer_info()}.Inbound limit reached." ) await connection.close() close_event.set() else: await self.connection_added(connection, self.on_connect) if self._local_type is NodeType.INTRODUCER and connection.connection_type is NodeType.FULL_NODE: self.introducer_peers.add(connection.get_peer_info()) except ProtocolError as e: if connection is not None: await connection.close(self.invalid_protocol_ban_seconds, WSCloseCode.PROTOCOL_ERROR, e.code) if e.code == Err.INVALID_HANDSHAKE: self.log.warning( "Invalid handshake with peer. Maybe the peer is running old software." ) close_event.set() elif e.code == Err.INCOMPATIBLE_NETWORK_ID: self.log.warning( "Incompatible network ID. Maybe the peer is on another network" ) close_event.set() elif e.code == Err.SELF_CONNECTION: close_event.set() else: error_stack = traceback.format_exc() self.log.error( f"Exception {e}, exception Stack: {error_stack}") close_event.set() except Exception as e: if connection is not None: await connection.close( ws_close_code=WSCloseCode.PROTOCOL_ERROR, error=Err.UNKNOWN) error_stack = traceback.format_exc() self.log.error(f"Exception {e}, exception Stack: {error_stack}") close_event.set() await close_event.wait() return ws