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