create the session when receiving a session-initiate
authorNicolas Cornu <nicolas.cornu@ensi-bourges.fr>
Sat, 14 Aug 2010 19:06:27 +0200
changeset 119 0b9a7b505079
parent 118 f3408f4fe61a
child 120 3e2085a44a5c
create the session when receiving a session-initiate
jingle-filetransfer/filetransfer.c
jingle-ibb/ibb.c
jingle/action-handlers.c
jingle/jingle.c
jingle/send.c
jingle/send.h
jingle/sessions.c
jingle/sessions.h
--- a/jingle-filetransfer/filetransfer.c	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle-filetransfer/filetransfer.c	Sat Aug 14 19:06:27 2010 +0200
@@ -152,7 +152,7 @@
   // check if the md5 hash is valid ([a-fA-F0-9){32})
   if (ft->hash != NULL && (strlen(ft->hash) != 32 || !is_md5_hash(ft->hash))) {
     g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE,
-                "the offered file has an invalid filename");
+                "the offered file has an invalid hash");
     g_free(ft->name);
     g_free(ft);
     return NULL;
@@ -162,12 +162,14 @@
   return (gconstpointer) ft;
 }
 
-gboolean jingle_ft_handle(JingleAction action, gconstpointer data, LmMessageNode *node)
+gboolean jingle_ft_handle(JingleAction action, gconstpointer data,
+                          LmMessageNode *node)
 {
   if (action == JINGLE_SESSION_INFO) {
-    if (!g_strcmp0(lm_message_node_get_attribute(node, "xmlns"), NS_JINGLE_APP_FT_INFO)
+    if (!g_strcmp0(lm_message_node_get_attribute(node, "xmlns"),
+                   NS_JINGLE_APP_FT_INFO)
         && !g_strcmp0(node->name, "hash")) {
-      ((JingleFT *)data)->hash = lm_message_node_get_value(node);
+      ((JingleFT *)data)->hash = g_strdup(lm_message_node_get_value(node));
       return TRUE;
 	}
 	return FALSE;
@@ -276,6 +278,7 @@
     jft->desc = g_strdup(args[0]);
     jft->type = JINGLE_FT_OFFER;
     jft->name = g_path_get_basename(filename);
+    // TODO: Transform date to a good format (ios8601)
     jft->date = fileinfo.st_mtime;
     jft->size = fileinfo.st_size;
     jft->outfile = g_io_channel_new_file (filename, "r", NULL);
@@ -435,7 +438,7 @@
 {
   JingleFT *jft = (JingleFT*)data;
 
-  if (jft->hash != NULL) {
+  if (jft->hash != NULL && jft->md5 != NULL) {
     if (g_strcmp0(jft->hash, g_checksum_get_string(jft->md5))) {
       scr_LogPrint(LPRINT_LOGNORM, "Jingle File Transfer: File corrupt (%s)", jft->name);
     } else {
@@ -447,9 +450,11 @@
 
   g_checksum_free(jft->md5);
 
-  g_io_channel_flush(jft->outfile, NULL);
+  if (jft->outfile != NULL) {
+    g_io_channel_flush(jft->outfile, NULL);
 
-  g_io_channel_unref(jft->outfile);
+    g_io_channel_unref(jft->outfile);
+  }
 }
 
 static void jingle_ft_init(void)
--- a/jingle-ibb/ibb.c	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle-ibb/ibb.c	Sat Aug 14 19:06:27 2010 +0200
@@ -88,7 +88,7 @@
   ibb = g_new0(JingleIBB, 1);
   
   blocksize  = lm_message_node_get_attribute(node, "block-size");
-  ibb->sid = lm_message_node_get_attribute(node, "sid");
+  ibb->sid = g_strdup(lm_message_node_get_attribute(node, "sid"));
    
   if (!ibb->sid || !blocksize) {
     g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_MISSING,
--- a/jingle/action-handlers.c	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle/action-handlers.c	Sat Aug 14 19:06:27 2010 +0200
@@ -75,6 +75,7 @@
     cn = (JingleContent *)(child->data);
     session_changestate_sessioncontent(sess, cn->name, JINGLE_SESSION_STATE_ACTIVE);
   }
+  jingle_free_jinglenode(jn);
 }
 
 void handle_content_add(JingleNode *jn)
@@ -172,6 +173,7 @@
       }
     }
   }
+  jingle_free_jinglenode(jn);
 }
 
 void handle_content_reject(JingleNode *jn)
@@ -215,6 +217,7 @@
     session_delete(sess);
     return;
   }
