--- a/qmsk/net/sctp/sock.pxd Mon Aug 17 01:29:31 2009 +0300
+++ b/qmsk/net/sctp/sock.pxd Mon Aug 17 19:40:23 2009 +0300
@@ -1,6 +1,14 @@
-from qmsk.net.libc cimport __u8, __u16, __u32, __s8, __s16, __s32
+"""
+ The socket-based interface for SCTP.
+
+ http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-15
+"""
+
+#from qmsk.net.libc cimport __u8, __u16, __u32, __s8, __s16, __s32, ssize_t
+from qmsk.net.libc cimport *
cimport qmsk.net.socket.platform as platform
+cimport qmsk.net.socket.socket
# <netinet/sctp.h>
# this defines the kernel SCTP -> userspace API extensions, such as structure types etc.
@@ -56,6 +64,8 @@
__u32 sinfo_cumtsn
sctp_assoc_t sinfo_assoc_id
+ # XXX: missing sctp_extrcvinfo
+
# sctp_sndrcvinfo.sinfo_flags values
enum sctp_sinfo_flags :
SCTP_UNORDERED # Send/receive message unordered
@@ -192,15 +202,76 @@
ctypedef sctp_sn_error sctp_sn_error_t
+
+ ###
+ ### 8 New Interfaces
+ ###
- ## sctp_bindx
+ ## 8.1 sctp_bindx
enum :
SCTP_BINDX_ADD_ADDR
SCTP_BINDX_REM_ADDR
- int c_sctp_bindx "sctp_bindx" (int sd, platform.sockaddr *addrs, int addrcnt, int flags)
+ int sctp_bindx (int sd, platform.sockaddr *addrs, int addrcnt, int flags)
- # XXX: missing return-sctp_assoc_t-id argument!
- int c_sctp_connectx "sctp_connectx" (int sd, platform.sockaddr *addrs, int addrcnt)
+ ## 8.2 sctp_peeloff
+ int sctp_peeloff (int sd, sctp_assoc_t assoc_id)
+
+ ## 8.3 sctp_getpaddrs
+ int sctp_getpaddrs (int sd, sctp_assoc_t assoc_id, platform.sockaddr **addrs)
+ ## 8.4 sctp_freepaddrs
+ void sctp_freepaddrs (platform.sockaddr *addrs)
+
+ ## 8.5 sctp_getladdrs
+ int sctp_getladdrs (int sd, sctp_assoc_t id, platform.sockaddr **ss)
+ ## 8.6 sctp_freeladdrs
+ void sctp_freeladdrs (platform.sockaddr **ss)
+
+ ## 8.7 sctp_sendmsg
+ ssize_t sctp_sendmsg (
+ int sd,
+ void *msg, size_t len,
+ platform.sockaddr *dst, platform.socklen_t dstlen,
+ uint32_t ppid, uint32_t flags, uint16_t stream_no, uint32_t timetolive, uint32_t context
+ )
+
+ ## 8.8 sctp_Recvmsg
+ ssize_t sctp_recvmsg (
+ int sd,
+ void *msg, size_t len,
+ platform.sockaddr *src, platform.socklen_t *srclen,
+ sctp_sndrcvinfo *sinfo,
+ int *msg_flags
+ )
+ ## 8.9 sctp_connectx
+ # XXX: missing return-sctp_assoc_t-id argument from RFC!
+ int sctp_connectx (int sd, platform.sockaddr *addrs, int addrcnt)
+
+ ## 8.10 sctp_send
+ int sctp_send (
+ int sd,
+ void *msg, size_t len,
+ sctp_sndrcvinfo *sinfo,
+ int flags
+ )
+
+ ## 8.11 sctp_sendx
+ int sctp_sendx (
+ int sd,
+ void *msg, size_t len,
+ platform.sockaddr *addrs, int addrcnt,
+ sctp_sndrcvinfo *sinfo,
+ int flags
+ )
+
+ ## 8.12 sctp_getaddrlen
+ int sctp_getaddrlen (platform.sa_family_t family)
+
+cdef class sctp_socket (qmsk.net.socket.socket.socket) :
+ """
+ SCTP-specific methods and functionality, built on top of the generic socket interface.
+ """
+
+
--- a/qmsk/net/sctp/sock.pyx Mon Aug 17 01:29:31 2009 +0300
+++ b/qmsk/net/sctp/sock.pyx Mon Aug 17 19:40:23 2009 +0300
@@ -1,10 +1,11 @@
"""
This C(ython) extension module provides an interface to the libsctp library and associated socket API.
- >>> from __future__ import absolute_import; import socket as _socket
- >>> from qmsk.net.socket.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 __future__ import absolute_import;
+ >>> from qmsk.net.socket.address import sockaddr_in
+ >>> from qmsk.net.socket.constants import *
+ >>> s = sctp_socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)
+ >>> s.sctp_bindx([sockaddr_in('127.0.0.1', 1337), sockaddr_in('127.0.0.2')], 0x01)
>>>
"""
@@ -53,48 +54,59 @@
# 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)
+cdef class sctp_socket (qmsk.net.socket.socket.socket) :
- # then call
- if c_sctp_bindx(sd, <platform.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
-
- """
+ def __init__ (self, int family = platform.AF_INET, int socktype = platform.SOCK_SEQPACKET, int protocol = IPPROTO_SCTP, int fd = -1) :
+ """
+ Same behaviour as socket.__init__, but different defaults.
+ """
- # 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))
+ qmsk.net.socket.socket.socket.__init__(self, family, socktype, protocol, fd)
- # store
- addrsoup_store(addrs, addr_buf)
+ def sctp_bindx (self, object addrs, int flags) :
+ """
+ Bind this IPPROTO_SCTP socket to the given set of local addresses.
- # then call
- if c_sctp_connectx(sd, <platform.sockaddr *> addr_buf, len(addrs)) < 0 :
- raise_errno('sctp_connectx')
+ This may be called multiple times on a socket, even after bind(), to change the set of local addresses.
+ This may affect ongoing associations, or only new associations.
+ addresses the list of 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 sctp_bindx(self.fd, <platform.sockaddr *> addr_buf, len(addrs), flags) :
+ raise_errno('sctp_bindx')
+
+ def sctp_connectx (self, int sd, object addrs) :
+ """
+ Establish an association with the given set of remote sockaddr's.
+
+ addresses the list of 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 sctp_connectx(self.fd, <platform.sockaddr *> addr_buf, len(addrs)) :
+ raise_errno('sctp_connectx')
+
+
--- a/qmsk/net/socket/socket.pxd Mon Aug 17 01:29:31 2009 +0300
+++ b/qmsk/net/socket/socket.pxd Mon Aug 17 19:40:23 2009 +0300
@@ -8,7 +8,7 @@
"""
Represents a single OS-level socket
- >>> from qmsk.net.socket import addr
+ >>> from qmsk.net.socket import address as addr
>>> from qmsk.net.socket.constants import *
>>> s = socket(1337)
@@ -33,6 +33,15 @@
...
OSError: [Errno 111] Connection refused
+
+ >>> s1 = socket(AF_INET, SOCK_STREAM); s2 = socket(AF_INET, SOCK_STREAM)
+ >>> s1.listen(1);
+ >>> s2.connect(s1.getsockname())
+ >>> s12, s12_addr = s1.accept()
+ >>> s12_addr == s12.getpeername() == s2.getsockname()
+ True
+ >>> s1.close(); s2.close()
+
"""
cdef readonly socket_t fd