async def process_p2p_handshake(self, cmd: Command, msg: PayloadType) -> None: msg = cast(Dict[str, Any], msg) if not isinstance(cmd, Hello): await self.disconnect(DisconnectReason.bad_protocol) raise HandshakeFailure( f"Expected a Hello msg, got {cmd}, disconnecting") # limit number of chars to be displayed, and try to keep printable ones only # MAGIC 256: arbitrary, "should be enough for everybody" original_version = msg['client_version_string'] client_version_string = original_version[:256] + ( '...' if original_version[256:] else '') if client_version_string.isprintable(): self.client_version_string = client_version_string.strip() else: self.client_version_string = repr(client_version_string) # Check whether to support Snappy Compression or not # based on other peer's p2p protocol version snappy_support = msg['version'] >= SNAPPY_PROTOCOL_VERSION if snappy_support: # Now update the base protocol to support snappy compression # This is needed so that Trinity is compatible with parity since # parity sends Ping immediately after Handshake self.base_protocol = P2PProtocol( self.transport, snappy_support=snappy_support, capabilities=self.capabilities, listen_port=self.listen_port, ) remote_capabilities = msg['capabilities'] matched_proto_classes = match_protocols_with_capabilities( self.supported_sub_protocols, remote_capabilities, ) if len(matched_proto_classes) == 1: self.sub_proto = matched_proto_classes[0]( self.transport, self.base_protocol.cmd_length, snappy_support, ) elif len(matched_proto_classes) > 1: raise NotImplementedError( f"Peer {self.remote} connection matched on multiple protocols " f"{matched_proto_classes}. Support for multiple protocols is not " f"yet supported") else: await self.disconnect(DisconnectReason.useless_peer) raise HandshakeFailure( f"No matching capabilities between us ({self.capabilities}) and {self.remote} " f"({remote_capabilities}), disconnecting") self.logger.debug( "Finished P2P handshake with %s, using sub-protocol %s", self.remote, self.sub_proto)
async def process_v4_p2p_handshake(self: BasePeer, cmd: protocol.Command, msg: protocol.Payload) -> None: """ This function is the replacement to the existing process_p2p_handshake function. This is used to simulate the v4 P2PProtocol node. The only change that has been made is to remove the snappy support irrespective of whether the other client supports it or not. """ msg = cast(Dict[str, Any], msg) if not isinstance(cmd, Hello): await self.disconnect(DisconnectReason.bad_protocol) raise HandshakeFailure( f"Expected a Hello msg, got {cmd}, disconnecting") # As far as a v4 P2PProtocol client is concerned, # it never support snappy compression snappy_support = False remote_capabilities = msg['capabilities'] matched_proto_classes = match_protocols_with_capabilities( self.supported_sub_protocols, remote_capabilities, ) if len(matched_proto_classes) == 1: self.sub_proto = matched_proto_classes[0]( self.transport, self.base_protocol.cmd_length, snappy_support, ) elif len(matched_proto_classes) > 1: raise NotImplementedError( f"Peer {self.remote} connection matched on multiple protocols " f"{matched_proto_classes}. Support for multiple protocols is not " f"yet supported") else: await self.disconnect(DisconnectReason.useless_peer) raise HandshakeFailure( f"No matching capabilities between us ({self.capabilities}) and {self.remote} " f"({remote_capabilities}), disconnecting") self.logger.debug("Finished P2P handshake with %s, using sub-protocol %s", self.remote, self.sub_proto)
def test_sub_protocol_selection(protocols, capabilities, expected): actual = match_protocols_with_capabilities(protocols, capabilities) assert actual == expected