+  jingle_free_jinglenode(jn);
 }
 
 void handle_content_remove(JingleNode *jn)
@@ -232,18 +235,22 @@
     scr_log_print(LPRINT_DEBUG, "jingle: One of the content element was invalid (%s)",
                   err->message);
     jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL);
+    jingle_free_jinglenode(jn);
     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);
+    jingle_free_jinglenode(jn);
     return;
   }
   
   // if a session with the same sid doesn't already exists
   if ((sess = session_find(jn)) == NULL) {
+    // TODO: look if it's really that
     jingle_send_iq_error(jn->message, "cancel", "item-not-found", "unknown-session");
+    jingle_free_jinglenode(jn);
     return;
   }
 
@@ -253,6 +260,7 @@
     cn = (JingleContent *)(child->data);
     session_remove_sessioncontent(sess, cn->name);
   }
+  jingle_free_jinglenode(jn);
 }
 
 void handle_session_initiate(JingleNode *jn)
@@ -264,11 +272,17 @@
   GSList *child = NULL;
   LmMessage *r;
   gchar *disp;
+  JingleSession *sess;
+  const gchar *xmlns;
+  JingleAppFuncs *appfuncs;
+  JingleTransportFuncs *transfuncs;
+  gconstpointer description, transport;
   
   // Make sure the request come from an user in our roster
   disp = jidtodisp(lm_message_get_from(jn->message));
   if (!roster_find(disp, jidsearch, 0)) {
-    // jingle_send_session_terminate(jn, "decline");
+    // We say that we doesn't support jingle.
+    jingle_send_iq_error(jn->message, "cancel", "service-unavailable", NULL);
     jingle_free_jinglenode(jn);
     g_free(disp);
     return;
@@ -278,6 +292,7 @@
     scr_log_print(LPRINT_DEBUG, "jingle: One of the content element was invalid (%s)",
                   err->message);
     jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL);
+    jingle_free_jinglenode(jn);
     g_free(disp);
     return;
   }
@@ -285,6 +300,7 @@
   // a session-initiate message must contains at least one <content> element
   if (g_slist_length(jn->content) < 1) {
     jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL);
+    jingle_free_jinglenode(jn);
     g_free(disp);
     return;
   }
@@ -301,6 +317,7 @@
   if (!valid_disposition) {
     jingle_send_iq_error(jn->message, "cancel", "bad-request", NULL);
     g_free(disp);
+    jingle_free_jinglenode(jn);
     return;  
   }
   
@@ -308,23 +325,55 @@
   if (session_find(jn) != NULL) {
     jingle_send_iq_error(jn->message, "cancel", "unexpected-request", "out-of-order");
     g_free(disp);
+    jingle_free_jinglenode(jn);
     return;
   }
 
   jingle_ack_iq(jn->message);
 
+  // We create a session
+  sess = session_new_from_jinglenode(jn);
+  
+  for (child = jn->content; child; child = child->next) {
+    cn = (JingleContent *)(child->data);
+    
+    xmlns = lm_message_node_get_attribute(cn->description, "xmlns");
+    appfuncs = jingle_get_appfuncs(xmlns);
+    if (appfuncs == NULL) continue;
+    
+    xmlns = lm_message_node_get_attribute(cn->transport, "xmlns");
+    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);
+  }
+  
+  if(g_slist_length(sess->content) == 0) {
+    jingle_send_session_terminate(sess, "unsupported-applications");
+    session_delete(sess);
+    return;
+  }
+  
   // Wait that user accept the jingle
   sbuf = g_string_new("");
-  g_string_printf(sbuf, "Received an invitation for a jingle session from <%s>", lm_message_get_from(jn->message));
+  g_string_printf(sbuf, "Received an invitation for a jingle session from <%s>",
+                  lm_message_get_from(jn->message));
 
   scr_WriteIncomingMessage(disp, sbuf->str, 0, HBB_PREFIX_INFO, 0);
   scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
 
   {
     const char *id;
-    char *desc = g_strdup_printf("<%s> invites you to do a jingle session", lm_message_get_from(jn->message));
+    char *desc = g_strdup_printf("<%s> invites you to do a jingle session",
+                                 lm_message_get_from(jn->message));
 
-    id = evs_new(desc, NULL, 0, evscallback_jingle, jn, NULL);
+    id = evs_new(desc, NULL, 0, evscallback_jingle, sess, NULL);
     g_free(desc);
     if (id)
       g_string_printf(sbuf, "Please use /event %s accept|reject", id);
@@ -334,6 +383,7 @@
     scr_LogPrint(LPRINT_LOGNORM, "%s", sbuf->str);
   }
   g_free(disp);
