Change the way IBB work
authorNicolas Cornu <nicolas.cornu@ensi-bourges.fr>
Mon, 16 Aug 2010 18:33:33 +0200
changeset 133 361d8577ebd1
parent 132 4fef4ced1e97
child 134 8c98308c139d
Change the way IBB work
jingle-filetransfer/filetransfer.c
jingle-filetransfer/filetransfer.h
jingle-ibb/ibb.c
jingle/action-handlers.c
jingle/jingle.c
jingle/jingle.h
jingle/register.h
jingle/sessions.c
jingle/sessions.h
--- a/jingle-filetransfer/filetransfer.c	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle-filetransfer/filetransfer.c	Mon Aug 16 18:33:33 2010 +0200
@@ -59,12 +59,22 @@
 static void jingle_ft_uninit(void);
 // Return must be free
 static gchar *_convert_size(guint64 size);
+static int _next_index(void);
+static void _free(gconstpointer data);
 
 const gchar *deps[] = { "jingle", NULL };
 
 static GSList *info_list = NULL;
 static guint jft_cid = 0;
 
+const gchar* strstate[] = {
+  "PENDING",
+  "STARTING",
+  "ENDING",
+  "REJECT",
+  "ERROR"
+};
+
 static JingleAppFuncs funcs = {
   .check        = check,
   .handle       = handle,
@@ -122,7 +132,6 @@
   ft->name = (gchar *) lm_message_node_get_attribute(node, "name");
   sizestr  = lm_message_node_get_attribute(node, "size");
   ft->transmit = 0;
-  
   ft->dir = JINGLE_FT_INCOMING;
   
   if (!ft->name || !sizestr) {
@@ -169,6 +178,13 @@
   }
   ft->hash = g_strndup(ft->hash, 32);
 
+  {
+    JingleFTInfo *jfti = g_new0(JingleFTInfo, 1);
+    jfti->index = _next_index();
+    jfti->jft = ft;
+    info_list = g_slist_append(info_list, jfti);
+  }
+
   return (gconstpointer) ft;
 }
 
@@ -226,6 +242,7 @@
       g_error_free(err);
       return FALSE;
 	}
+	jft->state = JINGLE_FT_STARTING;
 	status = g_io_channel_set_encoding(jft->outfile, NULL, &err);
 	if (status != G_IO_STATUS_NORMAL || err != NULL) {
      scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s %s", err->message,
@@ -234,7 +251,9 @@
      return FALSE;
    }
   }
-
+  
+  jft->state = JINGLE_FT_STARTING;
+	
   status = g_io_channel_write_chars(jft->outfile, data, (gssize) len,
                                     &bytes_written, &err);
   if (status != G_IO_STATUS_NORMAL || err != NULL) {
@@ -261,7 +280,7 @@
 }
 
 
-static int _next_index()
+static int _next_index(void)
 {
   static int a = 0;
   return a++;
@@ -296,7 +315,7 @@
 	  }
 	  
 	  scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Trying to send %s",
