File: evdns.pxi

package info (click to toggle)
python-gevent 0.13.6-1%2Bnmu3
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 2,324 kB
  • sloc: python: 13,296; makefile: 95; ansic: 37
file content (133 lines) | stat: -rw-r--r-- 4,642 bytes parent folder | download
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)