author | Tero Marttila <terom@fixme.fi> |
Sun, 23 Aug 2009 22:31:12 +0300 | |
changeset 30 | 0e0b9bc2c96b |
parent 27 | 12468e38227e |
child 46 | 64b4ffb44754 |
permissions | -rw-r--r-- |
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 |
||
11
7ae92c2b433f
move libc+py back to qmsk.net.x
Tero Marttila <terom@fixme.fi>
parents:
10
diff
changeset
|
9 |
cimport qmsk.net.libc as libc |
6 | 10 |
|
10 | 11 |
cimport qmsk.net.socket.platform as platform |
12 |
||
6 | 13 |
cdef class sockaddr : |
14 |
""" |
|
15 |
A network-level socket address |
|
27
12468e38227e
[socket] add sockaddr_un (still dysfunctional\!) + doc fixes
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
16 |
|
12468e38227e
[socket] add sockaddr_un (still dysfunctional\!) + doc fixes
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
17 |
XXX: not abstract enough. Functions/properties like getnameinfo/addr/port do not work for e.g. sockaddr_un |
6 | 18 |
|
19 |
>>> sockaddr().family |
|
20 |
0 |
|
21 |
>>> sockaddr().port |
|
22 |
Traceback (most recent call last): |
|
23 |
... |
|
24 |
NotImplementedError |
|
25 |
>>> sockaddr().getnameinfo() |
|
26 |
Traceback (most recent call last): |
|
27 |
... |
|
28 |
NotImplementedError |
|
29 |
""" |
|
30 |
||
31 |
# address family |
|
32 |
# XXX: this should be a class constant! It's part of our type safety! |
|
10 | 33 |
cdef readonly platform.sa_family_t family |
6 | 34 |
|
10 | 35 |
cdef void _init_family (self, platform.sa_family_t family = ?) |
6 | 36 |
|
37 |
# get the sockaddr/socklen |
|
38 |
# each of these can be NULL to ignore it |
|
10 | 39 |
cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 |
6 | 40 |
|
10 | 41 |
cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL |
42 |
cdef platform.socklen_t _get_sockaddr_len (self) except -1 |
|
6 | 43 |
|
44 |
# set the sockaddr, socklen must match |
|
10 | 45 |
cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 |
6 | 46 |
|
47 |
# build a sockaddr from the given sockaddr struct, based on sa_family |
|
10 | 48 |
cdef sockaddr build_sockaddr (platform.sockaddr *sa, size_t sa_len) |
6 | 49 |
|
50 |
cdef class addrinfo : |
|
51 |
""" |
|
23
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
52 |
A socket-level endpoint address, which contains the full socket parameters and an bind/connect address. |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
53 |
|
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
54 |
A full addrinfo struct is stored, but ai_canonname and ai_addr are stored as (optional) objects outside of the |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
55 |
addrinfo struct. |
30 | 56 |
|
57 |
>>> from qmsk.net.socket import af_inet |
|
23
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
58 |
>>> ai = addrinfo() |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
59 |
>>> ai.addr |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
60 |
>>> ai.canonname |
30 | 61 |
>>> print addrinfo(addr=af_inet.sockaddr_in()) |
23
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
62 |
family=0, socktype=0, protocol=0, addr=0.0.0.0:0, canonname=None |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
63 |
""" |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
64 |
|
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
65 |
# canonname is not stored |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
66 |
# may be NULL |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
67 |
cdef platform.addrinfo ai |
6 | 68 |
|
23
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
69 |
# may be NULL |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
70 |
cdef sockaddr ai_addr |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
71 |
cdef object ai_canonname |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
72 |
|
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
73 |
# update self.ai.ai_* to reflect self.ai_* |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
74 |
cdef _init_ai_members (self) |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
75 |
|
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
76 |
# set the contents of self.ai from the given real addrinfo |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
77 |
# this ignores the ai_canonname attribute |
15d8bb96b8d4
fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
Tero Marttila <terom@fixme.fi>
parents:
20
diff
changeset
|
78 |
cdef _init_addrinfo (self, platform.addrinfo *ai) |
6 | 79 |
|
80 |
# build and return a new addrinfo instance |
|
10 | 81 |
cdef addrinfo build_addrinfo (platform.addrinfo *c_ai) |
6 | 82 |
|
83 |
cdef class endpoint : |
|
84 |
""" |
|
85 |
A network-level socket endpoint. This is the level that humans mostly work with, but the tricky bit is that |
|
86 |
an endpoint can map to more than one sockaddr... |
|
87 |
||
88 |
Hence, endpoints are stored as human-readable hostname/service strings, which are then translated to sockaddrs |
|
89 |
using getaddrinfo. |
|
90 |
||
8 | 91 |
>>> from __future__ import absolute_import; import socket as _socket |
6 | 92 |
>>> e = endpoint('127.0.0.1', 80) |
93 |
>>> str(e) |
|
94 |
'hostname=127.0.0.1, service=80' |
|
8 | 95 |
>>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM) |
6 | 96 |
>>> len(res) |
97 |
1 |
|
98 |
>>> str(res[0]) |
|
99 |
'family=2, socktype=1, protocol=6, addr=127.0.0.1:80, canonname=None' |
|
100 |
>>> e = endpoint('2001::5', 80) |
|
101 |
>>> str(e) |
|
102 |
'hostname=2001::5, service=80' |
|
8 | 103 |
>>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM) |
6 | 104 |
>>> len(res) |
105 |
1 |
|
106 |
>>> str(res[0]) |
|
107 |
'family=10, socktype=1, protocol=6, addr=[2001::5]:80, canonname=None' |
|
108 |
||
109 |
""" |
|
110 |
||
111 |
# our defining attributes, set via __init__ |
|
30 | 112 |
cdef public object hostname, service |
6 | 113 |
|
114 |
cpdef getaddrinfo (self, int family, int socktype, int protocol = ?, int flags = ?) |
|
115 |