-		            args[0]);
+		            args[1]);
 
 	  {
 		 JingleSession *sess;
@@ -330,6 +349,7 @@
 		 jft->date = fileinfo.st_mtime;
 		 jft->size = fileinfo.st_size;
 		 jft->transmit = 0;
+		 jft->state = JINGLE_FT_PENDING;
 		 jft->dir = JINGLE_FT_OUTGOING;
 		 jft->outfile = g_io_channel_new_file (filename, "r", &err);
 		 if (jft->outfile == NULL || err != NULL) {
@@ -370,21 +390,52 @@
       scr_LogPrint(LPRINT_LOGNORM, "JFT: no file");
 
     for (el = info_list; el; el = el->next) {
-      JingleFTInfo* jftio = el->data;
+      JingleFTInfo *jftio = el->data;
       gchar *strsize = _convert_size(jftio->jft->size);
-      scr_LogPrint(LPRINT_LOGNORM, "[%i]%s %s %s %.2f%%: %s", jftio->index, 
+      scr_LogPrint(LPRINT_LOGNORM, "[%i]%s %s %s %.2f%%: %s %s", jftio->index, 
                    (jftio->jft->dir == JINGLE_FT_INCOMING)?"<==":"-->",
                    jftio->jft->name, strsize,
                    (gfloat)jftio->jft->transmit/(gfloat)jftio->jft->size * 100,
-                   jftio->jft->desc);
+                   jftio->jft->desc?jftio->jft->desc:"",
+                   strstate[jftio->jft->state]);
       g_free(strsize);
     }
-  
+  } else if (!g_strcmp0(args[0], "flush")) {
+    GSList *el, *el2 = NULL;
+    int count = 0;
+    for (el = info_list; el; el = el -> next) {
+      JingleFTInfo *jftio = el->data;
+      if (jftio->jft->state == JINGLE_FT_ERROR ||
+          jftio->jft->state == JINGLE_FT_REJECT ||
+          jftio->jft->state == JINGLE_FT_ENDING) {
+        g_slist_free_1(el2);
+        count++;
+        _free(jftio->jft);
+        info_list = g_slist_remove(info_list, jftio);
+        el2 = el;
+      }
+    }
+    g_slist_free_1(el2);
+    scr_LogPrint(LPRINT_LOGNORM, "JFT: %i files removed", count);
+  } else {
+    scr_LogPrint(LPRINT_LOGNORM, "/jft: %s is not a correct option.", args[1]);
   }
   
   free_arg_lst(args);
 }
 
+static void _free(gconstpointer data)
+{
+  JingleFT *jft = (JingleFT *)data;
+  g_free(jft->hash);
+  g_free(jft->name);
+  g_free(jft->desc);
+  g_io_channel_unref(jft->outfile);
+  if (jft->dir == JINGLE_FT_INCOMING)
+    g_checksum_free(jft->md5);
+  g_free(jft);
+}
+
 static void tomessage(gconstpointer data, LmMessageNode *node)
 {
   JingleFT *jft = (JingleFT*) data;
@@ -424,7 +475,7 @@
   //if (jft->data != 0)
 }
 
-static void send_hash(gchar *sid, gchar *to, gchar *hash)
+static void send_hash(const gchar *sid, const gchar *to, const gchar *hash)
 {
   JingleAckHandle *ackhandle;
   GError *err = NULL;
@@ -540,7 +591,7 @@
   SessionContent *sc2 = session_find_sessioncontent(sess, sc->name);
 
   jft = (JingleFT*)sc2->description;
-  
+  jft->state = JINGLE_FT_STARTING;
   jft->md5 = g_checksum_new(G_CHECKSUM_MD5);
   
   scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: Transfer start (%s)",
@@ -556,14 +607,14 @@
   GError *err = NULL;
   GIOStatus status;
   
+  jft->state = JINGLE_FT_ENDING;
   if (jft->outfile != NULL) {
-    status = g_io_channel_flush(jft->outfile, &err);
+    status = g_io_channel_shutdown(jft->outfile, TRUE, &err);
     if (status != G_IO_STATUS_NORMAL || err != NULL) {
       scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: %s",
                    err->message);
       g_error_free(err);
     }
-    g_io_channel_unref(jft->outfile);
   }
 
   if (jft->hash != NULL && jft->md5 != NULL) {
@@ -578,9 +629,6 @@
     scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: transfer finished (%s)"
                  " but not verified", jft->name);
   }
-
-  g_checksum_free(jft->md5);
-
 }
 
 static gchar *_convert_size(guint64 size)
@@ -619,6 +667,7 @@
     compl_add_category_word(jft_cid, "send");
     //compl_add_category_word(jft_cid, "request");
     compl_add_category_word(jft_cid, "info");
+    compl_add_category_word(jft_cid, "flush");
   }
   /* Add command */
   cmd_add("jft", "Manage file transfer", jft_cid, 0, do_sendfile, NULL);
@@ -626,6 +675,7 @@
 
 static void jingle_ft_uninit(void)
 {
+  g_slist_free(info_list);
   xmpp_del_feature(NS_JINGLE_APP_FT);
   jingle_unregister_app(NS_JINGLE_APP_FT);
   cmd_del("file");
--- a/jingle-filetransfer/filetransfer.h	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle-filetransfer/filetransfer.h	Mon Aug 16 18:33:33 2010 +0200
@@ -15,6 +15,15 @@
   JINGLE_FT_INCOMING,
   JINGLE_FT_OUTGOING
 } JingleFTDirection;
