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