qmsk/net/socket/sctp.pyx
changeset 24 f18b5787c46c
child 49 e2f79e68418a
equal deleted inserted replaced
23:15d8bb96b8d4 24:f18b5787c46c
       
     1 """
       
     2     This C(ython) extension module provides an interface to the libsctp library and associated socket API.
       
     3     
       
     4     >>> from __future__ import absolute_import;
       
     5     >>> from qmsk.net.socket.af_inet import sockaddr_in
       
     6     >>> from qmsk.net.socket.constants import *
       
     7     >>> s = sctp_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)
       
     8     >>> s.sctp_bindx([sockaddr_in('127.0.0.1', 1337), sockaddr_in('127.0.0.2')], 0x01)
       
     9     >>>
       
    10 
       
    11 """
       
    12 
       
    13 from qmsk.net.socket.sctp cimport *
       
    14 from qmsk.net.socket.address cimport sockaddr
       
    15 
       
    16 cimport qmsk.net.socket.platform as platform
       
    17 cimport qmsk.net.libc as libc
       
    18 
       
    19 from qmsk.net.py cimport raise_errno
       
    20 
       
    21 cdef size_t addrsoup_len (object addrs) except -1 :
       
    22     """
       
    23         Calculate the length of the addr_buf required to store the given addrsoup
       
    24     """
       
    25 
       
    26     cdef sockaddr addr
       
    27     cdef size_t addr_size = 0
       
    28 
       
    29     # whoever decided that sctp_bindx takes an array of mixed sockaddr_in/sockaddr_in6's should be shot
       
    30     for addr in addrs :
       
    31         addr_size += addr._get_sockaddr_len()
       
    32     
       
    33     return addr_size
       
    34 
       
    35 cdef addrsoup_store (object addrs, char *addr_buf) :
       
    36     """
       
    37         Store the sockaddr_*'s for the given addresses into the given buffer, which should be addrsoup_len() bytes long
       
    38     """
       
    39 
       
    40     cdef sockaddr addr
       
    41     cdef char *addr_ptr = addr_buf
       
    42 
       
    43     # fill it
       
    44     cdef platform.sockaddr *sa
       
    45     cdef platform.socklen_t sa_len
       
    46 
       
    47     for addr in addrs :
       
    48         # get address's sockaddr info
       
    49         addr._get_sockaddr(&sa, &sa_len)
       
    50         
       
    51         # copy to buffer
       
    52         libc.memcpy(addr_ptr, sa, sa_len)
       
    53         
       
    54         # move to next
       
    55         addr_ptr += sa_len
       
    56 
       
    57 cdef class sctp_socket (socket.socket) :
       
    58 
       
    59     def __init__ (self, int family = platform.AF_INET, int socktype = platform.SOCK_SEQPACKET, int protocol = IPPROTO_SCTP, int fd = -1) :
       
    60         """
       
    61             Same behaviour as socket.__init__, but different defaults.
       
    62         """
       
    63 
       
    64         socket.socket.__init__(self, family, socktype, protocol, fd)
       
    65 
       
    66     def sctp_bindx (self, object addrs, int flags) :
       
    67         """
       
    68             Bind this IPPROTO_SCTP socket to the given set of local addresses.
       
    69 
       
    70             This may be called multiple times on a socket, even after bind(), to change the set of local addresses.
       
    71             This may affect ongoing associations, or only new associations.
       
    72 
       
    73                 addresses   the list of sockaddr's
       
    74                 flags       one of SCTP_BINDX_ADD/REM_ADDR
       
    75             
       
    76         """
       
    77 
       
    78         # ensure that addrs stays the same... ?
       
    79         addrs = tuple(addrs)
       
    80 
       
    81         # alloc buffer to hold all the sockaddr_*'s
       
    82         cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs))
       
    83 
       
    84         # store
       
    85         addrsoup_store(addrs, addr_buf)
       
    86 
       
    87         # then call
       
    88         if sctp_bindx(self.fd, <platform.sockaddr *> addr_buf, len(addrs), flags) :
       
    89             raise_errno('sctp_bindx')
       
    90 
       
    91     def sctp_connectx (self, int sd, object addrs) :
       
    92         """
       
    93             Establish an association with the given set of remote sockaddr's.
       
    94 
       
    95                 addresses   the list of sockaddr's
       
    96             
       
    97         """
       
    98 
       
    99         # ensure that addrs stays the same... ?
       
   100         addrs = tuple(addrs)
       
   101 
       
   102         # alloc buffer to hold all the sockaddr_*'s
       
   103         cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs))
       
   104 
       
   105         # store
       
   106         addrsoup_store(addrs, addr_buf)
       
   107 
       
   108         # then call
       
   109         if sctp_connectx(self.fd, <platform.sockaddr *> addr_buf, len(addrs)) :
       
   110             raise_errno('sctp_connectx')
       
   111 
       
   112