async def ping(): while not self._pipeline_task.done(): to_close: List[Connection] = [] for connection in self.global_connections.get_connections(): if connection.handshake_finished: if (time.time() - connection.get_last_message_time() > config["timeout_duration"] and connection.connection_type == NodeType.FULL_NODE and self._local_type == NodeType.FULL_NODE): # Only closes down full_node <-> full_node connections, which can be recovered to_close.append(connection) for connection in to_close: log.info( f"Removing connection {connection} due to timeout.") self.global_connections.close(connection) msg = Message("ping", Ping(bytes32(token_bytes(32)))) self.push_message( OutboundMessage(NodeType.FARMER, msg, Delivery.BROADCAST)) self.push_message( OutboundMessage(NodeType.TIMELORD, msg, Delivery.BROADCAST)) self.push_message( OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST)) self.push_message( OutboundMessage(NodeType.HARVESTER, msg, Delivery.BROADCAST)) await asyncio.sleep(config["ping_interval"])
async def handle_message( triple: Tuple[ChiaConnection, Message, PeerConnections], api: Any ) -> AsyncGenerator[Tuple[ChiaConnection, OutboundMessage, PeerConnections], None]: """ Async generator which takes messages, parses, them, executes the right api function, and yields responses (to same connection, propagated, etc). """ connection, full_message, global_connections = triple try: if len(full_message.function) == 0 or full_message.function.startswith( "_"): # This prevents remote calling of private methods that start with "_" raise ProtocolError(Err.INVALID_PROTOCOL_MESSAGE, [full_message.function]) connection.log.info( f"<- {full_message.function} from peer {connection.get_peername()}" ) if full_message.function == "ping": ping_msg = Ping(full_message.data["nonce"]) assert connection.connection_type outbound_message = OutboundMessage( connection.connection_type, Message("pong", Pong(ping_msg.nonce)), Delivery.RESPOND, ) yield connection, outbound_message, global_connections return elif full_message.function == "pong": return f_with_peer_name = getattr(api, full_message.function + "_with_peer_name", None) if f_with_peer_name is not None: result = f_with_peer_name(full_message.data, connection.get_peername()) else: f = getattr(api, full_message.function, None) if f is None: raise ProtocolError(Err.INVALID_PROTOCOL_MESSAGE, [full_message.function]) result = f(full_message.data) if isinstance(result, AsyncGenerator): async for outbound_message in result: yield connection, outbound_message, global_connections else: await result except Exception: tb = traceback.format_exc() connection.log.error(f"Error, closing connection {connection}. {tb}") # TODO: Exception means peer gave us invalid information, so ban this peer. global_connections.close(connection)
async def ping(): while not self._pipeline_task.done(): msg = Message("ping", Ping(bytes32(token_bytes(32)))) self.push_message( OutboundMessage(NodeType.FARMER, msg, Delivery.BROADCAST)) self.push_message( OutboundMessage(NodeType.TIMELORD, msg, Delivery.BROADCAST)) self.push_message( OutboundMessage(NodeType.FULL_NODE, msg, Delivery.BROADCAST)) self.push_message( OutboundMessage(NodeType.HARVESTER, msg, Delivery.BROADCAST)) await asyncio.sleep(config["ping_interval"])
async def handle_message( self, pair: Tuple[Connection, Message], api: Any ) -> AsyncGenerator[Tuple[Connection, OutboundMessage], None]: """ Async generator which takes messages, parses, them, executes the right api function, and yields responses (to same connection, propagated, etc). """ connection, full_message = pair try: if len(full_message.function ) == 0 or full_message.function.startswith("_"): # This prevents remote calling of private methods that start with "_" raise InvalidProtocolMessage(full_message.function) log.info( f"<- {full_message.function} from peer {connection.get_peername()}" ) if full_message.function == "ping": ping_msg = Ping(full_message.data["nonce"]) assert connection.connection_type yield connection, OutboundMessage( connection.connection_type, Message("pong", Pong(ping_msg.nonce)), Delivery.RESPOND, ) return elif full_message.function == "pong": return f = getattr(api, full_message.function) if f is None: raise InvalidProtocolMessage(full_message.function) result = f(full_message.data) if isinstance(result, AsyncGenerator): async for outbound_message in result: yield connection, outbound_message else: await result except Exception as e: log.error(f"Error {type(e)} {e}, closing connection {connection}") self.global_connections.close(connection)