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)
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))
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)