Author: ArcRiley
Date: 2009-01-04 00:03:50 -0500 (Sun, 04 Jan 2009)
New Revision: 1417

Modified:
   trunk/concordance/src/Core.c
   trunk/concordance/src/Core.h
Log:
Added basic GMainLoop functionality


Modified: trunk/concordance/src/Core.c
===================================================================
--- trunk/concordance/src/Core.c        2009-01-04 00:09:52 UTC (rev 1416)
+++ trunk/concordance/src/Core.c        2009-01-04 05:03:50 UTC (rev 1417)
@@ -26,7 +26,9 @@
 
 #include "Core.h"
 
-static int opensocket(conSocket sock);
+static gpointer   conCore_loop          (gpointer);
+static int        conCore_listenChannel (conCoreObject*, conSocket*);
+static gboolean   conCore_listenNew     (GIOChannel*, GIOCondition, gpointer);
                                                                           /*\ 
 cdef class Core :                                                         \*/
   static char conCore_Doc[] = "Test";
@@ -41,6 +43,8 @@
     if (self) {
       self->c2s.sock = -1;
       self->s2s.sock = -1;
+      self->context  = NULL;
+      self->mainloop = NULL;
     }
     return (PyObject*) self;
   }
@@ -110,31 +114,39 @@
                                      &self->c2s.addr, &self->c2s.port, 
                                      &self->s2s.addr, &self->s2s.port))
       return -1;
-    
-    /* open the listening sockets (self->c2s->sock and self->s2s->sock)
 
-       Note that these default to -1 and remain -1 on failure, the dealloc
-       function uses this (if != -1) to close open all sockets.
+    /* We use a non-default context to avoid conflict with other glib-based 
+       Python packages which may have their own GMainLoop in other threads.
 
-       opensocket (see below) will set the Python error message on failure.
+       GMainContext*    g_main_context_new       (void);
     */
-    if (!opensocket(self->c2s))
+    self->context = g_main_context_new();
+
+    /* open the listening channels
+
+       Note that the sockets default to -1 and remain -1 on failure, the 
+       dealloc function uses this (if != -1) to close open all sockets.
+
+       listenchannel (see below) will set the Python error message on failure.
+    */
+    if (!conCore_listenChannel(self, &self->c2s))
       return -1;
-    if (!opensocket(self->s2s))
+    if (!conCore_listenChannel(self, &self->s2s))
       return -1;
 
-/*
-#ifdef MS_WINDOWS
-    sock.chan = g_io_channel_win32_new_socket(sock.sock);
-#else
-    sock.chan = g_io_channel_unix_new(sock.sock);
-#endif
-    g_io_add_watch(sock.chan, G_IO_IN, callback, NULL);
-*/
+    /* launch GMainLoop thread before returning
 
+       GThread*    g_thread_create     (GThreadFunc func,
+                                        gpointer data,
+                                        gboolean joinable,
+                                        GError **error);
+    */
+    self->thread = g_thread_create((GThreadFunc) conCore_loop,
+                                   (gpointer) self, 0, NULL);
     return 0;
   }
 
+
   static void
   conCore_dealloc(conCoreObject* self) {                                  /*\
     cdef :                                                                \*/
@@ -146,10 +158,166 @@
     PyObject_Del(self);
   }
 
