sctp/sock.pyx
changeset 6 10bd48c9b6ce
parent 5 59bed837c265
child 7 74fde84264b1
equal deleted inserted replaced
5:59bed837c265 6:10bd48c9b6ce
     1 """
       
     2     This C(ython) extension module provides an interface to the libsctp library and associated socket API.
       
     3     
       
     4     >>> import socket
       
     5     >>> from sock.addr import sockaddr_in
       
     6     >>> s = socket.socket(socket.AF_INET, socket.SOCK_SEQPACKET, 132)
       
     7     >>> sctp_bindx(s.fileno(), [sockaddr_in('127.0.0.1', 1337), sockaddr_in('127.0.0.2')], 0x01)
       
     8     >>>
       
     9 
       
    10 """
       
    11 
       
    12 from sctp.sock cimport *
       
    13 from py cimport raise_errno
       
    14 
       
    15 cimport libc
       
    16 cimport sock.addr
       
    17 
       
    18 cdef size_t addrsoup_len (object addrs) except -1 :
       
    19     """
       
    20         Calculate the length of the addr_buf required to store the given addrsoup
       
    21     """
       
    22 
       
    23     cdef sock.addr.sockaddr addr
       
    24     cdef size_t addr_size = 0
       
    25 
       
    26     # whoever decided that sctp_bindx takes an array of mixed sockaddr_in/sockaddr_in6's should be shot
       
    27     for addr in addrs :
       
    28         addr_size += addr._get_sockaddr_len()
       
    29     
       
    30     return addr_size
       
    31 
       
    32 cdef addrsoup_store (object addrs, char *addr_buf) :
       
    33     """
       
    34         Store the sockaddr_*'s for the given addresses into the given buffer, which should be addrsoup_len() bytes long
       
    35     """
       
    36 
       
    37     cdef sock.addr.sockaddr addr
       
    38     cdef char *addr_ptr = addr_buf
       
    39 
       
    40     # fill it
       
    41     cdef libc.sockaddr *sa
       
    42     cdef libc.socklen_t sa_len
       
    43 
       
    44     for addr in addrs :
       
    45         # get address's sockaddr info
       
    46         addr._get_sockaddr(&sa, &sa_len)
       
    47         
       
    48         # copy to buffer
       
    49         libc.memcpy(addr_ptr, sa, sa_len)
       
    50         
       
    51         # move to next
       
    52         addr_ptr += sa_len
       
    53 
       
    54 def sctp_bindx (int sd, object addrs, int flags) :
       
    55     """
       
    56         Bind the given SOCK_SEQPACKET to the given set of sock.addr.sockaddr's.
       
    57 
       
    58             sd          the system socket FD
       
    59             addresses   the list of qmsk.net.sock.addr.sockaddr's
       
    60             flags       one of SCTP_BINDX_ADD/REM_ADDR
       
    61         
       
    62     """
       
    63 
       
    64     # ensure that addrs stays the same... ?
       
    65     addrs = tuple(addrs)
       
    66 
       
    67     # alloc buffer to hold all the sockaddr_*'s
       
    68     cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs))
       
    69 
       
    70     # store
       
    71     addrsoup_store(addrs, addr_buf)
       
    72 
       
    73     # then call
       
    74     if c_sctp_bindx(sd, <libc.sockaddr *> addr_buf, len(addrs), flags) < 0 :
       
    75         raise_errno()
       
    76 
       
    77 def sctp_connectx (int sd, object addrs) :
       
    78     """
       
    79         Connect the given SOCK_SEQPACKET to the given set of remote sock.addr.sockaddr's.
       
    80 
       
    81             sd          the system socket FD
       
    82             addresses   the list of qmsk.net.sock.addr.sockaddr's
       
    83         
       
    84     """
       
    85 
       
    86     # ensure that addrs stays the same... ?
       
    87     addrs = tuple(addrs)
       
    88 
       
    89     # alloc buffer to hold all the sockaddr_*'s
       
    90     cdef char *addr_buf = <char *> libc.alloca(addrsoup_len(addrs))
       
    91 
       
    92     # store
       
    93     addrsoup_store(addrs, addr_buf)
       
    94 
       
    95     # then call
       
    96     if c_sctp_connectx(sd, <libc.sockaddr *> addr_buf, len(addrs)) < 0 :
       
    97         raise_errno()
       
    98