Wed Jan 8 2020 09:49:50

Asterisk developer's documentation


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