コード例 #1
0
 def get_protocol_command_for(self, msg: bytes) -> protocol.Command:
     """Return the Command corresponding to the cmd_id encoded in the given msg."""
     cmd_id = get_devp2p_cmd_id(msg)
     self.logger.debug("Got msg with cmd_id: %s", cmd_id)
     if cmd_id < self.base_protocol.cmd_length:
         proto = self.base_protocol
     elif cmd_id < self.sub_proto.cmd_id_offset + self.sub_proto.cmd_length:
         proto = self.sub_proto  # type: ignore
     else:
         raise UnknownProtocolCommand("No protocol found for cmd_id {}".format(cmd_id))
     return proto.cmd_by_id[cmd_id]
コード例 #2
0
 def process_msg(self, msg: bytes) -> protocol._DecodedMsgType:
     cmd_id = get_devp2p_cmd_id(msg)
     self.logger.debug("Got msg with cmd_id: {}".format(cmd_id))
     proto = self.get_protocol_for(cmd_id)
     if proto is None:
         raise UnknownProtocolCommand(
             "No protocol found for cmd_id {}".format(cmd_id))
     decoded = proto.process(cmd_id, msg)
     if decoded is None:
         return None
     # Check if this is a reply we're waiting for and, if so, call the callback for this
     # request_id.
     request_id = decoded.get('request_id')
     if request_id is not None and request_id in self._pending_replies:
         callback = self._pending_replies.pop(request_id)
         callback(decoded)
     return decoded
コード例 #3
0
async def handshake(remote: Node, privkey: datatypes.PrivateKey,
                    peer_class: 'Type[BasePeer]', chaindb: BaseChainDB,
                    network_id: int) -> 'BasePeer':
    """Perform the auth and P2P handshakes with the given remote.

    Return an instance of the given peer_class (must be a subclass of BasePeer) connected to that
    remote in case both handshakes are successful and at least one of the sub-protocols supported
    by peer_class is also supported by the remote.

    Raises UnreachablePeer if we cannot connect to the peer or UselessPeer if none of the
    sub-protocols supported by us is also supported by the remote.
    """
    try:
        (aes_secret, mac_secret, egress_mac, ingress_mac, reader,
         writer) = await auth.handshake(remote, privkey)
    except (ConnectionRefusedError, OSError) as e:
        raise UnreachablePeer(e)
    peer = peer_class(remote=remote,
                      privkey=privkey,
                      reader=reader,
                      writer=writer,
                      aes_secret=aes_secret,
                      mac_secret=mac_secret,
                      egress_mac=egress_mac,
                      ingress_mac=ingress_mac,
                      chaindb=chaindb,
                      network_id=network_id)
    peer.base_protocol.send_handshake()
    msg = await peer.read_msg()
    decoded = peer.process_msg(msg)
    if get_devp2p_cmd_id(msg) == Disconnect._cmd_id:
        # Peers may send a disconnect msg before they send the initial P2P handshake (e.g. when
        # they're not accepting more peers), so we special case that here because it's important
        # to distinguish this from a failed handshake (e.g. no matching protocols, etc).
        raise PeerDisconnected("{} disconnected before handshake: {}".format(
            peer, decoded['reason_name']))
    if len(peer.enabled_sub_protocols) == 0:
        raise UselessPeer("No matching sub-protocols with {}".format(peer))
    for proto in peer.enabled_sub_protocols:
        proto.send_handshake(peer.head_info)
    return peer
コード例 #4
0
    def process_msg(
            self,
            msg: bytes) -> Tuple[protocol.Command, protocol._DecodedMsgType]:
        cmd_id = get_devp2p_cmd_id(msg)
        self.logger.debug("Got msg with cmd_id: %s", cmd_id)
        proto = self.get_protocol_for(cmd_id)
        if proto is None:
            raise UnknownProtocolCommand(
                "No protocol found for cmd_id {}".format(cmd_id))

        cmd, decoded = proto.process(cmd_id, msg)
        if isinstance(decoded, dict):
            # Check if this is a reply we're waiting for and, if so, call the callback for this
            # request_id.
            request_id = decoded.get('request_id')
            if request_id is not None and request_id in self._pending_replies:
                callback = self._pending_replies.pop(request_id)
                callback(decoded)

        if self.received_msg_callback is not None:
            self.received_msg_callback(self, cmd, decoded)
        return cmd, decoded
コード例 #5
0
 def decode(self, data: bytes) -> _DecodedMsgType:
     packet_type = get_devp2p_cmd_id(data)
     if packet_type != self.cmd_id:
         raise ValueError("Wrong packet type: {}".format(packet_type))
     return self.decode_payload(data[1:])