jingle-ibb/ibb.c
changeset 122 8969dc3e2f14
parent 120 3e2085a44a5c
child 123 58bd57666ef9
equal deleted inserted replaced
121:3a3c0e16ea00 122:8969dc3e2f14
    20  */
    20  */
    21 
    21 
    22 #include "config.h"
    22 #include "config.h"
    23 
    23 
    24 #include <glib.h>
    24 #include <glib.h>
       
    25 #include <string.h>
    25 
    26 
    26 #include <mcabber/xmpp.h>
    27 #include <mcabber/xmpp.h>
    27 #include <mcabber/modules.h>
    28 #include <mcabber/modules.h>
    28 #include <mcabber/utils.h>
    29 #include <mcabber/utils.h>
    29 #include <mcabber/xmpp_helper.h>
    30 #include <mcabber/xmpp_helper.h>
    31 #include <mcabber/hooks.h>
    32 #include <mcabber/hooks.h>
    32 
    33 
    33 #include <jingle/jingle.h>
    34 #include <jingle/jingle.h>
    34 #include <jingle/check.h>
    35 #include <jingle/check.h>
    35 #include <jingle/register.h>
    36 #include <jingle/register.h>
       
    37 #include <jingle/sessions.h>
    36 
    38 
    37 #include "ibb.h"
    39 #include "ibb.h"
    38 
    40 
    39 static LmMessageHandler* jingle_ibb_handler = NULL;
    41 static LmMessageHandler* jingle_ibb_handler = NULL;
    40 
    42 
    41 gconstpointer jingle_ibb_check(JingleContent *cn, GError **err);
    43 gconstpointer jingle_ibb_check(JingleContent *cn, GError **err);
    42 gboolean jingle_ibb_cmp(gconstpointer data1, gconstpointer data2);
    44 gboolean jingle_ibb_cmp(gconstpointer data1, gconstpointer data2);
    43 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node);
    45 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node);
    44 const gchar* jingle_ibb_xmlns(void);
    46 const gchar* jingle_ibb_xmlns(void);
    45 gconstpointer jingle_ibb_new(void);
    47 gconstpointer jingle_ibb_new(void);
    46 void jingle_ibb_send(session_content *sc, const gchar *to, gconstpointer data, gchar *buf, gsize size);
    48 void jingle_ibb_send(session_content *sc, gconstpointer data, gchar *buf, gsize size);
       
    49 static void _send_internal(session_content *sc, const gchar *to, gchar *buf,
       
    50                            gsize size, const gchar *sid, gint64 *seq);
    47 
    51 
    48 static void jingle_ibb_init(void);
    52 static void jingle_ibb_init(void);
    49 static void jingle_ibb_uninit(void);
    53 static void jingle_ibb_uninit(void);
    50 
    54 
    51 static guint connect_hid = 0;
    55 static guint connect_hid = 0;
   101 
   105 
   102   // the size attribute is a xs:short an therefore can be negative.
   106   // the size attribute is a xs:short an therefore can be negative.
   103   if (ibb->blocksize < 0 || ibb->blocksize > IBB_BLOCK_SIZE_MAX) {
   107   if (ibb->blocksize < 0 || ibb->blocksize > IBB_BLOCK_SIZE_MAX) {
   104     g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE,
   108     g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE,
   105                 "block-size is negative");
   109                 "block-size is negative");
       
   110     g_free(ibb->sid);
   106     g_free(ibb);
   111     g_free(ibb);
   107     return NULL;
   112     return NULL;
   108   }
   113   }
   109 
   114   
   110   return (gconstpointer) ibb;
   115   return (gconstpointer) ibb;
   111 }
   116 }
   112 
   117 
   113 LmHandlerResult jingle_ibb_handle_iq(LmMessageHandler *handler,
   118 LmHandlerResult jingle_ibb_handle_iq(LmMessageHandler *handler,
   114                                  LmConnection *connection, LmMessage *message,
   119                                  LmConnection *connection, LmMessage *message,
   190 
   195 
   191 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node)
   196 void jingle_ibb_tomessage(gconstpointer data, LmMessageNode *node)
   192 {
   197 {
   193   JingleIBB *jibb = (JingleIBB*) data;
   198   JingleIBB *jibb = (JingleIBB*) data;
   194   gchar *bsize = g_strdup_printf("%i", jibb->blocksize);
   199   gchar *bsize = g_strdup_printf("%i", jibb->blocksize);
       
   200 
   195   if (lm_message_node_get_child(node, "transport") != NULL)
   201   if (lm_message_node_get_child(node, "transport") != NULL)
   196     return;
   202     return;
   197 
   203 
   198   LmMessageNode *node2 = lm_message_node_add_child(node, "transport", NULL);
   204   LmMessageNode *node2 = lm_message_node_add_child(node, "transport", NULL);
   199 
   205 
   205 }
   211 }
   206 
   212 
   207 static void jingle_ibb_handle_ack_iq_send(LmMessage *mess, gpointer data)
   213 static void jingle_ibb_handle_ack_iq_send(LmMessage *mess, gpointer data)
   208 {
   214 {
   209   // TODO: check the sub type (error ??)
   215   // TODO: check the sub type (error ??)
   210   handle_trans_next((session_content*)data);
   216   session_content *sc = (session_content *)data;
   211 }
   217   JingleSession *sess = session_find_by_sid(sc->sid, sc->from);
   212 
   218   SessionContent *sc2 = session_find_sessioncontent(sess, sc->name);
   213 void jingle_ibb_send(session_content *sc, const gchar *to, gconstpointer data, gchar *buf, gsize size)
   219 
   214 {
   220   JingleIBB *jibb = (JingleIBB *)sc2->transport;
   215   JingleIBB *jibb = (JingleIBB*)data;
   221 
       
   222   // We look if there is enough data staying
       
   223   if (jibb->dataleft > jibb->blocksize) {
       
   224     gchar *buf = g_memdup(jibb->buf, jibb->blocksize);
       
   225     jibb->dataleft-=jibb->blocksize;
       
   226     g_memmove(jibb->buf, jibb->buf+jibb->blocksize, jibb->dataleft);
       
   227     _send_internal(sc, sess->to, buf, jibb->blocksize, sess->sid, &jibb->seq);
       
   228     g_free(buf);
       
   229   } else { // ask for more data
       
   230     handle_trans_next(sc);
       
   231   }
       
   232 }
       
   233 
       
   234 static void _send_internal(session_content *sc, const gchar *to, gchar *buf,
       
   235                            gsize size, const gchar *sid, gint64 *seq)
       
   236 {
   216   JingleAckHandle *ackhandle;
   237   JingleAckHandle *ackhandle;
   217   LmMessageNode *node;
   238   LmMessage *r = lm_message_new_with_sub_type(to, LM_MESSAGE_TYPE_IQ,
       
   239                                               LM_MESSAGE_SUB_TYPE_SET);
       
   240   LmMessageNode *node = lm_message_get_node(r);
       
   241   
   218   gchar *base64 = g_base64_encode((const guchar *)buf, size);
   242   gchar *base64 = g_base64_encode((const guchar *)buf, size);
   219   gchar *seq = g_strdup_printf("%" G_GINT64_FORMAT, jibb->seq);
   243   gchar *strseq = g_strdup_printf("%" G_GINT64_FORMAT, *seq);
   220   
   244 
   221   LmMessage *r = lm_message_new_with_sub_type(to, LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET);
   245   node = lm_message_node_add_child(node, "data", NULL);
   222   LmMessageNode *node2 = lm_message_get_node(r);
       
   223   node = lm_message_node_add_child(node2, "data", NULL);
       
   224   lm_message_node_set_attributes(node, "xmlns", NS_TRANSPORT_IBB,
   246   lm_message_node_set_attributes(node, "xmlns", NS_TRANSPORT_IBB,
   225                                  "sid", jibb->sid,
   247                                  "sid", sid,
   226                                  "seq", seq,
   248                                  "seq", strseq,
   227                                  NULL);
   249                                  NULL);
   228   lm_message_node_set_value(node, base64);
   250   lm_message_node_set_value(node, base64);
   229   
   251   
   230   ackhandle = g_new0(JingleAckHandle, 1);
   252   ackhandle = g_new0(JingleAckHandle, 1);
   231   ackhandle->callback = jingle_ibb_handle_ack_iq_send;
   253   ackhandle->callback = jingle_ibb_handle_ack_iq_send;
   234   lm_connection_send_with_reply(lconnection, r,
   256   lm_connection_send_with_reply(lconnection, r,
   235                                 jingle_new_ack_handler(ackhandle), NULL);
   257                                 jingle_new_ack_handler(ackhandle), NULL);
   236   lm_message_unref(r);
   258   lm_message_unref(r);
   237   
   259   
   238   // The next packet will be seq++
   260   // The next packet will be seq++
   239   jibb->seq++;
   261   ++(*seq);
   240   
   262   
   241   g_free(base64);
   263   g_free(base64);
       
   264   g_free(strseq);
       
   265 }
       
   266 
       
   267 void jingle_ibb_send(session_content *sc, gconstpointer data, gchar *buf,
       
   268                      gsize size)
       
   269 {
       
   270   JingleIBB *jibb = (JingleIBB*)data;
       
   271   
       
   272   if (jibb->size_buf >= size + jibb->dataleft) {
       
   273     g_memmove(jibb->buf + jibb->dataleft, buf, size);
       
   274     jibb->dataleft+=size;
       
   275   } else {
       
   276     jibb->size_buf = size + jibb->dataleft;
       
   277     jibb->buf = g_realloc(jibb->buf, jibb->size_buf);
       
   278     g_memmove(jibb->buf + jibb->dataleft, buf, size);
       
   279     jibb->dataleft = jibb->size_buf;
       
   280   }
       
   281 
       
   282   // We need more data
       
   283   if (jibb->dataleft < jibb->blocksize) {
       
   284     handle_trans_next(sc);
       
   285     return;
       
   286   }
       
   287 
       
   288   // It's enough
       
   289   {
       
   290     JingleSession *sess = session_find_by_sid(sc->sid, sc->from);
       
   291     
       
   292     gchar *buffer = g_memdup(jibb->buf, jibb->blocksize);
       
   293   
       
   294     jibb->dataleft-=jibb->blocksize;
       
   295   
       
   296     g_memmove(jibb->buf, jibb->buf+jibb->blocksize, jibb->dataleft);
       
   297   
       
   298     _send_internal(sc, sess->to, buffer, jibb->blocksize, sess->sid, &jibb->seq);
       
   299   
       
   300     g_free(buf);
       
   301   }
   242 }
   302 }
   243 
   303 
   244 static void jingle_ibb_unregister_lm_handlers(void)
   304 static void jingle_ibb_unregister_lm_handlers(void)
   245 {
   305 {
   246   if (lconnection) {
   306   if (lconnection) {