async def request_nodes( self, receiver_node_id: NodeID, message: BaseMessage, endpoint: Optional[Endpoint] = None, ) -> Tuple[IncomingMessage, ...]: async with self.request_response_subscription( receiver_node_id, message, endpoint, ) as response_subscription: first_response = await response_subscription.receive() self.logger.debug( "Received %s from %s with request id %d", first_response, encode_hex(receiver_node_id), message.request_id, ) if not isinstance(first_response.message, NodesMessage): raise UnexpectedMessage( f"Peer {encode_hex(receiver_node_id)} responded with " f"{first_response.message.__class__.__name__} instead of Nodes message" ) total = first_response.message.total if total > MAX_NODES_MESSAGE_TOTAL: raise UnexpectedMessage( f"Peer {encode_hex(receiver_node_id)} sent nodes message with a total value of " f"{total} which is too big") self.logger.debug( "Received nodes response %d of %d from %s with request id %d", 1, total, encode_hex(receiver_node_id), message.request_id, ) responses = [first_response] for response_index in range(1, total): next_response = await response_subscription.receive() if not isinstance(first_response.message, NodesMessage): raise UnexpectedMessage( f"Peer {encode_hex(receiver_node_id)} responded with " f"{next_response.message.__class__.__name__} instead of Nodes message" ) responses.append(next_response) self.logger.debug( "Received nodes response %d of %d from %s with request id %d", response_index + 1, total, encode_hex(receiver_node_id), message.request_id, ) return tuple(responses)
def handle_p2p_msg(self, cmd: protocol.Command, msg: protocol.PayloadType) -> None: """Handle the base protocol (P2P) messages.""" if isinstance(cmd, Disconnect): msg = cast(Dict[str, Any], msg) raise RemoteDisconnected(msg['reason_name']) elif isinstance(cmd, Ping): self.base_protocol.send_pong() elif isinstance(cmd, Pong): # Currently we don't do anything when we get a pong, but eventually we should # update the last time we heard from a peer in our DB (which doesn't exist yet). pass else: raise UnexpectedMessage(f"Unexpected msg: {cmd} ({msg})")
def handle_p2p_msg(self, cmd: protocol.Command, msg: protocol._DecodedMsgType) -> None: """Handle the base protocol (P2P) messages.""" if isinstance(cmd, Disconnect): msg = cast(Dict[str, Any], msg) self.logger.debug( "%s disconnected; reason given: %s", self, msg['reason_name']) self.close() elif isinstance(cmd, Ping): self.base_protocol.send_pong() elif isinstance(cmd, Pong): # Currently we don't do anything when we get a pong, but eventually we should # update the last time we heard from a peer in our DB (which doesn't exist yet). pass else: raise UnexpectedMessage("Unexpected msg: {} ({})".format(cmd, msg))
async def get_collations(self, collation_hashes: List[Hash32], cancel_token: CancelToken) -> Set[Collation]: # Don't send empty request if len(collation_hashes) == 0: return set() request_id = gen_request_id() pending_reply: asyncio.Future[Tuple[ Command, protocol._DecodedMsgType]] = asyncio.Future() self._pending_replies[request_id] = pending_reply cast(ShardingProtocol, self.sub_proto).send_get_collations(request_id, collation_hashes) cmd, msg = await wait_with_token(pending_reply, token=cancel_token) if not isinstance(cmd, Collations): raise UnexpectedMessage( "Expected Collations as response to GetCollations, but got %s", cmd.__class__.__name__) return set(msg["collations"])
async def _handle_peer(self, peer: LESPeer) -> None: self._announcement_queue.put_nowait((peer, peer.head_info)) while True: try: cmd, msg = await peer.read_sub_proto_msg(self.cancel_token) except OperationCancelled: # Either the peer disconnected or our cancel_token has been triggered, so break # out of the loop to stop attempting to sync with this peer. break # We currently implement only the LES commands for retrieving data (apart from # Announce), and those should always come as a response to requests we make so will be # handled by LESPeer.handle_sub_proto_msg(). if isinstance(cmd, les.Announce): peer.head_info = cmd.as_head_info(msg) self._announcement_queue.put_nowait((peer, peer.head_info)) else: raise UnexpectedMessage("Unexpected msg from {}: {}".format(peer, msg)) await self.drop_peer(peer) self.logger.debug("%s finished", peer)