Ejemplo n.º 1
0
    def on_packet_recvname(self, data) -> bool:
        """ Handle RECV_NAME command, the first packet in a new connection. """
        if data[0] != ord('n'):
            return self.protocol_error(
                "Unexpected packet (expecting RECV_NAME)")

        # Read peer distribution version and compare to ours
        peer_max_min = (data[1], data[2])
        if dist_protocol.dist_version_check(peer_max_min):
            return self.protocol_error(
                "Dist protocol version have: %s got: %s"
                % (str(dist_protocol.DIST_VSN_PAIR), str(peer_max_min)))
        self.peer_distr_version_ = peer_max_min

        self.peer_flags_ = util.u32(data[3:7])
        self.peer_name_ = data[7:].decode("latin1")
        LOG.info("RECV_NAME: %s %s", self.peer_distr_version_, self.peer_name_)

        # Report
        self._send_packet2(b"sok")

        self.my_challenge_ = int(random.random() * 0x7fffffff)
        self._send_challenge(self.my_challenge_)

        self.state_ = self.WAIT_CHALLENGE_REPLY

        return True
Ejemplo n.º 2
0
    def query_node(node: str) -> tuple:
        """ Query EPMD about the port to the given node.

            :param node: String with node "name@ip" or "name@hostname"
            :return: Host and port where the node is, or None
            :rtype: tuple(str, int)
            :throws EPMDClientError: if something is wrong with input
            :throws EPMDConnectionError: if connection went wrong
        """
        # Trim the host name/IP after the @ and resolve the DNS name
        if "@" not in node:
            raise EPMDClientError("Node must have @ in it")

        (r_name, r_ip_or_hostname) = node.split("@")
        r_ip = socket.gethostbyname(r_ip_or_hostname)

        port_please2 = bytes([REQ_PORT_PLEASE2]) \
            + bytes(r_name, "utf8")  # not sure if latin-1 here

        resp = EPMDClient._fire_forget_query(r_ip, port_please2)

        # RESP_PORT2
        # Response Error structure
        # 1     1
        # 119   Result > 0
        if len(resp) < 2 or resp[0] != RESP_PORT2:
            ERROR("EPMD: PORT_PLEASE2 to %s sent wrong response %s" %
                  (r_ip, resp))
            raise EPMDConnectionError("PORT_PLEASE2 wrong response")

        if resp[1] != 0:
            ERROR("EPMD: PORT_PLEASE2 to %s: error %d" % (r_ip, resp[1]))
            raise EPMDConnectionError("PORT_PLEASE2 error %d" % resp[1])

        # Response structure
        # 1     1       2       1           1           2               ...
        # 119   Result  PortNo  NodeType    Protocol    HighestVersion  ...
        # 2             2       Nlen        2       Elen
        # LowestVersion Nlen    NodeName    Elen    >Extra

        r_port = util.u16(resp, 2)
        # node_type = resp[4]
        # protocol = resp[5]
        versions = (util.u16(resp, 6), util.u16(resp, 8))
        if not dist_protocol.dist_version_check(versions):
            raise EPMDConnectionError(
                "Remote node %s supports protocol version %s and we "
                "support %d" % (node, versions, dist_protocol.DIST_VSN))

        # ignore node name and extra

        return r_ip, r_port