|
1 """ |
|
2 Socket addresses at various levels: |
|
3 |
|
4 sockaddr - specific network-level address for socket operations |
|
5 addrinfo - information on a specific sockaddr including its socket parameters |
|
6 endpoint - human-readable network address, corresponding to multiple sockaddr's |
|
7 """ |
|
8 |
|
9 cimport libc |
|
10 |
|
11 cdef class sockaddr : |
|
12 """ |
|
13 A network-level socket address |
|
14 |
|
15 XXX: rename to 'address' |
|
16 |
|
17 >>> sockaddr().family |
|
18 0 |
|
19 >>> sockaddr().port |
|
20 Traceback (most recent call last): |
|
21 ... |
|
22 NotImplementedError |
|
23 >>> sockaddr().getnameinfo() |
|
24 Traceback (most recent call last): |
|
25 ... |
|
26 NotImplementedError |
|
27 """ |
|
28 |
|
29 # address family |
|
30 # XXX: this should be a class constant! It's part of our type safety! |
|
31 cdef readonly libc.sa_family_t family |
|
32 |
|
33 cdef void _init_family (self, libc.sa_family_t family = ?) |
|
34 |
|
35 # get the sockaddr/socklen |
|
36 # each of these can be NULL to ignore it |
|
37 cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 |
|
38 |
|
39 cdef libc.sockaddr* _get_sockaddr_ptr (self) except NULL |
|
40 cdef libc.socklen_t _get_sockaddr_len (self) except -1 |
|
41 |
|
42 # set the sockaddr, socklen must match |
|
43 cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 |
|
44 |
|
45 # build a sockaddr from the given sockaddr struct, based on sa_family |
|
46 cdef sockaddr build_sockaddr (libc.sockaddr *sa, size_t sa_len) |
|
47 |
|
48 cdef class addrinfo : |
|
49 """ |
|
50 A socket-level endpoint address, which contains the full socket parameters and an bind/connect address |
|
51 """ |
|
52 |
|
53 # cdef readonly int flags |
|
54 cdef readonly int family, socktype, protocol |
|
55 cdef readonly sockaddr addr |
|
56 cdef readonly object canonname |
|
57 |
|
58 cdef _init_addrinfo (self, libc.addrinfo *c_ai) |
|
59 |
|
60 # build and return a new addrinfo instance |
|
61 cdef addrinfo build_addrinfo (libc.addrinfo *c_ai) |
|
62 |
|
63 cdef class endpoint : |
|
64 """ |
|
65 A network-level socket endpoint. This is the level that humans mostly work with, but the tricky bit is that |
|
66 an endpoint can map to more than one sockaddr... |
|
67 |
|
68 Hence, endpoints are stored as human-readable hostname/service strings, which are then translated to sockaddrs |
|
69 using getaddrinfo. |
|
70 |
|
71 >>> import socket |
|
72 >>> e = endpoint('127.0.0.1', 80) |
|
73 >>> str(e) |
|
74 'hostname=127.0.0.1, service=80' |
|
75 >>> res = e.getaddrinfo(socket.AF_UNSPEC, socket.SOCK_STREAM) |
|
76 >>> len(res) |
|
77 1 |
|
78 >>> str(res[0]) |
|
79 'family=2, socktype=1, protocol=6, addr=127.0.0.1:80, canonname=None' |
|
80 >>> e = endpoint('2001::5', 80) |
|
81 >>> str(e) |
|
82 'hostname=2001::5, service=80' |
|
83 >>> res = e.getaddrinfo(socket.AF_UNSPEC, socket.SOCK_STREAM) |
|
84 >>> len(res) |
|
85 1 |
|
86 >>> str(res[0]) |
|
87 'family=10, socktype=1, protocol=6, addr=[2001::5]:80, canonname=None' |
|
88 |
|
89 """ |
|
90 |
|
91 # our defining attributes, set via __init__ |
|
92 cdef object hostname, service |
|
93 |
|
94 cpdef getaddrinfo (self, int family, int socktype, int protocol = ?, int flags = ?) |
|
95 |