jingle/jingle.c
changeset 144 efc92c939fef
parent 139 459b2503c1a3
child 151 b1acef78e4f5
equal deleted inserted replaced
143:cd97a18dd0b9 144:efc92c939fef
    88   .uninit          = jingle_uninit,
    88   .uninit          = jingle_uninit,
    89   .next            = NULL,
    89   .next            = NULL,
    90 };
    90 };
    91 
    91 
    92 
    92 
       
    93 /**
       
    94  * @brief Handle all incoming IQs containing a <jingle> node
       
    95  */
    93 LmHandlerResult jingle_handle_iq(LmMessageHandler *handler,
    96 LmHandlerResult jingle_handle_iq(LmMessageHandler *handler,
    94                                  LmConnection *connection, LmMessage *message,
    97                                  LmConnection *connection, LmMessage *message,
    95                                  gpointer user_data)
    98                                  gpointer user_data)
    96 {
    99 {
    97   LmMessageSubType iqtype = lm_message_get_sub_type(message);
   100   LmMessageSubType iqtype = lm_message_get_sub_type(message);
   137   jingle_free_jinglenode(jn);
   140   jingle_free_jinglenode(jn);
   138   return LM_HANDLER_RESULT_REMOVE_MESSAGE;
   141   return LM_HANDLER_RESULT_REMOVE_MESSAGE;
   139 }
   142 }
   140 
   143 
   141 /**
   144 /**
   142  * Handle incoming ack iq (type result or error).
   145  * @brief Handle incoming ack iq (type result or error).
   143  */
   146  */
   144 LmHandlerResult jingle_handle_ack_iq(LmMessageHandler *handler,
   147 LmHandlerResult jingle_handle_ack_iq(LmMessageHandler *handler,
   145                                      LmConnection *connection, 
   148                                      LmConnection *connection, 
   146                                      LmMessage *message, gpointer user_data)
   149                                      LmMessage *message, gpointer user_data)
   147 {
   150 {
   181     el = el->next;
   184     el = el->next;
   182   }
   185   }
   183   return TRUE;
   186   return TRUE;
   184 }
   187 }
   185 
   188 
       
   189 /**
       
   190  * @param ah A JingleAckHandle struct
       
   191  * @return   The LmMessageHandler to use when sending a message
       
   192  *           with lm_connection_send_with_reply
       
   193  * 
       
   194  * jingle_new_ack_handler allow to easily create new LmMessageHandler to
       
   195  * be called back when a message we sent was acknowledged by its recipient.
       
   196  */
   186 LmMessageHandler *jingle_new_ack_handler(JingleAckHandle *ah)
   197 LmMessageHandler *jingle_new_ack_handler(JingleAckHandle *ah)
   187 {
   198 {
   188   if(ack_timeout_checker == 0)
   199   if(ack_timeout_checker == 0)
   189 	  ack_timeout_checker = g_timeout_add_seconds(3, jingle_ack_timeout_checker, NULL);
   200 	  ack_timeout_checker = g_timeout_add_seconds(3, jingle_ack_timeout_checker, NULL);
   190   
   201   
   246 
   257 
   247   return FALSE;
   258   return FALSE;
   248 }
   259 }
   249 
   260 
   250 /**
   261 /**
       
   262  * @brief Acknowledge the receipt of a message.
       
   263  * @param m The LmMessage to ack
       
   264  * 
   251  * According to the specifications:
   265  * According to the specifications:
   252  * "An entity that receives an IQ request of type "get" or "set" MUST
   266  * "An entity that receives an IQ request of type "get" or "set" MUST
   253  * reply with an IQ response of type "result" or "error"."
   267  * reply with an IQ response of type "result" or "error"."\n
   254  * For Jingle's IQ, we have to reply with an empty "result" IQ to acknowledge
   268  * For Jingle's IQ, we have to reply with an empty "result" IQ to acknowledge
   255  * receipt.
   269  * receipt.
   256  */
   270  */
   257 void jingle_ack_iq(LmMessage *m)
   271 void jingle_ack_iq(LmMessage *m)
   258 {
   272 {
   262   lm_connection_send(lconnection, r, NULL);
   276   lm_connection_send(lconnection, r, NULL);
   263   lm_message_unref(r);
   277   lm_message_unref(r);
   264 }
   278 }
   265 
   279 
   266 /**
   280 /**
   267  * Create an error IQ.
   281  * @brief Create a new jingle IQ with an error.
       
   282  * @param m          The message to reply to
       
   283  * @param errtype    The error type (the type attribute of <error>)
       
   284  * @param cond       The error condition
       
   285  * @param jinglecond The jingle error condition
       
   286  * 
       
   287  * Error types are defined <a href="http://tools.ietf.org/html/
       
   288  * draft-ietf-xmpp-3920bis-12#section-8.3.2">section 8.3.2 of RFC 3920bis</a>.\n
       
   289  * Error conditions are defined <a href="http://tools.ietf.org/html/
       
   290  * draft-ietf-xmpp-3920bis-12#section-8.3.3">section 8.3.3 of RFC 3920bis</a>.\n
       
   291  * Jingle Error conditions are defined <a href="http://xmpp.org/extensions/
       
   292  * xep-0166.html#errors">section 10 of XEP-0166</a>.
   268  */
   293  */
   269 LmMessage *jingle_new_iq_error(LmMessage *m, const gchar *errtype,
   294 LmMessage *jingle_new_iq_error(LmMessage *m, const gchar *errtype,
   270                                const gchar *cond, const gchar *jinglecond)
   295                                const gchar *cond, const gchar *jinglecond)
   271 {
   296 {
   272   LmMessage *r;
   297   LmMessage *r;
   274 
   299 
   275   r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_ERROR);
   300   r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_ERROR);
   276   err = lm_message_node_add_child(r->node, "error", NULL);
   301   err = lm_message_node_add_child(r->node, "error", NULL);
   277   lm_message_node_set_attribute(err, "type", errtype);
   302   lm_message_node_set_attribute(err, "type", errtype);
   278 
   303 
   279   // error condition as defined by RFC 3920bis section 8.3.3
       
   280   if (cond != NULL) {
   304   if (cond != NULL) {
   281     tmpnode = lm_message_node_add_child(err, cond, NULL);
   305     tmpnode = lm_message_node_add_child(err, cond, NULL);
   282     lm_message_node_set_attribute(tmpnode, "xmlns", NS_XMPP_STANZAS);
   306     lm_message_node_set_attribute(tmpnode, "xmlns", NS_XMPP_STANZAS);
   283   }
   307   }
   284 
   308 
   285   // jingle error condition as defined by XEP-0166 section 10
       
   286   if (jinglecond != NULL) {
   309   if (jinglecond != NULL) {
   287     tmpnode = lm_message_node_add_child(err, jinglecond, NULL);
   310     tmpnode = lm_message_node_add_child(err, jinglecond, NULL);
   288     lm_message_node_set_attribute(tmpnode, "xmlns", NS_JINGLE_ERRORS);
   311     lm_message_node_set_attribute(tmpnode, "xmlns", NS_JINGLE_ERRORS);
   289   }
   312   }
   290 
   313 
   291   return r;
   314   return r;
   292 }
   315 }
   293 
   316 
   294 /**
   317 /**
   295  * Reply to a Jingle IQ with an error.
   318  * @brief Reply to a jingle IQ with an error
       
   319  * @param m          The message to reply to
       
   320  * @param errtype    The error type (the type attribute of <error>)
       
   321  * @param cond       The error condition
       
   322  * @param jinglecond The jingle error condition
       
   323  * 
       
   324  * Use jingle_new_iq_error internally to generate a LmMessage.
   296  */
   325  */
   297 void jingle_send_iq_error(LmMessage *m, const gchar *errtype,
   326 void jingle_send_iq_error(LmMessage *m, const gchar *errtype,
   298                           const gchar *cond, const gchar *jinglecond)
   327                           const gchar *cond, const gchar *jinglecond)
   299 {
   328 {
   300   LmMessage *r = jingle_new_iq_error(m, errtype, cond, jinglecond);
   329   LmMessage *r = jingle_new_iq_error(m, errtype, cond, jinglecond);
   302     lm_connection_send(lconnection, r, NULL);
   331     lm_connection_send(lconnection, r, NULL);
   303   }
   332   }
   304 }
   333 }
   305 
   334 
   306 /**
   335 /**
   307  * Find the best resource to initiate a jingle session.
   336  * @brief Find the best resource to initiate a jingle session with
   308  * Test every ressource for a given jid and return the one
   337  * @param jid The jid of the buddy
       
   338  * @param ns  The an array of namespaces we are looking for
       
   339  * @return    A ressource supporting all namespaces in ns or NULL
       
   340  *            if we couldn't find any
       
   341  * 
       
   342  * Test every ressource for the given jid and return the one
   309  * who support all namespaces in ns.
   343  * who support all namespaces in ns.
       
   344  * Note that you should free the string returned by this function.
   310  */
   345  */
   311 gchar *jingle_find_compatible_res(const gchar *jid, const gchar *ns[])
   346 gchar *jingle_find_compatible_res(const gchar *jid, const gchar *ns[])
   312 {
   347 {
   313   gchar *choosenres;
   348   gchar *choosenres;
   314   guint indexns;
   349   guint indexns;
   334 
   369 
   335   return NULL;
   370   return NULL;
   336 }
   371 }
   337 
   372 
   338 /**
   373 /**
   339  * Find the jingle_action corresponding to a string
   374  * @brief Find the JingleAction corresponding to a string
       
   375  * @param string The string to lockup
       
   376  * @return       The #JingleAction or JINGLE_UNKNOWN_ACTION if
       
   377  *               string is not a jingle action
   340  */
   378  */
   341 JingleAction jingle_action_from_str(const gchar *string)
   379 JingleAction jingle_action_from_str(const gchar *string)
   342 {
   380 {
   343   guint i, actstrlen = sizeof(jingle_action_list)/sizeof(jingle_action_list[0]);
   381   guint i, actstrlen = sizeof(jingle_action_list)/sizeof(jingle_action_list[0]);
   344   for (i = 0; i < actstrlen; i++)
   382   for (i = 0; i < actstrlen; i++)
   347 
   385 
   348   return JINGLE_UNKNOWN_ACTION;
   386   return JINGLE_UNKNOWN_ACTION;
   349 }
   387 }
   350 
   388 
   351 /**
   389 /**
   352  * This function should not be called if jn->message was created
   390  * @brief Free a JingleNode struct
   353  * using lm_message_from_jinglenode because loudmouth strdup
   391  * 
   354  * strings we insert as attributes. the pointers in the LmMessage
   392  * Since the JingleNode contains only pointers to the attributes
   355  * and the JingleNode would not refer to the same addresses and
   393  * and nodes of the LmMessage, we only have to unref the LmMessage
   356  * a call to lm_message_unref would not free the data from the
   394  * and free() the struct itself to destroy it.
   357  * JingleNode.
       
   358  */
   395  */
   359 void jingle_free_jinglenode(JingleNode *jn)
   396 void jingle_free_jinglenode(JingleNode *jn)
   360 {
   397 {
   361   g_slist_foreach(jn->content, (GFunc)g_free, NULL);
   398   g_slist_foreach(jn->content, (GFunc)g_free, NULL);
   362   g_slist_free(jn->content);
   399   g_slist_free(jn->content);
   363   lm_message_unref(jn->message);
   400   lm_message_unref(jn->message);
   364   g_free(jn);
   401   g_free(jn);
   365 }
   402 }
   366 
   403 
       
   404 /**
       
   405  * @brief Unregister our IQ handler to loudmouth.
       
   406  */
   367 static void jingle_unregister_lm_handlers(void)
   407 static void jingle_unregister_lm_handlers(void)
   368 {
   408 {
   369   if (lconnection) {
   409   if (lconnection) {
   370     lm_connection_unregister_message_handler(lconnection, jingle_iq_handler,
   410     lm_connection_unregister_message_handler(lconnection, jingle_iq_handler,
   371         LM_MESSAGE_TYPE_IQ);
   411         LM_MESSAGE_TYPE_IQ);
   372   }
   412   }
   373 }
   413 }
   374 
   414 
       
   415 /**
       
   416  * @brief Register our IQ handler to loudmouth.
       
   417  */
   375 static void jingle_register_lm_handlers(void)
   418 static void jingle_register_lm_handlers(void)
   376 {
   419 {
   377   jingle_unregister_lm_handlers();
   420   jingle_unregister_lm_handlers();
   378   if (lconnection) {
   421   if (lconnection) {
   379     lm_connection_register_message_handler(lconnection, jingle_iq_handler,
   422     lm_connection_register_message_handler(lconnection, jingle_iq_handler,