--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/address.pxd Mon Aug 17 01:29:31 2009 +0300
@@ -0,0 +1,97 @@
+"""
+ 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 qmsk.net.libc as libc
+
+cimport qmsk.net.socket.platform as platform
+
+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 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
+
+# build a sockaddr from the given sockaddr struct, based on sa_family
+cdef sockaddr build_sockaddr (platform.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, platform.addrinfo *c_ai)
+
+# build and return a new addrinfo instance
+cdef addrinfo build_addrinfo (platform.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.
+
+ >>> from __future__ import absolute_import; import socket as _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 = ?)
+