27 #include <mcabber/xmpp.h> |
27 #include <mcabber/xmpp.h> |
28 #include <mcabber/hooks.h> |
28 #include <mcabber/hooks.h> |
29 #include <mcabber/modules.h> |
29 #include <mcabber/modules.h> |
30 #include <mcabber/logprint.h> |
30 #include <mcabber/logprint.h> |
31 #include <mcabber/xmpp_helper.h> |
31 #include <mcabber/xmpp_helper.h> |
|
32 #include <mcabber/events.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/action-handlers.h> |
36 #include <jingle/action-handlers.h> |
36 #include <jingle/register.h> |
37 #include <jingle/register.h> |
37 #include <jingle/send.h> |
38 #include <jingle/send.h> |
38 #include <jingle/general-handlers.h> |
39 |
39 |
40 |
40 static void jingle_register_lm_handlers(void); |
41 static void jingle_register_lm_handlers(void); |
41 static void jingle_unregister_lm_handlers(void); |
42 static void jingle_unregister_lm_handlers(void); |
42 static guint jingle_connect_hh(const gchar *hname, hk_arg_t *args, |
43 static guint jingle_connect_hh(const gchar *hname, hk_arg_t *args, |
43 gpointer ignore); |
44 gpointer ignore); |
47 static void jingle_uninit(void); |
48 static void jingle_uninit(void); |
48 static void lm_insert_jinglecontent(gpointer data, gpointer userdata); |
49 static void lm_insert_jinglecontent(gpointer data, gpointer userdata); |
49 |
50 |
50 |
51 |
51 static LmMessageHandler* jingle_iq_handler = NULL; |
52 static LmMessageHandler* jingle_iq_handler = NULL; |
52 LmMessageHandler* jingle_ack_iq_handler = NULL; |
53 static GSList *ack_handlers = NULL; |
53 static guint connect_hid = 0; |
54 static guint connect_hid = 0; |
54 static guint disconn_hid = 0; |
55 static guint disconn_hid = 0; |
55 |
56 |
56 /** |
57 /** |
57 * Must be aligned with the values in JingleAction |
58 * Must be aligned with the values in JingleAction |
132 |
133 |
133 return LM_HANDLER_RESULT_REMOVE_MESSAGE; |
134 return LM_HANDLER_RESULT_REMOVE_MESSAGE; |
134 } |
135 } |
135 |
136 |
136 /** |
137 /** |
|
138 * Handle incoming ack iq (type result or error). |
|
139 */ |
|
140 LmHandlerResult jingle_handle_ack_iq(LmMessageHandler *handler, |
|
141 LmConnection *connection, |
|
142 LmMessage *message, gpointer user_data) |
|
143 { |
|
144 ack_handlers = g_slist_remove(ack_handlers, handler); |
|
145 lm_message_handler_unref(handler); |
|
146 |
|
147 // TODO: check subtype |
|
148 if (user_data != NULL) { |
|
149 JingleAckHandle *ah = user_data; |
|
150 if(ah->callback != NULL) |
|
151 ah->callback(message, ah->user_data); |
|
152 |
|
153 g_free(ah); |
|
154 } |
|
155 |
|
156 return LM_HANDLER_RESULT_REMOVE_MESSAGE; |
|
157 } |
|
158 |
|
159 LmMessageHandler *jingle_new_ack_handler(JingleAckHandle *ah) |
|
160 { |
|
161 LmMessageHandler *h = lm_message_handler_new(jingle_handle_ack_iq, |
|
162 (gpointer) ah, NULL); |
|
163 ack_handlers = g_slist_append(ack_handlers, h); |
|
164 return h; |
|
165 } |
|
166 |
|
167 /** |
|
168 * mcabber /event callback. |
|
169 */ |
|
170 gboolean evscallback_jingle(guint evcontext, const gchar *arg, |
|
171 gpointer userdata) |
|
172 { |
|
173 JingleNode *jn = userdata; |
|
174 |
|
175 /* |
|
176 if (G_UNLIKELY(!jn)) { |
|
177 scr_LogPrint(LPRINT_LOGNORM, "Error in evs callback."); |
|
178 return FALSE; |
|
179 } |
|
180 */ |
|
181 |
|
182 if (evcontext == EVS_CONTEXT_TIMEOUT) { |
|
183 scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s timed out, cancelled.", |
|
184 jn->initiator); |
|
185 jingle_free_jinglenode(jn); |
|
186 return FALSE; |
|
187 } |
|
188 if (evcontext = EVS_CONTEXT_CANCEL) { |
|
189 scr_LogPrint(LPRINT_LOGNORM, "Jingle event from %s cancelled.", |
|
190 jn->initiator); |
|
191 jingle_free_jinglenode(jn); |
|
192 return FALSE; |
|
193 } |
|
194 if (!(evcontext == EVS_CONTEXT_ACCEPT || evcontext == EVS_CONTEXT_REJECT)) { |
|
195 jingle_free_jinglenode(jn); |
|
196 return FALSE; |
|
197 } |
|
198 |
|
199 if (evcontext == EVS_CONTEXT_ACCEPT) { |
|
200 jingle_send_session_accept(jn); |
|
201 } else { |
|
202 jingle_send_session_terminate(jn, "decline"); |
|
203 jingle_free_jinglenode(jn); |
|
204 } |
|
205 |
|
206 return FALSE; |
|
207 } |
|
208 |
|
209 /** |
137 * According to the specifications: |
210 * According to the specifications: |
138 * "An entity that receives an IQ request of type "get" or "set" MUST |
211 * "An entity that receives an IQ request of type "get" or "set" MUST |
139 * reply with an IQ response of type "result" or "error"." |
212 * reply with an IQ response of type "result" or "error"." |
140 * For Jingle's IQ, we have to reply with an empty "result" IQ to acknowledge |
213 * For Jingle's IQ, we have to reply with an empty "result" IQ to acknowledge |
141 * receipt. |
214 * receipt. |
181 * Reply to a Jingle IQ with an error. |
254 * Reply to a Jingle IQ with an error. |
182 */ |
255 */ |
183 void jingle_send_iq_error(LmMessage *m, const gchar *errtype, |
256 void jingle_send_iq_error(LmMessage *m, const gchar *errtype, |
184 const gchar *cond, const gchar *jinglecond) |
257 const gchar *cond, const gchar *jinglecond) |
185 { |
258 { |
186 ack_iq *elem; |
|
187 LmMessage *r = jingle_new_iq_error(m, errtype, cond, jinglecond); |
259 LmMessage *r = jingle_new_iq_error(m, errtype, cond, jinglecond); |
188 if (r) { |
260 if (r) { |
189 elem->id = g_strdup(lm_message_get_id(r)); |
261 lm_connection_send(lconnection, r, NULL); |
190 elem->callback = NULL; |
|
191 elem->udata = NULL; |
|
192 add_ack_wait(elem); |
|
193 lm_connection_send_with_reply(lconnection, r, jingle_ack_iq_handler, NULL); |
|
194 lm_message_unref(r); |
|
195 } |
262 } |
196 } |
263 } |
197 |
264 |
198 /** |
265 /** |
199 * Find the jingle_action corresponding to a string |
266 * Find the jingle_action corresponding to a string |
249 } |
316 } |
250 |
317 |
251 static void jingle_init(void) |
318 static void jingle_init(void) |
252 { |
319 { |
253 jingle_iq_handler = lm_message_handler_new(jingle_handle_iq, NULL, NULL); |
320 jingle_iq_handler = lm_message_handler_new(jingle_handle_iq, NULL, NULL); |
254 jingle_ack_iq_handler = lm_message_handler_new(jingle_handle_ack_iq, NULL, |
|
255 NULL); |
|
256 xmpp_add_feature(NS_JINGLE); |
321 xmpp_add_feature(NS_JINGLE); |
257 |
322 |
258 connect_hid = hk_add_handler(jingle_connect_hh, HOOK_POST_CONNECT, |
323 connect_hid = hk_add_handler(jingle_connect_hh, HOOK_POST_CONNECT, |
259 G_PRIORITY_DEFAULT_IDLE, NULL); |
324 G_PRIORITY_DEFAULT_IDLE, NULL); |
260 disconn_hid = hk_add_handler(jingle_disconn_hh, HOOK_PRE_DISCONNECT, |
325 disconn_hid = hk_add_handler(jingle_disconn_hh, HOOK_PRE_DISCONNECT, |
270 hk_del_handler(HOOK_PRE_DISCONNECT, disconn_hid); |
335 hk_del_handler(HOOK_PRE_DISCONNECT, disconn_hid); |
271 jingle_unregister_lm_handlers(); |
336 jingle_unregister_lm_handlers(); |
272 |
337 |
273 lm_message_handler_invalidate(jingle_iq_handler); |
338 lm_message_handler_invalidate(jingle_iq_handler); |
274 lm_message_handler_unref(jingle_iq_handler); |
339 lm_message_handler_unref(jingle_iq_handler); |
275 lm_message_handler_invalidate(jingle_ack_iq_handler); |
|
276 lm_message_handler_unref(jingle_ack_iq_handler); |
|
277 } |
340 } |
278 |
341 |
279 LmMessage *lm_message_from_jinglenode(const JingleNode *jn, const gchar *to) |
342 LmMessage *lm_message_from_jinglenode(const JingleNode *jn, const gchar *to) |
280 { |
343 { |
281 LmMessage* m; |
344 LmMessage* m; |