jingle/jingle.c
changeset 129 2d5c3efda92a
parent 126 059a6737f6a4
child 133 361d8577ebd1
--- a/jingle/jingle.c	Sun Aug 15 22:12:04 2010 +0200
+++ b/jingle/jingle.c	Mon Aug 16 02:04:50 2010 +0200
@@ -49,6 +49,7 @@
 
 static LmMessageHandler* jingle_iq_handler = NULL;
 static GSList *ack_handlers = NULL;
+static guint ack_timeout_checker = 0;
 static guint connect_hid = 0;
 static guint disconn_hid = 0;
 
@@ -144,27 +145,56 @@
                                      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);
+      ah->callback(JINGLE_ACK_RESPONSE, message, ah->user_data);
 
-    g_free(ah);
+    jingle_ack_handler_free(ah);
   }
 
   return LM_HANDLER_RESULT_REMOVE_MESSAGE;
 }
 
+gboolean jingle_ack_timeout_checker(gpointer user_data)
+{
+  GSList *el;
+  time_t now = time(NULL);
+  JingleAckHandle *ah;
+
+  for (el = ack_handlers; el; el = g_slist_next(el)) {
+	JingleAckHandle *ah = el->data;
+
+    if (ah->timeout == 0 || ah->_inserted + ah->timeout > now)
+	  continue;
+
+    if(ah->callback != NULL)
+      ah->callback(JINGLE_ACK_TIMEOUT, NULL, ah->user_data);
+
+    lm_message_handler_unref(ah->_handler);
+    jingle_ack_handler_free(ah);
+  }
+  return TRUE;
+}
+
 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;
+  if(ack_timeout_checker == 0)
+	  ack_timeout_checker = g_timeout_add_seconds(3, jingle_ack_timeout_checker, NULL);
+  
+  ah->_inserted = time(NULL);
+  ah->_handler = lm_message_handler_new(jingle_handle_ack_iq,
+                                        (gpointer) ah, NULL);
+  ack_handlers = g_slist_append(ack_handlers, ah);
+  return ah->_handler;
+}
+
+void jingle_ack_handler_free(JingleAckHandle *ah)
+{
+  lm_message_handler_unref(ah->_handler);
+  ack_handlers = g_slist_remove(ack_handlers, ah);
+  g_free(ah);
 }
 
 /**
@@ -382,6 +412,11 @@
 
   lm_message_handler_invalidate(jingle_iq_handler);
   lm_message_handler_unref(jingle_iq_handler);
+
+  if (ack_timeout_checker != 0) {
+    GSource *s = g_main_context_find_source_by_id(NULL, ack_timeout_checker);
+    g_source_destroy(s);
+  }
 }
 
 void handle_trans_data(const gchar *xmlns, gconstpointer data, const gchar *data2, guint len)