+
+typedef enum {
+  JINGLE_FT_PENDING,
+  JINGLE_FT_STARTING,
+  JINGLE_FT_ENDING,
+  JINGLE_FT_REJECT,
+  JINGLE_FT_ERROR
+} JingleFTState;
+
 typedef struct {
   /* the last modification of the file, optional */
   time_t date;
@@ -40,6 +49,9 @@
   /* Is it if the file is incoming or outgoing */
   JingleFTDirection dir;
   
+  /* The state of the file (PENDING, STARTING, ...) */
+  JingleFTState state;
+  
   /* A little description of the transfer */
   gchar *desc;
   
--- a/jingle-ibb/ibb.c	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle-ibb/ibb.c	Mon Aug 16 18:33:33 2010 +0200
@@ -41,16 +41,16 @@
 static LmMessageHandler* jingle_ibb_handler = NULL;
 
 static gconstpointer check(JingleContent *cn, GError **err);
-static gboolean cmp(gconstpointer data1, gconstpointer data2);
 static void tomessage(gconstpointer data, LmMessageNode *node);
 static gconstpointer new(void);
 static void send(session_content *sc, gconstpointer data, gchar *buf, gsize size);
 static void init(session_content *sc, gconstpointer data);
 static void end(session_content *sc, gconstpointer data);
 static gchar *info(gconstpointer data);
+
 static void _send_internal(session_content *sc, const gchar *to, gchar *buf,
                            gsize size, const gchar *sid, gint64 *seq);
-
+                           
 static void jingle_ibb_init(void);
 static void jingle_ibb_uninit(void);
 
@@ -63,7 +63,6 @@
 static JingleTransportFuncs funcs = {
   .check     = check,
   .tomessage = tomessage,
-  .cmp       = cmp,
   .new       = new,
   .send      = send,
   .init      = init,
@@ -85,7 +84,6 @@
 /* Hash-Table of all emited JingleIBB struct */
 static GHashTable *JingleIBBs = NULL;
 
-
 static gconstpointer check(JingleContent *cn, GError **err)
 {
   JingleIBB *ibb = NULL;
@@ -128,7 +126,7 @@
                                  gpointer user_data)
 {
   const gchar *data64;
-  JingleIBB *jibb = g_new0(JingleIBB, 1);
+  JingleIBB *jibb = g_new0(JingleIBB, 1), *jibb2;
   gsize len;
   guchar *data;
   
@@ -144,7 +142,12 @@
 
   if (g_strcmp0(lm_message_node_get_attribute(dnode, "xmlns"),
                 NS_TRANSPORT_IBB))
-    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+
+  jibb2 = g_hash_table_lookup(JingleIBBs,
+                              lm_message_node_get_attribute(dnode, "sid"));
+  if (jibb2 == NULL)
+    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
 
   jingle_ack_iq(message);
   
@@ -154,21 +157,12 @@
   data64 = lm_message_node_get_value(dnode);
   
   data = g_base64_decode(data64, &len);
-  
-  handle_trans_data(NS_JINGLE_TRANSPORT_IBB, jibb, (const gchar *)data, (guint)len);
+
+  handle_trans_data(jibb2, (const gchar *)data, (guint)len);
   
   return LM_HANDLER_RESULT_REMOVE_MESSAGE;
 }
 
-
-static gboolean cmp(gconstpointer data1, gconstpointer data2)
-{
-  const JingleIBB *ibb1 = data1, *ibb2 = data2;
-  if(g_strcmp0(ibb1->sid, ibb2->sid))
-    return FALSE;
-  return TRUE;
-}
-
 static gchar *new_ibb_sid(void)
 {
   gchar *sid;
--- a/jingle/action-handlers.c	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle/action-handlers.c	Mon Aug 16 18:33:33 2010 +0200
@@ -105,6 +105,7 @@
   sess = session_new_from_jinglenode(jn);
   
   for (child = jn->content; child; child = child->next) {
+    SessionContent *sc;
     cn = (JingleContent *)(child->data);
     
     xmlns = lm_message_node_get_attribute(cn->description, "xmlns");
@@ -115,15 +116,15 @@
     transfuncs = jingle_get_transportfuncs(xmlns);
     if (transfuncs == NULL) continue;
     
-    description = appfuncs->check(cn, &err);
-    if (description == NULL || err != NULL) continue;
-    transport = transfuncs->check(cn, &err);
-    if (transport == NULL || err != NULL) continue;
-    
-    session_add_content_from_jinglecontent(sess, cn,
-                                           JINGLE_SESSION_STATE_PENDING);
+    sc = session_add_content_from_jinglecontent(sess, cn,
+                                                JINGLE_SESSION_STATE_PENDING,
+                                                &err);
+    if (err != NULL || sc == NULL) {
+      scr_LogPrint(LPRINT_LOGNORM, "Cannot add a content: %s", err->message);
+      g_error_free(err);
+    }
   }
-  
+
   if(g_slist_length(sess->content) == 0) {
     jingle_send_session_terminate(sess, "unsupported-applications");
     session_delete(sess);
--- a/jingle/jingle.c	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle/jingle.c	Mon Aug 16 18:33:33 2010 +0200
@@ -236,6 +236,7 @@
     scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.",
                  js->from);
     jingle_send_session_terminate(js, "decline");
+    
   }
 
   return FALSE;
@@ -419,9 +420,9 @@
   }
 }
 
