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, |