6
|
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 |
|
8
|
71 |
>>> from __future__ import absolute_import; import socket as _socket
|
6
|
72 |
>>> e = endpoint('127.0.0.1', 80)
|
|
73 |
>>> str(e)
|
|
74 |
'hostname=127.0.0.1, service=80'
|
8
|
75 |
>>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM)
|
6
|
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'
|
8
|
83 |
>>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM)
|
6
|
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 |
|