Author: ArcRiley
Date: 2009-01-07 00:07:27 -0500 (Wed, 07 Jan 2009)
New Revision: 1431

Modified:
   trunk/concordance/src/Core.c
   trunk/concordance/src/Core.h
Log:
 * added new buffered channel send functionality (via conCore_sessionSend)
 * started new depth+state switch/if system for XML handling


Modified: trunk/concordance/src/Core.c
===================================================================
--- trunk/concordance/src/Core.c        2009-01-07 05:04:56 UTC (rev 1430)
+++ trunk/concordance/src/Core.c        2009-01-07 05:07:27 UTC (rev 1431)
@@ -25,7 +25,8 @@
 static gpointer   conCore_loop          (gpointer);
 static int        conCore_listenChannel (conCoreObject*, conChannel*);
 static gboolean   conCore_listenNew     (GIOChannel*, GIOCondition, gpointer);
-static gboolean   conCore_sessionData   (GIOChannel*, GIOCondition, gpointer);
+static gboolean   conCore_sessionRead   (GIOChannel*, GIOCondition, gpointer);
+static gboolean   conCore_sessionWrite  (GIOChannel*, GIOCondition, gpointer);
 static void       conCore_xmlStart      (gpointer, const XML_Char*,
                                          const XML_Char**);
 static void       conCore_xmlEnd        (gpointer, const XML_Char*);
@@ -313,6 +314,61 @@
   }
 
 
+  static void
+  conCore_sessionSend(conSession* session, gchar* str, gint len) {        /*\
+    cdef :                                                                \*/
+      gint sent;
+
+    /* make sure the session write buffer is empty first */
+    if (session->buff->len == 0) {
+      /* send as much data as the channel will take
+
+         GIOStatus      g_io_channel_write_chars (GIOChannel *channel,
+                                                  const gchar *buf,
+                                                  gssize count,
+                                                  gsize *bytes_written,
+                                                  GError **error);
+      */
+      g_io_channel_write_chars(session->chan, str, len, &sent, NULL);
+
+
+      if (len != sent) {
+        /* append unsent string to the session write buffer
+
+           GString*     g_string_append_len      (GString *string,
+                                                  const gchar *val,
+                                                  gssize len);
+        */
+        session->buff = g_string_append_len(session->buff, str+sent, len-sent);
+
+        /* add a watch to send more when the channel is ready for it
+
+           gint         conAddWatch              (GIOChannel* channel,
+                                                  GIOCondition condition,
+                                                  GSourceFunc callback,
+                                                  gpointer data,
+                                                  GMainContext* context)
+        */
+        conAddWatch(session->chan, G_IO_OUT, (GSourceFunc)conCore_sessionWrite,
+                    (gpointer) session->core, session->core->context);
+      }
+    }
+    else
+      /* There is already data waiting to be sent, buffer this directly
+         and let the existing watch send it when ready
+
+         see above for g_string_append_len prototype
+      */
+      session->buff = g_string_append_len(session->buff, str, len);
+  }
+
+  /*
+  #
+  ###########################################################################
+  #
+  # Channel Callbacks
+  #                                                                        */  
+
   static gboolean
   conCore_listenNew(GIOChannel* sourceChannel, GIOCondition condition,
                     gpointer s) {                                         /*\
@@ -369,16 +425,24 @@
                                                   gboolean buffered);
       */
       newSession->chan = conAddSocket(fd, G_IO_IN | G_IO_HUP,
-                                      (GSourceFunc)conCore_sessionData,
+                                      (GSourceFunc)conCore_sessionRead,
                                       (gpointer) self, self->context);
       g_io_channel_set_encoding(newSession->chan, NULL, NULL);
       g_io_channel_set_buffered(newSession->chan, FALSE);
 
 
-      /* initialize channel mode to 0 */
-      newSession->mode = 0;
+      /* initialize session write buffer
 
+         GString*       g_string_new             (const gchar *init);
+      */
+      newSession->buff = g_string_new("");
 
+
+      /* initialize session state */
+      newSession->state = CON_E_NONE;
+      newSession->depth = 0;
+
+
       /* create the XML parser for this session
 
          XML_Parser     XML_ParserCreate         (const XML_Char *encoding);
@@ -405,7 +469,6 @@
                                                   gpointer value);
       */
       g_hash_table_insert(self->channels, newSession->chan, newSession);
-      newSession->depth = 0; /*temporary*/
       printf("new client: %s\n", newSession->host);
     }
     else
@@ -417,7 +480,7 @@
 
 
   static gboolean
