# HG changeset patch # User Tero Marttila # Date 1250803765 -10800 # Node ID 12468e38227eecd6f7390a4520f7b4ba3bf8982d # Parent d8a71a6758622acac927ffa9e1d260b4d3d24055 [socket] add sockaddr_un (still dysfunctional\!) + doc fixes diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/__init__.py --- a/qmsk/net/socket/__init__.py Wed Aug 19 00:12:07 2009 +0300 +++ b/qmsk/net/socket/__init__.py Fri Aug 21 00:29:25 2009 +0300 @@ -13,6 +13,8 @@ sockaddr - corresponds to the `struct sockaddr` used in socket API calls. This is an abstract type that cannot itself be instantated, see `sockaddr_in`/`sockaddr_in6`/`endpoint`. + XXX: these are only abstract at the internet level. They do not apply to e.g. UNIX socket addresses! + addrinfo - corresponds to the `struct addrinfo` used by the GAI API. Hold a concrete `sockaddr` endpoint - abstract internet hostname+service address as handled by getaddrinfo. Maps to a series of `addrinfo`'s. @@ -47,6 +49,12 @@ MSG_* - send/recv message flags etc. + + TODO: + * release GIL for operations + * expose some misc. functions (e.g. [hn]ton[slq]) via platform? + * define more constants + * consider some sockaddr_in::sin_addr/sockaddr_in6::sin6_addr -level interfaces? """ ## XXX: these shadow the modules... how do we want to provide these? diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/address.pxd --- a/qmsk/net/socket/address.pxd Wed Aug 19 00:12:07 2009 +0300 +++ b/qmsk/net/socket/address.pxd Fri Aug 21 00:29:25 2009 +0300 @@ -13,8 +13,8 @@ cdef class sockaddr : """ A network-level socket address - - XXX: rename to 'address' + + XXX: not abstract enough. Functions/properties like getnameinfo/addr/port do not work for e.g. sockaddr_un >>> sockaddr().family 0 diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/address.pyx --- a/qmsk/net/socket/address.pyx Wed Aug 19 00:12:07 2009 +0300 +++ b/qmsk/net/socket/address.pyx Fri Aug 21 00:29:25 2009 +0300 @@ -240,6 +240,25 @@ cpdef getaddrinfo (self, int family, int socktype, int protocol = 0, int flags = platform.AI_PASSIVE) : """ Look up our hostname/service using the given socket parameters, and return a sequence of addrinfo objects. + + family - the address family to use, one of AF_*. May be AF_UNSPEC. + socktype - the socket type to use, one of SOCK_*. + protocol - the protocol to use, one of IPPROTO_* or zero to pick a suitable protocol + for the given socktype. + flags - bitmask of AI_* flags for getaddrinfo() + + AI_NUMERICHOST - self.hostname is a literal address, do not perform any network host address lookups + AI_NUMERICSERV - self.service is a literal port number, do not lookup service names + AI_CANONNAME - return addrinfo objects with .canonname set to the official name of the host + AI_PASSIVE - intended for use by server applications, return addrinfos with an unspecified + .addr if no self.hostname is not given. + AI_ADDRCONFIG - only return addrinfos with a .addrs of a given address family if the system has at + least one local address of that address family configured. + AI_V4MAPPED - if family=AF_INET6, and no matching IPv6 addresses could be found, return IPv4-mapped + IPv6 addresses. + AI_ALL - if used together with AI_V4MAPPED, then return both IPv6 and IPv4-mapped IPv6 + addresses. + """ # XXX: Cython doesn't support proper compound value literals... diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/af_unix.pxd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qmsk/net/socket/af_unix.pxd Fri Aug 21 00:29:25 2009 +0300 @@ -0,0 +1,21 @@ +""" + AF_UNIX-specific stuff +""" + +from qmsk.net.socket.address cimport * + + +cdef class sockaddr_un (sockaddr) : + """ + AF_UNIX struct sockaddr_un + + XXX: doesn't support the abstract namespace + """ + + # the struct sockaddr_in + cdef platform.sockaddr_un sockaddr + + + cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 + cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 + diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/af_unix.pyx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qmsk/net/socket/af_unix.pyx Fri Aug 21 00:29:25 2009 +0300 @@ -0,0 +1,86 @@ +cimport qmsk.net.py as py + +cdef class sockaddr_un (sockaddr) : + + def __init__ (self, char *addr) : + """ + 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) + """ + + if len(addr) > sizeof(self.sockaddr.sun_path) - 1 : + raise ValueError("AF_UNIX path is too long: " + addr) + + # zero + libc.memset(&self.sockaddr, 0, sizeof(self.sockaddr)) + + # store our family + # XXX: this should be a class attribute... + self._init_family(platform.AF_UNIX) + + # constant af + self.sockaddr.sun_family = self.family + + # set the sun_path + memcpy(self.sockaddr.sun_path, addr, len(addr)) + self.sockaddr.sun_path[len(addr)] = '\0' + + cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 : + if sa_ptr : + sa_ptr[0] = &self.sockaddr + + if sa_len : + sa_len[0] = sizeof(self.sockaddr) + + return 0 + + cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 : + assert sa_len == sizeof(self.sockaddr) + + libc.memcpy(&self.sockaddr, sa, sa_len) + + property path : + """ + The string path + + XXX: abstract namespace + """ + + def __get__ (self) : + return self.sockaddr.sun_path + + def __cmp__ (self, other_obj) : + """ + A sockaddr_un is equal to any other sockaddr_un which has the same path + + >>> assert sockaddr_un() == sockaddr_un() + >>> assert sockaddr_un('/foo/bar') == sockaddr_un('/foo/bar') + >>> addr = sockaddr_un(); assert addr == addr + """ + + if not isinstance(other_obj, sockaddr_un) : + return py.Py_NotImplemented + + cdef sockaddr_un other = other_obj + cdef platform.sockaddr_un *sa1 = &self.sockaddr, *sa2 = &other.sockaddr + + if other is self : + return 0 + + return ( + libc.memcmp( &sa1.sin_path, &sa2.sin_path, sizeof(sa1.sin_path)) + ) + + def __str__ (self) : + """ + Return the literal ASCII representation for this sockaddr as an ' string + + >>> str(sockaddr_un('/foo')) + '/foo' + """ + + # format + return "%s" % self.path + diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/platform.pxd --- a/qmsk/net/socket/platform.pxd Wed Aug 19 00:12:07 2009 +0300 +++ b/qmsk/net/socket/platform.pxd Fri Aug 21 00:29:25 2009 +0300 @@ -191,6 +191,18 @@ uint16_t ntohs(uint16_t) uint32_t ntohl(uint32_t) +cdef extern from "sys/un.h" : + enum : + UNIX_PATH_MAX + + struct sockaddr_un : + sa_family_t sun_family + char sun_path[UNIX_PATH_MAX] + + # actually a macro + # sockaddr_un -> size_t actual length of the sockaddr + size_t SUN_LEN (sockaddr_un *sa) + cdef extern from "netdb.h" : ## getaddrinfo struct addrinfo : diff -r d8a71a675862 -r 12468e38227e qmsk/net/socket/socket.pyx --- a/qmsk/net/socket/socket.pyx Wed Aug 19 00:12:07 2009 +0300 +++ b/qmsk/net/socket/socket.pyx Fri Aug 21 00:29:25 2009 +0300 @@ -497,7 +497,8 @@ Returns a (name, iovs, control, flags) tuple : name - the source address of the message, or None - iovs - sequence of strings containing the recieved data corresponding to the iov_lens + iovs - sequence of buffers containing the recieved data corresponding to the iov_lens. + This may contain fewer buffers than iov_lens if there was insufficient data to fill all buffers. control - string containing recieved control message, if any flags - recieved flags """