Author: ArcRiley
Date: 2009-02-25 04:55:19 -0500 (Wed, 25 Feb 2009)
New Revision: 1518

Modified:
   trunk/concordance/include/concordance.sockets.h
   trunk/concordance/src/sockets/Client.c
   trunk/concordance/src/sockets/Socket.c
   trunk/concordance/src/sockets/__init__.c
   trunk/concordance/src/utils.c
Log:
is now handling basic replies, segfaults on valid stream version

Modified: trunk/concordance/include/concordance.sockets.h
===================================================================
--- trunk/concordance/include/concordance.sockets.h     2009-02-25 09:55:15 UTC 
(rev 1517)
+++ trunk/concordance/include/concordance.sockets.h     2009-02-25 09:55:19 UTC 
(rev 1518)
@@ -24,6 +24,10 @@
 
 #include "concordance.h"
 
+typedef struct {
+  PyObject*             _core;
+  Gsasl*                saslCntx;
+} sockets_State;
 
 /* concordance.sockets.Socket definition */
 typedef struct {
@@ -35,6 +39,7 @@
   PyObject_HEAD
   PyObject*             module;        /* reference to our own module */
   GMainContext*         context;       /* Concordance's Glib context */
+  Gsasl*                saslCntx;      /* Concordance's SASL context */
   const gchar*          addr;
   gushort               port;
   int                   sock;
@@ -44,32 +49,15 @@
 
 /* concordance.sockets.Client definition */
 typedef struct {
-  PyTypeObject          base;
-  gboolean           (* _gioNew )      (GIOChannel*, GIOCondition, gpointer);
-  gboolean           (* _gioRead )     (GIOChannel*, GIOCondition, gpointer);
-  gboolean           (* _gioWrite )    (GIOChannel*, GIOCondition, gpointer);
-  
-} socketsClient_TypeObject;
-extern socketsClient_TypeObject  socketsClient_Type;
-typedef struct {
   PyObject_HEAD
   PyObject*             module;        /* reference to our own module */
   GMainContext*         context;       /* Concordance's Glib context */
+  Gsasl*                saslCntx;      /* Concordance's SASL context */
   const gchar*          addr;
   gushort               port;
   int                   sock;
   GIOChannel*           chan;
 } socketsClient_Object;
-
-
-enum socketsClient_State {
-  CONCORD_E_CLOSE = 0,              /* close </stream>           */
-  CONCORD_E_OPEN,                   /* inside <stream>           */
-  CONCORD_E_CLIENT,                 /* <iq> <message> <presence> */
-  CONCORD_E_SASL,                   /* <auth> <response>         */
-};
-
-
 typedef struct {
   socketsClient_Object* self;          /* the listening socket this belongs */
   PyObject*             node;          /* Node object for this or NULL */
@@ -87,5 +75,21 @@
   GString*              efrom;         /* JID of origin */
   GString*              eto;           /* JID of destination */
 } socketsClient_Data;
+typedef struct {
+  PyTypeObject          base;
+  gboolean           (* _gioNew )      (GIOChannel*, GIOCondition, gpointer);
+  gboolean           (* _gioRead )     (GIOChannel*, GIOCondition, gpointer);
+  gboolean           (* _gioWrite )    (GIOChannel*, GIOCondition, gpointer);
+  void               (* _gioSend )     (socketsClient_Data, gchar*, gint);
+} socketsClient_TypeObject;
+extern socketsClient_TypeObject  socketsClient_Type;
 
+
+enum socketsClient_State {
+  CONCORD_E_CLOSE = 0,              /* close </stream>           */
+  CONCORD_E_OPEN,                   /* inside <stream>           */
+  CONCORD_E_CLIENT,                 /* <iq> <message> <presence> */
+  CONCORD_E_SASL,                   /* <auth> <response>         */
+};
+
 #endif

Modified: trunk/concordance/src/sockets/Client.c
===================================================================
--- trunk/concordance/src/sockets/Client.c      2009-02-25 09:55:15 UTC (rev 
1517)
+++ trunk/concordance/src/sockets/Client.c      2009-02-25 09:55:19 UTC (rev 
1518)
@@ -21,6 +21,10 @@
 
 #include "concordance.sockets.h"
 
+static void _xmlStart   (gpointer, const XML_Char*, const XML_Char**);
+static void _xmlEnd     (gpointer, const XML_Char*);
+static void _xmlCharData(gpointer data, const XML_Char* str, gint str_len);
+
                                                                           /*\
 cdef class Socket :                                                       \*/
   static char socketsClient_Doc[] = "Test";
@@ -89,7 +93,7 @@
     */
     source = g_io_create_watch(session->chan, G_IO_IN | G_IO_HUP);
     g_source_set_callback(source, (GSourceFunc)
-                          ((socketsClient_TypeObject*) self->base->ob_type)->
+                          ((socketsClient_TypeObject*) self->ob_base.ob_type)->
                           _gioRead,
                           (gpointer) session, NULL);
     g_source_attach(source, self->context);
@@ -231,6 +235,68 @@
     return (session->wbuff->len != 0);
   }
 
