Asterisk - The Open Source Telephony Project  21.4.1
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 /*** DOCUMENTATION
31  <managerEvent language="en_US" name="RTCPSent">
32  <managerEventInstance class="EVENT_FLAG_REPORTING">
33  <synopsis>Raised when an RTCP packet is sent.</synopsis>
34  <syntax>
35  <channel_snapshot/>
36  <parameter name="SSRC">
37  <para>The SSRC identifier for our stream</para>
38  </parameter>
39  <parameter name="PT">
40  <para>The type of packet for this RTCP report.</para>
41  <enumlist>
42  <enum name="200(SR)"/>
43  <enum name="201(RR)"/>
44  </enumlist>
45  </parameter>
46  <parameter name="To">
47  <para>The address the report is sent to.</para>
48  </parameter>
49  <parameter name="ReportCount">
50  <para>The number of reports that were sent.</para>
51  <para>The report count determines the number of ReportX headers in
52  the message. The X for each set of report headers will range from 0 to
53  <literal>ReportCount - 1</literal>.</para>
54  </parameter>
55  <parameter name="SentNTP" required="false">
56  <para>The time the sender generated the report. Only valid when
57  PT is <literal>200(SR)</literal>.</para>
58  </parameter>
59  <parameter name="SentRTP" required="false">
60  <para>The sender's last RTP timestamp. Only valid when PT is
61  <literal>200(SR)</literal>.</para>
62  </parameter>
63  <parameter name="SentPackets" required="false">
64  <para>The number of packets the sender has sent. Only valid when PT
65  is <literal>200(SR)</literal>.</para>
66  </parameter>
67  <parameter name="SentOctets" required="false">
68  <para>The number of bytes the sender has sent. Only valid when PT is
69  <literal>200(SR)</literal>.</para>
70  </parameter>
71  <parameter name="ReportXSourceSSRC">
72  <para>The SSRC for the source of this report block.</para>
73  </parameter>
74  <parameter name="ReportXFractionLost">
75  <para>The fraction of RTP data packets from <literal>ReportXSourceSSRC</literal>
76  lost since the previous SR or RR report was sent.</para>
77  </parameter>
78  <parameter name="ReportXCumulativeLost">
79  <para>The total number of RTP data packets from <literal>ReportXSourceSSRC</literal>
80  lost since the beginning of reception.</para>
81  </parameter>
82  <parameter name="ReportXHighestSequence">
83  <para>The highest sequence number received in an RTP data packet from
84  <literal>ReportXSourceSSRC</literal>.</para>
85  </parameter>
86  <parameter name="ReportXSequenceNumberCycles">
87  <para>The number of sequence number cycles seen for the RTP data
88  received from <literal>ReportXSourceSSRC</literal>.</para>
89  </parameter>
90  <parameter name="ReportXIAJitter">
91  <para>An estimate of the statistical variance of the RTP data packet
92  interarrival time, measured in timestamp units.</para>
93  </parameter>
94  <parameter name="ReportXLSR">
95  <para>The last SR timestamp received from <literal>ReportXSourceSSRC</literal>.
96  If no SR has been received from <literal>ReportXSourceSSRC</literal>,
97  then 0.</para>
98  </parameter>
99  <parameter name="ReportXDLSR">
100  <para>The delay, expressed in units of 1/65536 seconds, between
101  receiving the last SR packet from <literal>ReportXSourceSSRC</literal>
102  and sending this report.</para>
103  </parameter>
104  </syntax>
105  <see-also>
106  <ref type="managerEvent">RTCPReceived</ref>
107  </see-also>
108  </managerEventInstance>
109  </managerEvent>
110  <managerEvent language="en_US" name="RTCPReceived">
111  <managerEventInstance class="EVENT_FLAG_REPORTING">
112  <synopsis>Raised when an RTCP packet is received.</synopsis>
113  <syntax>
114  <channel_snapshot/>
115  <parameter name="SSRC">
116  <para>The SSRC identifier for the remote system</para>
117  </parameter>
118  <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='PT'])" />
119  <parameter name="From">
120  <para>The address the report was received from.</para>
121  </parameter>
122  <parameter name="RTT">
123  <para>Calculated Round-Trip Time in seconds</para>
124  </parameter>
125  <parameter name="ReportCount">
126  <para>The number of reports that were received.</para>
127  <para>The report count determines the number of ReportX headers in
128  the message. The X for each set of report headers will range from 0 to
129  <literal>ReportCount - 1</literal>.</para>
130  </parameter>
131  <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentNTP'])" />
132  <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentRTP'])" />
133  <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentPackets'])" />
134  <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentOctets'])" />
135  <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[contains(@name, 'ReportX')])" />
136  </syntax>
137  <see-also>
138  <ref type="managerEvent">RTCPSent</ref>
139  </see-also>
140  </managerEventInstance>
141  </managerEvent>
142  ***/
143 
144 #include "asterisk.h"
145 
146 #include <sched.h> /* for sched_yield */
147 #include <sys/time.h> /* for timeval */
148 #include <time.h> /* for time_t */
149 
150 #include "asterisk/_private.h" /* for ast_rtp_engine_init prototype */
151 #include "asterisk/astobj2.h" /* for ao2_cleanup, ao2_ref, etc */
152 #include "asterisk/channel.h" /* for ast_channel_name, etc */
153 #include "asterisk/codec.h" /* for ast_codec_media_type2str, etc */
154 #include "asterisk/format.h" /* for ast_format_cmp, etc */
155 #include "asterisk/format_cache.h" /* for ast_format_adpcm, etc */
156 #include "asterisk/format_cap.h" /* for ast_format_cap_alloc, etc */
157 #include "asterisk/json.h" /* for ast_json_ref, etc */
158 #include "asterisk/linkedlists.h" /* for ast_rtp_engine::<anonymous>, etc */
159 #include "asterisk/lock.h" /* for ast_rwlock_unlock, etc */
160 #include "asterisk/logger.h" /* for ast_log, ast_debug, etc */
161 #include "asterisk/manager.h"
162 #include "asterisk/module.h" /* for ast_module_unref, etc */
163 #include "asterisk/netsock2.h" /* for ast_sockaddr_copy, etc */
164 #include "asterisk/options.h" /* for ast_option_rtpptdynamic */
165 #include "asterisk/pbx.h" /* for pbx_builtin_setvar_helper */
166 #include "asterisk/res_srtp.h" /* for ast_srtp_res */
167 #include "asterisk/rtp_engine.h" /* for ast_rtp_codecs, etc */
168 #include "asterisk/stasis.h" /* for stasis_message_data, etc */
169 #include "asterisk/stasis_channels.h" /* for ast_channel_stage_snapshot, etc */
170 #include "asterisk/strings.h" /* for ast_str_append, etc */
171 #include "asterisk/time.h" /* for ast_tvdiff_ms, ast_tvnow */
172 #include "asterisk/translate.h" /* for ast_translate_available_formats */
173 #include "asterisk/utils.h" /* for ast_free, ast_strdup, etc */
174 #include "asterisk/vector.h" /* for AST_VECTOR_GET, etc */
175 
176 struct ast_srtp_res *res_srtp = NULL;
177 struct ast_srtp_policy_res *res_srtp_policy = NULL;
178 
179 /*! Structure that contains extmap negotiation information */
180 struct rtp_extmap {
181  /*! The RTP extension */
183  /*! The current negotiated direction */
185 };
186 
187 /*! Structure that represents an RTP session (instance) */
189  /*! Engine that is handling this RTP instance */
191  /*! Data unique to the RTP engine */
192  void *data;
193  /*! RTP properties that have been set and their value */
195  /*! Address that we are expecting RTP to come in to */
197  /*! The original source address */
199  /*! Address that we are sending RTP to */
201  /*! Instance that we are bridged to if doing remote or local bridging */
203  /*! Payload and packetization information */
205  /*! RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
206  int timeout;
207  /*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
209  /*! RTP keepalive interval */
211  /*! Glue currently in use */
213  /*! SRTP info associated with the instance */
214  struct ast_srtp *srtp;
215  /*! SRTP info dedicated for RTCP associated with the instance */
217  /*! Channel unique ID */
219  /*! Time of last packet sent */
220  time_t last_tx;
221  /*! Time of last packet received */
222  time_t last_rx;
223  /*! Enabled RTP extensions */
225  /*! Negotiated RTP extensions (using index based on extension) */
227  /*! Negotiated RTP extensions (using index based on unique id) */
229 };
230 
231 /*!
232  * \brief URIs for known RTP extensions
233  */
234 static const char * const rtp_extension_uris[AST_RTP_EXTENSION_MAX] = {
236  [AST_RTP_EXTENSION_ABS_SEND_TIME] = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",
237  [AST_RTP_EXTENSION_TRANSPORT_WIDE_CC] = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01",
238 };
239 
240 /*! List of RTP engines that are currently registered */
242 
243 /*! List of RTP glues */
245 
246 #define MAX_RTP_MIME_TYPES 128
247 
248 /*! The following array defines the MIME Media type (and subtype) for each
249  of our codecs, or RTP-specific data type. */
250 static struct ast_rtp_mime_type {
251  /*! \brief A mapping object between the Asterisk codec and this RTP payload */
252  struct ast_rtp_payload_type payload_type;
253  /*! \brief The media type */
254  char type[16];
255  /*! \brief The format type */
256  char subtype[64];
257  /*! \brief Expected sample rate of the /c subtype */
258  unsigned int sample_rate;
259 } ast_rtp_mime_types[128]; /* This will Likely not need to grow any time soon. */
260 static ast_rwlock_t mime_types_lock;
261 static int mime_types_len = 0;
262 
263 /*!
264  * \brief Mapping between Asterisk codecs and rtp payload types
265  *
266  * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
267  * also, our own choices for dynamic payload types. This is our master
268  * table for transmission
269  *
270  * See http://www.iana.org/assignments/rtp-parameters for a list of
271  * assigned values
272  */
274 static ast_rwlock_t static_RTP_PT_lock;
275 
276 /*! \brief \ref stasis topic for RTP related messages */
277 static struct stasis_topic *rtp_topic;
278 
279 
280 /*!
281  * \brief Set given json object into target with name
282  *
283  * \param target Target json.
284  * \param name key of given object.
285  * \param obj Json value will be set.
286  */
287 #define SET_AST_JSON_OBJ(target, name, obj) ({ \
288  struct ast_json *j_tmp = obj; \
289  if (j_tmp) { \
290  ast_json_object_set(target, name, j_tmp); \
291  } \
292 })
293 
294 /*!
295  * \internal
296  * \brief Destructor for \c ast_rtp_payload_type
297  */
298 static void rtp_payload_type_dtor(void *obj)
299 {
300  struct ast_rtp_payload_type *payload = obj;
301 
302  ao2_cleanup(payload->format);
303 }
304 
305 static struct ast_rtp_payload_type *rtp_payload_type_alloc(struct ast_format *format,
306  int payload, int rtp_code, int primary_mapping, unsigned int sample_rate)
307 {
308  struct ast_rtp_payload_type *type = ao2_alloc_options(
309  sizeof(*type), rtp_payload_type_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
310 
311  if (!type) {
312  return NULL;
313  }
314 
315  type->format = ao2_bump(format);
316  type->asterisk_format = type->format != NULL;
317  type->payload = payload;
318  type->rtp_code = rtp_code;
320  type->sample_rate = sample_rate;
321 
322  return type;
323 }
324 
326 {
327  return rtp_payload_type_alloc(NULL, 0, 0, 0, 0);
328 }
329 
330 int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
331 {
332  struct ast_rtp_engine *current_engine;
333 
334  /* Perform a sanity check on the engine structure to make sure it has the basics */
335  if (ast_strlen_zero(engine->name) || !engine->new || !engine->destroy || !engine->write || !engine->read) {
336  ast_log(LOG_WARNING, "RTP Engine '%s' failed sanity check so it was not registered.\n", !ast_strlen_zero(engine->name) ? engine->name : "Unknown");
337  return -1;
338  }
339 
340  /* Link owner module to the RTP engine for reference counting purposes */
341  engine->mod = module;
342 
344 
345  /* Ensure that no two modules with the same name are registered at the same time */
346  AST_RWLIST_TRAVERSE(&engines, current_engine, entry) {
347  if (!strcmp(current_engine->name, engine->name)) {
348  ast_log(LOG_WARNING, "An RTP engine with the name '%s' has already been registered.\n", engine->name);
350  return -1;
351  }
352  }
353 
354  /* The engine survived our critique. Off to the list it goes to be used */
355  AST_RWLIST_INSERT_TAIL(&engines, engine, entry);
356 
358 
359  ast_verb(5, "Registered RTP engine '%s'\n", engine->name);
360 
361  return 0;
362 }
363 
365 {
366  struct ast_rtp_engine *current_engine = NULL;
367 
369 
370  if ((current_engine = AST_RWLIST_REMOVE(&engines, engine, entry))) {
371  ast_verb(5, "Unregistered RTP engine '%s'\n", engine->name);
372  }
373 
375 
376  return current_engine ? 0 : -1;
377 }
378 
379 int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module)
380 {
381  struct ast_rtp_glue *current_glue = NULL;
382 
383  if (ast_strlen_zero(glue->type)) {
384  return -1;
385  }
386 
387  glue->mod = module;
388 
390 
391  AST_RWLIST_TRAVERSE(&glues, current_glue, entry) {
392  if (!strcasecmp(current_glue->type, glue->type)) {
393  ast_log(LOG_WARNING, "RTP glue with the name '%s' has already been registered.\n", glue->type);
395  return -1;
396  }
397  }
398 
399  AST_RWLIST_INSERT_TAIL(&glues, glue, entry);
400 
402 
403  ast_verb(5, "Registered RTP glue '%s'\n", glue->type);
404 
405  return 0;
406 }
407 
409 {
410  struct ast_rtp_glue *current_glue = NULL;
411 
413 
414  if ((current_glue = AST_RWLIST_REMOVE(&glues, glue, entry))) {
415  ast_verb(5, "Unregistered RTP glue '%s'\n", glue->type);
416  }
417 
419 
420  return current_glue ? 0 : -1;
421 }
422 
423 static void instance_destructor(void *obj)
424 {
425  struct ast_rtp_instance *instance = obj;
426 
427  /* Pass us off to the engine to destroy */
428  if (instance->data) {
429  /*
430  * Lock in case the RTP engine has other threads that
431  * need synchronization with the destruction.
432  */
433  ao2_lock(instance);
434  instance->engine->destroy(instance);
435  ao2_unlock(instance);
436  }
437 
438  if (instance->srtp) {
439  res_srtp->destroy(instance->srtp);
440  }
441 
442  if (instance->rtcp_srtp) {
443  res_srtp->destroy(instance->rtcp_srtp);
444  }
445 
447 
448  AST_VECTOR_FREE(&instance->extmap_enabled);
451 
452  /* Drop our engine reference */
453  ast_module_unref(instance->engine->mod);
454 
455  ast_debug(1, "Destroyed RTP instance '%p'\n", instance);
456 }
457 
459 {
460  if (!instance) {
461  return 0;
462  }
463  if (ast_debug_rtp_is_allowed) {
464  char buffer[4][512];
465  ast_debug_rtp(1, "%s:\n"
466  " RTT: %s\n"
467  " Loss: %s\n"
468  " Jitter: %s\n"
469  " MES: %s\n",
470  instance->channel_uniqueid,
472  buffer[0], sizeof(buffer[0])),
474  buffer[1], sizeof(buffer[1])),
476  buffer[2], sizeof(buffer[2])),
478  buffer[3], sizeof(buffer[3]))
479  );
480  }
481 
482  ao2_cleanup(instance);
483 
484  return 0;
485 }
486 
487 struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
488  struct ast_sched_context *sched, const struct ast_sockaddr *sa,
489  void *data)
490 {
491  struct ast_sockaddr address = {{0,}};
492  struct ast_rtp_instance *instance = NULL;
493  struct ast_rtp_engine *engine = NULL;
494  struct ast_module *mod_ref;
495 
497 
498  /* If an engine name was specified try to use it or otherwise use the first one registered */
499  if (!ast_strlen_zero(engine_name)) {
500  AST_RWLIST_TRAVERSE(&engines, engine, entry) {
501  if (!strcmp(engine->name, engine_name)) {
502  break;
503  }
504  }
505  } else {
506  engine = AST_RWLIST_FIRST(&engines);
507  }
508 
509  /* If no engine was actually found bail out now */
510  if (!engine) {
511  ast_log(LOG_ERROR, "No RTP engine was found. Do you have one loaded?\n");
513  return NULL;
514  }
515 
516  /* Bump up the reference count before we return so the module can not be unloaded */
517  mod_ref = ast_module_running_ref(engine->mod);
518 
520 
521  if (!mod_ref) {
522  /* BUGBUG: improve handling of this situation. */
523  return NULL;
524  }
525 
526  /* Allocate a new RTP instance */
527  if (!(instance = ao2_alloc(sizeof(*instance), instance_destructor))) {
528  ast_module_unref(engine->mod);
529  return NULL;
530  }
531  instance->engine = engine;
532  ast_sockaddr_copy(&instance->local_address, sa);
533  ast_sockaddr_copy(&address, sa);
534 
535  if (ast_rtp_codecs_payloads_initialize(&instance->codecs)) {
536  ao2_ref(instance, -1);
537  return NULL;
538  }
539 
540  /* Initialize RTP extension support */
541  if (AST_VECTOR_INIT(&instance->extmap_enabled, 0) ||
542  AST_VECTOR_INIT(&instance->extmap_negotiated, 0) ||
543  AST_VECTOR_INIT(&instance->extmap_unique_ids, 0)) {
544  ao2_ref(instance, -1);
545  return NULL;
546  }
547 
548  ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
549 
550  /*
551  * And pass it off to the engine to setup
552  *
553  * Lock in case the RTP engine has other threads that
554  * need synchronization with the construction.
555  */
556  ao2_lock(instance);
557  if (instance->engine->new(instance, sched, &address, data)) {
558  ast_debug(1, "Engine '%s' failed to setup RTP instance '%p'\n", engine->name, instance);
559  ao2_unlock(instance);
560  ao2_ref(instance, -1);
561  return NULL;
562  }
563  ao2_unlock(instance);
564 
565  ast_debug(1, "RTP instance '%p' is setup and ready to go\n", instance);
566 
567  return instance;
568 }
569 
571 {
572  return instance->channel_uniqueid;
573 }
574 
575 void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
576 {
577  ast_copy_string(instance->channel_uniqueid, uniqueid, sizeof(instance->channel_uniqueid));
578 }
579 
580 void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
581 {
582  instance->data = data;
583 }
584 
586 {
587  return instance->data;
588 }
589 
590 int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
591 {
592  int res;
593 
594  ao2_lock(instance);
595  res = instance->engine->write(instance, frame);
596  ao2_unlock(instance);
597  return res;
598 }
599 
600 struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
601 {
602  struct ast_frame *frame;
603 
604  ao2_lock(instance);
605  frame = instance->engine->read(instance, rtcp);
606  ao2_unlock(instance);
607  return frame;
608 }
609 
611  const struct ast_sockaddr *address)
612 {
613  ao2_lock(instance);
614  ast_sockaddr_copy(&instance->local_address, address);
615  ao2_unlock(instance);
616  return 0;
617 }
618 
619 static void rtp_instance_set_incoming_source_address_nolock(struct ast_rtp_instance *instance,
620  const struct ast_sockaddr *address)
621 {
622  ast_sockaddr_copy(&instance->incoming_source_address, address);
623  if (instance->engine->remote_address_set) {
624  instance->engine->remote_address_set(instance, &instance->incoming_source_address);
625  }
626 }
627 
629  const struct ast_sockaddr *address)
630 {
631  ao2_lock(instance);
632  rtp_instance_set_incoming_source_address_nolock(instance, address);
633  ao2_unlock(instance);
634 
635  return 0;
636 }
637 
639  const struct ast_sockaddr *address)
640 {
641  ao2_lock(instance);
642 
643  ast_sockaddr_copy(&instance->requested_target_address, address);
644  rtp_instance_set_incoming_source_address_nolock(instance, address);
645 
646  ao2_unlock(instance);
647 
648  return 0;
649 }
650 
652  struct ast_sockaddr *address)
653 {
654  ao2_lock(instance);
655  if (ast_sockaddr_cmp(address, &instance->local_address) != 0) {
656  ast_sockaddr_copy(address, &instance->local_address);
657  ao2_unlock(instance);
658  return 1;
659  }
660  ao2_unlock(instance);
661 
662  return 0;
663 }
664 
666  struct ast_sockaddr *address)
667 {
668  ao2_lock(instance);
669  ast_sockaddr_copy(address, &instance->local_address);
670  ao2_unlock(instance);
671 }
672 
674  struct ast_sockaddr *address)
675 {
676  ao2_lock(instance);
677  if (ast_sockaddr_cmp(address, &instance->requested_target_address) != 0) {
678  ast_sockaddr_copy(address, &instance->requested_target_address);
679  ao2_unlock(instance);
680  return 1;
681  }
682  ao2_unlock(instance);
683 
684  return 0;
685 }
686 
688  struct ast_sockaddr *address)
689 {
690  ao2_lock(instance);
691  ast_sockaddr_copy(address, &instance->incoming_source_address);
692  ao2_unlock(instance);
693 }
694 
696  struct ast_sockaddr *address)
697 {
698  ao2_lock(instance);
699  ast_sockaddr_copy(address, &instance->requested_target_address);
700  ao2_unlock(instance);
701 }
702 
703 void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value)
704 {
705  if (instance->engine->extended_prop_set) {
706  ao2_lock(instance);
707  instance->engine->extended_prop_set(instance, property, value);
708  ao2_unlock(instance);
709  }
710 }
711 
712 void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property)
713 {
714  void *prop;
715 
716  if (instance->engine->extended_prop_get) {
717  ao2_lock(instance);
718  prop = instance->engine->extended_prop_get(instance, property);
719  ao2_unlock(instance);
720  } else {
721  prop = NULL;
722  }
723 
724  return prop;
725 }
726 
727 void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
728 {
729  ao2_lock(instance);
730  instance->properties[property] = value;
731 
732  if (instance->engine->prop_set) {
733  instance->engine->prop_set(instance, property, value);
734  }
735  ao2_unlock(instance);
736 }
737 
738 int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
739 {
740  int prop;
741 
742  ao2_lock(instance);
743  prop = instance->properties[property];
744  ao2_unlock(instance);
745 
746  return prop;
747 }
748 
750 {
751  return &instance->codecs;
752 }
753 
755  enum ast_rtp_extension_direction direction)
756 {
757  struct rtp_extmap extmap = {
758  .extension = extension,
759  .direction = direction,
760  };
761 
762  ao2_lock(instance);
763 
764  if (!instance->engine->extension_enable || !instance->engine->extension_enable(instance, extension)) {
765  ao2_unlock(instance);
766  return 0;
767  }
768 
769  /* We store enabled extensions separately so we can easily do negotiation */
770  if (AST_VECTOR_REPLACE(&instance->extmap_enabled, extension, direction)) {
771  ao2_unlock(instance);
772  return -1;
773  }
774 
775  if (id <= 0) {
776  /* We find a free unique identifier for this extension by just appending it to the
777  * vector of unique ids. The size of the vector will become its unique identifier.
778  * As well when we are asking for information on the extensions it will be returned,
779  * allowing it to be added to the SDP offer.
780  */
781  if (AST_VECTOR_APPEND(&instance->extmap_unique_ids, extmap)) {
783  ao2_unlock(instance);
784  return -1;
785  }
786  id = AST_VECTOR_SIZE(&instance->extmap_unique_ids);
787  } else {
788  /* Otherwise we put it precisely where they want it */
789  if (AST_VECTOR_REPLACE(&instance->extmap_unique_ids, id - 1, extmap)) {
791  ao2_unlock(instance);
792  return -1;
793  }
794  }
795 
796  /* Now that we have an id add the extension to here */
797  if (AST_VECTOR_REPLACE(&instance->extmap_negotiated, extension, id)) {
801  AST_VECTOR_REPLACE(&instance->extmap_unique_ids, id - 1, extmap);
802  ao2_unlock(instance);
803  return -1;
804  }
805 
806  ao2_unlock(instance);
807 
808  return 0;
809 }
810 
811 /*! \brief Helper function which negotiates two RTP extension directions to get our current direction */
813  enum ast_rtp_extension_direction theirs)
814 {
816  /* This should not occur but if it does tolerate either side not having this extension
817  * in use.
818  */
820  } else if (theirs == AST_RTP_EXTENSION_DIRECTION_INACTIVE) {
821  /* Inactive is always inactive on our side */
823  } else if (theirs == AST_RTP_EXTENSION_DIRECTION_SENDRECV) {
824  return ours;
825  } else if (theirs == AST_RTP_EXTENSION_DIRECTION_SENDONLY) {
826  /* If they are send only then we become recvonly if we are configured as sendrecv or recvonly */
829  }
830  } else if (theirs == AST_RTP_EXTENSION_DIRECTION_RECVONLY) {
831  /* If they are recv only then we become sendonly if we are configured as sendrecv or sendonly */
834  }
835  }
836 
838 }
839 
841  const char *uri, const char *attributes)
842 {
843  /* 'attributes' is currently unused but exists in the API to ensure it does not need to be altered
844  * in the future in case we need to use it.
845  */
846  int idx;
848 
849  /* Per the RFC the identifier has to be 1 or above */
850  if (id < 1) {
851  return -1;
852  }
853 
854  /* Convert the provided URI to the internal representation */
855  for (idx = 0; idx < ARRAY_LEN(rtp_extension_uris); ++idx) {
856  if (!strcasecmp(rtp_extension_uris[idx], uri)) {
857  extension = idx;
858  break;
859  }
860  }
861 
862  ao2_lock(instance);
863  /* We only accept the extension if it is enabled */
864  if (extension < AST_VECTOR_SIZE(&instance->extmap_enabled) &&
866  struct rtp_extmap extmap = {
867  .extension = extension,
868  .direction = rtp_extmap_negotiate_direction(AST_VECTOR_GET(&instance->extmap_enabled, extension), direction),
869  };
870 
871  /* If the direction negotiation failed then don't accept or use this extension */
873  if (extension != AST_RTP_EXTENSION_UNSUPPORTED) {
874  AST_VECTOR_REPLACE(&instance->extmap_negotiated, extension, id);
875  }
876  AST_VECTOR_REPLACE(&instance->extmap_unique_ids, id - 1, extmap);
877  }
878  }
879  ao2_unlock(instance);
880 
881  return 0;
882 }
883 
885 {
886  static const struct rtp_extmap extmap_none = {
889  };
890  int idx;
891 
892  ao2_lock(instance);
893 
894  /* Clear both the known unique ids and the negotiated extensions as we are about to have
895  * new results set on us.
896  */
897  for (idx = 0; idx < AST_VECTOR_SIZE(&instance->extmap_unique_ids); ++idx) {
898  AST_VECTOR_REPLACE(&instance->extmap_unique_ids, idx, extmap_none);
899  }
900 
901  for (idx = 0; idx < AST_VECTOR_SIZE(&instance->extmap_negotiated); ++idx) {
902  AST_VECTOR_REPLACE(&instance->extmap_negotiated, idx, -1);
903  }
904 
905  ao2_unlock(instance);
906 }
907 
909 {
910  int id = -1;
911 
912  ao2_lock(instance);
913  if (extension < AST_VECTOR_SIZE(&instance->extmap_negotiated)) {
914  id = AST_VECTOR_GET(&instance->extmap_negotiated, extension);
915  }
916  ao2_unlock(instance);
917 
918  return id;
919 }
920 
922 {
923  size_t count;
924 
925  ao2_lock(instance);
926  count = AST_VECTOR_SIZE(&instance->extmap_unique_ids);
927  ao2_unlock(instance);
928 
929  return count;
930 }
931 
933 {
935 
936  ao2_lock(instance);
937 
938  /* The local unique identifier starts at '1' so the highest unique identifier
939  * can be the actual size of the vector. We compensate (as it is 0 index based)
940  * by dropping it down to 1 to get the correct information.
941  */
942  if (0 < id && id <= AST_VECTOR_SIZE(&instance->extmap_unique_ids)) {
943  struct rtp_extmap *extmap = AST_VECTOR_GET_ADDR(&instance->extmap_unique_ids, id - 1);
944 
945  extension = extmap->extension;
946  }
947  ao2_unlock(instance);
948 
949  return extension;
950 }
951 
953 {
955 
956  ao2_lock(instance);
957 
958  if (0 < id && id <= AST_VECTOR_SIZE(&instance->extmap_unique_ids)) {
959  struct rtp_extmap *extmap = AST_VECTOR_GET_ADDR(&instance->extmap_unique_ids, id - 1);
960 
961  direction = extmap->direction;
962  }
963  ao2_unlock(instance);
964 
965  return direction;
966 }
967 
968 const char *ast_rtp_instance_extmap_get_uri(struct ast_rtp_instance *instance, int id)
969 {
971 
972  if (extension == AST_RTP_EXTENSION_UNSUPPORTED ||
973  (unsigned int)extension >= ARRAY_LEN(rtp_extension_uris)) {
974  return NULL;
975  }
976 
978 }
979 
981 {
982  int res;
983 
984  codecs->framing = 0;
985  ast_rwlock_init(&codecs->codecs_lock);
988  if (res) {
991  }
992 
993  return res;
994 }
995 
997 {
998  int idx;
999  struct ast_rtp_payload_type *type;
1000 
1001  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
1002  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
1003  ao2_t_cleanup(type, "destroying ast_rtp_codec rx mapping");
1004  }
1006 
1007  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_tx); ++idx) {
1008  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, idx);
1009  ao2_t_cleanup(type, "destroying ast_rtp_codec tx mapping");
1010  }
1012 
1013  ao2_t_cleanup(codecs->preferred_format, "destroying ast_rtp_codec preferred format");
1014 
1015  ast_rwlock_destroy(&codecs->codecs_lock);
1016 }
1017 
1019 {
1022 
1023  if (instance && instance->engine && instance->engine->payload_set) {
1024  int i;
1025 
1026  ao2_lock(instance);
1027  for (i = 0; i < AST_RTP_MAX_PT; i++) {
1028  instance->engine->payload_set(instance, i, 0, NULL, 0);
1029  }
1030  ao2_unlock(instance);
1031  }
1032 }
1033 
1034 /*!
1035  * \internal
1036  * \brief Clear the rx primary mapping flag on all other matching mappings.
1037  * \since 14.0.0
1038  *
1039  * \param codecs Codecs that need rx clearing.
1040  * \param to_match Payload type object to compare against.
1041  *
1042  * \note It is assumed that codecs is write locked before calling.
1043  */
1044 static void payload_mapping_rx_clear_primary(struct ast_rtp_codecs *codecs, struct ast_rtp_payload_type *to_match)
1045 {
1046  int idx;
1047  struct ast_rtp_payload_type *current;
1048  struct ast_rtp_payload_type *new_type;
1049  struct timeval now;
1050 
1051  if (!to_match->primary_mapping) {
1052  return;
1053  }
1054 
1055  now = ast_tvnow();
1056  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
1057  current = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
1058 
1059  if (!current || current == to_match || !current->primary_mapping) {
1060  continue;
1061  }
1062  if (current->asterisk_format && to_match->asterisk_format) {
1063  if (ast_format_cmp(current->format, to_match->format) == AST_FORMAT_CMP_NOT_EQUAL) {
1064  continue;
1065  }
1066  } else if (!current->asterisk_format && !to_match->asterisk_format) {
1067  if (current->rtp_code != to_match->rtp_code) {
1068  continue;
1069  }
1070  } else {
1071  continue;
1072  }
1073 
1074  /* Replace current with non-primary marked version */
1075  new_type = ast_rtp_engine_alloc_payload_type();
1076  if (!new_type) {
1077  continue;
1078  }
1079  *new_type = *current;
1080  new_type->primary_mapping = 0;
1081  new_type->when_retired = now;
1082  ao2_bump(new_type->format);
1083  AST_VECTOR_REPLACE(&codecs->payload_mapping_rx, idx, new_type);
1084  ao2_ref(current, -1);
1085  }
1086 }
1087 
1088 /*!
1089  * \internal
1090  * \brief Put the new_type into the rx payload type mapping.
1091  * \since 21.0.0
1092  *
1093  * \param codecs Codecs structure to put new_type into
1094  * \param payload type position to replace.
1095  * \param new_type RTP payload mapping object to store.
1096  * \param replace Clear the primary flag
1097  *
1098  * \note It is assumed that codecs is write locked before calling.
1099  */
1100 static void rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int payload, struct ast_rtp_payload_type *new_type, int replace)
1101 {
1102  ao2_ref(new_type, +1);
1103  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_rx)) {
1104  ao2_t_cleanup(AST_VECTOR_GET(&codecs->payload_mapping_rx, payload),
1105  "cleaning up rx mapping vector element about to be replaced");
1106  }
1107  if (AST_VECTOR_REPLACE(&codecs->payload_mapping_rx, payload, new_type)) {
1108  ao2_ref(new_type, -1);
1109  return;
1110  }
1111 
1112  if (replace) {
1113  payload_mapping_rx_clear_primary(codecs, new_type);
1114  }
1115 }
1116 
1117 /*!
1118  * \internal
1119  * \brief Put the new_type into the rx payload type mapping.
1120  * \since 14.0.0
1121  *
1122  * \param codecs Codecs structure to put new_type into
1123  * \param payload type position to replace.
1124  * \param new_type RTP payload mapping object to store.
1125  *
1126  * \note It is assumed that codecs is write locked before calling.
1127  */
1128 static void rtp_codecs_payload_replace_rx(struct ast_rtp_codecs *codecs, int payload, struct ast_rtp_payload_type *new_type) {
1129  rtp_codecs_payload_set_rx(codecs, payload, new_type, 1);
1130 }
1131 
1132 
1133 /*!
1134  * \internal
1135  * \brief Copy the rx payload type mapping to the destination.
1136  * \since 14.0.0
1137  *
1138  * \param src The source codecs structure
1139  * \param dest The destination codecs structure that the values from src will be copied to
1140  * \param instance Optionally the instance that the dst codecs structure belongs to
1141  *
1142  * \note It is assumed that src is at least read locked before calling.
1143  * \note It is assumed that dest is write locked before calling.
1144  */
1145 static void rtp_codecs_payloads_copy_rx(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
1146 {
1147  int idx;
1148  struct ast_rtp_payload_type *type;
1149 
1150  for (idx = 0; idx < AST_VECTOR_SIZE(&src->payload_mapping_rx); ++idx) {
1151  type = AST_VECTOR_GET(&src->payload_mapping_rx, idx);
1152  if (!type) {
1153  continue;
1154  }
1155 
1156  ast_debug(2, "Copying rx payload mapping %d (%p) from %p to %p\n",
1157  idx, type, src, dest);
1158  rtp_codecs_payload_replace_rx(dest, idx, type);
1159 
1160  if (instance && instance->engine && instance->engine->payload_set) {
1161  ao2_lock(instance);
1162  instance->engine->payload_set(instance, idx, type->asterisk_format, type->format, type->rtp_code);
1163  ao2_unlock(instance);
1164  }
1165  }
1166 }
1167 
1168 /*!
1169  * \internal
1170  * \brief Determine if a type of payload is already present in mappings.
1171  * \since 14.0.0
1172  *
1173  * \param codecs Codecs to be checked for mappings.
1174  * \param to_match Payload type object to compare against.
1175  *
1176  * \note It is assumed that codecs is write locked before calling.
1177  *
1178  * \retval 0 not found
1179  * \retval 1 found
1180  */
1181 static int payload_mapping_tx_is_present(const struct ast_rtp_codecs *codecs, const struct ast_rtp_payload_type *to_match)
1182 {
1183  int idx;
1184  struct ast_rtp_payload_type *current;
1185 
1186  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_tx); ++idx) {
1187  current = AST_VECTOR_GET(&codecs->payload_mapping_tx, idx);
1188 
1189  if (!current) {
1190  continue;
1191  }
1192  if (current == to_match) {
1193  /* The exact object is already in the mapping. */
1194  return 1;
1195  }
1196  if (current->asterisk_format && to_match->asterisk_format) {
1197  if (ast_format_get_codec_id(current->format) != ast_format_get_codec_id(to_match->format)) {
1198  continue;
1199  } else if (current->payload == to_match->payload) {
1200  return 0;
1201  }
1202  } else if (!current->asterisk_format && !to_match->asterisk_format) {
1203  if (current->rtp_code != to_match->rtp_code) {
1204  continue;
1205  } else if (to_match->rtp_code == AST_RTP_DTMF && current->sample_rate != to_match->sample_rate) {
1206  /* it is possible for multiple DTMF types to exist with different sample rates */
1207  continue;
1208  }
1209  } else {
1210  continue;
1211  }
1212 
1213  return 1;
1214  }
1215 
1216  return 0;
1217 }
1218 
1219 /*!
1220  * \internal
1221  * \brief Copy the tx payload type mapping to the destination.
1222  * \since 14.0.0
1223  *
1224  * \param src The source codecs structure
1225  * \param dest The destination codecs structure that the values from src will be copied to
1226  * \param instance Optionally the instance that the dst codecs structure belongs to
1227  *
1228  * \note It is assumed that src is at least read locked before calling.
1229  * \note It is assumed that dest is write locked before calling.
1230  */
1231 static void rtp_codecs_payloads_copy_tx(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
1232 {
1233  int idx;
1234  struct ast_rtp_payload_type *type;
1235 
1236  for (idx = 0; idx < AST_VECTOR_SIZE(&src->payload_mapping_tx); ++idx) {
1237  type = AST_VECTOR_GET(&src->payload_mapping_tx, idx);
1238  if (!type) {
1239  continue;
1240  }
1241 
1242  ast_debug(2, "Copying tx payload mapping %d (%p) from %p to %p\n",
1243  idx, type, src, dest);
1244  ao2_ref(type, +1);
1245  if (idx < AST_VECTOR_SIZE(&dest->payload_mapping_tx)) {
1246  ao2_t_cleanup(AST_VECTOR_GET(&dest->payload_mapping_tx, idx),
1247  "cleaning up tx mapping vector element about to be replaced");
1248  }
1249  if (AST_VECTOR_REPLACE(&dest->payload_mapping_tx, idx, type)) {
1250  ao2_ref(type, -1);
1251  continue;
1252  }
1253 
1254  if (instance && instance->engine && instance->engine->payload_set) {
1255  ao2_lock(instance);
1256  instance->engine->payload_set(instance, idx, type->asterisk_format, type->format, type->rtp_code);
1257  ao2_unlock(instance);
1258  }
1259  }
1260 }
1261 
1262 void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
1263 {
1264  int idx;
1265  struct ast_rtp_payload_type *type;
1266 
1267  ast_rwlock_wrlock(&dest->codecs_lock);
1268 
1269  /* Deadlock avoidance because of held write lock. */
1270  while (ast_rwlock_tryrdlock(&src->codecs_lock)) {
1271  ast_rwlock_unlock(&dest->codecs_lock);
1272  sched_yield();
1273  ast_rwlock_wrlock(&dest->codecs_lock);
1274  }
1275 
1276  /*
1277  * This represents a completely new mapping of what the remote party is
1278  * expecting for payloads, so we clear out the entire tx payload mapping
1279  * vector and replace it.
1280  */
1281  for (idx = 0; idx < AST_VECTOR_SIZE(&dest->payload_mapping_tx); ++idx) {
1282  type = AST_VECTOR_GET(&dest->payload_mapping_tx, idx);
1283  ao2_t_cleanup(type, "destroying ast_rtp_codec tx mapping");
1284  AST_VECTOR_REPLACE(&dest->payload_mapping_tx, idx, NULL);
1285  }
1286 
1287  rtp_codecs_payloads_copy_rx(src, dest, instance);
1288  rtp_codecs_payloads_copy_tx(src, dest, instance);
1289  dest->framing = src->framing;
1291 
1292  ast_rwlock_unlock(&src->codecs_lock);
1293  ast_rwlock_unlock(&dest->codecs_lock);
1294 }
1295 
1296 void ast_rtp_codecs_payloads_xover(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
1297 {
1298  int idx;
1299  struct ast_rtp_payload_type *type;
1300 
1301  ast_rwlock_wrlock(&dest->codecs_lock);
1302  if (src != dest) {
1303  /* Deadlock avoidance because of held write lock. */
1304  while (ast_rwlock_tryrdlock(&src->codecs_lock)) {
1305  ast_rwlock_unlock(&dest->codecs_lock);
1306  sched_yield();
1307  ast_rwlock_wrlock(&dest->codecs_lock);
1308  }
1309  }
1310 
1311  /* Crossover copy payload type tx mapping to rx mapping. */
1312  for (idx = 0; idx < AST_VECTOR_SIZE(&src->payload_mapping_tx); ++idx) {
1313  type = AST_VECTOR_GET(&src->payload_mapping_tx, idx);
1314  if (!type) {
1315  continue;
1316  }
1317 
1318  /* All tx mapping elements should have the primary flag set. */
1319  ast_assert(type->primary_mapping);
1320 
1321  ast_debug(2, "Crossover copying tx to rx payload mapping %d (%p) from %p to %p\n",
1322  idx, type, src, dest);
1323  rtp_codecs_payload_replace_rx(dest, idx, type);
1324 
1325  if (instance && instance->engine && instance->engine->payload_set) {
1326  ao2_lock(instance);
1327  instance->engine->payload_set(instance, idx, type->asterisk_format, type->format, type->rtp_code);
1328  ao2_unlock(instance);
1329  }
1330  }
1331 
1332  dest->framing = src->framing;
1334 
1335  if (src != dest) {
1336  ast_rwlock_unlock(&src->codecs_lock);
1337  }
1338  ast_rwlock_unlock(&dest->codecs_lock);
1339 }
1340 
1341 void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
1342 {
1343  struct ast_rtp_payload_type *new_type;
1344 
1345  if (payload < 0 || payload >= AST_RTP_MAX_PT || payload > AST_RTP_PT_LAST_STATIC) {
1346  return;
1347  }
1348 
1349  ast_rwlock_rdlock(&static_RTP_PT_lock);
1350  new_type = ao2_bump(static_RTP_PT[payload]);
1351  ast_rwlock_unlock(&static_RTP_PT_lock);
1352  if (!new_type) {
1353  ast_debug(1, "Don't have a default tx payload type %d format for m type on %p\n",
1354  payload, codecs);
1355  return;
1356  }
1357 
1358  ast_debug(1, "Setting tx payload type %d based on m type on %p\n",
1359  payload, codecs);
1360 
1361  ast_rwlock_wrlock(&codecs->codecs_lock);
1362 
1363  if (!payload_mapping_tx_is_present(codecs, new_type)) {
1364  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)) {
1365  ao2_t_cleanup(AST_VECTOR_GET(&codecs->payload_mapping_tx, payload),
1366  "cleaning up replaced tx payload type");
1367  }
1368 
1369  if (AST_VECTOR_REPLACE(&codecs->payload_mapping_tx, payload, new_type)) {
1370  ao2_ref(new_type, -1);
1371  } else if (instance && instance->engine && instance->engine->payload_set) {
1372  ao2_lock(instance);
1373  instance->engine->payload_set(instance, payload, new_type->asterisk_format, new_type->format, new_type->rtp_code);
1374  ao2_unlock(instance);
1375  }
1376  } else {
1377  ao2_ref(new_type, -1);
1378  }
1379 
1380  ast_rwlock_unlock(&codecs->codecs_lock);
1381 }
1382 
1384  char *mimetype, char *mimesubtype,
1385  enum ast_rtp_options options,
1386  unsigned int sample_rate)
1387 {
1388  unsigned int idx;
1389  int found = 0;
1390 
1391  if (pt < 0 || pt >= AST_RTP_MAX_PT) {
1392  return -1; /* bogus payload type */
1393  }
1394 
1395  ast_rwlock_rdlock(&mime_types_lock);
1396  ast_rwlock_wrlock(&codecs->codecs_lock);
1397 
1398  for (idx = 0; idx < mime_types_len; ++idx) {
1399  const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[idx];
1400  struct ast_rtp_payload_type *new_type;
1401 
1402  if (strcasecmp(mimesubtype, t->subtype)) {
1403  continue;
1404  }
1405 
1406  if (strcasecmp(mimetype, t->type)) {
1407  continue;
1408  }
1409 
1410  /* if both sample rates have been supplied, and they don't match,
1411  * then this not a match; if one has not been supplied, then the
1412  * rates are not compared */
1413  if (sample_rate && t->sample_rate &&
1414  (sample_rate != t->sample_rate)) {
1415  continue;
1416  }
1417 
1418  found = 1;
1419 
1420  new_type = ast_rtp_engine_alloc_payload_type();
1421  if (!new_type) {
1422  continue;
1423  }
1424 
1426  new_type->rtp_code = t->payload_type.rtp_code;
1427  new_type->payload = pt;
1428  new_type->primary_mapping = 1;
1429  new_type->sample_rate = sample_rate;
1432  && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
1433  new_type->format = ast_format_g726_aal2;
1434  } else {
1435  new_type->format = t->payload_type.format;
1436  }
1437 
1438  if (new_type->format) {
1439  /* SDP parsing automatically increases the reference count */
1440  new_type->format = ast_format_parse_sdp_fmtp(new_type->format, "");
1441  }
1442 
1443  if (!payload_mapping_tx_is_present(codecs, new_type)) {
1444  if (pt < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)) {
1445  ao2_t_cleanup(AST_VECTOR_GET(&codecs->payload_mapping_tx, pt),
1446  "cleaning up replaced tx payload type");
1447  }
1448 
1449  if (AST_VECTOR_REPLACE(&codecs->payload_mapping_tx, pt, new_type)) {
1450  ao2_ref(new_type, -1);
1451  } else if (instance && instance->engine && instance->engine->payload_set) {
1452  ao2_lock(instance);
1453  instance->engine->payload_set(instance, pt, new_type->asterisk_format, new_type->format, new_type->rtp_code);
1454  ao2_unlock(instance);
1455  }
1456  } else {
1457  ao2_ref(new_type, -1);
1458  }
1459 
1460  break;
1461  }
1462 
1463  ast_rwlock_unlock(&codecs->codecs_lock);
1464  ast_rwlock_unlock(&mime_types_lock);
1465 
1466  return (found ? 0 : -2);
1467 }
1468 
1469 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)
1470 {
1471  return ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, instance, payload, mimetype, mimesubtype, options, 0);
1472 }
1473 
1474 void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
1475 {
1476  struct ast_rtp_payload_type *type;
1477 
1478  if (payload < 0 || payload >= AST_RTP_MAX_PT) {
1479  return;
1480  }
1481 
1482  ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
1483 
1484  ast_rwlock_wrlock(&codecs->codecs_lock);
1485 
1486  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)) {
1487  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, payload);
1488  /*
1489  * Remove the preferred format if we are unsetting its container.
1490  *
1491  * There can be empty slots in payload_mapping_tx corresponding to
1492  * dynamic payload types that haven't been seen before so we need
1493  * to check for NULL before attempting to use 'type' in the call to
1494  * ast_format_cmp.
1495  */
1496  if (type) {
1498  ao2_replace(codecs->preferred_format, NULL);
1499  }
1500  ao2_ref(type, -1);
1501  AST_VECTOR_REPLACE(&codecs->payload_mapping_tx, payload, NULL);
1502  }
1503  }
1504 
1505  if (instance && instance->engine && instance->engine->payload_set) {
1506  ao2_lock(instance);
1507  instance->engine->payload_set(instance, payload, 0, NULL, 0);
1508  ao2_unlock(instance);
1509  }
1510 
1511  ast_rwlock_unlock(&codecs->codecs_lock);
1512 }
1513 
1515 {
1516  enum ast_media_type stream_type = AST_MEDIA_TYPE_UNKNOWN;
1517  int payload;
1518  struct ast_rtp_payload_type *type;
1519 
1520  ast_rwlock_rdlock(&codecs->codecs_lock);
1521  for (payload = 0; payload < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++payload) {
1522  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, payload);
1523  if (type && type->asterisk_format) {
1524  stream_type = ast_format_get_type(type->format);
1525  break;
1526  }
1527  }
1528  ast_rwlock_unlock(&codecs->codecs_lock);
1529 
1530  return stream_type;
1531 }
1532 
1534 {
1535  struct ast_rtp_payload_type *type = NULL;
1536 
1537  if (payload < 0 || payload >= AST_RTP_MAX_PT) {
1538  return NULL;
1539  }
1540 
1541  ast_rwlock_rdlock(&codecs->codecs_lock);
1542  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_rx)) {
1543  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, payload);
1544  ao2_bump(type);
1545  }
1546  ast_rwlock_unlock(&codecs->codecs_lock);
1547 
1548  if (!type && payload <= AST_RTP_PT_LAST_STATIC) {
1549  ast_rwlock_rdlock(&static_RTP_PT_lock);
1550  type = ao2_bump(static_RTP_PT[payload]);
1551  ast_rwlock_unlock(&static_RTP_PT_lock);
1552  }
1553 
1554  return type;
1555 }
1556 
1558 {
1559  struct ast_format *format;
1560  ast_rwlock_rdlock(&codecs->codecs_lock);
1561  format = ao2_bump(codecs->preferred_format);
1562  ast_rwlock_unlock(&codecs->codecs_lock);
1563  return format;
1564 }
1565 
1567 {
1568  ast_rwlock_wrlock(&codecs->codecs_lock);
1569  ao2_replace(codecs->preferred_format, format);
1570  ast_rwlock_unlock(&codecs->codecs_lock);
1571  return 0;
1572 }
1573 
1574 int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
1575 {
1576  struct ast_rtp_payload_type *type;
1577 
1578  if (payload < 0 || payload >= AST_RTP_MAX_PT || !format) {
1579  return -1;
1580  }
1581 
1583  if (!type) {
1584  return -1;
1585  }
1586  ao2_ref(format, +1);
1587  type->format = format;
1588  type->asterisk_format = 1;
1589  type->payload = payload;
1590  type->primary_mapping = 1;
1591 
1592  ast_rwlock_wrlock(&codecs->codecs_lock);
1593  if (!payload_mapping_tx_is_present(codecs, type)) {
1594  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)) {
1595  ao2_cleanup(AST_VECTOR_GET(&codecs->payload_mapping_tx, payload));
1596  }
1597  if (AST_VECTOR_REPLACE(&codecs->payload_mapping_tx, payload, type)) {
1598  ao2_ref(type, -1);
1599  }
1600  } else {
1601  ao2_ref(type, -1);
1602  }
1603  ast_rwlock_unlock(&codecs->codecs_lock);
1604 
1605  return 0;
1606 }
1607 
1609 {
1610  struct ast_rtp_payload_type *type;
1611  struct ast_format *format = NULL;
1612 
1613  if (payload < 0 || payload >= AST_RTP_MAX_PT) {
1614  return NULL;
1615  }
1616 
1617  ast_rwlock_rdlock(&codecs->codecs_lock);
1618  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)) {
1619  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, payload);
1620  if (type && type->asterisk_format) {
1621  format = ao2_bump(type->format);
1622  }
1623  }
1624  ast_rwlock_unlock(&codecs->codecs_lock);
1625 
1626  return format;
1627 }
1628 
1629 void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
1630 {
1631  if (!framing) {
1632  return;
1633  }
1634 
1635  ast_rwlock_wrlock(&codecs->codecs_lock);
1636  codecs->framing = framing;
1637  ast_rwlock_unlock(&codecs->codecs_lock);
1638 }
1639 
1640 unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
1641 {
1642  unsigned int framing;
1643 
1644  ast_rwlock_rdlock(&codecs->codecs_lock);
1645  framing = codecs->framing;
1646  ast_rwlock_unlock(&codecs->codecs_lock);
1647 
1648  return framing;
1649 }
1650 
1651 void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
1652 {
1653  int idx;
1654 
1655  ast_format_cap_remove_by_type(astformats, AST_MEDIA_TYPE_UNKNOWN);
1656  *nonastformats = 0;
1657 
1658  ast_rwlock_rdlock(&codecs->codecs_lock);
1659 
1660  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_tx); ++idx) {
1661  struct ast_rtp_payload_type *type;
1662 
1663  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, idx);
1664  if (!type) {
1665  continue;
1666  }
1667 
1668  if (type->asterisk_format) {
1669  ast_format_cap_append(astformats, type->format, 0);
1670  } else {
1671  *nonastformats |= type->rtp_code;
1672  }
1673  }
1674  if (codecs->framing) {
1675  ast_format_cap_set_framing(astformats, codecs->framing);
1676  }
1677 
1678  ast_rwlock_unlock(&codecs->codecs_lock);
1679 }
1680 
1681 /*!
1682  * \internal
1683  * \brief Find the static payload type mapping for the format.
1684  * \since 14.0.0
1685  *
1686  * \param asterisk_format Non-zero if the given Asterisk format is present
1687  * \param format Asterisk format to look for
1688  * \param code The non-Asterisk format code to look for
1689  *
1690  * \note It is assumed that static_RTP_PT_lock is at least read locked before calling.
1691  *
1692  * \return Numerical payload type
1693  * \retval -1 if not found.
1694  */
1695 static int find_static_payload_type(int asterisk_format, const struct ast_format *format, int code)
1696 {
1697  int idx;
1698  int payload = -1;
1699 
1700  if (!asterisk_format) {
1701  for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
1702  if (static_RTP_PT[idx]
1703  && !static_RTP_PT[idx]->asterisk_format
1704  && static_RTP_PT[idx]->rtp_code == code) {
1705  payload = idx;
1706  break;
1707  }
1708  }
1709  } else if (format) {
1710  for (idx = 0; idx < AST_RTP_MAX_PT; ++idx) {
1711  if (static_RTP_PT[idx]
1712  && static_RTP_PT[idx]->asterisk_format
1713  && ast_format_cmp(format, static_RTP_PT[idx]->format)
1715  payload = idx;
1716  break;
1717  }
1718  }
1719  }
1720 
1721  return payload;
1722 }
1723 
1724 /*!
1725  * \internal
1726  * \brief Find the first unused payload type in a given range
1727  *
1728  * \param codecs The codec structure to look in
1729  * \param start Starting index
1730  * \param end Ending index
1731  * \param ignore Skip these payloads types
1732  *
1733  * \note The static_RTP_PT_lock object must be locked before calling
1734  *
1735  * \return Numerical payload type
1736  * \retval -1 if not found.
1737  */
1738 static int find_unused_payload_in_range(const struct ast_rtp_codecs *codecs,
1739  int start, int end, struct ast_rtp_payload_type *ignore[])
1740 {
1741  int x;
1742 
1743  for (x = start; x < end; ++x) {
1744  struct ast_rtp_payload_type *type;
1745 
1746  if (ignore[x]) {
1747  continue;
1748  } else if (!codecs || x >= AST_VECTOR_SIZE(&codecs->payload_mapping_rx)) {
1749  return x;
1750  }
1751 
1752  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, x);
1753  if (!type) {
1754  return x;
1755  }
1756  }
1757  return -1;
1758 }
1759 
1760 /*!
1761  * \internal
1762  * \brief Find an unused payload type
1763  *
1764  * \param codecs Codecs structure to look in
1765  *
1766  * \note Both static_RTP_PT_lock and codecs (if given) must be at least
1767  * read locked before calling.
1768  *
1769  * \return Numerical payload type
1770  * \retval -1 if not found.
1771  */
1772 static int find_unused_payload(const struct ast_rtp_codecs *codecs)
1773 {
1774  int res;
1775 
1776  /* find next available dynamic payload slot */
1777  res = find_unused_payload_in_range(
1778  codecs, AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT, static_RTP_PT);
1779  if (res != -1) {
1780  return res;
1781  }
1782 
1783  if (ast_option_rtpusedynamic) {
1784  /*
1785  * We're using default values for some dynamic types. So if an unused
1786  * slot was not found try again, but this time ignore the default
1787  * values declared for dynamic types (except for 101 and 121) .
1788  */
1789  static struct ast_rtp_payload_type *ignore[AST_RTP_MAX_PT] = {0};
1790 
1791  ignore[101] = static_RTP_PT[101];
1792  ignore[121] = static_RTP_PT[121];
1793 
1794  res = find_unused_payload_in_range(
1795  codecs, AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT, ignore);
1796  if (res != -1) {
1797  return res;
1798  }
1799  }
1800 
1801  /* http://www.iana.org/assignments/rtp-parameters
1802  * RFC 3551, Section 3: "[...] applications which need to define more
1803  * than 32 dynamic payload types MAY bind codes below 96, in which case
1804  * it is RECOMMENDED that unassigned payload type numbers be used
1805  * first". Updated by RFC 5761, Section 4: "[...] values in the range
1806  * 64-95 MUST NOT be used [to avoid conflicts with RTCP]". Summaries:
1807  * https://tools.ietf.org/html/draft-roach-mmusic-unified-plan#section-3.2.1.2
1808  * https://tools.ietf.org/html/draft-wu-avtcore-dynamic-pt-usage#section-3
1809  */
1810  res = find_unused_payload_in_range(
1811  codecs, MAX(ast_option_rtpptdynamic, AST_RTP_PT_LAST_STATIC + 1),
1812  AST_RTP_PT_LAST_REASSIGN, static_RTP_PT);
1813  if (res != -1) {
1814  return res;
1815  }
1816 
1817  /* Yet, reusing mappings below AST_RTP_PT_LAST_STATIC (35) is not supported
1818  * in Asterisk because when Compact Headers are activated, no rtpmap is
1819  * send for those below 35. If you want to use 35 and below
1820  * A) do not use Compact Headers,
1821  * B) remove that code in res_pjsip, or
1822  * C) add a flag that this RTP Payload Type got reassigned dynamically
1823  * and requires a rtpmap even with Compact Headers enabled.
1824  */
1825  res = find_unused_payload_in_range(
1826  codecs, MAX(ast_option_rtpptdynamic, 20),
1827  AST_RTP_PT_LAST_STATIC + 1, static_RTP_PT);
1828  if (res != -1) {
1829  return res;
1830  }
1831 
1832  return find_unused_payload_in_range(
1833  codecs, MAX(ast_option_rtpptdynamic, 0),
1834  20, static_RTP_PT);
1835 }
1836 
1837 /*!
1838  * \internal
1839  * \brief Find the oldest non-primary dynamic rx payload type.
1840  * \since 14.0.0
1841  *
1842  * \param codecs Codecs structure to look in
1843  *
1844  * \note It is assumed that codecs is at least read locked before calling.
1845  *
1846  * \return Numerical payload type
1847  * \retval -1 if not found.
1848  */
1849 static int rtp_codecs_find_non_primary_dynamic_rx(struct ast_rtp_codecs *codecs)
1850 {
1851  struct ast_rtp_payload_type *type;
1852  struct timeval oldest;
1853  int idx;
1854  int payload = -1;
1855 
1857  for (; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
1858  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
1859  if (type
1860  && !type->primary_mapping
1861  && (payload == -1
1862  || ast_tvdiff_ms(type->when_retired, oldest) < 0)) {
1863  oldest = type->when_retired;
1864  payload = idx;
1865  }
1866  }
1867  return payload;
1868 }
1869 
1870 /*!
1871  * \internal
1872  * \brief Assign a payload type for the rx mapping.
1873  * \since 14.0.0
1874  *
1875  * \param codecs Codecs structure to look in
1876  * \param asterisk_format Non-zero if the given Asterisk format is present
1877  * \param format Asterisk format to look for
1878  * \param code The format to look for
1879  * \param explicit Require the provided code to be explicitly used
1880  *
1881  * \note It is assumed that static_RTP_PT_lock is at least read locked before calling.
1882  *
1883  * \return Numerical payload type
1884  * \retval -1 if could not assign.
1885  */
1886 static int rtp_codecs_assign_payload_code_rx(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, int explicit, unsigned int sample_rate)
1887 {
1888  int payload = code, i;
1889  struct ast_rtp_payload_type *new_type;
1890  static struct ast_rtp_payload_type *ignore[AST_RTP_MAX_PT] = {0};
1891 
1892  if (!explicit) {
1893  payload = find_static_payload_type(asterisk_format, format, code);
1894 
1895  if (payload < 0 && (!asterisk_format || !ast_option_rtpusedynamic)) {
1896  return payload;
1897  }
1898  }
1899 
1900  new_type = rtp_payload_type_alloc(format, payload, code, 1, sample_rate);
1901  if (!new_type) {
1902  return -1;
1903  }
1904 
1905  ast_rwlock_wrlock(&codecs->codecs_lock);
1906 
1907  /* Go through the existing mapping to create an ignore list. */
1908  for (i = 0; i < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); i++) {
1909  if (AST_VECTOR_GET(&codecs->payload_mapping_rx, i)) {
1910  ignore[i] = static_RTP_PT[i];
1911  }
1912  }
1913 
1914 
1915  if (payload > -1 && (payload < AST_RTP_PT_FIRST_DYNAMIC
1916  || AST_VECTOR_SIZE(&codecs->payload_mapping_rx) <= payload
1917  || !AST_VECTOR_GET(&codecs->payload_mapping_rx, payload))) {
1918 
1919  /*
1920  * The payload type is a static assignment
1921  * or our default dynamic position is available.
1922  */
1923  rtp_codecs_payload_replace_rx(codecs, payload, new_type);
1924  } else if (payload > -1 && !explicit
1925  /* We can either call this with the full list or the current rx list. The former
1926  * (static_RTP_PT) results in payload types skipping statically 'used' slots so you
1927  * get 101, 113...
1928  * With the latter (the built ingore list) you get what's expected 101, 102, 103 under
1929  * most circumstances, but this results in static types being replaced. Probably fine
1930  * because we preclude the current list.
1931  */
1932  && (-1 < (payload = find_unused_payload_in_range(codecs, payload, AST_RTP_MAX_PT, ignore)))) {
1933  /*
1934  * Our dynamic position is currently in use.
1935  * Try for the numerically next free one before trying
1936  * across the full range. This keeps the payload id's
1937  * in the best numerical order we can through the free
1938  * types.
1939  */
1940  new_type->payload = payload;
1941  /*
1942  * In this case, consider this the primary mapping for
1943  * the payload type so don't clear it. Set not replace.
1944  */
1945  rtp_codecs_payload_set_rx(codecs, payload, new_type, 0);
1946  } else if (!explicit && (-1 < (payload = find_unused_payload(codecs))
1947  || -1 < (payload = rtp_codecs_find_non_primary_dynamic_rx(codecs)))) {
1948  /*
1949  * We found the first available empty dynamic position
1950  * or we found a mapping that should no longer be
1951  * actively used.
1952  */
1953  new_type->payload = payload;
1954  rtp_codecs_payload_replace_rx(codecs, payload, new_type);
1955  } else if (explicit) {
1956  /*
1957  * They explicitly requested this payload number be used but it couldn't be
1958  */
1959  payload = -1;
1960  } else {
1961  /*
1962  * There are no empty or non-primary dynamic positions
1963  * left. Sadness.
1964  *
1965  * I don't think this is really possible.
1966  */
1967  ast_log(LOG_WARNING, "No dynamic RTP payload type values available "
1968  "for %s - %d!\n", format ? ast_format_get_name(format) : "", code);
1969  }
1970  ast_rwlock_unlock(&codecs->codecs_lock);
1971 
1972  ao2_ref(new_type, -1);
1973 
1974  return payload;
1975 }
1976 
1977 int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
1978 {
1979  return ast_rtp_codecs_payload_code_sample_rate(codecs, asterisk_format, format, code, 0);
1980 }
1981 
1982 int ast_rtp_codecs_payload_code_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, unsigned int sample_rate)
1983 {
1984  struct ast_rtp_payload_type *type;
1985  int idx;
1986  int payload = -1;
1987 
1988  ast_rwlock_rdlock(&static_RTP_PT_lock);
1989  if (!asterisk_format) {
1990  ast_rwlock_rdlock(&codecs->codecs_lock);
1991  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
1992  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
1993  if (!type) {
1994  continue;
1995  }
1996 
1997  if (!type->asterisk_format
1998  && type->primary_mapping
1999  && type->rtp_code == code
2000  && (sample_rate == 0 || type->sample_rate == sample_rate)) {
2001  payload = idx;
2002  break;
2003  }
2004  }
2005  ast_rwlock_unlock(&codecs->codecs_lock);
2006  } else if (format) {
2007  ast_rwlock_rdlock(&codecs->codecs_lock);
2008  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_rx); ++idx) {
2009  type = AST_VECTOR_GET(&codecs->payload_mapping_rx, idx);
2010  if (!type) {
2011  continue;
2012  }
2013 
2014  if (type->asterisk_format
2015  && type->primary_mapping
2016  && ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL) {
2017  payload = idx;
2018  break;
2019  }
2020  }
2021  ast_rwlock_unlock(&codecs->codecs_lock);
2022  }
2023 
2024  if (payload < 0) {
2025  payload = rtp_codecs_assign_payload_code_rx(codecs, asterisk_format, format,
2026  code, 0, sample_rate);
2027  }
2028  ast_rwlock_unlock(&static_RTP_PT_lock);
2029 
2030  return payload;
2031 }
2032 
2033 int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format)
2034 {
2035  return rtp_codecs_assign_payload_code_rx(codecs, 1, format, code, 1, 0);
2036 }
2037 
2038 int ast_rtp_codecs_payload_set_rx_sample_rate(struct ast_rtp_codecs *codecs, int code, struct ast_format *format, unsigned int sample_rate)
2039 {
2040  return rtp_codecs_assign_payload_code_rx(codecs, 1, format, code, 0, sample_rate);
2041 }
2042 
2043 int ast_rtp_codecs_payload_code_tx_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code, unsigned int sample_rate)
2044 {
2045  struct ast_rtp_payload_type *type;
2046  int idx;
2047  int payload = -1;
2048 
2049  if (!asterisk_format) {
2050  ast_rwlock_rdlock(&codecs->codecs_lock);
2051  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_tx); ++idx) {
2052  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, idx);
2053  if (!type) {
2054  continue;
2055  }
2056 
2057  if (!type->asterisk_format
2058  && type->rtp_code == code
2059  /* Multiple DTMF types share an rtp code but have different sample rates. To ensure we have the right
2060  type we therefore need the sample rate as well as the format and code. Other types have a fixed
2061  sample rate so this is not needed. For those pass in a sample rate of 0 or use ast_rtp_codecs_payload_code_tx. */
2062  && (sample_rate == 0 || type->sample_rate == sample_rate)) {
2063  payload = idx;
2064  break;
2065  }
2066  }
2067  ast_rwlock_unlock(&codecs->codecs_lock);
2068  } else if (format) {
2069  ast_rwlock_rdlock(&codecs->codecs_lock);
2070  for (idx = 0; idx < AST_VECTOR_SIZE(&codecs->payload_mapping_tx); ++idx) {
2071  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, idx);
2072  if (!type) {
2073  continue;
2074  }
2075 
2076  if (type->asterisk_format
2077  && ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL) {
2078  payload = idx;
2079  break;
2080  }
2081  }
2082  ast_rwlock_unlock(&codecs->codecs_lock);
2083  }
2084 
2085  if (payload < 0) {
2086  ast_rwlock_rdlock(&static_RTP_PT_lock);
2087  payload = find_static_payload_type(asterisk_format, format, code);
2088  ast_rwlock_unlock(&static_RTP_PT_lock);
2089  }
2090 
2091  return payload;
2092 }
2093 
2094 int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
2095 {
2096  return ast_rtp_codecs_payload_code_tx_sample_rate(codecs, asterisk_format, format, code, 0);
2097 }
2098 
2099 int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int payload)
2100 {
2101  struct ast_rtp_payload_type *type;
2102  int res = -1;
2103 
2104  ast_rwlock_rdlock(&codecs->codecs_lock);
2105  if (payload < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)) {
2106  type = AST_VECTOR_GET(&codecs->payload_mapping_tx, payload);
2107  if (type) {
2108  res = payload;
2109  }
2110  }
2111  ast_rwlock_unlock(&codecs->codecs_lock);
2112 
2113  return res;
2114 }
2115 
2116 const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format,
2117  const struct ast_format *format, int code, enum ast_rtp_options options)
2118 {
2119  int i;
2120  const char *res = "";
2121 
2122  ast_rwlock_rdlock(&mime_types_lock);
2123  for (i = 0; i < mime_types_len; i++) {
2124  if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format &&
2125  (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
2127  (options & AST_RTP_OPT_G726_NONSTANDARD)) {
2128  res = "G726-32";
2129  break;
2130  } else {
2131  res = ast_rtp_mime_types[i].subtype;
2132  break;
2133  }
2134  } else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format &&
2135  ast_rtp_mime_types[i].payload_type.rtp_code == code) {
2136 
2137  res = ast_rtp_mime_types[i].subtype;
2138  break;
2139  }
2140  }
2141  ast_rwlock_unlock(&mime_types_lock);
2142 
2143  return res;
2144 }
2145 
2146 unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format,
2147  const struct ast_format *format, int code)
2148 {
2149  unsigned int i;
2150  unsigned int res = 0;
2151 
2152  ast_rwlock_rdlock(&mime_types_lock);
2153  for (i = 0; i < mime_types_len; ++i) {
2154  if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format &&
2155  (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
2156  res = ast_rtp_mime_types[i].sample_rate;
2157  break;
2158  } else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format &&
2159  ast_rtp_mime_types[i].payload_type.rtp_code == code) {
2160  res = ast_rtp_mime_types[i].sample_rate;
2161  break;
2162  }
2163  }
2164  ast_rwlock_unlock(&mime_types_lock);
2165 
2166  return res;
2167 }
2168 
2169 char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *ast_format_capability, int rtp_capability, const int asterisk_format, enum ast_rtp_options options)
2170 {
2171  int found = 0;
2172  const char *name;
2173  if (!buf) {
2174  return NULL;
2175  }
2176 
2177 
2178  if (asterisk_format) {
2179  int x;
2180  struct ast_format *tmp_fmt;
2181  for (x = 0; x < ast_format_cap_count(ast_format_capability); x++) {
2182  tmp_fmt = ast_format_cap_get_format(ast_format_capability, x);
2183  name = ast_rtp_lookup_mime_subtype2(asterisk_format, tmp_fmt, 0, options);
2184  ao2_ref(tmp_fmt, -1);
2185  ast_str_append(&buf, 0, "%s|", name);
2186  found = 1;
2187  }
2188  } else {
2189  int x;
2190  ast_str_append(&buf, 0, "0x%x (", (unsigned int) rtp_capability);
2191  for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
2192  if (rtp_capability & x) {
2193  name = ast_rtp_lookup_mime_subtype2(asterisk_format, NULL, x, options);
2194  ast_str_append(&buf, 0, "%s|", name);
2195  found = 1;
2196  }
2197  }
2198  }
2199 
2200  ast_str_append(&buf, 0, "%s", found ? ")" : "nothing)");
2201 
2202  return ast_str_buffer(buf);
2203 }
2204 
2205 int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
2206 {
2207  int res;
2208 
2209  if (instance->engine->dtmf_begin) {
2210  ao2_lock(instance);
2211  res = instance->engine->dtmf_begin(instance, digit);
2212  ao2_unlock(instance);
2213  } else {
2214  res = -1;
2215  }
2216  return res;
2217 }
2218 
2219 int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
2220 {
2221  int res;
2222 
2223  if (instance->engine->dtmf_end) {
2224  ao2_lock(instance);
2225  res = instance->engine->dtmf_end(instance, digit);
2226  ao2_unlock(instance);
2227  } else {
2228  res = -1;
2229  }
2230  return res;
2231 }
2232 
2233 int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
2234 {
2235  int res;
2236 
2237  if (instance->engine->dtmf_end_with_duration) {
2238  ao2_lock(instance);
2239  res = instance->engine->dtmf_end_with_duration(instance, digit, duration);
2240  ao2_unlock(instance);
2241  } else {
2242  res = -1;
2243  }
2244  return res;
2245 }
2246 
2248 {
2249  int res;
2250 
2251  if (instance->engine->dtmf_mode_set) {
2252  ao2_lock(instance);
2253  res = instance->engine->dtmf_mode_set(instance, dtmf_mode);
2254  ao2_unlock(instance);
2255  } else {
2256  res = -1;
2257  }
2258  return res;
2259 }
2260 
2262 {
2263  int res;
2264 
2265  if (instance->engine->dtmf_mode_get) {
2266  ao2_lock(instance);
2267  res = instance->engine->dtmf_mode_get(instance);
2268  ao2_unlock(instance);
2269  } else {
2270  res = 0;
2271  }
2272  return res;
2273 }
2274 
2276 {
2277  if (instance->engine->update_source) {
2278  ao2_lock(instance);
2279  instance->engine->update_source(instance);
2280  ao2_unlock(instance);
2281  }
2282 }
2283 
2285 {
2286  if (instance->engine->change_source) {
2287  ao2_lock(instance);
2288  instance->engine->change_source(instance);
2289  ao2_unlock(instance);
2290  }
2291 }
2292 
2293 int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
2294 {
2295  int res;
2296 
2297  if (instance->engine->qos) {
2298  ao2_lock(instance);
2299  res = instance->engine->qos(instance, tos, cos, desc);
2300  ao2_unlock(instance);
2301  } else {
2302  res = -1;
2303  }
2304  return res;
2305 }
2306 
2308 {
2309  if (instance->engine->stop) {
2310  ao2_lock(instance);
2311  instance->engine->stop(instance);
2312  ao2_unlock(instance);
2313  }
2314 }
2315 
2316 int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
2317 {
2318  int res;
2319 
2320  if (instance->engine->fd) {
2321  ao2_lock(instance);
2322  res = instance->engine->fd(instance, rtcp);
2323  ao2_unlock(instance);
2324  } else {
2325  res = -1;
2326  }
2327  return res;
2328 }
2329 
2330 struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type)
2331 {
2332  struct ast_rtp_glue *glue = NULL;
2333 
2335 
2336  AST_RWLIST_TRAVERSE(&glues, glue, entry) {
2337  if (!strcasecmp(glue->type, type)) {
2338  break;
2339  }
2340  }
2341 
2343 
2344  return glue;
2345 }
2346 
2347 /*!
2348  * \brief Conditionally unref an rtp instance
2349  */
2350 static void unref_instance_cond(struct ast_rtp_instance **instance)
2351 {
2352  if (*instance) {
2353  ao2_ref(*instance, -1);
2354  *instance = NULL;
2355  }
2356 }
2357 
2359 {
2360  struct ast_rtp_instance *bridged;
2361 
2362  ao2_lock(instance);
2363  bridged = instance->bridged;
2364  ao2_unlock(instance);
2365  return bridged;
2366 }
2367 
2368 void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_rtp_instance *bridged)
2369 {
2370  ao2_lock(instance);
2371  instance->bridged = bridged;
2372  ao2_unlock(instance);
2373 }
2374 
2376 {
2377  struct ast_rtp_instance *instance_dst = NULL, *instance_src = NULL,
2378  *vinstance_dst = NULL, *vinstance_src = NULL,
2379  *tinstance_dst = NULL, *tinstance_src = NULL;
2380  struct ast_rtp_glue *glue_dst, *glue_src;
2381  enum ast_rtp_glue_result audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
2382  enum ast_rtp_glue_result audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
2385 
2386  /* Lock both channels so we can look for the glue that binds them together */
2387  ast_channel_lock_both(c_dst, c_src);
2388 
2389  if (!cap_src || !cap_dst) {
2390  goto done;
2391  }
2392 
2393  /* Grab glue that binds each channel to something using the RTP engine */
2394  if (!(glue_dst = ast_rtp_instance_get_glue(ast_channel_tech(c_dst)->type)) || !(glue_src = ast_rtp_instance_get_glue(ast_channel_tech(c_src)->type))) {
2395  ast_debug(1, "Can't find native functions for channel '%s'\n", glue_dst ? ast_channel_name(c_src) : ast_channel_name(c_dst));
2396  goto done;
2397  }
2398 
2399  audio_glue_dst_res = glue_dst->get_rtp_info(c_dst, &instance_dst);
2400  video_glue_dst_res = glue_dst->get_vrtp_info ? glue_dst->get_vrtp_info(c_dst, &vinstance_dst) : AST_RTP_GLUE_RESULT_FORBID;
2401 
2402  audio_glue_src_res = glue_src->get_rtp_info(c_src, &instance_src);
2403  video_glue_src_res = glue_src->get_vrtp_info ? glue_src->get_vrtp_info(c_src, &vinstance_src) : AST_RTP_GLUE_RESULT_FORBID;
2404 
2405  /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
2406  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)) {
2407  audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
2408  }
2409  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)) {
2410  audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
2411  }
2412  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) {
2413  glue_dst->get_codec(c_dst, cap_dst);
2414  }
2415  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) {
2416  glue_src->get_codec(c_src, cap_src);
2417  }
2418 
2419  /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
2420  if (audio_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE) {
2421  goto done;
2422  }
2423 
2424  /* Make sure we have matching codecs */
2425  if (!ast_format_cap_iscompatible(cap_dst, cap_src)) {
2426  goto done;
2427  }
2428 
2429  ast_rtp_codecs_payloads_xover(&instance_src->codecs, &instance_dst->codecs, instance_dst);
2430 
2431  if (vinstance_dst && vinstance_src) {
2432  ast_rtp_codecs_payloads_xover(&vinstance_src->codecs, &vinstance_dst->codecs, vinstance_dst);
2433  }
2434  if (tinstance_dst && tinstance_src) {
2435  ast_rtp_codecs_payloads_xover(&tinstance_src->codecs, &tinstance_dst->codecs, tinstance_dst);
2436  }
2437 
2438  if (glue_dst->update_peer(c_dst, instance_src, vinstance_src, tinstance_src, cap_src, 0)) {
2439  ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n",
2440  ast_channel_name(c_dst), ast_channel_name(c_src));
2441  } else {
2442  ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n",
2443  ast_channel_name(c_dst), ast_channel_name(c_src));
2444  }
2445 
2446 done:
2447  ast_channel_unlock(c_dst);
2448  ast_channel_unlock(c_src);
2449 
2450  ao2_cleanup(cap_dst);
2451  ao2_cleanup(cap_src);
2452 
2453  unref_instance_cond(&instance_dst);
2454  unref_instance_cond(&instance_src);
2455  unref_instance_cond(&vinstance_dst);
2456  unref_instance_cond(&vinstance_src);
2457  unref_instance_cond(&tinstance_dst);
2458  unref_instance_cond(&tinstance_src);
2459 }
2460 
2462 {
2463  struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
2464  *vinstance0 = NULL, *vinstance1 = NULL,
2465  *tinstance0 = NULL, *tinstance1 = NULL;
2466  struct ast_rtp_glue *glue0, *glue1;
2467  enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
2468  enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
2471 
2472  /* If there is no second channel just immediately bail out, we are of no use in that scenario */
2473  if (!c1 || !cap1 || !cap0) {
2474  ao2_cleanup(cap0);
2475  ao2_cleanup(cap1);
2476  return -1;
2477  }
2478 
2479  /* Lock both channels so we can look for the glue that binds them together */
2480  ast_channel_lock_both(c0, c1);
2481 
2482  /* Grab glue that binds each channel to something using the RTP engine */
2483  if (!(glue0 = ast_rtp_instance_get_glue(ast_channel_tech(c0)->type)) || !(glue1 = ast_rtp_instance_get_glue(ast_channel_tech(c1)->type))) {
2484  ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? ast_channel_name(c1) : ast_channel_name(c0));
2485  goto done;
2486  }
2487 
2488  audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
2489  video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
2490 
2491  audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
2492  video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
2493 
2494  /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
2495  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)) {
2496  audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
2497  }
2498  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)) {
2499  audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
2500  }
2501  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) {
2502  glue0->get_codec(c0, cap0);
2503  }
2504  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) {
2505  glue1->get_codec(c1, cap1);
2506  }
2507 
2508  /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
2509  if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
2510  goto done;
2511  }
2512 
2513  /* Make sure we have matching codecs */
2514  if (!ast_format_cap_iscompatible(cap0, cap1)) {
2515  goto done;
2516  }
2517 
2518  /* Bridge media early */
2519  if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, cap1, 0)) {
2520  ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", ast_channel_name(c0), c1 ? ast_channel_name(c1) : "<unspecified>");
2521  }
2522 
2523 done:
2524  ast_channel_unlock(c0);
2525  ast_channel_unlock(c1);
2526 
2527  ao2_cleanup(cap0);
2528  ao2_cleanup(cap1);
2529 
2530  unref_instance_cond(&instance0);
2531  unref_instance_cond(&instance1);
2532  unref_instance_cond(&vinstance0);
2533  unref_instance_cond(&vinstance1);
2534  unref_instance_cond(&tinstance0);
2535  unref_instance_cond(&tinstance1);
2536 
2537  ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", ast_channel_name(c0), c1 ? ast_channel_name(c1) : "<unspecified>");
2538 
2539  return 0;
2540 }
2541 
2542 int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
2543 {
2544  int res;
2545 
2546  if (instance->engine->red_init) {
2547  ao2_lock(instance);
2548  res = instance->engine->red_init(instance, buffer_time, payloads, generations);
2549  ao2_unlock(instance);
2550  } else {
2551  res = -1;
2552  }
2553  return res;
2554 }
2555 
2556 int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
2557 {
2558  int res;
2559 
2560  if (instance->engine->red_buffer) {
2561  ao2_lock(instance);
2562  res = instance->engine->red_buffer(instance, frame);
2563  ao2_unlock(instance);
2564  } else {
2565  res = -1;
2566  }
2567  return res;
2568 }
2569 
2571 {
2572  int res;
2573 
2574  if (!instance || !instance->engine || !stats) {
2575  return -1;
2576  }
2577 
2578  if (instance->engine->get_stat) {
2579  ao2_lock(instance);
2580  res = instance->engine->get_stat(instance, stats, stat);
2581  ao2_unlock(instance);
2582  } else {
2583  res = -1;
2584  }
2585  return res;
2586 }
2587 
2588 char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
2589 {
2590  struct ast_rtp_instance_stats stats = { 0, };
2591  enum ast_rtp_instance_stat stat;
2592 
2593  /* Determine what statistics we will need to retrieve based on field passed in */
2594  if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
2596  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
2598  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
2600  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
2602  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES) {
2604  } else {
2605  return NULL;
2606  }
2607 
2608  /* Attempt to actually retrieve the statistics we need to generate the quality string */
2609  if (ast_rtp_instance_get_stats(instance, &stats, stat)) {
2610  return NULL;
2611  }
2612 
2613  /* Now actually fill the buffer with the good information */
2614  if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
2615  snprintf(buf, size, "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;"
2616  "txjitter=%f;txcount=%u;rlp=%u;rtt=%f;rxmes=%f;txmes=%f",
2617  stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.rxjitter,
2618  stats.rxcount, stats.txjitter, stats.txcount, stats.txploss, stats.rtt,
2619  stats.rxmes, stats.txmes);
2620  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
2621  snprintf(buf, size, "minrxjitter=%010.6f;maxrxjitter=%010.6f;avgrxjitter=%010.6f;stdevrxjitter=%010.6f;mintxjitter=%010.6f;maxtxjitter=%010.6f;avgtxjitter=%010.6f;stdevtxjitter=%010.6f;",
2623  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
2624  snprintf(buf, size, " minrxlost=%010.6f; maxrxlost=%010.6f; avgrxlost=%010.6f; stdevrxlost=%010.6f; mintxlost=%010.6f; maxtxlost=%010.6f; avgtxlost=%010.6f; stdevtxlost=%010.6f;",
2626  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
2627  snprintf(buf, size, " minrtt=%010.6f; maxrtt=%010.6f; avgrtt=%010.6f; stdevrtt=%010.6f;", stats.minrtt, stats.maxrtt, stats.normdevrtt, stats.stdevrtt);
2628  } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES) {
2629  snprintf(buf, size, " minrxmes=%010.6f; maxrxmes=%010.6f; avgrxmes=%010.6f; stdevrxmes=%010.6f; mintxmes=%010.6f; maxtxmes=%010.6f; avgtxmes=%010.6f; stdevtxmes=%010.6f;",
2630  stats.local_minmes, stats.local_maxmes,
2631  stats.local_normdevmes, stats.local_stdevmes,
2632  stats.remote_minmes, stats.remote_maxmes,
2633  stats.remote_normdevmes, stats.remote_stdevmes);
2634  }
2635 
2636  return buf;
2637 }
2638 
2640 {
2641  char quality_buf[AST_MAX_USER_FIELD];
2642  char *quality;
2643  struct ast_channel *bridge;
2644 
2645  bridge = ast_channel_bridge_peer(chan);
2646  if (bridge) {
2647  ast_channel_lock_both(chan, bridge);
2649  } else {
2650  ast_channel_lock(chan);
2651  }
2653 
2655  quality_buf, sizeof(quality_buf));
2656  if (quality) {
2657  pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality);
2658  if (bridge) {
2659  pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality);
2660  }
2661  }
2662 
2663  quality = ast_rtp_instance_get_quality(instance,
2664  AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf));
2665  if (quality) {
2666  pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality);
2667  if (bridge) {
2668  pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality);
2669  }
2670  }
2671 
2672  quality = ast_rtp_instance_get_quality(instance,
2673  AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf));
2674  if (quality) {
2675  pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality);
2676  if (bridge) {
2677  pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality);
2678  }
2679  }
2680 
2681  quality = ast_rtp_instance_get_quality(instance,
2682  AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf));
2683  if (quality) {
2684  pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality);
2685  if (bridge) {
2686  pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality);
2687  }
2688  }
2689 
2690  quality = ast_rtp_instance_get_quality(instance,
2691  AST_RTP_INSTANCE_STAT_FIELD_QUALITY_MES, quality_buf, sizeof(quality_buf));
2692  if (quality) {
2693  pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSMES", quality);
2694  if (bridge) {
2695  pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSMESBRIDGED", quality);
2696  }
2697  }
2698 
2700  ast_channel_unlock(chan);
2701  if (bridge) {
2703  ast_channel_unlock(bridge);
2704  ast_channel_unref(bridge);
2705  }
2706 }
2707 
2708 int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, struct ast_format *format)
2709 {
2710  int res;
2711 
2712  if (instance->engine->set_read_format) {
2713  ao2_lock(instance);
2714  res = instance->engine->set_read_format(instance, format);
2715  ao2_unlock(instance);
2716  } else {
2717  res = -1;
2718  }
2719  return res;
2720 }
2721 
2723 {
2724  int res;
2725 
2726  if (instance->engine->set_read_format) {
2727  ao2_lock(instance);
2728  res = instance->engine->set_write_format(instance, format);
2729  ao2_unlock(instance);
2730  } else {
2731  res = -1;
2732  }
2733  return res;
2734 }
2735 
2736 /* XXX Nothing calls this */
2737 int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer)
2738 {
2739  struct ast_rtp_glue *glue;
2740  struct ast_rtp_instance *peer_instance = NULL;
2741  int res = -1;
2742 
2743  if (!instance->engine->make_compatible) {
2744  return -1;
2745  }
2746 
2747  ast_channel_lock(peer);
2748 
2749  if (!(glue = ast_rtp_instance_get_glue(ast_channel_tech(peer)->type))) {
2750  ast_channel_unlock(peer);
2751  return -1;
2752  }
2753 
2754  glue->get_rtp_info(peer, &peer_instance);
2755  if (!peer_instance) {
2756  ast_log(LOG_ERROR, "Unable to get_rtp_info for peer type %s\n", glue->type);
2757  ast_channel_unlock(peer);
2758  return -1;
2759  }
2760  if (peer_instance->engine != instance->engine) {
2761  ast_log(LOG_ERROR, "Peer engine mismatch for type %s\n", glue->type);
2762  ast_channel_unlock(peer);
2763  ao2_ref(peer_instance, -1);
2764  return -1;
2765  }
2766 
2767  /*
2768  * XXX Good thing nothing calls this function because we would need
2769  * deadlock avoidance to get the two instance locks.
2770  */
2771  res = instance->engine->make_compatible(chan, instance, peer, peer_instance);
2772 
2773  ast_channel_unlock(peer);
2774 
2775  ao2_ref(peer_instance, -1);
2776  peer_instance = NULL;
2777 
2778  return res;
2779 }
2780 
2781 void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result)
2782 {
2783  if (instance->engine->available_formats) {
2784  ao2_lock(instance);
2785  instance->engine->available_formats(instance, to_endpoint, to_asterisk, result);
2786  ao2_unlock(instance);
2787  if (ast_format_cap_count(result)) {
2788  return;
2789  }
2790  }
2791 
2792  ast_translate_available_formats(to_endpoint, to_asterisk, result);
2793 }
2794 
2796 {
2797  int res;
2798 
2799  if (instance->engine->activate) {
2800  ao2_lock(instance);
2801  res = instance->engine->activate(instance);
2802  ao2_unlock(instance);
2803  } else {
2804  res = 0;
2805  }
2806  return res;
2807 }
2808 
2810  struct ast_sockaddr *suggestion,
2811  const char *username)
2812 {
2813  if (instance->engine->stun_request) {
2814  instance->engine->stun_request(instance, suggestion, username);
2815  }
2816 }
2817 
2818 void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
2819 {
2820  instance->timeout = timeout;
2821 }
2822 
2823 void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout)
2824 {
2825  instance->holdtimeout = timeout;
2826 }
2827 
2828 void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int interval)
2829 {
2830  instance->keepalive = interval;
2831 }
2832 
2834 {
2835  return instance->timeout;
2836 }
2837 
2839 {
2840  return instance->holdtimeout;
2841 }
2842 
2844 {
2845  return instance->keepalive;
2846 }
2847 
2849 {
2850  return instance->engine;
2851 }
2852 
2854 {
2855  return instance->glue;
2856 }
2857 
2858 int ast_rtp_engine_register_srtp(struct ast_srtp_res *srtp_res, struct ast_srtp_policy_res *policy_res)
2859 {
2860  if (res_srtp || res_srtp_policy) {
2861  return -1;
2862  }
2863  if (!srtp_res || !policy_res) {
2864  return -1;
2865  }
2866 
2867  res_srtp = srtp_res;
2868  res_srtp_policy = policy_res;
2869 
2870  return 0;
2871 }
2872 
2873 void ast_rtp_engine_unregister_srtp(void)
2874 {
2875  res_srtp = NULL;
2876  res_srtp_policy = NULL;
2877 }
2878 
2879 int ast_rtp_engine_srtp_is_registered(void)
2880 {
2881  return res_srtp && res_srtp_policy;
2882 }
2883 
2884 int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *remote_policy, struct ast_srtp_policy *local_policy, int rtcp)
2885 {
2886  int res = 0;
2887  struct ast_srtp **srtp;
2888 
2889  if (!res_srtp) {
2890  return -1;
2891  }
2892 
2893  ao2_lock(instance);
2894 
2895  srtp = rtcp ? &instance->rtcp_srtp : &instance->srtp;
2896 
2897  if (!*srtp) {
2898  res = res_srtp->create(srtp, instance, remote_policy);
2899  } else if (remote_policy) {
2900  res = res_srtp->replace(srtp, instance, remote_policy);
2901  }
2902  if (!res) {
2903  res = res_srtp->add_stream(*srtp, local_policy);
2904  }
2905 
2906  ao2_unlock(instance);
2907 
2908  return res;
2909 }
2910 
2911 struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
2912 {
2913  if (rtcp && instance->rtcp_srtp) {
2914  return instance->rtcp_srtp;
2915  } else {
2916  return instance->srtp;
2917  }
2918 }
2919 
2920 int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
2921 {
2922  int res;
2923 
2924  if (instance->engine->sendcng) {
2925  ao2_lock(instance);
2926  res = instance->engine->sendcng(instance, level);
2927  ao2_unlock(instance);
2928  } else {
2929  res = -1;
2930  }
2931  return res;
2932 }
2933 
2934 static void rtp_ice_wrap_set_authentication(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
2935 {
2936  ao2_lock(instance);
2937  instance->engine->ice->set_authentication(instance, ufrag, password);
2938  ao2_unlock(instance);
2939 }
2940 
2941 static void rtp_ice_wrap_add_remote_candidate(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
2942 {
2943  ao2_lock(instance);
2944  instance->engine->ice->add_remote_candidate(instance, candidate);
2945  ao2_unlock(instance);
2946 }
2947 
2948 static void rtp_ice_wrap_start(struct ast_rtp_instance *instance)
2949 {
2950  ao2_lock(instance);
2951  instance->engine->ice->start(instance);
2952  ao2_unlock(instance);
2953 }
2954 
2955 static void rtp_ice_wrap_stop(struct ast_rtp_instance *instance)
2956 {
2957  ao2_lock(instance);
2958  instance->engine->ice->stop(instance);
2959  ao2_unlock(instance);
2960 }
2961 
2962 static const char *rtp_ice_wrap_get_ufrag(struct ast_rtp_instance *instance)
2963 {
2964  const char *ufrag;
2965 
2966  ao2_lock(instance);
2967  ufrag = instance->engine->ice->get_ufrag(instance);
2968  ao2_unlock(instance);
2969  return ufrag;
2970 }
2971 
2972 static const char *rtp_ice_wrap_get_password(struct ast_rtp_instance *instance)
2973 {
2974  const char *password;
2975 
2976  ao2_lock(instance);
2977  password = instance->engine->ice->get_password(instance);
2978  ao2_unlock(instance);
2979  return password;
2980 }
2981 
2982 static struct ao2_container *rtp_ice_wrap_get_local_candidates(struct ast_rtp_instance *instance)
2983 {
2984  struct ao2_container *local_candidates;
2985 
2986  ao2_lock(instance);
2987  local_candidates = instance->engine->ice->get_local_candidates(instance);
2988  ao2_unlock(instance);
2989  return local_candidates;
2990 }
2991 
2992 static void rtp_ice_wrap_ice_lite(struct ast_rtp_instance *instance)
2993 {
2994  ao2_lock(instance);
2995  instance->engine->ice->ice_lite(instance);
2996  ao2_unlock(instance);
2997 }
2998 
2999 static void rtp_ice_wrap_set_role(struct ast_rtp_instance *instance,
3000  enum ast_rtp_ice_role role)
3001 {
3002  ao2_lock(instance);
3003  instance->engine->ice->set_role(instance, role);
3004  ao2_unlock(instance);
3005 }
3006 
3007 static void rtp_ice_wrap_turn_request(struct ast_rtp_instance *instance,
3008  enum ast_rtp_ice_component_type component, enum ast_transport transport,
3009  const char *server, unsigned int port, const char *username, const char *password)
3010 {
3011  ao2_lock(instance);
3012  instance->engine->ice->turn_request(instance, component, transport, server, port,
3013  username, password);
3014  ao2_unlock(instance);
3015 }
3016 
3017 static void rtp_ice_wrap_change_components(struct ast_rtp_instance *instance,
3018  int num_components)
3019 {
3020  ao2_lock(instance);
3021  instance->engine->ice->change_components(instance, num_components);
3022  ao2_unlock(instance);
3023 }
3024 
3025 static struct ast_rtp_engine_ice rtp_ice_wrappers = {
3026  .set_authentication = rtp_ice_wrap_set_authentication,
3027  .add_remote_candidate = rtp_ice_wrap_add_remote_candidate,
3028  .start = rtp_ice_wrap_start,
3029  .stop = rtp_ice_wrap_stop,
3030  .get_ufrag = rtp_ice_wrap_get_ufrag,
3031  .get_password = rtp_ice_wrap_get_password,
3032  .get_local_candidates = rtp_ice_wrap_get_local_candidates,
3033  .ice_lite = rtp_ice_wrap_ice_lite,
3034  .set_role = rtp_ice_wrap_set_role,
3035  .turn_request = rtp_ice_wrap_turn_request,
3036  .change_components = rtp_ice_wrap_change_components,
3037 };
3038 
3040 {
3041  if (instance->engine->ice) {
3042  return &rtp_ice_wrappers;
3043  }
3044  /* ICE not available */
3045  return NULL;
3046 }
3047 
3048 #ifdef TEST_FRAMEWORK
3049 struct ast_rtp_engine_test *ast_rtp_instance_get_test(struct ast_rtp_instance *instance)
3050 {
3051  return instance->engine->test;
3052 }
3053 #endif
3054 
3055 static int rtp_dtls_wrap_set_configuration(struct ast_rtp_instance *instance,
3056  const struct ast_rtp_dtls_cfg *dtls_cfg)
3057 {
3058  int set_configuration;
3059 
3060  ao2_lock(instance);
3061  set_configuration = instance->engine->dtls->set_configuration(instance, dtls_cfg);
3062  ao2_unlock(instance);
3063  return set_configuration;
3064 }
3065 
3066 static int rtp_dtls_wrap_active(struct ast_rtp_instance *instance)
3067 {
3068  int active;
3069 
3070  ao2_lock(instance);
3071  active = instance->engine->dtls->active(instance);
3072  ao2_unlock(instance);
3073  return active;
3074 }
3075 
3076 static void rtp_dtls_wrap_stop(struct ast_rtp_instance *instance)
3077 {
3078  ao2_lock(instance);
3079  instance->engine->dtls->stop(instance);
3080  ao2_unlock(instance);
3081 }
3082 
3083 static void rtp_dtls_wrap_reset(struct ast_rtp_instance *instance)
3084 {
3085  ao2_lock(instance);
3086  instance->engine->dtls->reset(instance);
3087  ao2_unlock(instance);
3088 }
3089 
3090 static enum ast_rtp_dtls_connection rtp_dtls_wrap_get_connection(struct ast_rtp_instance *instance)
3091 {
3092  enum ast_rtp_dtls_connection get_connection;
3093 
3094  ao2_lock(instance);
3095  get_connection = instance->engine->dtls->get_connection(instance);
3096  ao2_unlock(instance);
3097  return get_connection;
3098 }
3099 
3100 static enum ast_rtp_dtls_setup rtp_dtls_wrap_get_setup(struct ast_rtp_instance *instance)
3101 {
3102  enum ast_rtp_dtls_setup get_setup;
3103 
3104  ao2_lock(instance);
3105  get_setup = instance->engine->dtls->get_setup(instance);
3106  ao2_unlock(instance);
3107  return get_setup;
3108 }
3109 
3110 static void rtp_dtls_wrap_set_setup(struct ast_rtp_instance *instance,
3111  enum ast_rtp_dtls_setup setup)
3112 {
3113  ao2_lock(instance);
3114  instance->engine->dtls->set_setup(instance, setup);
3115  ao2_unlock(instance);
3116 }
3117 
3118 static void rtp_dtls_wrap_set_fingerprint(struct ast_rtp_instance *instance,
3119  enum ast_rtp_dtls_hash hash, const char *fingerprint)
3120 {
3121  ao2_lock(instance);
3122  instance->engine->dtls->set_fingerprint(instance, hash, fingerprint);
3123  ao2_unlock(instance);
3124 }
3125 
3126 static enum ast_rtp_dtls_hash rtp_dtls_wrap_get_fingerprint_hash(struct ast_rtp_instance *instance)
3127 {
3128  enum ast_rtp_dtls_hash get_fingerprint_hash;
3129 
3130  ao2_lock(instance);
3131  get_fingerprint_hash = instance->engine->dtls->get_fingerprint_hash(instance);
3132  ao2_unlock(instance);
3133  return get_fingerprint_hash;
3134 }
3135 
3136 static const char *rtp_dtls_wrap_get_fingerprint(struct ast_rtp_instance *instance)
3137 {
3138  const char *get_fingerprint;
3139 
3140  ao2_lock(instance);
3141  get_fingerprint = instance->engine->dtls->get_fingerprint(instance);
3142  ao2_unlock(instance);
3143  return get_fingerprint;
3144 }
3145 
3146 static struct ast_rtp_engine_dtls rtp_dtls_wrappers = {
3147  .set_configuration = rtp_dtls_wrap_set_configuration,
3148  .active = rtp_dtls_wrap_active,
3149  .stop = rtp_dtls_wrap_stop,
3150  .reset = rtp_dtls_wrap_reset,
3151  .get_connection = rtp_dtls_wrap_get_connection,
3152  .get_setup = rtp_dtls_wrap_get_setup,
3153  .set_setup = rtp_dtls_wrap_set_setup,
3154  .set_fingerprint = rtp_dtls_wrap_set_fingerprint,
3155  .get_fingerprint_hash = rtp_dtls_wrap_get_fingerprint_hash,
3156  .get_fingerprint = rtp_dtls_wrap_get_fingerprint,
3157 };
3158 
3160 {
3161  if (instance->engine->dtls) {
3162  return &rtp_dtls_wrappers;
3163  }
3164  /* DTLS not available */
3165  return NULL;
3166 }
3167 
3168 int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name, const char *value)
3169 {
3170  if (!strcasecmp(name, "dtlsenable")) {
3171  dtls_cfg->enabled = ast_true(value) ? 1 : 0;
3172  } else if (!strcasecmp(name, "dtlsverify")) {
3173  if (!strcasecmp(value, "yes")) {
3175  } else if (!strcasecmp(value, "fingerprint")) {
3177  } else if (!strcasecmp(value, "certificate")) {
3179  } else if (!strcasecmp(value, "no")) {
3180  dtls_cfg->verify = AST_RTP_DTLS_VERIFY_NONE;
3181  } else {
3182  return -1;
3183  }
3184  } else if (!strcasecmp(name, "dtlsrekey")) {
3185  if (sscanf(value, "%30u", &dtls_cfg->rekey) != 1) {
3186  return -1;
3187  }
3188  } else if (!strcasecmp(name, "dtlsautogeneratecert")) {
3189  dtls_cfg->ephemeral_cert = ast_true(value) ? 1 : 0;
3190  } else if (!strcasecmp(name, "dtlscertfile")) {
3191  if (!ast_strlen_zero(value) && !ast_file_is_readable(value)) {
3192  ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
3193  return -1;
3194  }
3195  ast_free(dtls_cfg->certfile);
3196  dtls_cfg->certfile = ast_strdup(value);
3197  } else if (!strcasecmp(name, "dtlsprivatekey")) {
3198  if (!ast_strlen_zero(value) && !ast_file_is_readable(value)) {
3199  ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
3200  return -1;
3201  }
3202  ast_free(dtls_cfg->pvtfile);
3203  dtls_cfg->pvtfile = ast_strdup(value);
3204  } else if (!strcasecmp(name, "dtlscipher")) {
3205  ast_free(dtls_cfg->cipher);
3206  dtls_cfg->cipher = ast_strdup(value);
3207  } else if (!strcasecmp(name, "dtlscafile")) {
3208  if (!ast_strlen_zero(value) && !ast_file_is_readable(value)) {
3209  ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
3210  return -1;
3211  }
3212  ast_free(dtls_cfg->cafile);
3213  dtls_cfg->cafile = ast_strdup(value);
3214  } else if (!strcasecmp(name, "dtlscapath") || !strcasecmp(name, "dtlscadir")) {
3215  if (!ast_strlen_zero(value) && !ast_file_is_readable(value)) {
3216  ast_log(LOG_ERROR, "%s file %s does not exist or is not readable\n", name, value);
3217  return -1;
3218  }
3219  ast_free(dtls_cfg->capath);
3220  dtls_cfg->capath = ast_strdup(value);
3221  } else if (!strcasecmp(name, "dtlssetup")) {
3222  if (!strcasecmp(value, "active")) {
3224  } else if (!strcasecmp(value, "passive")) {
3226  } else if (!strcasecmp(value, "actpass")) {
3228  }
3229  } else if (!strcasecmp(name, "dtlsfingerprint")) {
3230  if (!strcasecmp(value, "sha-256")) {
3231  dtls_cfg->hash = AST_RTP_DTLS_HASH_SHA256;
3232  } else if (!strcasecmp(value, "sha-1")) {
3233  dtls_cfg->hash = AST_RTP_DTLS_HASH_SHA1;
3234  }
3235  } else {
3236  return -1;
3237  }
3238 
3239  return 0;
3240 }
3241 
3243 {
3244  if (dtls_cfg->ephemeral_cert) {
3245  if (!ast_strlen_zero(dtls_cfg->certfile)) {
3246  ast_log(LOG_ERROR, "You cannot request automatically generated certificates"
3247  " (dtls_auto_generate_cert) and also specify a certificate file"
3248  " (dtls_cert_file) at the same time\n");
3249  return -1;
3250  } else if (!ast_strlen_zero(dtls_cfg->pvtfile)
3251  || !ast_strlen_zero(dtls_cfg->cafile)
3252  || !ast_strlen_zero(dtls_cfg->capath)) {
3253  ast_log(LOG_NOTICE, "dtls_pvt_file, dtls_cafile, and dtls_ca_path are"
3254  " ignored when dtls_auto_generate_cert is enabled\n");
3255  }
3256  }
3257 
3258  return 0;
3259 }
3260 
3261 void ast_rtp_dtls_cfg_copy(const struct ast_rtp_dtls_cfg *src_cfg, struct ast_rtp_dtls_cfg *dst_cfg)
3262 {
3263  ast_rtp_dtls_cfg_free(dst_cfg); /* Prevent a double-call leaking memory via ast_strdup */
3264 
3265  dst_cfg->enabled = src_cfg->enabled;
3266  dst_cfg->verify = src_cfg->verify;
3267  dst_cfg->rekey = src_cfg->rekey;
3268  dst_cfg->suite = src_cfg->suite;
3269  dst_cfg->hash = src_cfg->hash;
3270  dst_cfg->ephemeral_cert = src_cfg->ephemeral_cert;
3271  dst_cfg->certfile = ast_strdup(src_cfg->certfile);
3272  dst_cfg->pvtfile = ast_strdup(src_cfg->pvtfile);
3273  dst_cfg->cipher = ast_strdup(src_cfg->cipher);
3274  dst_cfg->cafile = ast_strdup(src_cfg->cafile);
3275  dst_cfg->capath = ast_strdup(src_cfg->capath);
3276  dst_cfg->default_setup = src_cfg->default_setup;
3277 }
3278 
3280 {
3281  ast_free(dtls_cfg->certfile);
3282  dtls_cfg->certfile = NULL;
3283  ast_free(dtls_cfg->pvtfile);
3284  dtls_cfg->pvtfile = NULL;
3285  ast_free(dtls_cfg->cipher);
3286  dtls_cfg->cipher = NULL;
3287  ast_free(dtls_cfg->cafile);
3288  dtls_cfg->cafile = NULL;
3289  ast_free(dtls_cfg->capath);
3290  dtls_cfg->capath = NULL;
3291 }
3292 
3293 /*! \internal
3294  * \brief Small helper routine that cleans up entry i in
3295  * \c ast_rtp_mime_types.
3296  */
3297 static void rtp_engine_mime_type_cleanup(int i)
3298 {
3299  ao2_cleanup(ast_rtp_mime_types[i].payload_type.format);
3300  memset(&ast_rtp_mime_types[i], 0, sizeof(struct ast_rtp_mime_type));
3301 }
3302 
3303 static void set_next_mime_type(struct ast_format *format, int rtp_code, const char *type, const char *subtype, unsigned int sample_rate)
3304 {
3305  int x;
3306 
3307  ast_rwlock_wrlock(&mime_types_lock);
3308 
3309  x = mime_types_len;
3310  if (ARRAY_LEN(ast_rtp_mime_types) <= x) {
3311  ast_rwlock_unlock(&mime_types_lock);
3312  return;
3313  }
3314 
3315  /* Make sure any previous value in ast_rtp_mime_types is cleaned up */
3316  memset(&ast_rtp_mime_types[x], 0, sizeof(struct ast_rtp_mime_type));
3317  if (format) {
3318  ast_rtp_mime_types[x].payload_type.asterisk_format = 1;
3319  ast_rtp_mime_types[x].payload_type.format = ao2_bump(format);
3320  } else {
3321  ast_rtp_mime_types[x].payload_type.rtp_code = rtp_code;
3322  }
3323  ast_copy_string(ast_rtp_mime_types[x].type, type, sizeof(ast_rtp_mime_types[x].type));
3324  ast_copy_string(ast_rtp_mime_types[x].subtype, subtype, sizeof(ast_rtp_mime_types[x].subtype));
3325  ast_rtp_mime_types[x].sample_rate = sample_rate;
3326  mime_types_len++;
3327 
3328  ast_rwlock_unlock(&mime_types_lock);
3329 }
3330 
3331 static void add_static_payload(int payload, struct ast_format *format, int rtp_code)
3332 {
3333  struct ast_rtp_payload_type *type;
3334 
3335  /*
3336  * ARRAY_LEN's result is cast to an int so 'map' is not autocast to a size_t,
3337  * which if negative would cause an assertion.
3338  */
3339  ast_assert(payload < (int)ARRAY_LEN(static_RTP_PT));
3340 
3341  if (ast_option_rtpusedynamic && payload < 0) {
3342  /*
3343  * We're going to build dynamic payloads dynamically. An RTP code is
3344  * required otherwise one will be dynamically allocated per instance.
3345  */
3346  return;
3347  }
3348 
3349  /*
3350  * Either the given payload is truly a static type, or Asterisk is
3351  * globally storing the dynamic payloads in the static_RTP_PT object.
3352  */
3353  ast_rwlock_wrlock(&static_RTP_PT_lock);
3354 
3355  if (payload < 0) {
3356  /*
3357  * This is a dynamic payload that will be stored globally,
3358  * so find the next available empty slot.
3359  */
3360  payload = find_unused_payload(NULL);
3361  if (payload < 0) {
3362  ast_log(LOG_WARNING, "No dynamic RTP payload type values available "
3363  "for %s - %d!\n", format ? ast_format_get_name(format) : "", rtp_code);
3364  ast_rwlock_unlock(&static_RTP_PT_lock);
3365  return;
3366  }
3367  }
3368 
3369  type = rtp_payload_type_alloc(format, payload, rtp_code, 1, 0);
3370  if (type) {
3371  ao2_cleanup(static_RTP_PT[payload]);
3372  static_RTP_PT[payload] = type;
3373  }
3374  ast_rwlock_unlock(&static_RTP_PT_lock);
3375 }
3376 
3378 {
3379  char *codec_name = ast_strdupa(ast_format_get_codec_name(format));
3380 
3381  codec_name = ast_str_to_upper(codec_name);
3382 
3383  set_next_mime_type(format,
3384  0,
3386  codec_name,
3387  ast_format_get_sample_rate(format));
3388  add_static_payload(-1, format, 0);
3389 
3390  return 0;
3391 }
3392 
3394 {
3395  int x;
3396  int y = 0;
3397 
3398  ast_rwlock_wrlock(&static_RTP_PT_lock);
3399  /* remove everything pertaining to this format id from the lists */
3400  for (x = 0; x < AST_RTP_MAX_PT; x++) {
3401  if (static_RTP_PT[x]
3402  && ast_format_cmp(static_RTP_PT[x]->format, format) == AST_FORMAT_CMP_EQUAL) {
3403  ao2_ref(static_RTP_PT[x], -1);
3404  static_RTP_PT[x] = NULL;
3405  }
3406  }
3407  ast_rwlock_unlock(&static_RTP_PT_lock);
3408 
3409  ast_rwlock_wrlock(&mime_types_lock);
3410  /* rebuild the list skipping the items matching this id */
3411  for (x = 0; x < mime_types_len; x++) {
3412  if (ast_format_cmp(ast_rtp_mime_types[x].payload_type.format, format) == AST_FORMAT_CMP_EQUAL) {
3413  rtp_engine_mime_type_cleanup(x);
3414  continue;
3415  }
3416  if (x != y) {
3417  ast_rtp_mime_types[y] = ast_rtp_mime_types[x];
3418  }
3419  y++;
3420  }
3421  mime_types_len = y;
3422  ast_rwlock_unlock(&mime_types_lock);
3423  return 0;
3424 }
3425 
3426 /*!
3427  * \internal
3428  * \brief \ref stasis message payload for RTCP messages
3429  */
3431  struct ast_channel_snapshot *snapshot; /*< The channel snapshot, if available */
3432  struct ast_rtp_rtcp_report *report; /*< The RTCP report */
3433  struct ast_json *blob; /*< Extra JSON data to publish */
3434 };
3435 
3436 static void rtcp_message_payload_dtor(void *obj)
3437 {
3438  struct rtcp_message_payload *payload = obj;
3439 
3440  ao2_cleanup(payload->report);
3441  ao2_cleanup(payload->snapshot);
3442  ast_json_unref(payload->blob);
3443 }
3444 
3445 static struct ast_manager_event_blob *rtcp_report_to_ami(struct stasis_message *msg)
3446 {
3447  struct rtcp_message_payload *payload = stasis_message_data(msg);
3448  RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
3449  RAII_VAR(struct ast_str *, packet_string, ast_str_create(512), ast_free);
3450  unsigned int ssrc = payload->report->ssrc;
3451  unsigned int type = payload->report->type;
3452  unsigned int report_count = payload->report->reception_report_count;
3453  int i;
3454 
3455  if (!packet_string) {
3456  return NULL;
3457  }
3458 
3459  if (payload->snapshot) {
3460  channel_string = ast_manager_build_channel_state_string(payload->snapshot);
3461  if (!channel_string) {
3462  return NULL;
3463  }
3464  }
3465 
3466  if (payload->blob) {
3467  /* Optional data */
3468  struct ast_json *to = ast_json_object_get(payload->blob, "to");
3469  struct ast_json *from = ast_json_object_get(payload->blob, "from");
3470  struct ast_json *rtt = ast_json_object_get(payload->blob, "rtt");
3471  struct ast_json *mes = ast_json_object_get(payload->blob, "mes");
3472  if (to) {
3473  ast_str_append(&packet_string, 0, "To: %s\r\n", ast_json_string_get(to));
3474  }
3475  if (from) {
3476  ast_str_append(&packet_string, 0, "From: %s\r\n", ast_json_string_get(from));
3477  }
3478  if (rtt) {
3479  ast_str_append(&packet_string, 0, "RTT: %4.4f\r\n", ast_json_real_get(rtt));
3480  }
3481  if (mes) {
3482  ast_str_append(&packet_string, 0, "MES: %4.1f\r\n", ast_json_real_get(mes));
3483  }
3484  }
3485 
3486  ast_str_append(&packet_string, 0, "SSRC: 0x%.8x\r\n", ssrc);
3487  ast_str_append(&packet_string, 0, "PT: %u(%s)\r\n", type, type== AST_RTP_RTCP_SR ? "SR" : "RR");
3488  ast_str_append(&packet_string, 0, "ReportCount: %u\r\n", report_count);
3489  if (type == AST_RTP_RTCP_SR) {
3490  ast_str_append(&packet_string, 0, "SentNTP: %lu.%06lu\r\n",
3491  (unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec,
3492  (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec);
3493  ast_str_append(&packet_string, 0, "SentRTP: %u\r\n",
3494  payload->report->sender_information.rtp_timestamp);
3495  ast_str_append(&packet_string, 0, "SentPackets: %u\r\n",
3496  payload->report->sender_information.packet_count);
3497  ast_str_append(&packet_string, 0, "SentOctets: %u\r\n",
3498  payload->report->sender_information.octet_count);
3499  }
3500 
3501  for (i = 0; i < report_count; i++) {
3502  RAII_VAR(struct ast_str *, report_string, NULL, ast_free);
3503 
3504  if (!payload->report->report_block[i]) {
3505  break;
3506  }
3507 
3508  report_string = ast_str_create(256);
3509  if (!report_string) {
3510  return NULL;
3511  }
3512 
3513  ast_str_append(&report_string, 0, "Report%dSourceSSRC: 0x%.8x\r\n",
3514  i, payload->report->report_block[i]->source_ssrc);
3515  ast_str_append(&report_string, 0, "Report%dFractionLost: %d\r\n",
3516  i, payload->report->report_block[i]->lost_count.fraction);
3517  ast_str_append(&report_string, 0, "Report%dCumulativeLost: %u\r\n",
3518  i, payload->report->report_block[i]->lost_count.packets);
3519  ast_str_append(&report_string, 0, "Report%dHighestSequence: %u\r\n",
3520  i, payload->report->report_block[i]->highest_seq_no & 0xffff);
3521  ast_str_append(&report_string, 0, "Report%dSequenceNumberCycles: %u\r\n",
3522  i, payload->report->report_block[i]->highest_seq_no >> 16);
3523  ast_str_append(&report_string, 0, "Report%dIAJitter: %u\r\n",
3524  i, payload->report->report_block[i]->ia_jitter);
3525  ast_str_append(&report_string, 0, "Report%dLSR: %u\r\n",
3526  i, payload->report->report_block[i]->lsr);
3527  ast_str_append(&report_string, 0, "Report%dDLSR: %4.4f\r\n",
3528  i, ((double)payload->report->report_block[i]->dlsr) / 65536);
3529  ast_str_append(&packet_string, 0, "%s", ast_str_buffer(report_string));
3530  }
3531 
3532  return ast_manager_event_blob_create(EVENT_FLAG_REPORTING,
3533  stasis_message_type(msg) == ast_rtp_rtcp_received_type() ? "RTCPReceived" : "RTCPSent",
3534  "%s%s",
3535  AS_OR(channel_string, ""),
3536  ast_str_buffer(packet_string));
3537 }
3538 
3539 static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
3540  const struct stasis_message_sanitizer *sanitize)
3541 {
3542  struct rtcp_message_payload *payload = stasis_message_data(msg);
3543  struct ast_json *json_rtcp_report = NULL;
3544  struct ast_json *json_rtcp_report_blocks;
3545  struct ast_json *json_rtcp_sender_info = NULL;
3546  struct ast_json *json_channel = NULL;
3547  int i;
3548 
3549  json_rtcp_report_blocks = ast_json_array_create();
3550  if (!json_rtcp_report_blocks) {
3551  return NULL;
3552  }
3553 
3554  for (i = 0; i < payload->report->reception_report_count && payload->report->report_block[i]; i++) {
3555  struct ast_json *json_report_block;
3556  char str_lsr[32];
3557 
3558  snprintf(str_lsr, sizeof(str_lsr), "%u", payload->report->report_block[i]->lsr);
3559  json_report_block = ast_json_pack("{s: I, s: I, s: I, s: I, s: I, s: s, s: I}",
3560  "source_ssrc", (ast_json_int_t)payload->report->report_block[i]->source_ssrc,
3561  "fraction_lost", (ast_json_int_t)payload->report->report_block[i]->lost_count.fraction,
3562  "packets_lost", (ast_json_int_t)payload->report->report_block[i]->lost_count.packets,
3563  "highest_seq_no", (ast_json_int_t)payload->report->report_block[i]->highest_seq_no,
3564  "ia_jitter", (ast_json_int_t)payload->report->report_block[i]->ia_jitter,
3565  "lsr", str_lsr,
3566  "dlsr", (ast_json_int_t)payload->report->report_block[i]->dlsr);
3567  if (!json_report_block
3568  || ast_json_array_append(json_rtcp_report_blocks, json_report_block)) {
3569  ast_json_unref(json_rtcp_report_blocks);
3570  return NULL;
3571  }
3572  }
3573 
3574  if (payload->report->type == AST_RTP_RTCP_SR) {
3575  char sec[32];
3576  char usec[32];
3577 
3578  snprintf(sec, sizeof(sec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec);
3579  snprintf(usec, sizeof(usec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec);
3580  json_rtcp_sender_info = ast_json_pack("{s: s, s: s, s: I, s: I, s: I}",
3581  "ntp_timestamp_sec", sec,
3582  "ntp_timestamp_usec", usec,
3583  "rtp_timestamp", (ast_json_int_t)payload->report->sender_information.rtp_timestamp,
3584  "packets", (ast_json_int_t)payload->report->sender_information.packet_count,
3585  "octets", (ast_json_int_t)payload->report->sender_information.octet_count);
3586  if (!json_rtcp_sender_info) {
3587  ast_json_unref(json_rtcp_report_blocks);
3588  return NULL;
3589  }
3590  }
3591 
3592  json_rtcp_report = ast_json_pack("{s: I, s: I, s: i, s: o, s: o}",
3593  "ssrc", (ast_json_int_t)payload->report->ssrc,
3594  "type", (ast_json_int_t)payload->report->type,
3595  "report_count", payload->report->reception_report_count,
3596  "sender_information", json_rtcp_sender_info ?: ast_json_null(),
3597  "report_blocks", json_rtcp_report_blocks);
3598  if (!json_rtcp_report) {
3599  return NULL;
3600  }
3601 
3602  if (payload->snapshot) {
3603  json_channel = ast_channel_snapshot_to_json(payload->snapshot, sanitize);
3604  if (!json_channel) {
3605  ast_json_unref(json_rtcp_report);
3606  return NULL;
3607  }
3608  }
3609 
3610  return ast_json_pack("{s: s, s: o?, s: o, s: O?}",
3611  "type", stasis_message_type(msg) == ast_rtp_rtcp_received_type() ? "RTCPReceived" : "RTCPSent",
3612  "channel", json_channel,
3613  "rtcp_report", json_rtcp_report,
3614  "blob", payload->blob);
3615 }
3616 
3617 static void rtp_rtcp_report_dtor(void *obj)
3618 {
3619  int i;
3620  struct ast_rtp_rtcp_report *rtcp_report = obj;
3621 
3622  for (i = 0; i < rtcp_report->reception_report_count; i++) {
3623  ast_free(rtcp_report->report_block[i]);
3624  }
3625 }
3626 
3627 struct ast_rtp_rtcp_report *ast_rtp_rtcp_report_alloc(unsigned int report_blocks)
3628 {
3629  struct ast_rtp_rtcp_report *rtcp_report;
3630 
3631  /* Size of object is sizeof the report + the number of report_blocks * sizeof pointer */
3632  rtcp_report = ao2_alloc((sizeof(*rtcp_report) + report_blocks * sizeof(struct ast_rtp_rtcp_report_block *)),
3633  rtp_rtcp_report_dtor);
3634 
3635  return rtcp_report;
3636 }
3637 
3639  struct stasis_message_type *message_type,
3640  struct ast_rtp_rtcp_report *report,
3641  struct ast_json *blob)
3642 {
3643  RAII_VAR(struct rtcp_message_payload *, payload, NULL, ao2_cleanup);
3644  RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
3645 
3646  if (!message_type) {
3647  return;
3648  }
3649 
3650  payload = ao2_alloc(sizeof(*payload), rtcp_message_payload_dtor);
3651  if (!payload || !report) {
3652  return;
3653  }
3654 
3655  if (!ast_strlen_zero(rtp->channel_uniqueid)) {
3656  payload->snapshot = ast_channel_snapshot_get_latest(rtp->channel_uniqueid);
3657  }
3658  if (blob) {
3659  payload->blob = blob;
3660  ast_json_ref(blob);
3661  }
3662  ao2_ref(report, +1);
3663  payload->report = report;
3664 
3665  message = stasis_message_create(message_type, payload);
3666  if (!message) {
3667  return;
3668  }
3669 
3671 }
3672 
3673 /*!
3674  * @{ \brief Define RTCP/RTP message types.
3675  */
3677  .to_ami = rtcp_report_to_ami,
3678  .to_json = rtcp_report_to_json,);
3680  .to_ami = rtcp_report_to_ami,
3681  .to_json = rtcp_report_to_json,);
3682 /*! @} */
3683 
3685 {
3686  return rtp_topic;
3687 }
3688 
3689 static uintmax_t debug_category_rtp_id;
3690 
3691 uintmax_t ast_debug_category_rtp_id(void)
3692 {
3693  return debug_category_rtp_id;
3694 }
3695 
3696 static uintmax_t debug_category_rtp_packet_id;
3697 
3698 uintmax_t ast_debug_category_rtp_packet_id(void)
3699 {
3700  return debug_category_rtp_packet_id;
3701 }
3702 
3703 static uintmax_t debug_category_rtcp_id;
3704 
3705 uintmax_t ast_debug_category_rtcp_id(void)
3706 {
3707  return debug_category_rtcp_id;
3708 }
3709 
3710 static uintmax_t debug_category_rtcp_packet_id;
3711 
3712 uintmax_t ast_debug_category_rtcp_packet_id(void)
3713 {
3714  return debug_category_rtcp_packet_id;
3715 }
3716 
3717 static uintmax_t debug_category_dtls_id;
3718 
3719 uintmax_t ast_debug_category_dtls_id(void)
3720 {
3721  return debug_category_dtls_id;
3722 }
3723 
3724 static uintmax_t debug_category_dtls_packet_id;
3725 
3726 uintmax_t ast_debug_category_dtls_packet_id(void)
3727 {
3728  return debug_category_dtls_packet_id;
3729 }
3730 
3731 static uintmax_t debug_category_ice_id;
3732 
3733 uintmax_t ast_debug_category_ice_id(void)
3734 {
3735  return debug_category_ice_id;
3736 }
3737 
3738 /*!
3739  * \internal
3740  * \brief Shutdown the RTP engine
3741  * This function will not get called if any module fails to unload.
3742  */
3743 static void rtp_engine_shutdown(void)
3744 {
3745  int x;
3746 
3747  ao2_cleanup(rtp_topic);
3748  rtp_topic = NULL;
3751 
3752  ast_rwlock_wrlock(&static_RTP_PT_lock);
3753  for (x = 0; x < AST_RTP_MAX_PT; x++) {
3754  ao2_cleanup(static_RTP_PT[x]);
3755  static_RTP_PT[x] = NULL;
3756  }
3757  ast_rwlock_unlock(&static_RTP_PT_lock);
3758 
3759  ast_rwlock_wrlock(&mime_types_lock);
3760  for (x = 0; x < mime_types_len; x++) {
3761  if (ast_rtp_mime_types[x].payload_type.format) {
3762  rtp_engine_mime_type_cleanup(x);
3763  }
3764  }
3765  mime_types_len = 0;
3766  ast_rwlock_unlock(&mime_types_lock);
3767 }
3768 
3769 /*!
3770  * \internal
3771  * \brief Unregister the debug categories
3772  * This function will always get called even if any module fails to unload.
3773  */
3774 static void rtp_engine_atexit(void)
3775 {
3776  ast_debug_category_unregister(AST_LOG_CATEGORY_ICE);
3777 
3778  ast_debug_category_unregister(AST_LOG_CATEGORY_DTLS_PACKET);
3779  ast_debug_category_unregister(AST_LOG_CATEGORY_DTLS);
3780 
3781  ast_debug_category_unregister(AST_LOG_CATEGORY_RTCP_PACKET);
3782  ast_debug_category_unregister(AST_LOG_CATEGORY_RTCP);
3783 
3784  ast_debug_category_unregister(AST_LOG_CATEGORY_RTP_PACKET);
3785  ast_debug_category_unregister(AST_LOG_CATEGORY_RTP);
3786 }
3787 
3789 {
3790  ast_rwlock_init(&mime_types_lock);
3791  ast_rwlock_init(&static_RTP_PT_lock);
3792 
3793  rtp_topic = stasis_topic_create("rtp:all");
3794  if (!rtp_topic) {
3795  return -1;
3796  }
3799  ast_register_cleanup(rtp_engine_shutdown);
3800 
3801  /* Define all the RTP mime types available */
3802  set_next_mime_type(ast_format_g723, 0, "audio", "G723", 8000);
3803  set_next_mime_type(ast_format_gsm, 0, "audio", "GSM", 8000);
3804  set_next_mime_type(ast_format_ulaw, 0, "audio", "PCMU", 8000);
3805  set_next_mime_type(ast_format_ulaw, 0, "audio", "G711U", 8000);
3806  set_next_mime_type(ast_format_alaw, 0, "audio", "PCMA", 8000);
3807  set_next_mime_type(ast_format_alaw, 0, "audio", "G711A", 8000);
3808  set_next_mime_type(ast_format_g726, 0, "audio", "G726-32", 8000);
3809  set_next_mime_type(ast_format_adpcm, 0, "audio", "DVI4", 8000);
3810  set_next_mime_type(ast_format_slin, 0, "audio", "L16", 8000);
3811  set_next_mime_type(ast_format_slin16, 0, "audio", "L16", 16000);
3812  set_next_mime_type(ast_format_slin16, 0, "audio", "L16-256", 16000);
3813  set_next_mime_type(ast_format_slin12, 0, "audio", "L16", 12000);
3814  set_next_mime_type(ast_format_slin24, 0, "audio", "L16", 24000);
3815  set_next_mime_type(ast_format_slin32, 0, "audio", "L16", 32000);
3816  set_next_mime_type(ast_format_slin44, 0, "audio", "L16", 44100);
3817  set_next_mime_type(ast_format_slin48, 0, "audio", "L16", 48000);
3818  set_next_mime_type(ast_format_slin96, 0, "audio", "L16", 96000);
3819  set_next_mime_type(ast_format_slin192, 0, "audio", "L16", 192000);
3820  set_next_mime_type(ast_format_lpc10, 0, "audio", "LPC", 8000);
3821  set_next_mime_type(ast_format_g729, 0, "audio", "G729", 8000);
3822  set_next_mime_type(ast_format_g729, 0, "audio", "G729A", 8000);
3823  set_next_mime_type(ast_format_g729, 0, "audio", "G.729", 8000);
3824  set_next_mime_type(ast_format_speex, 0, "audio", "speex", 8000);
3825  set_next_mime_type(ast_format_speex16, 0, "audio", "speex", 16000);
3826  set_next_mime_type(ast_format_speex32, 0, "audio", "speex", 32000);
3827  set_next_mime_type(ast_format_ilbc, 0, "audio", "iLBC", 8000);
3828  /* this is the sample rate listed in the RTP profile for the G.722 codec, *NOT* the actual sample rate of the media stream */
3829  set_next_mime_type(ast_format_g722, 0, "audio", "G722", 8000);
3830  set_next_mime_type(ast_format_g726_aal2, 0, "audio", "AAL2-G726-32", 8000);
3831  /* we need all possible dtmf/bitrate combinations or ast_rtp_codecs_payloads_set_rtpmap_type_rate will not examine it */
3832  set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 8000);
3833  set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 16000);
3834  set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 24000);
3835  set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 32000);
3836  set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 48000);
3837  set_next_mime_type(NULL, AST_RTP_CISCO_DTMF, "audio", "cisco-telephone-event", 8000);
3838  set_next_mime_type(NULL, AST_RTP_CN, "audio", "CN", 8000);
3839  set_next_mime_type(ast_format_jpeg, 0, "video", "JPEG", 90000);
3840  set_next_mime_type(ast_format_png, 0, "video", "PNG", 90000);
3841  set_next_mime_type(ast_format_h261, 0, "video", "H261", 90000);
3842  set_next_mime_type(ast_format_h263, 0, "video", "H263", 90000);
3843  set_next_mime_type(ast_format_h263p, 0, "video", "h263-1998", 90000);
3844  set_next_mime_type(ast_format_h264, 0, "video", "H264", 90000);
3845  set_next_mime_type(ast_format_h265, 0, "video", "H265", 90000);
3846  set_next_mime_type(ast_format_mp4, 0, "video", "MP4V-ES", 90000);
3847  set_next_mime_type(ast_format_t140_red, 0, "text", "RED", 1000);
3848  set_next_mime_type(ast_format_t140, 0, "text", "T140", 1000);
3849  set_next_mime_type(ast_format_siren7, 0, "audio", "G7221", 16000);
3850  set_next_mime_type(ast_format_siren14, 0, "audio", "G7221", 32000);
3851  set_next_mime_type(ast_format_g719, 0, "audio", "G719", 48000);
3852  /* Opus, VP8, and VP9 */
3853  set_next_mime_type(ast_format_opus, 0, "audio", "opus", 48000);
3854  set_next_mime_type(ast_format_vp8, 0, "video", "VP8", 90000);
3855  set_next_mime_type(ast_format_vp9, 0, "video", "VP9", 90000);
3856 
3857  /* Define the static rtp payload mappings */
3858  add_static_payload(0, ast_format_ulaw, 0);
3859  #ifdef USE_DEPRECATED_G726
3860  add_static_payload(2, ast_format_g726, 0);/* Technically this is G.721, but if Cisco can do it, so can we... */
3861  #endif
3862  add_static_payload(3, ast_format_gsm, 0);
3863  add_static_payload(4, ast_format_g723, 0);
3864  add_static_payload(5, ast_format_adpcm, 0);/* 8 kHz */
3865  add_static_payload(6, ast_format_adpcm, 0); /* 16 kHz */
3866  add_static_payload(7, ast_format_lpc10, 0);
3867  add_static_payload(8, ast_format_alaw, 0);
3868  add_static_payload(9, ast_format_g722, 0);
3869  add_static_payload(10, ast_format_slin, 0); /* 2 channels */
3870  add_static_payload(11, ast_format_slin, 0); /* 1 channel */
3871  add_static_payload(13, NULL, AST_RTP_CN);
3872  add_static_payload(16, ast_format_adpcm, 0); /* 11.025 kHz */
3873  add_static_payload(17, ast_format_adpcm, 0); /* 22.050 kHz */
3874  add_static_payload(18, ast_format_g729, 0);
3875  add_static_payload(19, NULL, AST_RTP_CN); /* Also used for CN */
3876  add_static_payload(26, ast_format_jpeg, 0);
3877  add_static_payload(31, ast_format_h261, 0);
3878  add_static_payload(34, ast_format_h263, 0);
3879 
3880  /*
3881  * Dynamic payload types - Even when dynamically assigning them we'll fall
3882  * back to using the statically declared values as the default number.
3883  */
3884  add_static_payload(96, ast_format_slin192, 0);
3885  add_static_payload(97, ast_format_ilbc, 0);
3886 
3887  add_static_payload(99, ast_format_h264, 0);
3888  add_static_payload(100, ast_format_vp8, 0);
3889  add_static_payload(101, NULL, AST_RTP_DTMF);
3890  add_static_payload(102, ast_format_siren7, 0);
3891  add_static_payload(103, ast_format_h263p, 0);
3892  add_static_payload(104, ast_format_mp4, 0);
3893  add_static_payload(105, ast_format_t140_red, 0); /* Real time text chat (with redundancy encoding) */
3894  add_static_payload(106, ast_format_t140, 0); /* Real time text chat */
3895  add_static_payload(107, ast_format_opus, 0);
3896  add_static_payload(108, ast_format_vp9, 0);
3897  add_static_payload(109, ast_format_h265, 0);
3898 
3899  add_static_payload(110, ast_format_speex, 0);
3900  add_static_payload(111, ast_format_g726, 0);
3901  add_static_payload(112, ast_format_g726_aal2, 0);
3902 
3903  add_static_payload(115, ast_format_siren14, 0);
3904  add_static_payload(116, ast_format_g719, 0);
3905  add_static_payload(117, ast_format_speex16, 0);
3906  add_static_payload(118, ast_format_slin16, 0); /* 16 Khz signed linear */
3907  add_static_payload(119, ast_format_speex32, 0);
3908 
3909  add_static_payload(121, NULL, AST_RTP_CISCO_DTMF); /* Must be type 121 */
3910  add_static_payload(122, ast_format_slin12, 0);
3911  add_static_payload(123, ast_format_slin24, 0);
3912  add_static_payload(124, ast_format_slin32, 0);
3913  add_static_payload(125, ast_format_slin44, 0);
3914  add_static_payload(126, ast_format_slin48, 0);
3915  add_static_payload(127, ast_format_slin96, 0);
3916  /* payload types above 127 are not valid */
3917 
3918  debug_category_rtp_id = ast_debug_category_register(AST_LOG_CATEGORY_RTP);
3919  debug_category_rtp_packet_id = ast_debug_category_register(AST_LOG_CATEGORY_RTP_PACKET);
3920  debug_category_rtcp_id = ast_debug_category_register(AST_LOG_CATEGORY_RTCP);
3921  debug_category_rtcp_packet_id = ast_debug_category_register(AST_LOG_CATEGORY_RTCP_PACKET);
3922  debug_category_dtls_id = ast_debug_category_register(AST_LOG_CATEGORY_DTLS);
3923  debug_category_dtls_packet_id = ast_debug_category_register(AST_LOG_CATEGORY_DTLS_PACKET);
3924  debug_category_ice_id = ast_debug_category_register(AST_LOG_CATEGORY_ICE);
3925 
3926  /*
3927  * Normnally a core module should call ast_register_cleanup,
3928  * which doesn't run if any module fails to unload. This
3929  * prevents resources being pulled out from under a running
3930  * module and possibly causing a segfault. In this case however,
3931  * the only thing we're cleaning up are the registrations of the
3932  * debug categories.
3933  */
3934  ast_register_atexit(rtp_engine_atexit);
3935 
3936  return 0;
3937 }
3938 
3940 {
3941  return rtp->last_tx;
3942 }
3943 
3944 void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
3945 {
3946  rtp->last_tx = time;
3947 }
3948 
3950 {
3951  return rtp->last_rx;
3952 }
3953 
3954 void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time)
3955 {
3956  rtp->last_rx = time;
3957 }
3958 
3960 {
3961  unsigned int ssrc = 0;
3962 
3963  ao2_lock(rtp);
3964  if (rtp->engine->ssrc_get) {
3965  ssrc = rtp->engine->ssrc_get(rtp);
3966  }
3967  ao2_unlock(rtp);
3968 
3969  return ssrc;
3970 }
3971 
3973 {
3974  const char *cname = "";
3975 
3976  ao2_lock(rtp);
3977  if (rtp->engine->cname_get) {
3978  cname = rtp->engine->cname_get(rtp);
3979  }
3980  ao2_unlock(rtp);
3981 
3982  return cname;
3983 }
3984 
3986 {
3987  int res = -1;
3988 
3989  if (parent && (child->engine != parent->engine)) {
3990  return -1;
3991  }
3992 
3993  ao2_lock(child);
3994  if (child->engine->bundle) {
3995  res = child->engine->bundle(child, parent);
3996  }
3997  ao2_unlock(child);
3998 
3999  return res;
4000 }
4001 
4002 void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc)
4003 {
4004  ao2_lock(rtp);
4005  if (rtp->engine->set_remote_ssrc) {
4006  rtp->engine->set_remote_ssrc(rtp, ssrc);
4007  }
4008  ao2_unlock(rtp);
4009 }
4010 
4011 void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *rtp, int stream_num)
4012 {
4013  ao2_lock(rtp);
4014  if (rtp->engine->set_stream_num) {
4015  rtp->engine->set_stream_num(rtp, stream_num);
4016  }
4017  ao2_unlock(rtp);
4018 }
4019 
4020 #ifdef TEST_FRAMEWORK
4021 size_t ast_rtp_instance_get_recv_buffer_max(struct ast_rtp_instance *instance)
4022 {
4023  size_t res;
4024  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4025 
4026  if (!test) {
4027  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4028  return 0;
4029  }
4030 
4031  ao2_lock(instance);
4032  res = test->recv_buffer_max(instance);
4033  ao2_unlock(instance);
4034 
4035  return res;
4036 }
4037 
4038 size_t ast_rtp_instance_get_recv_buffer_count(struct ast_rtp_instance *instance)
4039 {
4040  size_t res;
4041  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4042 
4043  if (!test) {
4044  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4045  return 0;
4046  }
4047 
4048  ao2_lock(instance);
4049  res = test->recv_buffer_count(instance);
4050  ao2_unlock(instance);
4051 
4052  return res;
4053 }
4054 
4055 size_t ast_rtp_instance_get_send_buffer_count(struct ast_rtp_instance *instance)
4056 {
4057  size_t res;
4058  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4059 
4060  if (!test) {
4061  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4062  return 0;
4063  }
4064 
4065  ao2_lock(instance);
4066  res = test->send_buffer_count(instance);
4067  ao2_unlock(instance);
4068 
4069  return res;
4070 }
4071 
4072 void ast_rtp_instance_set_schedid(struct ast_rtp_instance *instance, int id)
4073 {
4074  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4075 
4076  if (!test) {
4077  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4078  return;
4079  }
4080 
4081  ao2_lock(instance);
4082  test->set_schedid(instance, id);
4083  ao2_unlock(instance);
4084 }
4085 
4086 void ast_rtp_instance_drop_packets(struct ast_rtp_instance *instance, int num)
4087 {
4088  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4089 
4090  if (!test) {
4091  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4092  return;
4093  }
4094 
4095  test->packets_to_drop = num;
4096 }
4097 
4098 void ast_rtp_instance_queue_report(struct ast_rtp_instance *instance)
4099 {
4100  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4101 
4102  if (!test) {
4103  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4104  return;
4105  }
4106 
4107  test->send_report = 1;
4108 }
4109 
4110 int ast_rtp_instance_get_sdes_received(struct ast_rtp_instance *instance)
4111 {
4112  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4113 
4114  if (!test) {
4115  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4116  return 0;
4117  }
4118 
4119  return test->sdes_received;
4120 }
4121 
4122 void ast_rtp_instance_reset_test_engine(struct ast_rtp_instance *instance)
4123 {
4124  struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
4125 
4126  if (!test) {
4127  ast_log(LOG_ERROR, "There is no test engine set up!\n");
4128  return;
4129  }
4130 
4131  test->packets_to_drop = 0;
4132  test->send_report = 0;
4133  test->sdes_received = 0;
4134 }
4135 #endif
4136 
4138 {
4139  struct ast_json *j_res;
4140  int ret;
4141 
4142  j_res = ast_json_object_create();
4143  if (!j_res) {
4144  return NULL;
4145  }
4146 
4147  /* set mandatory items */
4148  ret = ast_json_object_set(j_res, "txcount", ast_json_integer_create(stats->txcount));
4149  ret |= ast_json_object_set(j_res, "rxcount", ast_json_integer_create(stats->rxcount));
4150 
4151  ret |= ast_json_object_set(j_res, "txploss", ast_json_integer_create(stats->txploss));
4152  ret |= ast_json_object_set(j_res, "rxploss", ast_json_integer_create(stats->rxploss));
4153 
4154  ret |= ast_json_object_set(j_res, "local_ssrc", ast_json_integer_create(stats->local_ssrc));
4155  ret |= ast_json_object_set(j_res, "remote_ssrc", ast_json_integer_create(stats->remote_ssrc));
4156 
4157  ret |= ast_json_object_set(j_res, "txoctetcount", ast_json_integer_create(stats->txoctetcount));
4158  ret |= ast_json_object_set(j_res, "rxoctetcount", ast_json_integer_create(stats->rxoctetcount));
4159 
4160  ret |= ast_json_object_set(j_res, "channel_uniqueid", ast_json_string_create(stats->channel_uniqueid));
4161  if (ret) {
4162  ast_log(LOG_WARNING, "Could not create rtp statistics info. channel: %s\n", stats->channel_uniqueid);
4163  ast_json_unref(j_res);
4164  return NULL;
4165  }
4166 
4167  /* set other items */
4168  SET_AST_JSON_OBJ(j_res, "txjitter", ast_json_real_create(stats->txjitter));
4169  SET_AST_JSON_OBJ(j_res, "rxjitter", ast_json_real_create(stats->rxjitter));
4170 
4171  SET_AST_JSON_OBJ(j_res, "remote_maxjitter", ast_json_real_create(stats->remote_maxjitter));
4172  SET_AST_JSON_OBJ(j_res, "remote_minjitter", ast_json_real_create(stats->remote_minjitter));
4173  SET_AST_JSON_OBJ(j_res, "remote_normdevjitter", ast_json_real_create(stats->remote_normdevjitter));
4174  SET_AST_JSON_OBJ(j_res, "remote_stdevjitter", ast_json_real_create(stats->remote_stdevjitter));
4175 
4176  SET_AST_JSON_OBJ(j_res, "local_maxjitter", ast_json_real_create(stats->local_maxjitter));
4177  SET_AST_JSON_OBJ(j_res, "local_minjitter", ast_json_real_create(stats->local_minjitter));
4178  SET_AST_JSON_OBJ(j_res, "local_normdevjitter", ast_json_real_create(stats->local_normdevjitter));
4179  SET_AST_JSON_OBJ(j_res, "local_stdevjitter", ast_json_real_create(stats->local_stdevjitter));
4180 
4181  SET_AST_JSON_OBJ(j_res, "remote_maxrxploss", ast_json_real_create(stats->remote_maxrxploss));
4182  SET_AST_JSON_OBJ(j_res, "remote_minrxploss", ast_json_real_create(stats->remote_minrxploss));
4183  SET_AST_JSON_OBJ(j_res, "remote_normdevrxploss", ast_json_real_create(stats->remote_normdevrxploss));
4184  SET_AST_JSON_OBJ(j_res, "remote_stdevrxploss", ast_json_real_create(stats->remote_stdevrxploss));
4185 
4186  SET_AST_JSON_OBJ(j_res, "local_maxrxploss", ast_json_real_create(stats->local_maxrxploss));
4187  SET_AST_JSON_OBJ(j_res, "local_minrxploss", ast_json_real_create(stats->local_minrxploss));
4188  SET_AST_JSON_OBJ(j_res, "local_normdevrxploss", ast_json_real_create(stats->local_normdevrxploss));
4189  SET_AST_JSON_OBJ(j_res, "local_stdevrxploss", ast_json_real_create(stats->local_stdevrxploss));
4190 
4191  SET_AST_JSON_OBJ(j_res, "rtt", ast_json_real_create(stats->rtt));
4192  SET_AST_JSON_OBJ(j_res, "maxrtt", ast_json_real_create(stats->maxrtt));
4193  SET_AST_JSON_OBJ(j_res, "minrtt", ast_json_real_create(stats->minrtt));
4194  SET_AST_JSON_OBJ(j_res, "normdevrtt", ast_json_real_create(stats->normdevrtt));
4195  SET_AST_JSON_OBJ(j_res, "stdevrtt", ast_json_real_create(stats->stdevrtt));
4196 
4197  SET_AST_JSON_OBJ(j_res, "txmes", ast_json_integer_create(stats->txmes));
4198  SET_AST_JSON_OBJ(j_res, "rxmes", ast_json_integer_create(stats->rxmes));
4199 
4200  SET_AST_JSON_OBJ(j_res, "remote_maxmes", ast_json_real_create(stats->remote_maxmes));
4201  SET_AST_JSON_OBJ(j_res, "remote_minmes", ast_json_real_create(stats->remote_minmes));
4202  SET_AST_JSON_OBJ(j_res, "remote_normdevmes", ast_json_real_create(stats->remote_normdevmes));
4203  SET_AST_JSON_OBJ(j_res, "remote_stdevmes", ast_json_real_create(stats->remote_stdevmes));
4204 
4205  SET_AST_JSON_OBJ(j_res, "local_maxmes", ast_json_real_create(stats->local_maxmes));
4206  SET_AST_JSON_OBJ(j_res, "local_minmes", ast_json_real_create(stats->local_minmes));
4207  SET_AST_JSON_OBJ(j_res, "local_normdevmes", ast_json_real_create(stats->local_normdevmes));
4208  SET_AST_JSON_OBJ(j_res, "local_stdevmes", ast_json_real_create(stats->local_stdevmes));
4209 
4210  return j_res;
4211 }
4212 
4214 {
4215  struct ast_rtp_instance_stats stats = {0,};
4216 
4217  if(ast_rtp_instance_get_stats(instance, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
4218  return NULL;
4219  }
4220 
4221  return ast_rtp_convert_stats_json(&stats);
4222 }
4223 
4224 int ast_rtp_get_rate(const struct ast_format *format)
4225 {
4226  /* For those wondering: due to a fluke in RFC publication, G.722 is advertised
4227  * as having a sample rate of 8kHz, while implementations must know that its
4228  * real rate is 16kHz. Seriously.
4229  */
4230  return (ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL) ? 8000 : (int)ast_format_get_sample_rate(format);
4231 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
struct stasis_message_type * ast_rtp_rtcp_sent_type(void)
Message type for an RTCP message sent from this Asterisk instance.
int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, struct ast_format *format)
Tell underlying RTP engine that audio frames will be provided in a specific format.
Definition: rtp_engine.c:2722
struct ast_format * ast_format_vp8
Built-in cached vp8 format.
Definition: format_cache.c:191
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:3039
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:2920
int(* activate)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:724
struct ast_format * ast_format_g726
Built-in cached g726 format.
Definition: format_cache.c:111
Struct containing info for an AMI event to send out.
Definition: manager.h:502
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:361
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:980
void ast_rtp_instance_extmap_clear(struct ast_rtp_instance *instance)
Clear negotiated RTP extension information.
Definition: rtp_engine.c:884
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:364
Main Channel structure associated with a channel.
char type[16]
The media type.
Definition: rtp_engine.c:254
int(* bundle)(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
Definition: rtp_engine.h:736
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:2556
struct ast_format * ast_format_g723
Built-in cached g723.1 format.
Definition: format_cache.c:146
struct ast_format * ast_format_siren14
Built-in cached siren14 format.
Definition: format_cache.c:211
void(* prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Definition: rtp_engine.h:692
void(* payload_set)(struct ast_rtp_instance *instance, int payload, int asterisk_format, struct ast_format *format, int code)
Definition: rtp_engine.h:694
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int interval)
Set the RTP keepalive interval.
Definition: rtp_engine.c:2828
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
static void unref_instance_cond(struct ast_rtp_instance **instance)
Conditionally unref an rtp instance.
Definition: rtp_engine.c:2350
ast_rtp_options
Definition: rtp_engine.h:145
int(* set_configuration)(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
Definition: rtp_engine.h:623
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
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 tx payload type to a known MIME media type for a codec with a specific sample rate...
Definition: rtp_engine.c:1383
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
Definition: rtp_engine.c:1629
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:2639
unsigned int framing
Definition: rtp_engine.h:764
struct ast_format * ast_format_slin192
Built-in cached signed linear 192kHz format.
Definition: format_cache.c:81
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_format * ast_format_mp4
Built-in cached mp4 format.
Definition: format_cache.c:186
int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format)
Set a payload code for use with a specific Asterisk format.
Definition: rtp_engine.c:2033
int(* set_write_format)(struct ast_rtp_instance *instance, struct ast_format *format)
Definition: rtp_engine.h:718
struct ast_format * ast_format_t140_red
Built-in cached t140 red format.
Definition: format_cache.c:236
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:2848
void *(* extended_prop_get)(struct ast_rtp_instance *instance, int property)
Definition: rtp_engine.h:690
String manipulation functions.
int ast_rtp_engine_unload_format(struct ast_format *format)
Formats requiring the use of a format attribute interface must have that interface registered in orde...
Definition: rtp_engine.c:3393
enum ast_rtp_dtmf_mode(* dtmf_mode_get)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:700
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:548
const char *(* get_fingerprint)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:641
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:2588
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code...
Definition: rtp_engine.c:2094
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1640
int(* sendcng)(struct ast_rtp_instance *instance, int level)
Definition: rtp_engine.h:730
char subtype[64]
The format type.
Definition: rtp_engine.c:256
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 tx payload type information that was seen in an a=rtpmap: SDP line.
Definition: rtp_engine.c:1469
int(* write)(struct ast_rtp_instance *instance, struct ast_frame *frame)
Definition: rtp_engine.h:675
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
Support for translation of data formats. translate.c.
enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs)
Determine the type of RTP stream media from the codecs mapped.
Definition: rtp_engine.c:1514
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:167
int ast_rtp_engine_init(void)
initializes the rtp engine arrays
Definition: rtp_engine.c:3788
Time-related functions and macros.
struct ast_rtp_instance::@388 extmap_enabled
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
const char * ast_format_get_codec_name(const struct ast_format *format)
Get the codec name associated with a format.
Definition: format.c:339
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:2375
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
struct ast_format * ast_format_slin32
Built-in cached signed linear 32kHz format.
Definition: format_cache.c:61
const char * ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp)
Retrieve the CNAME used in RTCP SDES items.
Definition: rtp_engine.c:3972
struct ast_format * ast_format_slin96
Built-in cached signed linear 96kHz format.
Definition: format_cache.c:76
struct ast_frame *(* read)(struct ast_rtp_instance *instance, int rtcp)
Definition: rtp_engine.h:712
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
enum ast_rtp_extension ast_rtp_instance_extmap_get_extension(struct ast_rtp_instance *instance, int id)
Retrieve the extension for an RTP extension id.
Definition: rtp_engine.c:932
#define AST_RTP_PT_LAST_STATIC
Definition: rtp_engine.h:89
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: utils.c:3107
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
Register an RTP engine.
Definition: rtp_engine.c:330
int ast_rtp_codecs_payload_code_tx_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code, unsigned int sample_rate)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code...
Definition: rtp_engine.c:2043
struct ast_format * ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload)
Retrieve the actual ast_format stored on the codecs structure for a specific tx payload type...
Definition: rtp_engine.c:1608
unsigned int txcount
Definition: rtp_engine.h:398
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
Definition: rtp_engine.c:2307
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:677
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:348
void ast_rtp_instance_get_incoming_source_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the incoming source address of the remote endpoint.
Definition: rtp_engine.c:687
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:2116
Structure representing a snapshot of channel state.
int(* dtmf_end)(struct ast_rtp_instance *instance, char digit)
Definition: rtp_engine.h:681
struct ast_format * ast_format_jpeg
Built-in cached jpeg format.
Definition: format_cache.c:201
unsigned int ast_rtp_instance_get_ssrc(struct ast_rtp_instance *rtp)
Retrieve the local SSRC value that we will be using.
Definition: rtp_engine.c:3959
struct ast_format * ast_format_g726_aal2
Built-in cached g726 aal2 format.
Definition: format_cache.c:116
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:2358
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
static enum ast_rtp_extension_direction rtp_extmap_negotiate_direction(enum ast_rtp_extension_direction ours, enum ast_rtp_extension_direction theirs)
Helper function which negotiates two RTP extension directions to get our current direction.
Definition: rtp_engine.c:812
struct ast_rtp_rtcp_report_block * report_block[0]
Definition: rtp_engine.h:374
Definition: sched.c:76
unsigned int rxploss
Definition: rtp_engine.h:424
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
Retrieve all formats that were found.
Definition: rtp_engine.c:1651
int(* update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active)
Definition: rtp_engine.h:809
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
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:738
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
Codec API.
const char *(* cname_get)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:734
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:2261
void(* change_source)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:686
void(* change_components)(struct ast_rtp_instance *instance, int num_components)
Definition: rtp_engine.h:560
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:540
Definition of a media format.
Definition: format.c:43
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:1139
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:651
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:627
struct ast_rtp_codecs::@280 payload_mapping_rx
unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, const struct ast_format *format, int code)
Get the sample rate associated with known RTP payload types.
Definition: rtp_engine.c:2146
int ast_rtp_engine_load_format(struct ast_format *format)
Custom formats declared in codecs.conf at startup must be communicated to the rtp_engine so their mim...
Definition: rtp_engine.c:3377
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
ast_rtp_extension
Known RTP extensions.
Definition: rtp_engine.h:593
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
A report block within a SR/RR report.
Definition: rtp_engine.h:346
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:727
struct ast_rtp_payload_type * ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
Retrieve rx payload mapped information by payload type.
Definition: rtp_engine.c:1533
struct ast_format * ast_format_slin24
Built-in cached signed linear 24kHz format.
Definition: format_cache.c:56
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
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:2823
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:544
#define AST_RTP_PT_FIRST_DYNAMIC
Definition: rtp_engine.h:92
void ast_format_cap_set_framing(struct ast_format_cap *cap, unsigned int framing)
Set the global framing.
Definition: format_cap.c:136
void(* update_source)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:684
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:2316
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
ast_rwlock_t codecs_lock
Definition: rtp_engine.h:758
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:106
void ast_rtp_dtls_cfg_copy(const struct ast_rtp_dtls_cfg *src_cfg, struct ast_rtp_dtls_cfg *dst_cfg)
Copy contents of a DTLS configuration structure.
Definition: rtp_engine.c:3261
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition: rtp_engine.c:575
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:487
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:720
Structure for an ICE candidate.
Definition: rtp_engine.h:525
unsigned int sample_rate
Expected sample rate of the /c subtype.
Definition: rtp_engine.c:258
Socket address structure.
Definition: netsock2.h:97
void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
Destroy the contents of an RTP codecs structure (but not the structure itself)
Definition: rtp_engine.c:996
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:665
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
enum ast_rtp_dtls_hash(* get_fingerprint_hash)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:639
const char * type
Definition: rtp_engine.h:775
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10563
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:2570
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
Definition: rtp_engine.c:4224
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
enum ast_rtp_dtls_setup(* get_setup)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:633
struct stasis_message_type * ast_rtp_rtcp_received_type(void)
Message type for an RTCP message received from some external source.
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
Get the last RTP transmission time.
Definition: rtp_engine.c:3939
void(* remote_address_set)(struct ast_rtp_instance *instance, struct ast_sockaddr *sa)
Definition: rtp_engine.h:696
void(* turn_request)(struct ast_rtp_instance *instance, enum ast_rtp_ice_component_type component, enum ast_transport transport, const char *server, unsigned int port, const char *username, const char *password)
Definition: rtp_engine.h:556
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
Find available formats.
Definition: translate.c:1616
Utility functions.
Media Format API.
struct ast_format * ast_format_h261
Built-in cached h261 format.
Definition: format_cache.c:161
struct ast_format * ast_format_g719
Built-in cached g719 format.
Definition: format_cache.c:156
struct ast_rtp_engine_dtls * ast_rtp_instance_get_dtls(struct ast_rtp_instance *instance)
Obtain a pointer to the DTLS support present on an RTP instance.
Definition: rtp_engine.c:3159
enum ast_rtp_extension_direction ast_rtp_instance_extmap_get_direction(struct ast_rtp_instance *instance, int id)
Retrieve the negotiated direction for an RTP extension id.
Definition: rtp_engine.c:952
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
Get the RTP timeout value.
Definition: rtp_engine.c:2833
#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:333
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
struct ast_format * ast_format_h263p
Built-in cached h263 plus format.
Definition: format_cache.c:171
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:600
struct ast_format * ast_format_lpc10
Built-in cached ilbc format.
Definition: format_cache.c:126
int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module)
Register RTP glue.
Definition: rtp_engine.c:379
char * ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *ast_format_capability, int rtp_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:2169
enum ast_rtp_dtls_connection(* get_connection)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:631
struct ast_rtp_instance::@390 extmap_unique_ids
#define AST_RTP_MAX
Definition: rtp_engine.h:300
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:749
int(* destroy)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:673
struct ast_format * ast_format_slin12
Built-in cached signed linear 12kHz format.
Definition: format_cache.c:46
void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg)
Free contents of a DTLS configuration structure.
Definition: rtp_engine.c:3279
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
Definition: rtp_engine.c:2205
struct ast_rtp_payload_type payload_type
A mapping object between the Asterisk codec and this RTP payload.
Definition: rtp_engine.c:252
struct ast_rtp_engine_dtls * dtls
Definition: rtp_engine.h:744
void ast_rtp_instance_get_requested_target_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the requested target address of the remote endpoint.
Definition: rtp_engine.c:695
STASIS_MESSAGE_TYPE_DEFN(ast_rtp_rtcp_sent_type,.to_ami=rtcp_report_to_ami,.to_json=rtcp_report_to_json,)
Define RTCP/RTP message types.
int(* red_buffer)(struct ast_rtp_instance *instance, struct ast_frame *frame)
Definition: rtp_engine.h:710
#define AST_RTP_MAX_PT
Definition: rtp_engine.h:83
struct ast_rtp_codecs::@281 payload_mapping_tx
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
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:2795
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
Get the RTP keepalive interval.
Definition: rtp_engine.c:2843
int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int payload)
Search for the tx payload type in the ast_rtp_codecs structure.
Definition: rtp_engine.c:2099
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:668
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
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:2293
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:782
struct ast_rtp_payload_type * ast_rtp_engine_alloc_payload_type(void)
Allocation routine for ast_rtp_payload_type.
Definition: rtp_engine.c:325
struct ast_format * ast_format_opus
Built-in cached opus format.
Definition: format_cache.c:221
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:590
ast_rtp_instance_stat
Definition: rtp_engine.h:185
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
Maximum number of RTP properties supported.
Definition: rtp_engine.h:141
struct stasis_topic * ast_rtp_topic(void)
Stasis Message Bus API topic for RTP and RTCP related messages
Definition: rtp_engine.c:3684
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void(* available_formats)(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result)
Definition: rtp_engine.h:728
ast_rtp_ice_role
ICE role during negotiation.
Definition: rtp_engine.h:519
void(* set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint)
Definition: rtp_engine.h:637
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ast_rtp_codecs_payload_set_rx_sample_rate(struct ast_rtp_codecs *codecs, int code, struct ast_format *format, unsigned int sample_rate)
Set a payload code with sample rate for use with a specific Asterisk format.
Definition: rtp_engine.c:2038
void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *rtp, int stream_num)
Set the stream number for an RTP instance.
Definition: rtp_engine.c:4011
struct ast_rtp_glue * glue
Definition: rtp_engine.c:212
Scheduler Routines (derived from cheops)
int(* new)(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *sa, void *data)
Definition: rtp_engine.h:671
structure to hold extensions
struct ast_format * ast_format_gsm
Built-in cached gsm format.
Definition: format_cache.c:96
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
char channel_uniqueid[MAX_CHANNEL_ID]
Definition: rtp_engine.h:456
ast_rtp_ice_component_type
ICE component types.
Definition: rtp_engine.h:513
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:712
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
Set the RTP timeout value.
Definition: rtp_engine.c:2818
A set of macros to manage forward-linked lists.
enum ast_rtp_dtls_hash hash
Definition: rtp_engine.h:610
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:2330
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:2275
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
Clear rx and tx payload mapping information from an RTP instance.
Definition: rtp_engine.c:1018
#define ast_debug(level,...)
Log a DEBUG message.
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP transmission time.
Definition: rtp_engine.c:3944
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
struct ast_format * ast_format_speex16
Built-in cached speex at 16kHz format.
Definition: format_cache.c:136
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:617
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:2737
struct ast_format * ast_format_png
Built-in cached png format.
Definition: format_cache.c:206
unsigned int txoctetcount
Definition: rtp_engine.h:458
ast_rtp_glue_result
Definition: rtp_engine.h:161
int ast_rtp_instance_get_and_cmp_requested_target_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the requested target address of the remote endpoint and compare it to the given address...
Definition: rtp_engine.c:673
void(* get_codec)(struct ast_channel *chan, struct ast_format_cap *result_cap)
Callback for retrieving codecs that the channel can do. Result returned in result_cap.
Definition: rtp_engine.h:814
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
Network socket handling.
Core PBX routines and definitions.
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
Structure that represents the optional DTLS SRTP support within an RTP engine.
Definition: rtp_engine.h:621
int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
Request that an RTP instance be bundled with another.
Definition: rtp_engine.c:3985
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:523
unsigned int rxcount
Definition: rtp_engine.h:400
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
Format Capabilities API.
enum ast_rtp_extension_direction direction
Definition: rtp_engine.c:184
struct ast_srtp * srtp
Definition: rtp_engine.c:214
static struct stasis_topic * rtp_topic
Stasis Message Bus API topic for RTP related messages
Definition: rtp_engine.c:277
ast_rtp_dtls_setup
DTLS setup types.
Definition: rtp_engine.h:564
struct ast_sockaddr incoming_source_address
Definition: rtp_engine.c:200
struct ast_module * mod
Definition: rtp_engine.h:669
static force_inline char * ast_str_to_upper(char *str)
Convert a string to all upper-case.
Definition: strings.h:1342
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:546
unsigned int enabled
Definition: rtp_engine.h:606
enum ast_rtp_dtls_setup default_setup
Definition: rtp_engine.h:608
struct ast_json * ast_rtp_instance_get_stats_all_json(struct ast_rtp_instance *instance)
Retrieve statistics about an RTP instance in json format.
Definition: rtp_engine.c:4213
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:538
void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Remove tx payload type mapped information.
Definition: rtp_engine.c:1474
int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
Stop sending a DTMF digit.
Definition: rtp_engine.c:2219
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
int(* dtmf_begin)(struct ast_rtp_instance *instance, char digit)
Definition: rtp_engine.h:679
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:550
Support for dynamic strings.
Definition: strings.h:623
unsigned int rxoctetcount
Definition: rtp_engine.h:460
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
enum ast_rtp_dtls_verify verify
Definition: rtp_engine.h:611
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:408
ast_rtp_extension_direction
Directions for RTP extensions.
Definition: rtp_engine.h:822
void(* set_role)(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
Definition: rtp_engine.h:554
unsigned int local_ssrc
Definition: rtp_engine.h:452
int(* dtmf_mode_set)(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
Definition: rtp_engine.h:698
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct ast_format * ast_format_speex
Built-in cached speex format.
Definition: format_cache.c:131
ast_rtp_dtls_connection
DTLS connection states.
Definition: rtp_engine.h:572
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct ast_rtp_engine_ice * ice
Definition: rtp_engine.h:742
struct ast_format * format
Definition: rtp_engine.h:306
int(* extended_prop_set)(struct ast_rtp_instance *instance, int property, void *value)
Definition: rtp_engine.h:688
unsigned int(* ssrc_get)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:732
int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name, const char *value)
Parse DTLS related configuration options.
Definition: rtp_engine.c:3168
struct ast_module * mod
Definition: rtp_engine.h:777
struct ast_format * ast_format_vp9
Built-in cached vp9 format.
Definition: format_cache.c:196
enum ast_rtp_extension extension
Definition: rtp_engine.c:182
struct ast_format * ast_format_h264
Built-in cached h264 format.
Definition: format_cache.c:176
void(* reset)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:629
void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result)
Request the formats that can be transcoded.
Definition: rtp_engine.c:2781
ast_rtp_dtls_hash
DTLS fingerprint hashes.
Definition: rtp_engine.h:578
struct ast_bridge * bridge
int properties[AST_RTP_PROPERTY_MAX]
Definition: rtp_engine.c:194
#define AST_RTP_CISCO_DTMF
Definition: rtp_engine.h:298
int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
Update the format associated with a tx payload type in a codecs structure.
Definition: rtp_engine.c:1574
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
Retrieve a rx mapped payload type based on whether it is an Asterisk format and the code...
Definition: rtp_engine.c:1977
unsigned int txploss
Definition: rtp_engine.h:422
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:273
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:542
void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc)
Set the remote SSRC for an RTP instance.
Definition: rtp_engine.c:4002
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:2247
struct ast_srtp * rtcp_srtp
Definition: rtp_engine.c:216
void(* set_setup)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
Definition: rtp_engine.h:635
double ast_json_real_get(const struct ast_json *real)
Get the value from a JSON real number.
Definition: json.c:347
Support for logging to various files, console and syslog Configuration in file logger.conf.
Prototypes for public functions only of internal interest,.
int(* qos)(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Definition: rtp_engine.h:704
const char * name
Definition: rtp_engine.h:667
Vector container support.
struct ast_sockaddr local_address
Definition: rtp_engine.c:196
void(* set_remote_ssrc)(struct ast_rtp_instance *instance, unsigned int ssrc)
Definition: rtp_engine.h:738
int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *remote_policy, struct ast_srtp_policy *local_policy, int rtcp)
Add or replace the SRTP policies for the given RTP instance.
Definition: rtp_engine.c:2884
unsigned int ephemeral_cert
Definition: rtp_engine.h:617
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record tx payload type information that was seen in an m= SDP line.
Definition: rtp_engine.c:1341
ast_rtp_dtmf_mode
Definition: rtp_engine.h:151
void(* set_stream_num)(struct ast_rtp_instance *instance, int stream_num)
Definition: rtp_engine.h:740
int ast_rtp_codecs_payload_code_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, unsigned int sample_rate)
Retrieve a rx mapped payload type based on whether it is an Asterisk format, the code and the sample ...
Definition: rtp_engine.c:1982
int ast_rtp_instance_set_incoming_source_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the incoming source address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:628
void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP reception time.
Definition: rtp_engine.c:3954
void(* stun_request)(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
Definition: rtp_engine.h:726
int ast_rtp_instance_set_requested_target_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the requested target address of the remote endpoint.
Definition: rtp_engine.c:638
struct ast_sockaddr requested_target_address
Definition: rtp_engine.c:198
ast_rtp_property
Definition: rtp_engine.h:116
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:703
struct ast_rtp_instance * bridged
Definition: rtp_engine.c:202
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
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...
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
int(* set_read_format)(struct ast_rtp_instance *instance, struct ast_format *format)
Definition: rtp_engine.h:716
struct ast_rtp_rtcp_report * ast_rtp_rtcp_report_alloc(unsigned int report_blocks)
Allocate an ao2 ref counted instance of ast_rtp_rtcp_report.
Definition: rtp_engine.c:3627
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
const char * ast_rtp_instance_get_channel_id(struct ast_rtp_instance *instance)
Get the unique ID of the channel that owns this RTP instance.
Definition: rtp_engine.c:570
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
Definition: json.c:399
struct ast_format * ast_format_h265
Built-in cached h265 format.
Definition: format_cache.c:181
int(* active)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:625
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:610
ast_rtp_instance_stat_field
Definition: rtp_engine.h:171
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
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:2809
struct ast_format * ast_format_siren7
Built-in cached siren7 format.
Definition: format_cache.c:216
char channel_uniqueid[AST_MAX_UNIQUEID]
Definition: rtp_engine.c:218
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
struct ast_json * ast_json_real_create(double value)
Create a JSON real number.
Definition: json.c:342
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:3017
Structure for rwlock and tracking information.
Definition: lock.h:157
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10564
void ast_rtp_codecs_payloads_xover(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Crossover copy the tx payload mapping of src to the rx payload mapping of dest.
Definition: rtp_engine.c:1296
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:2542
#define AST_RTP_RTCP_SR
Definition: rtp_engine.h:323
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
struct ast_rtp_instance::@389 extmap_negotiated
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
unsigned int sample_rate
Definition: rtp_engine.h:318
Data structure associated with a single frame of data.
#define AST_RTP_PT_LAST_REASSIGN
Definition: rtp_engine.h:95
enum ast_srtp_suite suite
Definition: rtp_engine.h:609
struct ast_format * ast_format_adpcm
Built-in cached adpcm format.
Definition: format_cache.c:101
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:536
Abstract JSON element (object, array, string, int, ...).
struct ast_rtp_engine * engine
Definition: rtp_engine.c:190
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:908
struct ast_format * ast_format_slin44
Built-in cached signed linear 44kHz format.
Definition: format_cache.c:66
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
Definition: rtp_engine.c:2911
SRTP resource.
struct ast_json * ast_rtp_convert_stats_json(const struct ast_rtp_instance_stats *stats)
Convert given stat instance into json format.
Definition: rtp_engine.c:4137
Options provided by main asterisk program.
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:580
struct ast_format * ast_format_slin16
Built-in cached signed linear 16kHz format.
Definition: format_cache.c:51
struct ast_format * ast_rtp_codecs_get_preferred_format(struct ast_rtp_codecs *codecs)
Retrieve rx preferred format.
Definition: rtp_engine.c:1557
Definition: search.h:40
int(* red_init)(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
Definition: rtp_engine.h:708
ast_media_type
Types of media.
Definition: codec.h:30
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
struct ast_format * preferred_format
Definition: rtp_engine.h:766
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:2284
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:794
Generic container type.
struct ast_format * ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
This function is used to have a media format aware module parse and interpret SDP attribute informati...
Definition: format.c:286
struct ast_format * ast_format_g729
Built-in cached g729 format.
Definition: format_cache.c:151
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
int ast_rtp_dtls_cfg_validate(struct ast_rtp_dtls_cfg *dtls_cfg)
Validates DTLS related configuration options.
Definition: rtp_engine.c:3242
int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, struct ast_format *format)
Request that the underlying RTP engine provide audio frames in a specific format. ...
Definition: rtp_engine.c:2708
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
unsigned int primary_mapping
Definition: rtp_engine.h:314
struct timeval when_retired
Definition: rtp_engine.h:316
struct ast_format * ast_format_speex32
Built-in cached speex at 32kHz format.
Definition: format_cache.c:141
#define AST_RTP_CN
Definition: rtp_engine.h:296
size_t ast_rtp_instance_extmap_count(struct ast_rtp_instance *instance)
Get the number of known unique identifiers.
Definition: rtp_engine.c:921
time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp)
Get the last RTP reception time.
Definition: rtp_engine.c:3949
#define AST_RTP_DTMF
Definition: rtp_engine.h:294
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:585
Pluggable RTP Architecture.
int ast_rtp_instance_extmap_negotiate(struct ast_rtp_instance *instance, int id, enum ast_rtp_extension_direction direction, const char *uri, const char *attributes)
Negotiate received RTP extension information.
Definition: rtp_engine.c:840
int(* extension_enable)(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Definition: rtp_engine.h:750
struct ast_format * ast_format_t140
Built-in cached t140 format.
Definition: format_cache.c:231
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
unsigned int rekey
Definition: rtp_engine.h:607
#define AST_MAX_UNIQUEID
Definition: channel.h:168
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
void(* destroy)(struct ast_srtp *srtp)
Definition: res_srtp.h:40
void ast_rtp_publish_rtcp_message(struct ast_rtp_instance *rtp, struct stasis_message_type *message_type, struct ast_rtp_rtcp_report *report, struct ast_json *blob)
Publish an RTCP message to Stasis Message Bus API.
Definition: rtp_engine.c:3638
struct ast_format * ast_format_h263
Built-in cached h263 format.
Definition: format_cache.c:166
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:2853
int ast_rtp_codecs_set_preferred_format(struct ast_rtp_codecs *codecs, struct ast_format *format)
Set the preferred format.
Definition: rtp_engine.c:1566
const char * ast_rtp_instance_extmap_get_uri(struct ast_rtp_instance *instance, int id)
Retrieve the URI for an RTP extension id.
Definition: rtp_engine.c:968
static const char *const rtp_extension_uris[AST_RTP_EXTENSION_MAX]
URIs for known RTP extensions.
Definition: rtp_engine.c:234
unsigned int ast_format_get_codec_id(const struct ast_format *format)
Get the codec identifier associated with a format.
Definition: format.c:329
int(* fd)(struct ast_rtp_instance *instance, int rtcp)
Definition: rtp_engine.h:706
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
int ast_rtp_instance_extmap_enable(struct ast_rtp_instance *instance, int id, enum ast_rtp_extension extension, enum ast_rtp_extension_direction direction)
Enable support for an RTP extension on an instance.
Definition: rtp_engine.c:754
struct ast_format * ast_format_slin48
Built-in cached signed linear 48kHz format.
Definition: format_cache.c:71
struct ast_rtp_codecs codecs
Definition: rtp_engine.c:204
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:2461
#define SET_AST_JSON_OBJ(target, name, obj)
Set given json object into target with name.
Definition: rtp_engine.c:287
DTLS configuration structure.
Definition: rtp_engine.h:605
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
unsigned int remote_ssrc
Definition: rtp_engine.h:454
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:2838
int(* get_stat)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Definition: rtp_engine.h:702
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:1262
struct ast_format * ast_format_ilbc
Built-in cached ilbc format.
Definition: format_cache.c:121
int(* create)(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy)
Definition: res_srtp.h:36
void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_rtp_instance *bridged)
Set the other RTP instance that an instance is bridged to.
Definition: rtp_engine.c:2368
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition: json.c:327
void(* ice_lite)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:552
#define AST_MAX_USER_FIELD
Definition: channel.h:174
int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if any joint capabilities exist between two capabilities structures.
Definition: format_cap.c:653