Fix the ack handlers.
authorNicolas Cornu <nicolas.cornu@ensi-bourges.fr>
Tue, 13 Jul 2010 18:30:23 +0200
changeset 52 d803c882a182
parent 51 0a13062d0a11
child 53 64a47491c068
Fix the ack handlers.
jingle/CMakeLists.txt
jingle/action-handlers.c
jingle/general-handlers.c
jingle/general-handlers.h
jingle/jingle.c
jingle/jingle.h
jingle/send.c
--- 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})
--- 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 <jingle/register.h>
 #include <jingle/send.h>
 #include <jingle/action-handlers.h>
-#include <jingle/general-handlers.h>
+
 
 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);
--- 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 <nicolas.cornu@ensi-bourges.fr>
- *
- * 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 <glib.h>
-
-#include <mcabber/events.h>
-#include <mcabber/logprint.h>
-#include <mcabber/xmpp_helper.h>
-
-#include <jingle/jingle.h>
-#include <jingle/general-handlers.h>
-
-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);
-}
--- 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
--- 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 <mcabber/modules.h>
 #include <mcabber/logprint.h>
 #include <mcabber/xmpp_helper.h>
+#include <mcabber/events.h>
 
 #include <jingle/jingle.h>
 #include <jingle/check.h>
 #include <jingle/action-handlers.h>
 #include <jingle/register.h>
 #include <jingle/send.h>
-#include <jingle/general-handlers.h>
+
 
 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)
--- 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
--- 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 <jingle/jingle.h>
 #include <jingle/sessions.h>
 #include <jingle/send.h>
-#include <jingle/general-handlers.h>
 
-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);
   }
 }