re-implement sctp_bindx using new sock_addr
authorTero Marttila <terom@fixme.fi>
Sun, 16 Aug 2009 03:38:01 +0300
changeset 2 171e77f8d675
parent 1 0ca9278146d7
child 3 bbad9790b786
re-implement sctp_bindx using new sock_addr
inc/addr.pxd
inc/libc.pxd
inc/sctp.pxd
sctp/sock.pyx
sock/addr.pyx
--- a/inc/addr.pxd	Sun Aug 16 03:12:46 2009 +0300
+++ b/inc/addr.pxd	Sun Aug 16 03:38:01 2009 +0300
@@ -26,3 +26,6 @@
     # each of these can be NULL to ignore it
     cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1
 
+    cdef libc.sockaddr* _get_sockaddr_ptr (self) except NULL
+    cdef libc.socklen_t _get_sockaddr_len (self) except -1
+
--- a/inc/libc.pxd	Sun Aug 16 03:12:46 2009 +0300
+++ b/inc/libc.pxd	Sun Aug 16 03:38:01 2009 +0300
@@ -22,6 +22,9 @@
     ctypedef int16_t __s16
     ctypedef int32_t __s32
 
+cdef extern from "string.h" :
+    void* memcpy (void *dest, void *src, size_t n)
+
 cdef extern from "alloca.h" :
     void* alloca (size_t size)
 
--- a/inc/sctp.pxd	Sun Aug 16 03:12:46 2009 +0300
+++ b/inc/sctp.pxd	Sun Aug 16 03:38:01 2009 +0300
@@ -195,7 +195,7 @@
     int SCTP_BINDX_ADD_ADDR
     int SCTP_BINDX_REM_ADDR
 
-    int sctp_bindx (int sd, libc.sockaddr *addrs, int addrcnt, int flags)
+    int c_sctp_bindx "sctp_bindx" (int sd, libc.sockaddr *addrs, int addrcnt, int flags)
     int sctp_connectx (int sd, libc.sockaddr *addrs, int addrcnt)
 
 
--- a/sctp/sock.pyx	Sun Aug 16 03:12:46 2009 +0300
+++ b/sctp/sock.pyx	Sun Aug 16 03:38:01 2009 +0300
@@ -5,39 +5,47 @@
 from sctp cimport *
 
 cimport libc
+cimport sock.addr
 
-def bindx (int sd, object addrs, int flags) :
+def sctp_bindx (int sd, object addrs, int flags) :
     """
-        Bind the given SOCK_SEQPACKET to the given set of local addresses.
+        Bind the given SOCK_SEQPACKET to the given set of sock.addr.sockaddr's.
 
             sd          the system socket FD
-            addresses   the list of address tuples
+            addresses   the list of qmsk.net.sock.addr.sockaddr's
             flags       one of SCTP_BINDX_ADD/REM_ADDR
     """
-    
-    # automatically allocated array of sockaddr_storage's for passing given addresses to sctp_bindx
-    cdef libc.sockaddr_storage *addrs_out
-
-    # used to iterate through addrs_out
-    cdef libc.sockaddr_in *addr_in
-    
-    # number of addresses given
-    cdef size_t addr_count = len(addrs)
-
-    # alloc stack storage for converting addresses
-    addrs_out = <libc.sockaddr_storage *> libc.alloca(addr_count * sizeof(libc.sockaddr_storage))
 
-    for i, address in enumerate(addrs) :
-        # XXX: assume socket-style IPv4 for now...
-        addr, port = address
+    # ensure that addrs stays the same... ?
+    addrs = tuple(addrs)
 
-        addr_in = <libc.sockaddr_in *>(&addrs_out[i])
+    cdef size_t addr_count = len(addrs)
+    cdef size_t addr_size = 0
+    cdef 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)
         
-        addr_in.sin_family = libc.AF_INET
-        addr_in.sin_port = libc.htons(port)
+        # copy to buffer
+        libc.memcpy(addr_ptr, sa, sa_len)
+        
+        # move to next
+        addr_ptr += sa_len
 
-        # XXX: known broken
-        libc.inet_aton(addr, &addr_in.sin_addr)
-    
-    return sctp_bindx(sd, <libc.sockaddr *>addrs_out, addr_count, flags)
+    # then call
+    if c_sctp_bindx(sd, <libc.sockaddr *> addr_buf, addr_count, flags) < 0 :
+        raise OSError
 
--- a/sock/addr.pyx	Sun Aug 16 03:12:46 2009 +0300
+++ b/sock/addr.pyx	Sun Aug 16 03:38:01 2009 +0300
@@ -17,6 +17,30 @@
 
         raise NotImplementedError()
 
+    cdef libc.sockaddr* _get_sockaddr_ptr (self) except NULL :
+        """
+            Get the sockaddr pointer
+        """
+
+        cdef libc.sockaddr *sa
+        cdef libc.socklen_t sa_len
+
+        self._get_sockaddr(&sa, &sa_len)
+
+        return sa
+    
+    cdef libc.socklen_t _get_sockaddr_len (self) except -1 :
+        """
+            Get the sockaddr len
+        """
+
+        cdef libc.sockaddr *sa
+        cdef libc.socklen_t sa_len
+
+        self._get_sockaddr(&sa, &sa_len)
+
+        return sa_len
+
     def getnameinfo (self) :
         """
             Returns a (host, serv) tuple for this address à la getnameinfo