[jdev] Flash Patch

Marcel Bootsma marcel.bootsma at logicacmg.com
Thu Dec 16 05:52:11 CST 2004


Hello Jabbers,

For our project we use a flash based client for Jabber 2.0
As most of you know this normally doesn't work because of
Flash not being 100% compatible with XML streams.

I did read the discussions about this topic (mainly in April)
And agree that using a patch in jaber is not the nicest solution
And a proxy would be much better...

But I never build a proxy and didn't have time to learn how to
Because it had to work fast (as always).

So, I just ported the old 1.4 patch into 2.0 and it worked within 
a couple of days (hey, I am knew to networking and Jabber)

You don't have to embed it into your code but its just for anyone 
who can use it.

Grt

Marcel

Here it is:

diff -Naur /home/jabber/jabberd-2.0s6.orig/c2s/c2s.c jabberd-2.0s6/c2s/c2s.c
--- /home/jabber/jabberd-2.0s6.orig/c2s/c2s.c	2004-12-15
11:03:08.000000000 +0100
+++ jabberd-2.0s6/c2s/c2s.c	2004-12-16 11:50:42.000000000 +0100
@@ -20,6 +20,67 @@
 
 #include "c2s.h"
 
+
+/*
+ * M.Bootsma, LogicaCMG Hoofddorp, Netherlands
+ * October 2004
+ *
+ * Added a patch for flash:stream support
+ *
+ * Flash is not 100% compatible with the XML stream standard:
+ * 1. it terminates every XML message with a '\0'
+ * 2. it terminates the stream header with a / 
+ *    (this would close the stream)
+ * 3. it starts the stream with a flash:stream header instead of
+ *    a stream:stream header.
+ *
+ * The patch checks the first message of a starting session stream
+ * for any '\0'. If found it flags the session as a Flash session
+ * and replases the complete header with a Jabber compatible
+ * header.
+ * After that every incomming message is filtered from '\0' which
+ * are substuted for ' '
+ * For every outgoing message a '\0' is appended and the response
+ * of the header is replaced for a flash friendly version
+ *
+ * The whole flash patch can be switch off undefining CP2005_FLASH_PATCH
+ * in config.h(.in)
+ */
+
+#ifdef CP2005_FLASH_PATCH
+
+#define FLASH_BUFFER_SIZE 256
+
+static const char caStreamHeader [] = "<?xml version='1.0'?><stream:stream
xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'
to='%s' >";
+static const char caFlashHeader []  = "<?xml version='1.0'?><flash:stream
xmlns:flash='http://www.jabber.com/streams/flash'
xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'
from='%s' id='%s' />";
+
+static void ExtractValue (char *pMessage, char *pVariable, char *pValue)
+{
+int iLen;
+char *p;
+char *pEnd;
+
+    /* 
+     * extract the value of an attribute from a XML message
+     * eg: <.... id='1234567890' ....> returns 1234567890
+     */
+
+    p = strstr (pMessage, pVariable); 
+    if (p != NULL) {
+        p += (strlen (pVariable) + 1);
+        /* find end of value, search for closing ' or " */
+        pEnd = strchr (p, p [-1]);    
+        iLen = pEnd - p;             
+        if (iLen < FLASH_BUFFER_SIZE) {
+            memcpy (pValue, p, iLen);
+            pValue [iLen] = '\0';
+            log_debug (ZONE, "++++ Extracted Var %s: [%s]\n", pVariable,
pValue);
+        }
+    }
+}
+#endif
+
+
 static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void
