terom@24: """ terom@24: This C(ython) extension module provides an interface to the libsctp library and associated socket API. terom@24: terom@24: >>> from __future__ import absolute_import; terom@24: >>> from qmsk.net.socket.af_inet import sockaddr_in terom@24: >>> from qmsk.net.socket.constants import * terom@24: >>> s = sctp_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP) terom@24: >>> s.sctp_bindx([sockaddr_in('127.0.0.1', 1337), sockaddr_in('127.0.0.2')], 0x01) terom@24: >>> terom@24: terom@24: """ terom@24: terom@24: from qmsk.net.socket.sctp cimport * terom@24: from qmsk.net.socket.address cimport sockaddr terom@24: terom@24: cimport qmsk.net.socket.platform as platform terom@24: cimport qmsk.net.libc as libc terom@24: terom@24: from qmsk.net.py cimport raise_errno terom@24: terom@24: cdef size_t addrsoup_len (object addrs) except -1 : terom@24: """ terom@24: Calculate the length of the addr_buf required to store the given addrsoup terom@24: """ terom@24: terom@24: cdef sockaddr addr terom@24: cdef size_t addr_size = 0 terom@24: terom@24: # whoever decided that sctp_bindx takes an array of mixed sockaddr_in/sockaddr_in6's should be shot terom@24: for addr in addrs : terom@24: addr_size += addr._get_sockaddr_len() terom@24: terom@24: return addr_size terom@24: terom@24: cdef addrsoup_store (object addrs, char *addr_buf) : terom@24: """ terom@24: Store the sockaddr_*'s for the given addresses into the given buffer, which should be addrsoup_len() bytes long terom@24: """ terom@24: terom@24: cdef sockaddr addr terom@24: cdef char *addr_ptr = addr_buf terom@24: terom@24: # fill it terom@24: cdef platform.sockaddr *sa terom@24: cdef platform.socklen_t sa_len terom@24: terom@24: for addr in addrs : terom@24: # get address's sockaddr info terom@24: addr._get_sockaddr(&sa, &sa_len) terom@24: terom@24: # copy to buffer terom@24: libc.memcpy(addr_ptr, sa, sa_len) terom@24: terom@24: # move to next terom@24: addr_ptr += sa_len terom@24: terom@24: cdef class sctp_socket (socket.socket) : terom@24: terom@24: def __init__ (self, int family = platform.AF_INET, int socktype = platform.SOCK_SEQPACKET, int protocol = IPPROTO_SCTP, int fd = -1) : terom@24: """ terom@24: Same behaviour as socket.__init__, but different defaults. terom@24: """ terom@24: terom@24: socket.socket.__init__(self, family, socktype, protocol, fd) terom@24: terom@24: def sctp_bindx (self, object addrs, int flags) : terom@24: """ terom@24: Bind this IPPROTO_SCTP socket to the given set of local addresses. terom@24: terom@24: This may be called multiple times on a socket, even after bind(), to change the set of local addresses. terom@24: This may affect ongoing associations, or only new associations. terom@24: terom@24: addresses the list of sockaddr's terom@24: flags one of SCTP_BINDX_ADD/REM_ADDR terom@24: terom@24: """ terom@24: terom@24: # ensure that addrs stays the same... ? terom@24: addrs = tuple(addrs) terom@24: terom@24: # alloc buffer to hold all the sockaddr_*'s terom@24: cdef char *addr_buf = libc.alloca(addrsoup_len(addrs)) terom@24: terom@24: # store terom@24: addrsoup_store(addrs, addr_buf) terom@24: terom@24: # then call terom@24: if sctp_bindx(self.fd, addr_buf, len(addrs), flags) : terom@24: raise_errno('sctp_bindx') terom@24: terom@24: def sctp_connectx (self, int sd, object addrs) : terom@24: """ terom@24: Establish an association with the given set of remote sockaddr's. terom@24: terom@24: addresses the list of sockaddr's terom@24: terom@24: """ terom@24: terom@24: # ensure that addrs stays the same... ? terom@24: addrs = tuple(addrs) terom@24: terom@24: # alloc buffer to hold all the sockaddr_*'s terom@24: cdef char *addr_buf = libc.alloca(addrsoup_len(addrs)) terom@24: terom@24: # store terom@24: addrsoup_store(addrs, addr_buf) terom@24: terom@24: # then call terom@24: if sctp_connectx(self.fd, addr_buf, len(addrs)) : terom@24: raise_errno('sctp_connectx') terom@24: terom@24: