--- a/inc/libc.pxd Sun Aug 16 18:29:55 2009 +0300
+++ b/inc/libc.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -1,1 +1,1 @@
-../libc.pxd
\ No newline at end of file
+../qmsk/net/libc.pxd
\ No newline at end of file
--- a/inc/py.pxd Sun Aug 16 18:29:55 2009 +0300
+++ b/inc/py.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -1,1 +1,1 @@
-../py.pxd
\ No newline at end of file
+../qmsk/net/py.pxd
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/qmsk.net.socket.addr.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,1 @@
+../qmsk/net/socket/addr.pxd
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/qmsk.net.socket.socket.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,1 @@
+../qmsk/net/socket/socket.pxd
\ No newline at end of file
--- a/inc/sctp.sock.pxd Sun Aug 16 18:29:55 2009 +0300
+++ b/inc/sctp.sock.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -1,1 +1,1 @@
-../sctp/sock.pxd
\ No newline at end of file
+../qmsk/net/sctp/sock.pxd
\ No newline at end of file
--- a/inc/sock.addr.pxd Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../sock/addr.pxd
\ No newline at end of file
--- a/libc.pxd Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-"""
- Libc stuff
-"""
-
-cdef extern from "stdint.h" :
- # yes, these are "wrong"
- ctypedef unsigned char uint8_t
- ctypedef unsigned short uint16_t
- ctypedef unsigned int uint32_t
-
- ctypedef signed char int8_t
- ctypedef signed short int16_t
- ctypedef signed int int32_t
-
-cdef extern from "sys/types.h" :
- # potentially wrong...
- ctypedef signed long ssize_t
-
-# <linux/types.h>
-cdef extern from "linux/types.h" :
- ctypedef uint8_t __u8
- ctypedef uint16_t __u16
- ctypedef uint32_t __u32
-
- ctypedef int8_t __s8
- ctypedef int16_t __s16
- ctypedef int32_t __s32
-
-cdef extern from "errno.h" :
- int errno
-
-cdef extern from "string.h" :
- void* memcpy (void *dest, void *src, size_t n)
- void* memset (void *s, int c, size_t n)
-
- char* strerror (int errno)
-
-cdef extern from "alloca.h" :
- void* alloca (size_t size)
-
-cdef extern from "sys/uio.h" :
- struct iovec :
- void *iov_base
- size_t iov_len
-
-cdef extern from "arpa/inet.h" :
- # XXX: correct?!
- ctypedef uint32_t socklen_t
-
- char* c_inet_ntop "inet_ntop" (int af, void *sockaddr, char *buf, socklen_t len)
- int c_inet_pton "inet_pton" (int af, char *src, void *dst)
-
-# <sys/socket.h>
-cdef extern from "sys/socket.h" :
- # socket types
- enum :
- SOCK_STREAM
- SOCK_DGRAM
- SOCK_RAW
- SOCK_RDM
- SOCK_SEQPACKET
- SOCK_PACKET
-
- # packet/address families
- enum :
- PF_UNSPEC
- PF_LOCAL
- PF_UNIX # same as PF_LOCAL
- PF_FILE # same as PF_LOCAL
- PF_INET
- PF_INET6
- PF_NETLINK
- PF_ROUTE # same as PF_NETLINK
-
-
- # aliases for PF_*
- enum :
- AF_UNSPEC
- AF_LOCAL
- AF_UNIX
- AF_FILE
- AF_INET
- AF_INET6
- AF_NETLINK
- AF_ROUTE
-
- # base sockaddr stuff
- ctypedef uint16_t sa_family_t
-
- struct sockaddr :
- sa_family_t sa_family
-
- struct sockaddr_storage :
- sa_family_t ss_family
-
- # flag values
- enum :
- MSG_OOB
- MSG_PEEK
- MSG_DONTROUTE
- MSG_CTRUNC
- MSG_PROXY
- MSG_TRUNC
- MSG_DONTWAIT
- MSG_EOR
- MSG_WAITALL
- MSG_FIN
- MSG_SYN
- MSG_CONFIRM
- MSG_RST
- MSG_ERRQUEUE
- MSG_NOSIGNAL
- MSG_MORE
- MSG_CMSG_CLOEXEC
-
- ## send/recv-msg
- struct msghdr :
- void *msg_name # sockaddr
- socklen_t msg_namelen
-
- iovec *msg_iov # message data
- size_t msg_iovlen
-
- void *msg_control # aux data
- size_t msg_controllen
-
- int msg_flags # flags
-
- struct cmsghdr :
- size_t cmsg_len # length including this cmsghdr struct
-
- int cmsg_level # originating protocol (IPPROTO_* ???)
- int cmsg_type # protocol-specific type
-
- ## socket-level cmsghdr types
- enum :
- SCM_RIGHTS
- SCM_CREDENTIALS
-
- #- ucred
-
- # SO_LINGER parameters
- struct linger :
- int l_onoff
- int l_linger
-
-
- ## API
- int socket (int domain, int socktype, int protocol)
- int bind (int fd, sockaddr *addr, socklen_t len)
- int connect (int fd, sockaddr *addr, socklen_t len)
- int listen (int fd, int n)
- int accept (int fd, sockaddr *addr, socklen_t *len)
- int shutdown (int fd, int how)
-
- int getsockname (int fd, sockaddr *addr, socklen_t *len)
- int getpeername (int fd, sockaddr *addr, socklen_t *len)
-
- ssize_t send (int fd, void *buf, size_t n, int flags)
- ssize_t recv (int fd, void *buf, size_t n, int flags)
- ssize_t sendto (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t addr_len)
- ssize_t recvfrom (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t addr_len)
- ssize_t sendmsg (int fd, msghdr *msg, int flags)
- ssize_t recvmsg (int fd, msghdr *msg, int flags)
-
- int getsockopt (int fd, int level, int optname, void *optval, socklen_t optlen)
- int setsockopt (int fd, int level, int optname, void *optval, socklen_t optlen)
-
- enum :
- SHUT_RD
- SHUT_WR
- SHUT_RDWR
-
-cdef extern from "netinet/in.h" :
- ## socket protocol types
- enum :
- IPPROTO_IP
- IPPROTO_ICMP
- IPPROTO_IGMP
- IPPROTO_TCP
- IPPROTO_UDP
- IPPROTO_IPV6
- IPPROTO_ICMPV6
- IPPROTO_SCTP
- IPPROTO_RAW
-
-
- ## ports
- ctypedef uint16_t in_port_t
-
- ## AF_INET
- ctypedef uint32_t in_addr_t
- struct in_addr :
- in_addr_t s_addr
-
- # XXX: should these be in another cdef?
- in_addr_t INADDR_ANY
-
- ## AF_INET6
- struct in6_addr :
- # XXX: check POSIX...
- uint8_t s6_addr[16]
- uint16_t s6_addr16[8]
- uint32_t s6_addr32[4]
-
- # common in6_addr's
- in6_addr in6addr_any
- in6_addr in6addr_loopback
-
- ## constants
- enum :
- INET_ADDRSTRLEN
- INET6_ADDRSTRLEN
-
- ## sockaddrs
- struct sockaddr_in :
- sa_family_t sin_family
- in_port_t sin_port
- in_addr sin_addr
-
- struct sockaddr_in6 :
- sa_family_t sin6_family
- in_port_t sin6_port
- uint32_t sin6_flowinfo
- in6_addr sin6_addr
- uint32_t sin6_scope_id
-
- uint16_t htons(uint16_t)
- uint32_t htonl(uint32_t)
- uint16_t ntohs(uint16_t)
- uint32_t ntohl(uint32_t)
-
-cdef extern from "netdb.h" :
- ## getaddrinfo
- struct addrinfo :
- int ai_flags
- int ai_family
- int ai_socktype
- int ai_protocol
- int ai_addrlen
- sockaddr *ai_addr
- char *ai_canonname
- addrinfo *ai_next
-
- enum :
- AI_PASSIVE
- AI_CANONNAME
- AI_NUMERICHOST
- AI_V4MAPPED
- AI_ALL
- AI_ADDRCONFIG
- # AI_*IDN*
- AI_NUMERICSERV
-
- int c_getaddrinfo "getaddrinfo" (
- char *node, char *service,
- addrinfo *hints, addrinfo **res
- )
-
- void c_freeaddrinfo "freeaddrinfo" (addrinfo *res)
-
- ## getnameinfo
- int c_getnameinfo "getnameinfo" (
- sockaddr *sa, socklen_t salen,
- char *host, size_t hostlen,
- char *serv, size_t servlen,
- int flags
- )
-
- enum :
- NI_NOFQDN
- NI_NUMERICHOST
- NI_NAMEREQD
- NI_NUMERICSERV
- NI_DGRAM
-
- NI_MAXHOST
- NI_MAXSERV
-
- char* gai_strerror (int err)
-
-# python-friendly wrapper around inet_ntop
-cdef object inet_ntop (int af, void *sockaddr)
-cdef object inet_pton (int af, char *addr, void *sockaddr_out)
-
-# sockaddr, flags -> (host, service)
-cdef object getnameinfo (sockaddr *sa, socklen_t salen, int flags)
-
-## general errno-based errors
-#cdef class Errno (py.OSError) :
-# """
-# Some libc function returned an error code:
-#
-# func - the name of the function called
-# err - the system error code
-# strerror - human-readable error code -> message
-# """
-#
-# cdef readonly char *func
-# cdef readonly int err
-# cdef readonly object strerror
-#
-#cdef class GAIError (py.OSError) :
-# """
-# Some libc GAI function returnd an error code:
-#
-# func - the name of the function called
-# err - the GAI_* error code
-# strerror - human-readable error code -> message
-# """
-#
-# cdef readonly char *func
-# cdef readonly int err
-# cdef readonly object strerror
-#
--- a/libc.pyx Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-from libc cimport *
-
-from py cimport raise_errno
-
-cdef object inet_ntop (int af, void *sockaddr) :
- """
- Wrapper around inet_ntop, returning a PyString
- """
-
- # XXX: longest possible address...
- cdef char buf[INET6_ADDRSTRLEN]
-
- if c_inet_ntop(af, sockaddr, buf, sizeof(buf)) == NULL :
- raise_errno('inet_ntop')
-
- # autoconvert -> str
- return buf
-
-cdef object inet_pton (int af, char *addr, void *sockaddr_out) :
- cdef int ret
-
- ret = c_inet_pton(af, addr, sockaddr_out)
-
- if ret < 0 :
- raise_errno('inet_pton')
-
- elif ret == 0 :
- raise NameError("Invalid network address for specified address family: %r" % (addr, ))
-
-cdef object getnameinfo (sockaddr *sa, socklen_t salen, int flags) :
- cdef char hostbuf[NI_MAXHOST]
- cdef char servbuf[NI_MAXSERV]
- cdef int err
-
- err = c_getnameinfo(sa, salen, hostbuf, sizeof(hostbuf), servbuf, sizeof(servbuf), flags)
-
- if err :
- # XXX: raise a GAIError
- raise Exception(gai_strerror(err))
-# raise GAIError('getnameinfo', err)
-
- else :
- return hostbuf, servbuf
-
-#cdef class Errno (py.OSError) :
-# def __init__ (self, func) :
-# self.func = func
-# self.err = errno
-# self.strerror = strerror(errno)
-#
-# def __str__ (self) :
-# return "%s: %s" % (self.func, self.strerror)
-#
-#cdef class GAIError (py.OSError) :
-# def __init__ (self, func, err) :
-# self.func = func
-# self.err = err
-# self.strerror = gai_strerror(err)
-#
-# def __str__ (self) :
-# return "%s: %s" % (self.func, self.strerror)
-#
--- a/py.pxd Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-cimport libc
-
-cdef extern from "Python.h" :
- struct PyObject :
- pass
-
- ## string stuff
- int PyObject_AsCharBuffer (object obj, char **buf, libc.ssize_t *len) except -1
-
- ## except setting
- PyObject* PyErr_SetFromErrno (PyObject *type)
-
- PyObject *PyExc_OSError
-
-# raise OSError with errno
-# XXX: doesn't do anything with func
-cdef int raise_errno (char *func) except -1
-
--- a/py.pyx Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-cdef int raise_errno (char *func) except -1 :
- PyErr_SetFromErrno(PyExc_OSError)
-
- return -1
-
--- a/qmsk.net/sctp/constants.pyx Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-cimport sctp.sock as sctp
-
-SOL_SCTP = sctp.SOL_SCTP
-IPPROTO_SCTP = sctp.IPPROTO_SCTP
-
-SCTP_RTOINFO = sctp.SCTP_RTOINFO
-SCTP_ASSOCINFO = sctp.SCTP_ASSOCINFO
-SCTP_INITMSG = sctp.SCTP_INITMSG
-SCTP_NODELAY = sctp.SCTP_NODELAY
-SCTP_AUTOCLOSE = sctp.SCTP_AUTOCLOSE
-SCTP_SET_PEER_PRIMARY_ADDR = sctp.SCTP_SET_PEER_PRIMARY_ADDR
-SCTP_PRIMARY_ADDR = sctp.SCTP_PRIMARY_ADDR
-SCTP_ADAPTATION_LAYER = sctp.SCTP_ADAPTATION_LAYER
-SCTP_DISABLE_FRAGMENTS = sctp.SCTP_DISABLE_FRAGMENTS
-SCTP_PEER_ADDR_PARAMS = sctp.SCTP_PEER_ADDR_PARAMS
-SCTP_DEFAULT_SEND_PARAM = sctp.SCTP_DEFAULT_SEND_PARAM
-SCTP_EVENTS = sctp.SCTP_EVENTS
-SCTP_I_WANT_MAPPED_V4_ADDR = sctp.SCTP_I_WANT_MAPPED_V4_ADDR
-SCTP_MAXSEG = sctp.SCTP_MAXSEG
-SCTP_STATUS = sctp.SCTP_STATUS
-SCTP_GET_PEER_ADDR_INFO = sctp.SCTP_GET_PEER_ADDR_INFO
-SCTP_DELAYED_ACK_TIME = sctp.SCTP_DELAYED_ACK_TIME
-SCTP_CONTEXT = sctp.SCTP_CONTEXT
-SCTP_FRAGMENT_INTERLEAVE = sctp.SCTP_FRAGMENT_INTERLEAVE
-SCTP_PARTIAL_DELIVERY_POINT = sctp.SCTP_PARTIAL_DELIVERY_POINT
-SCTP_MAX_BURST = sctp.SCTP_MAX_BURST
-
-SCTP_ADDR_AVAILABLE = sctp.SCTP_ADDR_AVAILABLE
-SCTP_ADDR_UNREACHABLE = sctp.SCTP_ADDR_UNREACHABLE
-SCTP_ADDR_REMOVED = sctp.SCTP_ADDR_REMOVED
-SCTP_ADDR_ADDED = sctp.SCTP_ADDR_ADDED
-SCTP_ADDR_MADE_PRIM = sctp.SCTP_ADDR_MADE_PRIM
-SCTP_ADDR_CONFIRMED = sctp.SCTP_ADDR_CONFIRMED
-
-
-SCTP_DATA_UNSENT = sctp.SCTP_DATA_UNSENT
-SCTP_DATA_SENT = sctp.SCTP_DATA_SENT
-
-SCTP_PARTIAL_DELIVERY_ABORTED = sctp.SCTP_PARTIAL_DELIVERY_ABORTED
-
-# enum sctp_sn_type :
-SCTP_SN_TYPE_BASE = sctp.SCTP_SN_TYPE_BASE
-SCTP_ASSOC_CHANGE = sctp.SCTP_ASSOC_CHANGE
-SCTP_PEER_ADDR_CHANGE = sctp.SCTP_PEER_ADDR_CHANGE
-SCTP_SEND_FAILED = sctp.SCTP_SEND_FAILED
-SCTP_REMOTE_ERROR = sctp.SCTP_REMOTE_ERROR
-SCTP_SHUTDOWN_EVENT = sctp.SCTP_SHUTDOWN_EVENT
-SCTP_PARTIAL_DELIVERY_EVENT = sctp.SCTP_PARTIAL_DELIVERY_EVENT
-SCTP_ADAPTATION_INDICATION = sctp.SCTP_ADAPTATION_INDICATION
-
-# enum sctp_sn_error :
-SCTP_FAILED_THRESHOLD = sctp.SCTP_FAILED_THRESHOLD
-SCTP_RECEIVED_SACK = sctp.SCTP_RECEIVED_SACK
-SCTP_HEARTBEAT_SUCCESS = sctp.SCTP_HEARTBEAT_SUCCESS
-SCTP_RESPONSE_TO_USER_REQ = sctp.SCTP_RESPONSE_TO_USER_REQ
-SCTP_INTERNAL_ERROR = sctp.SCTP_INTERNAL_ERROR
-SCTP_SHUTDOWN_GUARD_EXPIRES = sctp.SCTP_SHUTDOWN_GUARD_EXPIRES
-SCTP_PEER_FAULTY = sctp.SCTP_PEER_FAULTY
-
-SCTP_BINDX_ADD_ADDR = sctp.SCTP_BINDX_ADD_ADDR
-SCTP_BINDX_REM_ADDR = sctp.SCTP_BINDX_REM_ADDR
-
--- a/qmsk.net/sctp/sock.pxd Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-cimport libc
-
-from libc cimport __u8, __u16, __u32, __s8, __s16, __s32
-
-# <netinet/sctp.h>
-# this defines the kernel SCTP -> userspace API extensions, such as structure types etc.
-cdef extern from "netinet/sctp.h" :
- ## types
- ctypedef __s32 sctp_assoc_t
-
- ## constants
- # sockapi
- enum :
- SOL_SCTP
- IPPROTO_SCTP
-
- # sockopts
- enum :
- SCTP_RTOINFO
- SCTP_ASSOCINFO
- SCTP_INITMSG
- SCTP_NODELAY
- SCTP_AUTOCLOSE
- SCTP_SET_PEER_PRIMARY_ADDR
- SCTP_PRIMARY_ADDR
- SCTP_ADAPTATION_LAYER
- SCTP_DISABLE_FRAGMENTS
- SCTP_PEER_ADDR_PARAMS
- SCTP_DEFAULT_SEND_PARAM
- SCTP_EVENTS
- SCTP_I_WANT_MAPPED_V4_ADDR
- SCTP_MAXSEG
- SCTP_STATUS
- SCTP_GET_PEER_ADDR_INFO
- SCTP_DELAYED_ACK_TIME
- SCTP_CONTEXT
- SCTP_FRAGMENT_INTERLEAVE
- SCTP_PARTIAL_DELIVERY_POINT
- SCTP_MAX_BURST
-
- ## send/recv-msg cmsghdr's
- struct sctp_initmsg :
- __u16 sinit_num_ostreams
- __u16 sinit_max_instreams
- __u16 sinit_max_attempts
- __u16 sinit_max_init_timeo
-
- struct sctp_sndrcvinfo :
- __u16 sinfo_stream
- __u16 sinfo_ssn
- __u16 sinfo_flags
- __u32 sinfo_ppid
- __u32 sinfo_context
- __u32 sinfo_timetolive
- __u32 sinfo_tsn
- __u32 sinfo_cumtsn
- sctp_assoc_t sinfo_assoc_id
-
- # sctp_sndrcvinfo.sinfo_flags values
- enum sctp_sinfo_flags :
- SCTP_UNORDERED # Send/receive message unordered
- SCTP_ADDR_OVER # Override the primary destination
- SCTP_ABORT # Send an ABORT message to the peer
- SCTP_EOF # Initiate graceful shutdown process
-
- ## notifications
- struct sctp_assoc_change :
- __u16 sac_type
- __u16 sac_flags
- __u32 sac_length
- __u16 sac_state
- __u16 sac_error
- __u16 sac_outbound_streams
- __u16 sac_inbound_streams
- sctp_assoc_t sac_assoc_id
- __u8 sac_info[0]
-
- # sctp_assoc_change.sac_state
- enum sctp_sac_state :
- SCTP_COMM_UP
- SCTP_COMM_LOST
- SCTP_RESTART
- SCTP_SHUTDOWN_COMP
- SCTP_CANT_STR_ASSOC
-
- struct sctp_paddr_change :
- __u16 spc_type
- __u16 spc_flags
- __u32 spc_length
- libc.sockaddr_storage spc_aaddr
- int spc_state
- int spc_error
- sctp_assoc_t spc_assoc_id
-
- enum sctp_spc_state :
- SCTP_ADDR_AVAILABLE
- SCTP_ADDR_UNREACHABLE
- SCTP_ADDR_REMOVED
- SCTP_ADDR_ADDED
- SCTP_ADDR_MADE_PRIM
- SCTP_ADDR_CONFIRMED
-
- struct sctp_remote_error :
- __u16 sre_type
- __u16 sre_flags
- __u32 sre_length
- __u16 sre_error
- sctp_assoc_t sre_assoc_id
- __u8 sre_data[0]
-
-
- struct sctp_send_failed :
- __u16 ssf_type
- __u16 ssf_flags
- __u32 ssf_length
- __u32 ssf_error
- sctp_sndrcvinfo ssf_info
- sctp_assoc_t ssf_assoc_id
- __u8 ssf_data[0]
-
- enum sctp_ssf_flags :
- SCTP_DATA_UNSENT
- SCTP_DATA_SENT
-
- struct sctp_shutdown_event :
- __u16 sse_type
- __u16 sse_flags
- __u32 sse_length
- sctp_assoc_t sse_assoc_id
-
- struct sctp_adaptation_event :
- __u16 sai_type
- __u16 sai_flags
- __u32 sai_length
- __u32 sai_adaptation_ind
- sctp_assoc_t sai_assoc_id
-
- struct sctp_pdapi_event :
- __u16 pdapi_type
- __u16 pdapi_flags
- __u32 pdapi_length
- __u32 pdapi_indication
- sctp_assoc_t pdapi_assoc_id
-
- enum :
- SCTP_PARTIAL_DELIVERY_ABORTED
-
- struct sctp_event_subscribe :
- __u8 sctp_data_io_event
- __u8 sctp_association_event
- __u8 sctp_address_event
- __u8 sctp_send_failure_event
- __u8 sctp_peer_error_event
- __u8 sctp_shutdown_event
- __u8 sctp_partial_delivery_event
- __u8 sctp_adaptation_layer_event
-
- struct sn_header :
- __u16 sn_type
- __u16 sn_flags
- __u32 sn_length
-
- union sctp_notification :
- sn_header sn_header
-
- sctp_assoc_change sn_assoc_change
- sctp_paddr_change sn_paddr_change
- sctp_remote_error sn_remote_error
- sctp_send_failed sn_send_failed
- sctp_shutdown_event sn_shutdown_event
- sctp_adaptation_event sn_adaptation_event
- sctp_pdapi_event sn_pdapi_event
-
- enum sctp_sn_type :
- SCTP_SN_TYPE_BASE
- SCTP_ASSOC_CHANGE
- SCTP_PEER_ADDR_CHANGE
- SCTP_SEND_FAILED
- SCTP_REMOTE_ERROR
- SCTP_SHUTDOWN_EVENT
- SCTP_PARTIAL_DELIVERY_EVENT
- SCTP_ADAPTATION_INDICATION
-
- enum sctp_sn_error :
- SCTP_FAILED_THRESHOLD
- SCTP_RECEIVED_SACK
- SCTP_HEARTBEAT_SUCCESS
- SCTP_RESPONSE_TO_USER_REQ
- SCTP_INTERNAL_ERROR
- SCTP_SHUTDOWN_GUARD_EXPIRES
- SCTP_PEER_FAULTY
-
- ctypedef sctp_sn_error sctp_sn_error_t
-
-
- ## sctp_bindx
- enum :
- SCTP_BINDX_ADD_ADDR
- SCTP_BINDX_REM_ADDR
-
- int c_sctp_bindx "sctp_bindx" (int sd, libc.sockaddr *addrs, int addrcnt, int flags)
-
- # XXX: missing return-sctp_assoc_t-id argument!
- int c_sctp_connectx "sctp_connectx" (int sd, libc.sockaddr *addrs, int addrcnt)
-
-
--- a/qmsk.net/sctp/sock.pyx Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-"""
- 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 sock.addr
-
-cdef size_t addrsoup_len (object addrs) except -1 :
- """
- Calculate the length of the addr_buf required to store the given addrsoup
- """
-
- cdef sock.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 sock.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')
-
--- a/qmsk.net/socket/addr.pxd Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-"""
- Socket addresses at various levels:
-
- sockaddr - specific network-level address for socket operations
- addrinfo - information on a specific sockaddr including its socket parameters
- endpoint - human-readable network address, corresponding to multiple sockaddr's
-"""
-
-cimport libc
-
-cdef class sockaddr :
- """
- A network-level socket address
-
- XXX: rename to 'address'
-
- >>> sockaddr().family
- 0
- >>> sockaddr().port
- Traceback (most recent call last):
- ...
- NotImplementedError
- >>> sockaddr().getnameinfo()
- Traceback (most recent call last):
- ...
- NotImplementedError
- """
-
- # address family
- # XXX: this should be a class constant! It's part of our type safety!
- cdef readonly libc.sa_family_t family
-
- cdef void _init_family (self, libc.sa_family_t family = ?)
-
- # get the sockaddr/socklen
- # 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
-
- # set the sockaddr, socklen must match
- cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1
-
-# build a sockaddr from the given sockaddr struct, based on sa_family
-cdef sockaddr build_sockaddr (libc.sockaddr *sa, size_t sa_len)
-
-cdef class addrinfo :
- """
- A socket-level endpoint address, which contains the full socket parameters and an bind/connect address
- """
-
-# cdef readonly int flags
- cdef readonly int family, socktype, protocol
- cdef readonly sockaddr addr
- cdef readonly object canonname
-
- cdef _init_addrinfo (self, libc.addrinfo *c_ai)
-
-# build and return a new addrinfo instance
-cdef addrinfo build_addrinfo (libc.addrinfo *c_ai)
-
-cdef class endpoint :
- """
- A network-level socket endpoint. This is the level that humans mostly work with, but the tricky bit is that
- an endpoint can map to more than one sockaddr...
-
- Hence, endpoints are stored as human-readable hostname/service strings, which are then translated to sockaddrs
- using getaddrinfo.
-
- >>> import socket
- >>> e = endpoint('127.0.0.1', 80)
- >>> str(e)
- 'hostname=127.0.0.1, service=80'
- >>> res = e.getaddrinfo(socket.AF_UNSPEC, socket.SOCK_STREAM)
- >>> len(res)
- 1
- >>> str(res[0])
- 'family=2, socktype=1, protocol=6, addr=127.0.0.1:80, canonname=None'
- >>> e = endpoint('2001::5', 80)
- >>> str(e)
- 'hostname=2001::5, service=80'
- >>> res = e.getaddrinfo(socket.AF_UNSPEC, socket.SOCK_STREAM)
- >>> len(res)
- 1
- >>> str(res[0])
- 'family=10, socktype=1, protocol=6, addr=[2001::5]:80, canonname=None'
-
- """
-
- # our defining attributes, set via __init__
- cdef object hostname, service
-
- cpdef getaddrinfo (self, int family, int socktype, int protocol = ?, int flags = ?)
-
--- a/qmsk.net/socket/addr.pyx Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-cimport libc
-
-from addr cimport *
-
-cdef class sockaddr :
- cdef void _init_family (self, libc.sa_family_t family=libc.AF_UNSPEC) :
- self.family = family
-
- # XXX:use size_t
- cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 :
- """
- Get the sockaddr pointer and sockaddr length for this address
- """
-
- 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
-
- cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 :
- """
- Set the sockaddr value for this address; sa_len must match!
- """
-
- raise NotImplementedError()
-
- def getnameinfo (self) :
- """
- Returns a (host, serv) tuple for this address à la getnameinfo
- """
-
- cdef libc.sockaddr *sa
- cdef libc.socklen_t sa_len
-
- # XXX: take as args?
- cdef int flags = libc.NI_NUMERICHOST | libc.NI_NUMERICSERV
-
- # get our abstract sockaddr
- self._get_sockaddr(&sa, &sa_len)
-
- # get nice text format
- return libc.getnameinfo(sa, sa_len, flags)
-
- property addr :
- """
- The ASCII literal network address
- """
-
- def __get__ (self) :
- """
- Default implmentation using getnameinfo()
- """
-
- addr, port = self.getnameinfo()
-
- return addr
-
- property port :
- """
- The integer port number
- """
-
- def __get__ (self) :
- """
- Default implementation using getnameinfo() and int()
- """
-
- addr, port = self.getnameinfo()
-
- return int(port)
-
-cdef class sockaddr_in (sockaddr) :
- """
- AF_INET struct sockaddr_in
-
- >>> sa = sockaddr_in("127.0.0.1", 80)
- >>> sa.addr
- '127.0.0.1'
- >>> sa.port
- 80
- >>> str(sa)
- '127.0.0.1:80'
- >>> str(sockaddr_in())
- '0.0.0.0:0'
- """
-
- # the struct sockaddr_in
- cdef libc.sockaddr_in sockaddr
-
- def __init__ (self, object addr=None, libc.in_port_t port=0) :
- """
- Construct using given literal IPv4 address and TCP/UDP port
-
- addr - IPv4 address, defaults to INADDR_ANY (0.0.0.0)
- port - TCP/UDP port, defaults to 0 (ephemeral)
- """
-
- # store our family
- # XXX: this should be a class attribute...
- self._init_family(libc.AF_INET)
-
- # constant af
- self.sockaddr.sin_family = self.family
-
- # set the sin_port
- self.sockaddr.sin_port = libc.htons(port)
-
- if addr :
- # set the sin_addr
- # this automatically converts the addr from str -> char *
- libc.inet_pton(self.family, addr, &self.sockaddr.sin_addr)
-
- else :
- # set as INADDR_ANY
- self.sockaddr.sin_addr.s_addr = libc.INADDR_ANY
-
- cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 :
- if sa_ptr :
- sa_ptr[0] = <libc.sockaddr *> &self.sockaddr
-
- if sa_len :
- sa_len[0] = sizeof(self.sockaddr)
-
- return 0
-
- cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 :
- assert sa_len == sizeof(self.sockaddr)
-
- libc.memcpy(&self.sockaddr, sa, sa_len)
-
- property port :
- """
- The integer port number
- """
-
- def __get__ (self) :
- return libc.ntohs(self.sockaddr.sin_port)
-
- def __str__ (self) :
- """
- Return the literal ASCII representation for this sockaddr as an '<addr>:<port> string
- """
-
- # format
- return "%s:%s" % self.getnameinfo()
-
-cdef class sockaddr_in6 (sockaddr) :
- """
- AF_INET6 struct sockaddr_in6
-
- >>> sa6 = sockaddr_in6("::1", 80)
- >>> sa6.addr
- '::1'
- >>> sa6.port
- 80
- >>> str(sa6)
- '[::1]:80'
- >>> str(sockaddr_in6())
- '[::]:0'
- """
-
- cdef libc.sockaddr_in6 sockaddr
-
- def __init__ (self, object addr=None, libc.in_port_t port=0) :
- """
- Construct using given literal IPv6 address and TCP/UDP port
-
- addr - IPv6 address, defaults to in6addr_any (::)
- port - TCP/UDP port, defaults to 0 (ephemeral)
- """
-
- # store our family
- # XXX: this should be a class attribute...
- self._init_family(libc.AF_INET6)
-
- # constant af
- self.sockaddr.sin6_family = self.family
-
- # set the sin_port
- self.sockaddr.sin6_port = libc.htons(port)
-
- if addr :
- # set the sin_addr
- # this automatically converts the addr from str -> char *
- libc.inet_pton(self.family, addr, &self.sockaddr.sin6_addr)
-
- else :
- # set as INADDR_ANY
- self.sockaddr.sin6_addr = libc.in6addr_any
-
- cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 :
- if sa_ptr :
- sa_ptr[0] = <libc.sockaddr *> &self.sockaddr
-
- if sa_len :
- sa_len[0] = sizeof(self.sockaddr)
-
- return 0
-
- cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 :
- assert sa_len == sizeof(self.sockaddr)
-
- libc.memcpy(&self.sockaddr, sa, sa_len)
-
- property port :
- """
- The integer port number
- """
-
- def __get__ (self) :
- return libc.ntohs(self.sockaddr.sin6_port)
-
-
- def __str__ (self) :
- """
- Return the literal ASCII representation for this sockaddr as a '[<addr>]:<port> string
- """
-
- # format
- return "[%s]:%s" % self.getnameinfo()
-
-# mapping of AF -> sockaddr, user-modifyable
-SOCKADDR_BY_FAMILY = {
- libc.AF_INET: sockaddr_in,
- libc.AF_INET6: sockaddr_in6,
-}
-
-# build a sockaddr from the given sockaddr struct, based on sa_family
-cdef sockaddr build_sockaddr (libc.sockaddr *sa, size_t sa_len) :
- # lookup correct class to use
- addr_type = SOCKADDR_BY_FAMILY[sa.sa_family]
-
- # construct with defaults
- cdef sockaddr addr = addr_type()
-
- # store
- addr._set_sockaddr(sa, sa_len)
-
- return addr
-
-cdef class addrinfo :
-
- cdef _init_addrinfo (self, libc.addrinfo *ai) :
- #ai.flags = c_ai.ai_flags
- self.family = ai.ai_family
- self.socktype = ai.ai_socktype
- self.protocol = ai.ai_protocol
- self.addr = build_sockaddr(ai.ai_addr, ai.ai_addrlen)
- self.canonname = ai.ai_canonname if ai.ai_canonname else None
-
- def __str__ (self) :
- return "family=%d, socktype=%d, protocol=%d, addr=%s, canonname=%s" % (self.family, self.socktype, self.protocol, self.addr, self.canonname)
-
-cdef addrinfo build_addrinfo (libc.addrinfo *c_ai) :
- cdef addrinfo ai = addrinfo()
-
- ai._init_addrinfo(c_ai)
-
- return ai
-
-cdef class endpoint :
-
- def __init__ (self, hostname=None, service=None) :
- """
- Construct with the given hostname/service, either of which may be None.
-
- A hostname of None implies all valid local addresses (with AI_PASSIVE), and a service of None implies an
- ephemeral port.
-
- hostname - the literal address or DNS hostname or anything else that GAI supports
- service - the numeric port or service name
- """
-
- self.hostname = str(hostname)
- self.service = str(service)
-
- cpdef getaddrinfo (self, int family, int socktype, int protocol = 0, int flags = libc.AI_PASSIVE) :
- """
- Look up our hostname/service using the given socket parameters, and return a sequence of addrinfo objects.
- """
-
- # XXX: Cython doesn't support proper compound value literals...
- cdef libc.addrinfo hints
-
- libc.memset(&hints, 0, sizeof(hints))
- hints.ai_flags = flags
- hints.ai_family = family
- hints.ai_socktype = socktype
- hints.ai_protocol = protocol
-
- cdef libc.addrinfo *res, *r
- cdef int err
- cdef object ret = []
-
- cdef char *hostname = NULL
- cdef char *service = NULL
-
- if self.hostname is not None :
- hostname = self.hostname
-
- if self.service is not None :
- service = self.service
-
- # operate!
- err = libc.c_getaddrinfo(hostname, service, &hints, &res)
-
- try :
- if err :
- # XXX: raise a GAIError
- raise Exception(libc.gai_strerror(err))
-
- # gather results
- r = res
-
- while r :
- ret.append(build_addrinfo(r))
-
- r = r.ai_next
-
- # ok
- return ret
-
- finally :
- libc.c_freeaddrinfo(res)
-
- def __str__ (self) :
- return "hostname=%s, service=%s" % (self.hostname, self.service)
-
--- a/qmsk.net/socket/sock.pxd Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-"""
- Sockect Object/API
-"""
-
-ctypedef int socket_t
-
-cdef class sock :
- """
- Represents a single OS-level socket
-
- >>> from socket import addr
- >>> s = sock()
- >>> s.send('foo')
- Traceback (most recent call last):
- ...
- OSError: [Errno 9] Bad file descriptor
- >>> s.socket()
- >>> s.bind(addr.sockaddr_in('127.0.0.1', 1337))
- >>> s.listen(1)
- >>> s.listen(0)
- >>> s.connect(addr.sockaddr_in('127.0.01.', 1338))
- x
- """
-
- cdef readonly socket_t fd
-
--- a/qmsk.net/socket/sock.pyx Sun Aug 16 18:29:55 2009 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-from sock.sock cimport *
-from sock.addr cimport sockaddr, build_sockaddr
-
-cimport libc, py
-
-from py cimport raise_errno
-
-# XXX: do some GIL-releasin'
-cdef class sock :
-
- def __init__ (self, int fd = -1) :
- """
- Construct this socket with the given fd, or -1 to mark it as fd-less
- """
-
- self.fd = fd
-
- def socket (self, int family = libc.AF_INET, int socktype = libc.SOCK_STREAM, int protocol = 0) :
- """
- Create a new socket endpoint with the given family/domain, socktype and optionally, specific protocol.
-
- family - one of AF_*
- socktype - one of SOCK_*
- protocol - one of IPPROTO_* or zero to select default
- """
-
- if self.fd >= 0 :
- raise Exception("Socket fd already exists")
-
- # socket()
- self.fd = libc.socket(family, socktype, protocol)
-
- # trap
- if self.fd < 0 :
- raise_errno('socket')
-
- def bind (self, sockaddr addr) :
- """
- Bind this socket to the given local socket address. The given sockaddr should be of the same or a
- compatible address family.
-
- addr - the local address to bind to. The port may be zero to let the system choose an unused
- ephemeral port.
- """
-
- cdef libc.sockaddr *sa_ptr
- cdef libc.socklen_t sa_len
-
- # get the address
- addr._get_sockaddr(&sa_ptr, &sa_len)
-
- # bind()
- if libc.bind(self.fd, sa_ptr, sa_len) :
- raise_errno('bind')
-
- def listen (self, int backlog) :
- """
- Listen for connections, marking this socket as a passive socket, which can accept incoming connection
- requests using sock.accept().
-
- It is customary to call .bind() before .listen().
-
- backlog - maximum number of pending connections (those not yet .accept()'d).
- """
-
- # listen()
- if libc.listen(self.fd, backlog) :
- raise_errno('listen')
-
- def connect (self, sockaddr addr) :
- """
- Initiate a connection, connecting this socket to the remote endpoint specified by `addr`. The given sockaddr
- should be of the same or a compatible address family.
-
- If the socket is in non-blocking mode, this will presumeably return errno.EINPROGRESS.
-
- If the socket has not yet been bound (using .bind()), the system will pick an appropriate local address and
- ephemeral port.
-
- addr - the remote address to connect to.
- """
-
- cdef libc.sockaddr *sa_ptr
- cdef libc.socklen_t sa_len
-
- # get the address
- addr._get_sockaddr(&sa_ptr, &sa_len)
-
- # connect()
- if libc.connect(self.fd, sa_ptr, sa_len) :
- raise_errno('connect')
-
- def accept (self) :
- """
- Accept a connection, dequeueing the first pending connection and returning a new sock object for it. This
- socket must be a connection-based socket (SOCK_STREAM/SOCK_SEQPACKET) and in the passive listening mode
- (.listen()).
-
- This returns a (sock, sockaddr) tuple:
- sock - the newly created sock, corresponding to the incoming connection
- sockaddr - the remote address of the incoming connection
- """
-
- # prep the sockaddr that we will return
- cdef libc.sockaddr_storage ss
- cdef libc.socklen_t ss_len = sizeof(ss)
-
- cdef socket_t sock_fd
-
- # accept()
- sock_fd = libc.accept(self.fd, <libc.sockaddr *> &ss, &ss_len)
-
- if sock_fd < 0 :
- raise_errno('accept')
-
- # prep the new socket
- sock_obj = sock(sock_fd)
-
- # prep the new addr
- sock_addr = build_sockaddr(<libc.sockaddr *> &ss, ss_len)
-
- return sock_obj, sock_addr
-
- def send (self, object buf, int flags = 0) :
- """
- Transmit a message to the connected remote endpoint.
-
- buf - the data to send
- flags - MSG_* flags to send with
-
- Returns the number of bytes sent, which may be less than the length of buf.
- """
-
- cdef char *buf_ptr
- cdef libc.ssize_t buf_len, ret
-
- # get buffer
- # XXX: test that except works right
- py.PyObject_AsCharBuffer(buf, &buf_ptr, &buf_len)
-
- # send()
- ret = libc.send(self.fd, <void *> buf_ptr, buf_len, flags)
-
- if ret < 0 :
- raise_errno('send')
-
- else :
- return ret
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/libc.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,315 @@
+"""
+ Libc stuff
+"""
+
+cdef extern from "stdint.h" :
+ # yes, these are "wrong"
+ ctypedef unsigned char uint8_t
+ ctypedef unsigned short uint16_t
+ ctypedef unsigned int uint32_t
+
+ ctypedef signed char int8_t
+ ctypedef signed short int16_t
+ ctypedef signed int int32_t
+
+cdef extern from "sys/types.h" :
+ # potentially wrong...
+ ctypedef signed long ssize_t
+
+# <linux/types.h>
+cdef extern from "linux/types.h" :
+ ctypedef uint8_t __u8
+ ctypedef uint16_t __u16
+ ctypedef uint32_t __u32
+
+ ctypedef int8_t __s8
+ ctypedef int16_t __s16
+ ctypedef int32_t __s32
+
+cdef extern from "errno.h" :
+ int errno
+
+cdef extern from "string.h" :
+ void* memcpy (void *dest, void *src, size_t n)
+ void* memset (void *s, int c, size_t n)
+
+ char* strerror (int errno)
+
+cdef extern from "alloca.h" :
+ void* alloca (size_t size)
+
+cdef extern from "sys/uio.h" :
+ struct iovec :
+ void *iov_base
+ size_t iov_len
+
+cdef extern from "arpa/inet.h" :
+ # XXX: correct?!
+ ctypedef uint32_t socklen_t
+
+ char* c_inet_ntop "inet_ntop" (int af, void *sockaddr, char *buf, socklen_t len)
+ int c_inet_pton "inet_pton" (int af, char *src, void *dst)
+
+# <sys/socket.h>
+cdef extern from "sys/socket.h" :
+ # socket types
+ enum :
+ SOCK_STREAM
+ SOCK_DGRAM
+ SOCK_RAW
+ SOCK_RDM
+ SOCK_SEQPACKET
+ SOCK_PACKET
+
+ # packet/address families
+ enum :
+ PF_UNSPEC
+ PF_LOCAL
+ PF_UNIX # same as PF_LOCAL
+ PF_FILE # same as PF_LOCAL
+ PF_INET
+ PF_INET6
+ PF_NETLINK
+ PF_ROUTE # same as PF_NETLINK
+
+
+ # aliases for PF_*
+ enum :
+ AF_UNSPEC
+ AF_LOCAL
+ AF_UNIX
+ AF_FILE
+ AF_INET
+ AF_INET6
+ AF_NETLINK
+ AF_ROUTE
+
+ # base sockaddr stuff
+ ctypedef uint16_t sa_family_t
+
+ struct sockaddr :
+ sa_family_t sa_family
+
+ struct sockaddr_storage :
+ sa_family_t ss_family
+
+ # flag values
+ enum :
+ MSG_OOB
+ MSG_PEEK
+ MSG_DONTROUTE
+ MSG_CTRUNC
+ MSG_PROXY
+ MSG_TRUNC
+ MSG_DONTWAIT
+ MSG_EOR
+ MSG_WAITALL
+ MSG_FIN
+ MSG_SYN
+ MSG_CONFIRM
+ MSG_RST
+ MSG_ERRQUEUE
+ MSG_NOSIGNAL
+ MSG_MORE
+ MSG_CMSG_CLOEXEC
+
+ ## send/recv-msg
+ struct msghdr :
+ void *msg_name # sockaddr
+ socklen_t msg_namelen
+
+ iovec *msg_iov # message data
+ size_t msg_iovlen
+
+ void *msg_control # aux data
+ size_t msg_controllen
+
+ int msg_flags # flags
+
+ struct cmsghdr :
+ size_t cmsg_len # length including this cmsghdr struct
+
+ int cmsg_level # originating protocol (IPPROTO_* ???)
+ int cmsg_type # protocol-specific type
+
+ ## socket-level cmsghdr types
+ enum :
+ SCM_RIGHTS
+ SCM_CREDENTIALS
+
+ #- ucred
+
+ # SO_LINGER parameters
+ struct linger :
+ int l_onoff
+ int l_linger
+
+
+ ## API
+ int socket (int domain, int socktype, int protocol)
+ int bind (int fd, sockaddr *addr, socklen_t len)
+ int connect (int fd, sockaddr *addr, socklen_t len)
+ int listen (int fd, int n)
+ int accept (int fd, sockaddr *addr, socklen_t *len)
+ int shutdown (int fd, int how)
+
+ int getsockname (int fd, sockaddr *addr, socklen_t *len)
+ int getpeername (int fd, sockaddr *addr, socklen_t *len)
+
+ ssize_t send (int fd, void *buf, size_t n, int flags)
+ ssize_t recv (int fd, void *buf, size_t n, int flags)
+ ssize_t sendto (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t addr_len)
+ ssize_t recvfrom (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t addr_len)
+ ssize_t sendmsg (int fd, msghdr *msg, int flags)
+ ssize_t recvmsg (int fd, msghdr *msg, int flags)
+
+ int getsockopt (int fd, int level, int optname, void *optval, socklen_t optlen)
+ int setsockopt (int fd, int level, int optname, void *optval, socklen_t optlen)
+
+ enum :
+ SHUT_RD
+ SHUT_WR
+ SHUT_RDWR
+
+cdef extern from "netinet/in.h" :
+ ## socket protocol types
+ enum :
+ IPPROTO_IP
+ IPPROTO_ICMP
+ IPPROTO_IGMP
+ IPPROTO_TCP
+ IPPROTO_UDP
+ IPPROTO_IPV6
+ IPPROTO_ICMPV6
+ IPPROTO_SCTP
+ IPPROTO_RAW
+
+
+ ## ports
+ ctypedef uint16_t in_port_t
+
+ ## AF_INET
+ ctypedef uint32_t in_addr_t
+ struct in_addr :
+ in_addr_t s_addr
+
+ # XXX: should these be in another cdef?
+ in_addr_t INADDR_ANY
+
+ ## AF_INET6
+ struct in6_addr :
+ # XXX: check POSIX...
+ uint8_t s6_addr[16]
+ uint16_t s6_addr16[8]
+ uint32_t s6_addr32[4]
+
+ # common in6_addr's
+ in6_addr in6addr_any
+ in6_addr in6addr_loopback
+
+ ## constants
+ enum :
+ INET_ADDRSTRLEN
+ INET6_ADDRSTRLEN
+
+ ## sockaddrs
+ struct sockaddr_in :
+ sa_family_t sin_family
+ in_port_t sin_port
+ in_addr sin_addr
+
+ struct sockaddr_in6 :
+ sa_family_t sin6_family
+ in_port_t sin6_port
+ uint32_t sin6_flowinfo
+ in6_addr sin6_addr
+ uint32_t sin6_scope_id
+
+ uint16_t htons(uint16_t)
+ uint32_t htonl(uint32_t)
+ uint16_t ntohs(uint16_t)
+ uint32_t ntohl(uint32_t)
+
+cdef extern from "netdb.h" :
+ ## getaddrinfo
+ struct addrinfo :
+ int ai_flags
+ int ai_family
+ int ai_socktype
+ int ai_protocol
+ int ai_addrlen
+ sockaddr *ai_addr
+ char *ai_canonname
+ addrinfo *ai_next
+
+ enum :
+ AI_PASSIVE
+ AI_CANONNAME
+ AI_NUMERICHOST
+ AI_V4MAPPED
+ AI_ALL
+ AI_ADDRCONFIG
+ # AI_*IDN*
+ AI_NUMERICSERV
+
+ int c_getaddrinfo "getaddrinfo" (
+ char *node, char *service,
+ addrinfo *hints, addrinfo **res
+ )
+
+ void c_freeaddrinfo "freeaddrinfo" (addrinfo *res)
+
+ ## getnameinfo
+ int c_getnameinfo "getnameinfo" (
+ sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags
+ )
+
+ enum :
+ NI_NOFQDN
+ NI_NUMERICHOST
+ NI_NAMEREQD
+ NI_NUMERICSERV
+ NI_DGRAM
+
+ NI_MAXHOST
+ NI_MAXSERV
+
+ char* gai_strerror (int err)
+
+# python-friendly wrapper around inet_ntop
+cdef object inet_ntop (int af, void *sockaddr)
+cdef object inet_pton (int af, char *addr, void *sockaddr_out)
+
+# sockaddr, flags -> (host, service)
+cdef object getnameinfo (sockaddr *sa, socklen_t salen, int flags)
+
+## general errno-based errors
+#cdef class Errno (py.OSError) :
+# """
+# Some libc function returned an error code:
+#
+# func - the name of the function called
+# err - the system error code
+# strerror - human-readable error code -> message
+# """
+#
+# cdef readonly char *func
+# cdef readonly int err
+# cdef readonly object strerror
+#
+#cdef class GAIError (py.OSError) :
+# """
+# Some libc GAI function returnd an error code:
+#
+# func - the name of the function called
+# err - the GAI_* error code
+# strerror - human-readable error code -> message
+# """
+#
+# cdef readonly char *func
+# cdef readonly int err
+# cdef readonly object strerror
+#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/libc.pyx Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,61 @@
+from libc cimport *
+from py cimport raise_errno
+
+cdef object inet_ntop (int af, void *sockaddr) :
+ """
+ Wrapper around inet_ntop, returning a PyString
+ """
+
+ # XXX: longest possible address...
+ cdef char buf[INET6_ADDRSTRLEN]
+
+ if c_inet_ntop(af, sockaddr, buf, sizeof(buf)) == NULL :
+ raise_errno('inet_ntop')
+
+ # autoconvert -> str
+ return buf
+
+cdef object inet_pton (int af, char *addr, void *sockaddr_out) :
+ cdef int ret
+
+ ret = c_inet_pton(af, addr, sockaddr_out)
+
+ if ret < 0 :
+ raise_errno('inet_pton')
+
+ elif ret == 0 :
+ raise NameError("Invalid network address for specified address family: %r" % (addr, ))
+
+cdef object getnameinfo (sockaddr *sa, socklen_t salen, int flags) :
+ cdef char hostbuf[NI_MAXHOST]
+ cdef char servbuf[NI_MAXSERV]
+ cdef int err
+
+ err = c_getnameinfo(sa, salen, hostbuf, sizeof(hostbuf), servbuf, sizeof(servbuf), flags)
+
+ if err :
+ # XXX: raise a GAIError
+ raise Exception(gai_strerror(err))
+# raise GAIError('getnameinfo', err)
+
+ else :
+ return hostbuf, servbuf
+
+#cdef class Errno (py.OSError) :
+# def __init__ (self, func) :
+# self.func = func
+# self.err = errno
+# self.strerror = strerror(errno)
+#
+# def __str__ (self) :
+# return "%s: %s" % (self.func, self.strerror)
+#
+#cdef class GAIError (py.OSError) :
+# def __init__ (self, func, err) :
+# self.func = func
+# self.err = err
+# self.strerror = gai_strerror(err)
+#
+# def __str__ (self) :
+# return "%s: %s" % (self.func, self.strerror)
+#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/py.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,18 @@
+cimport libc
+
+cdef extern from "Python.h" :
+ struct PyObject :
+ pass
+
+ ## string stuff
+ int PyObject_AsCharBuffer (object obj, char **buf, libc.ssize_t *len) except -1
+
+ ## except setting
+ PyObject* PyErr_SetFromErrno (PyObject *type)
+
+ PyObject *PyExc_OSError
+
+# raise OSError with errno
+# XXX: doesn't do anything with func
+cdef int raise_errno (char *func) except -1
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/py.pyx Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,7 @@
+from py cimport *
+
+cdef int raise_errno (char *func) except -1 :
+ PyErr_SetFromErrno(PyExc_OSError)
+
+ return -1
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/sctp/constants.pyx Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,62 @@
+cimport sctp.sock as sctp
+
+SOL_SCTP = sctp.SOL_SCTP
+IPPROTO_SCTP = sctp.IPPROTO_SCTP
+
+SCTP_RTOINFO = sctp.SCTP_RTOINFO
+SCTP_ASSOCINFO = sctp.SCTP_ASSOCINFO
+SCTP_INITMSG = sctp.SCTP_INITMSG
+SCTP_NODELAY = sctp.SCTP_NODELAY
+SCTP_AUTOCLOSE = sctp.SCTP_AUTOCLOSE
+SCTP_SET_PEER_PRIMARY_ADDR = sctp.SCTP_SET_PEER_PRIMARY_ADDR
+SCTP_PRIMARY_ADDR = sctp.SCTP_PRIMARY_ADDR
+SCTP_ADAPTATION_LAYER = sctp.SCTP_ADAPTATION_LAYER
+SCTP_DISABLE_FRAGMENTS = sctp.SCTP_DISABLE_FRAGMENTS
+SCTP_PEER_ADDR_PARAMS = sctp.SCTP_PEER_ADDR_PARAMS
+SCTP_DEFAULT_SEND_PARAM = sctp.SCTP_DEFAULT_SEND_PARAM
+SCTP_EVENTS = sctp.SCTP_EVENTS
+SCTP_I_WANT_MAPPED_V4_ADDR = sctp.SCTP_I_WANT_MAPPED_V4_ADDR
+SCTP_MAXSEG = sctp.SCTP_MAXSEG
+SCTP_STATUS = sctp.SCTP_STATUS
+SCTP_GET_PEER_ADDR_INFO = sctp.SCTP_GET_PEER_ADDR_INFO
+SCTP_DELAYED_ACK_TIME = sctp.SCTP_DELAYED_ACK_TIME
+SCTP_CONTEXT = sctp.SCTP_CONTEXT
+SCTP_FRAGMENT_INTERLEAVE = sctp.SCTP_FRAGMENT_INTERLEAVE
+SCTP_PARTIAL_DELIVERY_POINT = sctp.SCTP_PARTIAL_DELIVERY_POINT
+SCTP_MAX_BURST = sctp.SCTP_MAX_BURST
+
+SCTP_ADDR_AVAILABLE = sctp.SCTP_ADDR_AVAILABLE
+SCTP_ADDR_UNREACHABLE = sctp.SCTP_ADDR_UNREACHABLE
+SCTP_ADDR_REMOVED = sctp.SCTP_ADDR_REMOVED
+SCTP_ADDR_ADDED = sctp.SCTP_ADDR_ADDED
+SCTP_ADDR_MADE_PRIM = sctp.SCTP_ADDR_MADE_PRIM
+SCTP_ADDR_CONFIRMED = sctp.SCTP_ADDR_CONFIRMED
+
+
+SCTP_DATA_UNSENT = sctp.SCTP_DATA_UNSENT
+SCTP_DATA_SENT = sctp.SCTP_DATA_SENT
+
+SCTP_PARTIAL_DELIVERY_ABORTED = sctp.SCTP_PARTIAL_DELIVERY_ABORTED
+
+# enum sctp_sn_type :
+SCTP_SN_TYPE_BASE = sctp.SCTP_SN_TYPE_BASE
+SCTP_ASSOC_CHANGE = sctp.SCTP_ASSOC_CHANGE
+SCTP_PEER_ADDR_CHANGE = sctp.SCTP_PEER_ADDR_CHANGE
+SCTP_SEND_FAILED = sctp.SCTP_SEND_FAILED
+SCTP_REMOTE_ERROR = sctp.SCTP_REMOTE_ERROR
+SCTP_SHUTDOWN_EVENT = sctp.SCTP_SHUTDOWN_EVENT
+SCTP_PARTIAL_DELIVERY_EVENT = sctp.SCTP_PARTIAL_DELIVERY_EVENT
+SCTP_ADAPTATION_INDICATION = sctp.SCTP_ADAPTATION_INDICATION
+
+# enum sctp_sn_error :
+SCTP_FAILED_THRESHOLD = sctp.SCTP_FAILED_THRESHOLD
+SCTP_RECEIVED_SACK = sctp.SCTP_RECEIVED_SACK
+SCTP_HEARTBEAT_SUCCESS = sctp.SCTP_HEARTBEAT_SUCCESS
+SCTP_RESPONSE_TO_USER_REQ = sctp.SCTP_RESPONSE_TO_USER_REQ
+SCTP_INTERNAL_ERROR = sctp.SCTP_INTERNAL_ERROR
+SCTP_SHUTDOWN_GUARD_EXPIRES = sctp.SCTP_SHUTDOWN_GUARD_EXPIRES
+SCTP_PEER_FAULTY = sctp.SCTP_PEER_FAULTY
+
+SCTP_BINDX_ADD_ADDR = sctp.SCTP_BINDX_ADD_ADDR
+SCTP_BINDX_REM_ADDR = sctp.SCTP_BINDX_REM_ADDR
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/sctp/sock.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,206 @@
+cimport libc
+
+from libc cimport __u8, __u16, __u32, __s8, __s16, __s32
+
+# <netinet/sctp.h>
+# this defines the kernel SCTP -> userspace API extensions, such as structure types etc.
+cdef extern from "netinet/sctp.h" :
+ ## types
+ ctypedef __s32 sctp_assoc_t
+
+ ## constants
+ # sockapi
+ enum :
+ SOL_SCTP
+ IPPROTO_SCTP
+
+ # sockopts
+ enum :
+ SCTP_RTOINFO
+ SCTP_ASSOCINFO
+ SCTP_INITMSG
+ SCTP_NODELAY
+ SCTP_AUTOCLOSE
+ SCTP_SET_PEER_PRIMARY_ADDR
+ SCTP_PRIMARY_ADDR
+ SCTP_ADAPTATION_LAYER
+ SCTP_DISABLE_FRAGMENTS
+ SCTP_PEER_ADDR_PARAMS
+ SCTP_DEFAULT_SEND_PARAM
+ SCTP_EVENTS
+ SCTP_I_WANT_MAPPED_V4_ADDR
+ SCTP_MAXSEG
+ SCTP_STATUS
+ SCTP_GET_PEER_ADDR_INFO
+ SCTP_DELAYED_ACK_TIME
+ SCTP_CONTEXT
+ SCTP_FRAGMENT_INTERLEAVE
+ SCTP_PARTIAL_DELIVERY_POINT
+ SCTP_MAX_BURST
+
+ ## send/recv-msg cmsghdr's
+ struct sctp_initmsg :
+ __u16 sinit_num_ostreams
+ __u16 sinit_max_instreams
+ __u16 sinit_max_attempts
+ __u16 sinit_max_init_timeo
+
+ struct sctp_sndrcvinfo :
+ __u16 sinfo_stream
+ __u16 sinfo_ssn
+ __u16 sinfo_flags
+ __u32 sinfo_ppid
+ __u32 sinfo_context
+ __u32 sinfo_timetolive
+ __u32 sinfo_tsn
+ __u32 sinfo_cumtsn
+ sctp_assoc_t sinfo_assoc_id
+
+ # sctp_sndrcvinfo.sinfo_flags values
+ enum sctp_sinfo_flags :
+ SCTP_UNORDERED # Send/receive message unordered
+ SCTP_ADDR_OVER # Override the primary destination
+ SCTP_ABORT # Send an ABORT message to the peer
+ SCTP_EOF # Initiate graceful shutdown process
+
+ ## notifications
+ struct sctp_assoc_change :
+ __u16 sac_type
+ __u16 sac_flags
+ __u32 sac_length
+ __u16 sac_state
+ __u16 sac_error
+ __u16 sac_outbound_streams
+ __u16 sac_inbound_streams
+ sctp_assoc_t sac_assoc_id
+ __u8 sac_info[0]
+
+ # sctp_assoc_change.sac_state
+ enum sctp_sac_state :
+ SCTP_COMM_UP
+ SCTP_COMM_LOST
+ SCTP_RESTART
+ SCTP_SHUTDOWN_COMP
+ SCTP_CANT_STR_ASSOC
+
+ struct sctp_paddr_change :
+ __u16 spc_type
+ __u16 spc_flags
+ __u32 spc_length
+ libc.sockaddr_storage spc_aaddr
+ int spc_state
+ int spc_error
+ sctp_assoc_t spc_assoc_id
+
+ enum sctp_spc_state :
+ SCTP_ADDR_AVAILABLE
+ SCTP_ADDR_UNREACHABLE
+ SCTP_ADDR_REMOVED
+ SCTP_ADDR_ADDED
+ SCTP_ADDR_MADE_PRIM
+ SCTP_ADDR_CONFIRMED
+
+ struct sctp_remote_error :
+ __u16 sre_type
+ __u16 sre_flags
+ __u32 sre_length
+ __u16 sre_error
+ sctp_assoc_t sre_assoc_id
+ __u8 sre_data[0]
+
+
+ struct sctp_send_failed :
+ __u16 ssf_type
+ __u16 ssf_flags
+ __u32 ssf_length
+ __u32 ssf_error
+ sctp_sndrcvinfo ssf_info
+ sctp_assoc_t ssf_assoc_id
+ __u8 ssf_data[0]
+
+ enum sctp_ssf_flags :
+ SCTP_DATA_UNSENT
+ SCTP_DATA_SENT
+
+ struct sctp_shutdown_event :
+ __u16 sse_type
+ __u16 sse_flags
+ __u32 sse_length
+ sctp_assoc_t sse_assoc_id
+
+ struct sctp_adaptation_event :
+ __u16 sai_type
+ __u16 sai_flags
+ __u32 sai_length
+ __u32 sai_adaptation_ind
+ sctp_assoc_t sai_assoc_id
+
+ struct sctp_pdapi_event :
+ __u16 pdapi_type
+ __u16 pdapi_flags
+ __u32 pdapi_length
+ __u32 pdapi_indication
+ sctp_assoc_t pdapi_assoc_id
+
+ enum :
+ SCTP_PARTIAL_DELIVERY_ABORTED
+
+ struct sctp_event_subscribe :
+ __u8 sctp_data_io_event
+ __u8 sctp_association_event
+ __u8 sctp_address_event
+ __u8 sctp_send_failure_event
+ __u8 sctp_peer_error_event
+ __u8 sctp_shutdown_event
+ __u8 sctp_partial_delivery_event
+ __u8 sctp_adaptation_layer_event
+
+ struct sn_header :
+ __u16 sn_type
+ __u16 sn_flags
+ __u32 sn_length
+
+ union sctp_notification :
+ sn_header sn_header
+
+ sctp_assoc_change sn_assoc_change
+ sctp_paddr_change sn_paddr_change
+ sctp_remote_error sn_remote_error
+ sctp_send_failed sn_send_failed
+ sctp_shutdown_event sn_shutdown_event
+ sctp_adaptation_event sn_adaptation_event
+ sctp_pdapi_event sn_pdapi_event
+
+ enum sctp_sn_type :
+ SCTP_SN_TYPE_BASE
+ SCTP_ASSOC_CHANGE
+ SCTP_PEER_ADDR_CHANGE
+ SCTP_SEND_FAILED
+ SCTP_REMOTE_ERROR
+ SCTP_SHUTDOWN_EVENT
+ SCTP_PARTIAL_DELIVERY_EVENT
+ SCTP_ADAPTATION_INDICATION
+
+ enum sctp_sn_error :
+ SCTP_FAILED_THRESHOLD
+ SCTP_RECEIVED_SACK
+ SCTP_HEARTBEAT_SUCCESS
+ SCTP_RESPONSE_TO_USER_REQ
+ SCTP_INTERNAL_ERROR
+ SCTP_SHUTDOWN_GUARD_EXPIRES
+ SCTP_PEER_FAULTY
+
+ ctypedef sctp_sn_error sctp_sn_error_t
+
+
+ ## sctp_bindx
+ enum :
+ SCTP_BINDX_ADD_ADDR
+ SCTP_BINDX_REM_ADDR
+
+ int c_sctp_bindx "sctp_bindx" (int sd, libc.sockaddr *addrs, int addrcnt, int flags)
+
+ # XXX: missing return-sctp_assoc_t-id argument!
+ int c_sctp_connectx "sctp_connectx" (int sd, libc.sockaddr *addrs, int addrcnt)
+
+
--- /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')
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/addr.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,95 @@
+"""
+ Socket addresses at various levels:
+
+ sockaddr - specific network-level address for socket operations
+ addrinfo - information on a specific sockaddr including its socket parameters
+ endpoint - human-readable network address, corresponding to multiple sockaddr's
+"""
+
+cimport libc
+
+cdef class sockaddr :
+ """
+ A network-level socket address
+
+ XXX: rename to 'address'
+
+ >>> sockaddr().family
+ 0
+ >>> sockaddr().port
+ Traceback (most recent call last):
+ ...
+ NotImplementedError
+ >>> sockaddr().getnameinfo()
+ Traceback (most recent call last):
+ ...
+ NotImplementedError
+ """
+
+ # address family
+ # XXX: this should be a class constant! It's part of our type safety!
+ cdef readonly libc.sa_family_t family
+
+ cdef void _init_family (self, libc.sa_family_t family = ?)
+
+ # get the sockaddr/socklen
+ # 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
+
+ # set the sockaddr, socklen must match
+ cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1
+
+# build a sockaddr from the given sockaddr struct, based on sa_family
+cdef sockaddr build_sockaddr (libc.sockaddr *sa, size_t sa_len)
+
+cdef class addrinfo :
+ """
+ A socket-level endpoint address, which contains the full socket parameters and an bind/connect address
+ """
+
+# cdef readonly int flags
+ cdef readonly int family, socktype, protocol
+ cdef readonly sockaddr addr
+ cdef readonly object canonname
+
+ cdef _init_addrinfo (self, libc.addrinfo *c_ai)
+
+# build and return a new addrinfo instance
+cdef addrinfo build_addrinfo (libc.addrinfo *c_ai)
+
+cdef class endpoint :
+ """
+ A network-level socket endpoint. This is the level that humans mostly work with, but the tricky bit is that
+ an endpoint can map to more than one sockaddr...
+
+ Hence, endpoints are stored as human-readable hostname/service strings, which are then translated to sockaddrs
+ using getaddrinfo.
+
+ >>> import socket
+ >>> e = endpoint('127.0.0.1', 80)
+ >>> str(e)
+ 'hostname=127.0.0.1, service=80'
+ >>> res = e.getaddrinfo(socket.AF_UNSPEC, socket.SOCK_STREAM)
+ >>> len(res)
+ 1
+ >>> str(res[0])
+ 'family=2, socktype=1, protocol=6, addr=127.0.0.1:80, canonname=None'
+ >>> e = endpoint('2001::5', 80)
+ >>> str(e)
+ 'hostname=2001::5, service=80'
+ >>> res = e.getaddrinfo(socket.AF_UNSPEC, socket.SOCK_STREAM)
+ >>> len(res)
+ 1
+ >>> str(res[0])
+ 'family=10, socktype=1, protocol=6, addr=[2001::5]:80, canonname=None'
+
+ """
+
+ # our defining attributes, set via __init__
+ cdef object hostname, service
+
+ cpdef getaddrinfo (self, int family, int socktype, int protocol = ?, int flags = ?)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/addr.pyx Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,349 @@
+cimport libc
+
+from addr cimport *
+
+cdef class sockaddr :
+ cdef void _init_family (self, libc.sa_family_t family=libc.AF_UNSPEC) :
+ self.family = family
+
+ # XXX:use size_t
+ cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 :
+ """
+ Get the sockaddr pointer and sockaddr length for this address
+ """
+
+ 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
+
+ cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 :
+ """
+ Set the sockaddr value for this address; sa_len must match!
+ """
+
+ raise NotImplementedError()
+
+ def getnameinfo (self) :
+ """
+ Returns a (host, serv) tuple for this address à la getnameinfo
+ """
+
+ cdef libc.sockaddr *sa
+ cdef libc.socklen_t sa_len
+
+ # XXX: take as args?
+ cdef int flags = libc.NI_NUMERICHOST | libc.NI_NUMERICSERV
+
+ # get our abstract sockaddr
+ self._get_sockaddr(&sa, &sa_len)
+
+ # get nice text format
+ return libc.getnameinfo(sa, sa_len, flags)
+
+ property addr :
+ """
+ The ASCII literal network address
+ """
+
+ def __get__ (self) :
+ """
+ Default implmentation using getnameinfo()
+ """
+
+ addr, port = self.getnameinfo()
+
+ return addr
+
+ property port :
+ """
+ The integer port number
+ """
+
+ def __get__ (self) :
+ """
+ Default implementation using getnameinfo() and int()
+ """
+
+ addr, port = self.getnameinfo()
+
+ return int(port)
+
+cdef class sockaddr_in (sockaddr) :
+ """
+ AF_INET struct sockaddr_in
+
+ >>> sa = sockaddr_in("127.0.0.1", 80)
+ >>> sa.addr
+ '127.0.0.1'
+ >>> sa.port
+ 80
+ >>> str(sa)
+ '127.0.0.1:80'
+ >>> str(sockaddr_in())
+ '0.0.0.0:0'
+ """
+
+ # the struct sockaddr_in
+ cdef libc.sockaddr_in sockaddr
+
+ def __init__ (self, object addr=None, libc.in_port_t port=0) :
+ """
+ Construct using given literal IPv4 address and TCP/UDP port
+
+ addr - IPv4 address, defaults to INADDR_ANY (0.0.0.0)
+ port - TCP/UDP port, defaults to 0 (ephemeral)
+ """
+
+ # store our family
+ # XXX: this should be a class attribute...
+ self._init_family(libc.AF_INET)
+
+ # constant af
+ self.sockaddr.sin_family = self.family
+
+ # set the sin_port
+ self.sockaddr.sin_port = libc.htons(port)
+
+ if addr :
+ # set the sin_addr
+ # this automatically converts the addr from str -> char *
+ libc.inet_pton(self.family, addr, &self.sockaddr.sin_addr)
+
+ else :
+ # set as INADDR_ANY
+ self.sockaddr.sin_addr.s_addr = libc.INADDR_ANY
+
+ cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 :
+ if sa_ptr :
+ sa_ptr[0] = <libc.sockaddr *> &self.sockaddr
+
+ if sa_len :
+ sa_len[0] = sizeof(self.sockaddr)
+
+ return 0
+
+ cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 :
+ assert sa_len == sizeof(self.sockaddr)
+
+ libc.memcpy(&self.sockaddr, sa, sa_len)
+
+ property port :
+ """
+ The integer port number
+ """
+
+ def __get__ (self) :
+ return libc.ntohs(self.sockaddr.sin_port)
+
+ def __str__ (self) :
+ """
+ Return the literal ASCII representation for this sockaddr as an '<addr>:<port> string
+ """
+
+ # format
+ return "%s:%s" % self.getnameinfo()
+
+cdef class sockaddr_in6 (sockaddr) :
+ """
+ AF_INET6 struct sockaddr_in6
+
+ >>> sa6 = sockaddr_in6("::1", 80)
+ >>> sa6.addr
+ '::1'
+ >>> sa6.port
+ 80
+ >>> str(sa6)
+ '[::1]:80'
+ >>> str(sockaddr_in6())
+ '[::]:0'
+ """
+
+ cdef libc.sockaddr_in6 sockaddr
+
+ def __init__ (self, object addr=None, libc.in_port_t port=0) :
+ """
+ Construct using given literal IPv6 address and TCP/UDP port
+
+ addr - IPv6 address, defaults to in6addr_any (::)
+ port - TCP/UDP port, defaults to 0 (ephemeral)
+ """
+
+ # store our family
+ # XXX: this should be a class attribute...
+ self._init_family(libc.AF_INET6)
+
+ # constant af
+ self.sockaddr.sin6_family = self.family
+
+ # set the sin_port
+ self.sockaddr.sin6_port = libc.htons(port)
+
+ if addr :
+ # set the sin_addr
+ # this automatically converts the addr from str -> char *
+ libc.inet_pton(self.family, addr, &self.sockaddr.sin6_addr)
+
+ else :
+ # set as INADDR_ANY
+ self.sockaddr.sin6_addr = libc.in6addr_any
+
+ cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 :
+ if sa_ptr :
+ sa_ptr[0] = <libc.sockaddr *> &self.sockaddr
+
+ if sa_len :
+ sa_len[0] = sizeof(self.sockaddr)
+
+ return 0
+
+ cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 :
+ assert sa_len == sizeof(self.sockaddr)
+
+ libc.memcpy(&self.sockaddr, sa, sa_len)
+
+ property port :
+ """
+ The integer port number
+ """
+
+ def __get__ (self) :
+ return libc.ntohs(self.sockaddr.sin6_port)
+
+
+ def __str__ (self) :
+ """
+ Return the literal ASCII representation for this sockaddr as a '[<addr>]:<port> string
+ """
+
+ # format
+ return "[%s]:%s" % self.getnameinfo()
+
+# mapping of AF -> sockaddr, user-modifyable
+SOCKADDR_BY_FAMILY = {
+ libc.AF_INET: sockaddr_in,
+ libc.AF_INET6: sockaddr_in6,
+}
+
+# build a sockaddr from the given sockaddr struct, based on sa_family
+cdef sockaddr build_sockaddr (libc.sockaddr *sa, size_t sa_len) :
+ # lookup correct class to use
+ addr_type = SOCKADDR_BY_FAMILY[sa.sa_family]
+
+ # construct with defaults
+ cdef sockaddr addr = addr_type()
+
+ # store
+ addr._set_sockaddr(sa, sa_len)
+
+ return addr
+
+cdef class addrinfo :
+
+ cdef _init_addrinfo (self, libc.addrinfo *ai) :
+ #ai.flags = c_ai.ai_flags
+ self.family = ai.ai_family
+ self.socktype = ai.ai_socktype
+ self.protocol = ai.ai_protocol
+ self.addr = build_sockaddr(ai.ai_addr, ai.ai_addrlen)
+ self.canonname = ai.ai_canonname if ai.ai_canonname else None
+
+ def __str__ (self) :
+ return "family=%d, socktype=%d, protocol=%d, addr=%s, canonname=%s" % (self.family, self.socktype, self.protocol, self.addr, self.canonname)
+
+cdef addrinfo build_addrinfo (libc.addrinfo *c_ai) :
+ cdef addrinfo ai = addrinfo()
+
+ ai._init_addrinfo(c_ai)
+
+ return ai
+
+cdef class endpoint :
+
+ def __init__ (self, hostname=None, service=None) :
+ """
+ Construct with the given hostname/service, either of which may be None.
+
+ A hostname of None implies all valid local addresses (with AI_PASSIVE), and a service of None implies an
+ ephemeral port.
+
+ hostname - the literal address or DNS hostname or anything else that GAI supports
+ service - the numeric port or service name
+ """
+
+ self.hostname = str(hostname)
+ self.service = str(service)
+
+ cpdef getaddrinfo (self, int family, int socktype, int protocol = 0, int flags = libc.AI_PASSIVE) :
+ """
+ Look up our hostname/service using the given socket parameters, and return a sequence of addrinfo objects.
+ """
+
+ # XXX: Cython doesn't support proper compound value literals...
+ cdef libc.addrinfo hints
+
+ libc.memset(&hints, 0, sizeof(hints))
+ hints.ai_flags = flags
+ hints.ai_family = family
+ hints.ai_socktype = socktype
+ hints.ai_protocol = protocol
+
+ cdef libc.addrinfo *res, *r
+ cdef int err
+ cdef object ret = []
+
+ cdef char *hostname = NULL
+ cdef char *service = NULL
+
+ if self.hostname is not None :
+ hostname = self.hostname
+
+ if self.service is not None :
+ service = self.service
+
+ # operate!
+ err = libc.c_getaddrinfo(hostname, service, &hints, &res)
+
+ try :
+ if err :
+ # XXX: raise a GAIError
+ raise Exception(libc.gai_strerror(err))
+
+ # gather results
+ r = res
+
+ while r :
+ ret.append(build_addrinfo(r))
+
+ r = r.ai_next
+
+ # ok
+ return ret
+
+ finally :
+ libc.c_freeaddrinfo(res)
+
+ def __str__ (self) :
+ return "hostname=%s, service=%s" % (self.hostname, self.service)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/socket.pxd Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,26 @@
+"""
+ Sockect Object/API
+"""
+
+ctypedef int socket_t
+
+cdef class sock :
+ """
+ Represents a single OS-level socket
+
+ >>> from socket import addr
+ >>> s = sock()
+ >>> s.send('foo')
+ Traceback (most recent call last):
+ ...
+ OSError: [Errno 9] Bad file descriptor
+ >>> s.socket()
+ >>> s.bind(addr.sockaddr_in('127.0.0.1', 1337))
+ >>> s.listen(1)
+ >>> s.listen(0)
+ >>> s.connect(addr.sockaddr_in('127.0.01.', 1338))
+ x
+ """
+
+ cdef readonly socket_t fd
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/socket.pyx Sun Aug 16 19:01:21 2009 +0300
@@ -0,0 +1,150 @@
+from qmsk.net.socket.socket cimport *
+from qmsk.net.socket.addr cimport sockaddr, build_sockaddr
+
+cimport libc, py
+
+from py cimport raise_errno
+
+
+# XXX: do some GIL-releasin'
+cdef class sock :
+
+ def __init__ (self, int fd = -1) :
+ """
+ Construct this socket with the given fd, or -1 to mark it as fd-less
+ """
+
+ self.fd = fd
+
+ def socket (self, int family = libc.AF_INET, int socktype = libc.SOCK_STREAM, int protocol = 0) :
+ """
+ Create a new socket endpoint with the given family/domain, socktype and optionally, specific protocol.
+
+ family - one of AF_*
+ socktype - one of SOCK_*
+ protocol - one of IPPROTO_* or zero to select default
+ """
+
+ if self.fd >= 0 :
+ raise Exception("Socket fd already exists")
+
+ # socket()
+ self.fd = libc.socket(family, socktype, protocol)
+
+ # trap
+ if self.fd < 0 :
+ raise_errno('socket')
+
+ def bind (self, sockaddr addr) :
+ """
+ Bind this socket to the given local socket address. The given sockaddr should be of the same or a
+ compatible address family.
+
+ addr - the local address to bind to. The port may be zero to let the system choose an unused
+ ephemeral port.
+ """
+
+ cdef libc.sockaddr *sa_ptr
+ cdef libc.socklen_t sa_len
+
+ # get the address
+ addr._get_sockaddr(&sa_ptr, &sa_len)
+
+ # bind()
+ if libc.bind(self.fd, sa_ptr, sa_len) :
+ raise_errno('bind')
+
+ def listen (self, int backlog) :
+ """
+ Listen for connections, marking this socket as a passive socket, which can accept incoming connection
+ requests using sock.accept().
+
+ It is customary to call .bind() before .listen().
+
+ backlog - maximum number of pending connections (those not yet .accept()'d).
+ """
+
+ # listen()
+ if libc.listen(self.fd, backlog) :
+ raise_errno('listen')
+
+ def connect (self, sockaddr addr) :
+ """
+ Initiate a connection, connecting this socket to the remote endpoint specified by `addr`. The given sockaddr
+ should be of the same or a compatible address family.
+
+ If the socket is in non-blocking mode, this will presumeably return errno.EINPROGRESS.
+
+ If the socket has not yet been bound (using .bind()), the system will pick an appropriate local address and
+ ephemeral port.
+
+ addr - the remote address to connect to.
+ """
+
+ cdef libc.sockaddr *sa_ptr
+ cdef libc.socklen_t sa_len
+
+ # get the address
+ addr._get_sockaddr(&sa_ptr, &sa_len)
+
+ # connect()
+ if libc.connect(self.fd, sa_ptr, sa_len) :
+ raise_errno('connect')
+
+ def accept (self) :
+ """
+ Accept a connection, dequeueing the first pending connection and returning a new sock object for it. This
+ socket must be a connection-based socket (SOCK_STREAM/SOCK_SEQPACKET) and in the passive listening mode
+ (.listen()).
+
+ This returns a (sock, sockaddr) tuple:
+ sock - the newly created sock, corresponding to the incoming connection
+ sockaddr - the remote address of the incoming connection
+ """
+
+ # prep the sockaddr that we will return
+ cdef libc.sockaddr_storage ss
+ cdef libc.socklen_t ss_len = sizeof(ss)
+
+ cdef socket_t sock_fd
+
+ # accept()
+ sock_fd = libc.accept(self.fd, <libc.sockaddr *> &ss, &ss_len)
+
+ if sock_fd < 0 :
+ raise_errno('accept')
+
+ # prep the new socket
+ sock_obj = sock(sock_fd)
+
+ # prep the new addr
+ sock_addr = build_sockaddr(<libc.sockaddr *> &ss, ss_len)
+
+ return sock_obj, sock_addr
+
+ def send (self, object buf, int flags = 0) :
+ """
+ Transmit a message to the connected remote endpoint.
+
+ buf - the data to send
+ flags - MSG_* flags to send with
+
+ Returns the number of bytes sent, which may be less than the length of buf.
+ """
+
+ cdef char *buf_ptr
+ cdef libc.ssize_t buf_len, ret
+
+ # get buffer
+ # XXX: test that except works right
+ py.PyObject_AsCharBuffer(buf, &buf_ptr, &buf_len)
+
+ # send()
+ ret = libc.send(self.fd, <void *> buf_ptr, buf_len, flags)
+
+ if ret < 0 :
+ raise_errno('send')
+
+ else :
+ return ret
+
--- a/setup.py Sun Aug 16 18:29:55 2009 +0300
+++ b/setup.py Sun Aug 16 19:01:21 2009 +0300
@@ -6,14 +6,31 @@
return Extension(name, files, include_dirs=['inc'], **opts)
setup(
- cmdclass = {'build_ext': build_ext},
+ name = 'qmsk.net',
+ version = '0.0.1',
+ description = "Python network programming re-invented",
+ author = "Tero Marttila",
+ author_email = "terom@fixme.fi",
+ url = "http://projects.qmsk.net/qmsk.net",
+
+ # for python code
+ packages = [
+ 'qmsk.net.socket',
+ 'qmsk.net.sctp',
+ ],
+
+ # override build_ext to use Cython
+ cmdclass = {'build_ext': build_ext},
+
+ # describe Cython modules
+ ext_package = 'qmsk.net',
ext_modules = [
- cython_ext("libc", ["libc.pyx"]),
- cython_ext("py", ["py.pyx"]),
- cython_ext("socket.addr", ["socket/addr.pyx"]),
- cython_ext("socket.sock", ["socket/sock.pyx"]),
- cython_ext("sctp.sock", ["sctp/sock.pyx"], libraries=['sctp']),
- cython_ext("sctp.constants", ["sctp/constants.pyx"]),
+ cython_ext("libc", ["qmsk/net/libc.pyx"]),
+ cython_ext("py", ["qmsk/net/py.pyx"]),
+ cython_ext("socket.addr", ["qmsk/net/socket/addr.pyx"]),
+ cython_ext("socket.socket", ["qmsk/net/socket/socket.pyx"]),
+ cython_ext("sctp.sock", ["qmsk/net/sctp/sock.pyx"], libraries=['sctp']),
+ cython_ext("sctp.constants", ["qmsk/net/sctp/constants.pyx"]),
]
)