1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
__all__ += ['dns_init', 'dns_shutdown', 'dns_err_to_string',
'dns_resolve_ipv4', 'dns_resolve_ipv6',
'dns_resolve_reverse', 'dns_resolve_reverse_ipv6']
cdef extern from *:
ctypedef char* const_char_ptr "const char*"
cdef extern from "libevent.h":
ctypedef void (*evdns_handler)(int result, char t, int count, int ttl, void *addrs, void *arg)
int evdns_init()
const_char_ptr evdns_err_to_string(int err)
int evdns_resolve_ipv4(char *name, int flags, evdns_handler callback, void *arg)
int evdns_resolve_ipv6(char *name, int flags, evdns_handler callback, void *arg)
int evdns_resolve_reverse(void *ip, int flags, evdns_handler callback, void *arg)
int evdns_resolve_reverse_ipv6(void *ip, int flags, evdns_handler callback, void *arg)
void evdns_shutdown(int fail_requests)
# Result codes
DNS_ERR_NONE = 0
DNS_ERR_FORMAT = 1
DNS_ERR_SERVERFAILED = 2
DNS_ERR_NOTEXIST = 3
DNS_ERR_NOTIMPL = 4
DNS_ERR_REFUSED = 5
DNS_ERR_TRUNCATED = 65
DNS_ERR_UNKNOWN = 66
DNS_ERR_TIMEOUT = 67
DNS_ERR_SHUTDOWN = 68
# Types
DNS_IPv4_A = 1
DNS_PTR = 2
DNS_IPv6_AAAA = 3
# Flags
DNS_QUERY_NO_SEARCH = 1
def dns_init():
"""Initialize async DNS resolver."""
evdns_init()
def dns_shutdown(int fail_requests=0):
"""Shutdown the async DNS resolver and terminate all active requests."""
evdns_shutdown(fail_requests)
def dns_err_to_string(int err):
cdef const_char_ptr result = evdns_err_to_string(err)
if result:
return result
cdef void __evdns_callback(int code, char type, int count, int ttl, void *addrs, void *arg) with gil:
cdef int i
cdef object callback = <object>arg
Py_DECREF(<PyObjectPtr>callback)
cdef object addr
cdef object result
if type == DNS_IPv4_A:
result = []
for i from 0 <= i < count:
addr = PyString_FromStringAndSize(&(<char *>addrs)[i*4], 4)
result.append(addr)
elif type == DNS_IPv6_AAAA:
result = []
for i from 0 <= i < count:
addr = PyString_FromStringAndSize(&(<char *>addrs)[i*16], 16)
result.append(addr)
elif type == DNS_PTR and count == 1: # only 1 PTR possible
result = PyString_FromString((<char **>addrs)[0])
else:
result = None
try:
callback(code, type, ttl, result)
except:
traceback.print_exc()
sys.exc_clear()
def dns_resolve_ipv4(char *name, int flags, object callback):
"""Lookup an A record for a given name.
- *name* -- DNS hostname
- *flags* -- either 0 or DNS_QUERY_NO_SEARCH
- *callback* -- callback with ``(result, type, ttl, addrs)`` prototype
"""
cdef int result = evdns_resolve_ipv4(name, flags, __evdns_callback, <void *>callback)
if result:
raise IOError('evdns_resolve_ipv4(%r, %r) returned %s' % (name, flags, result, ))
Py_INCREF(<PyObjectPtr>callback)
def dns_resolve_ipv6(char *name, int flags, object callback):
"""Lookup an AAAA record for a given name.
- *name* -- DNS hostname
- *flags* -- either 0 or DNS_QUERY_NO_SEARCH
- *callback* -- callback with ``(result, type, ttl, addrs)`` prototype
"""
cdef int result = evdns_resolve_ipv6(name, flags, __evdns_callback, <void *>callback)
if result:
raise IOError('evdns_resolve_ip6(%r, %r) returned %s' % (name, flags, result, ))
Py_INCREF(<PyObjectPtr>callback)
def dns_resolve_reverse(char* packed_ip, int flags, object callback):
"""Lookup a PTR record for a given IPv4 address.
- *packed_ip* -- IPv4 address (as 4-byte binary string)
- *flags* -- either 0 or DNS_QUERY_NO_SEARCH
- *callback* -- callback with ``(result, type, ttl, addrs)`` prototype
"""
cdef int result = evdns_resolve_reverse(<void *>packed_ip, flags, __evdns_callback, <void *>callback)
if result:
raise IOError('evdns_resolve_reverse(%r, %r) returned %s' % (packed_ip, flags, result, ))
Py_INCREF(<PyObjectPtr>callback)
def dns_resolve_reverse_ipv6(char* packed_ip, int flags, object callback):
"""Lookup a PTR record for a given IPv6 address.
- *packed_ip* -- IPv6 address (as 16-byte binary string)
- *flags* -- either 0 or DNS_QUERY_NO_SEARCH
- *callback* -- callback with ``(result, type, ttl, addrs)`` prototype
"""
cdef int result = evdns_resolve_reverse_ipv6(<void *>packed_ip, flags, __evdns_callback, <void *>callback)
if result:
raise IOError('evdns_resolve_reverse_ipv6(%r, %r) returned %s' % (packed_ip, flags, result, ))
Py_INCREF(<PyObjectPtr>callback)
|