+
+  static gpointer
+  conCore_loop(gpointer s) {                                              /*\
+    cdef :                                                                \*/
+      conCoreObject*    self = (conCoreObject*) s;
+    /* create and run the GMainLoop, terminates thread on g_main_loop_quit()
+
+       GMainLoop*  g_main_loop_new     (GMainContext *context,
+                                        gboolean is_running);
+       void        g_main_loop_run     (GMainLoop *loop);
+    */
+    self->mainloop = g_main_loop_new(self->context, 0);
+    g_main_loop_run(self->mainloop);
+    return NULL;
+  }
+
+
+  static int 
+  conCore_listenChannel(conCoreObject* self, conSocket* sock) {           /*\
+    cdef :                                                                \*/
+      int                ret;
+      struct addrinfo*   resinfo = NULL;
+      GSource*           source;
+
+    /* Get address family and struct
+
+       int getaddrinfo(const char *node, const char *service,
+                       const struct addrinfo *hints,
+                       struct addrinfo **res);
+       getaddrinfo() returns  0  if it succeeds, or non-zero on failure.
+    */
+    ret = getaddrinfo(sock->addr, NULL, NULL, &resinfo);
+    if (ret != 0) {
+      switch (ret) {
+        case EAI_AGAIN : 
+          /* EAI_AGAIN
+              The  name  server  returned a temporary failure indication.
+              Try again later. */
+          PyErr_SetString(PyExc_OSError, "temporary dns failure");
+        case EAI_FAIL : 
+          /* EAI_FAIL
+              The name server returned a permanent failure indication. */
+          PyErr_SetString(PyExc_OSError, "permanent dns failure");
+        case EAI_FAMILY :
+          /* EAI_FAMILY
+              The requested address family is not supported. */
+          PyErr_SetString(PyExc_OSError, "address family not supported");
+        case EAI_MEMORY :
+          /* EAI_MEMORY
+              Out of memory. */
+          PyErr_SetString(PyExc_MemoryError, "out of memory on getaddrinfo");
+        case EAI_NODATA :
+          /* EAI_NODATA
+              The specified network host exists, but does not have any
+              network addresses defined. */
+          PyErr_SetString(PyExc_AttributeError, "host lacks IP address");
+        default :
+          PyErr_SetString(PyExc_AttributeError, "invalid address/hostname");
+      }
+      return 0;
+    }
+
+    /* Copy port into sockaddr struct
+
+       uint16_t htons(uint16_t hostshort);
+         The htons() function converts the unsigned short integer hostshort 
+         from host byte order to network byte order.
+    */
+    ((struct sockaddr_in*) resinfo->ai_addr)->sin_port = htons(sock->port);
+
+    /* Open new socket of the appropriate family (AF_INET or AF_INET6)
+
+       int socket(int domain, int type, int protocol);
+    */
+    sock->sock = socket(resinfo->ai_family, SOCK_STREAM, 0);
+
+    /* If successful continue to bind/listen, else set error message */
+    if (sock->sock > -1) {
+      /* Bind and Listen to opened socket
+
+         int bind(int fd, const struct sockaddr *addr, 
+                  socklen_t addrlen);
+           On success, zero is returned.  On error, -1 is returned.
+
+         int listen(int fd, int backlog);
+           On  success,  zero is returned.  On error, -1 is returned.
+      */
+      if (bind(sock->sock, resinfo->ai_addr, resinfo->ai_addrlen) == 0 &&
+          listen(sock->sock, 16) == 0 ) {
+
+        /* create new channel using an OS-dependent function
+
+           GIOChannel*       g_io_channel_win32_new_fd     (gint fd);
+           GIOChannel*       g_io_channel_unix_new         (gint fd);
+        */
+        #ifdef MS_WINDOWS
+          sock->chan = g_io_channel_win32_new_socket(sock->sock);
+        #else
+          sock->chan = g_io_channel_unix_new(sock->sock);
+        #endif
+
+        /* add channel to our context watch
+
+           Note that this block is a replacement for g_io_add_watch() which
+           uses our own context rather than the default context.
+
+           GSource *    g_io_create_watch        (GIOChannel *channel,
+                                                  GIOCondition condition);
+           void         g_source_set_callback    (GSource *source,
+                                                  GSourceFunc func,
+                                                  gpointer data,
+                                                  GDestroyNotify notify);
+           guint        g_source_attach          (GSource *source,
+                                                  GMainContext *context);
+        */
+        source = g_io_create_watch (sock->chan, G_IO_IN);
+        g_source_set_callback(source, (GSourceFunc)conCore_listenNew,
+                              (gpointer) self, NULL);
+        g_source_attach(source, self->context);
+        ret = 1;
+      }
+      else {
+        PyErr_SetString(PyExc_OSError, "unable to bind listening socket");
+        ret = 0;
+      }
+    } 
+    else {
+      PyErr_SetString(PyExc_OSError, "unable to bind listening socket");
+      ret = 0;
+    }
+
+    /* before returning, free the previously created resinfo struct
+
+       void freeaddrinfo(struct addrinfo *res);
+    */
+    if (resinfo)
+      freeaddrinfo(resinfo);
+
+    return ret;
+  }
+
+
+  static gboolean
+  conCore_listenNew(GIOChannel* source, GIOCondition condition,
+                    gpointer s) {                                         /*\
+    cdef :                                                                \*/
+      conCoreObject*    self = (conCoreObject*) s;
+    if (source == self->s2s.chan)
+      printf("new server\n");
+    else
+      printf("new client\n");
+    return 1;
+  }
+
+
   static PyMethodDef conCore_methods[] = {
     { NULL, NULL },
   };
 
