add CallbackEvent helper, and move getaddrinfo from endpoint into its own function
--- a/qmsk/net/lib/event2/event.pyx Mon Aug 31 22:17:54 2009 +0300
+++ b/qmsk/net/lib/event2/event.pyx Tue Sep 01 00:04:26 2009 +0300
@@ -134,3 +134,20 @@
lib.event_free(self.ev)
+class CallbackEvent (event) :
+ """
+ Extends the event type to take a callback and additional arguments to invoke from the __call__ method.
+ """
+
+ def __init__ (self, event_base base, lib.evutil_socket_t fd, short events, object callback, *args, **kwargs) :
+ # parent
+ super(CallbackEvent, self).__init__(base, fd, events)
+
+ # store
+ self.callback = callback
+ self.args = args
+ self.kwargs = kwargs
+
+ def __call__ (self, lib.evutil_socket_t fd, short mask) :
+ self.callback(fd, mask, *self.args, **self.kwargs)
+
--- a/qmsk/net/socket/address.pxd Mon Aug 31 22:17:54 2009 +0300
+++ b/qmsk/net/socket/address.pxd Tue Sep 01 00:04:26 2009 +0300
@@ -111,5 +111,3 @@
# our defining attributes, set via __init__
cdef public object hostname, service
- cpdef getaddrinfo (self, int family, int socktype, int protocol = ?, int flags = ?)
-
--- a/qmsk/net/socket/address.pyx Mon Aug 31 22:17:54 2009 +0300
+++ b/qmsk/net/socket/address.pyx Tue Sep 01 00:04:26 2009 +0300
@@ -221,6 +221,78 @@
return ai
+def getaddrinfo (hostname, service, int family, int socktype, int protocol = 0, int flags = 0) :
+ """
+ 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)
+ 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
+ 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...
+ cdef platform.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 platform.addrinfo *res, *r
+ cdef int err
+ cdef object ret = []
+
+ cdef char *_hostname = NULL
+ cdef char *_service = NULL
+
+ if hostname is not None :
+ _hostname = hostname
+
+ if service is not None :
+ _service = service
+
+ # operate!
+ err = platform.c_getaddrinfo(_hostname, _service, &hints, &res)
+
+ if err :
+ # XXX: raise a GAIError
+ raise Exception(platform.gai_strerror(err))
+
+ try :
+ # gather results from linked list to PyList
+ r = res
+
+ while r :
+ ret.append(build_addrinfo(r))
+
+ r = r.ai_next
+
+ # ok
+ return ret
+
+ finally :
+ platform.c_freeaddrinfo(res)
+
+
+
cdef class endpoint :
def __init__ (self, hostname=None, service=None) :
@@ -234,76 +306,15 @@
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 = platform.AI_PASSIVE) :
- """
- Look up our hostname/service using the given socket parameters, and return a sequence of addrinfo objects.
+ self.hostname = hostname
+ self.service = service
- 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.
-
+ def getaddrinfo (self, int family, int socktype, int protocol = 0, int flags = platform.AI_PASSIVE) :
"""
-
- # XXX: Cython doesn't support proper compound value literals...
- cdef platform.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 platform.addrinfo *res, *r
- cdef int err
- cdef object ret = []
-
- cdef char *hostname = NULL
- cdef char *service = NULL
+ See getaddrinfo().
+ """
- if self.hostname is not None :
- hostname = self.hostname
-
- if self.service is not None :
- service = self.service
-
- # operate!
- err = platform.c_getaddrinfo(hostname, service, &hints, &res)
-
- if err :
- # XXX: raise a GAIError
- raise Exception(platform.gai_strerror(err))
-
- try :
- # gather results from linked list to PyList
- r = res
-
- while r :
- ret.append(build_addrinfo(r))
-
- r = r.ai_next
-
- # ok
- return ret
-
- finally :
- platform.c_freeaddrinfo(res)
+ return getaddrinfo(self.hostname, self.service, family, socktype, protocol, flags)
def __str__ (self) :
return "hostname=%s, service=%s" % (self.hostname, self.service)