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