Add required items for Google video support.
[asterisk/asterisk.git] / channels / chan_motif.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \author Joshua Colp <jcolp@digium.com>
22  *
23  * \brief Motif Jingle Channel Driver
24  *
25  * \extref Iksemel http://iksemel.jabberstudio.org/
26  *
27  * \ingroup channel_drivers
28  */
29
30 /*** MODULEINFO
31         <depend>iksemel</depend>
32         <depend>res_xmpp</depend>
33         <use type="external">openssl</use>
34         <support_level>core</support_level>
35  ***/
36
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include <sys/socket.h>
42 #include <fcntl.h>
43 #include <netdb.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <sys/signal.h>
47 #include <iksemel.h>
48 #include <pthread.h>
49
50 #include "asterisk/lock.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/config_options.h"
53 #include "asterisk/module.h"
54 #include "asterisk/pbx.h"
55 #include "asterisk/sched.h"
56 #include "asterisk/io.h"
57 #include "asterisk/rtp_engine.h"
58 #include "asterisk/acl.h"
59 #include "asterisk/callerid.h"
60 #include "asterisk/file.h"
61 #include "asterisk/cli.h"
62 #include "asterisk/app.h"
63 #include "asterisk/musiconhold.h"
64 #include "asterisk/manager.h"
65 #include "asterisk/stringfields.h"
66 #include "asterisk/utils.h"
67 #include "asterisk/causes.h"
68 #include "asterisk/astobj.h"
69 #include "asterisk/abstract_jb.h"
70 #include "asterisk/xmpp.h"
71
72 /*! \brief Default maximum number of ICE candidates we will offer */
73 #define DEFAULT_MAX_ICE_CANDIDATES "10"
74
75 /*! \brief Default maximum number of payloads we will offer */
76 #define DEFAULT_MAX_PAYLOADS "30"
77
78 /*! \brief Number of buckets for endpoints */
79 #define ENDPOINT_BUCKETS 37
80
81 /*! \brief Number of buckets for sessions, on a per-endpoint basis */
82 #define SESSION_BUCKETS 37
83
84 /*! \brief Namespace for Jingle itself */
85 #define JINGLE_NS "urn:xmpp:jingle:1"
86
87 /*! \brief Namespace for Jingle RTP sessions */
88 #define JINGLE_RTP_NS "urn:xmpp:jingle:apps:rtp:1"
89
90 /*! \brief Namespace for Jingle RTP info */
91 #define JINGLE_RTP_INFO_NS "urn:xmpp:jingle:apps:rtp:info:1"
92
93 /*! \brief Namespace for Jingle ICE-UDP */
94 #define JINGLE_ICE_UDP_NS "urn:xmpp:jingle:transports:ice-udp:1"
95
96 /*! \brief Namespace for Google Talk ICE-UDP */
97 #define GOOGLE_TRANSPORT_NS "http://www.google.com/transport/p2p"
98
99 /*! \brief Namespace for Google Talk Raw UDP */
100 #define GOOGLE_TRANSPORT_RAW_NS "http://www.google.com/transport/raw-udp"
101
102 /*! \brief Namespace for Google Session */
103 #define GOOGLE_SESSION_NS "http://www.google.com/session"
104
105 /*! \brief Namespace for Google Phone description */
106 #define GOOGLE_PHONE_NS "http://www.google.com/session/phone"
107
108 /*! \brief Namespace for Google Video description */
109 #define GOOGLE_VIDEO_NS "http://www.google.com/session/video"
110
111 /*! \brief Namespace for XMPP stanzas */
112 #define XMPP_STANZAS_NS "urn:ietf:params:xml:ns:xmpp-stanzas"
113
114 /*! \brief The various transport methods supported, from highest priority to lowest priority when doing fallback */
115 enum jingle_transport {
116         JINGLE_TRANSPORT_ICE_UDP = 3,   /*!< XEP-0176 */
117         JINGLE_TRANSPORT_GOOGLE_V2 = 2, /*!< https://developers.google.com/talk/call_signaling */
118         JINGLE_TRANSPORT_GOOGLE_V1 = 1, /*!< Undocumented initial Google specification */
119         JINGLE_TRANSPORT_NONE = 0,      /*!< No transport specified */
120 };
121
122 /*! \brief Endpoint state information */
123 struct jingle_endpoint_state {
124         struct ao2_container *sessions; /*!< Active sessions to or from the endpoint */
125 };
126
127 /*! \brief Endpoint which contains configuration information and active sessions */
128 struct jingle_endpoint {
129         AST_DECLARE_STRING_FIELDS(
130                 AST_STRING_FIELD(name);              /*!< Name of the endpoint */
131                 AST_STRING_FIELD(context);           /*!< Context to place incoming calls into */
132                 AST_STRING_FIELD(accountcode);       /*!< Account code */
133                 AST_STRING_FIELD(language);          /*!< Default language for prompts */
134                 AST_STRING_FIELD(musicclass);        /*!< Configured music on hold class */
135                 AST_STRING_FIELD(parkinglot);        /*!< Configured parking lot */
136                 );
137         struct ast_xmpp_client *connection;     /*!< Connection to use for traffic */
138         iksrule *rule;                          /*!< Active matching rule */
139         unsigned int maxicecandidates;          /*!< Maximum number of ICE candidates we will offer */
140         unsigned int maxpayloads;               /*!< Maximum number of payloads we will offer */
141         struct ast_codec_pref prefs;            /*!< Codec preferences */
142         struct ast_format_cap *cap;             /*!< Formats to use */
143         ast_group_t callgroup;                  /*!< Call group */
144         ast_group_t pickupgroup;                /*!< Pickup group */
145         enum jingle_transport transport;        /*!< Default transport to use on outgoing sessions */
146         struct jingle_endpoint_state *state;    /*!< Endpoint state information */
147 };
148
149 /*! \brief Session which contains information about an active session */
150 struct jingle_session {
151         AST_DECLARE_STRING_FIELDS(
152                 AST_STRING_FIELD(sid);        /*!< Session identifier */
153                 AST_STRING_FIELD(audio_name); /*!< Name of the audio content */
154                 AST_STRING_FIELD(video_name); /*!< Name of the video content */
155                 );
156         struct jingle_endpoint_state *state;  /*!< Endpoint we are associated with */
157         struct ast_xmpp_client *connection;   /*!< Connection to use for traffic */
158         enum jingle_transport transport;      /*!< Transport type to use for this session */
159         unsigned int maxicecandidates;        /*!< Maximum number of ICE candidates we will offer */
160         unsigned int maxpayloads;             /*!< Maximum number of payloads we will offer */
161         char remote_original[XMPP_MAX_JIDLEN];/*!< Identifier of the original remote party (remote may have changed due to redirect) */
162         char remote[XMPP_MAX_JIDLEN];         /*!< Identifier of the remote party */
163         iksrule *rule;                        /*!< Session matching rule */
164         struct ast_codec_pref prefs;          /*!< Codec preferences */
165         struct ast_channel *owner;            /*!< Master Channel */
166         struct ast_rtp_instance *rtp;         /*!< RTP audio session */
167         struct ast_rtp_instance *vrtp;        /*!< RTP video session */
168         struct ast_format_cap *cap;           /*!< Local codec capabilities */
169         struct ast_format_cap *jointcap;      /*!< Joint codec capabilities */
170         struct ast_format_cap *peercap;       /*!< Peer codec capabilities */
171         unsigned int outgoing:1;              /*!< Whether this is an outgoing leg or not */
172         unsigned int gone:1;                  /*!< In the eyes of Jingle this session is already gone */
173 };
174
175 static const char desc[] = "Motif Jingle Channel";
176 static const char channel_type[] = "Motif";
177
178 struct jingle_config {
179         struct ao2_container *endpoints; /*!< Configured endpoints */
180 };
181
182 static AO2_GLOBAL_OBJ_STATIC(globals);
183
184 static struct ast_sched_context *sched; /*!< Scheduling context for RTCP */
185
186 /* \brief Asterisk core interaction functions */
187 static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
188 static int jingle_sendtext(struct ast_channel *ast, const char *text);
189 static int jingle_digit_begin(struct ast_channel *ast, char digit);
190 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
191 static int jingle_call(struct ast_channel *ast, const char *dest, int timeout);
192 static int jingle_hangup(struct ast_channel *ast);
193 static int jingle_answer(struct ast_channel *ast);
194 static struct ast_frame *jingle_read(struct ast_channel *ast);
195 static int jingle_write(struct ast_channel *ast, struct ast_frame *f);
196 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
197 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
198 static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, const char *from, const char *sid);
199
200 /*! \brief Action handlers */
201 static void jingle_action_session_initiate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
202 static void jingle_action_transport_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
203 static void jingle_action_session_accept(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
204 static void jingle_action_session_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
205 static void jingle_action_session_terminate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
206
207 /*! \brief PBX interface structure for channel registration */
208 static struct ast_channel_tech jingle_tech = {
209         .type = "Motif",
210         .description = "Motif Jingle Channel Driver",
211         .requester = jingle_request,
212         .send_text = jingle_sendtext,
213         .send_digit_begin = jingle_digit_begin,
214         .send_digit_end = jingle_digit_end,
215         .bridge = ast_rtp_instance_bridge,
216         .call = jingle_call,
217         .hangup = jingle_hangup,
218         .answer = jingle_answer,
219         .read = jingle_read,
220         .write = jingle_write,
221         .write_video = jingle_write,
222         .exception = jingle_read,
223         .indicate = jingle_indicate,
224         .fixup = jingle_fixup,
225         .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER
226 };
227
228 /*! \brief Defined handlers for different Jingle actions */
229 static const struct jingle_action_handler {
230         const char *action;
231         void (*handler)(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak);
232 } jingle_action_handlers[] = {
233         /* Jingle actions */
234         { "session-initiate", jingle_action_session_initiate, },
235         { "transport-info", jingle_action_transport_info, },
236         { "session-accept", jingle_action_session_accept, },
237         { "session-info", jingle_action_session_info, },
238         { "session-terminate", jingle_action_session_terminate, },
239         /* Google-V1 actions */
240         { "initiate", jingle_action_session_initiate, },
241         { "candidates", jingle_action_transport_info, },
242         { "accept", jingle_action_session_accept, },
243         { "terminate", jingle_action_session_terminate, },
244         { "reject", jingle_action_session_terminate, },
245 };
246
247 /*! \brief Reason text <-> cause code mapping */
248 static const struct jingle_reason_mapping {
249         const char *reason;
250         int cause;
251 } jingle_reason_mappings[] = {
252         { "busy", AST_CAUSE_BUSY, },
253         { "cancel", AST_CAUSE_CALL_REJECTED, },
254         { "connectivity-error", AST_CAUSE_INTERWORKING, },
255         { "decline", AST_CAUSE_CALL_REJECTED, },
256         { "expired", AST_CAUSE_NO_USER_RESPONSE, },
257         { "failed-transport", AST_CAUSE_PROTOCOL_ERROR, },
258         { "failed-application", AST_CAUSE_SWITCH_CONGESTION, },
259         { "general-error", AST_CAUSE_CONGESTION, },
260         { "gone", AST_CAUSE_NORMAL_CLEARING, },
261         { "incompatible-parameters", AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, },
262         { "media-error", AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, },
263         { "security-error", AST_CAUSE_PROTOCOL_ERROR, },
264         { "success", AST_CAUSE_NORMAL_CLEARING, },
265         { "timeout", AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, },
266         { "unsupported-applications", AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, },
267         { "unsupported-transports", AST_CAUSE_FACILITY_NOT_IMPLEMENTED, },
268 };
269
270 /*! \brief Hashing function for Jingle sessions */
271 static int jingle_session_hash(const void *obj, const int flags)
272 {
273         const struct jingle_session *session = obj;
274         const char *sid = obj;
275
276         return ast_str_hash(flags & OBJ_KEY ? sid : session->sid);
277 }
278
279 /*! \brief Comparator function for Jingle sessions */
280 static int jingle_session_cmp(void *obj, void *arg, int flags)
281 {
282         struct jingle_session *session1 = obj, *session2 = arg;
283         const char *sid = arg;
284
285         return !strcmp(session1->sid, flags & OBJ_KEY ? sid : session2->sid) ? CMP_MATCH | CMP_STOP : 0;
286 }
287
288 /*! \brief Destructor for Jingle endpoint state */
289 static void jingle_endpoint_state_destructor(void *obj)
290 {
291         struct jingle_endpoint_state *state = obj;
292
293         ao2_ref(state->sessions, -1);
294 }
295
296 /*! \brief Destructor for Jingle endpoints */
297 static void jingle_endpoint_destructor(void *obj)
298 {
299         struct jingle_endpoint *endpoint = obj;
300
301         if (endpoint->rule) {
302                 iks_filter_remove_rule(endpoint->connection->filter, endpoint->rule);
303         }
304
305         if (endpoint->connection) {
306                 ast_xmpp_client_unref(endpoint->connection);
307         }
308
309         ast_format_cap_destroy(endpoint->cap);
310
311         ao2_ref(endpoint->state, -1);
312
313         ast_string_field_free_memory(endpoint);
314 }
315
316 /*! \brief Find function for Jingle endpoints */
317 static void *jingle_endpoint_find(struct ao2_container *tmp_container, const char *category)
318 {
319         return ao2_find(tmp_container, category, OBJ_KEY);
320 }
321
322 /*! \brief Allocator function for Jingle endpoint state */
323 static struct jingle_endpoint_state *jingle_endpoint_state_create(void)
324 {
325         struct jingle_endpoint_state *state;
326
327         if (!(state = ao2_alloc(sizeof(*state), jingle_endpoint_state_destructor))) {
328                 return NULL;
329         }
330
331         if (!(state->sessions = ao2_container_alloc(SESSION_BUCKETS, jingle_session_hash, jingle_session_cmp))) {
332                 ao2_ref(state, -1);
333                 return NULL;
334         }
335
336         return state;
337 }
338
339 /*! \brief State find/create function */
340 static struct jingle_endpoint_state *jingle_endpoint_state_find_or_create(const char *category)
341 {
342         RAII_VAR(struct jingle_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
343         RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
344
345         if (!cfg || !cfg->endpoints || !(endpoint = jingle_endpoint_find(cfg->endpoints, category))) {
346                 return jingle_endpoint_state_create();
347         }
348
349         ao2_ref(endpoint->state, +1);
350         return endpoint->state;
351 }
352
353 /*! \brief Allocator function for Jingle endpoints */
354 static void *jingle_endpoint_alloc(const char *cat)
355 {
356         struct jingle_endpoint *endpoint;
357
358         if (!(endpoint = ao2_alloc(sizeof(*endpoint), jingle_endpoint_destructor))) {
359                 return NULL;
360         }
361
362         if (ast_string_field_init(endpoint, 512)) {
363                 ao2_ref(endpoint, -1);
364                 return NULL;
365         }
366
367         if (!(endpoint->state = jingle_endpoint_state_find_or_create(cat))) {
368                 ao2_ref(endpoint, -1);
369                 return NULL;
370         }
371
372         ast_string_field_set(endpoint, name, cat);
373
374         endpoint->cap = ast_format_cap_alloc_nolock();
375         endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
376
377         return endpoint;
378 }
379
380 /*! \brief Hashing function for Jingle endpoints */
381 static int jingle_endpoint_hash(const void *obj, const int flags)
382 {
383         const struct jingle_endpoint *endpoint = obj;
384         const char *name = obj;
385
386         return ast_str_hash(flags & OBJ_KEY ? name : endpoint->name);
387 }
388
389 /*! \brief Comparator function for Jingle endpoints */
390 static int jingle_endpoint_cmp(void *obj, void *arg, int flags)
391 {
392         struct jingle_endpoint *endpoint1 = obj, *endpoint2 = arg;
393         const char *name = arg;
394
395         return !strcmp(endpoint1->name, flags & OBJ_KEY ? name : endpoint2->name) ? CMP_MATCH | CMP_STOP : 0;
396 }
397
398 static struct aco_type endpoint_option = {
399         .type = ACO_ITEM,
400         .category_match = ACO_BLACKLIST,
401         .category = "^general$",
402         .item_alloc = jingle_endpoint_alloc,
403         .item_find = jingle_endpoint_find,
404         .item_offset = offsetof(struct jingle_config, endpoints),
405 };
406
407 struct aco_type *endpoint_options[] = ACO_TYPES(&endpoint_option);
408
409 struct aco_file jingle_conf = {
410         .filename = "motif.conf",
411         .types = ACO_TYPES(&endpoint_option),
412 };
413
414 /*! \brief Destructor for Jingle sessions */
415 static void jingle_session_destructor(void *obj)
416 {
417         struct jingle_session *session = obj;
418
419         if (session->rule) {
420                 iks_filter_remove_rule(session->connection->filter, session->rule);
421         }
422
423         if (session->connection) {
424                 ast_xmpp_client_unref(session->connection);
425         }
426
427         if (session->rtp) {
428                 ast_rtp_instance_destroy(session->rtp);
429         }
430
431         if (session->vrtp) {
432                 ast_rtp_instance_destroy(session->vrtp);
433         }
434
435         ast_format_cap_destroy(session->cap);
436         ast_format_cap_destroy(session->jointcap);
437         ast_format_cap_destroy(session->peercap);
438
439         ast_string_field_free_memory(session);
440 }
441
442 /*! \brief Destructor called when module configuration goes away */
443 static void jingle_config_destructor(void *obj)
444 {
445         struct jingle_config *cfg = obj;
446         ao2_cleanup(cfg->endpoints);
447 }
448
449 /*! \brief Allocator called when module configuration should appear */
450 static void *jingle_config_alloc(void)
451 {
452         struct jingle_config *cfg;
453
454         if (!(cfg = ao2_alloc(sizeof(*cfg), jingle_config_destructor))) {
455                 return NULL;
456         }
457
458         if (!(cfg->endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, jingle_endpoint_hash, jingle_endpoint_cmp))) {
459                 ao2_ref(cfg, -1);
460                 return NULL;
461         }
462
463         return cfg;
464 }
465
466 CONFIG_INFO_STANDARD(cfg_info, globals, jingle_config_alloc,
467                      .files = ACO_FILES(&jingle_conf),
468         );
469
470 /*! \brief Function called by RTP engine to get local RTP peer */
471 static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
472 {
473         struct jingle_session *session = ast_channel_tech_pvt(chan);
474         enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
475
476         if (!session->rtp) {
477                 return AST_RTP_GLUE_RESULT_FORBID;
478         }
479
480         ao2_ref(session->rtp, +1);
481         *instance = session->rtp;
482
483         return res;
484 }
485
486 /*! \brief Function called by RTP engine to get peer capabilities */
487 static void jingle_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
488 {
489 }
490
491 /*! \brief Function called by RTP engine to change where the remote party should send media */
492 static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active)
493 {
494         return -1;
495 }
496
497 /*! \brief Local glue for interacting with the RTP engine core */
498 static struct ast_rtp_glue jingle_rtp_glue = {
499         .type = "Motif",
500         .get_rtp_info = jingle_get_rtp_peer,
501         .get_codec = jingle_get_codec,
502         .update_peer = jingle_set_rtp_peer,
503 };
504
505 /*! \brief Internal helper function which enables video support on a sesson if possible */
506 static void jingle_enable_video(struct jingle_session *session)
507 {
508         struct ast_sockaddr tmp;
509         struct ast_rtp_engine_ice *ice;
510
511         /* If video is already present don't do anything */
512         if (session->vrtp) {
513                 return;
514         }
515
516         /* If there are no configured video codecs do not turn video support on, it just won't work */
517         if (!ast_format_cap_has_type(session->cap, AST_FORMAT_TYPE_VIDEO)) {
518                 return;
519         }
520
521         ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
522
523         if (!(session->vrtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
524                 return;
525         }
526
527         ast_rtp_instance_set_prop(session->vrtp, AST_RTP_PROPERTY_RTCP, 1);
528
529         ast_channel_set_fd(session->owner, 2, ast_rtp_instance_fd(session->vrtp, 0));
530         ast_channel_set_fd(session->owner, 3, ast_rtp_instance_fd(session->vrtp, 1));
531         ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->vrtp), session->vrtp, &session->prefs);
532
533         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
534                 ice->stop(session->vrtp);
535         }
536 }
537
538 /*! \brief Internal helper function used to allocate Jingle session on an endpoint */
539 static struct jingle_session *jingle_alloc(struct jingle_endpoint *endpoint, const char *from, const char *sid)
540 {
541         struct jingle_session *session;
542         struct ast_sockaddr tmp;
543
544         if (!(session = ao2_alloc(sizeof(*session), jingle_session_destructor))) {
545                 return NULL;
546         }
547
548         if (ast_string_field_init(session, 512)) {
549                 ao2_ref(session, -1);
550                 return NULL;
551         }
552
553         if (!ast_strlen_zero(from)) {
554                 ast_copy_string(session->remote_original, from, sizeof(session->remote_original));
555                 ast_copy_string(session->remote, from, sizeof(session->remote));
556         }
557
558         if (ast_strlen_zero(sid)) {
559                 ast_string_field_build(session, sid, "%08lx%08lx", ast_random(), ast_random());
560                 session->outgoing = 1;
561                 ast_string_field_set(session, audio_name, "audio");
562                 ast_string_field_set(session, video_name, "video");
563         } else {
564                 ast_string_field_set(session, sid, sid);
565         }
566
567         ao2_ref(endpoint->state, +1);
568         session->state = endpoint->state;
569         ao2_ref(endpoint->connection, +1);
570         session->connection = endpoint->connection;
571         session->transport = endpoint->transport;
572
573         if (!(session->cap = ast_format_cap_alloc_nolock()) ||
574             !(session->jointcap = ast_format_cap_alloc_nolock()) ||
575             !(session->peercap = ast_format_cap_alloc_nolock())) {
576                 ao2_ref(session, -1);
577                 return NULL;
578         }
579
580         ast_format_cap_copy(session->cap, endpoint->cap);
581
582         /* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine
583          * that we want IPv4 */
584         ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
585
586         /* Sessions always carry audio, but video is optional so don't enable it here */
587         if (!(session->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
588                 ao2_ref(session, -1);
589                 return NULL;
590         }
591         ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_RTCP, 1);
592         ast_rtp_instance_set_prop(session->rtp, AST_RTP_PROPERTY_DTMF, 1);
593
594         memcpy(&session->prefs, &endpoint->prefs, sizeof(session->prefs));
595
596         session->maxicecandidates = endpoint->maxicecandidates;
597         session->maxpayloads = endpoint->maxpayloads;
598
599         return session;
600 }
601
602 /*! \brief Function called to create a new Jingle Asterisk channel */
603 static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct jingle_session *session, int state, const char *title, const char *linkedid, const char *cid_name)
604 {
605         struct ast_channel *chan;
606         const char *str = S_OR(title, session->remote);
607         struct ast_format tmpfmt;
608
609         if (ast_format_cap_is_empty(session->cap)) {
610                 return NULL;
611         }
612
613         if (!(chan = ast_channel_alloc(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", linkedid, 0, "Motif/%s-%04lx", str, ast_random() & 0xffff))) {
614                 return NULL;
615         }
616
617         ast_channel_tech_set(chan, &jingle_tech);
618         ast_channel_tech_pvt_set(chan, session);
619         session->owner = chan;
620
621         ast_format_cap_copy(ast_channel_nativeformats(chan), session->cap);
622         ast_codec_choose(&session->prefs, session->cap, 1, &tmpfmt);
623
624         if (session->rtp) {
625                 struct ast_rtp_engine_ice *ice;
626
627                 ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->rtp, 0));
628                 ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->rtp, 1));
629                 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(session->rtp), session->rtp, &session->prefs);
630
631                 if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
632                      (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
633                     (ice = ast_rtp_instance_get_ice(session->rtp))) {
634                         /* We stop built in ICE support because we need to fall back to old old old STUN support */
635                         ice->stop(session->rtp);
636                 }
637         }
638
639         if (state == AST_STATE_RING) {
640                 ast_channel_rings_set(chan, 1);
641         }
642
643         ast_channel_adsicpe_set(chan, AST_ADSI_UNAVAILABLE);
644
645         ast_best_codec(ast_channel_nativeformats(chan), &tmpfmt);
646         ast_format_copy(ast_channel_writeformat(chan), &tmpfmt);
647         ast_format_copy(ast_channel_rawwriteformat(chan), &tmpfmt);
648         ast_format_copy(ast_channel_readformat(chan), &tmpfmt);
649         ast_format_copy(ast_channel_rawreadformat(chan), &tmpfmt);
650
651         ao2_lock(endpoint);
652
653         ast_channel_callgroup_set(chan, endpoint->callgroup);
654         ast_channel_pickupgroup_set(chan, endpoint->pickupgroup);
655
656         if (!ast_strlen_zero(endpoint->accountcode)) {
657                 ast_channel_accountcode_set(chan, endpoint->accountcode);
658         }
659
660         if (!ast_strlen_zero(endpoint->language)) {
661                 ast_channel_language_set(chan, endpoint->language);
662         }
663
664         if (!ast_strlen_zero(endpoint->musicclass)) {
665                 ast_channel_musicclass_set(chan, endpoint->musicclass);
666         }
667
668         ast_channel_context_set(chan, endpoint->context);
669         ast_channel_exten_set(chan, "s");
670         ast_channel_priority_set(chan, 1);
671
672         ao2_unlock(endpoint);
673
674         return chan;
675 }
676
677 /*! \brief Internal helper function which sends a response */
678 static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
679 {
680         iks *response;
681
682         if (!(response = iks_new("iq"))) {
683                 ast_log(LOG_ERROR, "Unable to allocate an IKS response stanza\n");
684                 return;
685         }
686
687         iks_insert_attrib(response, "type", "result");
688         iks_insert_attrib(response, "from", connection->jid->full);
689         iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
690         iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
691
692         ast_xmpp_client_send(connection, response);
693
694         iks_delete(response);
695 }
696
697 /*! \brief Internal helper function which sends an error response */
698 static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
699 {
700         iks *response, *error = NULL, *reason = NULL, *reason2 = NULL;
701
702         if (!(response = iks_new("iq")) ||
703             !(error = iks_new("error")) ||
704             !(reason = iks_new(reasonstr))) {
705                 ast_log(LOG_ERROR, "Unable to allocate IKS error response stanzas\n");
706                 goto end;
707         }
708
709         iks_insert_attrib(response, "type", "error");
710         iks_insert_attrib(response, "from", connection->jid->full);
711         iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
712         iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
713
714         iks_insert_attrib(error, "type", type);
715         iks_insert_node(error, reason);
716
717         if (!ast_strlen_zero(reasonstr2) && (reason2 = iks_new(reasonstr2))) {
718                 iks_insert_node(error, reason2);
719         }
720
721         iks_insert_node(response, error);
722
723         ast_xmpp_client_send(connection, response);
724 end:
725         iks_delete(reason2);
726         iks_delete(reason);
727         iks_delete(error);
728         iks_delete(response);
729 }
730
731 /*! \brief Internal helper function which adds ICE-UDP candidates to a transport node */
732 static int jingle_add_ice_udp_candidates_to_transport(struct ast_rtp_instance *rtp, iks *transport, iks **candidates, unsigned int maximum)
733 {
734         struct ast_rtp_engine_ice *ice;
735         struct ao2_container *local_candidates;
736         struct ao2_iterator it;
737         struct ast_rtp_engine_ice_candidate *candidate;
738         int i = 0, res = 0;
739
740         if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
741                 ast_log(LOG_ERROR, "Unable to add ICE-UDP candidates as ICE support not available or no candidates available\n");
742                 return -1;
743         }
744
745         iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
746         iks_insert_attrib(transport, "pwd", ice->get_password(rtp));
747         iks_insert_attrib(transport, "ufrag", ice->get_ufrag(rtp));
748
749         it = ao2_iterator_init(local_candidates, 0);
750
751         while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
752                 iks *local_candidate;
753                 char tmp[30];
754
755                 if (!(local_candidate = iks_new("candidate"))) {
756                         res = -1;
757                         ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for ICE-UDP transport\n");
758                         break;
759                 }
760
761                 snprintf(tmp, sizeof(tmp), "%d", candidate->id);
762                 iks_insert_attrib(local_candidate, "component", tmp);
763                 snprintf(tmp, sizeof(tmp), "%d", ast_str_hash(candidate->foundation));
764                 iks_insert_attrib(local_candidate, "foundation", tmp);
765                 iks_insert_attrib(local_candidate, "generation", "0");
766                 snprintf(tmp, sizeof(tmp), "%04lx", ast_random() & 0xffff);
767                 iks_insert_attrib(local_candidate, "id", tmp);
768                 iks_insert_attrib(local_candidate, "ip", ast_sockaddr_stringify_host(&candidate->address));
769                 iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
770                 snprintf(tmp, sizeof(tmp), "%d", candidate->priority);
771                 iks_insert_attrib(local_candidate, "priority", tmp);
772                 iks_insert_attrib(local_candidate, "protocol", "udp");
773
774                 if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
775                         iks_insert_attrib(local_candidate, "type", "host");
776                 } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
777                         iks_insert_attrib(local_candidate, "type", "srflx");
778                 } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_RELAYED) {
779                         iks_insert_attrib(local_candidate, "type", "relay");
780                 }
781
782                 iks_insert_node(transport, local_candidate);
783                 candidates[i++] = local_candidate;
784         }
785
786         ao2_iterator_destroy(&it);
787         ao2_ref(local_candidates, -1);
788
789         return res;
790 }
791
792 /*! \brief Internal helper function which adds Google candidates to a transport node */
793 static int jingle_add_google_candidates_to_transport(struct ast_rtp_instance *rtp, iks *transport, iks **candidates, unsigned int video, enum jingle_transport transport_type, unsigned int maximum)
794 {
795         struct ast_rtp_engine_ice *ice;
796         struct ao2_container *local_candidates;
797         struct ao2_iterator it;
798         struct ast_rtp_engine_ice_candidate *candidate;
799         int i = 0, res = 0;
800
801         if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
802                 ast_log(LOG_ERROR, "Unable to add Google ICE candidates as ICE support not available or no candidates available\n");
803                 return -1;
804         }
805
806         if (transport_type != JINGLE_TRANSPORT_GOOGLE_V1) {
807                 iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
808         }
809
810         it = ao2_iterator_init(local_candidates, 0);
811
812         while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
813                 iks *local_candidate;
814                 /* In Google land a username is 16 bytes, explicitly */
815                 char ufrag[17] = "";
816
817                 if (!(local_candidate = iks_new("candidate"))) {
818                         res = -1;
819                         ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for Google ICE transport\n");
820                         break;
821                 }
822
823                 if (candidate->id == 1) {
824                         iks_insert_attrib(local_candidate, "name", !video ? "rtp" : "video_rtp");
825                 } else if (candidate->id == 2) {
826                         iks_insert_attrib(local_candidate, "name", !video ? "rtcp" : "video_rtcp");
827                 } else {
828                         iks_delete(local_candidate);
829                         continue;
830                 }
831
832                 iks_insert_attrib(local_candidate, "address", ast_sockaddr_stringify_host(&candidate->address));
833                 iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
834
835                 if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
836                         iks_insert_attrib(local_candidate, "preference", "0.95");
837                         iks_insert_attrib(local_candidate, "type", "local");
838                 } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
839                         iks_insert_attrib(local_candidate, "preference", "0.9");
840                         iks_insert_attrib(local_candidate, "type", "stun");
841                 }
842
843                 iks_insert_attrib(local_candidate, "protocol", "udp");
844                 iks_insert_attrib(local_candidate, "network", "0");
845                 snprintf(ufrag, sizeof(ufrag), "%s", ice->get_ufrag(rtp));
846                 iks_insert_attrib(local_candidate, "username", ufrag);
847                 iks_insert_attrib(local_candidate, "generation", "0");
848
849                 if (transport_type == JINGLE_TRANSPORT_GOOGLE_V1) {
850                         iks_insert_attrib(local_candidate, "password", "");
851                         iks_insert_attrib(local_candidate, "foundation", "0");
852                         iks_insert_attrib(local_candidate, "component", "1");
853                 } else {
854                         iks_insert_attrib(local_candidate, "password", ice->get_password(rtp));
855                 }
856
857                 /* You may notice a lack of relay support up above - this is because we don't support it for use with
858                  * the Google talk transport due to their arcane support. */
859
860                 iks_insert_node(transport, local_candidate);
861                 candidates[i++] = local_candidate;
862         }
863
864         ao2_iterator_destroy(&it);
865         ao2_ref(local_candidates, -1);
866
867         return res;
868 }
869
870 /*! \brief Internal function which sends a session-terminate message */
871 static void jingle_send_session_terminate(struct jingle_session *session, const char *reasontext)
872 {
873         iks *iq = NULL, *jingle = NULL, *reason = NULL, *text = NULL;
874
875         if (!(iq = iks_new("iq")) || !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle")) ||
876             !(reason = iks_new("reason")) || !(text = iks_new(reasontext))) {
877                 ast_log(LOG_ERROR, "Failed to allocate stanzas for session-terminate message on session '%s'\n", session->sid);
878                 goto end;
879         }
880
881         iks_insert_attrib(iq, "to", session->remote);
882         iks_insert_attrib(iq, "type", "set");
883         iks_insert_attrib(iq, "id", session->connection->mid);
884         ast_xmpp_increment_mid(session->connection->mid);
885
886         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
887                 iks_insert_attrib(jingle, "type", "terminate");
888                 iks_insert_attrib(jingle, "id", session->sid);
889                 iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
890                 iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
891         } else {
892                 iks_insert_attrib(jingle, "action", "session-terminate");
893                 iks_insert_attrib(jingle, "sid", session->sid);
894                 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
895         }
896
897         iks_insert_node(iq, jingle);
898         iks_insert_node(jingle, reason);
899         iks_insert_node(reason, text);
900
901         ast_xmpp_client_send(session->connection, iq);
902
903 end:
904         iks_delete(text);
905         iks_delete(reason);
906         iks_delete(jingle);
907         iks_delete(iq);
908 }
909
910 /*! \brief Internal function which sends a session-info message */
911 static void jingle_send_session_info(struct jingle_session *session, const char *info)
912 {
913         iks *iq = NULL, *jingle = NULL, *text = NULL;
914
915         /* Google-V1 has no way to send informational messages so don't even bother trying */
916         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
917                 return;
918         }
919
920         if (!(iq = iks_new("iq")) || !(jingle = iks_new("jingle")) || !(text = iks_new(info))) {
921                 ast_log(LOG_ERROR, "Failed to allocate stanzas for session-info message on session '%s'\n", session->sid);
922                 goto end;
923         }
924
925         iks_insert_attrib(iq, "to", session->remote);
926         iks_insert_attrib(iq, "type", "set");
927         iks_insert_attrib(iq, "id", session->connection->mid);
928         ast_xmpp_increment_mid(session->connection->mid);
929
930         iks_insert_attrib(jingle, "action", "session-info");
931         iks_insert_attrib(jingle, "sid", session->sid);
932         iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
933         iks_insert_node(iq, jingle);
934         iks_insert_node(jingle, text);
935
936         ast_xmpp_client_send(session->connection, iq);
937
938 end:
939         iks_delete(text);
940         iks_delete(jingle);
941         iks_delete(iq);
942 }
943
944 /*! \internal
945  *
946  * \brief Locks both pvt and pvt owner if owner is present.
947  *
948  * \note This function gives a ref to pvt->owner if it is present and locked.
949  *       This reference must be decremented after pvt->owner is unlocked.
950  *
951  * \note This function will never give you up,
952  * \note This function will never let you down.
953  * \note This function will run around and desert you.
954  *
955  * \pre pvt is not locked
956  * \post pvt is locked
957  * \post pvt->owner is locked and its reference count is increased (if pvt->owner is not NULL)
958  *
959  * \returns a pointer to the locked and reffed pvt->owner channel if it exists.
960  */
961 static struct ast_channel *jingle_session_lock_full(struct jingle_session *pvt)
962 {
963         struct ast_channel *chan;
964
965         /* Locking is simple when it is done right.  If you see a deadlock resulting
966          * in this function, it is not this function's fault, Your problem exists elsewhere.
967          * This function is perfect... seriously. */
968         for (;;) {
969                 /* First, get the channel and grab a reference to it */
970                 ao2_lock(pvt);
971                 chan = pvt->owner;
972                 if (chan) {
973                         /* The channel can not go away while we hold the pvt lock.
974                          * Give the channel a ref so it will not go away after we let
975                          * the pvt lock go. */
976                         ast_channel_ref(chan);
977                 } else {
978                         /* no channel, return pvt locked */
979                         return NULL;
980                 }
981
982                 /* We had to hold the pvt lock while getting a ref to the owner channel
983                  * but now we have to let this lock go in order to preserve proper
984                  * locking order when grabbing the channel lock */
985                 ao2_unlock(pvt);
986
987                 /* Look, no deadlock avoidance, hooray! */
988                 ast_channel_lock(chan);
989                 ao2_lock(pvt);
990                 if (pvt->owner == chan) {
991                         /* done */
992                         break;
993                 }
994
995                 /* If the owner changed while everything was unlocked, no problem,
996                  * just start over and everthing will work.  This is rare, do not be
997                  * confused by this loop and think this it is an expensive operation.
998                  * The majority of the calls to this function will never involve multiple
999                  * executions of this loop. */
1000                 ast_channel_unlock(chan);
1001                 ast_channel_unref(chan);
1002                 ao2_unlock(pvt);
1003         }
1004
1005         /* If owner exists, it is locked and reffed */
1006         return pvt->owner;
1007 }
1008
1009 /*! \brief Helper function which queues a hangup frame with cause code */
1010 static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
1011 {
1012         struct ast_channel *chan;
1013
1014         if ((chan = jingle_session_lock_full(session))) {
1015                 ast_debug(3, "Hanging up channel '%s' with cause '%d'\n", ast_channel_name(chan), cause);
1016                 ast_queue_hangup_with_cause(chan, cause);
1017                 ast_channel_unlock(chan);
1018                 ast_channel_unref(chan);
1019         }
1020         ao2_unlock(session);
1021 }
1022
1023 /*! \brief Internal function which sends a transport-info message */
1024 static void jingle_send_transport_info(struct jingle_session *session, const char *from)
1025 {
1026         iks *iq, *jingle = NULL, *audio = NULL, *audio_transport = NULL, *video = NULL, *video_transport = NULL;
1027         iks *audio_candidates[session->maxicecandidates], *video_candidates[session->maxicecandidates];
1028         int i, res = 0;
1029
1030         if (!(iq = iks_new("iq")) ||
1031             !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
1032                 iks_delete(iq);
1033                 jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
1034                 ast_log(LOG_ERROR, "Failed to allocate stanzas for transport-info message, hanging up session '%s'\n", session->sid);
1035                 return;
1036         }
1037
1038         memset(audio_candidates, 0, sizeof(audio_candidates));
1039         memset(video_candidates, 0, sizeof(video_candidates));
1040
1041         iks_insert_attrib(iq, "from", session->connection->jid->full);
1042         iks_insert_attrib(iq, "to", from);
1043         iks_insert_attrib(iq, "type", "set");
1044         iks_insert_attrib(iq, "id", session->connection->mid);
1045         ast_xmpp_increment_mid(session->connection->mid);
1046
1047         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1048                 iks_insert_attrib(jingle, "type", "candidates");
1049                 iks_insert_attrib(jingle, "id", session->sid);
1050                 iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1051                 iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : from);
1052         } else {
1053                 iks_insert_attrib(jingle, "action", "transport-info");
1054                 iks_insert_attrib(jingle, "sid", session->sid);
1055                 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1056         }
1057         iks_insert_node(iq, jingle);
1058
1059         if (session->rtp) {
1060                 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1061                         /* V1 protocol has the candidates directly in the session */
1062                         res = jingle_add_google_candidates_to_transport(session->rtp, jingle, audio_candidates, 0, session->transport, session->maxicecandidates);
1063                 } else if ((audio = iks_new("content")) && (audio_transport = iks_new("transport"))) {
1064                         iks_insert_attrib(audio, "creator", session->outgoing ? "initiator" : "responder");
1065                         iks_insert_attrib(audio, "name", session->audio_name);
1066                         iks_insert_node(jingle, audio);
1067                         iks_insert_node(audio, audio_transport);
1068
1069                         if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1070                                 res = jingle_add_ice_udp_candidates_to_transport(session->rtp, audio_transport, audio_candidates, session->maxicecandidates);
1071                         } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1072                                 res = jingle_add_google_candidates_to_transport(session->rtp, audio_transport, audio_candidates, 0, session->transport,
1073                                                                                 session->maxicecandidates);
1074                         }
1075                 } else {
1076                         res = -1;
1077                 }
1078         }
1079
1080         if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
1081                 if ((video = iks_new("content")) && (video_transport = iks_new("transport"))) {
1082                         iks_insert_attrib(video, "creator", session->outgoing ? "initiator" : "responder");
1083                         iks_insert_attrib(video, "name", session->video_name);
1084                         iks_insert_node(jingle, video);
1085                         iks_insert_node(video, video_transport);
1086
1087                         if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1088                                 res = jingle_add_ice_udp_candidates_to_transport(session->vrtp, video_transport, video_candidates, session->maxicecandidates);
1089                         } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1090                                 res = jingle_add_google_candidates_to_transport(session->vrtp, video_transport, video_candidates, 1, session->transport,
1091                                                                                 session->maxicecandidates);
1092                         }
1093                 } else {
1094                         res = -1;
1095                 }
1096         }
1097
1098         if (!res) {
1099                 ast_xmpp_client_send(session->connection, iq);
1100         } else {
1101                 jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
1102         }
1103
1104         /* Clean up after ourselves */
1105         for (i = 0; i < session->maxicecandidates; i++) {
1106                 iks_delete(video_candidates[i]);
1107                 iks_delete(audio_candidates[i]);
1108         }
1109
1110         iks_delete(video_transport);
1111         iks_delete(video);
1112         iks_delete(audio_transport);
1113         iks_delete(audio);
1114         iks_delete(jingle);
1115         iks_delete(iq);
1116 }
1117
1118 /*! \brief Internal helper function which adds payloads to a description */
1119 static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_format_type type)
1120 {
1121         struct ast_format format;
1122         int i = 0, res = 0;
1123
1124         ast_format_cap_iter_start(session->jointcap);
1125         while (!(ast_format_cap_iter_next(session->jointcap, &format)) && (i < (session->maxpayloads - 2))) {
1126                 int rtp_code;
1127                 iks *payload;
1128                 char tmp[32];
1129
1130                 if (AST_FORMAT_GET_TYPE(format.id) != type) {
1131                         continue;
1132                 }
1133
1134                 if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, &format, 0)) == -1) ||
1135                     (!(payload = iks_new("payload-type")))) {
1136                         res = -1;
1137                         goto end;
1138                 }
1139
1140                 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1141                         iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
1142                 }
1143
1144                 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
1145                 iks_insert_attrib(payload, "id", tmp);
1146                 iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, &format, 0, 0));
1147                 iks_insert_attrib(payload, "channels", "1");
1148
1149                 if ((format.id == AST_FORMAT_G722) && ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
1150                         iks_insert_attrib(payload, "clockrate", "16000");
1151                 } else {
1152                         snprintf(tmp, sizeof(tmp), "%d", ast_rtp_lookup_sample_rate2(1, &format, 0));
1153                         iks_insert_attrib(payload, "clockrate", tmp);
1154                 }
1155
1156                 if ((type == AST_FORMAT_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
1157                         iks *parameter;
1158
1159                         /* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */
1160                         if ((parameter = iks_new("parameter"))) {
1161                                 iks_insert_attrib(parameter, "name", "width");
1162                                 iks_insert_attrib(parameter, "value", "640");
1163                                 iks_insert_node(payload, parameter);
1164                         }
1165                         if ((parameter = iks_new("parameter"))) {
1166                                 iks_insert_attrib(parameter, "name", "height");
1167                                 iks_insert_attrib(parameter, "value", "480");
1168                                 iks_insert_node(payload, parameter);
1169                         }
1170                         if ((parameter = iks_new("parameter"))) {
1171                                 iks_insert_attrib(parameter, "name", "framerate");
1172                                 iks_insert_attrib(parameter, "value", "30");
1173                                 iks_insert_node(payload, parameter);
1174                         }
1175                 }
1176
1177                 iks_insert_node(description, payload);
1178                 payloads[i++] = payload;
1179         }
1180         /* If this is for audio and there is room for RFC2833 add it in */
1181         if ((type == AST_FORMAT_TYPE_AUDIO) && (i < session->maxpayloads)) {
1182                 iks *payload;
1183
1184                 if ((payload = iks_new("payload-type"))) {
1185                         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1186                                 iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
1187                         }
1188
1189                         iks_insert_attrib(payload, "id", "101");
1190                         iks_insert_attrib(payload, "name", "telephone-event");
1191                         iks_insert_attrib(payload, "channels", "1");
1192                         iks_insert_attrib(payload, "clockrate", "8000");
1193                         iks_insert_node(description, payload);
1194                         payloads[i++] = payload;
1195                 }
1196         }
1197
1198 end:
1199         ast_format_cap_iter_end(session->jointcap);
1200
1201         return res;
1202 }
1203
1204 /*! \brief Helper function which adds content to a description */
1205 static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport,
1206                               const char *name, enum ast_format_type type, struct ast_rtp_instance *rtp, iks **payloads)
1207 {
1208         int res = 0;
1209
1210         if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
1211                 iks_insert_attrib(content, "creator", session->outgoing ? "initiator" : "responder");
1212                 iks_insert_attrib(content, "name", name);
1213                 iks_insert_node(jingle, content);
1214
1215                 iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS);
1216                 if (type == AST_FORMAT_TYPE_AUDIO) {
1217                         iks_insert_attrib(description, "media", "audio");
1218                 } else if (type == AST_FORMAT_TYPE_VIDEO) {
1219                         iks_insert_attrib(description, "media", "video");
1220                 } else {
1221                         return -1;
1222                 }
1223                 iks_insert_node(content, description);
1224         } else {
1225                 iks_insert_attrib(description, "xmlns", GOOGLE_PHONE_NS);
1226                 iks_insert_node(jingle, description);
1227         }
1228
1229         if (!(res = jingle_add_payloads_to_description(session, rtp, description, payloads, type))) {
1230                 if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1231                         iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
1232                         iks_insert_node(content, transport);
1233                 } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1234                         iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
1235                         iks_insert_node(content, transport);
1236                 }
1237         }
1238
1239         return res;
1240 }
1241
1242 /*! \brief Internal function which sends a complete session message */
1243 static void jingle_send_session_action(struct jingle_session *session, const char *action)
1244 {
1245         iks *iq, *jingle, *audio = NULL, *audio_description = NULL, *video = NULL, *video_description = NULL;
1246         iks *audio_payloads[session->maxpayloads], *video_payloads[session->maxpayloads];
1247         iks *audio_transport = NULL, *video_transport = NULL;
1248         int i, res = 0;
1249
1250         if (!(iq = iks_new("iq")) ||
1251             !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
1252                 jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
1253                 iks_delete(iq);
1254                 return;
1255         }
1256
1257         memset(audio_payloads, 0, sizeof(audio_payloads));
1258         memset(video_payloads, 0, sizeof(video_payloads));
1259
1260         iks_insert_attrib(iq, "from", session->connection->jid->full);
1261         iks_insert_attrib(iq, "to", session->remote);
1262         iks_insert_attrib(iq, "type", "set");
1263         iks_insert_attrib(iq, "id", session->connection->mid);
1264         ast_xmpp_increment_mid(session->connection->mid);
1265
1266         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1267                 iks_insert_attrib(jingle, "type", action);
1268                 iks_insert_attrib(jingle, "id", session->sid);
1269                 iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1270         } else {
1271                 iks_insert_attrib(jingle, "action", action);
1272                 iks_insert_attrib(jingle, "sid", session->sid);
1273                 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1274         }
1275
1276         if (!strcasecmp(action, "session-initiate") || !strcasecmp(action, "initiate") || !strcasecmp(action, "accept")) {
1277                 iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
1278         }
1279
1280         iks_insert_node(iq, jingle);
1281
1282         if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) &&
1283             (audio_transport = iks_new("transport"))) {
1284                 res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name,
1285                                          AST_FORMAT_TYPE_AUDIO, session->rtp, audio_payloads);
1286         } else {
1287                 ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid);
1288                 res = -1;
1289         }
1290
1291         if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
1292                 if ((video = iks_new("content")) && (video_description = iks_new("description")) &&
1293                     (video_transport = iks_new("transport"))) {
1294                         res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name,
1295                                                  AST_FORMAT_TYPE_VIDEO, session->vrtp, video_payloads);
1296                 } else {
1297                         ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid);
1298                         res = -1;
1299                 }
1300         }
1301
1302         if (!res) {
1303                 ast_xmpp_client_send(session->connection, iq);
1304         } else {
1305                 jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
1306         }
1307
1308         iks_delete(video_transport);
1309         iks_delete(audio_transport);
1310
1311         for (i = 0; i < session->maxpayloads; i++) {
1312                 iks_delete(video_payloads[i]);
1313                 iks_delete(audio_payloads[i]);
1314         }
1315
1316         iks_delete(video_description);
1317         iks_delete(video);
1318         iks_delete(audio_description);
1319         iks_delete(audio);
1320         iks_delete(jingle);
1321         iks_delete(iq);
1322 }
1323
1324 /*! \brief Internal function which sends a session-inititate message */
1325 static void jingle_send_session_initiate(struct jingle_session *session)
1326 {
1327         jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "initiate" : "session-initiate");
1328 }
1329
1330 /*! \brief Internal function which sends a session-accept message */
1331 static void jingle_send_session_accept(struct jingle_session *session)
1332 {
1333         jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "accept" : "session-accept");
1334 }
1335
1336 /*! \brief Callback for when a response is received for an outgoing session-initiate message */
1337 static int jingle_outgoing_hook(void *data, ikspak *pak)
1338 {
1339         struct jingle_session *session = data;
1340         iks *error = iks_find(pak->x, "error"), *redirect;
1341
1342         /* In all cases this hook is done with */
1343         iks_filter_remove_rule(session->connection->filter, session->rule);
1344         session->rule = NULL;
1345
1346         /* If no error occurred they accepted our session-initiate message happily */
1347         if (!error) {
1348                 struct ast_channel *chan;
1349
1350                 if ((chan = jingle_session_lock_full(session))) {
1351                         ast_queue_control(chan, AST_CONTROL_PROCEEDING);
1352                         ast_channel_unlock(chan);
1353                         ast_channel_unref(chan);
1354                 }
1355                 ao2_unlock(session);
1356
1357                 jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
1358                 return IKS_FILTER_EAT;
1359         }
1360
1361         /* Assume that because this is an error the session is gone, there is only one case where this is incorrect - a redirect */
1362         session->gone = 1;
1363
1364         /* Map the error we received to an appropriate cause code and hang up the channel */
1365         if ((redirect = iks_find_with_attrib(error, "redirect", "xmlns", XMPP_STANZAS_NS))) {
1366                 iks *to = iks_child(redirect);
1367                 char *target;
1368
1369                 if (to && (target = iks_name(to)) && !ast_strlen_zero(target)) {
1370                         /* Make the xmpp: go away if it is present */
1371                         if (!strncmp(target, "xmpp:", 5)) {
1372                                 target += 5;
1373                         }
1374
1375                         /* This is actually a fairly simple operation - we update the remote and send another session-initiate */
1376                         ast_copy_string(session->remote, target, sizeof(session->remote));
1377
1378                         /* Add a new hook so we can get the status of redirected session */
1379                         session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1380                                                             IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1381
1382                         jingle_send_session_initiate(session);
1383
1384                         session->gone = 0;
1385                 } else {
1386                         jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
1387                 }
1388         } else if (iks_find_with_attrib(error, "service-unavailable", "xmlns", XMPP_STANZAS_NS)) {
1389                 jingle_queue_hangup_with_cause(session, AST_CAUSE_CONGESTION);
1390         } else if (iks_find_with_attrib(error, "resource-constraint", "xmlns", XMPP_STANZAS_NS)) {
1391                 jingle_queue_hangup_with_cause(session, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
1392         } else if (iks_find_with_attrib(error, "bad-request", "xmlns", XMPP_STANZAS_NS)) {
1393                 jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
1394         } else if (iks_find_with_attrib(error, "remote-server-not-found", "xmlns", XMPP_STANZAS_NS)) {
1395                 jingle_queue_hangup_with_cause(session, AST_CAUSE_NO_ROUTE_DESTINATION);
1396         } else if (iks_find_with_attrib(error, "feature-not-implemented", "xmlns", XMPP_STANZAS_NS)) {
1397                 /* Assume that this occurred because the remote side does not support our transport, so drop it down one and try again */
1398                 session->transport--;
1399
1400                 /* If we still have a viable transport mechanism re-send the session-initiate */
1401                 if (session->transport != JINGLE_TRANSPORT_NONE) {
1402                         struct ast_rtp_engine_ice *ice;
1403
1404                         if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
1405                              (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
1406                             (ice = ast_rtp_instance_get_ice(session->rtp))) {
1407                                 /* We stop built in ICE support because we need to fall back to old old old STUN support */
1408                                 ice->stop(session->rtp);
1409                         }
1410
1411                         /* Re-send the message to the *original* target and not a redirected one */
1412                         ast_copy_string(session->remote, session->remote_original, sizeof(session->remote));
1413
1414                         session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1415                                                             IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1416
1417                         jingle_send_session_initiate(session);
1418
1419                         session->gone = 0;
1420                 } else {
1421                         /* Otherwise we have exhausted all transports */
1422                         jingle_queue_hangup_with_cause(session, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
1423                 }
1424         } else {
1425                 jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
1426         }
1427
1428         return IKS_FILTER_EAT;
1429 }
1430
1431 /*! \brief Function called by core when we should answer a Jingle session */
1432 static int jingle_answer(struct ast_channel *ast)
1433 {
1434         struct jingle_session *session = ast_channel_tech_pvt(ast);
1435
1436         /* The channel has already been answered so we don't need to do anything */
1437         if (ast_channel_state(ast) == AST_STATE_UP) {
1438                 return 0;
1439         }
1440
1441         jingle_send_session_accept(session);
1442
1443         return 0;
1444 }
1445
1446 /*! \brief Function called by core to read any waiting frames */
1447 static struct ast_frame *jingle_read(struct ast_channel *ast)
1448 {
1449         struct jingle_session *session = ast_channel_tech_pvt(ast);
1450         struct ast_frame *frame = &ast_null_frame;
1451
1452         switch (ast_channel_fdno(ast)) {
1453         case 0:
1454                 if (session->rtp) {
1455                         frame = ast_rtp_instance_read(session->rtp, 0);
1456                 }
1457                 break;
1458         case 1:
1459                 if (session->rtp) {
1460                         frame = ast_rtp_instance_read(session->rtp, 1);
1461                 }
1462                 break;
1463         case 2:
1464                 if (session->vrtp) {
1465                         frame = ast_rtp_instance_read(session->vrtp, 0);
1466                 }
1467                 break;
1468         case 3:
1469                 if (session->vrtp) {
1470                         frame = ast_rtp_instance_read(session->vrtp, 1);
1471                 }
1472                 break;
1473         default:
1474                 break;
1475         }
1476
1477         if (frame && frame->frametype == AST_FRAME_VOICE &&
1478             !ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format)) {
1479                 if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) {
1480                         ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
1481                                   ast_getformatname(&frame->subclass.format), ast_channel_name(ast));
1482                         ast_frfree(frame);
1483                         frame = &ast_null_frame;
1484                 } else {
1485                         ast_debug(1, "Oooh, format changed to %s\n",
1486                                   ast_getformatname(&frame->subclass.format));
1487                         ast_format_cap_remove_bytype(ast_channel_nativeformats(ast), AST_FORMAT_TYPE_AUDIO);
1488                         ast_format_cap_add(ast_channel_nativeformats(ast), &frame->subclass.format);
1489                         ast_set_read_format(ast, ast_channel_readformat(ast));
1490                         ast_set_write_format(ast, ast_channel_writeformat(ast));
1491                 }
1492         }
1493
1494         return frame;
1495 }
1496
1497 /*! \brief Function called by core to write frames */
1498 static int jingle_write(struct ast_channel *ast, struct ast_frame *frame)
1499 {
1500         struct jingle_session *session = ast_channel_tech_pvt(ast);
1501         int res = 0;
1502         char buf[256];
1503
1504         switch (frame->frametype) {
1505         case AST_FRAME_VOICE:
1506                 if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
1507                         ast_log(LOG_WARNING,
1508                                 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1509                                 ast_getformatname(&frame->subclass.format),
1510                                 ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
1511                                 ast_getformatname(ast_channel_readformat(ast)),
1512                                 ast_getformatname(ast_channel_writeformat(ast)));
1513                         return 0;
1514                 }
1515                 if (session && session->rtp) {
1516                         res = ast_rtp_instance_write(session->rtp, frame);
1517                 }
1518                 break;
1519         case AST_FRAME_VIDEO:
1520                 if (session && session->vrtp) {
1521                         res = ast_rtp_instance_write(session->vrtp, frame);
1522                 }
1523                 break;
1524         default:
1525                 ast_log(LOG_WARNING, "Can't send %d type frames with Jingle write\n",
1526                         frame->frametype);
1527                 return 0;
1528         }
1529
1530         return res;
1531 }
1532
1533 /*! \brief Function called by core to change the underlying owner channel */
1534 static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1535 {
1536         struct jingle_session *session = ast_channel_tech_pvt(newchan);
1537
1538         ao2_lock(session);
1539
1540         session->owner = newchan;
1541
1542         ao2_unlock(session);
1543
1544         return 0;
1545 }
1546
1547 /*! \brief Function called by core to ask the channel to indicate some sort of condition */
1548 static int jingle_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
1549 {
1550         struct jingle_session *session = ast_channel_tech_pvt(ast);
1551         int res = 0;
1552
1553         switch (condition) {
1554         case AST_CONTROL_RINGING:
1555                 if (ast_channel_state(ast) == AST_STATE_RING) {
1556                         jingle_send_session_info(session, "ringing xmlns='urn:xmpp:jingle:apps:rtp:info:1'");
1557                 } else {
1558                         res = -1;
1559                 }
1560                 break;
1561         case AST_CONTROL_BUSY:
1562                 if (ast_channel_state(ast) != AST_STATE_UP) {
1563                         ast_channel_hangupcause_set(ast, AST_CAUSE_BUSY);
1564                         ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
1565                 } else {
1566                         res = -1;
1567                 }
1568                 break;
1569         case AST_CONTROL_CONGESTION:
1570                 if (ast_channel_state(ast) != AST_STATE_UP) {
1571                         ast_channel_hangupcause_set(ast, AST_CAUSE_CONGESTION);
1572                         ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
1573                 } else {
1574                         res = -1;
1575                 }
1576                 break;
1577         case AST_CONTROL_INCOMPLETE:
1578                 if (ast_channel_state(ast) != AST_STATE_UP) {
1579                         ast_channel_hangupcause_set(ast, AST_CAUSE_CONGESTION);
1580                         ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
1581                 }
1582                 break;
1583         case AST_CONTROL_HOLD:
1584                 ast_moh_start(ast, data, NULL);
1585                 break;
1586         case AST_CONTROL_UNHOLD:
1587                 ast_moh_stop(ast);
1588                 break;
1589         case AST_CONTROL_SRCUPDATE:
1590                 if (session->rtp) {
1591                         ast_rtp_instance_update_source(session->rtp);
1592                 }
1593                 break;
1594         case AST_CONTROL_SRCCHANGE:
1595                 if (session->rtp) {
1596                         ast_rtp_instance_change_source(session->rtp);
1597                 }
1598                 break;
1599         case AST_CONTROL_VIDUPDATE:
1600         case AST_CONTROL_UPDATE_RTP_PEER:
1601         case AST_CONTROL_CONNECTED_LINE:
1602                 break;
1603         case AST_CONTROL_PVT_CAUSE_CODE:
1604         case -1:
1605                 res = -1;
1606                 break;
1607         default:
1608                 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
1609                 res = -1;
1610         }
1611
1612         return res;
1613 }
1614
1615 /*! \brief Function called by core to send text to the remote party of the Jingle session */
1616 static int jingle_sendtext(struct ast_channel *chan, const char *text)
1617 {
1618         struct jingle_session *session = ast_channel_tech_pvt(chan);
1619
1620         return ast_xmpp_client_send_message(session->connection, session->remote, text);
1621 }
1622
1623 /*! \brief Function called by core to start a DTMF digit */
1624 static int jingle_digit_begin(struct ast_channel *chan, char digit)
1625 {
1626         struct jingle_session *session = ast_channel_tech_pvt(chan);
1627
1628         if (session->rtp) {
1629                 ast_rtp_instance_dtmf_begin(session->rtp, digit);
1630         }
1631
1632         return 0;
1633 }
1634
1635 /*! \brief Function called by core to stop a DTMF digit */
1636 static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
1637 {
1638         struct jingle_session *session = ast_channel_tech_pvt(ast);
1639
1640         if (session->rtp) {
1641                 ast_rtp_instance_dtmf_end_with_duration(session->rtp, digit, duration);
1642         }
1643
1644         return 0;
1645 }
1646
1647 /*! \brief Function called by core to actually start calling a remote party */
1648 static int jingle_call(struct ast_channel *ast, const char *dest, int timeout)
1649 {
1650         struct jingle_session *session = ast_channel_tech_pvt(ast);
1651
1652         ast_setstate(ast, AST_STATE_RING);
1653
1654         /* Since we have no idea of the remote capabilities use ours for now */
1655         ast_format_cap_copy(session->jointcap, session->cap);
1656
1657         /* We set up a hook so we can know when our session-initiate message was accepted or rejected */
1658         session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1659                                             IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1660
1661         jingle_send_session_initiate(session);
1662
1663         return 0;
1664 }
1665
1666 /*! \brief Function called by core to hang up a Jingle session */
1667 static int jingle_hangup(struct ast_channel *ast)
1668 {
1669         struct jingle_session *session = ast_channel_tech_pvt(ast);
1670
1671         ao2_lock(session);
1672
1673         if ((ast_channel_state(ast) != AST_STATE_DOWN) && !session->gone) {
1674                 int cause = (session->owner ? ast_channel_hangupcause(session->owner) : AST_CAUSE_CONGESTION);
1675                 const char *reason = "success";
1676                 int i;
1677
1678                 /* Get the appropriate reason and send a session-terminate */
1679                 for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
1680                         if (jingle_reason_mappings[i].cause == cause) {
1681                                 reason = jingle_reason_mappings[i].reason;
1682                                 break;
1683                         }
1684                 }
1685
1686                 jingle_send_session_terminate(session, reason);
1687         }
1688
1689         ast_channel_tech_pvt_set(ast, NULL);
1690         session->owner = NULL;
1691
1692         ao2_unlink(session->state->sessions, session);
1693         ao2_ref(session->state, -1);
1694
1695         ao2_unlock(session);
1696         ao2_ref(session, -1);
1697
1698         return 0;
1699 }
1700
1701 /*! \brief Function called by core to create a new outgoing Jingle session */
1702 static struct ast_channel *jingle_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
1703 {
1704         RAII_VAR(struct jingle_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
1705         RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
1706         char *dialed, target[200] = "";
1707         struct ast_xmpp_buddy *buddy;
1708         struct jingle_session *session;
1709         struct ast_channel *chan;
1710         enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
1711         AST_DECLARE_APP_ARGS(args,
1712                              AST_APP_ARG(name);
1713                              AST_APP_ARG(target);
1714                 );
1715
1716         /* We require at a minimum one audio format to be requested */
1717         if (!ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO)) {
1718                 ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n");
1719                 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
1720                 return NULL;
1721         }
1722
1723         if (ast_strlen_zero(data) || !(dialed = ast_strdupa(data))) {
1724                 ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
1725                 *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
1726                 return NULL;
1727         }
1728
1729         /* Parse the given dial string and validate the results */
1730         AST_NONSTANDARD_APP_ARGS(args, dialed, '/');
1731
1732         if (ast_strlen_zero(args.name) || ast_strlen_zero(args.target)) {
1733                 ast_log(LOG_ERROR, "Unable to determine endpoint name and target.\n");
1734                 *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
1735                 return NULL;
1736         }
1737
1738         if (!(endpoint = jingle_endpoint_find(cfg->endpoints, args.name))) {
1739                 ast_log(LOG_ERROR, "Endpoint '%s' does not exist.\n", args.name);
1740                 *cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
1741                 return NULL;
1742         }
1743
1744         ao2_lock(endpoint->state);
1745
1746         /* If we don't have a connection for the endpoint we can't exactly start a session on it */
1747         if (!endpoint->connection) {
1748                 ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no valid connection exists\n", args.name);
1749                 *cause = AST_CAUSE_SWITCH_CONGESTION;
1750                 ao2_unlock(endpoint->state);
1751                 return NULL;
1752         }
1753
1754         /* Find the target in the roster so we can choose a resource */
1755         if ((buddy = ao2_find(endpoint->connection->buddies, args.target, OBJ_KEY))) {
1756                 struct ao2_iterator res;
1757                 struct ast_xmpp_resource *resource;
1758
1759                 /* Iterate through finding the first viable Jingle capable resource */
1760                 res = ao2_iterator_init(buddy->resources, 0);
1761                 while ((resource = ao2_iterator_next(&res))) {
1762                         if (resource->caps.jingle) {
1763                                 snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
1764                                 transport = JINGLE_TRANSPORT_ICE_UDP;
1765                                 break;
1766                         } else if (resource->caps.google) {
1767                                 snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
1768                                 transport = JINGLE_TRANSPORT_GOOGLE_V2;
1769                                 break;
1770                         }
1771                         ao2_ref(resource, -1);
1772                 }
1773                 ao2_iterator_destroy(&res);
1774
1775                 ao2_ref(buddy, -1);
1776         } else {
1777                 /* If the target is NOT in the roster use the provided target as-is */
1778                 ast_copy_string(target, args.target, sizeof(target));
1779         }
1780
1781         ao2_unlock(endpoint->state);
1782
1783         /* If no target was found we can't set up a session */
1784         if (ast_strlen_zero(target)) {
1785                 ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no capable resource for target '%s' was found\n", args.name, args.target);
1786                 *cause = AST_CAUSE_SWITCH_CONGESTION;
1787                 return NULL;
1788         }
1789
1790         if (!(session = jingle_alloc(endpoint, target, NULL))) {
1791                 ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s'\n", args.name);
1792                 *cause = AST_CAUSE_SWITCH_CONGESTION;
1793                 return NULL;
1794         }
1795
1796         /* Update the transport if we learned what we should actually use */
1797         if (transport != JINGLE_TRANSPORT_NONE) {
1798                 session->transport = transport;
1799                 /* Note that for Google-V1 and Google-V2 we don't stop built-in ICE support, this will happen in jingle_new */
1800         }
1801
1802         if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, target, requestor ? ast_channel_linkedid(requestor) : NULL, NULL))) {
1803                 ast_log(LOG_ERROR, "Unable to create Jingle channel on endpoint '%s'\n", args.name);
1804                 *cause = AST_CAUSE_SWITCH_CONGESTION;
1805                 ao2_ref(session, -1);
1806                 return NULL;
1807         }
1808
1809         /* If video was requested try to enable it on the session */
1810         if (ast_format_cap_has_type(cap, AST_FORMAT_TYPE_VIDEO)) {
1811                 jingle_enable_video(session);
1812         }
1813
1814         /* We purposely don't decrement the session here as there is a reference on the channel */
1815         ao2_link(endpoint->state->sessions, session);
1816
1817         return chan;
1818 }
1819
1820 /*! \brief Helper function which handles content descriptions */
1821 static int jingle_interpret_description(struct jingle_session *session, iks *description, const char *name, struct ast_rtp_instance **rtp)
1822 {
1823         char *media = iks_find_attrib(description, "media");
1824         struct ast_rtp_codecs codecs;
1825         iks *codec;
1826         int othercapability = 0;
1827
1828         /* Google-V1 is always carrying audio, but just doesn't tell us so */
1829         if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1830                 media = "audio";
1831         } else if (ast_strlen_zero(media)) {
1832                 jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
1833                 ast_log(LOG_ERROR, "Received a content description on session '%s' without a name\n", session->sid);
1834                 return -1;
1835         }
1836
1837         /* Determine the type of media that is being carried and update the RTP instance, as well as the name */
1838         if (!strcasecmp(media, "audio")) {
1839                 if (!ast_strlen_zero(name)) {
1840                         ast_string_field_set(session, audio_name, name);
1841                 }
1842                 *rtp = session->rtp;
1843                 ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_AUDIO);
1844                 ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_AUDIO);
1845         } else if (!strcasecmp(media, "video")) {
1846                 if (!ast_strlen_zero(name)) {
1847                         ast_string_field_set(session, video_name, name);
1848                 }
1849
1850                 jingle_enable_video(session);
1851                 *rtp = session->vrtp;
1852
1853                 /* If video is not present cancel this session */
1854                 if (!session->vrtp) {
1855                         jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
1856                         ast_log(LOG_ERROR, "Received a video content description on session '%s' but could not enable video\n", session->sid);
1857                         return -1;
1858                 }
1859
1860                 ast_format_cap_remove_bytype(session->peercap, AST_FORMAT_TYPE_VIDEO);
1861                 ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_VIDEO);
1862         } else {
1863                 /* Unknown media type */
1864                 jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
1865                 ast_log(LOG_ERROR, "Unsupported media type '%s' received in content description on session '%s'\n", media, session->sid);
1866                 return -1;
1867         }
1868
1869         ast_rtp_codecs_payloads_clear(&codecs, NULL);
1870
1871         /* Iterate the codecs updating the relevant RTP instance as we go */
1872         for (codec = iks_child(description); codec; codec = iks_next(codec)) {
1873                 char *id = iks_find_attrib(codec, "id"), *name = iks_find_attrib(codec, "name");
1874                 char *clockrate = iks_find_attrib(codec, "clockrate");
1875                 int rtp_id, rtp_clockrate;
1876
1877                 if (!ast_strlen_zero(id) && !ast_strlen_zero(name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
1878                         ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, rtp_id);
1879
1880                         if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
1881                                 ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, name, 0, rtp_clockrate);
1882                         } else {
1883                                 ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, rtp_id, media, name, 0);
1884                         }
1885                 }
1886         }
1887
1888         ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability);
1889         ast_format_cap_joint_append(session->cap, session->peercap, session->jointcap);
1890
1891         if (ast_format_cap_is_empty(session->jointcap)) {
1892                 /* We have no compatible codecs, so terminate the session appropriately */
1893                 jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
1894                 return -1;
1895         }
1896
1897         ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(*rtp), *rtp);
1898
1899         return 0;
1900 }
1901
1902 /*! \brief Helper function which handles ICE-UDP transport information */
1903 static int jingle_interpret_ice_udp_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
1904 {
1905         struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(rtp);
1906         char *ufrag = iks_find_attrib(transport, "ufrag"), *pwd = iks_find_attrib(transport, "pwd");
1907         iks *candidate;
1908
1909         if (!ice) {
1910                 jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
1911                 ast_log(LOG_ERROR, "Received ICE-UDP transport information on session '%s' but ICE support not available\n", session->sid);
1912                 return -1;
1913         }
1914
1915         if (ast_strlen_zero(ufrag) || ast_strlen_zero(pwd)) {
1916                 jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
1917                 ast_log(LOG_ERROR, "Invalid ICE-UDP transport information received on session '%s', ufrag or pwd not present\n", session->sid);
1918                 return -1;
1919         }
1920
1921         ice->set_authentication(rtp, ufrag, pwd);
1922
1923         for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
1924                 char *component = iks_find_attrib(candidate, "component"), *foundation = iks_find_attrib(candidate, "foundation");
1925                 char *generation = iks_find_attrib(candidate, "generation"), *id = iks_find_attrib(candidate, "id");
1926                 char *ip = iks_find_attrib(candidate, "ip"), *network = iks_find_attrib(candidate, "network");
1927                 char *port = iks_find_attrib(candidate, "port"), *priority = iks_find_attrib(candidate, "priority");
1928                 char *protocol = iks_find_attrib(candidate, "protocol"), *type = iks_find_attrib(candidate, "type");
1929                 struct ast_rtp_engine_ice_candidate local_candidate = { 0, };
1930                 int real_port;
1931                 struct ast_sockaddr remote_address = { { 0, } };
1932
1933                 /* If this candidate is incomplete skip it */
1934                 if (ast_strlen_zero(component) || ast_strlen_zero(foundation) || ast_strlen_zero(generation) || ast_strlen_zero(id) ||
1935                     ast_strlen_zero(ip) || ast_strlen_zero(network) || ast_strlen_zero(port) || ast_strlen_zero(priority) ||
1936                     ast_strlen_zero(protocol) || ast_strlen_zero(type)) {
1937                         jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
1938                         ast_log(LOG_ERROR, "Incomplete ICE-UDP candidate received on session '%s'\n", session->sid);
1939                         return -1;
1940                 }
1941
1942                 if ((sscanf(component, "%30u", &local_candidate.id) != 1) ||
1943                     (sscanf(priority, "%30u", &local_candidate.priority) != 1) ||
1944                     (sscanf(port, "%30d", &real_port) != 1)) {
1945                         jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
1946                         ast_log(LOG_ERROR, "Invalid ICE-UDP candidate information received on session '%s'\n", session->sid);
1947                         return -1;
1948                 }
1949
1950                 local_candidate.foundation = foundation;
1951                 local_candidate.transport = protocol;
1952
1953                 ast_sockaddr_parse(&local_candidate.address, ip, PARSE_PORT_FORBID);
1954
1955                 /* We only support IPv4 right now */
1956                 if (!ast_sockaddr_is_ipv4(&local_candidate.address)) {
1957                         continue;
1958                 }
1959
1960                 ast_sockaddr_set_port(&local_candidate.address, real_port);
1961
1962                 if (!strcasecmp(type, "host")) {
1963                         local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_HOST;
1964                 } else if (!strcasecmp(type, "srflx")) {
1965                         local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_SRFLX;
1966                 } else if (!strcasecmp(type, "relay")) {
1967                         local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED;
1968                 } else {
1969                         continue;
1970                 }
1971
1972                 /* Worst case use the first viable address */
1973                 ast_rtp_instance_get_remote_address(rtp, &remote_address);
1974
1975                 if (ast_sockaddr_is_ipv4(&local_candidate.address) && ast_sockaddr_isnull(&remote_address)) {
1976                         ast_rtp_instance_set_remote_address(rtp, &local_candidate.address);
1977                 }
1978
1979                 ice->add_remote_candidate(rtp, &local_candidate);
1980         }
1981
1982         ice->start(rtp);
1983
1984         return 0;
1985 }
1986
1987 /*! \brief Helper function which handles Google transport information */
1988 static int jingle_interpret_google_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
1989 {
1990         struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(rtp);
1991         iks *candidate;
1992
1993         if (!ice) {
1994                 jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
1995                 ast_log(LOG_ERROR, "Received Google transport information on session '%s' but ICE support not available\n", session->sid);
1996                 return -1;
1997         }
1998
1999         /* If this session has not transitioned to the Google transport do so now */
2000         if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V2) &&
2001             (session->transport != JINGLE_TRANSPORT_GOOGLE_V1)) {
2002                 /* Stop built-in ICE support... we need to fall back to the old old old STUN */
2003                 ice->stop(rtp);
2004
2005                 session->transport = JINGLE_TRANSPORT_GOOGLE_V2;
2006         }
2007
2008         for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
2009                 char *address = iks_find_attrib(candidate, "address"), *port = iks_find_attrib(candidate, "port");
2010                 char *username = iks_find_attrib(candidate, "username"), *name = iks_find_attrib(candidate, "name");
2011                 char *protocol = iks_find_attrib(candidate, "protocol");
2012                 int real_port;
2013                 struct ast_sockaddr target = { { 0, } };
2014                 /* In Google land the combined value is 32 bytes */
2015                 char combined[33] = "";
2016
2017                 /* If this is NOT actually a candidate just skip it */
2018                 if (strcasecmp(iks_name(candidate), "candidate") &&
2019                     strcasecmp(iks_name(candidate), "p:candidate") &&
2020                     strcasecmp(iks_name(candidate), "ses:candidate")) {
2021                         continue;
2022                 }
2023
2024                 /* If this candidate is incomplete skip it */
2025                 if (ast_strlen_zero(address) || ast_strlen_zero(port) || ast_strlen_zero(username) ||
2026                     ast_strlen_zero(name)) {
2027                         jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
2028                         ast_log(LOG_ERROR, "Incomplete Google candidate received on session '%s'\n", session->sid);
2029                         return -1;
2030                 }
2031
2032                 /* We only support UDP so skip any other protocols */
2033                 if (!ast_strlen_zero(protocol) && strcasecmp(protocol, "udp")) {
2034                         continue;
2035                 }
2036
2037                 /* We only permit audio and video, not RTCP */
2038                 if (strcasecmp(name, "rtp") && strcasecmp(name, "video_rtp")) {
2039                         continue;
2040                 }
2041
2042                 /* Parse the target information so we can send a STUN request to the candidate */
2043                 if (sscanf(port, "%30d", &real_port) != 1) {
2044                         jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
2045                         ast_log(LOG_ERROR, "Invalid Google candidate port '%s' received on session '%s'\n", port, session->sid);
2046                         return -1;
2047                 }
2048                 ast_sockaddr_parse(&target, address, PARSE_PORT_FORBID);
2049                 ast_sockaddr_set_port(&target, real_port);
2050
2051                 /* Per the STUN support Google talk uses combine the two usernames */
2052                 snprintf(combined, sizeof(combined), "%s%s", username, ice->get_ufrag(rtp));
2053
2054                 /* This should appease the masses... we will actually change the remote address when we get their STUN packet */
2055                 ast_rtp_instance_stun_request(rtp, &target, combined);
2056         }
2057
2058         return 0;
2059 }
2060
2061 /*!
2062  * \brief Helper function which locates content stanzas and interprets them
2063  *
2064  * \note The session *must not* be locked before calling this
2065  */
2066 static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
2067 {
2068         iks *content;
2069         unsigned int changed = 0;
2070         struct ast_channel *chan;
2071
2072         /* Look at the content in the session initiation */
2073         for (content = iks_child(iks_child(pak->x)); content; content = iks_next(content)) {
2074                 char *name = iks_find_attrib(content, "name");
2075                 struct ast_rtp_instance *rtp = NULL;
2076                 iks *description, *transport;
2077
2078                 if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
2079                         /* If this content stanza has no name consider it invalid and move on */
2080                         if (ast_strlen_zero(name) && !(name = iks_find_attrib(content, "jin:name"))) {
2081                                 jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
2082                                 ast_log(LOG_ERROR, "Received content without a name on session '%s'\n", session->sid);
2083                                 return -1;
2084                         }
2085
2086                         /* Try to pre-populate which RTP instance this content is relevant to */
2087                         if (!strcmp(session->audio_name, name)) {
2088                                 rtp = session->rtp;
2089                         } else if (!strcmp(session->video_name, name)) {
2090                                 rtp = session->vrtp;
2091                         }
2092                 } else {
2093                         /* Google-V1 has no concept of assocating things like the above does, so since we only support audio over it assume they want audio */
2094                         rtp = session->rtp;
2095                 }
2096
2097                 /* If description information is available use it */
2098                 if ((description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_RTP_NS)) ||
2099                     (description = iks_find_with_attrib(content, "rtp:description", "xmlns:rtp", JINGLE_RTP_NS)) ||
2100                     (description = iks_find_with_attrib(pak->query, "description", "xmlns", GOOGLE_PHONE_NS)) ||
2101                     (description = iks_find_with_attrib(pak->query, "vid:description", "xmlns", GOOGLE_VIDEO_NS))) {
2102                         /* If we failed to do something with the content description abort immediately */
2103                         if (jingle_interpret_description(session, description, name, &rtp)) {
2104                                 return -1;
2105                         }
2106
2107                         /* If we successfully interpret the description then the codecs need updating */
2108                         changed = 1;
2109                 }
2110
2111                 /* If we get past the description handling and we still don't know what RTP instance this is for... it is unknown content */
2112                 if (!rtp) {
2113                         ast_log(LOG_ERROR, "Received a content stanza but have no RTP instance for it on session '%s'\n", session->sid);
2114                         jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
2115                         return -1;
2116                 }
2117
2118                 /* If ICE UDP transport information is available use it */
2119                 if ((transport = iks_find_with_attrib(content, "transport", "xmlns", JINGLE_ICE_UDP_NS))) {
2120                         if (jingle_interpret_ice_udp_transport(session, transport, rtp)) {
2121                                 return -1;
2122                         }
2123                 } else if ((transport = iks_find_with_attrib(content, "transport", "xmlns", GOOGLE_TRANSPORT_NS)) ||
2124                            (transport = iks_find_with_attrib(content, "p:transport", "xmlns:p", GOOGLE_TRANSPORT_NS)) ||
2125                            (transport = iks_find_with_attrib(pak->x, "session", "xmlns", GOOGLE_SESSION_NS)) ||
2126                            (transport = iks_find_with_attrib(pak->x, "ses:session", "xmlns:ses", GOOGLE_SESSION_NS))) {
2127                         /* If Google transport support is available use it */
2128                         if (jingle_interpret_google_transport(session, transport, rtp)) {
2129                                 return -1;
2130                         }
2131                 } else if (iks_find(content, "transport")) {
2132                         /* If this is a transport we do not support terminate the session as it probably won't work out in the end */
2133                         jingle_queue_hangup_with_cause(session, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
2134                         ast_log(LOG_ERROR, "Unsupported transport type received on session '%s'\n", session->sid);
2135                         return -1;
2136                 }
2137         }
2138
2139         if (!changed) {
2140                 return 0;
2141         }
2142
2143         if ((chan = jingle_session_lock_full(session))) {
2144                 struct ast_format fmt;
2145
2146                 ast_format_cap_copy(ast_channel_nativeformats(chan), session->jointcap);
2147                 ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt);
2148                 ast_set_read_format(chan, &fmt);
2149                 ast_set_write_format(chan, &fmt);
2150
2151                 ast_channel_unlock(chan);
2152                 ast_channel_unref(chan);
2153         }
2154         ao2_unlock(session);
2155
2156         return 0;
2157 }
2158
2159 /*! \brief Handler function for the 'session-initiate' action */
2160 static void jingle_action_session_initiate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
2161 {
2162         char *sid;
2163         enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
2164         struct ast_channel *chan;
2165         int res;
2166
2167         if (session) {
2168                 /* This is a duplicate session setup, so respond accordingly */
2169                 jingle_send_error_response(endpoint->connection, pak, "result", "out-of-order", NULL);
2170                 return;
2171         }
2172
2173         /* Retrieve the session identifier from the message, note that this may alter the transport */
2174         if ((sid = iks_find_attrib(pak->query, "id"))) {
2175                 /* The presence of the session identifier in the 'id' attribute tells us that this is Google-V1 as everything else uses 'sid' */
2176                 transport = JINGLE_TRANSPORT_GOOGLE_V1;
2177         } else if (!(sid = iks_find_attrib(pak->query, "sid"))) {
2178                 jingle_send_error_response(endpoint->connection, pak, "bad-request", NULL, NULL);
2179                 return;
2180         }
2181
2182         /* Create a new local session */
2183         if (!(session = jingle_alloc(endpoint, pak->from->full, sid))) {
2184                 jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2185                 return;
2186         }
2187
2188         /* If we determined that the transport should change as a result of how we got the SID change it */
2189         if (transport != JINGLE_TRANSPORT_NONE) {
2190                 session->transport = transport;
2191         }
2192
2193         /* Create a new Asterisk channel using the above local session */
2194         if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, pak->from->user, NULL, pak->from->full))) {
2195                 ao2_ref(session, -1);
2196                 jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2197                 return;
2198         }
2199
2200         ao2_link(endpoint->state->sessions, session);
2201
2202         ast_setstate(chan, AST_STATE_RING);
2203         res = ast_pbx_start(chan);
2204
2205         switch (res) {
2206         case AST_PBX_FAILED:
2207                 ast_log(LOG_WARNING, "Failed to start PBX :(\n");
2208                 jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2209                 session->gone = 1;
2210                 ast_hangup(chan);
2211                 break;
2212         case AST_PBX_CALL_LIMIT:
2213                 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
2214                 jingle_send_error_response(endpoint->connection, pak, "wait", "resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2215                 ast_hangup(chan);
2216                 break;
2217         case AST_PBX_SUCCESS:
2218                 jingle_send_response(endpoint->connection, pak);
2219
2220                 /* Only send a transport-info message if we successfully interpreted the available content */
2221                 if (!jingle_interpret_content(session, pak)) {
2222                         jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
2223                 }
2224                 break;
2225         }
2226 }
2227
2228 /*! \brief Handler function for the 'transport-info' action */
2229 static void jingle_action_transport_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
2230 {
2231         if (!session) {
2232                 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2233                                            "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2234                 return;
2235         }
2236
2237         jingle_interpret_content(session, pak);
2238         jingle_send_response(endpoint->connection, pak);
2239 }
2240
2241 /*! \brief Handler function for the 'session-accept' action */
2242 static void jingle_action_session_accept(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
2243 {
2244         struct ast_channel *chan;
2245
2246         if (!session) {
2247                 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2248                                            "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2249                 return;
2250         }
2251
2252
2253         jingle_interpret_content(session, pak);
2254
2255         if ((chan = jingle_session_lock_full(session))) {
2256                 ast_queue_control(chan, AST_CONTROL_ANSWER);
2257                 ast_channel_unlock(chan);
2258                 ast_channel_unref(chan);
2259         }
2260         ao2_unlock(session);
2261
2262         jingle_send_response(endpoint->connection, pak);
2263 }
2264
2265 /*! \brief Handler function for the 'session-info' action */
2266 static void jingle_action_session_info(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
2267 {
2268         struct ast_channel *chan;
2269
2270         if (!session) {
2271                 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2272                                            "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2273                 return;
2274         }
2275
2276         if (!(chan = jingle_session_lock_full(session))) {
2277                 ao2_unlock(session);
2278                 jingle_send_response(endpoint->connection, pak);
2279                 return;
2280         }
2281
2282         if (iks_find_with_attrib(pak->query, "ringing", "xmlns", JINGLE_RTP_INFO_NS)) {
2283                 ast_queue_control(chan, AST_CONTROL_RINGING);
2284                 if (ast_channel_state(chan) != AST_STATE_UP) {
2285                         ast_setstate(chan, AST_STATE_RINGING);
2286                 }
2287         } else if (iks_find_with_attrib(pak->query, "hold", "xmlns", JINGLE_RTP_INFO_NS)) {
2288                 ast_queue_control(chan, AST_CONTROL_HOLD);
2289         } else if (iks_find_with_attrib(pak->query, "unhold", "xmlns", JINGLE_RTP_INFO_NS)) {
2290                 ast_queue_control(chan, AST_CONTROL_UNHOLD);
2291         }
2292
2293         ast_channel_unlock(chan);
2294         ast_channel_unref(chan);
2295         ao2_unlock(session);
2296
2297         jingle_send_response(endpoint->connection, pak);
2298 }
2299
2300 /*! \brief Handler function for the 'session-terminate' action */
2301 static void jingle_action_session_terminate(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
2302 {
2303         struct ast_channel *chan;
2304         iks *reason, *text;
2305         int cause = AST_CAUSE_NORMAL;
2306
2307         if (!session) {
2308                 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2309                                            "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2310                 return;
2311         }
2312
2313         if (!(chan = jingle_session_lock_full(session))) {
2314                 ao2_unlock(session);
2315                 jingle_send_response(endpoint->connection, pak);
2316                 return;
2317         }
2318
2319         /* Pull the reason text from the session-terminate message and translate it into a cause code */
2320         if ((reason = iks_find(pak->query, "reason")) && (text = iks_child(reason))) {
2321                 int i;
2322
2323                 /* Get the appropriate cause code mapping for this reason */
2324                 for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
2325                         if (!strcasecmp(jingle_reason_mappings[i].reason, iks_name(text))) {
2326                                 cause = jingle_reason_mappings[i].cause;
2327                                 break;
2328                         }
2329                 }
2330         }
2331
2332         ast_debug(3, "Hanging up channel '%s' due to session terminate message with cause '%d'\n", ast_channel_name(chan), cause);
2333         ast_queue_hangup_with_cause(chan, cause);
2334         session->gone = 1;
2335
2336         ast_channel_unlock(chan);
2337         ast_channel_unref(chan);
2338         ao2_unlock(session);
2339
2340         jingle_send_response(endpoint->connection, pak);
2341 }
2342
2343 /*! \brief Callback for when a Jingle action is received from an endpoint */
2344 static int jingle_action_hook(void *data, ikspak *pak)
2345 {
2346         char *action;
2347         const char *sid = NULL;
2348         struct jingle_session *session = NULL;
2349         struct jingle_endpoint *endpoint = data;
2350         int i, handled = 0;
2351
2352         /* We accept both Jingle and Google-V1 */
2353         if (!(action = iks_find_attrib(pak->query, "action")) &&
2354             !(action = iks_find_attrib(pak->query, "type"))) {
2355                 /* This occurs if either receive a packet masquerading as Jingle or Google-V1 that is actually not OR we receive a response
2356                  * to a message that has no response hook. */
2357                 return IKS_FILTER_EAT;
2358         }
2359
2360         /* Bump the endpoint reference count up in case a reload occurs. Unfortunately the available synchronization between iksemel and us
2361          * does not permit us to make this completely safe. */
2362         ao2_ref(endpoint, +1);
2363
2364         /* If a Jingle session identifier is present use it */
2365         if (!(sid = iks_find_attrib(pak->query, "sid"))) {
2366                 /* If a Google-V1 session identifier is present use it */
2367                 sid = iks_find_attrib(pak->query, "id");
2368         }
2369
2370         /* If a session identifier was present in the message attempt to find the session, it is up to the action handler whether
2371          * this is required or not */
2372         if (!ast_strlen_zero(sid)) {
2373                 session = ao2_find(endpoint->state->sessions, sid, OBJ_KEY);
2374         }
2375
2376         /* Iterate through supported action handlers looking for one that is able to handle this */
2377         for (i = 0; i < ARRAY_LEN(jingle_action_handlers); i++) {
2378                 if (!strcasecmp(jingle_action_handlers[i].action, action)) {
2379                         jingle_action_handlers[i].handler(endpoint, session, pak);
2380                         handled = 1;
2381                         break;
2382                 }
2383         }
2384
2385         /* If no action handler is present for the action they sent us make it evident */
2386         if (!handled) {
2387                 ast_log(LOG_NOTICE, "Received action '%s' for session '%s' that has no handler\n", action, sid);
2388         }
2389
2390         /* If a session was successfully found for this message deref it now since the handler is done */
2391         if (session) {
2392                 ao2_ref(session, -1);
2393         }
2394
2395         ao2_ref(endpoint, -1);
2396
2397         return IKS_FILTER_EAT;
2398 }
2399
2400 /*! \brief Custom handler for groups */
2401 static int custom_group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
2402 {
2403         struct jingle_endpoint *endpoint = obj;
2404
2405         if (!strcasecmp(var->name, "callgroup")) {
2406                 endpoint->callgroup = ast_get_group(var->value);
2407         } else if (!strcasecmp(var->name, "pickupgroup")) {
2408                 endpoint->pickupgroup = ast_get_group(var->value);
2409         } else {
2410                 return -1;
2411         }
2412
2413         return 0;
2414 }
2415
2416 /*! \brief Custom handler for connection */
2417 static int custom_connection_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
2418 {
2419         struct jingle_endpoint *endpoint = obj;
2420
2421         /* You might think... but Josh, shouldn't you do this in a prelink callback? Well I *could* but until the original is destroyed
2422          * this will not actually get called, so even if the config turns out to be bogus this is harmless.
2423          */
2424         if (!(endpoint->connection = ast_xmpp_client_find(var->value))) {
2425                 ast_log(LOG_ERROR, "Connection '%s' configured on endpoint '%s' could not be found\n", var->value, endpoint->name);
2426                 return -1;
2427         }
2428
2429         if (!(endpoint->rule = iks_filter_add_rule(endpoint->connection->filter, jingle_action_hook, endpoint,
2430                                                    IKS_RULE_TYPE, IKS_PAK_IQ,
2431                                                    IKS_RULE_NS, JINGLE_NS,
2432                                                    IKS_RULE_NS, GOOGLE_SESSION_NS,
2433                                                    IKS_RULE_DONE))) {
2434                 ast_log(LOG_ERROR, "Action hook could not be added to connection '%s' on endpoint '%s'\n", var->value, endpoint->name);
2435                 return -1;
2436         }
2437
2438         return 0;
2439 }
2440
2441 /*! \brief Custom handler for transport */
2442 static int custom_transport_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
2443 {
2444         struct jingle_endpoint *endpoint = obj;
2445
2446         if (!strcasecmp(var->value, "ice-udp")) {
2447                 endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
2448         } else if (!strcasecmp(var->value, "google")) {
2449                 endpoint->transport = JINGLE_TRANSPORT_GOOGLE_V2;
2450         } else if (!strcasecmp(var->value, "google-v1")) {
2451                 endpoint->transport = JINGLE_TRANSPORT_GOOGLE_V1;
2452         } else {
2453                 ast_log(LOG_WARNING, "Unknown transport type '%s' on endpoint '%s', defaulting to 'ice-udp'\n", var->value, endpoint->name);
2454                 endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
2455         }
2456
2457         return 0;
2458 }
2459
2460 /*! \brief Load module into PBX, register channel */
2461 static int load_module(void)
2462 {
2463         if (!(jingle_tech.capabilities = ast_format_cap_alloc())) {
2464                 return AST_MODULE_LOAD_DECLINE;
2465         }
2466
2467         if (aco_info_init(&cfg_info)) {
2468                 ast_log(LOG_ERROR, "Unable to intialize configuration for chan_motif.\n");
2469                 goto end;
2470         }
2471
2472         aco_option_register(&cfg_info, "context", ACO_EXACT, endpoint_options, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, context));
2473         aco_option_register_custom(&cfg_info, "callgroup", ACO_EXACT, endpoint_options, NULL, custom_group_handler, 0);
2474         aco_option_register_custom(&cfg_info, "pickupgroup", ACO_EXACT, endpoint_options, NULL, custom_group_handler, 0);
2475         aco_option_register(&cfg_info, "language", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, language));
2476         aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
2477         aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
2478         aco_option_register(&cfg_info, "accountcode", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, accountcode));
2479         aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, prefs, cap));
2480         aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, prefs, cap));
2481         aco_option_register_custom(&cfg_info, "connection", ACO_EXACT, endpoint_options, NULL, custom_connection_handler, 0);
2482         aco_option_register_custom(&cfg_info, "transport", ACO_EXACT, endpoint_options, NULL, custom_transport_handler, 0);
2483         aco_option_register(&cfg_info, "maxicecandidates", ACO_EXACT, endpoint_options, DEFAULT_MAX_ICE_CANDIDATES, OPT_UINT_T, PARSE_DEFAULT,
2484                             FLDSET(struct jingle_endpoint, maxicecandidates));
2485         aco_option_register(&cfg_info, "maxpayloads", ACO_EXACT, endpoint_options, DEFAULT_MAX_PAYLOADS, OPT_UINT_T, PARSE_DEFAULT,
2486                             FLDSET(struct jingle_endpoint, maxpayloads));
2487
2488         ast_format_cap_add_all_by_type(jingle_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
2489
2490         if (aco_process_config(&cfg_info, 0)) {
2491                 ast_log(LOG_ERROR, "Unable to read config file motif.conf. Not loading module.\n");
2492                 goto end;
2493         }
2494
2495         if (!(sched = ast_sched_context_create())) {
2496                 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2497                 goto end;
2498         }
2499
2500         if (ast_sched_start_thread(sched)) {
2501                 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2502                 goto end;
2503         }
2504
2505         ast_rtp_glue_register(&jingle_rtp_glue);
2506
2507         if (ast_channel_register(&jingle_tech)) {
2508                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
2509                 goto end;
2510         }
2511
2512         return 0;
2513
2514 end:
2515         ast_rtp_glue_unregister(&jingle_rtp_glue);
2516
2517         if (sched) {
2518                 ast_sched_context_destroy(sched);
2519         }
2520
2521         aco_info_destroy(&cfg_info);
2522
2523         return AST_MODULE_LOAD_FAILURE;
2524 }
2525
2526 /*! \brief Reload module */
2527 static int reload(void)
2528 {
2529         return aco_process_config(&cfg_info, 1);
2530 }
2531
2532 /*! \brief Unload the jingle channel from Asterisk */
2533 static int unload_module(void)
2534 {
2535         ast_channel_unregister(&jingle_tech);
2536         ast_rtp_glue_unregister(&jingle_rtp_glue);
2537         ast_sched_context_destroy(sched);
2538         aco_info_destroy(&cfg_info);
2539         ao2_global_obj_release(globals);
2540
2541         return 0;
2542 }
2543
2544 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Motif Jingle Channel Driver",
2545                 .load = load_module,
2546                 .unload = unload_module,
2547                 .reload = reload,
2548                 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
2549                );