"""
This C(ython) extension module provides an interface to the libsctp library and associated socket API.
>>> import socket
>>> from sock.addr import sockaddr_in
>>> s = socket.socket(socket.AF_INET, socket.SOCK_SEQPACKET, 132)
>>> sctp_bindx(s.fileno(), [sockaddr_in('127.0.0.1', 1337), sockaddr_in('127.0.0.2')], 0x01)
>>>
"""
from sctp cimport *
cimport libc
cimport sock.addr
cdef extern from "Python.h" :
struct PyObject :
pass
PyObject* PyErr_SetFromErrno (PyObject *type)
PyObject* PyExc_OSError
cdef int raise_errno () except -1 :
PyErr_SetFromErrno(PyExc_OSError)
return -1
def sctp_bindx (int sd, object addrs, int flags) :
"""
Bind the given SOCK_SEQPACKET to the given set of sock.addr.sockaddr's.
sd the system socket FD
addresses the list of qmsk.net.sock.addr.sockaddr's
flags one of SCTP_BINDX_ADD/REM_ADDR
"""
# ensure that addrs stays the same... ?
addrs = tuple(addrs)
cdef size_t addr_count = len(addrs)
cdef size_t addr_size = 0
cdef sock.addr.sockaddr addr
# whoever decided that sctp_bindx takes an array of mixed sockaddr_in/sockaddr_in6's should be shot
for addr in addrs :
addr_size += addr._get_sockaddr_len()
# alloc buffer to hold all the sockaddr_*'s
cdef char *addr_buf = <char *> libc.alloca(addr_size)
cdef char *addr_ptr = addr_buf
# fill it
cdef libc.sockaddr *sa
cdef libc.socklen_t sa_len
for addr in addrs :
# get address's sockaddr info
addr._get_sockaddr(&sa, &sa_len)
# copy to buffer
libc.memcpy(addr_ptr, sa, sa_len)
# move to next
addr_ptr += sa_len
# then call
if c_sctp_bindx(sd, <libc.sockaddr *> addr_buf, addr_count, flags) < 0 :
raise_errno()