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