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