+  static void
+  _gioSend(socketsClient_Data* session, gchar* str, gint len) {           /*\
+    cdef :                                                                \*/
+      socketsClient_Object*  self = session->self;
+      guint                  sent;
+      GSource*               source;      
+
+    /* make sure the session write buffer is empty first */
+    if (session->wbuff->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->wbuff = g_string_append_len(session->wbuff,
+                                             str+sent, len-sent);
+        /* add a channel to our context watch
+
+           Note that this function 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(session->chan, G_IO_OUT);
+        g_source_set_callback(source, (GSourceFunc)
+                              ((socketsClient_TypeObject*)
+                               self->ob_base.ob_type)->
+                              _gioWrite,
+                              (gpointer) session, NULL);
+        g_source_attach(source, self->context);
+        g_source_unref(source);
+      }
+    }
+    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->wbuff = g_string_append_len(session->wbuff, str, len);
+  }
+
   /*
   #
   ###########################################################################
@@ -260,7 +326,7 @@
                     "<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'>"
                     "%s</text></stream:error></stream:stream>",
                     err, t);
-    _send(session, buff->str, buff->len);
+    _gioSend(session, buff->str, buff->len);
 
     /* CLOSE the session state so the socket will close properly */
     session->state = CONCORD_E_CLOSE;
@@ -275,7 +341,7 @@
 
 
   static void
-  _reply_stream(concordSession_Data* session, gchar* version) {           /*\
+  _reply_stream(socketsClient_Data* session, gchar* version) {            /*\
     cdef :                                                                \*/
       socketsClient_Object* self = session->self;
       GString*              buff;
@@ -321,7 +387,7 @@
          * error is "<bad-format/>"
     */
     if (version == NULL) {
-      *error = "<unsupported-version/>";
+      error = "<unsupported-version/>";
       buff = g_string_append(buff, ">");
     }
     else if (g_strrstr(version, ".") != NULL) {
@@ -335,14 +401,14 @@
           
         }
         else {
-          *error = "<unsupported-version/>";
+          error = "<unsupported-version/>";
           buff = g_string_append(buff, " version='1.0'>");
         }
       }
       g_strfreev(versions);
     }
     else {
-      *error = "<bad-format/>";
+      error = "<bad-format/>";
       buff = g_string_append(buff, " version='1.0'>");
     }
 
@@ -350,9 +416,9 @@
       /* a stream error has taken place!
 
          send the <stream:stream> element we have so far, free the buffer,
-         then pass control over concordSession_reply_streamError for the rest.
+         then pass control over _reply_streamError for the rest.
       */
-      _send(session, buff->str, buff->len);
+      _gioSend(session, buff->str, buff->len);
       g_string_free(buff, TRUE);
       _reply_streamError(session, error, "");
       return;
@@ -369,14 +435,14 @@
        GString*         g_string_append          (GString *string,
                                                   const gchar *val);
     */
-    if (gsasl_server_support_p(core->saslCntx, "DIGEST-MD5"))
+    if (gsasl_server_support_p(self->saslCntx, "DIGEST-MD5"))
       buff = g_string_append(buff, "<mechanism>DIGEST-MD5</mechanism>");
-    if (gsasl_server_support_p(core->saslCntx, "PLAIN"))
+    if (gsasl_server_support_p(self->saslCntx, "PLAIN"))
       buff = g_string_append(buff, "<mechanism>PLAIN</mechanism>");
 
     /* close <mechanisms> and <stream:features>, then send buffer */
     buff = g_string_append(buff, "</mechanisms></stream:features>");
-    _send(session, buff->str, buff->len);
+    _gioSend(session, buff->str, buff->len);
 
     /* free response buffer before returning
 
@@ -388,7 +454,7 @@
 
 
   static void
-  _reply_saslChallenge(concordSession_Data* session) {                    /*\
+  _reply_saslChallenge(socketsClient_Data* session) {                     /*\
     cdef :                                                                \*/
 
 
@@ -422,7 +488,7 @@
     buff = g_string_new("");
     g_string_printf(buff, "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
                           "%s</failure>", failure);
-    concordSession_send(session, buff->str, buff->len);
+    _gioSend(session, buff->str, buff->len);
     g_string_free(buff, TRUE);
   }
 
@@ -431,34 +497,12 @@
   ###########################################################################
   #
   # XML Callbacks
