async def handshake_for_version(remote: Node, factory):
    """Perform the auth and P2P handshakes (without sub-protocol handshake) with the given remote.
    Disconnect after initial hello message exchange, and return version id
    """
    try:
        (
            aes_secret,
            mac_secret,
            egress_mac,
            ingress_mac,
            reader,
            writer,
        ) = await auth.handshake(remote, factory.privkey, factory.cancel_token)
    except (ConnectionRefusedError, OSError) as e:
        raise UnreachablePeer() from e
    connection = PeerConnection(
        reader=reader,
        writer=writer,
        aes_secret=aes_secret,
        mac_secret=mac_secret,
        egress_mac=egress_mac,
        ingress_mac=ingress_mac,
    )
    peer = factory.create_peer(remote=remote, connection=connection, inbound=False)
    # see await peer.do_p2p_handshake()
    peer.base_protocol.send_handshake()
    try:
        cmd, msg = await peer.read_msg(timeout=peer.conn_idle_timeout)
    except rlp.DecodingError:
        raise HandshakeFailure("Got invalid rlp data during handshake")
    except MalformedMessage as e:
        raise HandshakeFailure("Got malformed message during handshake") from e
    if isinstance(cmd, Disconnect):
        msg = cast(Dict[str, Any], msg)
        raise HandshakeDisconnectedFailure(
            "disconnected before completing sub-proto handshake: {}".format(
                msg["reason_name"]
            )
        )
    msg = cast(Dict[str, Any], msg)
    if not isinstance(cmd, Hello):
        await peer.disconnect(DisconnectReason.bad_protocol)
        raise HandshakeFailure(
            "Expected a Hello msg, got {}, disconnecting".format(cmd)
        )
    return msg["client_version_string"]
示例#2
0
async def handshake(remote: Node, factory: "BasePeerFactory") -> "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
    HandshakeFailure if the remote disconnects before completing the
    handshake or 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, factory.privkey, factory.cancel_token)
    except (ConnectionRefusedError, OSError) as e:
        raise UnreachablePeer() from e
    connection = PeerConnection(
        reader=reader,
        writer=writer,
        aes_secret=aes_secret,
        mac_secret=mac_secret,
        egress_mac=egress_mac,
        ingress_mac=ingress_mac,
    )
    peer = factory.create_peer(remote=remote,
                               connection=connection,
                               inbound=False)
    await peer.do_p2p_handshake()
    await peer.do_sub_proto_handshake()
    return peer