+
   PyTypeObject conCore_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "concordance.Core",                /*tp_name*/
@@ -194,99 +362,3 @@
     0,                                 /*tp_free*/
     0,                                 /*tp_is_gc*/
   };
-
-
-
-/***************************************************************************\
- * Core helper functions                                                   */
-
-static int opensocket(conSocket sock) {                                   /*\
-  cdef :                                                                  \*/
-    int                ret;
-    struct addrinfo*   resinfo = NULL;
-
-  /* Get address family and struct
-
-     int getaddrinfo(const char *node, const char *service,
-                     const struct addrinfo *hints,
-                     struct addrinfo **res);
-     getaddrinfo() returns  0  if it succeeds, or non-zero on failure.
-  */
-  ret = getaddrinfo(sock.addr, NULL, NULL, &resinfo);
-  if (ret != 0) {
-    switch (ret) {
-      case EAI_AGAIN : 
-        /* EAI_AGAIN
-            The  name  server  returned a temporary failure indication.
-            Try again later. */
-        PyErr_SetString(PyExc_OSError, "temporary dns failure");
-      case EAI_FAIL : 
-        /* EAI_FAIL
-            The name server returned a permanent failure indication. */
-        PyErr_SetString(PyExc_OSError, "permanent dns failure");
-      case EAI_FAMILY :
-        /* EAI_FAMILY
-            The requested address family is not supported. */
-        PyErr_SetString(PyExc_OSError, "address family not supported");
-      case EAI_MEMORY :
-        /* EAI_MEMORY
-            Out of memory. */
-        PyErr_SetString(PyExc_MemoryError, "out of memory on getaddrinfo");
-      case EAI_NODATA :
-        /* EAI_NODATA
-            The specified network host exists, but does not have any
-            network addresses defined. */
-        PyErr_SetString(PyExc_AttributeError, "host lacks IP address");
-      default :
-        PyErr_SetString(PyExc_AttributeError, "invalid address/hostname");
-    }
-    return 0;
-  }
-
-  /* Copy port into sockaddr struct
-
-     uint16_t htons(uint16_t hostshort);
-       The htons() function converts the unsigned short integer hostshort 
-       from host byte order to network byte order.
-  */
-  ((struct sockaddr_in*) resinfo->ai_addr)->sin_port = htons(sock.port);
-
-  /* Open new socket of the appropriate family (AF_INET or AF_INET6)
-
-     int socket(int domain, int type, int protocol);
-  */
-  sock.sock = socket(resinfo->ai_family, SOCK_STREAM, 0);
-
-  /* If successful continue to bind/listen, else set error message */
-  if (sock.sock > -1) {
-    /* Bind and Listen to opened socket
-
-       int bind(int sockfd, const struct sockaddr *addr, 
-                socklen_t addrlen);
-         On success, zero is returned.  On error, -1 is returned.
-
-       int listen(int sockfd, int backlog);
-         On  success,  zero is returned.  On error, -1 is returned.
-    */
-    if (bind(sock.sock, resinfo->ai_addr, resinfo->ai_addrlen) == 0 &&
-        listen(sock.sock, 16) == 0 )
-      ret = 1;
-    else {
-      PyErr_SetString(PyExc_OSError, "unable to bind listening socket");
-      ret = 0;
-    }
-  } 
-  else {
-    PyErr_SetString(PyExc_OSError, "unable to bind listening socket");
-    ret = 0;
-  }
-
-  /* before returning, free the previously created resinfo struct
-
-     void freeaddrinfo(struct addrinfo *res);
-  */
-  if (resinfo)
-    freeaddrinfo(resinfo);
-
-  return ret;
-}

Modified: trunk/concordance/src/Core.h
===================================================================
--- trunk/concordance/src/Core.h        2009-01-04 00:09:52 UTC (rev 1416)
+++ trunk/concordance/src/Core.h        2009-01-04 05:03:50 UTC (rev 1417)
@@ -31,8 +31,11 @@
 
 typedef struct {
   PyObject_HEAD
-  conSocket c2s;
-  conSocket s2s;
+  conSocket        c2s;
+  conSocket        s2s;
+  GThread*         thread;
+  GMainContext*    context;
+  GMainLoop*       mainloop;
 } conCoreObject;
 
 PyTypeObject conCore_Type;

_______________________________________________
PySoy-SVN mailing list
PySoy-SVN@pysoy.org
http://www.pysoy.org/mailman/listinfo/pysoy-svn

Reply via email to