|
1 """ |
|
2 This C(ython) extension module provides an interface to the libsctp library and associated socket API. |
|
3 |
|
4 >>> import socket |
|
5 >>> from sock.addr import sockaddr_in |
|
6 >>> s = socket.socket(socket.AF_INET, socket.SOCK_SEQPACKET, 132) |
|
7 >>> sctp_bindx(s.fileno(), [sockaddr_in('127.0.0.1', 1337), sockaddr_in('127.0.0.2')], 0x01) |
|
8 >>> |
|
9 |
|
10 """ |
|
11 |
|
12 from sctp.sock cimport * |
|
13 from py cimport raise_errno |
|
14 |
|
15 cimport libc |
|
16 cimport socket.addr |
|
17 |
|
18 cdef size_t addrsoup_len (object addrs) except -1 : |
|
19 """ |
|
20 Calculate the length of the addr_buf required to store the given addrsoup |
|
21 """ |
|
22 |
|
23 cdef socket.addr.sockaddr addr |
|
24 cdef size_t addr_size = 0 |
|
25 |
|
26 # whoever decided that sctp_bindx takes an array of mixed sockaddr_in/sockaddr_in6's should be shot |
|
27 for addr in addrs : |
|
28 addr_size += addr._get_sockaddr_len() |
|
29 |
|
30 return addr_size |
|
31 |
|
32 cdef addrsoup_store (object addrs, char *addr_buf) : |
|
33 """ |
|
34 Store the sockaddr_*'s for the given addresses into the given buffer, which should be addrsoup_len() bytes long |
|
35 """ |
|
36 |
|
37 cdef socket.addr.sockaddr addr |
|
38 cdef char *addr_ptr = addr_buf |
|
39 |
|
40 # fill it |
|
41 cdef libc.sockaddr *sa |
|
42 cdef libc.socklen_t sa_len |
|
43 |
|
44 for addr in addrs : |
|
45 # get address's sockaddr info |
|
46 addr._get_sockaddr(&sa, &sa_len) |
|
47 |
|
48 # copy to buffer |
|
49 libc.memcpy(addr_ptr, sa, sa_len) |
|
50 |
|
51 # move to next |
|
52 addr_ptr += sa_len |
|
53 |
|
54 def sctp_bindx (int sd, object addrs, int flags) : |
|
55 """ |
|
56 Bind the given SOCK_SEQPACKET to the given set of sock.addr.sockaddr's. |
|
57 |
|
58 sd the system socket FD |
|
59 addresses the list of qmsk.net.sock.addr.sockaddr's |
|
60 flags one of SCTP_BINDX_ADD/REM_ADDR |
|
61 |
|
62 """ |
|
63 |
|
64 # ensure that addrs stays the same... ? |
|
65 addrs = tuple(addrs) |
|
66 |
|
67 # alloc buffer to hold all the sockaddr_*'s |
|
68 cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs)) |
|
69 |
|
70 # store |
|
71 addrsoup_store(addrs, addr_buf) |
|
72 |
|
73 # then call |
|
74 if c_sctp_bindx(sd, <libc.sockaddr *> addr_buf, len(addrs), flags) < 0 : |
|
75 raise_errno('sctp_bindx') |
|
76 |
|
77 def sctp_connectx (int sd, object addrs) : |
|
78 """ |
|
79 Connect the given SOCK_SEQPACKET to the given set of remote sock.addr.sockaddr's. |
|
80 |
|
81 sd the system socket FD |
|
82 addresses the list of qmsk.net.sock.addr.sockaddr's |
|
83 |
|
84 """ |
|
85 |
|
86 # ensure that addrs stays the same... ? |
|
87 addrs = tuple(addrs) |
|
88 |
|
89 # alloc buffer to hold all the sockaddr_*'s |
|
90 cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs)) |
|
91 |
|
92 # store |
|
93 addrsoup_store(addrs, addr_buf) |
|
94 |
|
95 # then call |
|
96 if c_sctp_connectx(sd, <libc.sockaddr *> addr_buf, len(addrs)) < 0 : |
|
97 raise_errno('sctp_connectx') |
|
98 |