qmsk/net/sctp/sock.pyx
changeset 7 74fde84264b1
parent 6 10bd48c9b6ce
child 8 b3880dafbab1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/sctp/sock.pyx	Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,98 @@
+"""
+    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.sock cimport *
+from py cimport raise_errno
+
+cimport libc
+cimport socket.addr
+
+cdef size_t addrsoup_len (object addrs) except -1 :
+    """
+        Calculate the length of the addr_buf required to store the given addrsoup
+    """
+
+    cdef socket.addr.sockaddr addr
+    cdef size_t addr_size = 0
+
+    # 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()
+    
+    return addr_size
+
+cdef addrsoup_store (object addrs, char *addr_buf) :
+    """
+        Store the sockaddr_*'s for the given addresses into the given buffer, which should be addrsoup_len() bytes long
+    """
+
+    cdef socket.addr.sockaddr addr
+    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
+
+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)
+
+    # alloc buffer to hold all the sockaddr_*'s
+    cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs))
+
+    # store
+    addrsoup_store(addrs, addr_buf)
+
+    # then call
+    if c_sctp_bindx(sd, <libc.sockaddr *> addr_buf, len(addrs), flags) < 0 :
+        raise_errno('sctp_bindx')
+
+def sctp_connectx (int sd, object addrs) :
+    """
+        Connect the given SOCK_SEQPACKET to the given set of remote sock.addr.sockaddr's.
+
+            sd          the system socket FD
+            addresses   the list of qmsk.net.sock.addr.sockaddr's
+        
+    """
+
+    # ensure that addrs stays the same... ?
+    addrs = tuple(addrs)
+
+    # alloc buffer to hold all the sockaddr_*'s
+    cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs))
+
+    # store
+    addrsoup_store(addrs, addr_buf)
+
+    # then call
+    if c_sctp_connectx(sd, <libc.sockaddr *> addr_buf, len(addrs)) < 0 :
+        raise_errno('sctp_connectx')
+