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