Author: ArcRiley
Date: 2009-01-08 15:16:43 -0500 (Thu, 08 Jan 2009)
New Revision: 1445

Modified:
   trunk/concordance/src/Core.c
Log:
 * now recompiles <iq/> <message/> & <presence/> tags for routing or callback
 * fixed switch statements (forgot to break; at the end of each case)


Modified: trunk/concordance/src/Core.c
===================================================================
--- trunk/concordance/src/Core.c        2009-01-08 20:14:53 UTC (rev 1444)
+++ trunk/concordance/src/Core.c        2009-01-08 20:16:43 UTC (rev 1445)
@@ -256,30 +256,42 @@
     ret = getaddrinfo(sock->addr, NULL, NULL, &resinfo);
     if (ret != 0) {
       switch (ret) {
-        case EAI_AGAIN :
+        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 :
+          break;
+        }
+        case EAI_FAIL : {
           /* EAI_FAIL
               The name server returned a permanent failure indication. */
           PyErr_SetString(PyExc_OSError, "permanent dns failure");
-        case EAI_FAMILY :
+          break;
+        }
+        case EAI_FAMILY : {
           /* EAI_FAMILY
               The requested address family is not supported. */
           PyErr_SetString(PyExc_OSError, "address family not supported");
-        case EAI_MEMORY :
+          break;
+        }
+        case EAI_MEMORY : {
           /* EAI_MEMORY
               Out of memory. */
           PyErr_SetString(PyExc_MemoryError, "out of memory on getaddrinfo");
-        case EAI_NODATA :
+          break;
+        }
+        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 :
+          break;
+        }
+        default : {
           PyErr_SetString(PyExc_AttributeError, "invalid address/hostname");
+          break;
+        }
       }
       return FALSE;
     }
@@ -463,12 +475,14 @@
       g_io_channel_set_buffered(newSession->chan, FALSE);
 
 
-      /* initialize session write and element buffers
+      /* initialize session strings
 
          GString*       g_string_new             (const gchar *init);
       */
-      newSession->wbuff = g_string_new("");
-      newSession->ebuff = g_string_new("");
+      newSession->wbuff = g_string_new("");      /* write buffer */
+      newSession->ebuff = g_string_new("");      /* element buffer */
+      newSession->efrom = g_string_new("");      /* element origin */
+      newSession->eto   = g_string_new("");      /* element destination */
 
       /* initialize session state */
       newSession->state = CON_E_OPEN;
@@ -624,34 +638,8 @@
   # Element responses
   #                                                                        */
   static void
-  conCore_saslFailure(conSession* session, gchar* failure) {              /*\
+  conCore_reply_stream(conSession* session) {                             /*\
     cdef :                                                                \*/
-      GString* buff;
-    /* printf failure to a GString, then send it
-
-       GString*         g_string_new             (const gchar *init);
-       void             g_string_printf          (GString *string,
-                                                  const gchar *format,
-                                                  ...);
-       gchar*           g_string_free            (GString *string,
-                                                  gboolean free_segment);
-    */
-    buff = g_string_new("");
-    g_string_printf(buff, "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
-                          "%s</failure>", failure);
-    conCore_sessionSend(session, buff->str, buff->len);
-    g_string_free(buff, TRUE);
-  }
-
-  /*
-  #
-  ###########################################################################
-  #
-  # Element handlers
-  #                                                                        */
-  static void
-  conCore_stream(conSession* session) {                                   /*\
-    cdef :                                                                \*/
       conCoreObject*        self = session->core;
       GString*              buff;
 
@@ -667,13 +655,13 @@
                                                   const gchar *format,
                                                   ...);
     */
-    g_string_printf(buff, "<?xml version='1.0' encoding='UTF-8'?>"
-                          "<stream:stream xmlns='jabber:client'"
-                          " xmlns:stream='http://etherx.jabber.org/streams'"
-                          " from='%s' id='%s'>"
-                          "<stream:features><mechanisms"
-                          " xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>",
-                          "selket.apogean.org", "concordance-1");
+    g_string_printf(buff,
+                    "<?xml version='1.0' encoding='UTF-8'?>"
+                    "<stream:stream xmlns='jabber:client'"
+                    " xmlns:stream='http://etherx.jabber.org/streams'"
+                    " from='%s' id='%s'><stream:features><mechanisms"
+                    " xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>",
+                    "selket.apogean.org", "concordance-1");
 
     /* add a <mechanism> element for each supported SASL mechanism
 
@@ -701,27 +689,98 @@
 
 
   static void
-  conCore_saslChallenge(conSession* session) {                            /*\
+  conCore_reply_streamError(conSession* session, gchar* err, gchar* txt) {/*\
     cdef :                                                                \*/
