# HG changeset patch # User Nicolas Cornu # Date 1281976413 -7200 # Node ID 361d8577ebd14d75456c6e9fef689aedf89aaa56 # Parent 4fef4ced1e97e9004874f9d24b89bd12d15f22ad Change the way IBB work diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle-filetransfer/filetransfer.c --- 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"); diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle-filetransfer/filetransfer.h --- 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; diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle-ibb/ibb.c --- 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; diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle/action-handlers.c --- 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); diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle/jingle.c --- 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; } diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle/jingle.h --- 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); diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle/register.h --- 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; diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle/sessions.c --- 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; } } diff -r 4fef4ced1e97 -r 361d8577ebd1 jingle/sessions.h --- 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);