-void handle_trans_data(const gchar *xmlns, gconstpointer data, const gchar *data2, guint len)
+void handle_trans_data(gconstpointer data, const gchar *data2, guint len)
 {
-  SessionContent *sc = session_find_transport(xmlns, data);
+  SessionContent *sc = session_find_transport(data);
   if (sc == NULL) {
     return;  
   }
--- a/jingle/jingle.h	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle/jingle.h	Mon Aug 16 18:33:33 2010 +0200
@@ -163,7 +163,7 @@
 gboolean evscallback_jingle(guint evcontext, const gchar *arg,
                             gpointer userdata);
                             
-void handle_trans_data(const gchar *xmlns, gconstpointer data, const gchar *data2, guint len);
+void handle_trans_data(gconstpointer data, const gchar *data2, guint len);
 
 gchar *jingle_generate_sid(void);
 
--- a/jingle/register.h	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle/register.h	Mon Aug 16 18:33:33 2010 +0200
@@ -45,7 +45,6 @@
 
 typedef gconstpointer (*JingleTransportCheck) (JingleContent *cn, GError **err);
 typedef void (*JingleTransportToMessage) (gconstpointer data, LmMessageNode *node);
-typedef gboolean (*JingleTransportCmp) (gconstpointer data1, gconstpointer data2);
 typedef gconstpointer (*JingleTransportNew) (void);
 typedef void (*JingleTransportSend) (session_content *sc, gconstpointer data, gchar *buf, gsize size);
 typedef void (*JingleTransportInit) (session_content *sc, gconstpointer data);
@@ -81,8 +80,6 @@
 
   JingleTransportToMessage tomessage;
 
-  JingleTransportCmp cmp;
-
   JingleTransportNew new;
 
   JingleTransportSend send;
--- a/jingle/sessions.c	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle/sessions.c	Mon Aug 16 18:33:33 2010 +0200
@@ -85,8 +85,8 @@
   return session_find_by_sid(jn->sid, from);
 }
 
-void session_add_content(JingleSession *sess, const gchar *name,
-                         SessionState state)
+SessionContent* session_add_content(JingleSession *sess, const gchar *name,
+                                    SessionState state)
 {
   SessionContent *sc = g_new0(SessionContent, 1);
   
@@ -94,6 +94,8 @@
   sc->state = state;
 
   sess->content = g_slist_append(sess->content, sc);
+  
+  return sc;
 }
 
 void session_add_app(JingleSession *sess, const gchar *name,
@@ -116,22 +118,48 @@
   sc->transport = data;
 }
 