+      GString*              buff;
+
+    /* initialize response buffer
+
+       GString*         g_string_new             (const gchar *init);
+    */
+    buff = g_string_new("");
+
+    /* printf error and send it
+
+       void             g_string_printf          (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+    */
+    g_string_printf(buff,
+                    "<stream:error><%s"
+                    " xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>"
+                    "<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'>"
+                    "%s</text></stream:error></stream:stream>",
+                    err, txt);
+    conCore_sessionSend(session, buff->str, buff->len);
+
+    /* CLOSE the session state so the socket will close properly */
+    session->state = CON_E_CLOSE;
+
+    /* free response buffer before returning
+
+       gchar*           g_string_free            (GString *string,
+                                                  gboolean free_segment);
+    */
+    g_string_free(buff, TRUE);
+  }
+
+
+  static void
+  conCore_reply_saslChallenge(conSession* session) {                      /*\
+    cdef :                                                                \*/
       conCoreObject*        self = session->core;
 
-    
-    return; /* unfinished */
-    /* gchar*           g_base64_encode          (const guchar *data,
+
+    return;
+    /*
+       gchar*           g_base64_encode          (const guchar *data,
                                                   gsize len);
     */
 
 
+
     /*g_string_printf(buff,
                     "<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
                     "%s</challenge>", ""); */
   }
 
+  static void
+  conCore_reply_saslFailure(conSession* session, gchar* failure) {        /*\
+    cdef :                                                                \*/
+      GString* buff;
+    /* printf failure to a GString, then send it
 
+       GString*         g_string_new             (const gchar *init);
+       void             g_string_printf          (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+       gchar*           g_string_free            (GString *string,
+                                                  gboolean free_segment);
+    */
+    buff = g_string_new("");
+    g_string_printf(buff, "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
+                          "%s</failure>", failure);
+    conCore_sessionSend(session, buff->str, buff->len);
+    g_string_free(buff, TRUE);
+  }
+
   /*
   #
   ###########################################################################
   #
+  # Python Handles
+  #                                                                        */
+  static void
+  conCore_handle_client(conSession* session) {                            /*\
+    cdef :                                                                \*/
+      GString* buff;
+    printf("------ client callback: \"%s\"\n", session->ebuff->str);
+  }
+
+  /*
+  #
+  ###########################################################################
+  #
   # XML Callbacks
   #                                                                        */
   static void
