add CallbackEvent helper, and move getaddrinfo from endpoint into its own function
authorTero Marttila <terom@fixme.fi>
Tue, 01 Sep 2009 00:04:26 +0300
changeset 46 64b4ffb44754
parent 44 01ac7755b15a
child 47 b45a6648931c
add CallbackEvent helper, and move getaddrinfo from endpoint into its own function
qmsk/net/lib/event2/event.pyx
qmsk/net/socket/address.pxd
qmsk/net/socket/address.pyx
--- 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)