adds support for slin16 in sip
[asterisk/asterisk.git] / main / rtp_engine.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, 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  * \brief Pluggable RTP Architecture
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include <math.h>
31
32 #include "asterisk/channel.h"
33 #include "asterisk/frame.h"
34 #include "asterisk/module.h"
35 #include "asterisk/rtp_engine.h"
36 #include "asterisk/manager.h"
37 #include "asterisk/options.h"
38 #include "asterisk/astobj2.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/translate.h"
41
42 struct ast_srtp_res *res_srtp = NULL;
43 struct ast_srtp_policy_res *res_srtp_policy = NULL;
44
45 /*! Structure that represents an RTP session (instance) */
46 struct ast_rtp_instance {
47         /*! Engine that is handling this RTP instance */
48         struct ast_rtp_engine *engine;
49         /*! Data unique to the RTP engine */
50         void *data;
51         /*! RTP properties that have been set and their value */
52         int properties[AST_RTP_PROPERTY_MAX];
53         /*! Address that we are expecting RTP to come in to */
54         struct sockaddr_in local_address;
55         /*! Address that we are sending RTP to */
56         struct sockaddr_in remote_address;
57         /*! Alternate address that we are receiving RTP from */
58         struct sockaddr_in alt_remote_address;
59         /*! Instance that we are bridged to if doing remote or local bridging */
60         struct ast_rtp_instance *bridged;
61         /*! Payload and packetization information */
62         struct ast_rtp_codecs codecs;
63         /*! RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
64         int timeout;
65         /*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
66         int holdtimeout;
67         /*! DTMF mode in use */
68         enum ast_rtp_dtmf_mode dtmf_mode;
69         /*! Glue currently in use */
70         struct ast_rtp_glue *glue;
71         /*! Channel associated with the instance */
72         struct ast_channel *chan;
73         /*! SRTP info associated with the instance */
74         struct ast_srtp *srtp;
75 };
76
77 /*! List of RTP engines that are currently registered */
78 static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
79
80 /*! List of RTP glues */
81 static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
82
83 /*! The following array defines the MIME Media type (and subtype) for each
84    of our codecs, or RTP-specific data type. */
85 static const struct ast_rtp_mime_type {
86         struct ast_rtp_payload_type payload_type;
87         char *type;
88         char *subtype;
89         unsigned int sample_rate;
90 } ast_rtp_mime_types[] = {
91         {{1, AST_FORMAT_G723_1}, "audio", "G723", 8000},
92         {{1, AST_FORMAT_GSM}, "audio", "GSM", 8000},
93         {{1, AST_FORMAT_ULAW}, "audio", "PCMU", 8000},
94         {{1, AST_FORMAT_ULAW}, "audio", "G711U", 8000},
95         {{1, AST_FORMAT_ALAW}, "audio", "PCMA", 8000},
96         {{1, AST_FORMAT_ALAW}, "audio", "G711A", 8000},
97         {{1, AST_FORMAT_G726}, "audio", "G726-32", 8000},
98         {{1, AST_FORMAT_ADPCM}, "audio", "DVI4", 8000},
99         {{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
100         {{1, AST_FORMAT_SLINEAR16}, "audio", "L16", 16000},
101         {{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
102         {{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
103         {{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
104         {{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
105         {{1, AST_FORMAT_SPEEX}, "audio", "speex", 8000},
106         {{1, AST_FORMAT_SPEEX16}, "audio", "speex", 16000},
107         {{1, AST_FORMAT_ILBC}, "audio", "iLBC", 8000},
108         /* this is the sample rate listed in the RTP profile for the G.722
109                       codec, *NOT* the actual sample rate of the media stream
110         */
111         {{1, AST_FORMAT_G722}, "audio", "G722", 8000},
112         {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32", 8000},
113         {{0, AST_RTP_DTMF}, "audio", "telephone-event", 8000},
114         {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000},
115         {{0, AST_RTP_CN}, "audio", "CN", 8000},
116         {{1, AST_FORMAT_JPEG}, "video", "JPEG", 90000},
117         {{1, AST_FORMAT_PNG}, "video", "PNG", 90000},
118         {{1, AST_FORMAT_H261}, "video", "H261", 90000},
119         {{1, AST_FORMAT_H263}, "video", "H263", 90000},
120         {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998", 90000},
121         {{1, AST_FORMAT_H264}, "video", "H264", 90000},
122         {{1, AST_FORMAT_MP4_VIDEO}, "video", "MP4V-ES", 90000},
123         {{1, AST_FORMAT_T140RED}, "text", "RED", 1000},
124         {{1, AST_FORMAT_T140}, "text", "T140", 1000},
125         {{1, AST_FORMAT_SIREN7}, "audio", "G7221", 16000},
126         {{1, AST_FORMAT_SIREN14}, "audio", "G7221", 32000},
127         {{1, AST_FORMAT_G719}, "audio", "G719", 48000},
128 };
129
130 /*!
131  * \brief Mapping between Asterisk codecs and rtp payload types
132  *
133  * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
134  * also, our own choices for dynamic payload types.  This is our master
135  * table for transmission
136  *
137  * See http://www.iana.org/assignments/rtp-parameters for a list of
138  * assigned values
139  */
140 static const struct ast_rtp_payload_type static_RTP_PT[AST_RTP_MAX_PT] = {
141         [0] = {1, AST_FORMAT_ULAW},
142         #ifdef USE_DEPRECATED_G726
143         [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
144         #endif
145         [3] = {1, AST_FORMAT_GSM},
146         [4] = {1, AST_FORMAT_G723_1},
147         [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
148         [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
149         [7] = {1, AST_FORMAT_LPC10},
150         [8] = {1, AST_FORMAT_ALAW},
151         [9] = {1, AST_FORMAT_G722},
152         [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
153         [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
154         [13] = {0, AST_RTP_CN},
155         [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
156         [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
157         [18] = {1, AST_FORMAT_G729A},
158         [19] = {0, AST_RTP_CN},         /* Also used for CN */
159         [26] = {1, AST_FORMAT_JPEG},
160         [31] = {1, AST_FORMAT_H261},
161         [34] = {1, AST_FORMAT_H263},
162         [97] = {1, AST_FORMAT_ILBC},
163         [98] = {1, AST_FORMAT_H263_PLUS},
164         [99] = {1, AST_FORMAT_H264},
165         [101] = {0, AST_RTP_DTMF},
166         [102] = {1, AST_FORMAT_SIREN7},
167         [103] = {1, AST_FORMAT_H263_PLUS},
168         [104] = {1, AST_FORMAT_MP4_VIDEO},
169         [105] = {1, AST_FORMAT_T140RED},   /* Real time text chat (with redundancy encoding) */
170         [106] = {1, AST_FORMAT_T140},      /* Real time text chat */
171         [110] = {1, AST_FORMAT_SPEEX},
172         [111] = {1, AST_FORMAT_G726},
173         [112] = {1, AST_FORMAT_G726_AAL2},
174         [115] = {1, AST_FORMAT_SIREN14},
175         [116] = {1, AST_FORMAT_G719},
176         [117] = {1, AST_FORMAT_SPEEX16},
177         [118] = {1, AST_FORMAT_SLINEAR16}, /* 16 Khz signed linear */
178         [121] = {0, AST_RTP_CISCO_DTMF},   /* Must be type 121 */
179 };
180
181 int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
182 {
183         struct ast_rtp_engine *current_engine;
184
185         /* Perform a sanity check on the engine structure to make sure it has the basics */
186         if (ast_strlen_zero(engine->name) || !engine->new || !engine->destroy || !engine->write || !engine->read) {
187                 ast_log(LOG_WARNING, "RTP Engine '%s' failed sanity check so it was not registered.\n", !ast_strlen_zero(engine->name) ? engine->name : "Unknown");
188                 return -1;
189         }
190
191         /* Link owner module to the RTP engine for reference counting purposes */
192         engine->mod = module;
193
194         AST_RWLIST_WRLOCK(&engines);
195
196         /* Ensure that no two modules with the same name are registered at the same time */
197         AST_RWLIST_TRAVERSE(&engines, current_engine, entry) {
198                 if (!strcmp(current_engine->name, engine->name)) {
199                         ast_log(LOG_WARNING, "An RTP engine with the name '%s' has already been registered.\n", engine->name);
200                         AST_RWLIST_UNLOCK(&engines);
201                         return -1;
202                 }
203         }
204
205         /* The engine survived our critique. Off to the list it goes to be used */
206         AST_RWLIST_INSERT_TAIL(&engines, engine, entry);
207
208         AST_RWLIST_UNLOCK(&engines);
209
210         ast_verb(2, "Registered RTP engine '%s'\n", engine->name);
211
212         return 0;
213 }
214
215 int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
216 {
217         struct ast_rtp_engine *current_engine = NULL;
218
219         AST_RWLIST_WRLOCK(&engines);
220
221         if ((current_engine = AST_RWLIST_REMOVE(&engines, engine, entry))) {
222                 ast_verb(2, "Unregistered RTP engine '%s'\n", engine->name);
223         }
224
225         AST_RWLIST_UNLOCK(&engines);
226
227         return current_engine ? 0 : -1;
228 }
229
230 int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module)
231 {
232         struct ast_rtp_glue *current_glue = NULL;
233
234         if (ast_strlen_zero(glue->type)) {
235                 return -1;
236         }
237
238         glue->mod = module;
239
240         AST_RWLIST_WRLOCK(&glues);
241
242         AST_RWLIST_TRAVERSE(&glues, current_glue, entry) {
243                 if (!strcasecmp(current_glue->type, glue->type)) {
244                         ast_log(LOG_WARNING, "RTP glue with the name '%s' has already been registered.\n", glue->type);
245                         AST_RWLIST_UNLOCK(&glues);
246                         return -1;
247                 }
248         }
249
250         AST_RWLIST_INSERT_TAIL(&glues, glue, entry);
251
252         AST_RWLIST_UNLOCK(&glues);
253
254         ast_verb(2, "Registered RTP glue '%s'\n", glue->type);
255
256         return 0;
257 }
258
259 int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
260 {
261         struct ast_rtp_glue *current_glue = NULL;
262
263         AST_RWLIST_WRLOCK(&glues);
264
265         if ((current_glue = AST_RWLIST_REMOVE(&glues, glue, entry))) {
266                 ast_verb(2, "Unregistered RTP glue '%s'\n", glue->type);
267         }
268
269         AST_RWLIST_UNLOCK(&glues);
270
271         return current_glue ? 0 : -1;
272 }
273
274 static void instance_destructor(void *obj)
275 {
276         struct ast_rtp_instance *instance = obj;
277
278         /* Pass us off to the engine to destroy */
279         if (instance->data && instance->engine->destroy(instance)) {
280                 ast_debug(1, "Engine '%s' failed to destroy RTP instance '%p'\n", instance->engine->name, instance);
281                 return;
282         }
283
284         /* Drop our engine reference */
285         ast_module_unref(instance->engine->mod);
286
287         ast_debug(1, "Destroyed RTP instance '%p'\n", instance);
288 }
289
290 int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
291 {
292         ao2_ref(instance, -1);
293
294         return 0;
295 }
296
297 struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data)
298 {
299         struct sockaddr_in address = { 0, };
300         struct ast_rtp_instance *instance = NULL;
301         struct ast_rtp_engine *engine = NULL;
302
303         AST_RWLIST_RDLOCK(&engines);
304
305         /* If an engine name was specified try to use it or otherwise use the first one registered */
306         if (!ast_strlen_zero(engine_name)) {
307                 AST_RWLIST_TRAVERSE(&engines, engine, entry) {
308                         if (!strcmp(engine->name, engine_name)) {
309                                 break;
310                         }
311                 }
312         } else {
313                 engine = AST_RWLIST_FIRST(&engines);
314         }
315
316         /* If no engine was actually found bail out now */
317         if (!engine) {
318                 ast_log(LOG_ERROR, "No RTP engine was found. Do you have one loaded?\n");
319                 AST_RWLIST_UNLOCK(&engines);
320                 return NULL;
321         }
322
323         /* Bump up the reference count before we return so the module can not be unloaded */
324         ast_module_ref(engine->mod);
325
326         AST_RWLIST_UNLOCK(&engines);
327
328         /* Allocate a new RTP instance */
329         if (!(instance = ao2_alloc(sizeof(*instance), instance_destructor))) {
330                 ast_module_unref(engine->mod);
331                 return NULL;
332         }
333         instance->engine = engine;
334         instance->local_address.sin_family = AF_INET;
335         instance->local_address.sin_addr = sin->sin_addr;
336         instance->remote_address.sin_family = AF_INET;
337         address.sin_family = AF_INET;
338         address.sin_addr = sin->sin_addr;
339
340         ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
341
342         /* And pass it off to the engine to setup */
343         if (instance->engine->new(instance, sched, &address, data)) {
344                 ast_debug(1, "Engine '%s' failed to setup RTP instance '%p'\n", engine->name, instance);
345                 ao2_ref(instance, -1);
346                 return NULL;
347         }
348
349         ast_debug(1, "RTP instance '%p' is setup and ready to go\n", instance);
350
351         return instance;
352 }
353
354 void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
355 {
356         instance->data = data;
357 }
358
359 void *ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
360 {
361         return instance->data;
362 }
363
364 int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
365 {
366         return instance->engine->write(instance, frame);
367 }
368
369 struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
370 {
371         return instance->engine->read(instance, rtcp);
372 }
373
374 int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
375 {
376         instance->local_address.sin_addr = address->sin_addr;
377         instance->local_address.sin_port = address->sin_port;
378         return 0;
379 }
380
381 int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
382 {
383         instance->remote_address.sin_addr = address->sin_addr;
384         instance->remote_address.sin_port = address->sin_port;
385
386         /* moo */
387
388         if (instance->engine->remote_address_set) {
389                 instance->engine->remote_address_set(instance, &instance->remote_address);
390         }
391
392         return 0;
393 }
394
395 int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
396 {
397         instance->alt_remote_address.sin_addr = address->sin_addr;
398         instance->alt_remote_address.sin_port = address->sin_port;
399
400         /* oink */
401
402         if (instance->engine->alt_remote_address_set) {
403                 instance->engine->alt_remote_address_set(instance, &instance->alt_remote_address);
404         }
405
406         return 0;
407 }
408
409 int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
410 {
411         if ((address->sin_family != AF_INET) ||
412             (address->sin_port != instance->local_address.sin_port) ||
413             (address->sin_addr.s_addr != instance->local_address.sin_addr.s_addr)) {
414                 memcpy(address, &instance->local_address, sizeof(*address));
415                 return 1;
416         }
417
418         return 0;
419 }
420
421 int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
422 {
423         if ((address->sin_family != AF_INET) ||
424             (address->sin_port != instance->remote_address.sin_port) ||
425             (address->sin_addr.s_addr != instance->remote_address.sin_addr.s_addr)) {
426                 memcpy(address, &instance->remote_address, sizeof(*address));
427                 return 1;
428         }
429
430         return 0;
431 }
432
433 void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value)
434 {
435         if (instance->engine->extended_prop_set) {
436                 instance->engine->extended_prop_set(instance, property, value);
437         }
438 }
439
440 void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property)
441 {
442         if (instance->engine->extended_prop_get) {
443                 return instance->engine->extended_prop_get(instance, property);
444         }
445
446         return NULL;
447 }
448
449 void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
450 {
451         instance->properties[property] = value;
452
453         if (instance->engine->prop_set) {
454                 instance->engine->prop_set(instance, property, value);
455         }
456 }
457
458 int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
459 {
460         return instance->properties[property];
461 }
462
463 struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
464 {
465         return &instance->codecs;
466 }
467
468 void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
469 {
470         int i;
471
472         for (i = 0; i < AST_RTP_MAX_PT; i++) {
473                 codecs->payloads[i].asterisk_format = 0;
474                 codecs->payloads[i].code = 0;
475                 if (instance && instance->engine && instance->engine->payload_set) {
476                         instance->engine->payload_set(instance, i, 0, 0);
477                 }
478         }
479 }
480
481 void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
482 {
483         int i;
484
485         for (i = 0; i < AST_RTP_MAX_PT; i++) {
486                 if (static_RTP_PT[i].code) {
487                         codecs->payloads[i].asterisk_format = static_RTP_PT[i].asterisk_format;
488                         codecs->payloads[i].code = static_RTP_PT[i].code;
489                         if (instance && instance->engine && instance->engine->payload_set) {
490                                 instance->engine->payload_set(instance, i, codecs->payloads[i].asterisk_format, codecs->payloads[i].code);
491                         }
492                 }
493         }
494 }
495
496 void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
497 {
498         int i;
499
500         for (i = 0; i < AST_RTP_MAX_PT; i++) {
501                 if (src->payloads[i].code) {
502                         ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
503                         dest->payloads[i].asterisk_format = src->payloads[i].asterisk_format;
504                         dest->payloads[i].code = src->payloads[i].code;
505                         if (instance && instance->engine && instance->engine->payload_set) {
506                                 instance->engine->payload_set(instance, i, dest->payloads[i].asterisk_format, dest->payloads[i].code);
507                         }
508                 }
509         }
510 }
511
512 void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
513 {
514         if (payload < 0 || payload >= AST_RTP_MAX_PT || !static_RTP_PT[payload].code) {
515                 return;
516         }
517
518         codecs->payloads[payload].asterisk_format = static_RTP_PT[payload].asterisk_format;
519         codecs->payloads[payload].code = static_RTP_PT[payload].code;
520
521         ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs);
522
523         if (instance && instance->engine && instance->engine->payload_set) {
524                 instance->engine->payload_set(instance, payload, codecs->payloads[payload].asterisk_format, codecs->payloads[payload].code);
525         }
526 }
527
528 int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt,
529                                  char *mimetype, char *mimesubtype,
530                                  enum ast_rtp_options options,
531                                  unsigned int sample_rate)
532 {
533         unsigned int i;
534         int found = 0;
535
536         if (pt < 0 || pt >= AST_RTP_MAX_PT)
537                 return -1; /* bogus payload type */
538
539         for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) {
540                 const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[i];
541
542                 if (strcasecmp(mimesubtype, t->subtype)) {
543                         continue;
544                 }
545
546                 if (strcasecmp(mimetype, t->type)) {
547                         continue;
548                 }
549
550                 /* if both sample rates have been supplied, and they don't match,
551                                       then this not a match; if one has not been supplied, then the
552                                       rates are not compared */
553                 if (sample_rate && t->sample_rate &&
554                     (sample_rate != t->sample_rate)) {
555                         continue;
556                 }
557
558                 found = 1;
559                 codecs->payloads[pt] = t->payload_type;
560
561                 if ((t->payload_type.code == AST_FORMAT_G726) &&
562                                         t->payload_type.asterisk_format &&
563                     (options & AST_RTP_OPT_G726_NONSTANDARD)) {
564                         codecs->payloads[pt].code = AST_FORMAT_G726_AAL2;
565                 }
566
567                 if (instance && instance->engine && instance->engine->payload_set) {
568                         instance->engine->payload_set(instance, pt, codecs->payloads[i].asterisk_format, codecs->payloads[i].code);
569                 }
570
571                 break;
572         }
573
574         return (found ? 0 : -2);
575 }
576
577 int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
578 {
579         return ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, instance, payload, mimetype, mimesubtype, options, 0);
580 }
581
582 void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
583 {
584         if (payload < 0 || payload >= AST_RTP_MAX_PT) {
585                 return;
586         }
587
588         ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
589
590         codecs->payloads[payload].asterisk_format = 0;
591         codecs->payloads[payload].code = 0;
592
593         if (instance && instance->engine && instance->engine->payload_set) {
594                 instance->engine->payload_set(instance, payload, 0, 0);
595         }
596 }
597
598 struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload)
599 {
600         struct ast_rtp_payload_type result = { .asterisk_format = 0, };
601
602         if (payload < 0 || payload >= AST_RTP_MAX_PT) {
603                 return result;
604         }
605
606         result.asterisk_format = codecs->payloads[payload].asterisk_format;
607         result.code = codecs->payloads[payload].code;
608
609         if (!result.code) {
610                 result = static_RTP_PT[payload];
611         }
612
613         return result;
614 }
615
616 void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, format_t *astformats, int *nonastformats)
617 {
618         int i;
619
620         *astformats = *nonastformats = 0;
621
622         for (i = 0; i < AST_RTP_MAX_PT; i++) {
623                 if (codecs->payloads[i].code) {
624                         ast_debug(1, "Incorporating payload %d on %p\n", i, codecs);
625                 }
626                 if (codecs->payloads[i].asterisk_format) {
627                         *astformats |= codecs->payloads[i].code;
628                 } else {
629                         *nonastformats |= codecs->payloads[i].code;
630                 }
631         }
632 }
633
634 int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const format_t code)
635 {
636         int i;
637
638         for (i = 0; i < AST_RTP_MAX_PT; i++) {
639                 if (codecs->payloads[i].asterisk_format == asterisk_format && codecs->payloads[i].code == code) {
640                         return i;
641                 }
642         }
643
644         for (i = 0; i < AST_RTP_MAX_PT; i++) {
645                 if (static_RTP_PT[i].asterisk_format == asterisk_format && static_RTP_PT[i].code == code) {
646                         return i;
647                 }
648         }
649
650         return -1;
651 }
652
653 const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const format_t code, enum ast_rtp_options options)
654 {
655         int i;
656
657         for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); i++) {
658                 if (ast_rtp_mime_types[i].payload_type.code == code && ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format) {
659                         if (asterisk_format && (code == AST_FORMAT_G726_AAL2) && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
660                                 return "G726-32";
661                         } else {
662                                 return ast_rtp_mime_types[i].subtype;
663                         }
664                 }
665         }
666
667         return "";
668 }
669
670 unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, format_t code)
671 {
672         unsigned int i;
673
674         for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) {
675                 if ((ast_rtp_mime_types[i].payload_type.code == code) && (ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format)) {
676                         return ast_rtp_mime_types[i].sample_rate;
677                 }
678         }
679
680         return 0;
681 }
682
683 char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const format_t capability, const int asterisk_format, enum ast_rtp_options options)
684 {
685         format_t format;
686         int found = 0;
687
688         if (!buf) {
689                 return NULL;
690         }
691
692         ast_str_append(&buf, 0, "0x%llx (", (unsigned long long) capability);
693
694         for (format = 1; format < AST_RTP_MAX; format <<= 1) {
695                 if (capability & format) {
696                         const char *name = ast_rtp_lookup_mime_subtype2(asterisk_format, format, options);
697                         ast_str_append(&buf, 0, "%s|", name);
698                         found = 1;
699                 }
700         }
701
702         ast_str_append(&buf, 0, "%s", found ? ")" : "nothing)");
703
704         return ast_str_buffer(buf);
705 }
706
707 void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
708 {
709         codecs->pref = *prefs;
710
711         if (instance && instance->engine->packetization_set) {
712                 instance->engine->packetization_set(instance, &instance->codecs.pref);
713         }
714 }
715
716 int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
717 {
718         return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
719 }
720
721 int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
722 {
723         return instance->engine->dtmf_end ? instance->engine->dtmf_end(instance, digit) : -1;
724 }
725
726 int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
727 {
728         if (!instance->engine->dtmf_mode_set || instance->engine->dtmf_mode_set(instance, dtmf_mode)) {
729                 return -1;
730         }
731
732         instance->dtmf_mode = dtmf_mode;
733
734         return 0;
735 }
736
737 enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
738 {
739         return instance->dtmf_mode;
740 }
741
742 void ast_rtp_instance_update_source(struct ast_rtp_instance *instance)
743 {
744         if (instance->engine->update_source) {
745                 instance->engine->update_source(instance);
746         }
747 }
748
749 void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
750 {
751         if (instance->engine->change_source) {
752                 instance->engine->change_source(instance);
753         }
754 }
755
756 int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
757 {
758         return instance->engine->qos ? instance->engine->qos(instance, tos, cos, desc) : -1;
759 }
760
761 void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
762 {
763         if (instance->engine->stop) {
764                 instance->engine->stop(instance);
765         }
766 }
767
768 int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
769 {
770         return instance->engine->fd ? instance->engine->fd(instance, rtcp) : -1;
771 }
772
773 struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type)
774 {
775         struct ast_rtp_glue *glue = NULL;
776
777         AST_RWLIST_RDLOCK(&glues);
778
779         AST_RWLIST_TRAVERSE(&glues, glue, entry) {
780                 if (!strcasecmp(glue->type, type)) {
781                         break;
782                 }
783         }
784
785         AST_RWLIST_UNLOCK(&glues);
786
787         return glue;
788 }
789
790 static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
791 {
792         enum ast_bridge_result res = AST_BRIDGE_FAILED;
793         struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
794         struct ast_frame *fr = NULL;
795
796         /* Start locally bridging both instances */
797         if (instance0->engine->local_bridge && instance0->engine->local_bridge(instance0, instance1)) {
798                 ast_debug(1, "Failed to locally bridge %s to %s, backing out.\n", c0->name, c1->name);
799                 ast_channel_unlock(c0);
800                 ast_channel_unlock(c1);
801                 return AST_BRIDGE_FAILED_NOWARN;
802         }
803         if (instance1->engine->local_bridge && instance1->engine->local_bridge(instance1, instance0)) {
804                 ast_debug(1, "Failed to locally bridge %s to %s, backing out.\n", c1->name, c0->name);
805                 if (instance0->engine->local_bridge) {
806                         instance0->engine->local_bridge(instance0, NULL);
807                 }
808                 ast_channel_unlock(c0);
809                 ast_channel_unlock(c1);
810                 return AST_BRIDGE_FAILED_NOWARN;
811         }
812
813         ast_channel_unlock(c0);
814         ast_channel_unlock(c1);
815
816         instance0->bridged = instance1;
817         instance1->bridged = instance0;
818
819         ast_poll_channel_add(c0, c1);
820
821         /* Hop into a loop waiting for a frame from either channel */
822         cs[0] = c0;
823         cs[1] = c1;
824         cs[2] = NULL;
825         for (;;) {
826                 /* If the underlying formats have changed force this bridge to break */
827                 if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
828                         ast_debug(1, "rtp-engine-local-bridge: Oooh, formats changed, backing out\n");
829                         res = AST_BRIDGE_FAILED_NOWARN;
830                         break;
831                 }
832                 /* Check if anything changed */
833                 if ((c0->tech_pvt != pvt0) ||
834                     (c1->tech_pvt != pvt1) ||
835                     (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
836                     (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
837                         ast_debug(1, "rtp-engine-local-bridge: Oooh, something is weird, backing out\n");
838                         /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */
839                         if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) {
840                                 ast_frfree(fr);
841                         }
842                         if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) {
843                                 ast_frfree(fr);
844                         }
845                         res = AST_BRIDGE_RETRY;
846                         break;
847                 }
848                 /* Wait on a channel to feed us a frame */
849                 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
850                         if (!timeoutms) {
851                                 res = AST_BRIDGE_RETRY;
852                                 break;
853                         }
854                         ast_debug(2, "rtp-engine-local-bridge: Ooh, empty read...\n");
855                         if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
856                                 break;
857                         }
858                         continue;
859                 }
860                 /* Read in frame from channel */
861                 fr = ast_read(who);
862                 other = (who == c0) ? c1 : c0;
863                 /* Depending on the frame we may need to break out of our bridge */
864                 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
865                             ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
866                             ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
867                         /* Record received frame and who */
868                         *fo = fr;
869                         *rc = who;
870                         ast_debug(1, "rtp-engine-local-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
871                         res = AST_BRIDGE_COMPLETE;
872                         break;
873                 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
874                         if ((fr->subclass.integer == AST_CONTROL_HOLD) ||
875                             (fr->subclass.integer == AST_CONTROL_UNHOLD) ||
876                             (fr->subclass.integer == AST_CONTROL_VIDUPDATE) ||
877                             (fr->subclass.integer == AST_CONTROL_SRCUPDATE) ||
878                             (fr->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {
879                                 /* If we are going on hold, then break callback mode and P2P bridging */
880                                 if (fr->subclass.integer == AST_CONTROL_HOLD) {
881                                         if (instance0->engine->local_bridge) {
882                                                 instance0->engine->local_bridge(instance0, NULL);
883                                         }
884                                         if (instance1->engine->local_bridge) {
885                                                 instance1->engine->local_bridge(instance1, NULL);
886                                         }
887                                         instance0->bridged = NULL;
888                                         instance1->bridged = NULL;
889                                 } else if (fr->subclass.integer == AST_CONTROL_UNHOLD) {
890                                         if (instance0->engine->local_bridge) {
891                                                 instance0->engine->local_bridge(instance0, instance1);
892                                         }
893                                         if (instance1->engine->local_bridge) {
894                                                 instance1->engine->local_bridge(instance1, instance0);
895                                         }
896                                         instance0->bridged = instance1;
897                                         instance1->bridged = instance0;
898                                 }
899                                 ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
900                                 ast_frfree(fr);
901                         } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
902                                 if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
903                                         ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
904                                 }
905                                 ast_frfree(fr);
906                         } else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
907                                 if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
908                                         ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
909                                 }
910                                 ast_frfree(fr);
911                         } else {
912                                 *fo = fr;
913                                 *rc = who;
914                                 ast_debug(1, "rtp-engine-local-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass.integer, who->name);
915                                 res = AST_BRIDGE_COMPLETE;
916                                 break;
917                         }
918                 } else {
919                         if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
920                             (fr->frametype == AST_FRAME_DTMF_END) ||
921                             (fr->frametype == AST_FRAME_VOICE) ||
922                             (fr->frametype == AST_FRAME_VIDEO) ||
923                             (fr->frametype == AST_FRAME_IMAGE) ||
924                             (fr->frametype == AST_FRAME_HTML) ||
925                             (fr->frametype == AST_FRAME_MODEM) ||
926                             (fr->frametype == AST_FRAME_TEXT)) {
927                                 ast_write(other, fr);
928                         }
929
930                         ast_frfree(fr);
931                 }
932                 /* Swap priority */
933                 cs[2] = cs[0];
934                 cs[0] = cs[1];
935                 cs[1] = cs[2];
936         }
937
938         /* Stop locally bridging both instances */
939         if (instance0->engine->local_bridge) {
940                 instance0->engine->local_bridge(instance0, NULL);
941         }
942         if (instance1->engine->local_bridge) {
943                 instance1->engine->local_bridge(instance1, NULL);
944         }
945
946         instance0->bridged = NULL;
947         instance1->bridged = NULL;
948
949         ast_poll_channel_del(c0, c1);
950
951         return res;
952 }
953
954 static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1,
955                                                  struct ast_rtp_instance *vinstance0, struct ast_rtp_instance *vinstance1, struct ast_rtp_instance *tinstance0,
956                                                  struct ast_rtp_instance *tinstance1, struct ast_rtp_glue *glue0, struct ast_rtp_glue *glue1, format_t codec0, format_t codec1, int timeoutms,
957                                                  int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
958 {
959         enum ast_bridge_result res = AST_BRIDGE_FAILED;
960         struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
961         format_t oldcodec0 = codec0, oldcodec1 = codec1;
962         struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
963         struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
964         struct ast_frame *fr = NULL;
965
966         /* Test the first channel */
967         if (!(glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0))) {
968                 ast_rtp_instance_get_remote_address(instance1, &ac1);
969                 if (vinstance1) {
970                         ast_rtp_instance_get_remote_address(vinstance1, &vac1);
971                 }
972                 if (tinstance1) {
973                         ast_rtp_instance_get_remote_address(tinstance1, &tac1);
974                 }
975         } else {
976                 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
977         }
978
979         /* Test the second channel */
980         if (!(glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0))) {
981                 ast_rtp_instance_get_remote_address(instance0, &ac0);
982                 if (vinstance0) {
983                         ast_rtp_instance_get_remote_address(instance0, &vac0);
984                 }
985                 if (tinstance0) {
986                         ast_rtp_instance_get_remote_address(instance0, &tac0);
987                 }
988         } else {
989                 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
990         }
991
992         ast_channel_unlock(c0);
993         ast_channel_unlock(c1);
994
995         instance0->bridged = instance1;
996         instance1->bridged = instance0;
997
998         ast_poll_channel_add(c0, c1);
999
1000         /* Go into a loop handling any stray frames that may come in */
1001         cs[0] = c0;
1002         cs[1] = c1;
1003         cs[2] = NULL;
1004         for (;;) {
1005                 /* Check if anything changed */
1006                 if ((c0->tech_pvt != pvt0) ||
1007                     (c1->tech_pvt != pvt1) ||
1008                     (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
1009                     (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
1010                         ast_debug(1, "Oooh, something is weird, backing out\n");
1011                         res = AST_BRIDGE_RETRY;
1012                         break;
1013                 }
1014
1015                 /* Check if they have changed their address */
1016                 ast_rtp_instance_get_remote_address(instance1, &t1);
1017                 if (vinstance1) {
1018                         ast_rtp_instance_get_remote_address(vinstance1, &vt1);
1019                 }
1020                 if (tinstance1) {
1021                         ast_rtp_instance_get_remote_address(tinstance1, &tt1);
1022                 }
1023                 if (glue1->get_codec) {
1024                         codec1 = glue1->get_codec(c1);
1025                 }
1026
1027                 ast_rtp_instance_get_remote_address(instance0, &t0);
1028                 if (vinstance0) {
1029                         ast_rtp_instance_get_remote_address(vinstance0, &vt0);
1030                 }
1031                 if (tinstance0) {
1032                         ast_rtp_instance_get_remote_address(tinstance0, &tt0);
1033                 }
1034                 if (glue0->get_codec) {
1035                         codec0 = glue0->get_codec(c0);
1036                 }
1037
1038                 if ((inaddrcmp(&t1, &ac1)) ||
1039                     (vinstance1 && inaddrcmp(&vt1, &vac1)) ||
1040                     (tinstance1 && inaddrcmp(&tt1, &tac1)) ||
1041                     (codec1 != oldcodec1)) {
1042                         ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %s)\n",
1043                                   c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), ast_getformatname(codec1));
1044                         ast_debug(1, "Oooh, '%s' changed end vaddress to %s:%d (format %s)\n",
1045                                   c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), ast_getformatname(codec1));
1046                         ast_debug(1, "Oooh, '%s' changed end taddress to %s:%d (format %s)\n",
1047                                   c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), ast_getformatname(codec1));
1048                         ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
1049                                   c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), ast_getformatname(oldcodec1));
1050                         ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
1051                                   c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), ast_getformatname(oldcodec1));
1052                         ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
1053                                   c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), ast_getformatname(oldcodec1));
1054                         if (glue0->update_peer(c0, t1.sin_addr.s_addr ? instance1 : NULL, vt1.sin_addr.s_addr ? vinstance1 : NULL, tt1.sin_addr.s_addr ? tinstance1 : NULL, codec1, 0)) {
1055                                 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
1056                         }
1057                         memcpy(&ac1, &t1, sizeof(ac1));
1058                         memcpy(&vac1, &vt1, sizeof(vac1));
1059                         memcpy(&tac1, &tt1, sizeof(tac1));
1060                         oldcodec1 = codec1;
1061                 }
1062                 if ((inaddrcmp(&t0, &ac0)) ||
1063                     (vinstance0 && inaddrcmp(&vt0, &vac0)) ||
1064                     (tinstance0 && inaddrcmp(&tt0, &tac0)) ||
1065                     (codec0 != oldcodec0)) {
1066                         ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %s)\n",
1067                                   c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), ast_getformatname(codec0));
1068                         ast_debug(1, "Oooh, '%s' was %s:%d/(format %s)\n",
1069                                   c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), ast_getformatname(oldcodec0));
1070                         if (glue1->update_peer(c1, t0.sin_addr.s_addr ? instance0 : NULL, vt0.sin_addr.s_addr ? vinstance0 : NULL, tt0.sin_addr.s_addr ? tinstance0 : NULL, codec0, 0)) {
1071                                 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
1072                         }
1073                         memcpy(&ac0, &t0, sizeof(ac0));
1074                         memcpy(&vac0, &vt0, sizeof(vac0));
1075                         memcpy(&tac0, &tt0, sizeof(tac0));
1076                         oldcodec0 = codec0;
1077                 }
1078
1079                 /* Wait for frame to come in on the channels */
1080                 if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
1081                         if (!timeoutms) {
1082                                 res = AST_BRIDGE_RETRY;
1083                                 break;
1084                         }
1085                         ast_debug(1, "Ooh, empty read...\n");
1086                         if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
1087                                 break;
1088                         }
1089                         continue;
1090                 }
1091                 fr = ast_read(who);
1092                 other = (who == c0) ? c1 : c0;
1093                 if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
1094                             (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
1095                              ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
1096                         /* Break out of bridge */
1097                         *fo = fr;
1098                         *rc = who;
1099                         ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
1100                         res = AST_BRIDGE_COMPLETE;
1101                         break;
1102                 } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
1103                         if ((fr->subclass.integer == AST_CONTROL_HOLD) ||
1104                             (fr->subclass.integer == AST_CONTROL_UNHOLD) ||
1105                             (fr->subclass.integer == AST_CONTROL_VIDUPDATE) ||
1106                             (fr->subclass.integer == AST_CONTROL_SRCUPDATE) ||
1107                             (fr->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {
1108                                 if (fr->subclass.integer == AST_CONTROL_HOLD) {
1109                                         /* If we someone went on hold we want the other side to reinvite back to us */
1110                                         if (who == c0) {
1111                                                 glue1->update_peer(c1, NULL, NULL, NULL, 0, 0);
1112                                         } else {
1113                                                 glue0->update_peer(c0, NULL, NULL, NULL, 0, 0);
1114                                         }
1115                                 } else if (fr->subclass.integer == AST_CONTROL_UNHOLD) {
1116                                         /* If they went off hold they should go back to being direct */
1117                                         if (who == c0) {
1118                                                 glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0);
1119                                         } else {
1120                                                 glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0);
1121                                         }
1122                                 }
1123                                 /* Update local address information */
1124                                 ast_rtp_instance_get_remote_address(instance0, &t0);
1125                                 memcpy(&ac0, &t0, sizeof(ac0));
1126                                 ast_rtp_instance_get_remote_address(instance1, &t1);
1127                                 memcpy(&ac1, &t1, sizeof(ac1));
1128                                 /* Update codec information */
1129                                 if (glue0->get_codec && c0->tech_pvt) {
1130                                         oldcodec0 = codec0 = glue0->get_codec(c0);
1131                                 }
1132                                 if (glue1->get_codec && c1->tech_pvt) {
1133                                         oldcodec1 = codec1 = glue1->get_codec(c1);
1134                                 }
1135                                 ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
1136                                 ast_frfree(fr);
1137                         } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
1138                                 if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
1139                                         ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
1140                                 }
1141                                 ast_frfree(fr);
1142                         } else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
1143                                 if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
1144                                         ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
1145                                 }
1146                                 ast_frfree(fr);
1147                         } else {
1148                                 *fo = fr;
1149                                 *rc = who;
1150                                 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass.integer, who->name);
1151                                 return AST_BRIDGE_COMPLETE;
1152                         }
1153                 } else {
1154                         if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
1155                             (fr->frametype == AST_FRAME_DTMF_END) ||
1156                             (fr->frametype == AST_FRAME_VOICE) ||
1157                             (fr->frametype == AST_FRAME_VIDEO) ||
1158                             (fr->frametype == AST_FRAME_IMAGE) ||
1159                             (fr->frametype == AST_FRAME_HTML) ||
1160                             (fr->frametype == AST_FRAME_MODEM) ||
1161                             (fr->frametype == AST_FRAME_TEXT)) {
1162                                 ast_write(other, fr);
1163                         }
1164                         ast_frfree(fr);
1165                 }
1166                 /* Swap priority */
1167                 cs[2] = cs[0];
1168                 cs[0] = cs[1];
1169                 cs[1] = cs[2];
1170         }
1171
1172         if (glue0->update_peer(c0, NULL, NULL, NULL, 0, 0)) {
1173                 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
1174         }
1175         if (glue1->update_peer(c1, NULL, NULL, NULL, 0, 0)) {
1176                 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
1177         }
1178
1179         instance0->bridged = NULL;
1180         instance1->bridged = NULL;
1181
1182         ast_poll_channel_del(c0, c1);
1183
1184         return res;
1185 }
1186
1187 /*!
1188  * \brief Conditionally unref an rtp instance
1189  */
1190 static void unref_instance_cond(struct ast_rtp_instance **instance)
1191 {
1192         if (*instance) {
1193                 ao2_ref(*instance, -1);
1194                 *instance = NULL;
1195         }
1196 }
1197
1198 enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
1199 {
1200         struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
1201                         *vinstance0 = NULL, *vinstance1 = NULL,
1202                         *tinstance0 = NULL, *tinstance1 = NULL;
1203         struct ast_rtp_glue *glue0, *glue1;
1204         enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1205         enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1206         enum ast_bridge_result res = AST_BRIDGE_FAILED;
1207         format_t codec0 = 0, codec1 = 0;
1208         int unlock_chans = 1;
1209
1210         /* Lock both channels so we can look for the glue that binds them together */
1211         ast_channel_lock(c0);
1212         while (ast_channel_trylock(c1)) {
1213                 ast_channel_unlock(c0);
1214                 usleep(1);
1215                 ast_channel_lock(c0);
1216         }
1217
1218         /* Ensure neither channel got hungup during lock avoidance */
1219         if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
1220                 ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
1221                 goto done;
1222         }
1223
1224         /* Grab glue that binds each channel to something using the RTP engine */
1225         if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
1226                 ast_debug(1, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
1227                 goto done;
1228         }
1229
1230         audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
1231         video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1232         text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1233
1234         audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
1235         video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1236         text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1237
1238         /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
1239         if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1240                 audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1241         }
1242         if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1243                 audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1244         }
1245
1246         /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
1247         if (audio_glue0_res == AST_RTP_GLUE_RESULT_FORBID || audio_glue1_res == AST_RTP_GLUE_RESULT_FORBID) {
1248                 res = AST_BRIDGE_FAILED_NOWARN;
1249                 goto done;
1250         }
1251
1252         /* If we need to get DTMF see if we can do it outside of the RTP stream itself */
1253         if ((flags & AST_BRIDGE_DTMF_CHANNEL_0) && instance0->properties[AST_RTP_PROPERTY_DTMF]) {
1254                 res = AST_BRIDGE_FAILED_NOWARN;
1255                 goto done;
1256         }
1257         if ((flags & AST_BRIDGE_DTMF_CHANNEL_1) && instance1->properties[AST_RTP_PROPERTY_DTMF]) {
1258                 res = AST_BRIDGE_FAILED_NOWARN;
1259                 goto done;
1260         }
1261
1262         /* If we have gotten to a local bridge make sure that both sides have the same local bridge callback and that they are DTMF compatible */
1263         if ((audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL || audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) && ((instance0->engine->local_bridge != instance1->engine->local_bridge) || (instance0->engine->dtmf_compatible && !instance0->engine->dtmf_compatible(c0, instance0, c1, instance1)))) {
1264                 res = AST_BRIDGE_FAILED_NOWARN;
1265                 goto done;
1266         }
1267
1268         /* Make sure that codecs match */
1269         codec0 = glue0->get_codec ? glue0->get_codec(c0) : 0;
1270         codec1 = glue1->get_codec ? glue1->get_codec(c1) : 0;
1271         if (codec0 && codec1 && !(codec0 & codec1)) {
1272                 ast_debug(1, "Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n", ast_getformatname(codec0), ast_getformatname(codec1));
1273                 res = AST_BRIDGE_FAILED_NOWARN;
1274                 goto done;
1275         }
1276
1277         instance0->glue = glue0;
1278         instance1->glue = glue1;
1279         instance0->chan = c0;
1280         instance1->chan = c1;
1281
1282         /* Depending on the end result for bridging either do a local bridge or remote bridge */
1283         if (audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL || audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) {
1284                 ast_verbose(VERBOSE_PREFIX_3 "Locally bridging %s and %s\n", c0->name, c1->name);
1285                 res = local_bridge_loop(c0, c1, instance0, instance1, timeoutms, flags, fo, rc, c0->tech_pvt, c1->tech_pvt);
1286         } else {
1287                 ast_verbose(VERBOSE_PREFIX_3 "Remotely bridging %s and %s\n", c0->name, c1->name);
1288                 res = remote_bridge_loop(c0, c1, instance0, instance1, vinstance0, vinstance1,
1289                                 tinstance0, tinstance1, glue0, glue1, codec0, codec1, timeoutms, flags,
1290                                 fo, rc, c0->tech_pvt, c1->tech_pvt);
1291         }
1292
1293         instance0->glue = NULL;
1294         instance1->glue = NULL;
1295         instance0->chan = NULL;
1296         instance1->chan = NULL;
1297
1298         unlock_chans = 0;
1299
1300 done:
1301         if (unlock_chans) {
1302                 ast_channel_unlock(c0);
1303                 ast_channel_unlock(c1);
1304         }
1305
1306         unref_instance_cond(&instance0);
1307         unref_instance_cond(&instance1);
1308         unref_instance_cond(&vinstance0);
1309         unref_instance_cond(&vinstance1);
1310         unref_instance_cond(&tinstance0);
1311         unref_instance_cond(&tinstance1);
1312
1313         return res;
1314 }
1315
1316 struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
1317 {
1318         return instance->bridged;
1319 }
1320
1321 void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
1322 {
1323         struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
1324                 *vinstance0 = NULL, *vinstance1 = NULL,
1325                 *tinstance0 = NULL, *tinstance1 = NULL;
1326         struct ast_rtp_glue *glue0, *glue1;
1327         enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1328         enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1329         format_t codec0 = 0, codec1 = 0;
1330         int res = 0;
1331
1332         /* Lock both channels so we can look for the glue that binds them together */
1333         ast_channel_lock(c0);
1334         while (ast_channel_trylock(c1)) {
1335                 ast_channel_unlock(c0);
1336                 usleep(1);
1337                 ast_channel_lock(c0);
1338         }
1339
1340         /* Grab glue that binds each channel to something using the RTP engine */
1341         if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
1342                 ast_debug(1, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
1343                 goto done;
1344         }
1345
1346         audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
1347         video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1348         text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1349
1350         audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
1351         video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1352         text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1353
1354         /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
1355         if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1356                 audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1357         }
1358         if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1359                 audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1360         }
1361         if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) {
1362                 codec0 = glue0->get_codec(c0);
1363         }
1364         if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) {
1365                 codec1 = glue1->get_codec(c1);
1366         }
1367
1368         /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
1369         if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
1370                 goto done;
1371         }
1372
1373         /* Make sure we have matching codecs */
1374         if (!(codec0 & codec1)) {
1375                 goto done;
1376         }
1377
1378         ast_rtp_codecs_payloads_copy(&instance0->codecs, &instance1->codecs, instance1);
1379
1380         if (vinstance0 && vinstance1) {
1381                 ast_rtp_codecs_payloads_copy(&vinstance0->codecs, &vinstance1->codecs, vinstance1);
1382         }
1383         if (tinstance0 && tinstance1) {
1384                 ast_rtp_codecs_payloads_copy(&tinstance0->codecs, &tinstance1->codecs, tinstance1);
1385         }
1386
1387         res = 0;
1388
1389 done:
1390         ast_channel_unlock(c0);
1391         ast_channel_unlock(c1);
1392
1393         unref_instance_cond(&instance0);
1394         unref_instance_cond(&instance1);
1395         unref_instance_cond(&vinstance0);
1396         unref_instance_cond(&vinstance1);
1397         unref_instance_cond(&tinstance0);
1398         unref_instance_cond(&tinstance1);
1399
1400         if (!res) {
1401                 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
1402         }
1403 }
1404
1405 int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
1406 {
1407         struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
1408                         *vinstance0 = NULL, *vinstance1 = NULL,
1409                         *tinstance0 = NULL, *tinstance1 = NULL;
1410         struct ast_rtp_glue *glue0, *glue1;
1411         enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1412         enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1413         format_t codec0 = 0, codec1 = 0;
1414         int res = 0;
1415
1416         /* If there is no second channel just immediately bail out, we are of no use in that scenario */
1417         if (!c1) {
1418                 return -1;
1419         }
1420
1421         /* Lock both channels so we can look for the glue that binds them together */
1422         ast_channel_lock(c0);
1423         while (ast_channel_trylock(c1)) {
1424                 ast_channel_unlock(c0);
1425                 usleep(1);
1426                 ast_channel_lock(c0);
1427         }
1428
1429         /* Grab glue that binds each channel to something using the RTP engine */
1430         if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
1431                 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
1432                 goto done;
1433         }
1434
1435         audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
1436         video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1437         text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1438
1439         audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
1440         video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1441         text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1442
1443         /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
1444         if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1445                 audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1446         }
1447         if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1448                 audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1449         }
1450         if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) {
1451                 codec0 = glue0->get_codec(c0);
1452         }
1453         if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) {
1454                 codec1 = glue1->get_codec(c1);
1455         }
1456
1457         /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
1458         if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
1459                 goto done;
1460         }
1461
1462         /* Make sure we have matching codecs */
1463         if (!(codec0 & codec1)) {
1464                 goto done;
1465         }
1466
1467         /* Bridge media early */
1468         if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0)) {
1469                 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
1470         }
1471
1472         res = 0;
1473
1474 done:
1475         ast_channel_unlock(c0);
1476         ast_channel_unlock(c1);
1477
1478         unref_instance_cond(&instance0);
1479         unref_instance_cond(&instance1);
1480         unref_instance_cond(&vinstance0);
1481         unref_instance_cond(&vinstance1);
1482         unref_instance_cond(&tinstance0);
1483         unref_instance_cond(&tinstance1);
1484
1485         if (!res) {
1486                 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
1487         }
1488
1489         return res;
1490 }
1491
1492 int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
1493 {
1494         return instance->engine->red_init ? instance->engine->red_init(instance, buffer_time, payloads, generations) : -1;
1495 }
1496
1497 int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
1498 {
1499         return instance->engine->red_buffer ? instance->engine->red_buffer(instance, frame) : -1;
1500 }
1501
1502 int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
1503 {
1504         return instance->engine->get_stat ? instance->engine->get_stat(instance, stats, stat) : -1;
1505 }
1506
1507 char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
1508 {
1509         struct ast_rtp_instance_stats stats = { 0, };
1510         enum ast_rtp_instance_stat stat;
1511
1512         /* Determine what statistics we will need to retrieve based on field passed in */
1513         if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
1514                 stat = AST_RTP_INSTANCE_STAT_ALL;
1515         } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
1516                 stat = AST_RTP_INSTANCE_STAT_COMBINED_JITTER;
1517         } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
1518                 stat = AST_RTP_INSTANCE_STAT_COMBINED_LOSS;
1519         } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
1520                 stat = AST_RTP_INSTANCE_STAT_COMBINED_RTT;
1521         } else {
1522                 return NULL;
1523         }
1524
1525         /* Attempt to actually retrieve the statistics we need to generate the quality string */
1526         if (ast_rtp_instance_get_stats(instance, &stats, stat)) {
1527                 return NULL;
1528         }
1529
1530         /* Now actually fill the buffer with the good information */
1531         if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
1532                 snprintf(buf, size, "ssrc=%i;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
1533                          stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.txjitter, stats.rxcount, stats.rxjitter, stats.txcount, stats.txploss, stats.rtt);
1534         } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
1535                 snprintf(buf, size, "minrxjitter=%f;maxrxjitter=%f;avgrxjitter=%f;stdevrxjitter=%f;reported_minjitter=%f;reported_maxjitter=%f;reported_avgjitter=%f;reported_stdevjitter=%f;",
1536                          stats.local_minjitter, stats.local_maxjitter, stats.local_normdevjitter, sqrt(stats.local_stdevjitter), stats.remote_minjitter, stats.remote_maxjitter, stats.remote_normdevjitter, sqrt(stats.remote_stdevjitter));
1537         } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
1538                 snprintf(buf, size, "minrxlost=%f;maxrxlost=%f;avgrxlost=%f;stdevrxlost=%f;reported_minlost=%f;reported_maxlost=%f;reported_avglost=%f;reported_stdevlost=%f;",
1539                          stats.local_minrxploss, stats.local_maxrxploss, stats.local_normdevrxploss, sqrt(stats.local_stdevrxploss), stats.remote_minrxploss, stats.remote_maxrxploss, stats.remote_normdevrxploss, sqrt(stats.remote_stdevrxploss));
1540         } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
1541                 snprintf(buf, size, "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", stats.minrtt, stats.maxrtt, stats.normdevrtt, stats.stdevrtt);
1542         }
1543
1544         return buf;
1545 }
1546
1547 void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
1548 {
1549         char quality_buf[AST_MAX_USER_FIELD], *quality;
1550         struct ast_channel *bridge = ast_bridged_channel(chan);
1551
1552         if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
1553                 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality);
1554                 if (bridge) {
1555                         pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality);
1556                 }
1557         }
1558
1559         if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) {
1560                 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality);
1561                 if (bridge) {
1562                         pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality);
1563                 }
1564         }
1565
1566         if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) {
1567                 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality);
1568                 if (bridge) {
1569                         pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality);
1570                 }
1571         }
1572
1573         if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) {
1574                 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality);
1575                 if (bridge) {
1576                         pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality);
1577                 }
1578         }
1579 }
1580
1581 int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, format_t format)
1582 {
1583         return instance->engine->set_read_format ? instance->engine->set_read_format(instance, format) : -1;
1584 }
1585
1586 int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, format_t format)
1587 {
1588         return instance->engine->set_write_format ? instance->engine->set_write_format(instance, format) : -1;
1589 }
1590
1591 int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer)
1592 {
1593         struct ast_rtp_glue *glue;
1594         struct ast_rtp_instance *peer_instance = NULL;
1595         int res = -1;
1596
1597         if (!instance->engine->make_compatible) {
1598                 return -1;
1599         }
1600
1601         ast_channel_lock(peer);
1602
1603         if (!(glue = ast_rtp_instance_get_glue(peer->tech->type))) {
1604                 ast_channel_unlock(peer);
1605                 return -1;
1606         }
1607
1608         glue->get_rtp_info(peer, &peer_instance);
1609
1610         if (!peer_instance || peer_instance->engine != instance->engine) {
1611                 ast_channel_unlock(peer);
1612                 ao2_ref(peer_instance, -1);
1613                 peer_instance = NULL;
1614                 return -1;
1615         }
1616
1617         res = instance->engine->make_compatible(chan, instance, peer, peer_instance);
1618
1619         ast_channel_unlock(peer);
1620
1621         ao2_ref(peer_instance, -1);
1622         peer_instance = NULL;
1623
1624         return res;
1625 }
1626
1627 format_t ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk)
1628 {
1629         format_t formats;
1630
1631         if (instance->engine->available_formats && (formats = instance->engine->available_formats(instance, to_endpoint, to_asterisk))) {
1632                 return formats;
1633         }
1634
1635         return ast_translate_available_formats(to_endpoint, to_asterisk);
1636 }
1637
1638 int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
1639 {
1640         return instance->engine->activate ? instance->engine->activate(instance) : 0;
1641 }
1642
1643 void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
1644 {
1645         if (instance->engine->stun_request) {
1646                 instance->engine->stun_request(instance, suggestion, username);
1647         }
1648 }
1649
1650 void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
1651 {
1652         instance->timeout = timeout;
1653 }
1654
1655 void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout)
1656 {
1657         instance->holdtimeout = timeout;
1658 }
1659
1660 int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
1661 {
1662         return instance->timeout;
1663 }
1664
1665 int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance)
1666 {
1667         return instance->holdtimeout;
1668 }
1669
1670 struct ast_rtp_engine *ast_rtp_instance_get_engine(struct ast_rtp_instance *instance)
1671 {
1672         return instance->engine;
1673 }
1674
1675 struct ast_rtp_glue *ast_rtp_instance_get_active_glue(struct ast_rtp_instance *instance)
1676 {
1677         return instance->glue;
1678 }
1679
1680 struct ast_channel *ast_rtp_instance_get_chan(struct ast_rtp_instance *instance)
1681 {
1682         return instance->chan;
1683 }
1684
1685 int ast_rtp_engine_register_srtp(struct ast_srtp_res *srtp_res, struct ast_srtp_policy_res *policy_res)
1686 {
1687         if (res_srtp || res_srtp_policy) {
1688                 return -1;
1689         }
1690         if (!srtp_res || !policy_res) {
1691                 return -1;
1692         }
1693
1694         res_srtp = srtp_res;
1695         res_srtp_policy = policy_res;
1696
1697         return 0;
1698 }
1699
1700 void ast_rtp_engine_unregister_srtp(void)
1701 {
1702         res_srtp = NULL;
1703         res_srtp_policy = NULL;
1704 }
1705
1706 int ast_rtp_engine_srtp_is_registered(void)
1707 {
1708         return res_srtp && res_srtp_policy;
1709 }
1710
1711 int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *policy)
1712 {
1713         if (!res_srtp) {
1714                 return -1;
1715         }
1716
1717         if (!instance->srtp) {
1718                 return res_srtp->create(&instance->srtp, instance, policy);
1719         } else {
1720                 return res_srtp->add_stream(instance->srtp, policy);
1721         }
1722 }
1723
1724 struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance)
1725 {
1726         return instance->srtp;
1727 }