-  #
-                                                                           */
-  static gchar*
-  _xmlFindAttr(const gchar** attrs, const gchar* key) {                   /*\
-    cdef :                                                                \*/
-      gint i;
-
-    for (i = 0; attrs[i]; i += 2) {
-      /* compare attribute strings case insensitive
-
-         gint           g_ascii_strcasecmp       (const gchar *s1,
-                                                  const gchar *s2);
-      */
-      if (g_ascii_strcasecmp(attrs[i], key) == 0)
-        break;
-    }
-
-    /* return either the found attribute value or NULL */
-    if (attrs[i])
-      return (gchar*) attrs[i+1];
-    else
-      return NULL;
-  }
-
+  #                                                                        */
   static void
   _xmlStart(gpointer data, const XML_Char* name, const XML_Char** atts) { /*\
     cdef :                                                                \*/
       socketsClient_Data*   session = (socketsClient_Data*) data;
+      socketsClient_Object* self = session->self;
       gchar**               element;
       gint                  i;
       gchar*                attr;
@@ -496,7 +540,7 @@
         */
         if (g_ascii_strcasecmp(name,
                                "http://etherx.jabber.org/streams stream") == 0)
-          _reply_stream(session, _xmlFindAttr(atts, "version"));
+          _reply_stream(session, concordFindAttr(atts, "version"));
         else
           session->state = CONCORD_E_CLOSE;
         break;
@@ -519,10 +563,10 @@
                GString* g_string_assign          (GString *string,
                                                   const gchar *rval);
             */
-            if (!(attr = _xmlFindAttr(atts, "to")))
+            if (!(attr = concordFindAttr(atts, "to")))
               attr = "";
             session->eto = g_string_assign(session->eto, attr);
-            if (!(attr = _xmlFindAttr(atts, "from")))
+            if (!(attr = concordFindAttr(atts, "from")))
               attr = "";
             session->efrom = g_string_assign(session->efrom, attr);
             printf("--------- from: %s to: %s\n",
@@ -551,8 +595,8 @@
         if (g_ascii_strcasecmp(element[0],
                                "urn:ietf:params:xml:ns:xmpp-sasl") == 0) {
           if (g_ascii_strcasecmp(element[1], "auth") == 0) {
-            gchar* mec = _xmlFindAttr(atts, "mechanism");
-            if (mec && gsasl_server_support_p(session->core->saslCntx, mec)) {
+            gchar* mec = concordFindAttr(atts, "mechanism");
+            if (mec && gsasl_server_support_p(self->saslCntx, mec)) {
               /* initiate server session
 
                  int    gsasl_server_start       (Gsasl* ctx,
@@ -560,8 +604,7 @@
                                                   Gsasl_session** sctx);
               */
               printf("------ init %s mechanism\n", mec);
-              gsasl_server_start(session->core->saslCntx, mec,
-                                 &session->sctx);
+              gsasl_server_start(self->saslCntx, mec, &session->sctx);
               session->state = CONCORD_E_SASL;
             }
             else {
@@ -609,9 +652,9 @@
 
 
   static void
-  concordSession_xmlEnd(gpointer data, const XML_Char* name) {            /*\
+  _xmlEnd(gpointer data, const XML_Char* name) {                          /*\
     cdef :                                                                \*/
-      concordSession_Data*  session = (concordSession_Data*) data;
+      socketsClient_Data*   session = (socketsClient_Data*) data;
       gchar**               element;
       gint                  i;
 
@@ -647,11 +690,11 @@
                                                   ...);
             */
             g_string_append_printf(session->ebuff, "</%s>", element[1]);
-            concordCore_queuePush(session->core, session);
+            // !!! concordCore_queuePush(session->core, session);
             break;
           }
           case CONCORD_E_SASL : {
-            concordSession_reply_saslChallenge(session);
+            _reply_saslChallenge(session);
             break;
           }
         }
@@ -690,10 +733,9 @@
 
 
   static void
-  concordSession_xmlCharData(gpointer data, const XML_Char* str,
-                             gint str_len) {                              /*\
+  _xmlCharData(gpointer data, const XML_Char* str, gint str_len) {        /*\
     cdef :                                                                \*/
-      concordSession_Data*  session = (concordSession_Data*) data;
+      socketsClient_Data*   session = (socketsClient_Data*) data;
       gint                  i;
       gchar*                strn;
 
@@ -825,4 +867,5 @@
     _gioNew,
     _gioRead,
     _gioWrite,
+    _gioSend,
   };

Modified: trunk/concordance/src/sockets/Socket.c
===================================================================
--- trunk/concordance/src/sockets/Socket.c      2009-02-25 09:55:15 UTC (rev 
1517)
+++ trunk/concordance/src/sockets/Socket.c      2009-02-25 09:55:19 UTC (rev 
1518)
@@ -246,7 +246,7 @@
   _new(PyTypeObject* type, PyObject* args, PyObject* kwds) {              /*\
     cdef :                                                                \*/
       socketsSocket_Object*      self;
-      PyObject*                  _core;
+      sockets_State*             state;
   
     /* this is lowest level, just alloc */
     self = (socketsSocket_Object*) type->tp_alloc(type, 0);
@@ -281,8 +281,10 @@
 
        void*            PyModule_GetState        (PyObject*);
     */
-    _core = *(PyObject**) PyModule_GetState(self->module);
-    self->context = ((concordGlobals*) PyModule_GetState(_core))->context;
+    state = (sockets_State*) PyModule_GetState(self->module);
+    self->context = ((concordGlobals*)
+                     PyModule_GetState(state->_core))->context;
+    self->saslCntx = state->saslCntx;
 
     /* return self */
     return (PyObject*) self;

Modified: trunk/concordance/src/sockets/__init__.c
===================================================================
--- trunk/concordance/src/sockets/__init__.c    2009-02-25 09:55:15 UTC (rev 
1517)
+++ trunk/concordance/src/sockets/__init__.c    2009-02-25 09:55:19 UTC (rev 
1518)
@@ -30,7 +30,7 @@
   PyModuleDef_HEAD_INIT,
   "sockets",                           /*m_name*/
   "Test Help",                         /*m_doc*/
-  sizeof(gpointer),                    /*m_size*/
+  sizeof(sockets_State),               /*m_size*/
   sockets_Methods,                     /*m_methods*/
   NULL,                                /*m_reload*/
   NULL,                                /*m_traverse*/
@@ -38,11 +38,14 @@
   NULL                                 /*m_free*/
 };
 
+
 PyMODINIT_FUNC
 PyInit_sockets(void) {                                                    /*\
   cdef :                                                                  \*/
-    gpointer            _core;
     PyObject*           module;
+    sockets_State*      state;
+    PyObject*           _core;
+    Gsasl*              saslCntx;
 
   /* Initialize Glib threading support
 
@@ -70,11 +73,21 @@
   if (PyType_Ready((PyTypeObject*) &socketsClient_Type) < 0)
     return NULL;
 
+  /* initialize gsasl context
+
+     int                gsasl_init               (Gsasl** ctx)
+     Return value: GSASL_OK if successful, otherwise GSASL_MALLOC_ERROR.
+  */
+  if (gsasl_init(&saslCntx) != GSASL_OK) {
+    PyErr_SetString(PyExc_MemoryError, "out of memory on gsasl_init");
+    return NULL;
+  }
+
   /* Get a handle to _core or fail
 
      PyObject*          PyImport_ImportModule    (const char *name);
   */
-  if (!(_core = (gpointer) PyImport_ImportModule("concordance._core")))
+  if (!(_core = PyImport_ImportModule("concordance._core")))
     return NULL;
 
   /* Create concordance module object
@@ -83,11 +96,13 @@
   */
   module = PyModule_Create(&sockets_Module);
 
-  /* Record _core in module state so we can decref during garbage collection
+  /* Record _core and saslCntx in module state
 
      void*              PyModule_GetState        (PyObject*);
   */
-  *(gpointer*) PyModule_GetState(module) = _core;
+  state = (sockets_State*) PyModule_GetState(module);
+  state->_core = _core;
+  state->saslCntx = saslCntx;  
 
   /* incref each extension type */
   Py_INCREF(&socketsSocket_Type);

Modified: trunk/concordance/src/utils.c
===================================================================
--- trunk/concordance/src/utils.c       2009-02-25 09:55:15 UTC (rev 1517)
+++ trunk/concordance/src/utils.c       2009-02-25 09:55:19 UTC (rev 1518)
@@ -19,9 +19,32 @@
 # $Id$
 */
 
-#include "utils.h"
+#include "concordance.h"
 
 gchar*
+concordFindAttr(const gchar** attrs, const gchar* key) {                   /*\
+  cdef :                                                                   \*/
+    gint i;
+
+  for (i = 0; attrs[i]; i += 2) {
+    /* compare attribute strings case insensitive
+
+        gint            g_ascii_strcasecmp       (const gchar *s1,
+                                                  const gchar *s2);
+    */
+    if (g_ascii_strcasecmp(attrs[i], key) == 0)
+      break;
+  }
+
+  /* return either the found attribute value or NULL */
+  if (attrs[i])
+    return (gchar*) attrs[i+1];
+  else
+    return NULL;
+}
+
+
+gchar*
 concordPyUnicodeToUTF8(PyObject* unicode) {                               /*\
   cdef :                                                                  \*/
     PY_UNICODE_TYPE* uni;

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

Reply via email to