-void session_add_content_from_jinglecontent(JingleSession *sess,
+SessionContent* session_add_content_from_jinglecontent(JingleSession *sess,
                                             JingleContent *cn,
-                                            SessionState state)
+                                            SessionState state,
+                                            GError **err)
 {
   const gchar *xmlns;
-  JingleAppFuncs *app_funcs;
-  JingleTransportFuncs *trans_funcs;
-  session_add_content(sess, cn->name, state);
+  JingleAppFuncs *appfuncs;
+  JingleTransportFuncs *transfuncs;
+  GError *error = NULL;
+  SessionContent *sc;
+  gconstpointer data;
+  
+  sc = session_add_content(sess, cn->name, state);
   
-  xmlns = lm_message_node_get_attribute(cn->description, "xmlns");
-  app_funcs = jingle_get_appfuncs(xmlns);
-  session_add_app(sess, cn->name, xmlns, app_funcs->check(cn, NULL));
+  // Check and add the application
+  {
+    xmlns = lm_message_node_get_attribute(cn->description, "xmlns");
+    appfuncs = jingle_get_appfuncs(xmlns);
+    data = appfuncs->check(cn, &error);
+    if (data == NULL || error != NULL) {
+      g_propagate_error(err, error);
+      sess->content = g_slist_remove(sess->content, sc);
+      return NULL;
+    }
+    session_add_app(sess, cn->name, xmlns, data);
+  }
   
-  xmlns = lm_message_node_get_attribute(cn->transport, "xmlns");
-  trans_funcs = jingle_get_transportfuncs(xmlns);
-  session_add_trans(sess, cn->name, xmlns, trans_funcs->check(cn, NULL));
+  // Check and add the transport
+  {
+    xmlns = lm_message_node_get_attribute(cn->transport, "xmlns");
+    transfuncs = jingle_get_transportfuncs(xmlns);
+    data = transfuncs->check(cn, &error);
+    if (data == NULL || error != NULL) {
+      g_propagate_error(err, error);
+      g_free(sc->xmlns_desc);
+      sess->content = g_slist_remove(sess->content, sc);
+      return NULL;
+    }
+    session_add_trans(sess, cn->name, xmlns, data);
+  }
+  
+  return sc;
 }
 
 SessionContent *session_find_sessioncontent(JingleSession *sess,
@@ -147,7 +175,7 @@
   return NULL;
 }
 
-SessionContent *session_find_transport(const gchar *xmlns_trans, gconstpointer data)
+SessionContent *session_find_transport(gconstpointer data)
 {
   GSList *el, *el1;
   JingleSession *sess;
@@ -156,7 +184,7 @@
     sess = (JingleSession*) el1->data;
     for (el = sess->content; el; el = el->next) {
       sc = (SessionContent*) el->data;
-      if (!g_strcmp0(sc->xmlns_trans, xmlns_trans) && sc->transfuncs->cmp(sc->transport, data))
+      if (data == sc->transport)
         return sc;
     }
   }
--- a/jingle/sessions.h	Mon Aug 16 18:32:55 2010 +0200
+++ b/jingle/sessions.h	Mon Aug 16 18:33:33 2010 +0200
@@ -75,16 +75,17 @@
 JingleSession *session_new_from_jinglenode(JingleNode *jn);
 JingleSession *session_find_by_sid(const gchar *sid, const gchar *from);
 JingleSession *session_find(const JingleNode *jn);
-void session_add_content(JingleSession *sess, const gchar *name,
-                         SessionState state);
+SessionContent* session_add_content(JingleSession *sess, const gchar *name,
+                                    SessionState state);
 void session_add_app(JingleSession *sess, const gchar *name,
                            const gchar *xmlns, gconstpointer data);
 void session_add_trans(JingleSession *sess, const gchar *name,
                            const gchar *xmlns, gconstpointer data);
-void session_add_content_from_jinglecontent(JingleSession *sess, JingleContent *cn,
-                         SessionState state);
-SessionContent *session_find_sessioncontent(JingleSession *sess, const gchar *name);
-SessionContent *session_find_transport(const gchar *xmlns_trans, gconstpointer data);
+SessionContent* session_add_content_from_jinglecontent(JingleSession *sess,
+                           JingleContent *cn, SessionState state, GError **err);
+SessionContent *session_find_transport(gconstpointer data);
+SessionContent *session_find_sessioncontent(JingleSession *sess,
+                                            const gchar *name);
 int session_remove_sessioncontent(JingleSession *sess, const gchar *name);
 void session_changestate_sessioncontent(JingleSession *sess, const gchar *name,
                                         SessionState state);