Пример #1
0
 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"])
Пример #2
0
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)
Пример #3
0
 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"])
Пример #4
0
    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)