# HG changeset patch # User Nicolas Cornu # Date 1279038623 -7200 # Node ID d803c882a1825b454731ef17d0bcdf092f0b14f7 # Parent 0a13062d0a1118c4d1c7de59ca082fbc2ae3baf7 Fix the ack handlers. diff -r 0a13062d0a11 -r d803c882a182 jingle/CMakeLists.txt --- a/jingle/CMakeLists.txt Tue Jul 13 17:14:57 2010 +0200 +++ b/jingle/CMakeLists.txt Tue Jul 13 18:30:23 2010 +0200 @@ -1,4 +1,4 @@ -add_library(jingle MODULE jingle.c jingle.h check.c check.h action-handlers.c action-handlers.c register.c register.h sessions.c sessions.h send.c send.h general-handlers.c general-handlers.h) +add_library(jingle MODULE jingle.c jingle.h check.c check.h action-handlers.c action-handlers.c register.c register.h sessions.c sessions.h send.c send.h) set_target_properties(jingle PROPERTIES COMPILE_FLAGS "") include_directories(${LM_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}) target_link_libraries(jingle ${LM_LIBRARIES}) diff -r 0a13062d0a11 -r d803c882a182 jingle/action-handlers.c --- a/jingle/action-handlers.c Tue Jul 13 17:14:57 2010 +0200 +++ b/jingle/action-handlers.c Tue Jul 13 18:30:23 2010 +0200 @@ -33,10 +33,11 @@ #include #include #include -#include + extern LmMessageHandler* jingle_ack_iq_handler; + void handle_content_accept(JingleNode *jn) { GError *err = NULL; @@ -55,7 +56,7 @@ return; } - /* it's better if there is at least one content elem */ + // it's better if there is at least one content elem if (g_slist_length(jn->content) < 1) { jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL); return; @@ -88,7 +89,6 @@ JingleNode accept, reject; JingleContent tmp_cn; LmMessage *r; - ack_iq *elem; if (!check_contents(jn, &err)) { scr_log_print(LPRINT_DEBUG, "jingle: One of the content element was invalid (%s)", @@ -97,13 +97,11 @@ return; } - /* it's better if there is at least one content elem */ if (g_slist_length(jn->content) < 1) { jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL); return; } - - // if a session with the same sid doesn't already exists + if ((sess = session_find(jn)) == NULL) { jingle_send_iq_error(jn->message, "cancel", "item-not-found", "unknown-session"); return; @@ -145,28 +143,32 @@ } if (g_slist_length(accept.content) != 0) { + JingleAckHandle *ackhandle = g_new0(JingleAckHandle, 1); r = lm_message_from_jinglenode(&accept, lm_message_get_from(jn->message)); if (r) { - elem->id = g_strdup(lm_message_get_id(r)); - elem->callback = NULL; - elem->udata = NULL; - add_ack_wait(elem); - // TODO: errors - lm_connection_send_with_reply(lconnection, r, jingle_ack_iq_handler, &err); + ackhandle->callback = NULL; + ackhandle->user_data = NULL; + lm_connection_send_with_reply(lconnection, r, + jingle_new_ack_handler(ackhandle), &err); lm_message_unref(r); + if (err != NULL) { + // TODO + } } } if (g_slist_length(reject.content) != 0) { + JingleAckHandle *ackhandle = g_new0(JingleAckHandle, 1); r = lm_message_from_jinglenode(&reject, lm_message_get_from(jn->message)); if (r) { - elem->id = g_strdup(lm_message_get_id(r)); - elem->callback = NULL; - elem->udata = NULL; - add_ack_wait(elem); - // TODO: errors - lm_connection_send_with_reply(lconnection, r, jingle_ack_iq_handler, &err); + ackhandle->callback = NULL; + ackhandle->user_data = NULL; + lm_connection_send_with_reply(lconnection, r, + jingle_new_ack_handler(ackhandle), &err); lm_message_unref(r); + if (err != NULL) { + // TODO + } } } } @@ -189,13 +191,11 @@ return; } - /* it's better if there is at least one content elem */ if (g_slist_length(jn->content) < 1) { jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL); return; } - - // if a session with the same sid doesn't already exists + if ((sess = session_find(jn)) == NULL) { jingle_send_iq_error(jn->message, "cancel", "item-not-found", "unknown-session"); return; @@ -263,7 +263,7 @@ GSList *child = NULL; LmMessage *r; - // Make sure the from are an user in our roster + // Make sure the request come from an user in our roster if (!roster_find(jidtodisp(lm_message_get_from(jn->message)), jidsearch, 0)) { jingle_send_session_terminate(jn, "decline"); jingle_free_jinglenode(jn); diff -r 0a13062d0a11 -r d803c882a182 jingle/general-handlers.c --- a/jingle/general-handlers.c Tue Jul 13 17:14:57 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * general-handlers.c - * - * Copyrigth (C) 2010 Nicolas Cornu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include - -#include -#include -#include - -#include -#include - -GSList *ack_wait = NULL; - -extern LmMessageHandler* jingle_ack_iq_handler; -gboolean evscallback_jingle(guint evcontext, const gchar *arg, - gpointer userdata) -{ - JingleNode *jn = userdata; - - // Demande à mcKael l'utilité de ce truc - /* - if (G_UNLIKELY(!jn)) { - scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); - return FALSE; - } - */ - - if (evcontext == EVS_CONTEXT_TIMEOUT) { - scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s timed out, cancelled.", - jn->initiator); - jingle_free_jinglenode(jn); - return FALSE; - } - if (evcontext = EVS_CONTEXT_CANCEL) { - scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.", - jn->initiator); - jingle_free_jinglenode(jn); - return FALSE; - } - if (!(evcontext == EVS_CONTEXT_ACCEPT || evcontext == EVS_CONTEXT_REJECT)) { - jingle_free_jinglenode(jn); - return FALSE; - } - - if (evcontext == EVS_CONTEXT_ACCEPT) { - jingle_send_session_accept(jn); - } else { - jingle_send_session_terminate(jn, "decline"); - jingle_free_jinglenode(jn); - } - - return FALSE; -} - -LmHandlerResult jingle_handle_ack_iq (LmMessageHandler *handler, - LmConnection *connection, - LmMessage *message, gpointer user_data) -{ - GSList *child; - const gchar *id = lm_message_get_id(message); - ack_iq *ai; - for (child = ack_wait; child; child = child->next) { - ai = (ack_iq*)child->data; - if(!g_strcmp0(ai->id, id)) { - g_free(ai->id); - if(ai->callback != NULL) - ai->callback(message, ai->udata); - ack_wait = g_slist_remove(ack_wait, child); - return LM_HANDLER_RESULT_REMOVE_MESSAGE; - } - } - return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS; -} - -void add_ack_wait(ack_iq *elem) -{ - ack_wait = g_slist_append(ack_wait, elem); -} diff -r 0a13062d0a11 -r d803c882a182 jingle/general-handlers.h --- a/jingle/general-handlers.h Tue Jul 13 17:14:57 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -#ifndef __JINGLE_GENERAL_HANDLERS_H__ -#define __JINGLE_GENERAL_HANDLERS_H__ 1 - -typedef void (*jingle_func_ack_iq) (LmMessage*, void*); - -typedef struct { - gchar *id; - jingle_func_ack_iq callback; - void *udata; -} ack_iq; - -gboolean evscallback_jingle(guint evcontext, const gchar *arg, - gpointer userdata); -LmHandlerResult jingle_handle_ack_iq (LmMessageHandler *handler, - LmConnection *connection, - LmMessage *message, gpointer user_data); -void add_ack_wait(ack_iq *elem); -#endif diff -r 0a13062d0a11 -r d803c882a182 jingle/jingle.c --- a/jingle/jingle.c Tue Jul 13 17:14:57 2010 +0200 +++ b/jingle/jingle.c Tue Jul 13 18:30:23 2010 +0200 @@ -29,13 +29,14 @@ #include #include #include +#include #include #include #include #include #include -#include + static void jingle_register_lm_handlers(void); static void jingle_unregister_lm_handlers(void); @@ -49,7 +50,7 @@ static LmMessageHandler* jingle_iq_handler = NULL; -LmMessageHandler* jingle_ack_iq_handler = NULL; +static GSList *ack_handlers = NULL; static guint connect_hid = 0; static guint disconn_hid = 0; @@ -134,6 +135,78 @@ } /** + * Handle incoming ack iq (type result or error). + */ +LmHandlerResult jingle_handle_ack_iq(LmMessageHandler *handler, + LmConnection *connection, + LmMessage *message, gpointer user_data) +{ + ack_handlers = g_slist_remove(ack_handlers, handler); + lm_message_handler_unref(handler); + + // TODO: check subtype + if (user_data != NULL) { + JingleAckHandle *ah = user_data; + if(ah->callback != NULL) + ah->callback(message, ah->user_data); + + g_free(ah); + } + + return LM_HANDLER_RESULT_REMOVE_MESSAGE; +} + +LmMessageHandler *jingle_new_ack_handler(JingleAckHandle *ah) +{ + LmMessageHandler *h = lm_message_handler_new(jingle_handle_ack_iq, + (gpointer) ah, NULL); + ack_handlers = g_slist_append(ack_handlers, h); + return h; +} + +/** + * mcabber /event callback. + */ +gboolean evscallback_jingle(guint evcontext, const gchar *arg, + gpointer userdata) +{ + JingleNode *jn = userdata; + + /* + if (G_UNLIKELY(!jn)) { + scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); + return FALSE; + } + */ + + if (evcontext == EVS_CONTEXT_TIMEOUT) { + scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s timed out, cancelled.", + jn->initiator); + jingle_free_jinglenode(jn); + return FALSE; + } + if (evcontext = EVS_CONTEXT_CANCEL) { + scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.", + jn->initiator); + jingle_free_jinglenode(jn); + return FALSE; + } + if (!(evcontext == EVS_CONTEXT_ACCEPT || evcontext == EVS_CONTEXT_REJECT)) { + jingle_free_jinglenode(jn); + return FALSE; + } + + if (evcontext == EVS_CONTEXT_ACCEPT) { + jingle_send_session_accept(jn); + } else { + jingle_send_session_terminate(jn, "decline"); + jingle_free_jinglenode(jn); + } + + return FALSE; +} + +/** * According to the specifications: * "An entity that receives an IQ request of type "get" or "set" MUST * reply with an IQ response of type "result" or "error"." @@ -183,15 +256,9 @@ void jingle_send_iq_error(LmMessage *m, const gchar *errtype, const gchar *cond, const gchar *jinglecond) { - ack_iq *elem; LmMessage *r = jingle_new_iq_error(m, errtype, cond, jinglecond); if (r) { - elem->id = g_strdup(lm_message_get_id(r)); - elem->callback = NULL; - elem->udata = NULL; - add_ack_wait(elem); - lm_connection_send_with_reply(lconnection, r, jingle_ack_iq_handler, NULL); - lm_message_unref(r); + lm_connection_send(lconnection, r, NULL); } } @@ -251,8 +318,6 @@ static void jingle_init(void) { jingle_iq_handler = lm_message_handler_new(jingle_handle_iq, NULL, NULL); - jingle_ack_iq_handler = lm_message_handler_new(jingle_handle_ack_iq, NULL, - NULL); xmpp_add_feature(NS_JINGLE); connect_hid = hk_add_handler(jingle_connect_hh, HOOK_POST_CONNECT, @@ -272,8 +337,6 @@ lm_message_handler_invalidate(jingle_iq_handler); lm_message_handler_unref(jingle_iq_handler); - lm_message_handler_invalidate(jingle_ack_iq_handler); - lm_message_handler_unref(jingle_ack_iq_handler); } LmMessage *lm_message_from_jinglenode(const JingleNode *jn, const gchar *to) diff -r 0a13062d0a11 -r d803c882a182 jingle/jingle.h --- a/jingle/jingle.h Tue Jul 13 17:14:57 2010 +0200 +++ b/jingle/jingle.h Tue Jul 13 18:30:23 2010 +0200 @@ -107,12 +107,32 @@ void (*handler)(JingleNode *); }; +typedef void (*JingleAckCallback) (LmMessage *, gpointer *); + +typedef struct { + JingleAckCallback callback; + gpointer *user_data; +} JingleAckHandle; + + +LmHandlerResult jingle_handle_ack_iq(LmMessageHandler *handler, + LmConnection *connection, + LmMessage *message, gpointer user_data); +LmMessageHandler *jingle_new_ack_handler(JingleAckHandle *ri); LmMessage *jingle_new_iq_error(LmMessage *m, const gchar *errtype, const gchar *cond, const gchar *jinglecond); void jingle_send_iq_error(LmMessage *m, const gchar *errtype, const gchar *cond, const gchar *jinglecond); + void jingle_ack_iq(LmMessage *m); + +LmMessage *lm_message_from_jinglenode(const JingleNode *jn, const gchar *to); +void jingle_free_jinglenode(JingleNode *jn); + JingleAction jingle_action_from_str(const gchar* string); -LmMessage *lm_message_from_jinglenode(const JingleNode *jn, const gchar *to); + +gboolean evscallback_jingle(guint evcontext, const gchar *arg, + gpointer userdata); + #endif diff -r 0a13062d0a11 -r d803c882a182 jingle/send.c --- a/jingle/send.c Tue Jul 13 17:14:57 2010 +0200 +++ b/jingle/send.c Tue Jul 13 18:30:23 2010 +0200 @@ -28,21 +28,20 @@ #include #include #include -#include -extern LmMessageHandler* jingle_ack_iq_handler; void jingle_send_session_terminate(JingleNode *jn, const gchar *reason) { LmMessage *r; LmMessageNode *err; JingleNode *reply = g_new0(JingleNode, 1); - ack_iq *elem; + JingleAckHandle *ackhandle; reply->action = JINGLE_SESSION_TERMINATE; reply->sid = jn->sid; r = lm_message_from_jinglenode(reply, lm_message_get_from(jn->message)); + if (r == NULL) return; if (reason != NULL) { // TODO check reason @@ -50,15 +49,13 @@ lm_message_node_add_child(err, reason, NULL); } - if (r) { - elem->id = g_strdup(lm_message_get_id(r)); - elem->callback = NULL; - elem->udata = NULL; - add_ack_wait(elem); + ackhandle = g_new0(JingleAckHandle, 1); + ackhandle->callback = NULL; + ackhandle->user_data = NULL; - lm_connection_send_with_reply(lconnection, r, jingle_ack_iq_handler, NULL); - lm_message_unref(r); - } + lm_connection_send_with_reply(lconnection, r, + jingle_new_ack_handler(ackhandle), NULL); + lm_message_unref(r); } void jingle_send_session_accept(JingleNode *jn) @@ -72,7 +69,7 @@ gconstpointer description, transport; const gchar *xmlns; GError *err = NULL; - ack_iq *elem; + JingleAckHandle *ackhandle; accept.action = JINGLE_SESSION_ACCEPT; accept.responder = g_strdup_printf("%s/%s", @@ -114,12 +111,11 @@ accept.message = lm_message_from_jinglenode(&accept, lm_message_get_from(jn->message)); if (accept.message) { - elem->id = g_strdup(lm_message_get_id(accept.message)); - elem->callback = NULL; - elem->udata = NULL; - add_ack_wait(elem); + ackhandle = g_new0(JingleAckHandle, 1); + ackhandle->callback = NULL; + ackhandle->user_data = NULL; lm_connection_send_with_reply(lconnection, accept.message, - jingle_ack_iq_handler, &err); + jingle_new_ack_handler(ackhandle), NULL); lm_message_unref(accept.message); } }