fix up addrinfo to hold a real platform.addrinfo, storing ai_addr/ai_canonname as objects
--- a/qmsk/net/socket/address.pxd Mon Aug 17 20:24:12 2009 +0300
+++ b/qmsk/net/socket/address.pxd Tue Aug 18 22:24:36 2009 +0300
@@ -49,15 +49,32 @@
cdef class addrinfo :
"""
- A socket-level endpoint address, which contains the full socket parameters and an bind/connect address
- """
+ A socket-level endpoint address, which contains the full socket parameters and an bind/connect address.
+
+ A full addrinfo struct is stored, but ai_canonname and ai_addr are stored as (optional) objects outside of the
+ addrinfo struct.
-# cdef readonly int flags
- cdef readonly int family, socktype, protocol
- cdef readonly sockaddr addr
- cdef readonly object canonname
+ >>> ai = addrinfo()
+ >>> ai.addr
+ >>> ai.canonname
+ >>> print addrinfo(addr=sockaddr_in())
+ family=0, socktype=0, protocol=0, addr=0.0.0.0:0, canonname=None
+ """
+
+ # canonname is not stored
+ # may be NULL
+ cdef platform.addrinfo ai
- cdef _init_addrinfo (self, platform.addrinfo *c_ai)
+ # may be NULL
+ cdef sockaddr ai_addr
+ cdef object ai_canonname
+
+ # update self.ai.ai_* to reflect self.ai_*
+ cdef _init_ai_members (self)
+
+ # set the contents of self.ai from the given real addrinfo
+ # this ignores the ai_canonname attribute
+ cdef _init_addrinfo (self, platform.addrinfo *ai)
# build and return a new addrinfo instance
cdef addrinfo build_addrinfo (platform.addrinfo *c_ai)
--- a/qmsk/net/socket/address.pyx Mon Aug 17 20:24:12 2009 +0300
+++ b/qmsk/net/socket/address.pyx Tue Aug 18 22:24:36 2009 +0300
@@ -51,6 +51,9 @@
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
@@ -165,6 +168,9 @@
property port :
"""
The integer port number
+
+ >>> sockaddr_in(port=1234).port
+ 1234
"""
def __get__ (self) :
@@ -273,6 +279,9 @@
The integer port number.
This will represent it correctly in host byte order.
+
+ >>> sockaddr_in6(port=1234).port
+ 1234
"""
def __get__ (self) :
@@ -284,6 +293,9 @@
The integer flowinfo
XXX: byteorder?
+
+ >>> sockaddr_in6().flowinfo
+ 0
"""
def __get__ (self) :
@@ -295,6 +307,9 @@
The scope ID - corresponds to an interface index for link-scope addresses.
This should be in host byte order...
+
+ >>> sockaddr_in6(scope_id=1337).scope_id
+ 1337
"""
def __get__ (self) :
@@ -372,14 +387,95 @@
return addr
cdef class addrinfo :
+
+ cdef _init_ai_members (self) :
+ """
+ Update self.ai.ai_* to reflect self.ai_*
+ """
+
+ cdef platform.socklen_t addr_len
+
+ if self.ai_addr is not None :
+ self.ai_addr._get_sockaddr(&self.ai.ai_addr, &addr_len)
+ self.ai.ai_addrlen = addr_len
+
+ else :
+ self.ai.ai_addr = NULL
+ self.ai.ai_addrlen = 0
+
+ if self.ai_canonname is not None :
+ self.ai.ai_canonname = self.ai_canonname
+
+ else :
+ self.ai.ai_canonname = NULL
+ def __init__ (self, int flags = 0, int family = 0, int socktype = 0, int protocol = 0, sockaddr addr = None, object canonname = None) :
+ """
+ Construct a new addrinfo with the given parameters
+ """
+
+
+ self.ai.ai_flags = flags
+ self.ai.ai_family = family
+ self.ai.ai_socktype = socktype
+ self.ai.ai_protocol = protocol
+
+ self.ai_addr = addr
+
+ if canonname is not None :
+ self.ai_canonname = str(canonname)
+
+ else :
+ self.ai_canonname = None
+
+ # update self.ai
+ self._init_ai_members()
+
cdef _init_addrinfo (self, platform.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
+ """
+ Re-initialize this addrinfo's parameters from the given addrinfo
+ """
+
+ # copy raw
+ self.ai = ai[0]
+
+ # store copies of external objects
+ if ai.ai_addr :
+ # copy addr as object
+ self.ai_addr = build_sockaddr(ai.ai_addr, ai.ai_addrlen)
+
+ else :
+ self.ai_addr = None
+
+ if ai.ai_canonname :
+ # copy as object
+ self.ai_canonname = ai.ai_canonname
+
+ else :
+ self.ai_canonname = None
+
+ # update self.ai
+ self._init_ai_members()
+
+ property flags :
+ def __get__ (self) : return self.ai.ai_flags
+
+ property family :
+ def __get__ (self) : return self.ai.ai_family
+
+ property socktype :
+ def __get__ (self) : return self.ai.ai_socktype
+
+ property protocol :
+ def __get__ (self) : return self.ai.ai_protocol
+
+ property addr :
+ # XXX: None?
+ def __get__ (self) : return self.ai_addr
+
+ property canonname :
+ # XXX: None?
+ def __get__ (self) : return self.ai_canonname
def __str__ (self) :
return "family=%d, socktype=%d, protocol=%d, addr=%s, canonname=%s" % (self.family, self.socktype, self.protocol, self.addr, self.canonname)
@@ -442,7 +538,7 @@
# XXX: raise a GAIError
raise Exception(platform.gai_strerror(err))
- # gather results
+ # gather results from linked list to PyList
r = res
while r :