+  jingle_free_jinglenode(jn);
 }
 
 void handle_session_info(JingleNode *jn)
@@ -376,6 +426,7 @@
    * error condition of <unsupported-info/>." */
   jingle_send_iq_error(jn->message, "modify", "feature-not-implemented",
                        "unsupported-info");
+  jingle_free_jinglenode(jn);
 }
 
 void handle_session_accept(JingleNode *jn)
@@ -421,7 +472,7 @@
     sc2->name = sc->name;
     sc->appfuncs->start(sc2, 2048);
   }
-
+  jingle_free_jinglenode(jn);
 }
 
 void handle_session_terminate(JingleNode *jn)
@@ -444,4 +495,5 @@
   }
   session_delete(sess);
   jingle_ack_iq(jn->message);
+  jingle_free_jinglenode(jn);
 }
--- a/jingle/jingle.c	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle/jingle.c	Sat Aug 14 19:06:27 2010 +0200
@@ -173,7 +173,7 @@
 gboolean evscallback_jingle(guint evcontext, const gchar *arg,
                             gpointer userdata)
 {
-  JingleNode *jn = userdata;
+  JingleSession *js = (JingleSession*)userdata;
 
   /*
   if (G_UNLIKELY(!jn)) {
@@ -184,33 +184,28 @@
 
   if (evcontext == EVS_CONTEXT_TIMEOUT) {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s timed out, cancelled.",
-                 jn->initiator);
-    jingle_free_jinglenode(jn);
+                 js->from);
     return FALSE;
   }
   if (evcontext == EVS_CONTEXT_CANCEL) {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.",
-                 jn->initiator);
-    jingle_free_jinglenode(jn);
+                 js->from);
     return FALSE;
   }
   if (!(evcontext == EVS_CONTEXT_ACCEPT || evcontext == EVS_CONTEXT_REJECT)) {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.",
-                 jn->initiator);
-    jingle_free_jinglenode(jn);
+                 js->from);
     return FALSE;
   }
   
   if (evcontext == EVS_CONTEXT_ACCEPT) {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s accepted.",
-                 jn->initiator);
-    jingle_send_session_accept(jn);
-
+                 js->from);
+    jingle_send_session_accept(js);
   } else {
     scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.",
-                 jn->initiator);
-    // TODO: jingle_send_session_terminate(jn, "decline");
-    jingle_free_jinglenode(jn);
+                 js->from);
+    jingle_send_session_terminate(js, "decline");
   }
 
   return FALSE;
--- a/jingle/send.c	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle/send.c	Sat Aug 14 19:06:27 2010 +0200
@@ -84,54 +84,19 @@
   session_delete(sess);
 }
 
-void jingle_send_session_accept(JingleNode *jn)
+void jingle_send_session_accept(JingleSession *js)
 {
-  JingleSession *sess;
-  JingleContent *cn;
   LmMessage *mess;
-  GSList *child = NULL;
-  JingleAppFuncs *appfuncs;
-  JingleTransportFuncs *transfuncs;
-  gconstpointer description, transport;
-  const gchar *xmlns;
-  GError *err = NULL;
   JingleAckHandle *ackhandle;
- 
-  sess = session_new_from_jinglenode(jn);
-
-  for (child = jn->content; child; child = child->next) {
-    cn = (JingleContent *)(child->data);
-
-    xmlns = lm_message_node_get_attribute(cn->description, "xmlns");
-    appfuncs = jingle_get_appfuncs(xmlns);
-    if (appfuncs == NULL) continue;
 
-    xmlns = lm_message_node_get_attribute(cn->transport, "xmlns");
-    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;
-   
-    scr_log_print(LPRINT_DEBUG, "jingle: New content accepted: %s", cn->name);
 
-    session_add_content_from_jinglecontent(sess, cn, JINGLE_SESSION_STATE_ACTIVE);
-  }
-
-  if(g_slist_length(sess->content) == 0) {
-    jingle_send_session_terminate(sess, "unsupported-applications");
-    session_delete(sess);
-    return;
-  }
-
-  mess = lm_message_from_jinglesession(sess, JINGLE_SESSION_ACCEPT);
+  mess = lm_message_from_jinglesession(js, JINGLE_SESSION_ACCEPT);
  
   if (mess) {
     ackhandle = g_new0(JingleAckHandle, 1);
     ackhandle->callback = jingle_handle_ack_iq_sa;
-    ackhandle->user_data = (gpointer)sess;
+    ackhandle->user_data = (gpointer)js;
     lm_connection_send_with_reply(lconnection, mess,
                                   jingle_new_ack_handler(ackhandle), NULL);
     lm_message_unref(mess);
--- a/jingle/send.h	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle/send.h	Sat Aug 14 19:06:27 2010 +0200
@@ -9,6 +9,6 @@
 
 void jingle_send_session_terminate(JingleSession *js, const gchar *reason);
 void jingle_send_session_initiate(JingleSession *js);
-void jingle_send_session_accept(JingleNode *jn);
+void jingle_send_session_accept(JingleSession *js);
 
 #endif
--- a/jingle/sessions.c	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle/sessions.c	Sat Aug 14 19:06:27 2010 +0200
@@ -90,7 +90,7 @@
 {
   SessionContent *sc = g_new0(SessionContent, 1);
   
-  sc->name = name;
+  sc->name = g_strdup(name);
   sc->state = state;
 
   sess->content = g_slist_append(sess->content, sc);
@@ -101,23 +101,24 @@
 {
   SessionContent *sc = session_find_sessioncontent(sess, name);
   
-  sc->xmlns_desc = xmlns;
+  sc->xmlns_desc = g_strdup(xmlns);
   sc->appfuncs = jingle_get_appfuncs(xmlns);
   sc->description = data;
 }
 
 void session_add_trans(JingleSession *sess, const gchar *name,
-                           const gchar *xmlns, gconstpointer data)
+                       const gchar *xmlns, gconstpointer data)
 {
   SessionContent *sc = session_find_sessioncontent(sess, name);
   
-  sc->xmlns_trans = xmlns;
+  sc->xmlns_trans = g_strdup(xmlns);
   sc->transfuncs = jingle_get_transportfuncs(xmlns);
   sc->transport = data;
 }
 
-void session_add_content_from_jinglecontent(JingleSession *sess, JingleContent *cn,
-                         SessionState state)
+void session_add_content_from_jinglecontent(JingleSession *sess,
+                                            JingleContent *cn,
+                                            SessionState state)
 {
   const gchar *xmlns;
   JingleAppFuncs *app_funcs;
@@ -168,8 +169,10 @@
   sc = session_find_sessioncontent(sess, name);
   if(sc == NULL) return;
 
-  if (sc->state == JINGLE_SESSION_STATE_ACTIVE); // We should stop the transfer
-
+  if (sc->state == JINGLE_SESSION_STATE_ACTIVE) {
+    // TODO: stop the transfer
+  }
+  
   sess->content = g_slist_remove(sess->content, sc);
   
   return g_slist_length(sess->content);
@@ -206,8 +209,19 @@
  */
 void session_free(JingleSession *sess)
 {
+  GSList *el;
+  SessionContent *sc;
+  
   g_free(sess->sid);
   g_free(sess->from);
+  g_free(sess->to);
+  
+  // Remove and free contents
+  for (el = sess->content; el; el = el->next) {
+    sc = (SessionContent*)el->data;
+    session_remove_sessioncontent(sess, sc->name);
+  }
+  
   g_free(sess);
 }
 
--- a/jingle/sessions.h	Sat Aug 14 12:00:59 2010 +0200
+++ b/jingle/sessions.h	Sat Aug 14 19:06:27 2010 +0200
@@ -46,13 +46,13 @@
 typedef struct {
   /* "A unique name or identifier for the content type
    *  according to the creator" */
-  const gchar *name;
+  gchar *name;
 
   /* */
   SessionState state;
 
   /* The namespace of the app */
-  const gchar *xmlns_desc;
+  gchar *xmlns_desc;
 
   /* The internal struct of the app module */
   gconstpointer description;
@@ -61,7 +61,7 @@
   JingleAppFuncs *appfuncs;
 
   /* The namespace of the transport */
-  const gchar *xmlns_trans;
+  gchar *xmlns_trans;
 
   /* The internal struct of the transport module */
   gconstpointer transport;