-  conCore_sessionData(GIOChannel* channel, GIOCondition condition,
+  conCore_sessionRead(GIOChannel* channel, GIOCondition condition,
                       gpointer s) {                                       /*\
     cdef :                                                                \*/
       conCoreObject*        self = (conCoreObject*) s;
@@ -477,12 +540,59 @@
   }
 
 
+  static gboolean
+  conCore_sessionWrite(GIOChannel* channel, GIOCondition condition,
+                       gpointer s) {                                      /*\
+    cdef :                                                                \*/
+      conCoreObject*        self = (conCoreObject*) s;
+      conSession*           session;
+      gint                  sent;
+
+    /* get session from hashtable
+
+       gpointer         g_hash_table_lookup      (GHashTable *hash_table,
+                                                  gconstpointer key);
+    */
+    session = g_hash_table_lookup(self->channels, channel);
+    
+    /* send as much data as the channel will take
+
+       GIOStatus        g_io_channel_write_chars (GIOChannel *channel,
+                                                  const gchar *buf,
+                                                  gssize count,
+                                                  gsize *bytes_written,
+                                                  GError **error);
+    */
+    g_io_channel_write_chars(channel, session->buff->str,
+                             session->buff->len, &sent, NULL);
+
+    /* erase what we've just written
+
+       GString*         g_string_erase           (GString *string,
+                                                  gssize pos,
+                                                  gssize len);
+    */
+    session->buff = g_string_erase(session->buff, 0, sent); 
+
+    /* keep this event alive only if there's more in the buffer to write */
+    return (session->buff->len != 0);
+  }
+
+
+  /*
+  #
+  ###########################################################################
+  #
+  # XML Callbacks
+  #                                                                        */  
   static void
   conCore_xmlStart(gpointer s, const XML_Char* name,
                    const XML_Char** atts) {                               /*\
     cdef :                                                                \*/
       conSession*           session = (conSession*) s;
       conCoreObject*        self = session->core;
+      gchar*                buff;
+      gint                  blen;
       gint                  i;
 
     /* this from http://www.xml.com/pub/a/1999/09/expat/index.html?page=2 */
@@ -493,24 +603,31 @@
     for (i = 0; atts[i]; i += 2)
       printf(" %s='%s'", atts[i], atts[i + 1]);
     printf(">\n");
-    session->depth++;
 
-    if (strcmp(name, "stream:stream")==0) {
-      /* write stream:stream tags
+    switch (session->depth) {
+      case 0 : {
+        /* only stream element is valid at depth == 0 */
+        if (strcmp(name, "stream") == 0 || strcmp(name, "stream:stream") == 0) 
{
+          /* write stream:stream tags
 
-         GIOStatus      g_io_channel_write_chars (GIOChannel *channel,
-                                                  const gchar *buf,
-                                                  gssize count,
-                                                  gsize *bytes_written,
-                                                  GError **error);
-      */
-      g_io_channel_write_chars(session->chan,
-                               "<?xml version='1.0' encoding=\"UTF-8\"?>",
-                               38, &i, NULL);
-      g_io_channel_write_chars(session->chan,
-                               "<stream:stream from=\"selket.apogean.org\" 
id=\"1\" xmlns:stream=\"http://etherx.jabber.org/streams\"; 
xmlns=\"jabber:client\">",
-                               118, &i, NULL);
+             int        asprintf                 (char **strp,
+                                                  const char *fmt,
+                                                  ...);
+          */
+          blen = asprintf(&buff,
+                          "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                          "<stream:stream from=\"%s\" id=\"%s\""
+                          " xmlns:stream=\"http://etherx.jabber.org/streams\"";
+                          " xmlns=\"jabber:client\">",
+                          "selket.apogean.org",
+                          "1");
+          conCore_sessionSend(session, buff, blen);
+          free(buff);
+        }
+        /* should disconnect here, something other than session was sent */
+      }
     }
+    session->depth++;
   }
 
 
@@ -543,6 +660,12 @@
     g_free(strn);
   }
 
+  /*
+  #
+  ###########################################################################
+  #
+  # Class Methods and Type
+  #                                                                        */  
 
   static PyMethodDef conCore_methods[] = {
     { NULL, NULL },
@@ -593,3 +716,6 @@
     0,                                 /*tp_free*/
     0,                                 /*tp_is_gc*/
   };
+  /*
+  #
+  #########################################################################*/

Modified: trunk/concordance/src/Core.h
===================================================================
--- trunk/concordance/src/Core.h        2009-01-07 05:04:56 UTC (rev 1430)
+++ trunk/concordance/src/Core.h        2009-01-07 05:07:27 UTC (rev 1431)
@@ -43,6 +43,7 @@
   int          sock;
 } conChannel;
 
+
 typedef struct {
   PyObject_HEAD
   conChannel       c2s;                /* xmpp-client listening port */
@@ -53,23 +54,28 @@
   GThread*         thread;             /* thread ID for mainloop thread */
 } conCoreObject;
 
+
 enum conSessionState {
-  CON_MODE_TLS     = 1,                /* TLS is enabled */
-  CON_MODE_STREAM  = 2,                /* stream:stream is received */
+  CON_E_NONE,                       /* new session     */
+  CON_E_STREAM,                     /* <stream:stream> */
+  CON_E_STREAM_PRESENCE,            /*   <presence>    */
+  CON_E_STREAM_MESSAGE,             /*   <message>     */
+  CON_E_STREAM_IQ,                  /*   <iq>          */
 };
 
+
 typedef struct {
   PyObject*        self;               /* Session object for this or NULL */
   conCoreObject*   core;               /* Core this session belongs to */
   GIOChannel*      chan;               /* Glib IO channel for this session */
   XML_Parser       pars;               /* expat parser for this session */
   gchar            host[256];          /* verified hostname or NULL */
-  guint            mode;               /* current session state */
-  gint             depth;              /* temporary */
+  GString*         buff;               /* write buffer */
+  gboolean         tls;                /* flag for whether tls is enabled */
+  gint             state;              /* current session state */
+  gint             depth;              /* parser element depth */
 } conSession;
 
-
-
 PyTypeObject conCore_Type;
 
 #define conCoreObject_Check(v)  (Py_TYPE(v) == &conCore_Type)

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

Reply via email to