@@ -751,22 +810,73 @@
     printf(">\n");
 
     switch (session->depth) {
-      case 0 :
+      /* match element by depth, namespace, and finally element name
+
+         gint           g_ascii_strcasecmp       (const gchar* str1,
+                                                  const gchar* str2);
+         Returns -1, 0 or 1, if str1 is <, == or > than str2.
+      */
+      case 0 : {
         /* only stream:stream element is valid at depth == 0
 
            if anything else is sent, session->state will be changed from
            CON_E_OPEN to CON_E_CLOSE and the session will be cleanly closed
            in the conCore_sessionRead just after the XMLParse call (above).
         */
-        if (strcmp(name, "http://etherx.jabber.org/streams stream") == 0)
+        if (g_ascii_strcasecmp(name,
+                               "http://etherx.jabber.org/streams stream") == 0)
           /* need to test version and other important attributes */
-          conCore_stream(session);
+          conCore_reply_stream(session);
         else
           session->state = CON_E_CLOSE;
+        break;
+      }
 
       case 1 : {
-        if (strcmp(element[0], "urn:ietf:params:xml:ns:xmpp-sasl") == 0) {
-          if (strcmp(element[1], "auth") == 0) {
+        if (g_ascii_strcasecmp(element[0], "jabber:client") == 0) {
+          /* ensure it's a valid element for the jabber:client namespace
+
+             see http://xmpp.org/rfcs/rfc3920.html#def
+          */
+          if (g_ascii_strcasecmp(element[1], "iq") == 0 ||
+              g_ascii_strcasecmp(element[1], "message") == 0 ||
+              g_ascii_strcasecmp(element[1], "presence") == 0) {
+            /* set the client mode */
+            session->state = CON_E_CLIENT;
+
+            /* copy "from" and "to" attributes, will verify in conCore_xmlEnd
+
+               GString* g_string_assign          (GString *string,
+                                                  const gchar *rval);
+            */
+            session->eto = g_string_assign(session->eto,
+                                           conSearchAttributes(atts, "to"));
+            session->efrom = g_string_assign(session->efrom,
+                                           conSearchAttributes(atts, "from"));
+
+
+            /* copy element and attributes to ebuff
+
+               void     g_string_printf          (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+               void     g_string_append_printf   (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+            */
+            g_string_printf(session->ebuff, "<%s", element[1]);
+            for (i = 0; atts[i]; i += 2)
+              g_string_append_printf(session->ebuff, " %s='%s'",
+                                     atts[i], atts[i+1]);
+            g_string_append_printf(session->ebuff, ">");
+          }
+          else
+            conCore_reply_streamError(session, "invalid-xml", "invalid element"
+                                      "for jabber:client namespace");
+        }
+        if (g_ascii_strcasecmp(element[0],
+                               "urn:ietf:params:xml:ns:xmpp-sasl") == 0) {
+          if (g_ascii_strcasecmp(element[1], "auth") == 0) {
             const gchar* mech = conSearchAttributes(atts, "mechanism");
             if (gsasl_server_support_p(self->saslCntx, mech)) {
               /* initiate server session
@@ -780,19 +890,35 @@
               session->state = CON_E_SASL;
             }
             else {
-              conCore_saslFailure(session, "<invalid-mechanism/>");
+              conCore_reply_saslFailure(session, "<invalid-mechanism/>");
               session->state = CON_E_CLOSE;
             }
           }
 
           /* remaining: response, abort */
         }
-
+        
         /* other depth=1 namespaces */
+        break;
       }
 
       default : {
         /* process inner tags depending on state */
+        if (session->state == CON_E_CLIENT) {
+          /* copy element and attributes to ebuff
+
+             void       g_string_append_printf   (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+          */
+          g_string_append_printf(session->ebuff, "<%s xmlns='%s'", 
+                                 element[1], element[0]);
+          for (i = 0; atts[i]; i += 2)
+            g_string_append_printf(session->ebuff, " %s='%s'",
+                                   atts[i], atts[i+1]);
+          g_string_append_printf(session->ebuff, ">");
+        }
+        break;
       }
     }
 
@@ -818,6 +944,7 @@
     /* decrease XML depth */
     session->depth--;
 
+
     /* split name by namespace and element
 
     gchar**             g_strsplit               (const gchar *string,
@@ -826,25 +953,60 @@
     */
     element = g_strsplit(name, " ", 2);
 
-    if (session->depth == 1) {
-      switch (session->state) {
-        case CON_E_SASL :
-          conCore_saslChallenge(session);
+    for (i = 0; i < session->depth; i++)
+      printf("  ");
+    printf("</%s>\n", element[1]);
+
+    switch (session->depth) {
+      case 0 : {
+        /* close session when </stream:stream> is sent */
+        session->state = CON_E_CLOSE;
+        break;
       }
+      case 1 : {
+        switch (session->state) {
+          case CON_E_CLIENT : {
+            /* copy final element close to ebuff
 
-      /* reset the element chardata buffer when returning to stream depth
+               void     g_string_append_printf   (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+            */
+            g_string_append_printf(session->ebuff, "</%s>", element[1]);
+            conCore_handle_client(session);
+            break;
+          }
+          case CON_E_SASL : {
+            conCore_reply_saslChallenge(session);
+            break;
+          }
+        }
 
-         GString*       g_string_assign          (GString *string,
+        /* reset the element strings when returning to depth 1
+
+           GString*     g_string_assign          (GString *string,
                                                   const gchar *rval);
-      */
-      session->ebuff = g_string_assign(session->ebuff, "");
+        */
+        session->ebuff = g_string_assign(session->ebuff, "");
+        session->efrom = g_string_assign(session->efrom, "");
+        session->eto   = g_string_assign(session->eto,   "");
+
+        break;
+      }
+      default : {
+        if (session->state == CON_E_CLIENT) {
+          /* copy element close to ebuff
+
+             void       g_string_append_printf   (GString *string,
+                                                  const gchar *format,
+                                                  ...);
+          */
+          g_string_append_printf(session->ebuff, "</%s>", element[1]);
+        }
+        break;
+      }
     }
-    
 
-    for (i = 0; i < session->depth; i++)
-      printf("  ");
-    printf("</%s>\n", element[1]);
-
     /* free the element string array before returning
 
        void             g_strfreev               (gchar **str_array);
@@ -861,24 +1023,24 @@
       gint                  i;
       gchar*                strn;
 
-    /* This is used repeatedly in the following code
-
-       GString*         g_string_append_len      (GString *string,
-                                                  const gchar *val,
-                                                  gssize len);
-    */
-    switch (session->state) {
-      case CON_E_SASL :
-        /* append Base64 (p)response data to element buffer */
-        session->ebuff = g_string_append_len(session->ebuff, str, str_len);
-    }
-
+    /* output to stdout for debugging */
     strn = g_strndup(str, str_len);
     for (i = 0; i < session->depth; i++)
       printf("  ");
     printf("\"%s\"\n", strn);
     g_free(strn);
 
+    if (session->state == CON_E_OPEN)
+      /* character data should be ignored at the stream level */
+      return;
+ 
+    /* append character data to element buffer
+
+       GString*         g_string_append_len      (GString *string,
+                                                  const gchar *val,
+                                                  gssize len);
+    */
+    session->ebuff = g_string_append_len(session->ebuff, str, str_len);
   }
 
   /*

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

Reply via email to