Ejemplo n.º 1
0
    def getnameinfo(self, ip_port, flags, callback):
        if not callable(callback):
            raise AresError("a callable is required")

        ip, port = ip_port

        if port < 0 or port > 65535:
            raise ValueError("port must be between 0 and 65535")

        sa4 = _ffi.new("struct sockaddr_in*")
        sa6 = _ffi.new("struct sockaddr_in6*")

        if 1 == _lib.ares_inet_pton(socket.AF_INET, s2b(ip), _ffi.addressof(sa4.sin_addr)):
            sa4.sin_family = socket.AF_INET
            sa4.sin_port = socket.htons(port)
            sa = sa4
        elif 1 == _lib.ares_inet_pton(socket.AF_INET6, s2b(ip), _ffi.addressof(sa6.sin6_addr)):
            sa6.sin6_family = socket.AF_INET6
            sa6.sin6_port = socket.htons(port)
            sa = sa6
        else:
            raise ValueError("invalid IP address")

        userdata = _ffi.new_handle(callback)
        _global_set.add(userdata)
        _lib.ares_getnameinfo(self.channel, _ffi.cast("struct sockaddr*", sa), _ffi.sizeof(sa[0]), flags, _nameinfo_cb, userdata)
Ejemplo n.º 2
0
 def process_fd(self, read_fd, write_fd):
     _lib.ares_process_fd(self.channel, _ffi.cast("ares_socket_t", read_fd), _ffi.cast("ares_socket_t", write_fd))
