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