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