Ejemplo n.º 3
0
def _query_cb(arg, status, timeouts, abuf, alen):
    result = None
    callback, query_type = _ffi.from_handle(arg)
    if status == _lib.ARES_SUCCESS:
        if query_type == _lib.T_A:
            addrttls = _ffi.new("struct ares_addrttl[]", PYCARES_ADDRTTL_SIZE)
            naddrttls = _ffi.new("int*", PYCARES_ADDRTTL_SIZE)
            parse_status = _lib.ares_parse_a_reply(abuf, alen, _ffi.NULL,
                                                   addrttls, naddrttls)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = [
                    ares_query_simple_result(addrttls[i])
                    for i in range(naddrttls[0])
                ]
                status = None

        elif query_type == _lib.T_AAAA:
            addrttls = _ffi.new("struct ares_addr6ttl[]", PYCARES_ADDRTTL_SIZE)
            naddrttls = _ffi.new("int*", PYCARES_ADDRTTL_SIZE)
            parse_status = _lib.ares_parse_aaaa_reply(abuf, alen, _ffi.NULL,
                                                      addrttls, naddrttls)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = [
                    ares_query_simple_result(addrttls[i])
                    for i in range(naddrttls[0])
                ]
                status = None

        elif query_type == _lib.T_CNAME:
            host = _ffi.new("struct hostent **")
            parse_status = _lib.ares_parse_a_reply(abuf, alen, host, _ffi.NULL,
                                                   _ffi.NULL)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = ares_query_cname_result(host[0])
                _lib.ares_free_hostent(host[0])
                status = None

        elif query_type == _lib.T_MX:
            mx_reply = _ffi.new("struct ares_mx_reply **")
            parse_status = _lib.ares_parse_mx_reply(abuf, alen, mx_reply)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = []
                mx_reply_ptr = _ffi.new("struct ares_mx_reply **")
                mx_reply_ptr[0] = mx_reply[0]
                while True:
                    if mx_reply_ptr[0] == _ffi.NULL:
                        break
                    result.append(ares_query_mx_result(mx_reply[0]))
                    mx_reply_ptr[0] = mx_reply_ptr[0].next
                _lib.ares_free_data(mx_reply)
                status = None

        elif query_type == _lib.T_NAPTR:
            naptr_reply = _ffi.new("struct ares_naptr_reply **")
            parse_status = _lib.ares_parse_naptr_reply(abuf, alen, naptr_reply)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = []
                naptr_reply_ptr = _ffi.new("struct ares_naptr_reply **")
                naptr_reply_ptr[0] = naptr_reply[0]
                while True:
                    if naptr_reply_ptr[0] == _ffi.NULL:
                        break
                    result.append(ares_query_naptr_result(naptr_reply[0]))
                    naptr_reply_ptr[0] = naptr_reply_ptr[0].next
                _lib.ares_free_data(naptr_reply)
                status = None

        elif query_type == _lib.T_NS:
            hostent = _ffi.new("struct hostent **")
            parse_status = _lib.ares_parse_ns_reply(abuf, alen, hostent)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = []
                host = hostent[0]
                for i in range(100):
                    if host.h_aliases[i] == _ffi.NULL:
                        break
                    result.append(ares_query_ns_result(host.h_aliases[i]))

                _lib.ares_free_hostent(host)
                status = None

        elif query_type == _lib.T_PTR:
            hostent = _ffi.new("struct hostent **")
            hostttl = _ffi.new("int*", PYCARES_ADDRTTL_SIZE)
            parse_status = _lib.ares_parse_ptr_reply(abuf, alen, _ffi.NULL, 0,
                                                     socket.AF_UNSPEC, hostent,
                                                     hostttl)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                aliases = []
                i = 0
                terminator = _ffi.cast('char*', _ffi.NULL)
                while hostent[0].h_aliases[i] != terminator:
                    aliases.append(_ffi.string(hostent[0].h_aliases[i]))
                    i += 1
                result = ares_query_ptr_result(hostent[0], hostttl[0], aliases)
                _lib.ares_free_hostent(hostent[0])
                status = None

        elif query_type == _lib.T_SOA:
            soa_reply = _ffi.new("struct ares_soa_reply **")
            parse_status = _lib.ares_parse_soa_reply(abuf, alen, soa_reply)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = ares_query_soa_result(soa_reply[0])
                _lib.ares_free_data(soa_reply[0])
                status = None

        elif query_type == _lib.T_SRV:
            srv_reply = _ffi.new("struct ares_srv_reply **")
            parse_status = _lib.ares_parse_srv_reply(abuf, alen, srv_reply)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = []
                srv_reply_ptr = _ffi.new("struct ares_srv_reply **")
                srv_reply_ptr[0] = srv_reply[0]
                while True:
                    if srv_reply_ptr[0] == _ffi.NULL:
                        break
                    result.append(ares_query_srv_result(srv_reply_ptr[0]))
                    srv_reply_ptr[0] = srv_reply_ptr[0].next
                _lib.ares_free_data(srv_reply[0])
                status = None

        elif query_type == _lib.T_TXT:
            txt_reply = _ffi.new("struct ares_txt_ext **")
            parse_status = _lib.ares_parse_txt_reply_ext(
                abuf, alen, txt_reply)
            if parse_status != ARES_SUCCESS:
                result = None
                status = parse_status
            else:
                result = []
                txt_reply_ptr = _ffi.new("struct ares_txt_ext **")
                txt_reply_ptr[0] = txt_reply[0]
                tmp_obj = None
                while True:
                    if txt_reply_ptr[0] == _ffi.NULL:
                        if tmp_obj is not None:
                            result.append(tmp_obj)
                        break
                    if txt_reply_ptr[0].record_start == 1:
                        if tmp_obj is not None:
                            result.append(tmp_obj)
                        tmp_obj = ares_query_txt_result(txt_reply_ptr[0])
                    else:
                        new_chunk = ares_query_txt_result(txt_reply_ptr[0])
                        tmp_obj.text += new_chunk.text
                    txt_reply_ptr[0] = txt_reply_ptr[0].next
                _lib.ares_free_data(txt_reply[0])
                status = None
        else:
            raise ValueError("invalid query type specified")

    callback(result, status)
    _global_set.discard(arg)