# HG changeset patch # User Tero Marttila # Date 1253903644 -10800 # Node ID e2f79e68418ac4aa5ea37590a9f280e96f40aa1e # Parent ee7ade660c0b5a7de58f7c12362905159c8d100f fix up circular cimports related to the sockaddr type, and touch up endpoint/getaddrinfo a bit diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/_address.pxd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qmsk/net/socket/_address.pxd Fri Sep 25 21:34:04 2009 +0300 @@ -0,0 +1,42 @@ +""" + Internal module to keep the abstract sockaddr types out of the address module, which must contain backreferences to + the concrete implementations. +""" + +cimport qmsk.net.socket.platform as platform + +cdef class sockaddr : + """ + A network-level socket address + + XXX: not abstract enough. Functions/properties like getnameinfo/addr/port do not work for e.g. sockaddr_un + + >>> 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 platform.sa_family_t family + + cdef void _init_family (self, platform.sa_family_t family = ?) + + # get the sockaddr/socklen + # each of these can be NULL to ignore it + cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 + + cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL + cdef platform.socklen_t _get_sockaddr_len (self) except -1 + + # set the sockaddr, socklen must match + cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 + + diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/_address.pyx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qmsk/net/socket/_address.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -0,0 +1,97 @@ + + +cdef class sockaddr : + cdef void _init_family (self, platform.sa_family_t family=platform.AF_UNSPEC) : + self.family = family + + # XXX:use size_t + cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 : + """ + Get the sockaddr pointer and sockaddr length for this address + """ + + raise NotImplementedError() + + cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL : + """ + Get the sockaddr pointer + """ + + cdef platform.sockaddr *sa + cdef platform.socklen_t sa_len + + self._get_sockaddr(&sa, &sa_len) + + return sa + + cdef platform.socklen_t _get_sockaddr_len (self) except -1 : + """ + Get the sockaddr len + """ + + cdef platform.sockaddr *sa + cdef platform.socklen_t sa_len + + self._get_sockaddr(&sa, &sa_len) + + return sa_len + + cdef int _set_sockaddr (self, platform.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 + + >>> addr = sockaddr_in() + >>> assert addr.getnameinfo() == (addr.addr, str(addr.port)) + """ + + cdef platform.sockaddr *sa + cdef platform.socklen_t sa_len + + # XXX: take as args? + cdef int flags = platform.NI_NUMERICHOST | platform.NI_NUMERICSERV + + # get our abstract sockaddr + self._get_sockaddr(&sa, &sa_len) + + # get nice text format + return platform.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) + + def __repr__ (self) : + return "sockaddr(%d, %s, %d)" % (self.family, self.addr, self.port) + + diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/address.pxd --- a/qmsk/net/socket/address.pxd Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/address.pxd Fri Sep 25 21:34:04 2009 +0300 @@ -6,43 +6,9 @@ endpoint - human-readable network address, corresponding to multiple sockaddr's """ -cimport qmsk.net.libc as libc - cimport qmsk.net.socket.platform as platform -cdef class sockaddr : - """ - A network-level socket address - - XXX: not abstract enough. Functions/properties like getnameinfo/addr/port do not work for e.g. sockaddr_un - - >>> 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 platform.sa_family_t family - - cdef void _init_family (self, platform.sa_family_t family = ?) - - # get the sockaddr/socklen - # each of these can be NULL to ignore it - cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 - - cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL - cdef platform.socklen_t _get_sockaddr_len (self) except -1 - - # set the sockaddr, socklen must match - cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 +from qmsk.net.socket._address cimport sockaddr # build a sockaddr from the given sockaddr struct, based on sa_family cdef sockaddr build_sockaddr (platform.sockaddr *sa, size_t sa_len) @@ -82,17 +48,13 @@ 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... + XXX: silly abstraction, just use the getaddrinfo function - Hence, endpoints are stored as human-readable hostname/service strings, which are then translated to sockaddrs - using getaddrinfo. - - >>> from __future__ import absolute_import; import socket as _socket + >>> from qmsk.net.socket.constants import * >>> 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) + >>> res = e.getaddrinfo(AF_UNSPEC, SOCK_STREAM) >>> len(res) 1 >>> str(res[0]) @@ -100,7 +62,7 @@ >>> e = endpoint('2001::5', 80) >>> str(e) 'hostname=2001::5, service=80' - >>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM) + >>> res = e.getaddrinfo(AF_UNSPEC, SOCK_STREAM) >>> len(res) 1 >>> str(res[0]) diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/address.pyx --- a/qmsk/net/socket/address.pyx Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/address.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -1,104 +1,13 @@ cimport qmsk.net.libc as libc cimport qmsk.net.py as py -from qmsk.net.socket.address cimport * +#from qmsk.net.socket.address cimport * + +cimport qmsk.net.libc as libc cimport qmsk.net.socket.platform as platform -cdef class sockaddr : - cdef void _init_family (self, platform.sa_family_t family=platform.AF_UNSPEC) : - self.family = family - - # XXX:use size_t - cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 : - """ - Get the sockaddr pointer and sockaddr length for this address - """ - - raise NotImplementedError() - - cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL : - """ - Get the sockaddr pointer - """ - - cdef platform.sockaddr *sa - cdef platform.socklen_t sa_len - - self._get_sockaddr(&sa, &sa_len) - - return sa - - cdef platform.socklen_t _get_sockaddr_len (self) except -1 : - """ - Get the sockaddr len - """ - - cdef platform.sockaddr *sa - cdef platform.socklen_t sa_len - - self._get_sockaddr(&sa, &sa_len) - - return sa_len - - cdef int _set_sockaddr (self, platform.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 - - >>> addr = sockaddr_in() - >>> assert addr.getnameinfo() == (addr.addr, str(addr.port)) - """ - - cdef platform.sockaddr *sa - cdef platform.socklen_t sa_len - - # XXX: take as args? - cdef int flags = platform.NI_NUMERICHOST | platform.NI_NUMERICSERV - - # get our abstract sockaddr - self._get_sockaddr(&sa, &sa_len) - - # get nice text format - return platform.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) - - def __repr__ (self) : - return "sockaddr(%d, %s, %d)" % (self.family, self.addr, self.port) - +# concrete sockaddr implementation types # mapping of AF -> sockaddr, user-modifyable cimport qmsk.net.socket.af_inet, qmsk.net.socket.af_inet6 @@ -226,7 +135,7 @@ Look up given hostname/service using the given socket parameters, and return a sequence of addrinfo objects. hostname - internet address/hostname to look up, or None (for INADDR_ANY/localhost, see AI_PASSIVE) - service - port/service to use, or None (for ephemeral) + service - port/service to use, or None (for ephemeral). Should be given as a string family - address family to use, one of AF_*. May be AF_UNSPEC. socktype - socket type to use, one of SOCK_*. protocol - protocol to use, one of IPPROTO_* or zero to pick the default protocol for the given @@ -267,6 +176,10 @@ _hostname = hostname if service is not None : + # XXX: also accept integer port number? + if isinstance(service, int) : + service = str(service) + _service = service # operate! diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/af_inet.pxd --- a/qmsk/net/socket/af_inet.pxd Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/af_inet.pxd Fri Sep 25 21:34:04 2009 +0300 @@ -2,8 +2,8 @@ AF_INET-specific stuff """ -from qmsk.net.socket.address cimport * - +from qmsk.net.socket._address cimport sockaddr +cimport qmsk.net.socket.platform as platform cdef class sockaddr_in (sockaddr) : """ diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/af_inet.pyx --- a/qmsk/net/socket/af_inet.pyx Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/af_inet.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -1,3 +1,4 @@ +cimport qmsk.net.libc as libc cimport qmsk.net.py as py cdef class sockaddr_in (sockaddr) : diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/af_inet6.pxd --- a/qmsk/net/socket/af_inet6.pxd Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/af_inet6.pxd Fri Sep 25 21:34:04 2009 +0300 @@ -2,8 +2,8 @@ AF_INET6-specific stuff """ -from qmsk.net.socket.address cimport * - +from qmsk.net.socket._address cimport sockaddr +cimport qmsk.net.socket.platform as platform cdef class sockaddr_in6 (sockaddr) : """ diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/af_inet6.pyx --- a/qmsk/net/socket/af_inet6.pyx Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/af_inet6.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -1,3 +1,4 @@ +cimport qmsk.net.libc as libc cimport qmsk.net.py as py cdef class sockaddr_in6 (sockaddr) : diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/af_unix.pxd --- a/qmsk/net/socket/af_unix.pxd Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/af_unix.pxd Fri Sep 25 21:34:04 2009 +0300 @@ -2,7 +2,8 @@ AF_UNIX-specific stuff """ -from qmsk.net.socket.address cimport * +from qmsk.net.socket._address cimport sockaddr +cimport qmsk.net.socket.platform as platform cdef class sockaddr_un (sockaddr) : diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/af_unix.pyx --- a/qmsk/net/socket/af_unix.pyx Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/af_unix.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -1,5 +1,5 @@ +cimport qmsk.net.libc as libc cimport qmsk.net.py as py -cimport qmsk.net.libc as libc cdef class sockaddr_un (sockaddr) : diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/sctp.pyx --- a/qmsk/net/socket/sctp.pyx Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/sctp.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -10,7 +10,6 @@ """ -from qmsk.net.socket.sctp cimport * from qmsk.net.socket.address cimport sockaddr cimport qmsk.net.socket.platform as platform diff -r ee7ade660c0b -r e2f79e68418a qmsk/net/socket/socket.pyx --- a/qmsk/net/socket/socket.pyx Tue Sep 01 00:08:02 2009 +0300 +++ b/qmsk/net/socket/socket.pyx Fri Sep 25 21:34:04 2009 +0300 @@ -1,5 +1,6 @@ from qmsk.net.socket.socket cimport * -from qmsk.net.socket.address cimport sockaddr, build_sockaddr +from qmsk.net.socket._address cimport sockaddr +from qmsk.net.socket.address cimport build_sockaddr cimport qmsk.net.socket.platform as platform cimport qmsk.net.libc as libc, qmsk.net.py as py diff -r ee7ade660c0b -r e2f79e68418a setup.py --- a/setup.py Tue Sep 01 00:08:02 2009 +0300 +++ b/setup.py Fri Sep 25 21:34:04 2009 +0300 @@ -30,6 +30,7 @@ cython_ext("qmsk.net.py", ["qmsk/net/py.pyx"]), cython_ext("qmsk.net.socket.platform", ["qmsk/net/socket/platform.pyx"]), cython_ext("qmsk.net.socket.constants", ["qmsk/net/socket/constants.pyx"]), + cython_ext("qmsk.net.socket._address", ["qmsk/net/socket/_address.pyx"]), cython_ext("qmsk.net.socket.address", ["qmsk/net/socket/address.pyx"]), cython_ext("qmsk.net.socket.socket", ["qmsk/net/socket/socket.pyx"]), cython_ext("qmsk.net.socket.af_inet", ["qmsk/net/socket/af_inet.pyx"]),