*arg) {
     sess_t sess = (sess_t) arg;
     sx_buf_t buf = (sx_buf_t) data;
@@ -28,6 +89,12 @@
     nad_t nad;
     char root[9];
 
+#ifdef CP2005_FLASH_PATCH
+    char *p, *pEnd;
+    char caHost [FLASH_BUFFER_SIZE];
+    char caID [FLASH_BUFFER_SIZE];
+#endif
+
     switch(e) {
         case event_WANT_READ:
             log_debug(ZONE, "want read");
@@ -94,15 +161,79 @@
                 return -1;
             }
 
-            log_debug(ZONE, "read %d bytes", len);
-
             buf->len = len;
 
+#ifdef CP2005_FLASH_PATCH
+             /* check for 0 bytes in the first packet
+             * if found it must be a flash client
+             * remove any 0 in the data and 
+             * the / that ends the <?xml... header
+             */
+
+            pEnd = &buf->data [len];
+
+            if (sess->s->state == state_NONE) { 
+                /* stream is new, look for 0 bytes */
+                p = strchr (buf->data, '\0');
+                if ((p != NULL) && (p < pEnd)) {
+                    log_debug (ZONE, "++++ Flash Stream detected\n%.*s",
buf->len, buf->data);
+
+                    sess->flash_client = 1; 
+                    /* extract destination host */
+                    ExtractValue (buf->data, "to=", caHost);
+                    /* create normal stream:stream header, resize data
buffer first */
+                    _sx_buffer_alloc_margin (buf, 0, sizeof
(caStreamHeader) + strlen (caHost) + 8);
+                    sprintf (buf->data, caStreamHeader, caHost);
+                    buf->len = strlen (buf->data);
+
+                    log_debug(ZONE, "++++ Converted to\n%.*s", buf->len,
buf->data);
+                }
+            } 
+
+            /*
+             * Check all other messages in the stream 
+             * to remove \0's etc
+             */
+            
+            if (sess->flash_client) {
+                /* remove 0's from flash packets */
+                for (p = buf->data; p < pEnd; p++) {
+                    if (*p == '\0') {
+                        *p = ' ';
+                    }
+                }
+            }
+#endif
+            log_debug(ZONE, "read %d bytes", len);
+
             return len;
 
         case event_WRITE:
             log_debug(ZONE, "writing to %d", sess->fd);
 
+#ifdef CP2005_FLASH_PATCH
+            if (sess->flash_client) {
+                /* look for the header <? xml ...*/
+                if (strncmp (buf->data, "<?xml ", 6) == 0) {
+                    /* replace normal stream header with flash friendly
header */
+                    log_debug(ZONE, "++++ Found <?xml..., \n%.*s",
buf->len, buf->data);
+
+                    /* extract id from id="123456567778765" or
id='45454545454' */
+                    ExtractValue (buf->data, "from=", caHost);
+                    ExtractValue (buf->data, "id=", caID);
+                    /* create flash:stream header, realloc buffer first */
+                    _sx_buffer_alloc_margin (buf, 0, sizeof (caFlashHeader)
+ strlen (caHost) + strlen (caID) + 8);
+                    sprintf (buf->data, caFlashHeader, caHost, caID);
+                    buf->len = strlen (buf->data);
+
+                    log_debug(ZONE, "++++ Converted to %s", buf->data);
+                }
+                /* add a 0 to flash packets */
+                buf->data [buf->len] = '\0';
+                buf->len++;
+            }
+#endif
+
             len = send(sess->fd, buf->data, buf->len, 0);
             if(len >= 0) {
                 log_debug(ZONE, "%d bytes written", len);
diff -Naur /home/jabber/jabberd-2.0s6.orig/c2s/c2s.h jabberd-2.0s6/c2s/c2s.h
--- /home/jabber/jabberd-2.0s6.orig/c2s/c2s.h	2004-12-15
11:03:08.000000000 +0100
+++ jabberd-2.0s6/c2s/c2s.h	2004-12-16 11:55:08.000000000 +0100
@@ -62,6 +64,10 @@
     int                 bound;
     int                 active;
 
+#ifdef CP2005_FLASH_PATCH
+    int                 flash_client;
+#endif
+
     nad_t               result;
 
     int                 sasl_authd;     /* 1 = they did a sasl auth */
 

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.



More information about the JDev mailing list