Asterisk - The Open Source Telephony Project GIT-master-0a46be9
Data Structures | Macros | Enumerations | Functions | Variables
res_rtp_asterisk.c File Reference

Supports RTP and RTCP with Symmetric RTP support for NAT traversal. More...

#include "asterisk.h"
#include <arpa/nameser.h>
#include "asterisk/dns_core.h"
#include "asterisk/dns_internal.h"
#include "asterisk/dns_recurring.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <math.h>
#include "asterisk/conversions.h"
#include "asterisk/options.h"
#include "asterisk/logger_category.h"
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/smoother.h"
#include "asterisk/uuid.h"
#include "asterisk/test.h"
#include "asterisk/data_buffer.h"
Include dependency graph for res_rtp_asterisk.c:

Go to the source code of this file.

Data Structures

struct  ast_rtcp
 Structure defining an RTCP session. More...
 
struct  ast_rtp
 RTP session description. More...
 
struct  ast_rtp_rtcp_nack_payload
 Structure for storing RTP packets for retransmission. More...
 
struct  frame_list
 
struct  optional_ts
 
struct  rtp_learning_info
 RTP learning mode tracking information. More...
 
struct  rtp_red
 
struct  rtp_ssrc_mapping
 Structure used for mapping an incoming SSRC to an RTP instance. More...
 
struct  rtp_transport_wide_cc_packet_statistics
 Packet statistics (used for transport-cc) More...
 
struct  rtp_transport_wide_cc_statistics
 Statistics information (used for transport-cc) More...
 

Macros

#define CALC_LEARNING_MIN_DURATION(count)   (((count) - 1) * 9 - 5)
 Calculate the min learning duration in ms. More...
 
#define DEFAULT_DTLS_MTU   1200
 
#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
 
#define DEFAULT_ICESUPPORT   1
 
#define DEFAULT_LEARNING_MIN_DURATION   CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)
 
#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4
 
#define DEFAULT_RTP_END   31000
 
#define DEFAULT_RTP_RECV_BUFFER_SIZE   20
 
#define DEFAULT_RTP_SEND_BUFFER_SIZE   250
 
#define DEFAULT_RTP_START   5000
 
#define DEFAULT_SRTP_REPLAY_PROTECTION   1
 
#define DEFAULT_STRICT_RTP   STRICT_RTP_YES
 
#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE   1
 
#define DEFAULT_TURN_PORT   3478
 
#define FLAG_3389_WARNING   (1 << 0)
 
#define FLAG_DTMF_COMPENSATE   (1 << 4)
 
#define FLAG_NAT_ACTIVE   (3 << 1)
 
#define FLAG_NAT_INACTIVE   (0 << 1)
 
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
 
#define FLAG_NEED_MARKER_BIT   (1 << 3)
 
#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)
 
#define MAX_TIMESTAMP_SKEW   640
 
#define MAXIMUM_RTP_PORT   65535
 
#define MAXIMUM_RTP_RECV_BUFFER_SIZE   (DEFAULT_RTP_RECV_BUFFER_SIZE + 20)
 
#define MAXIMUM_RTP_SEND_BUFFER_SIZE   (DEFAULT_RTP_SEND_BUFFER_SIZE + 200)
 
#define MINIMUM_RTP_PORT   1024
 
#define MISSING_SEQNOS_ADDED_TRIGGER   2
 
#define OLD_PACKET_COUNT   1000
 
#define RESCALE(in, inmin, inmax, outmin, outmax)   ((((in - inmin)/(inmax-inmin))*(outmax-outmin))+outmin)
 
#define RTCP_DEFAULT_INTERVALMS   5000
 
#define RTCP_FB_NACK_BLOCK_WORD_LENGTH   2
 
#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4
 
#define RTCP_HEADER_SSRC_LENGTH   2
 
#define RTCP_LENGTH_MASK   0xFFFF
 
#define RTCP_LENGTH_SHIFT   0
 
#define RTCP_MAX_INTERVALMS   60000
 
#define RTCP_MIN_INTERVALMS   500
 
#define RTCP_PADDING_MASK   0x01
 
#define RTCP_PADDING_SHIFT   29
 
#define RTCP_PAYLOAD_TYPE_MASK   0xFF
 
#define RTCP_PAYLOAD_TYPE_SHIFT   16
 
#define RTCP_PT_APP   204
 
#define RTCP_PT_BYE   203
 
#define RTCP_PT_FUR   192
 
#define RTCP_PT_PSFB   AST_RTP_RTCP_PSFB
 
#define RTCP_PT_RR   AST_RTP_RTCP_RR
 
#define RTCP_PT_SDES   202
 
#define RTCP_PT_SR   AST_RTP_RTCP_SR
 
#define RTCP_REPORT_COUNT_MASK   0x1F
 
#define RTCP_REPORT_COUNT_SHIFT   24
 
#define RTCP_RR_BLOCK_WORD_LENGTH   6
 
#define RTCP_SR_BLOCK_WORD_LENGTH   5
 
#define RTCP_VALID_MASK   (RTCP_VERSION_MASK_SHIFTED | (((RTCP_PAYLOAD_TYPE_MASK & ~0x1)) << RTCP_PAYLOAD_TYPE_SHIFT))
 
#define RTCP_VALID_VALUE   (RTCP_VERSION_SHIFTED | (RTCP_PT_SR << RTCP_PAYLOAD_TYPE_SHIFT))
 
#define RTCP_VERSION   2U
 
#define RTCP_VERSION_MASK   0x03
 
#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)
 
#define RTCP_VERSION_SHIFT   30
 
#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)
 
#define RTP_DTLS_ESTABLISHED   -37
 
#define RTP_IGNORE_FIRST_PACKETS_COUNT   15
 
#define RTP_MTU   1200
 
#define RTP_SEQ_MOD   (1<<16)
 
#define SEQNO_CYCLE_OVER   65536
 
#define SRTP_MASTER_KEY_LEN   16
 
#define SRTP_MASTER_LEN   (SRTP_MASTER_KEY_LEN + SRTP_MASTER_SALT_LEN)
 
#define SRTP_MASTER_SALT_LEN   14
 
#define SSRC_MAPPING_ELEM_CMP(elem, value)   ((elem).instance == (value))
 SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED() More...
 
#define STRICT_RTP_LEARN_TIMEOUT   5000
 Strict RTP learning timeout time in milliseconds. More...
 
#define TRANSPORT_SOCKET_RTCP   1
 
#define TRANSPORT_SOCKET_RTP   0
 
#define TRANSPORT_TURN_RTCP   3
 
#define TRANSPORT_TURN_RTP   2
 
#define TURN_STATE_WAIT_TIME   2000
 
#define ZFONE_PROFILE_ID   0x505a
 

Enumerations

enum  strict_rtp_mode { STRICT_RTP_NO = 0 , STRICT_RTP_YES , STRICT_RTP_SEQNO }
 
enum  strict_rtp_state { STRICT_RTP_OPEN = 0 , STRICT_RTP_LEARN , STRICT_RTP_CLOSED }
 

Functions

static void __reg_module (void)
 
static struct ast_rtp_instance__rtp_find_instance_by_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc, int source)
 
static int __rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
 
static int __rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *via_ice, int use_srtp)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
 
static int ast_rtcp_calculate_sr_rr_statistics (struct ast_rtp_instance *instance, struct ast_rtp_rtcp_report *rtcp_report, struct ast_sockaddr remote_address, int ice, int sr)
 
static int ast_rtcp_generate_compound_prefix (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
 
static int ast_rtcp_generate_nack (struct ast_rtp_instance *instance, unsigned char *rtcpheader)
 
static int ast_rtcp_generate_report (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report, int *sr)
 
static int ast_rtcp_generate_sdes (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report)
 
static struct ast_frameast_rtcp_interpret (struct ast_rtp_instance *instance, struct ast_srtp *srtp, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
 
static struct ast_frameast_rtcp_read (struct ast_rtp_instance *instance)
 
static int ast_rtcp_write (const void *data)
 Write a RTCP packet to the far end. More...
 
static int ast_rtp_bundle (struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
 
static void ast_rtp_change_source (struct ast_rtp_instance *instance)
 
static int ast_rtp_destroy (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_begin (struct ast_rtp_instance *instance, char digit)
 
static int ast_rtp_dtmf_compatible (struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
 
static int ast_rtp_dtmf_continuation (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_end (struct ast_rtp_instance *instance, char digit)
 
static int ast_rtp_dtmf_end_with_duration (struct ast_rtp_instance *instance, char digit, unsigned int duration)
 
static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_mode_set (struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
 
static int ast_rtp_extension_enable (struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
 
static int ast_rtp_fd (struct ast_rtp_instance *instance, int rtcp)
 
static const char * ast_rtp_get_cname (struct ast_rtp_instance *instance)
 
static unsigned int ast_rtp_get_ssrc (struct ast_rtp_instance *instance)
 
static int ast_rtp_get_stat (struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
 
static struct ast_frameast_rtp_interpret (struct ast_rtp_instance *instance, struct ast_srtp *srtp, const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno, unsigned int bundled)
 
static int ast_rtp_local_bridge (struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
 
static int ast_rtp_new (struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
 
static void ast_rtp_prop_set (struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
 
static int ast_rtp_qos_set (struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
 
static struct ast_frameast_rtp_read (struct ast_rtp_instance *instance, int rtcp)
 
static void ast_rtp_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
 
static int ast_rtp_rtcp_handle_nack (struct ast_rtp_instance *instance, unsigned int *nackdata, unsigned int position, unsigned int length)
 
static int ast_rtp_sendcng (struct ast_rtp_instance *instance, int level)
 generate comfort noice (CNG) More...
 
static void ast_rtp_set_remote_ssrc (struct ast_rtp_instance *instance, unsigned int ssrc)
 
static void ast_rtp_set_stream_num (struct ast_rtp_instance *instance, int stream_num)
 
static void ast_rtp_stop (struct ast_rtp_instance *instance)
 
static void ast_rtp_stun_request (struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
 
static void ast_rtp_update_source (struct ast_rtp_instance *instance)
 
static int ast_rtp_write (struct ast_rtp_instance *instance, struct ast_frame *frame)
 
static int bridge_p2p_rtp_write (struct ast_rtp_instance *instance, struct ast_rtp_instance *instance1, unsigned int *rtpheader, int len, int hdrlen)
 
static void calc_mean_and_standard_deviation (double new_sample, double *mean, double *std_dev, unsigned int *count)
 
static double calc_media_experience_score (struct ast_rtp_instance *instance, double normdevrtt, double normdev_rxjitter, double stdev_rxjitter, double normdev_rxlost)
 Calculate a "media experience score" based on given data. More...
 
static void calc_rxstamp_and_jitter (struct timeval *tv, struct ast_rtp *rtp, unsigned int rx_rtp_ts, int mark)
 
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
 
static void calculate_lost_packet_statistics (struct ast_rtp *rtp, unsigned int *lost_packets, int *fraction_lost)
 
static int compare_by_value (int elem, int value)
 Helper function to compare an elem in a vector by value. More...
 
static struct ast_framecreate_dtmf_frame (struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
 
static int create_new_socket (const char *type, int af)
 
static int find_by_value (int elem, int value)
 Helper function to find an elem in a vector by value. More...
 
static char * handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_rtp_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int load_module (void)
 
static void ntp2timeval (unsigned int msw, unsigned int lsw, struct timeval *tv)
 
static struct ast_frameprocess_cn_rfc3389 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
 
static struct ast_frameprocess_dtmf_cisco (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
 
static void process_dtmf_rfc2833 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark, struct frame_list *frames)
 
static void put_unaligned_time24 (void *p, uint32_t time_msw, uint32_t time_lsw)
 
static struct ast_framered_t140_to_red (struct rtp_red *red)
 
static int red_write (const void *data)
 Write t140 redundancy frame. More...
 
static int reload_module (void)
 
static int rtcp_debug_test_addr (struct ast_sockaddr *addr)
 
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
 
static int rtcp_mux (struct ast_rtp *rtp, const unsigned char *packet)
 
static const char * rtcp_payload_subtype2str (unsigned int pt, unsigned int subtype)
 
static const char * rtcp_payload_type2str (unsigned int pt)
 
static int rtcp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
 
static int rtcp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 
static int rtp_allocate_transport (struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 
static void rtp_deallocate_transport (struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 
static int rtp_debug_test_addr (struct ast_sockaddr *addr)
 
static char * rtp_do_debug_ip (struct ast_cli_args *a)
 
static struct ast_rtp_instancertp_find_instance_by_media_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
 
static struct ast_rtp_instancertp_find_instance_by_packet_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
 
static void rtp_instance_parse_extmap_extensions (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *extension, int len)
 
static void rtp_instance_parse_transport_wide_cc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *data, int len)
 
static void rtp_instance_unlock (struct ast_rtp_instance *instance)
 
static int rtp_learning_rtp_seq_update (struct rtp_learning_info *info, uint16_t seq)
 
static void rtp_learning_seq_init (struct rtp_learning_info *info, uint16_t seq)
 
static void rtp_learning_start (struct ast_rtp *rtp)
 Start the strictrtp learning mode. More...
 
static int rtp_raw_write (struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
 
static int rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
 
static int rtp_red_buffer (struct ast_rtp_instance *instance, struct ast_frame *frame)
 
static int rtp_red_init (struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
 
static int rtp_reload (int reload, int by_external_config)
 
static int rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 
static int rtp_transport_wide_cc_feedback_produce (const void *data)
 
static void rtp_transport_wide_cc_feedback_status_append (unsigned char *rtcpheader, int *packet_len, int *status_vector_chunk_bits, uint16_t *status_vector_chunk, int *run_length_chunk_count, int *run_length_chunk_status, int status)
 
static void rtp_transport_wide_cc_feedback_status_vector_append (unsigned char *rtcpheader, int *packet_len, int *status_vector_chunk_bits, uint16_t *status_vector_chunk, int status)
 
static int rtp_transport_wide_cc_packet_statistics_cmp (struct rtp_transport_wide_cc_packet_statistics a, struct rtp_transport_wide_cc_packet_statistics b)
 
static void rtp_write_rtcp_fir (struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)
 
static void rtp_write_rtcp_psfb (struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_frame *frame, struct ast_sockaddr *remote_address)
 
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)
 
static int unload_module (void)
 
static void update_jitter_stats (struct ast_rtp *rtp, unsigned int ia_jitter)
 
static void update_local_mes_stats (struct ast_rtp *rtp)
 
static void update_lost_stats (struct ast_rtp *rtp, unsigned int lost_packets)
 
static void update_reported_mes_stats (struct ast_rtp *rtp)
 
static int update_rtt_stats (struct ast_rtp *rtp, unsigned int lsr, unsigned int dlsr)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, #ifdef HAVE_PJPROJECT .requires = "res_pjproject", #endif }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_rtp_engine asterisk_rtp_engine
 
static struct ast_cli_entry cli_rtp []
 
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
 
static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION
 
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL
 
struct ast_srtp_resres_srtp
 
struct ast_srtp_policy_resres_srtp_policy
 
static struct ast_sockaddr rtcpdebugaddr
 
static int rtcpdebugport
 
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
 
static int rtcpstats
 
static struct ast_sockaddr rtpdebugaddr
 
static int rtpdebugport
 
static int rtpend = DEFAULT_RTP_END
 
static int rtpstart = DEFAULT_RTP_START
 
static int srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION
 
static int strictrtp = DEFAULT_STRICT_RTP
 

Detailed Description

Supports RTP and RTCP with Symmetric RTP support for NAT traversal.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
RTP is defined in RFC 3550.

Definition in file res_rtp_asterisk.c.

Macro Definition Documentation

◆ CALC_LEARNING_MIN_DURATION

#define CALC_LEARNING_MIN_DURATION (   count)    (((count) - 1) * 9 - 5)

Calculate the min learning duration in ms.

The min supported packet size represents 10 ms and we need to account for some jitter and fast clocks while learning. Some messed up devices have very bad jitter for a small packet sample size. Jitter can also be introduced by the network itself.

So we'll allow packets to come in every 9ms on average for fast clocking with the last one coming in 5ms early for jitter.

Definition at line 159 of file res_rtp_asterisk.c.

◆ DEFAULT_DTLS_MTU

#define DEFAULT_DTLS_MTU   1200

Definition at line 193 of file res_rtp_asterisk.c.

◆ DEFAULT_DTMF_TIMEOUT

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))

samples

Definition at line 142 of file res_rtp_asterisk.c.

◆ DEFAULT_ICESUPPORT

#define DEFAULT_ICESUPPORT   1

Definition at line 191 of file res_rtp_asterisk.c.

◆ DEFAULT_LEARNING_MIN_DURATION

#define DEFAULT_LEARNING_MIN_DURATION   CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)

Definition at line 160 of file res_rtp_asterisk.c.

◆ DEFAULT_LEARNING_MIN_SEQUENTIAL

#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4

Definition at line 146 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_END

#define DEFAULT_RTP_END   31000

Default maximum port number to end allocating RTP ports at

Definition at line 106 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_RECV_BUFFER_SIZE

#define DEFAULT_RTP_RECV_BUFFER_SIZE   20

The initial size of the RTP receiver buffer

Definition at line 117 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_SEND_BUFFER_SIZE

#define DEFAULT_RTP_SEND_BUFFER_SIZE   250

The initial size of the RTP send buffer

Definition at line 115 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_START

#define DEFAULT_RTP_START   5000

Default port number to start allocating RTP ports from

Definition at line 105 of file res_rtp_asterisk.c.

◆ DEFAULT_SRTP_REPLAY_PROTECTION

#define DEFAULT_SRTP_REPLAY_PROTECTION   1

Definition at line 190 of file res_rtp_asterisk.c.

◆ DEFAULT_STRICT_RTP

#define DEFAULT_STRICT_RTP   STRICT_RTP_YES

Enabled by default

Definition at line 189 of file res_rtp_asterisk.c.

◆ DEFAULT_STUN_SOFTWARE_ATTRIBUTE

#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE   1

Definition at line 192 of file res_rtp_asterisk.c.

◆ DEFAULT_TURN_PORT

#define DEFAULT_TURN_PORT   3478

Definition at line 111 of file res_rtp_asterisk.c.

◆ FLAG_3389_WARNING

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 302 of file res_rtp_asterisk.c.

◆ FLAG_DTMF_COMPENSATE

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 307 of file res_rtp_asterisk.c.

◆ FLAG_NAT_ACTIVE

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 303 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 304 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE_NOWARN

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 305 of file res_rtp_asterisk.c.

◆ FLAG_NEED_MARKER_BIT

#define FLAG_NEED_MARKER_BIT   (1 << 3)

Definition at line 306 of file res_rtp_asterisk.c.

◆ FLAG_REQ_LOCAL_BRIDGE_BIT

#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)

Definition at line 308 of file res_rtp_asterisk.c.

◆ MAX_TIMESTAMP_SKEW

#define MAX_TIMESTAMP_SKEW   640

Definition at line 98 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_PORT

#define MAXIMUM_RTP_PORT   65535

Maximum port number to accept

Definition at line 109 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_RECV_BUFFER_SIZE

#define MAXIMUM_RTP_RECV_BUFFER_SIZE   (DEFAULT_RTP_RECV_BUFFER_SIZE + 20)

Maximum RTP receive buffer size

Definition at line 118 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_SEND_BUFFER_SIZE

#define MAXIMUM_RTP_SEND_BUFFER_SIZE   (DEFAULT_RTP_SEND_BUFFER_SIZE + 200)

Maximum RTP send buffer size

Definition at line 116 of file res_rtp_asterisk.c.

◆ MINIMUM_RTP_PORT

#define MINIMUM_RTP_PORT   1024

Minimum port number to accept

Definition at line 108 of file res_rtp_asterisk.c.

◆ MISSING_SEQNOS_ADDED_TRIGGER

#define MISSING_SEQNOS_ADDED_TRIGGER   2

The number of immediate missing packets that will trigger an immediate NACK

Definition at line 120 of file res_rtp_asterisk.c.

◆ OLD_PACKET_COUNT

#define OLD_PACKET_COUNT   1000

The number of previous packets that are considered old

Definition at line 119 of file res_rtp_asterisk.c.

◆ RESCALE

#define RESCALE (   in,
  inmin,
  inmax,
  outmin,
  outmax 
)    ((((in - inmin)/(inmax-inmin))*(outmax-outmin))+outmin)

Definition at line 6279 of file res_rtp_asterisk.c.

◆ RTCP_DEFAULT_INTERVALMS

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 101 of file res_rtp_asterisk.c.

◆ RTCP_FB_NACK_BLOCK_WORD_LENGTH

#define RTCP_FB_NACK_BLOCK_WORD_LENGTH   2

Definition at line 6662 of file res_rtp_asterisk.c.

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6661 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6660 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6625 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

Definition at line 6634 of file res_rtp_asterisk.c.

◆ RTCP_MAX_INTERVALMS

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 103 of file res_rtp_asterisk.c.

◆ RTCP_MIN_INTERVALMS

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 102 of file res_rtp_asterisk.c.

◆ RTCP_PADDING_MASK

#define RTCP_PADDING_MASK   0x01

Definition at line 6628 of file res_rtp_asterisk.c.

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6637 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6626 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

Definition at line 6635 of file res_rtp_asterisk.c.

◆ RTCP_PT_APP

#define RTCP_PT_APP   204

Application defined (From RFC3550)

Definition at line 135 of file res_rtp_asterisk.c.

◆ RTCP_PT_BYE

#define RTCP_PT_BYE   203

Goodbye (To remove SSRC's from tables) (From RFC3550)

Definition at line 133 of file res_rtp_asterisk.c.

◆ RTCP_PT_FUR

#define RTCP_PT_FUR   192

Full INTRA-frame Request / Fast Update Request (From RFC2032)

Definition at line 125 of file res_rtp_asterisk.c.

◆ RTCP_PT_PSFB

#define RTCP_PT_PSFB   AST_RTP_RTCP_PSFB

Payload Specific Feed Back (From RFC4585 also RFC5104)

Definition at line 138 of file res_rtp_asterisk.c.

◆ RTCP_PT_RR

#define RTCP_PT_RR   AST_RTP_RTCP_RR

Receiver Report (From RFC3550)

Definition at line 129 of file res_rtp_asterisk.c.

◆ RTCP_PT_SDES

#define RTCP_PT_SDES   202

Source Description (From RFC3550)

Definition at line 131 of file res_rtp_asterisk.c.

◆ RTCP_PT_SR

#define RTCP_PT_SR   AST_RTP_RTCP_SR

Sender Report (From RFC3550)

Definition at line 127 of file res_rtp_asterisk.c.

◆ RTCP_REPORT_COUNT_MASK

#define RTCP_REPORT_COUNT_MASK   0x1F

Definition at line 6627 of file res_rtp_asterisk.c.

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6636 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6659 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6658 of file res_rtp_asterisk.c.

◆ RTCP_VALID_MASK

#define RTCP_VALID_MASK   (RTCP_VERSION_MASK_SHIFTED | (((RTCP_PAYLOAD_TYPE_MASK & ~0x1)) << RTCP_PAYLOAD_TYPE_SHIFT))

Definition at line 6655 of file res_rtp_asterisk.c.

◆ RTCP_VALID_VALUE

#define RTCP_VALID_VALUE   (RTCP_VERSION_SHIFTED | (RTCP_PT_SR << RTCP_PAYLOAD_TYPE_SHIFT))

Definition at line 6656 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6640 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6629 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6642 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6638 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6641 of file res_rtp_asterisk.c.

◆ RTP_DTLS_ESTABLISHED

#define RTP_DTLS_ESTABLISHED   -37

Definition at line 166 of file res_rtp_asterisk.c.

◆ RTP_IGNORE_FIRST_PACKETS_COUNT

#define RTP_IGNORE_FIRST_PACKETS_COUNT   15

Because both ends usually don't start sending RTP at the same time, some of the calculations like rtt and jitter will probably be unstable for a while so we'll skip some received packets before starting analyzing. This just affects analyzing; we still process the RTP as normal.

Definition at line 203 of file res_rtp_asterisk.c.

◆ RTP_MTU

#define RTP_MTU   1200

Definition at line 140 of file res_rtp_asterisk.c.

◆ RTP_SEQ_MOD

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 100 of file res_rtp_asterisk.c.

◆ SEQNO_CYCLE_OVER

#define SEQNO_CYCLE_OVER   65536

The number after the maximum allowed sequence number

Definition at line 122 of file res_rtp_asterisk.c.

◆ SRTP_MASTER_KEY_LEN

#define SRTP_MASTER_KEY_LEN   16

Definition at line 162 of file res_rtp_asterisk.c.

◆ SRTP_MASTER_LEN

#define SRTP_MASTER_LEN   (SRTP_MASTER_KEY_LEN + SRTP_MASTER_SALT_LEN)

Definition at line 164 of file res_rtp_asterisk.c.

◆ SRTP_MASTER_SALT_LEN

#define SRTP_MASTER_SALT_LEN   14

Definition at line 163 of file res_rtp_asterisk.c.

◆ SSRC_MAPPING_ELEM_CMP

#define SSRC_MAPPING_ELEM_CMP (   elem,
  value 
)    ((elem).instance == (value))

SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()

Parameters
elemElement to compare against
valueValue to compare with the vector element.
Return values
0if element does not match.
Non-zeroif element matches.

Definition at line 4262 of file res_rtp_asterisk.c.

◆ STRICT_RTP_LEARN_TIMEOUT

#define STRICT_RTP_LEARN_TIMEOUT   5000

Strict RTP learning timeout time in milliseconds.

Note
Set to 5 seconds to allow reinvite chains for direct media to settle before media actually starts to arrive. There may be a reinvite collision involved on the other leg.

Definition at line 187 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTCP

#define TRANSPORT_SOCKET_RTCP   1

Definition at line 311 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTP

#define TRANSPORT_SOCKET_RTP   0

Definition at line 310 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTCP

#define TRANSPORT_TURN_RTCP   3

Definition at line 313 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTP

#define TRANSPORT_TURN_RTP   2

Definition at line 312 of file res_rtp_asterisk.c.

◆ TURN_STATE_WAIT_TIME

#define TURN_STATE_WAIT_TIME   2000

Definition at line 113 of file res_rtp_asterisk.c.

◆ ZFONE_PROFILE_ID

#define ZFONE_PROFILE_ID   0x505a

Definition at line 144 of file res_rtp_asterisk.c.

Enumeration Type Documentation

◆ strict_rtp_mode

Enumerator
STRICT_RTP_NO 
STRICT_RTP_YES 

Don't adhere to any strict RTP rules

STRICT_RTP_SEQNO 

Strict RTP that restricts packets based on time and sequence number

Definition at line 174 of file res_rtp_asterisk.c.

174 {
175 STRICT_RTP_NO = 0, /*! Don't adhere to any strict RTP rules */
176 STRICT_RTP_YES, /*! Strict RTP that restricts packets based on time and sequence number */
177 STRICT_RTP_SEQNO, /*! Strict RTP that restricts packets based on sequence number */
178};
@ STRICT_RTP_SEQNO
@ STRICT_RTP_YES
@ STRICT_RTP_NO

◆ strict_rtp_state

Enumerator
STRICT_RTP_OPEN 
STRICT_RTP_LEARN 

No RTP packets should be dropped, all sources accepted

STRICT_RTP_CLOSED 

Accept next packet as source

Definition at line 168 of file res_rtp_asterisk.c.

168 {
169 STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
170 STRICT_RTP_LEARN, /*! Accept next packet as source */
171 STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
172};
@ STRICT_RTP_LEARN
@ STRICT_RTP_OPEN
@ STRICT_RTP_CLOSED

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 10452 of file res_rtp_asterisk.c.

◆ __rtp_find_instance_by_ssrc()

static struct ast_rtp_instance * __rtp_find_instance_by_ssrc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned int  ssrc,
int  source 
)
static
Precondition
instance is locked

Definition at line 6433 of file res_rtp_asterisk.c.

6435{
6436 int index;
6437
6438 if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
6439 /* This instance is not bundled */
6440 return instance;
6441 }
6442
6443 /* Find the bundled child instance */
6444 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
6445 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
6446 unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
6447
6448 if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
6449 return mapping->instance;
6450 }
6451 }
6452
6453 /* Does the SSRC match the bundled parent? */
6454 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
6455 return instance;
6456 }
6457 return NULL;
6458}
static unsigned int ast_rtp_get_ssrc(struct ast_rtp_instance *instance)
#define NULL
Definition: resample.c:96
unsigned int themssrc_valid
struct ast_rtp::@478 ssrc_mapping
unsigned int themssrc
Structure used for mapping an incoming SSRC to an RTP instance.
unsigned int ssrc
The received SSRC.
unsigned int ssrc_valid
struct ast_rtp_instance * instance
The RTP instance this SSRC belongs to.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:620
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:679

References ast_rtp_get_ssrc(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, rtp_ssrc_mapping::instance, NULL, rtp_ssrc_mapping::ssrc, ast_rtp::ssrc_mapping, rtp_ssrc_mapping::ssrc_valid, ast_rtp::themssrc, and ast_rtp::themssrc_valid.

Referenced by rtp_find_instance_by_media_source_ssrc(), and rtp_find_instance_by_packet_source_ssrc().

◆ __rtp_recvfrom()

static int __rtp_recvfrom ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa,
int  rtcp 
)
static
Precondition
instance is locked

Definition at line 3229 of file res_rtp_asterisk.c.

3230{
3231 int len;
3232 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3233#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3234 char *in = buf;
3235#endif
3236#ifdef HAVE_PJPROJECT
3237 struct ast_sockaddr *loop = rtcp ? &rtp->rtcp_loop : &rtp->rtp_loop;
3238#endif
3239#ifdef TEST_FRAMEWORK
3240 struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
3241#endif
3242
3243 if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
3244 return len;
3245 }
3246
3247#ifdef TEST_FRAMEWORK
3248 if (test && test->packets_to_drop > 0) {
3249 test->packets_to_drop--;
3250 return 0;
3251 }
3252#endif
3253
3254#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3255 /* If this is an SSL packet pass it to OpenSSL for processing. RFC section for first byte value:
3256 * https://tools.ietf.org/html/rfc5764#section-5.1.2 */
3257 if ((*in >= 20) && (*in <= 63)) {
3258 struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
3259 int res = 0;
3260
3261 /* If no SSL session actually exists terminate things */
3262 if (!dtls->ssl) {
3263 ast_log(LOG_ERROR, "Received SSL traffic on RTP instance '%p' without an SSL session\n",
3264 instance);
3265 return -1;
3266 }
3267
3268 ast_debug_dtls(3, "(%p) DTLS - __rtp_recvfrom rtp=%p - Got SSL packet '%d'\n", instance, rtp, *in);
3269
3270 /*
3271 * If ICE is in use, we can prevent a possible DOS attack
3272 * by allowing DTLS protocol messages (client hello, etc)
3273 * only from sources that are in the active remote
3274 * candidates list.
3275 */
3276
3277#ifdef HAVE_PJPROJECT
3278 if (rtp->ice) {
3279 int pass_src_check = 0;
3280 int ix = 0;
3281
3282 /*
3283 * You'd think that this check would cause a "deadlock"
3284 * because ast_rtp_ice_start_media calls dtls_perform_handshake
3285 * before it sets ice_media_started = 1 so how can we do a
3286 * handshake if we're dropping packets before we send them
3287 * to openssl. Fortunately, dtls_perform_handshake just sets
3288 * up openssl to do the handshake and doesn't actually perform it
3289 * itself and the locking prevents __rtp_recvfrom from
3290 * running before the ice_media_started flag is set. So only
3291 * unexpected DTLS packets can get dropped here.
3292 */
3293 if (!rtp->ice_media_started) {
3294 ast_log(LOG_WARNING, "%s: DTLS packet from %s dropped. ICE not completed yet.\n",
3297 return 0;
3298 }
3299
3300 /*
3301 * If we got this far, then there have to be candidates.
3302 * We have to use pjproject's rcands because they may have
3303 * peer reflexive candidates that our ice_active_remote_candidates
3304 * won't.
3305 */
3306 for (ix = 0; ix < rtp->ice->real_ice->rcand_cnt; ix++) {
3307 pj_ice_sess_cand *rcand = &rtp->ice->real_ice->rcand[ix];
3308 if (ast_sockaddr_pj_sockaddr_cmp(sa, &rcand->addr) == 0) {
3309 pass_src_check = 1;
3310 break;
3311 }
3312 }
3313
3314 if (!pass_src_check) {
3315 ast_log(LOG_WARNING, "%s: DTLS packet from %s dropped. Source not in ICE active candidate list.\n",
3318 return 0;
3319 }
3320 }
3321#endif
3322
3323 /*
3324 * A race condition is prevented between dtls_perform_handshake()
3325 * and this function because both functions have to get the
3326 * instance lock before they can do anything. The
3327 * dtls_perform_handshake() function needs to start the timer
3328 * before we stop it below.
3329 */
3330
3331 /* Before we feed data into OpenSSL ensure that the timeout timer is either stopped or completed */
3332 ao2_unlock(instance);
3333 dtls_srtp_stop_timeout_timer(instance, rtp, rtcp);
3334 ao2_lock(instance);
3335
3336 /* If we don't yet know if we are active or passive and we receive a packet... we are obviously passive */
3337 if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
3338 dtls->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
3339 SSL_set_accept_state(dtls->ssl);
3340 }
3341
3342 BIO_write(dtls->read_bio, buf, len);
3343
3344 len = SSL_read(dtls->ssl, buf, len);
3345
3346 if ((len < 0) && (SSL_get_error(dtls->ssl, len) == SSL_ERROR_SSL)) {
3347 unsigned long error = ERR_get_error();
3348 ast_log(LOG_ERROR, "DTLS failure occurred on RTP instance '%p' due to reason '%s', terminating\n",
3349 instance, ERR_reason_error_string(error));
3350 return -1;
3351 }
3352
3353 if (SSL_is_init_finished(dtls->ssl)) {
3354 /* Any further connections will be existing since this is now established */
3355 dtls->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
3356 /* Use the keying material to set up key/salt information */
3357 if ((res = dtls_srtp_setup(rtp, instance, rtcp))) {
3358 return res;
3359 }
3360 /* Notify that dtls has been established */
3362
3363 ast_debug_dtls(3, "(%p) DTLS - __rtp_recvfrom rtp=%p - established'\n", instance, rtp);
3364 } else {
3365 /* Since we've sent additional traffic start the timeout timer for retransmission */
3366 dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
3367 }
3368
3369 return res;
3370 }
3371#endif
3372
3373#ifdef HAVE_PJPROJECT
3374 if (!ast_sockaddr_isnull(loop) && !ast_sockaddr_cmp(loop, sa)) {
3375 /* ICE traffic will have been handled in the TURN callback, so skip it but update the address
3376 * so it reflects the actual source and not the loopback
3377 */
3378 if (rtcp) {
3379 ast_sockaddr_copy(sa, &rtp->rtcp->them);
3380 } else {
3382 }
3383 } else if (rtp->ice) {
3384 pj_str_t combined = pj_str(ast_sockaddr_stringify(sa));
3385 pj_sockaddr address;
3386 pj_status_t status;
3387 struct ice_wrap *ice;
3388
3389 pj_thread_register_check();
3390
3391 pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &combined, &address);
3392
3393 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3394 ice = rtp->ice;
3395 ao2_ref(ice, +1);
3396 ao2_unlock(instance);
3397 status = pj_ice_sess_on_rx_pkt(ice->real_ice,
3400 pj_sockaddr_get_len(&address));
3401 ao2_ref(ice, -1);
3402 ao2_lock(instance);
3403 if (status != PJ_SUCCESS) {
3404 char err_buf[100];
3405
3406 pj_strerror(status, err_buf, sizeof(err_buf));
3407 ast_log(LOG_WARNING, "PJ ICE Rx error status code: %d '%s'.\n",
3408 (int)status, err_buf);
3409 return -1;
3410 }
3411 if (!rtp->passthrough) {
3412 /* If a unidirectional ICE negotiation occurs then lock on to the source of the
3413 * ICE traffic and use it as the target. This will occur if the remote side only
3414 * wants to receive media but never send to us.
3415 */
3416 if (!rtp->ice_active_remote_candidates && !rtp->ice_proposed_remote_candidates) {
3417 if (rtcp) {
3418 ast_sockaddr_copy(&rtp->rtcp->them, sa);
3419 } else {
3421 }
3422 }
3423 return 0;
3424 }
3425 rtp->passthrough = 0;
3426 }
3427#endif
3428
3429 return len;
3430}
jack_status_t status
Definition: app_jack.c:149
#define ast_log
Definition: astobj2.c:42
#define ao2_unlock(a)
Definition: astobj2.h:729
#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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * address
Definition: f2c.h:59
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_ERROR
#define LOG_WARNING
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
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
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
ssize_t ast_recvfrom(int sockfd, void *buf, size_t len, int flags, struct ast_sockaddr *src_addr)
Wrapper around recvfrom(2) that uses struct ast_sockaddr.
Definition: netsock2.c:606
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_sockaddr_pj_sockaddr_cmp(const struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)
Compare an ast_sockaddr to a pj_sockaddr.
#define RTP_DTLS_ESTABLISHED
#define TRANSPORT_SOCKET_RTP
#define TRANSPORT_SOCKET_RTCP
@ AST_RTP_DTLS_SETUP_PASSIVE
Definition: rtp_engine.h:566
@ AST_RTP_DTLS_SETUP_ACTPASS
Definition: rtp_engine.h:567
@ AST_RTP_ICE_COMPONENT_RTCP
Definition: rtp_engine.h:515
@ AST_RTP_ICE_COMPONENT_RTP
Definition: rtp_engine.h:514
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:591
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1250
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1138
@ AST_RTP_DTLS_CONNECTION_EXISTING
Definition: rtp_engine.h:574
#define ast_debug_dtls(sublevel,...)
Log debug level DTLS information.
Definition: rtp_engine.h:3133
const char * ast_rtp_instance_get_channel_id(struct ast_rtp_instance *instance)
Get the unique ID of the channel that owns this RTP instance.
Definition: rtp_engine.c:576
struct ast_sockaddr them
RTP session description.
struct ast_rtcp * rtcp
Socket address structure.
Definition: netsock2.h:97
int error(const char *format,...)
Definition: utils/frame.c:999
FILE * in
Definition: utils/frame.c:33

References ao2_lock, ao2_ref, ao2_unlock, ast_debug_dtls, ast_log, ast_recvfrom(), AST_RTP_DTLS_CONNECTION_EXISTING, AST_RTP_DTLS_SETUP_ACTPASS, AST_RTP_DTLS_SETUP_PASSIVE, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_instance_set_remote_address, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_pj_sockaddr_cmp(), ast_sockaddr_stringify(), buf, error(), in, len(), LOG_ERROR, LOG_WARNING, ast_rtp::rtcp, RTP_DTLS_ESTABLISHED, ast_rtp::s, ast_rtcp::s, status, ast_rtcp::them, TRANSPORT_SOCKET_RTCP, and TRANSPORT_SOCKET_RTP.

Referenced by rtcp_recvfrom(), and rtp_recvfrom().

◆ __rtp_sendto()

static int __rtp_sendto ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa,
int  rtcp,
int *  via_ice,
int  use_srtp 
)
static
Precondition
instance is locked

Definition at line 3445 of file res_rtp_asterisk.c.

3446{
3447 int len = size;
3448 void *temp = buf;
3449 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3450 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
3451 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
3452 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(transport, rtcp);
3453 int res;
3454#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3455 char *out = buf;
3456 struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
3457
3458 /* Don't send RTP if DTLS hasn't finished yet */
3459 if (dtls->ssl && ((*out < 20) || (*out > 63)) && dtls->connection == AST_RTP_DTLS_CONNECTION_NEW) {
3460 *via_ice = 0;
3461 return 0;
3462 }
3463#endif
3464
3465 *via_ice = 0;
3466
3467 if (use_srtp && res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
3468 return -1;
3469 }
3470
3471#ifdef HAVE_PJPROJECT
3472 if (transport_rtp->ice) {
3474 pj_status_t status;
3475 struct ice_wrap *ice;
3476
3477 /* If RTCP is sharing the same socket then use the same component */
3478 if (rtcp && rtp->rtcp->s == rtp->s) {
3479 component = AST_RTP_ICE_COMPONENT_RTP;
3480 }
3481
3482 pj_thread_register_check();
3483
3484 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3485 ice = transport_rtp->ice;
3486 ao2_ref(ice, +1);
3487 if (instance == transport) {
3488 ao2_unlock(instance);
3489 }
3490 status = pj_ice_sess_send_data(ice->real_ice, component, temp, len);
3491 ao2_ref(ice, -1);
3492 if (instance == transport) {
3493 ao2_lock(instance);
3494 }
3495 if (status == PJ_SUCCESS) {
3496 *via_ice = 1;
3497 return len;
3498 }
3499 }
3500#endif
3501
3502 res = ast_sendto(rtcp ? transport_rtp->rtcp->s : transport_rtp->s, temp, len, flags, sa);
3503 if (res > 0) {
3504 ast_rtp_instance_set_last_tx(instance, time(NULL));
3505 }
3506
3507 return res;
3508}
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition: netsock2.c:614
struct ast_srtp_res * res_srtp
Definition: rtp_engine.c:182
ast_rtp_ice_component_type
ICE component types.
Definition: rtp_engine.h:513
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
Definition: rtp_engine.c:2969
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP transmission time.
Definition: rtp_engine.c:4002
@ AST_RTP_DTLS_CONNECTION_NEW
Definition: rtp_engine.h:573
struct ast_rtp_instance * bundled
int(* protect)(struct ast_srtp *srtp, void **buf, int *size, int rtcp)
Definition: res_srtp.h:50
FILE * out
Definition: utils/frame.c:33

References ao2_lock, ao2_ref, ao2_unlock, AST_RTP_DTLS_CONNECTION_NEW, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_rtp_instance_set_last_tx(), ast_sendto(), buf, ast_rtp::bundled, len(), NULL, out, ast_srtp_res::protect, res_srtp, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, and status.

Referenced by rtcp_sendto(), and rtp_sendto().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 10452 of file res_rtp_asterisk.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 10452 of file res_rtp_asterisk.c.

◆ ast_rtcp_calc_interval()

static unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp)
static
Todo:
XXX Do a more reasonable calculation on this one Look in RFC 3550 Section A.7 for an example

Definition at line 3531 of file res_rtp_asterisk.c.

3532{
3533 unsigned int interval;
3534 /*! \todo XXX Do a more reasonable calculation on this one
3535 * Look in RFC 3550 Section A.7 for an example*/
3536 interval = rtcpinterval;
3537 return interval;
3538}
static int rtcpinterval

References rtcpinterval.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

◆ ast_rtcp_calculate_sr_rr_statistics()

static int ast_rtcp_calculate_sr_rr_statistics ( struct ast_rtp_instance instance,
struct ast_rtp_rtcp_report rtcp_report,
struct ast_sockaddr  remote_address,
int  ice,
int  sr 
)
static

Definition at line 4842 of file res_rtp_asterisk.c.

4844{
4845 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4846 struct ast_rtp_rtcp_report_block *report_block = NULL;
4847 RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
4848
4849 if (!rtp || !rtp->rtcp) {
4850 return 0;
4851 }
4852
4853 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4854 return 0;
4855 }
4856
4857 if (!rtcp_report) {
4858 return -1;
4859 }
4860
4861 report_block = rtcp_report->report_block[0];
4862
4863 if (sr) {
4864 rtp->rtcp->txlsr = rtcp_report->sender_information.ntp_timestamp;
4865 rtp->rtcp->sr_count++;
4866 rtp->rtcp->lastsrtxcount = rtp->txcount;
4867 } else {
4868 rtp->rtcp->rr_count++;
4869 }
4870
4871 if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
4872 ast_verbose("* Sent RTCP %s to %s%s\n", sr ? "SR" : "RR",
4873 ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
4874 ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
4875 if (sr) {
4876 ast_verbose(" Sent(NTP): %u.%06u\n",
4877 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
4878 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
4879 ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
4880 ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
4881 ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
4882 }
4883 if (report_block) {
4884 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
4885 ast_verbose(" Report block:\n");
4886 ast_verbose(" Their SSRC: %u\n", report_block->source_ssrc);
4887 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
4888 ast_verbose(" Cumulative loss: %u\n", report_block->lost_count.packets);
4889 ast_verbose(" Highest seq no: %u\n", report_block->highest_seq_no);
4890 ast_verbose(" IA jitter (samp): %u\n", report_block->ia_jitter);
4891 ast_verbose(" IA jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
4892 ast_verbose(" Their last SR: %u\n", report_block->lsr);
4893 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
4894 }
4895 }
4896
4897 message_blob = ast_json_pack("{s: s, s: s, s: f}",
4898 "to", ast_sockaddr_stringify(&remote_address),
4899 "from", rtp->rtcp->local_addr_str,
4900 "mes", rtp->rxmes);
4901
4903 rtcp_report, message_blob);
4904
4905 return 1;
4906}
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
struct stasis_message_type * ast_rtp_rtcp_sent_type(void)
Message type for an RTCP message sent from this Asterisk instance.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
static int rtcp_debug_test_addr(struct ast_sockaddr *addr)
void ast_rtp_publish_rtcp_message(struct ast_rtp_instance *rtp, struct stasis_message_type *message_type, struct ast_rtp_rtcp_report *report, struct ast_json *blob)
Publish an RTCP message to Stasis Message Bus API.
Definition: rtp_engine.c:3696
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
Definition: rtp_engine.c:4282
struct ast_format * format
struct ast_frame_subclass subclass
Abstract JSON element (object, array, string, int, ...).
unsigned int sr_count
unsigned int lastsrtxcount
struct timeval txlsr
unsigned int rr_count
char * local_addr_str
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::@277 lost_count
unsigned short fraction
Definition: rtp_engine.h:349
unsigned int source_ssrc
Definition: rtp_engine.h:347
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
struct ast_rtp_rtcp_report::@278 sender_information
unsigned int packet_count
Definition: rtp_engine.h:368
double rxmes
struct ast_frame f
unsigned int txcount
double ast_samp2sec(unsigned int _nsamp, unsigned int _rate)
Returns the duration in seconds of _nsamp samples at rate _rate.
Definition: time.h:316
#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:978

References ast_json_pack(), ast_json_unref(), ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_publish_rtcp_message(), ast_rtp_rtcp_sent_type(), ast_samp2sec(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose(), ast_rtp_rtcp_report_block::dlsr, ast_rtp::f, ast_frame_subclass::format, ast_rtp_rtcp_report_block::fraction, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, ast_rtcp::lastsrtxcount, ast_rtcp::local_addr_str, ast_rtp_rtcp_report_block::lost_count, ast_rtp_rtcp_report_block::lsr, ast_rtp_rtcp_report::ntp_timestamp, NULL, ast_rtp_rtcp_report::octet_count, ast_rtp_rtcp_report::packet_count, ast_rtp_rtcp_report_block::packets, RAII_VAR, ast_rtp_rtcp_report::report_block, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtp_rtcp_report::rtp_timestamp, ast_rtp::rxmes, ast_rtp_rtcp_report::sender_information, ast_rtp_rtcp_report_block::source_ssrc, ast_rtcp::sr_count, ast_rtp_rtcp_report::ssrc, ast_frame::subclass, ast_rtcp::them, ast_rtp::txcount, and ast_rtcp::txlsr.

Referenced by ast_rtcp_write(), ast_rtp_read(), rtp_write_rtcp_fir(), and rtp_write_rtcp_psfb().

◆ ast_rtcp_generate_compound_prefix()

static int ast_rtcp_generate_compound_prefix ( struct ast_rtp_instance instance,
unsigned char *  rtcpheader,
struct ast_rtp_rtcp_report report,
int *  sr 
)
static

Definition at line 4966 of file res_rtp_asterisk.c.

4968{
4969 int packet_len = 0;
4970 int res;
4971
4972 /* Every RTCP packet needs to be sent out with a SR/RR and SDES prefixing it.
4973 * At the end of this function, rtcpheader should contain both of those packets,
4974 * and will return the length of the overall packet. This can be used to determine
4975 * where further packets can be inserted in the compound packet.
4976 */
4977 res = ast_rtcp_generate_report(instance, rtcpheader, report, sr);
4978
4979 if (res == 0 || res == 1) {
4980 ast_debug_rtcp(1, "(%p) RTCP failed to generate %s report!\n", instance, sr ? "SR" : "RR");
4981 return 0;
4982 }
4983
4984 packet_len += res;
4985
4986 res = ast_rtcp_generate_sdes(instance, rtcpheader + packet_len, report);
4987
4988 if (res == 0 || res == 1) {
4989 ast_debug_rtcp(1, "(%p) RTCP failed to generate SDES!\n", instance);
4990 return 0;
4991 }
4992
4993 return packet_len + res;
4994}
static int ast_rtcp_generate_report(struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report, int *sr)
static int ast_rtcp_generate_sdes(struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report)
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:3116

References ast_debug_rtcp, ast_rtcp_generate_report(), and ast_rtcp_generate_sdes().

Referenced by ast_rtcp_write(), ast_rtp_read(), rtp_write_rtcp_fir(), and rtp_write_rtcp_psfb().

◆ ast_rtcp_generate_nack()

static int ast_rtcp_generate_nack ( struct ast_rtp_instance instance,
unsigned char *  rtcpheader 
)
static

Definition at line 4996 of file res_rtp_asterisk.c.

4997{
4998 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4999 int packet_len;
5000 int blp_index = -1;
5001 int current_seqno;
5002 unsigned int fci = 0;
5003 size_t remaining_missing_seqno;
5004
5005 if (!rtp || !rtp->rtcp) {
5006 return 0;
5007 }
5008
5009 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
5010 return 0;
5011 }
5012
5013 current_seqno = rtp->expectedrxseqno;
5014 remaining_missing_seqno = AST_VECTOR_SIZE(&rtp->missing_seqno);
5015 packet_len = 12; /* The header length is 12 (version line, packet source SSRC, media source SSRC) */
5016
5017 /* If there are no missing sequence numbers then don't bother sending a NACK needlessly */
5018 if (!remaining_missing_seqno) {
5019 return 0;
5020 }
5021
5022 /* This iterates through the possible forward sequence numbers seeing which ones we
5023 * have no packet for, adding it to the NACK until we are out of missing packets.
5024 */
5025 while (remaining_missing_seqno) {
5026 int *missing_seqno;
5027
5028 /* On the first entry to this loop blp_index will be -1, so this will become 0
5029 * and the sequence number will be placed into the packet as the PID.
5030 */
5031 blp_index++;
5032
5033 missing_seqno = AST_VECTOR_GET_CMP(&rtp->missing_seqno, current_seqno,
5035 if (missing_seqno) {
5036 /* We hit the max blp size, reset */
5037 if (blp_index >= 17) {
5038 put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
5039 fci = 0;
5040 blp_index = 0;
5041 packet_len += 4;
5042 }
5043
5044 if (blp_index == 0) {
5045 fci |= (current_seqno << 16);
5046 } else {
5047 fci |= (1 << (blp_index - 1));
5048 }
5049
5050 /* Since we've used a missing sequence number, we're down one */
5051 remaining_missing_seqno--;
5052 }
5053
5054 /* Handle cycling of the sequence number */
5055 current_seqno++;
5056 if (current_seqno == SEQNO_CYCLE_OVER) {
5057 current_seqno = 0;
5058 }
5059 }
5060
5061 put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
5062 packet_len += 4;
5063
5064 /* Length MUST be 2+n, where n is the number of NACKs. Same as length in words minus 1 */
5065 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_NACK << 24)
5066 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
5067 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
5068 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
5069
5070 return packet_len;
5071}
static int find_by_value(int elem, int value)
Helper function to find an elem in a vector by value.
#define SEQNO_CYCLE_OVER
#define AST_RTP_RTCP_RTPFB
Definition: rtp_engine.h:327
#define AST_RTP_RTCP_FMT_NACK
Definition: rtp_engine.h:333
int expectedrxseqno
struct ast_rtp::@477 missing_seqno
unsigned int ssrc
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:742

References ast_rtp_instance_get_data(), AST_RTP_RTCP_FMT_NACK, AST_RTP_RTCP_RTPFB, ast_sockaddr_isnull(), AST_VECTOR_GET_CMP, AST_VECTOR_SIZE, ast_rtp::expectedrxseqno, find_by_value(), ast_rtp::missing_seqno, put_unaligned_uint32(), ast_rtp::rtcp, SEQNO_CYCLE_OVER, ast_rtp::ssrc, ast_rtcp::them, and ast_rtp::themssrc.

Referenced by ast_rtp_read().

◆ ast_rtcp_generate_report()

static int ast_rtcp_generate_report ( struct ast_rtp_instance instance,
unsigned char *  rtcpheader,
struct ast_rtp_rtcp_report rtcp_report,
int *  sr 
)
static

Definition at line 4749 of file res_rtp_asterisk.c.

4751{
4752 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4753 int len = 0;
4754 struct timeval now;
4755 unsigned int now_lsw;
4756 unsigned int now_msw;
4757 unsigned int lost_packets;
4758 int fraction_lost;
4759 struct timeval dlsr = { 0, };
4760 struct ast_rtp_rtcp_report_block *report_block = NULL;
4761
4762 if (!rtp || !rtp->rtcp) {
4763 return 0;
4764 }
4765
4766 if (ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */
4767 /* RTCP was stopped. */
4768 return 0;
4769 }
4770
4771 if (!rtcp_report) {
4772 return 1;
4773 }
4774
4775 *sr = rtp->txcount > rtp->rtcp->lastsrtxcount ? 1 : 0;
4776
4777 /* Compute statistics */
4778 calculate_lost_packet_statistics(rtp, &lost_packets, &fraction_lost);
4779 /*
4780 * update_local_mes_stats must be called AFTER
4781 * calculate_lost_packet_statistics
4782 */
4784
4785 gettimeofday(&now, NULL);
4786 rtcp_report->reception_report_count = rtp->themssrc_valid ? 1 : 0;
4787 rtcp_report->ssrc = rtp->ssrc;
4788 rtcp_report->type = *sr ? RTCP_PT_SR : RTCP_PT_RR;
4789 if (*sr) {
4790 rtcp_report->sender_information.ntp_timestamp = now;
4791 rtcp_report->sender_information.rtp_timestamp = rtp->lastts;
4792 rtcp_report->sender_information.packet_count = rtp->txcount;
4793 rtcp_report->sender_information.octet_count = rtp->txoctetcount;
4794 }
4795
4796 if (rtp->themssrc_valid) {
4797 report_block = ast_calloc(1, sizeof(*report_block));
4798 if (!report_block) {
4799 return 1;
4800 }
4801
4802 rtcp_report->report_block[0] = report_block;
4803 report_block->source_ssrc = rtp->themssrc;
4804 report_block->lost_count.fraction = (fraction_lost & 0xff);
4805 report_block->lost_count.packets = (lost_packets & 0xffffff);
4806 report_block->highest_seq_no = (rtp->cycles | (rtp->lastrxseqno & 0xffff));
4807 report_block->ia_jitter = (unsigned int)rtp->rxjitter_samples;
4808 report_block->lsr = rtp->rtcp->themrxlsr;
4809 /* If we haven't received an SR report, DLSR should be 0 */
4810 if (!ast_tvzero(rtp->rtcp->rxlsr)) {
4811 timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
4812 report_block->dlsr = (((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000;
4813 }
4814 }
4815 timeval2ntp(rtcp_report->sender_information.ntp_timestamp, &now_msw, &now_lsw);
4816 put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc)); /* Our SSRC */
4817 len += 8;
4818 if (*sr) {
4819 put_unaligned_uint32(rtcpheader + len, htonl(now_msw)); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970 */
4820 put_unaligned_uint32(rtcpheader + len + 4, htonl(now_lsw)); /* now, LSW */
4821 put_unaligned_uint32(rtcpheader + len + 8, htonl(rtcp_report->sender_information.rtp_timestamp));
4822 put_unaligned_uint32(rtcpheader + len + 12, htonl(rtcp_report->sender_information.packet_count));
4823 put_unaligned_uint32(rtcpheader + len + 16, htonl(rtcp_report->sender_information.octet_count));
4824 len += 20;
4825 }
4826 if (report_block) {
4827 put_unaligned_uint32(rtcpheader + len, htonl(report_block->source_ssrc)); /* Their SSRC */
4828 put_unaligned_uint32(rtcpheader + len + 4, htonl((report_block->lost_count.fraction << 24) | report_block->lost_count.packets));
4829 put_unaligned_uint32(rtcpheader + len + 8, htonl(report_block->highest_seq_no));
4830 put_unaligned_uint32(rtcpheader + len + 12, htonl(report_block->ia_jitter));
4831 put_unaligned_uint32(rtcpheader + len + 16, htonl(report_block->lsr));
4832 put_unaligned_uint32(rtcpheader + len + 20, htonl(report_block->dlsr));
4833 len += 24;
4834 }
4835
4836 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (rtcp_report->reception_report_count << 24)
4837 | ((*sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1)));
4838
4839 return len;
4840}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
void timersub(struct timeval *tvend, struct timeval *tvstart, struct timeval *tvdiff)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define RTCP_PT_RR
static void calculate_lost_packet_statistics(struct ast_rtp *rtp, unsigned int *lost_packets, int *fraction_lost)
#define RTCP_PT_SR
static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
static void update_local_mes_stats(struct ast_rtp *rtp)
unsigned int themrxlsr
struct timeval rxlsr
unsigned int type
Definition: rtp_engine.h:364
unsigned short reception_report_count
Definition: rtp_engine.h:362
unsigned int lastts
unsigned int cycles
double rxjitter_samples
unsigned int txoctetcount
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117

References ast_calloc, ast_rtp_instance_get_data(), ast_sockaddr_isnull(), ast_tvzero(), calculate_lost_packet_statistics(), ast_rtp::cycles, ast_rtp_rtcp_report_block::dlsr, ast_rtp_rtcp_report_block::fraction, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, if(), ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), ast_rtp_rtcp_report_block::lost_count, ast_rtp_rtcp_report_block::lsr, ast_rtp_rtcp_report::ntp_timestamp, NULL, ast_rtp_rtcp_report::octet_count, ast_rtp_rtcp_report::packet_count, ast_rtp_rtcp_report_block::packets, put_unaligned_uint32(), ast_rtp_rtcp_report::reception_report_count, ast_rtp_rtcp_report::report_block, ast_rtp::rtcp, RTCP_PT_RR, RTCP_PT_SR, ast_rtp_rtcp_report::rtp_timestamp, ast_rtp::rxjitter_samples, ast_rtcp::rxlsr, ast_rtp_rtcp_report::sender_information, ast_rtp_rtcp_report_block::source_ssrc, ast_rtp_rtcp_report::ssrc, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, ast_rtp::themssrc_valid, timersub(), timeval2ntp(), ast_rtp::txcount, ast_rtp::txoctetcount, ast_rtp_rtcp_report::type, and update_local_mes_stats().

Referenced by ast_rtcp_generate_compound_prefix().

◆ ast_rtcp_generate_sdes()

static int ast_rtcp_generate_sdes ( struct ast_rtp_instance instance,
unsigned char *  rtcpheader,
struct ast_rtp_rtcp_report rtcp_report 
)
static

Definition at line 4908 of file res_rtp_asterisk.c.

4910{
4911 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4912 int len = 0;
4913 uint16_t sdes_packet_len_bytes;
4914 uint16_t sdes_packet_len_rounded;
4915
4916 if (!rtp || !rtp->rtcp) {
4917 return 0;
4918 }
4919
4920 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4921 return 0;
4922 }
4923
4924 if (!rtcp_report) {
4925 return -1;
4926 }
4927
4928 sdes_packet_len_bytes =
4929 4 + /* RTCP Header */
4930 4 + /* SSRC */
4931 1 + /* Type (CNAME) */
4932 1 + /* Text Length */
4933 AST_UUID_STR_LEN /* Text and NULL terminator */
4934 ;
4935
4936 /* Round to 32 bit boundary */
4937 sdes_packet_len_rounded = (sdes_packet_len_bytes + 3) & ~0x3;
4938
4939 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((sdes_packet_len_rounded / 4) - 1)));
4940 put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc));
4941 rtcpheader[8] = 0x01; /* CNAME */
4942 rtcpheader[9] = AST_UUID_STR_LEN - 1; /* Number of bytes of text */
4943 memcpy(rtcpheader + 10, rtp->cname, AST_UUID_STR_LEN);
4944 len += 10 + AST_UUID_STR_LEN;
4945
4946 /* Padding - Note that we don't set the padded bit on the packet. From
4947 * RFC 3550 Section 6.5:
4948 *
4949 * No length octet follows the null item type octet, but additional null
4950 * octets MUST be included if needd to pad until the next 32-bit
4951 * boundary. Note that this padding is separate from that indicated by
4952 * the P bit in the RTCP header.
4953 *
4954 * These bytes will already be zeroed out during array initialization.
4955 */
4956 len += (sdes_packet_len_rounded - sdes_packet_len_bytes);
4957
4958 return len;
4959}
#define RTCP_PT_SDES
char cname[AST_UUID_STR_LEN]
#define AST_UUID_STR_LEN
Definition: uuid.h:27

References ast_rtp_instance_get_data(), ast_sockaddr_isnull(), AST_UUID_STR_LEN, ast_rtp::cname, len(), put_unaligned_uint32(), ast_rtp::rtcp, RTCP_PT_SDES, ast_rtp_rtcp_report::ssrc, and ast_rtcp::them.

Referenced by ast_rtcp_generate_compound_prefix().

◆ ast_rtcp_interpret()

static struct ast_frame * ast_rtcp_interpret ( struct ast_rtp_instance instance,
struct ast_srtp srtp,
const unsigned char *  rtcpdata,
size_t  size,
struct ast_sockaddr addr 
)
static

True if we have seen an acceptable SSRC to learn the remote RTCP address

True if the ssrc value we have is valid and not garbage because it doesn't exist.

Always use packet source SSRC to find the rtp instance unless explicitly told not to.

Definition at line 6664 of file res_rtp_asterisk.c.

6666{
6667 struct ast_rtp_instance *transport = instance;
6668 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(instance);
6669 int len = size;
6670 unsigned int *rtcpheader = (unsigned int *)(rtcpdata);
6671 unsigned int packetwords;
6672 unsigned int position;
6673 unsigned int first_word;
6674 /*! True if we have seen an acceptable SSRC to learn the remote RTCP address */
6675 unsigned int ssrc_seen;
6676 struct ast_rtp_rtcp_report_block *report_block;
6677 struct ast_frame *f = &ast_null_frame;
6678#ifdef TEST_FRAMEWORK
6679 struct ast_rtp_engine_test *test_engine;
6680#endif
6681
6682 /* If this is encrypted then decrypt the payload */
6683 if ((*rtcpheader & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
6684 srtp, rtcpheader, &len, 1 | (srtp_replay_protection << 1)) < 0) {
6685 return &ast_null_frame;
6686 }
6687
6688 packetwords = len / 4;
6689
6690 ast_debug_rtcp(2, "(%s) RTCP got report of %d bytes from %s\n",
6693
6694 /*
6695 * Validate the RTCP packet according to an adapted and slightly
6696 * modified RFC3550 validation algorithm.
6697 */
6698 if (packetwords < RTCP_HEADER_SSRC_LENGTH) {
6699 ast_debug_rtcp(2, "(%s) RTCP %p -- from %s: Frame size (%u words) is too short\n",
6701 transport_rtp, ast_sockaddr_stringify(addr), packetwords);
6702 return &ast_null_frame;
6703 }
6704 position = 0;
6705 first_word = ntohl(rtcpheader[position]);
6706 if ((first_word & RTCP_VALID_MASK) != RTCP_VALID_VALUE) {
6707 ast_debug_rtcp(2, "(%s) RTCP %p -- from %s: Failed first packet validity check\n",
6709 transport_rtp, ast_sockaddr_stringify(addr));
6710 return &ast_null_frame;
6711 }
6712 do {
6713 position += ((first_word >> RTCP_LENGTH_SHIFT) & RTCP_LENGTH_MASK) + 1;
6714 if (packetwords <= position) {
6715 break;
6716 }
6717 first_word = ntohl(rtcpheader[position]);
6718 } while ((first_word & RTCP_VERSION_MASK_SHIFTED) == RTCP_VERSION_SHIFTED);
6719 if (position != packetwords) {
6720 ast_debug_rtcp(2, "(%s) RTCP %p -- from %s: Failed packet version or length check\n",
6722 transport_rtp, ast_sockaddr_stringify(addr));
6723 return &ast_null_frame;
6724 }
6725
6726 /*
6727 * Note: RFC3605 points out that true NAT (vs NAPT) can cause RTCP
6728 * to have a different IP address and port than RTP. Otherwise, when
6729 * strictrtp is enabled we could reject RTCP packets not coming from
6730 * the learned RTP IP address if it is available.
6731 */
6732
6733 /*
6734 * strictrtp safety needs SSRC to match before we use the
6735 * sender's address for symmetrical RTP to send our RTCP
6736 * reports.
6737 *
6738 * If strictrtp is not enabled then claim to have already seen
6739 * a matching SSRC so we'll accept this packet's address for
6740 * symmetrical RTP.
6741 */
6742 ssrc_seen = transport_rtp->strict_rtp_state == STRICT_RTP_OPEN;
6743
6744 position = 0;
6745 while (position < packetwords) {
6746 unsigned int i;
6747 unsigned int pt;
6748 unsigned int rc;
6749 unsigned int ssrc;
6750 /*! True if the ssrc value we have is valid and not garbage because it doesn't exist. */
6751 unsigned int ssrc_valid;
6752 unsigned int length;
6753 unsigned int min_length;
6754 /*! Always use packet source SSRC to find the rtp instance unless explicitly told not to. */
6755 unsigned int use_packet_source = 1;
6756
6757 struct ast_json *message_blob;
6758 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
6759 struct ast_rtp_instance *child;
6760 struct ast_rtp *rtp;
6761 struct ast_rtp_rtcp_feedback *feedback;
6762
6763 i = position;
6764 first_word = ntohl(rtcpheader[i]);
6765 pt = (first_word >> RTCP_PAYLOAD_TYPE_SHIFT) & RTCP_PAYLOAD_TYPE_MASK;
6766 rc = (first_word >> RTCP_REPORT_COUNT_SHIFT) & RTCP_REPORT_COUNT_MASK;
6767 /* RFC3550 says 'length' is the number of words in the packet - 1 */
6768 length = ((first_word >> RTCP_LENGTH_SHIFT) & RTCP_LENGTH_MASK) + 1;
6769
6770 /* Check expected RTCP packet record length */
6771 min_length = RTCP_HEADER_SSRC_LENGTH;
6772 switch (pt) {
6773 case RTCP_PT_SR:
6774 min_length += RTCP_SR_BLOCK_WORD_LENGTH;
6775 /* fall through */
6776 case RTCP_PT_RR:
6777 min_length += (rc * RTCP_RR_BLOCK_WORD_LENGTH);
6778 use_packet_source = 0;
6779 break;
6780 case RTCP_PT_FUR:
6781 break;
6782 case AST_RTP_RTCP_RTPFB:
6783 switch (rc) {
6785 min_length += RTCP_FB_NACK_BLOCK_WORD_LENGTH;
6786 break;
6787 default:
6788 break;
6789 }
6790 use_packet_source = 0;
6791 break;
6792 case RTCP_PT_PSFB:
6793 switch (rc) {
6795 min_length += RTCP_FB_REMB_BLOCK_WORD_LENGTH;
6796 break;
6797 default:
6798 break;
6799 }
6800 break;
6801 case RTCP_PT_SDES:
6802 case RTCP_PT_BYE:
6803 /*
6804 * There may not be a SSRC/CSRC present. The packet is
6805 * useless but still valid if it isn't present.
6806 *
6807 * We don't know what min_length should be so disable the check
6808 */
6809 min_length = length;
6810 break;
6811 default:
6812 ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: %u(%s) skipping record\n",
6813 instance, transport_rtp, ast_sockaddr_stringify(addr), pt, rtcp_payload_type2str(pt));
6814 if (rtcp_debug_test_addr(addr)) {
6815 ast_verbose("\n");
6816 ast_verbose("RTCP from %s: %u(%s) skipping record\n",
6818 }
6819 position += length;
6820 continue;
6821 }
6822 if (length < min_length) {
6823 ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: %u(%s) length field less than expected minimum. Min:%u Got:%u\n",
6824 instance, transport_rtp, ast_sockaddr_stringify(addr), pt, rtcp_payload_type2str(pt),
6825 min_length - 1, length - 1);
6826 return &ast_null_frame;
6827 }
6828
6829 /* Get the RTCP record SSRC if defined for the record */
6830 ssrc_valid = 1;
6831 switch (pt) {
6832 case RTCP_PT_SR:
6833 case RTCP_PT_RR:
6834 rtcp_report = ast_rtp_rtcp_report_alloc(rc);
6835 if (!rtcp_report) {
6836 return &ast_null_frame;
6837 }
6838 rtcp_report->reception_report_count = rc;
6839
6840 ssrc = ntohl(rtcpheader[i + 2]);
6841 rtcp_report->ssrc = ssrc;
6842 break;
6843 case RTCP_PT_FUR:
6844 case RTCP_PT_PSFB:
6845 ssrc = ntohl(rtcpheader[i + 1]);
6846 break;
6847 case AST_RTP_RTCP_RTPFB:
6848 ssrc = ntohl(rtcpheader[i + 2]);
6849 break;
6850 case RTCP_PT_SDES:
6851 case RTCP_PT_BYE:
6852 default:
6853 ssrc = 0;
6854 ssrc_valid = 0;
6855 break;
6856 }
6857
6858 if (rtcp_debug_test_addr(addr)) {
6859 const char *subtype = rtcp_payload_subtype2str(pt, rc);
6860
6861 ast_verbose("\n");
6862 ast_verbose("RTCP from %s\n", ast_sockaddr_stringify(addr));
6863 ast_verbose("PT: %u (%s)\n", pt, rtcp_payload_type2str(pt));
6864 if (subtype) {
6865 ast_verbose("Packet Subtype: %u (%s)\n", rc, subtype);
6866 } else {
6867 ast_verbose("Reception reports: %u\n", rc);
6868 }
6869 ast_verbose("SSRC of sender: %u\n", ssrc);
6870 }
6871
6872 /* Determine the appropriate instance for this */
6873 if (ssrc_valid) {
6874 /*
6875 * Depending on the payload type, either the packet source or media source
6876 * SSRC is used.
6877 */
6878 if (use_packet_source) {
6879 child = rtp_find_instance_by_packet_source_ssrc(transport, transport_rtp, ssrc);
6880 } else {
6881 child = rtp_find_instance_by_media_source_ssrc(transport, transport_rtp, ssrc);
6882 }
6883 if (child && child != transport) {
6884 /*
6885 * It is safe to hold the child lock while holding the parent lock.
6886 * We guarantee that the locking order is always parent->child or
6887 * that the child lock is not held when acquiring the parent lock.
6888 */
6889 ao2_lock(child);
6890 instance = child;
6891 rtp = ast_rtp_instance_get_data(instance);
6892 } else {
6893 /* The child is the parent! We don't need to unlock it. */
6894 child = NULL;
6895 rtp = transport_rtp;
6896 }
6897 } else {
6898 child = NULL;
6899 rtp = transport_rtp;
6900 }
6901
6902 if (ssrc_valid && rtp->themssrc_valid) {
6903 /*
6904 * If the SSRC is 1, we still need to handle RTCP since this could be a
6905 * special case. For example, if we have a unidirectional video stream, the
6906 * SSRC may be set to 1 by the browser (in the case of chromium), and requests
6907 * will still need to be processed so that video can flow as expected. This
6908 * should only be done for PLI and FUR, since there is not a way to get the
6909 * appropriate rtp instance when the SSRC is 1.
6910 */
6911 int exception = (ssrc == 1 && !((pt == RTCP_PT_PSFB && rc == AST_RTP_RTCP_FMT_PLI) || pt == RTCP_PT_FUR));
6912 if ((ssrc != rtp->themssrc && use_packet_source && ssrc != 1)
6913 || exception) {
6914 /*
6915 * Skip over this RTCP record as it does not contain the
6916 * correct SSRC. We should not act upon RTCP records
6917 * for a different stream.
6918 */
6919 position += length;
6920 ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: Skipping record, received SSRC '%u' != expected '%u'\n",
6921 instance, rtp, ast_sockaddr_stringify(addr), ssrc, rtp->themssrc);
6922 if (child) {
6923 ao2_unlock(child);
6924 }
6925 continue;
6926 }
6927 ssrc_seen = 1;
6928 }
6929
6930 if (ssrc_seen && ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
6931 /* Send to whoever sent to us */
6932 if (ast_sockaddr_cmp(&rtp->rtcp->them, addr)) {
6933 ast_sockaddr_copy(&rtp->rtcp->them, addr);
6935 ast_debug(0, "(%p) RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
6936 instance, ast_sockaddr_stringify(addr));
6937 }
6938 }
6939 }
6940
6941 i += RTCP_HEADER_SSRC_LENGTH; /* Advance past header and ssrc */
6942 switch (pt) {
6943 case RTCP_PT_SR:
6944 gettimeofday(&rtp->rtcp->rxlsr, NULL);
6945 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16);
6946 rtp->rtcp->spc = ntohl(rtcpheader[i + 3]);
6947 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
6948
6949 rtcp_report->type = RTCP_PT_SR;
6950 rtcp_report->sender_information.packet_count = rtp->rtcp->spc;
6951 rtcp_report->sender_information.octet_count = rtp->rtcp->soc;
6952 ntp2timeval((unsigned int)ntohl(rtcpheader[i]),
6953 (unsigned int)ntohl(rtcpheader[i + 1]),
6954 &rtcp_report->sender_information.ntp_timestamp);
6955 rtcp_report->sender_information.rtp_timestamp = ntohl(rtcpheader[i + 2]);
6956 if (rtcp_debug_test_addr(addr)) {
6957 ast_verbose("NTP timestamp: %u.%06u\n",
6958 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
6959 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
6960 ast_verbose("RTP timestamp: %u\n", rtcp_report->sender_information.rtp_timestamp);
6961 ast_verbose("SPC: %u\tSOC: %u\n",
6962 rtcp_report->sender_information.packet_count,
6963 rtcp_report->sender_information.octet_count);
6964 }
6966 /* Intentional fall through */
6967 case RTCP_PT_RR:
6968 if (rtcp_report->type != RTCP_PT_SR) {
6969 rtcp_report->type = RTCP_PT_RR;
6970 }
6971
6972 if (rc > 0) {
6973 /* Don't handle multiple reception reports (rc > 1) yet */
6974 report_block = ast_calloc(1, sizeof(*report_block));
6975 if (!report_block) {
6976 if (child) {
6977 ao2_unlock(child);
6978 }
6979 return &ast_null_frame;
6980 }
6981 rtcp_report->report_block[0] = report_block;
6982 report_block->source_ssrc = ntohl(rtcpheader[i]);
6983 report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
6984 report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
6985 report_block->highest_seq_no = ntohl(rtcpheader[i + 2]);
6986 report_block->ia_jitter = ntohl(rtcpheader[i + 3]);
6987 report_block->lsr = ntohl(rtcpheader[i + 4]);
6988 report_block->dlsr = ntohl(rtcpheader[i + 5]);
6989 if (report_block->lsr) {
6990 int skewed = update_rtt_stats(rtp, report_block->lsr, report_block->dlsr);
6991 if (skewed && rtcp_debug_test_addr(addr)) {
6992 struct timeval now;
6993 unsigned int lsr_now, lsw, msw;
6994 gettimeofday(&now, NULL);
6995 timeval2ntp(now, &msw, &lsw);
6996 lsr_now = (((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16));
6997 ast_verbose("Internal RTCP NTP clock skew detected: "
6998 "lsr=%u, now=%u, dlsr=%u (%u:%03ums), "
6999 "diff=%u\n",
7000 report_block->lsr, lsr_now, report_block->dlsr, report_block->dlsr / 65536,
7001 (report_block->dlsr % 65536) * 1000 / 65536,
7002 report_block->dlsr - (lsr_now - report_block->lsr));
7003 }
7004 }
7005 update_jitter_stats(rtp, report_block->ia_jitter);
7006 update_lost_stats(rtp, report_block->lost_count.packets);
7007 /*
7008 * update_reported_mes_stats must be called AFTER
7009 * update_rtt_stats, update_jitter_stats and
7010 * update_lost_stats.
7011 */
7013
7014 if (rtcp_debug_test_addr(addr)) {
7015 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
7016
7017 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
7018 ast_verbose(" Packets lost so far: %u\n", report_block->lost_count.packets);
7019 ast_verbose(" Highest sequence number: %u\n", report_block->highest_seq_no & 0x0000ffff);
7020 ast_verbose(" Sequence number cycles: %u\n", report_block->highest_seq_no >> 16);
7021 ast_verbose(" Interarrival jitter (samp): %u\n", report_block->ia_jitter);
7022 ast_verbose(" Interarrival jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
7023 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long)(report_block->lsr) >> 16,((unsigned long)(report_block->lsr) << 16) * 4096);
7024 ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
7025 ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
7026 ast_verbose(" MES: %4.1f\n", rtp->rtcp->reported_mes);
7027 }
7028 }
7029 /* If and when we handle more than one report block, this should occur outside
7030 * this loop.
7031 */
7032
7033 message_blob = ast_json_pack("{s: s, s: s, s: f, s: f}",
7034 "from", ast_sockaddr_stringify(addr),
7035 "to", transport_rtp->rtcp->local_addr_str,
7036 "rtt", rtp->rtcp->rtt,
7037 "mes", rtp->rtcp->reported_mes);
7039 rtcp_report,
7040 message_blob);
7041 ast_json_unref(message_blob);
7042
7043 /* Return an AST_FRAME_RTCP frame with the ast_rtp_rtcp_report
7044 * object as a its data */
7045 transport_rtp->f.frametype = AST_FRAME_RTCP;
7046 transport_rtp->f.subclass.integer = pt;
7047 transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
7048 memcpy(transport_rtp->f.data.ptr, rtcp_report, sizeof(struct ast_rtp_rtcp_report));
7049 transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_report);
7050 if (rc > 0) {
7051 /* There's always a single report block stored, here */
7052 struct ast_rtp_rtcp_report *rtcp_report2;
7053 report_block = transport_rtp->f.data.ptr + transport_rtp->f.datalen + sizeof(struct ast_rtp_rtcp_report_block *);
7054 memcpy(report_block, rtcp_report->report_block[0], sizeof(struct ast_rtp_rtcp_report_block));
7055 rtcp_report2 = (struct ast_rtp_rtcp_report *)transport_rtp->f.data.ptr;
7056 rtcp_report2->report_block[0] = report_block;
7057 transport_rtp->f.datalen += sizeof(struct ast_rtp_rtcp_report_block);
7058 }
7059 transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
7060 transport_rtp->f.samples = 0;
7061 transport_rtp->f.mallocd = 0;
7062 transport_rtp->f.delivery.tv_sec = 0;
7063 transport_rtp->f.delivery.tv_usec = 0;
7064 transport_rtp->f.src = "RTP";
7065 transport_rtp->f.stream_num = rtp->stream_num;
7066 f = &transport_rtp->f;
7067 break;
7068 case AST_RTP_RTCP_RTPFB:
7069 switch (rc) {
7071 /* If retransmissions are not enabled ignore this message */
7072 if (!rtp->send_buffer) {
7073 break;
7074 }
7075
7076 if (rtcp_debug_test_addr(addr)) {
7077 ast_verbose("Received generic RTCP NACK message\n");
7078 }
7079
7080 ast_rtp_rtcp_handle_nack(instance, rtcpheader, position, length);
7081 break;
7082 default:
7083 break;
7084 }
7085 break;
7086 case RTCP_PT_FUR:
7087 /* Handle RTCP FUR as FIR by setting the format to 4 */
7089 case RTCP_PT_PSFB:
7090 switch (rc) {
7093 if (rtcp_debug_test_addr(addr)) {
7094 ast_verbose("Received an RTCP Fast Update Request\n");
7095 }
7096 transport_rtp->f.frametype = AST_FRAME_CONTROL;
7097 transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
7098 transport_rtp->f.datalen = 0;
7099 transport_rtp->f.samples = 0;
7100 transport_rtp->f.mallocd = 0;
7101 transport_rtp->f.src = "RTP";
7102 f = &transport_rtp->f;
7103 break;
7105 /* If REMB support is not enabled ignore this message */
7107 break;
7108 }
7109
7110 if (rtcp_debug_test_addr(addr)) {
7111 ast_verbose("Received REMB report\n");
7112 }
7113 transport_rtp->f.frametype = AST_FRAME_RTCP;
7114 transport_rtp->f.subclass.integer = pt;
7115 transport_rtp->f.stream_num = rtp->stream_num;
7116 transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
7117 feedback = transport_rtp->f.data.ptr;
7118 feedback->fmt = rc;
7119
7120 /* We don't actually care about the SSRC information in the feedback message */
7121 first_word = ntohl(rtcpheader[i + 2]);
7122 feedback->remb.br_exp = (first_word >> 18) & ((1 << 6) - 1);
7123 feedback->remb.br_mantissa = first_word & ((1 << 18) - 1);
7124
7125 transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_feedback);
7126 transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
7127 transport_rtp->f.samples = 0;
7128 transport_rtp->f.mallocd = 0;
7129 transport_rtp->f.delivery.tv_sec = 0;
7130 transport_rtp->f.delivery.tv_usec = 0;
7131 transport_rtp->f.src = "RTP";
7132 f = &transport_rtp->f;
7133 break;
7134 default:
7135 break;
7136 }
7137 break;
7138 case RTCP_PT_SDES:
7139 if (rtcp_debug_test_addr(addr)) {
7140 ast_verbose("Received an SDES from %s\n",
7142 }
7143#ifdef TEST_FRAMEWORK
7144 if ((test_engine = ast_rtp_instance_get_test(instance))) {
7145 test_engine->sdes_received = 1;
7146 }
7147#endif
7148 break;
7149 case RTCP_PT_BYE:
7150 if (rtcp_debug_test_addr(addr)) {
7151 ast_verbose("Received a BYE from %s\n",
7153 }
7154 break;
7155 default:
7156 break;
7157 }
7158 position += length;
7159 rtp->rtcp->rtcp_info = 1;
7160
7161 if (child) {
7162 ao2_unlock(child);
7163 }
7164 }
7165
7166 return f;
7167}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct stasis_message_type * ast_rtp_rtcp_received_type(void)
Message type for an RTCP message received from some external source.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_FRAME_RTCP
@ AST_FRAME_CONTROL
@ AST_CONTROL_VIDUPDATE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define RTCP_LENGTH_SHIFT
static int ast_rtp_rtcp_handle_nack(struct ast_rtp_instance *instance, unsigned int *nackdata, unsigned int position, unsigned int length)
#define RTCP_PAYLOAD_TYPE_SHIFT
static void ntp2timeval(unsigned int msw, unsigned int lsw, struct timeval *tv)
#define RTCP_VALID_VALUE
#define RTCP_FB_NACK_BLOCK_WORD_LENGTH
#define RTCP_RR_BLOCK_WORD_LENGTH
static const char * rtcp_payload_subtype2str(unsigned int pt, unsigned int subtype)
#define RTCP_SR_BLOCK_WORD_LENGTH
static struct ast_rtp_instance * rtp_find_instance_by_packet_source_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
#define RTCP_REPORT_COUNT_SHIFT
#define RTCP_PT_FUR
static const char * rtcp_payload_type2str(unsigned int pt)
#define RTCP_PT_BYE
#define RTCP_HEADER_SSRC_LENGTH
#define RTCP_VALID_MASK
static int srtp_replay_protection
static void update_jitter_stats(struct ast_rtp *rtp, unsigned int ia_jitter)
#define RTCP_FB_REMB_BLOCK_WORD_LENGTH
#define RTCP_PT_PSFB
static int update_rtt_stats(struct ast_rtp *rtp, unsigned int lsr, unsigned int dlsr)
static struct ast_rtp_instance * rtp_find_instance_by_media_source_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
#define RTCP_VERSION_SHIFTED
#define RTCP_REPORT_COUNT_MASK
#define RTCP_PAYLOAD_TYPE_MASK
#define RTCP_VERSION_MASK_SHIFTED
static void update_reported_mes_stats(struct ast_rtp *rtp)
static void update_lost_stats(struct ast_rtp *rtp, unsigned int lost_packets)
#define RTCP_LENGTH_MASK
#define AST_RTP_RTCP_FMT_FIR
Definition: rtp_engine.h:337
struct ast_rtp_rtcp_report * ast_rtp_rtcp_report_alloc(unsigned int report_blocks)
Allocate an ao2 ref counted instance of ast_rtp_rtcp_report.
Definition: rtp_engine.c:3685
int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
Get the value of an RTP instance property.
Definition: rtp_engine.c:744
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:3107
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:339
@ AST_RTP_PROPERTY_NAT
Definition: rtp_engine.h:118
@ AST_RTP_PROPERTY_REMB
Definition: rtp_engine.h:134
#define AST_RTP_RTCP_FMT_PLI
Definition: rtp_engine.h:335
Data structure associated with a single frame of data.
struct timeval delivery
enum ast_frame_type frametype
union ast_frame::@231 data
const char * src
double reported_mes
unsigned char frame_buf[512+AST_FRIENDLY_OFFSET]
unsigned int soc
unsigned int spc
An object that represents data received in a feedback report.
Definition: rtp_engine.h:388
unsigned int fmt
Definition: rtp_engine.h:389
struct ast_rtp_rtcp_feedback_remb remb
Definition: rtp_engine.h:391
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:361
enum strict_rtp_state strict_rtp_state
struct ast_data_buffer * send_buffer
int(* unprotect)(struct ast_srtp *srtp, void *buf, int *size, int rtcp)
Definition: res_srtp.h:48

References ao2_cleanup, ao2_lock, ao2_unlock, ast_calloc, AST_CONTROL_VIDUPDATE, ast_debug, ast_debug_rtcp, ast_debug_rtp_packet_is_allowed, AST_FRAME_CONTROL, AST_FRAME_RTCP, AST_FRIENDLY_OFFSET, ast_json_pack(), ast_json_unref(), ast_null_frame, ast_rtp_get_rate(), ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_NAT, AST_RTP_PROPERTY_REMB, ast_rtp_publish_rtcp_message(), AST_RTP_RTCP_FMT_FIR, AST_RTP_RTCP_FMT_NACK, AST_RTP_RTCP_FMT_PLI, AST_RTP_RTCP_FMT_REMB, ast_rtp_rtcp_handle_nack(), ast_rtp_rtcp_received_type(), ast_rtp_rtcp_report_alloc(), AST_RTP_RTCP_RTPFB, ast_samp2sec(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_verbose(), ast_rtp_rtcp_feedback_remb::br_exp, ast_rtp_rtcp_feedback_remb::br_mantissa, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp_rtcp_report_block::dlsr, ast_rtp::f, ast_rtp_rtcp_feedback::fmt, ast_frame_subclass::format, ast_rtp_rtcp_report_block::fraction, ast_rtcp::frame_buf, ast_frame::frametype, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, ast_frame_subclass::integer, len(), ast_rtcp::local_addr_str, ast_rtp_rtcp_report_block::lost_count, ast_rtp_rtcp_report_block::lsr, ast_frame::mallocd, ntp2timeval(), NULL, ast_frame::offset, ast_rtp_rtcp_report_block::packets, ast_frame::ptr, RAII_VAR, ast_rtp_rtcp_feedback::remb, ast_rtp_rtcp_report::report_block, ast_rtcp::reported_mes, res_srtp, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_FB_NACK_BLOCK_WORD_LENGTH, RTCP_FB_REMB_BLOCK_WORD_LENGTH, RTCP_HEADER_SSRC_LENGTH, ast_rtcp::rtcp_info, RTCP_LENGTH_MASK, RTCP_LENGTH_SHIFT, rtcp_payload_subtype2str(), rtcp_payload_type2str(), RTCP_PAYLOAD_TYPE_MASK, RTCP_PAYLOAD_TYPE_SHIFT, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_PSFB, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, RTCP_REPORT_COUNT_MASK, RTCP_REPORT_COUNT_SHIFT, RTCP_RR_BLOCK_WORD_LENGTH, RTCP_SR_BLOCK_WORD_LENGTH, RTCP_VALID_MASK, RTCP_VALID_VALUE, RTCP_VERSION_MASK_SHIFTED, RTCP_VERSION_SHIFTED, rtp_find_instance_by_media_source_ssrc(), rtp_find_instance_by_packet_source_ssrc(), ast_rtcp::rtt, ast_rtcp::rxlsr, ast_frame::samples, ast_rtp::send_buffer, ast_rtcp::soc, ast_rtp_rtcp_report_block::source_ssrc, ast_rtcp::spc, ast_frame::src, srtp_replay_protection, ast_frame::stream_num, ast_rtp::stream_num, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, ast_rtp::themssrc_valid, timeval2ntp(), ast_srtp_res::unprotect, update_jitter_stats(), update_lost_stats(), update_reported_mes_stats(), and update_rtt_stats().

Referenced by ast_rtcp_read(), and ast_rtp_read().

◆ ast_rtcp_read()

static struct ast_frame * ast_rtcp_read ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 7170 of file res_rtp_asterisk.c.

7171{
7172 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7173 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 1);
7174 struct ast_sockaddr addr;
7175 unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
7176 unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
7177 size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
7178 int res;
7179
7180 /* Read in RTCP data from the socket */
7181 if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
7182 0, &addr)) < 0) {
7183 if (res == RTP_DTLS_ESTABLISHED) {
7186 return &rtp->f;
7187 }
7188
7189 ast_assert(errno != EBADF);
7190 if (errno != EAGAIN) {
7191 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n",
7192 (errno) ? strerror(errno) : "Unspecified");
7193 return NULL;
7194 }
7195 return &ast_null_frame;
7196 }
7197
7198 /* If this was handled by the ICE session don't do anything further */
7199 if (!res) {
7200 return &ast_null_frame;
7201 }
7202
7203 if (!*read_area) {
7204 struct sockaddr_in addr_tmp;
7205 struct ast_sockaddr addr_v4;
7206
7207 if (ast_sockaddr_is_ipv4(&addr)) {
7208 ast_sockaddr_to_sin(&addr, &addr_tmp);
7209 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
7210 ast_debug_stun(2, "(%p) STUN using IPv6 mapped address %s\n",
7211 instance, ast_sockaddr_stringify(&addr));
7212 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
7213 } else {
7214 ast_debug_stun(2, "(%p) STUN cannot do for non IPv4 address %s\n",
7215 instance, ast_sockaddr_stringify(&addr));
7216 return &ast_null_frame;
7217 }
7218 if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
7219 ast_sockaddr_from_sin(&addr, &addr_tmp);
7220 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
7221 }
7222 return &ast_null_frame;
7223 }
7224
7225 return ast_rtcp_interpret(instance, srtp, read_area, res, &addr);
7226}
@ AST_CONTROL_SRCCHANGE
int errno
int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
Convert an IPv4-mapped IPv6 address into an IPv4 address.
Definition: netsock2.c:37
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:765
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:778
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
static struct ast_frame * ast_rtcp_interpret(struct ast_rtp_instance *instance, struct ast_srtp *srtp, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
handle an incoming STUN message.
Definition: stun.c:293
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:54
@ AST_STUN_ACCEPT
Definition: stun.h:65
#define ast_assert(a)
Definition: utils.h:776

References ast_assert, AST_CONTROL_SRCCHANGE, ast_debug_stun, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_log, ast_null_frame, ast_rtcp_interpret(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_ipv4_mapped(), ast_sockaddr_is_ipv4(), ast_sockaddr_stringify(), ast_sockaddr_to_sin, AST_STUN_ACCEPT, ast_stun_handle_packet(), errno, ast_rtp::f, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, ast_rtp::rtcp, rtcp_recvfrom(), RTP_DTLS_ESTABLISHED, ast_rtcp::s, ast_frame::subclass, and ast_rtcp::them.

Referenced by ast_rtp_read().

◆ ast_rtcp_write()

static int ast_rtcp_write ( const void *  data)
static

Write a RTCP packet to the far end.

Note
Decide if we are going to send an SR (with Reception Block) or RR RR is sent if we have not sent any rtp packets in the previous interval

Scheduler callback

Definition at line 5081 of file res_rtp_asterisk.c.

5082{
5083 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
5084 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5085 int res;
5086 int sr = 0;
5087 int packet_len = 0;
5088 int ice;
5089 struct ast_sockaddr remote_address = { { 0, } };
5090 unsigned char *rtcpheader;
5091 unsigned char bdata[AST_UUID_STR_LEN + 128] = ""; /* More than enough */
5092 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5093
5094 if (!rtp || !rtp->rtcp || rtp->rtcp->schedid == -1) {
5095 ao2_ref(instance, -1);
5096 return 0;
5097 }
5098
5099 ao2_lock(instance);
5100 rtcpheader = bdata;
5101 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5102 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5103
5104 if (res == 0 || res == 1) {
5105 goto cleanup;
5106 }
5107
5108 packet_len += res;
5109
5110 if (rtp->bundled) {
5111 ast_rtp_instance_get_remote_address(instance, &remote_address);
5112 } else {
5113 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
5114 }
5115
5116 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
5117 if (res < 0) {
5118 ast_log(LOG_ERROR, "RTCP %s transmission error to %s, rtcp halted %s\n",
5119 sr ? "SR" : "RR",
5121 strerror(errno));
5122 res = 0;
5123 } else {
5124 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
5125 }
5126
5127cleanup:
5128 ao2_unlock(instance);
5129
5130 if (!res) {
5131 /*
5132 * Not being rescheduled.
5133 */
5134 rtp->rtcp->schedid = -1;
5135 ao2_ref(instance, -1);
5136 }
5137
5138 return res;
5139}
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
static int ast_rtcp_generate_compound_prefix(struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
static int ast_rtcp_calculate_sr_rr_statistics(struct ast_rtp_instance *instance, struct ast_rtp_rtcp_report *rtcp_report, struct ast_sockaddr remote_address, int ice, int sr)

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_log, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_rtcp_report_alloc(), ast_sockaddr_copy(), ast_sockaddr_stringify(), AST_UUID_STR_LEN, ast_rtp::bundled, cleanup(), ast_rtp_instance::data, errno, LOG_ERROR, NULL, RAII_VAR, ast_rtp::rtcp, rtcp_sendto(), ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::themssrc_valid.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

◆ ast_rtp_bundle()

static int ast_rtp_bundle ( struct ast_rtp_instance child,
struct ast_rtp_instance parent 
)
static
Precondition
child is locked

Definition at line 9538 of file res_rtp_asterisk.c.

9539{
9540 struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child);
9541 struct ast_rtp *parent_rtp;
9542 struct rtp_ssrc_mapping mapping;
9543 struct ast_sockaddr them = { { 0, } };
9544
9545 if (child_rtp->bundled == parent) {
9546 return 0;
9547 }
9548
9549 /* If this instance was already bundled then remove the SSRC mapping */
9550 if (child_rtp->bundled) {
9551 struct ast_rtp *bundled_rtp;
9552
9553 ao2_unlock(child);
9554
9555 /* The child lock can't be held while accessing the parent */
9556 ao2_lock(child_rtp->bundled);
9557 bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled);
9559 ao2_unlock(child_rtp->bundled);
9560
9561 ao2_lock(child);
9562 ao2_ref(child_rtp->bundled, -1);
9563 child_rtp->bundled = NULL;
9564 }
9565
9566 if (!parent) {
9567 /* We transitioned away from bundle so we need our own transport resources once again */
9568 rtp_allocate_transport(child, child_rtp);
9569 return 0;
9570 }
9571
9572 parent_rtp = ast_rtp_instance_get_data(parent);
9573
9574 /* We no longer need any transport related resources as we will use our parent RTP instance instead */
9575 rtp_deallocate_transport(child, child_rtp);
9576
9577 /* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
9578 child_rtp->bundled = ao2_bump(parent);
9579
9580 mapping.ssrc = child_rtp->themssrc;
9581 mapping.ssrc_valid = child_rtp->themssrc_valid;
9582 mapping.instance = child;
9583
9584 ao2_unlock(child);
9585
9586 ao2_lock(parent);
9587
9588 AST_VECTOR_APPEND(&parent_rtp->ssrc_mapping, mapping);
9589
9590#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9591 /* If DTLS-SRTP is already in use then add the local SSRC to it, otherwise it will get added once DTLS
9592 * negotiation has been completed.
9593 */
9594 if (parent_rtp->dtls.connection == AST_RTP_DTLS_CONNECTION_EXISTING) {
9595 dtls_srtp_add_local_ssrc(parent_rtp, parent, 0, child_rtp->ssrc, 0);
9596 }
9597#endif
9598
9599 /* Bundle requires that RTCP-MUX be in use so only the main remote address needs to match */
9601
9602 ao2_unlock(parent);
9603
9604 ao2_lock(child);
9605
9607
9608 return 0;
9609}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static void rtp_deallocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
static int rtp_allocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
#define SSRC_MAPPING_ELEM_CMP(elem, value)
SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:582
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition: vector.h:499
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:267

References ao2_bump, ao2_lock, ao2_ref, ao2_unlock, AST_RTP_DTLS_CONNECTION_EXISTING, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_instance_set_remote_address, AST_VECTOR_APPEND, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_REMOVE_CMP_UNORDERED, ast_rtp::bundled, rtp_ssrc_mapping::instance, NULL, rtp_allocate_transport(), rtp_deallocate_transport(), rtp_ssrc_mapping::ssrc, ast_rtp::ssrc, ast_rtp::ssrc_mapping, SSRC_MAPPING_ELEM_CMP, rtp_ssrc_mapping::ssrc_valid, ast_rtp::themssrc, and ast_rtp::themssrc_valid.

◆ ast_rtp_change_source()

static void ast_rtp_change_source ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4618 of file res_rtp_asterisk.c.

4619{
4620 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4621 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 0);
4622 struct ast_srtp *rtcp_srtp = ast_rtp_instance_get_srtp(instance, 1);
4623 unsigned int ssrc = ast_random();
4624
4625 if (rtp->lastts) {
4626 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4628 }
4629
4630 ast_debug_rtp(3, "(%p) RTP changing ssrc from %u to %u due to a source change\n",
4631 instance, rtp->ssrc, ssrc);
4632
4633 if (srtp) {
4634 ast_debug_rtp(3, "(%p) RTP changing ssrc for SRTP from %u to %u\n",
4635 instance, rtp->ssrc, ssrc);
4636 res_srtp->change_source(srtp, rtp->ssrc, ssrc);
4637 if (rtcp_srtp != srtp) {
4638 res_srtp->change_source(rtcp_srtp, rtp->ssrc, ssrc);
4639 }
4640 }
4641
4642 rtp->ssrc = ssrc;
4643
4644 /* Since the source is changing, we don't know what sequence number to expect next */
4645 rtp->expectedrxseqno = -1;
4646
4647 return;
4648}
#define FLAG_NEED_MARKER_BIT
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:3099
int(* change_source)(struct ast_srtp *srtp, unsigned int from_ssrc, unsigned int to_ssrc)
Definition: res_srtp.h:44
struct ast_rtp_instance * rtp
Definition: res_srtp.c:93
long int ast_random(void)
Definition: utils.c:2348
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_debug_rtp, ast_random(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_set_flag, ast_srtp_res::change_source, FLAG_NEED_MARKER_BIT, res_srtp, and ast_srtp::rtp.

◆ ast_rtp_destroy()

static int ast_rtp_destroy ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4265 of file res_rtp_asterisk.c.

4266{
4267 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4268
4269 if (rtp->bundled) {
4270 struct ast_rtp *bundled_rtp;
4271
4272 /* We can't hold our instance lock while removing ourselves from the parent */
4273 ao2_unlock(instance);
4274
4275 ao2_lock(rtp->bundled);
4276 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
4278 ao2_unlock(rtp->bundled);
4279
4280 ao2_lock(instance);
4281 ao2_ref(rtp->bundled, -1);
4282 }
4283
4284 rtp_deallocate_transport(instance, rtp);
4285
4286 /* Destroy the smoother that was smoothing out audio if present */
4287 if (rtp->smoother) {
4289 }
4290
4291 /* Destroy RTCP if it was being used */
4292 if (rtp->rtcp) {
4293 /*
4294 * It is not possible for there to be an active RTCP scheduler
4295 * entry at this point since it holds a reference to the
4296 * RTP instance while it's active.
4297 */
4299 ast_free(rtp->rtcp);
4300 }
4301
4302 /* Destroy RED if it was being used */
4303 if (rtp->red) {
4304 ao2_unlock(instance);
4305 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
4306 ao2_lock(instance);
4307 ast_free(rtp->red);
4308 rtp->red = NULL;
4309 }
4310
4311 /* Destroy the send buffer if it was being used */
4312 if (rtp->send_buffer) {
4314 }
4315
4316 /* Destroy the recv buffer if it was being used */
4317 if (rtp->recv_buffer) {
4319 }
4320
4322
4328
4329 /* Finally destroy ourselves */
4330 rtp->owner = NULL;
4331 ast_free(rtp);
4332
4333 return 0;
4334}
#define ast_free(a)
Definition: astmm.h:180
void ast_data_buffer_free(struct ast_data_buffer *buffer)
Free a data buffer (and all held data payloads)
Definition: data_buffer.c:338
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
struct ast_format * lasttxformat
struct rtp_transport_wide_cc_statistics transport_wide_cc
struct ast_smoother * smoother
struct ast_sched_context * sched
struct ast_data_buffer * recv_buffer
struct ast_rtp_instance * owner
The RTP instance owning us (used for debugging purposes) We don't hold a reference to the instance be...
struct rtp_red * red
struct ast_format * lastrxformat
struct rtp_transport_wide_cc_statistics::@476 packet_statistics
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:185

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_data_buffer_free(), ast_free, ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_smoother_free(), AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_FREE, AST_VECTOR_REMOVE_CMP_UNORDERED, ast_rtp::bundled, ast_rtp::f, ast_frame_subclass::format, ast_rtp::lastrxformat, ast_rtp::lasttxformat, ast_rtcp::local_addr_str, ast_rtp::missing_seqno, NULL, ast_rtp::owner, rtp_transport_wide_cc_statistics::packet_statistics, ast_rtp::recv_buffer, ast_rtp::red, ast_rtp::rtcp, rtp_deallocate_transport(), ast_rtp::sched, rtp_red::schedid, ast_rtp::send_buffer, ast_rtp::smoother, ast_rtp::ssrc_mapping, SSRC_MAPPING_ELEM_CMP, ast_frame::subclass, and ast_rtp::transport_wide_cc.

◆ ast_rtp_dtmf_begin()

static int ast_rtp_dtmf_begin ( struct ast_rtp_instance instance,
char  digit 
)
static
Precondition
instance is locked

Definition at line 4352 of file res_rtp_asterisk.c.

4353{
4354 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4355 struct ast_sockaddr remote_address = { {0,} };
4356 int hdrlen = 12, res = 0, i = 0, payload = -1, sample_rate = -1;
4357 char data[256];
4358 unsigned int *rtpheader = (unsigned int*)data;
4359 RAII_VAR(struct ast_format *, payload_format, NULL, ao2_cleanup);
4360
4361 ast_rtp_instance_get_remote_address(instance, &remote_address);
4362
4363 /* If we have no remote address information bail out now */
4364 if (ast_sockaddr_isnull(&remote_address)) {
4365 return -1;
4366 }
4367
4368 /* Convert given digit into what we want to transmit */
4369 if ((digit <= '9') && (digit >= '0')) {
4370 digit -= '0';
4371 } else if (digit == '*') {
4372 digit = 10;
4373 } else if (digit == '#') {
4374 digit = 11;
4375 } else if ((digit >= 'A') && (digit <= 'D')) {
4376 digit = digit - 'A' + 12;
4377 } else if ((digit >= 'a') && (digit <= 'd')) {
4378 digit = digit - 'a' + 12;
4379 } else {
4380 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4381 return -1;
4382 }
4383
4384 if (rtp->lasttxformat == ast_format_none) {
4385 /* No audio frames have been written yet so we have to lookup both the preferred payload type and bitrate. */
4387 if (payload_format) {
4388 /* If we have a preferred type, use that. Otherwise default to 8K. */
4389 sample_rate = ast_format_get_sample_rate(payload_format);
4390 }
4391 } else {
4392 sample_rate = ast_format_get_sample_rate(rtp->lasttxformat);
4393 }
4394
4395 if (sample_rate != -1) {
4397 }
4398
4399 if (payload == -1 ||
4402 /* Fall back to the preferred DTMF payload type and sample rate as either we couldn't find an audio codec to try and match
4403 sample rates with or we could, but a telephone-event matching that audio codec's sample rate was not included in the
4404 sdp negotiated by the far end. */
4407 }
4408
4409 /* The sdp negotiation has not yeilded a usable RFC 2833/4733 format. Try a default-rate one as a last resort. */
4410 if (payload == -1 || sample_rate == -1) {
4411 sample_rate = DEFAULT_DTMF_SAMPLE_RATE_MS;
4413 }
4414 /* Even trying a default payload has failed. We are trying to send a digit outside of what was negotiated for. */
4415 if (payload == -1) {
4416 return -1;
4417 }
4418
4419 ast_test_suite_event_notify("DTMF_BEGIN", "Digit: %d\r\nPayload: %d\r\nRate: %d\r\n", digit, payload, sample_rate);
4420 ast_debug(1, "Sending digit '%d' at rate %d with payload %d\n", digit, sample_rate, payload);
4421
4422 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4423 rtp->send_duration = 160;
4424 rtp->dtmf_samplerate_ms = (sample_rate / 1000);
4425 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4426 rtp->lastdigitts = rtp->lastts + rtp->send_duration;
4427
4428 /* Create the actual packet that we will be sending */
4429 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
4430 rtpheader[1] = htonl(rtp->lastdigitts);
4431 rtpheader[2] = htonl(rtp->ssrc);
4432
4433 /* Actually send the packet */
4434 for (i = 0; i < 2; i++) {
4435 int ice;
4436
4437 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4438 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4439 if (res < 0) {
4440 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4441 ast_sockaddr_stringify(&remote_address),
4442 strerror(errno));
4443 }
4444 if (rtp_debug_test_addr(&remote_address)) {
4445 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4446 ast_sockaddr_stringify(&remote_address),
4447 ice ? " (via ICE)" : "",
4448 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4449 }
4450 rtp->seqno++;
4451 rtp->send_duration += 160;
4452 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
4453 }
4454
4455 /* Record that we are in the process of sending a digit and information needed to continue doing so */
4456 rtp->sending_digit = 1;
4457 rtp->send_digit = digit;
4458 rtp->send_payload = payload;
4459
4460 return 0;
4461}
char digit
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
struct ast_format * ast_format_none
Built-in "null" format.
Definition: format_cache.c:246
static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
struct ast_format * ast_rtp_codecs_get_preferred_format(struct ast_rtp_codecs *codecs)
Retrieve rx preferred format.
Definition: rtp_engine.c:1578
struct ast_rtp_payload_type * ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
Retrieve rx payload mapped information by payload type.
Definition: rtp_engine.c:1554
#define AST_RTP_DTMF
Definition: rtp_engine.h:294
int ast_rtp_codecs_payload_code_tx_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code, unsigned int sample_rate)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:2091
int ast_rtp_codecs_get_preferred_dtmf_format_rate(struct ast_rtp_codecs *codecs)
Retrieve rx preferred dtmf format sample rate.
Definition: rtp_engine.c:1604
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:2152
int ast_rtp_payload_mapping_tx_is_present(struct ast_rtp_codecs *codecs, const struct ast_rtp_payload_type *to_match)
Determine if a type of payload is already present in mappings.
Definition: rtp_engine.c:1226
int ast_rtp_codecs_get_preferred_dtmf_format_pt(struct ast_rtp_codecs *codecs)
Retrieve rx preferred dtmf format payload type.
Definition: rtp_engine.c:1595
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:755
#define DEFAULT_DTMF_SAMPLE_RATE_MS
Definition: rtp_engine.h:110
Definition of a media format.
Definition: format.c:43
unsigned short seqno
struct timeval dtmfmute
unsigned int dtmf_samplerate_ms
unsigned int lastdigitts
char sending_digit
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

References ao2_cleanup, ast_debug, ast_format_get_sample_rate(), ast_format_none, ast_log, ast_rtp_codecs_get_payload(), ast_rtp_codecs_get_preferred_dtmf_format_pt(), ast_rtp_codecs_get_preferred_dtmf_format_rate(), ast_rtp_codecs_get_preferred_format(), ast_rtp_codecs_payload_code_tx(), ast_rtp_codecs_payload_code_tx_sample_rate(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_payload_mapping_tx_is_present(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_suite_event_notify, ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), calc_txstamp(), DEFAULT_DTMF_SAMPLE_RATE_MS, digit, ast_rtp::dtmf_samplerate_ms, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, ast_rtp::lasttxformat, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.

◆ ast_rtp_dtmf_compatible()

static int ast_rtp_dtmf_compatible ( struct ast_channel chan0,
struct ast_rtp_instance instance0,
struct ast_channel chan1,
struct ast_rtp_instance instance1 
)
static
Precondition
Neither instance0 nor instance1 are locked

Definition at line 9321 of file res_rtp_asterisk.c.

9322{
9323 /* If both sides are not using the same method of DTMF transmission
9324 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9325 * --------------------------------------------------
9326 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9327 * |-----------|------------|-----------------------|
9328 * | Inband | False | True |
9329 * | RFC2833 | True | True |
9330 * | SIP INFO | False | False |
9331 * --------------------------------------------------
9332 */
9334 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9335}
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:120

References ast_channel_tech(), ast_rtp_instance_get_prop(), and AST_RTP_PROPERTY_DTMF.

◆ ast_rtp_dtmf_continuation()

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4464 of file res_rtp_asterisk.c.

4465{
4466 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4467 struct ast_sockaddr remote_address = { {0,} };
4468 int hdrlen = 12, res = 0;
4469 char data[256];
4470 unsigned int *rtpheader = (unsigned int*)data;
4471 int ice;
4472
4473 ast_rtp_instance_get_remote_address(instance, &remote_address);
4474
4475 /* Make sure we know where the other side is so we can send them the packet */
4476 if (ast_sockaddr_isnull(&remote_address)) {
4477 return -1;
4478 }
4479
4480 /* Actually create the packet we will be sending */
4481 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4482 rtpheader[1] = htonl(rtp->lastdigitts);
4483 rtpheader[2] = htonl(rtp->ssrc);
4484 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
4485
4486 /* Boom, send it on out */
4487 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4488 if (res < 0) {
4489 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4490 ast_sockaddr_stringify(&remote_address),
4491 strerror(errno));
4492 }
4493
4494 if (rtp_debug_test_addr(&remote_address)) {
4495 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4496 ast_sockaddr_stringify(&remote_address),
4497 ice ? " (via ICE)" : "",
4498 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4499 }
4500
4501 /* And now we increment some values for the next time we swing by */
4502 rtp->seqno++;
4503 rtp->send_duration += 160;
4504 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4505
4506 return 0;
4507}

References ast_log, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose(), calc_txstamp(), ast_rtp::dtmf_samplerate_ms, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, NULL, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, and ast_rtp::ssrc.

Referenced by ast_rtp_interpret().

◆ ast_rtp_dtmf_end()

static int ast_rtp_dtmf_end ( struct ast_rtp_instance instance,
char  digit 
)
static
Precondition
instance is locked

Definition at line 4600 of file res_rtp_asterisk.c.

4601{
4602 return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
4603}
static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)

References ast_rtp_dtmf_end_with_duration(), and digit.

◆ ast_rtp_dtmf_end_with_duration()

static int ast_rtp_dtmf_end_with_duration ( struct ast_rtp_instance instance,
char  digit,
unsigned int  duration 
)
static
Precondition
instance is locked

Definition at line 4510 of file res_rtp_asterisk.c.

4511{
4512 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4513 struct ast_sockaddr remote_address = { {0,} };
4514 int hdrlen = 12, res = -1, i = 0;
4515 char data[256];
4516 unsigned int *rtpheader = (unsigned int*)data;
4517 unsigned int measured_samples;
4518
4519 ast_rtp_instance_get_remote_address(instance, &remote_address);
4520
4521 /* Make sure we know where the remote side is so we can send them the packet we construct */
4522 if (ast_sockaddr_isnull(&remote_address)) {
4523 goto cleanup;
4524 }
4525
4526 /* Convert the given digit to the one we are going to send */
4527 if ((digit <= '9') && (digit >= '0')) {
4528 digit -= '0';
4529 } else if (digit == '*') {
4530 digit = 10;
4531 } else if (digit == '#') {
4532 digit = 11;
4533 } else if ((digit >= 'A') && (digit <= 'D')) {
4534 digit = digit - 'A' + 12;
4535 } else if ((digit >= 'a') && (digit <= 'd')) {
4536 digit = digit - 'a' + 12;
4537 } else {
4538 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4539 goto cleanup;
4540 }
4541
4542 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4543
4544 if (duration > 0 && (measured_samples = duration * ast_rtp_get_rate(rtp->f.subclass.format) / 1000) > rtp->send_duration) {
4545 ast_debug_rtp(2, "(%p) RTP adjusting final end duration from %d to %u\n",
4546 instance, rtp->send_duration, measured_samples);
4547 rtp->send_duration = measured_samples;
4548 }
4549
4550 /* Construct the packet we are going to send */
4551 rtpheader[1] = htonl(rtp->lastdigitts);
4552 rtpheader[2] = htonl(rtp->ssrc);
4553 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4554 rtpheader[3] |= htonl((1 << 23));
4555
4556 /* Send it 3 times, that's the magical number */
4557 for (i = 0; i < 3; i++) {
4558 int ice;
4559
4560 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4561
4562 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4563
4564 if (res < 0) {
4565 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4566 ast_sockaddr_stringify(&remote_address),
4567 strerror(errno));
4568 }
4569
4570 if (rtp_debug_test_addr(&remote_address)) {
4571 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4572 ast_sockaddr_stringify(&remote_address),
4573 ice ? " (via ICE)" : "",
4574 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4575 }
4576
4577 rtp->seqno++;
4578 }
4579 res = 0;
4580
4581 /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
4582 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4583
4584 /* Reset the smoother as the delivery time stored in it is now out of date */
4585 if (rtp->smoother) {
4587 rtp->smoother = NULL;
4588 }
4589cleanup:
4590 rtp->sending_digit = 0;
4591 rtp->send_digit = 0;
4592
4593 /* Re-Learn expected seqno */
4594 rtp->expectedseqno = -1;
4595
4596 return res;
4597}

References ast_debug_rtp, ast_log, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_smoother_free(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), calc_txstamp(), cleanup(), digit, ast_rtp::dtmf_samplerate_ms, ast_rtp::dtmfmute, errno, ast_rtp::expectedseqno, ast_rtp::f, ast_frame_subclass::format, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, NULL, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::smoother, ast_rtp::ssrc, and ast_frame::subclass.

Referenced by ast_rtp_dtmf_end().

◆ ast_rtp_dtmf_mode_get()

static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4345 of file res_rtp_asterisk.c.

4346{
4347 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4348 return rtp->dtmfmode;
4349}
enum ast_rtp_dtmf_mode dtmfmode

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

◆ ast_rtp_dtmf_mode_set()

static int ast_rtp_dtmf_mode_set ( struct ast_rtp_instance instance,
enum ast_rtp_dtmf_mode  dtmf_mode 
)
static
Precondition
instance is locked

Definition at line 4337 of file res_rtp_asterisk.c.

4338{
4339 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4340 rtp->dtmfmode = dtmf_mode;
4341 return 0;
4342}

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

◆ ast_rtp_extension_enable()

static int ast_rtp_extension_enable ( struct ast_rtp_instance instance,
enum ast_rtp_extension  extension 
)
static

Definition at line 9526 of file res_rtp_asterisk.c.

9527{
9528 switch (extension) {
9531 return 1;
9532 default:
9533 return 0;
9534 }
9535}
@ AST_RTP_EXTENSION_TRANSPORT_WIDE_CC
Definition: rtp_engine.h:599
@ AST_RTP_EXTENSION_ABS_SEND_TIME
Definition: rtp_engine.h:597
structure to hold extensions

References AST_RTP_EXTENSION_ABS_SEND_TIME, and AST_RTP_EXTENSION_TRANSPORT_WIDE_CC.

◆ ast_rtp_fd()

static int ast_rtp_fd ( struct ast_rtp_instance instance,
int  rtcp 
)
static
Precondition
instance is locked

Definition at line 9075 of file res_rtp_asterisk.c.

9076{
9077 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9078
9079 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9080}

References ast_rtp_instance_get_data(), ast_rtp::rtcp, ast_rtp::s, and ast_rtcp::s.

◆ ast_rtp_get_cname()

static const char * ast_rtp_get_cname ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 9473 of file res_rtp_asterisk.c.

9474{
9475 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9476
9477 return rtp->cname;
9478}

References ast_rtp_instance_get_data(), and ast_rtp::cname.

◆ ast_rtp_get_ssrc()

static unsigned int ast_rtp_get_ssrc ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 9465 of file res_rtp_asterisk.c.

9466{
9467 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9468
9469 return rtp->ssrc;
9470}

References ast_rtp_instance_get_data(), and ast_rtp::ssrc.

Referenced by __rtp_find_instance_by_ssrc().

◆ ast_rtp_get_stat()

static int ast_rtp_get_stat ( struct ast_rtp_instance instance,
struct ast_rtp_instance_stats stats,
enum ast_rtp_instance_stat  stat 
)
static
Precondition
instance is locked

Definition at line 9256 of file res_rtp_asterisk.c.

9257{
9258 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9259
9260 if (!rtp->rtcp) {
9261 return -1;
9262 }
9263
9268
9280
9292
9299
9311
9312
9316
9317 return 0;
9318}
#define AST_RTP_STAT_TERMINATOR(combined)
Definition: rtp_engine.h:500
@ AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS
Definition: rtp_engine.h:207
@ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS
Definition: rtp_engine.h:203
@ AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS
Definition: rtp_engine.h:199
@ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVMES
Definition: rtp_engine.h:270
@ AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER
Definition: rtp_engine.h:223
@ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVMES
Definition: rtp_engine.h:278
@ AST_RTP_INSTANCE_STAT_MIN_RTT
Definition: rtp_engine.h:243
@ AST_RTP_INSTANCE_STAT_TXMES
Definition: rtp_engine.h:262
@ AST_RTP_INSTANCE_STAT_CHANNEL_UNIQUEID
Definition: rtp_engine.h:253
@ AST_RTP_INSTANCE_STAT_TXPLOSS
Definition: rtp_engine.h:195
@ AST_RTP_INSTANCE_STAT_MAX_RTT
Definition: rtp_engine.h:241
@ AST_RTP_INSTANCE_STAT_RXPLOSS
Definition: rtp_engine.h:197
@ AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER
Definition: rtp_engine.h:221
@ AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER
Definition: rtp_engine.h:229
@ AST_RTP_INSTANCE_STAT_REMOTE_MINMES
Definition: rtp_engine.h:268
@ AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER
Definition: rtp_engine.h:227
@ AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS
Definition: rtp_engine.h:201
@ AST_RTP_INSTANCE_STAT_LOCAL_MINMES
Definition: rtp_engine.h:276
@ AST_RTP_INSTANCE_STAT_TXOCTETCOUNT
Definition: rtp_engine.h:255
@ AST_RTP_INSTANCE_STAT_RXMES
Definition: rtp_engine.h:264
@ AST_RTP_INSTANCE_STAT_REMOTE_STDEVMES
Definition: rtp_engine.h:272
@ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS
Definition: rtp_engine.h:211
@ AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS
Definition: rtp_engine.h:205
@ AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS
Definition: rtp_engine.h:213
@ AST_RTP_INSTANCE_STAT_REMOTE_MAXMES
Definition: rtp_engine.h:266
@ AST_RTP_INSTANCE_STAT_TXCOUNT
Definition: rtp_engine.h:189
@ AST_RTP_INSTANCE_STAT_STDEVRTT
Definition: rtp_engine.h:247
@ AST_RTP_INSTANCE_STAT_COMBINED_MES
Definition: rtp_engine.h:260
@ AST_RTP_INSTANCE_STAT_LOCAL_MAXMES
Definition: rtp_engine.h:274
@ AST_RTP_INSTANCE_STAT_RXJITTER
Definition: rtp_engine.h:219
@ AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS
Definition: rtp_engine.h:209
@ AST_RTP_INSTANCE_STAT_LOCAL_SSRC
Definition: rtp_engine.h:249
@ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER
Definition: rtp_engine.h:225
@ AST_RTP_INSTANCE_STAT_COMBINED_JITTER
Definition: rtp_engine.h:215
@ AST_RTP_INSTANCE_STAT_TXJITTER
Definition: rtp_engine.h:217
@ AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER
Definition: rtp_engine.h:231
@ AST_RTP_INSTANCE_STAT_COMBINED_LOSS
Definition: rtp_engine.h:193
@ AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER
Definition: rtp_engine.h:235
@ AST_RTP_INSTANCE_STAT_COMBINED_RTT
Definition: rtp_engine.h:237
@ AST_RTP_INSTANCE_STAT_NORMDEVRTT
Definition: rtp_engine.h:245
@ AST_RTP_INSTANCE_STAT_RTT
Definition: rtp_engine.h:239
@ AST_RTP_INSTANCE_STAT_RXOCTETCOUNT
Definition: rtp_engine.h:257
@ AST_RTP_INSTANCE_STAT_LOCAL_STDEVMES
Definition: rtp_engine.h:280
@ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER
Definition: rtp_engine.h:233
@ AST_RTP_INSTANCE_STAT_RXCOUNT
Definition: rtp_engine.h:191
@ AST_RTP_INSTANCE_STAT_REMOTE_SSRC
Definition: rtp_engine.h:251
#define AST_RTP_STAT_STRCPY(current_stat, combined, placement, value)
Definition: rtp_engine.h:492
#define AST_RTP_STAT_SET(current_stat, combined, placement, value)
Definition: rtp_engine.h:484
double maxrxmes
double maxrxlost
unsigned int received_prior
double reported_maxjitter
double reported_normdev_lost
double reported_minlost
double normdevrtt
double reported_normdev_mes
double stdevrtt
double minrxjitter
double reported_maxmes
unsigned int reported_lost
double reported_stdev_jitter
double normdev_rxjitter
double reported_stdev_lost
double normdev_rxlost
double reported_stdev_mes
double normdev_rxmes
double maxrxjitter
double reported_normdev_jitter
double reported_maxlost
double stdev_rxjitter
double reported_jitter
double reported_minjitter
double minrxlost
double minrxmes
unsigned int expected_prior
double reported_minmes
double stdev_rxlost
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
unsigned int rxcount
unsigned int rxoctetcount
double rxjitter

References ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), AST_RTP_INSTANCE_STAT_CHANNEL_UNIQUEID, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, AST_RTP_INSTANCE_STAT_COMBINED_MES, AST_RTP_INSTANCE_STAT_COMBINED_RTT, AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MAXMES, AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MINMES, AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVMES, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_SSRC, AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_STDEVMES, AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MAXMES, AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MINMES, AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVMES, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_SSRC, AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_STDEVMES, AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_RXCOUNT, AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_RXMES, AST_RTP_INSTANCE_STAT_RXOCTETCOUNT, AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_TXCOUNT, AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_TXMES, AST_RTP_INSTANCE_STAT_TXOCTETCOUNT, AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_STAT_SET, AST_RTP_STAT_STRCPY, AST_RTP_STAT_TERMINATOR, ast_rtp_instance_stats::channel_uniqueid, ast_rtcp::expected_prior, ast_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxmes, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minmes, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevmes, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevmes, ast_rtp_instance_stats::local_stdevrxploss, ast_rtp_instance_stats::maxrtt, ast_rtcp::maxrtt, ast_rtcp::maxrxjitter, ast_rtcp::maxrxlost, ast_rtcp::maxrxmes, ast_rtp_instance_stats::minrtt, ast_rtcp::minrtt, ast_rtcp::minrxjitter, ast_rtcp::minrxlost, ast_rtcp::minrxmes, ast_rtcp::normdev_rxjitter, ast_rtcp::normdev_rxlost, ast_rtcp::normdev_rxmes, ast_rtp_instance_stats::normdevrtt, ast_rtcp::normdevrtt, ast_rtcp::received_prior, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxmes, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minmes, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevmes, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevmes, ast_rtp_instance_stats::remote_stdevrxploss, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_maxmes, ast_rtcp::reported_mes, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_minmes, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_normdev_mes, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtcp::reported_stdev_mes, ast_rtp::rtcp, ast_rtp_instance_stats::rtt, ast_rtcp::rtt, ast_rtp_instance_stats::rxcount, ast_rtp::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp::rxjitter, ast_rtp_instance_stats::rxmes, ast_rtp::rxmes, ast_rtp_instance_stats::rxoctetcount, ast_rtp::rxoctetcount, ast_rtp_instance_stats::rxploss, ast_rtp::ssrc, ast_rtcp::stdev_rxjitter, ast_rtcp::stdev_rxlost, ast_rtp_instance_stats::stdevrtt, ast_rtcp::stdevrtt, ast_rtp::themssrc, ast_rtp_instance_stats::txcount, ast_rtp::txcount, ast_rtp_instance_stats::txjitter, ast_rtp_instance_stats::txmes, ast_rtp_instance_stats::txoctetcount, ast_rtp::txoctetcount, and ast_rtp_instance_stats::txploss.

◆ ast_rtp_interpret()

static struct ast_frame * ast_rtp_interpret ( struct ast_rtp_instance instance,
struct ast_srtp srtp,
const struct ast_sockaddr remote_address,
unsigned char *  read_area,
int  length,
int  prev_seqno,
unsigned int  bundled 
)
static

Definition at line 7780 of file res_rtp_asterisk.c.

7783{
7784 unsigned int *rtpheader = (unsigned int*)(read_area);
7785 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7786 struct ast_rtp_instance *instance1;
7787 int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc;
7788 unsigned int timestamp;
7789 RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
7790 struct frame_list frames;
7791
7792 /* If this payload is encrypted then decrypt it using the given SRTP instance */
7793 if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
7794 srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
7795 return &ast_null_frame;
7796 }
7797
7798 /* If we are currently sending DTMF to the remote party send a continuation packet */
7799 if (rtp->sending_digit) {
7800 ast_rtp_dtmf_continuation(instance);
7801 }
7802
7803 /* Pull out the various other fields we will need */
7804 ssrc = ntohl(rtpheader[2]);
7805 seqno = ntohl(rtpheader[0]);
7806 payloadtype = (seqno & 0x7f0000) >> 16;
7807 padding = seqno & (1 << 29);
7808 mark = seqno & (1 << 23);
7809 ext = seqno & (1 << 28);
7810 cc = (seqno & 0xF000000) >> 24;
7811 seqno &= 0xffff;
7812 timestamp = ntohl(rtpheader[1]);
7813
7815
7816 /* Remove any padding bytes that may be present */
7817 if (padding) {
7818 res -= read_area[res - 1];
7819 }
7820
7821 /* Skip over any CSRC fields */
7822 if (cc) {
7823 hdrlen += cc * 4;
7824 }
7825
7826 /* Look for any RTP extensions, currently we do not support any */
7827 if (ext) {
7828 int extensions_size = (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
7829 unsigned int profile;
7830 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
7831
7832 if (profile == 0xbede) {
7833 /* We skip over the first 4 bytes as they are just for the one byte extension header */
7834 rtp_instance_parse_extmap_extensions(instance, rtp, read_area + hdrlen + 4, extensions_size);
7835 } else if (DEBUG_ATLEAST(1)) {
7836 if (profile == 0x505a) {
7837 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
7838 } else {
7839 /* SDP negotiated RTP extensions can not currently be output in logging */
7840 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
7841 }
7842 }
7843
7844 hdrlen += extensions_size;
7845 hdrlen += 4;
7846 }
7847
7848 /* Make sure after we potentially mucked with the header length that it is once again valid */
7849 if (res < hdrlen) {
7850 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
7852 }
7853
7854 /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
7855 if (!bundled) {
7856 /* Force a marker bit and change SSRC if the SSRC changes */
7857 if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
7858 struct ast_frame *f, srcupdate = {
7860 .subclass.integer = AST_CONTROL_SRCCHANGE,
7861 };
7862
7863 if (!mark) {
7865 ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance);
7866 }
7867 mark = 1;
7868 }
7869
7870 f = ast_frisolate(&srcupdate);
7872
7873 rtp->seedrxseqno = 0;
7874 rtp->rxcount = 0;
7875 rtp->rxoctetcount = 0;
7876 rtp->cycles = 0;
7877 prev_seqno = 0;
7878 rtp->last_seqno = 0;
7879 rtp->last_end_timestamp.ts = 0;
7880 rtp->last_end_timestamp.is_set = 0;
7881 if (rtp->rtcp) {
7882 rtp->rtcp->expected_prior = 0;
7883 rtp->rtcp->received_prior = 0;
7884 }
7885 }
7886
7887 rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
7888 rtp->themssrc_valid = 1;
7889 }
7890
7891 rtp->rxcount++;
7892 rtp->rxoctetcount += (res - hdrlen);
7893 if (rtp->rxcount == 1) {
7894 rtp->seedrxseqno = seqno;
7895 }
7896
7897 /* Do not schedule RR if RTCP isn't run */
7898 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 0) {
7899 /* Schedule transmission of Receiver Report */
7900 ao2_ref(instance, +1);
7902 if (rtp->rtcp->schedid < 0) {
7903 ao2_ref(instance, -1);
7904 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
7905 }
7906 }
7907 if ((int)prev_seqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
7908 rtp->cycles += RTP_SEQ_MOD;
7909
7910 /* If we are directly bridged to another instance send the audio directly out,
7911 * but only after updating core information about the received traffic so that
7912 * outgoing RTCP reflects it.
7913 */
7914 instance1 = ast_rtp_instance_get_bridged(instance);
7915 if (instance1
7916 && !bridge_p2p_rtp_write(instance, instance1, rtpheader, res, hdrlen)) {
7917 struct timeval rxtime;
7918 struct ast_frame *f;
7919
7920 /* Update statistics for jitter so they are correct in RTCP */
7921 calc_rxstamp_and_jitter(&rxtime, rtp, timestamp, mark);
7922
7923
7924 /* When doing P2P we don't need to raise any frames about SSRC change to the core */
7925 while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list)) != NULL) {
7926 ast_frfree(f);
7927 }
7928
7929 return &ast_null_frame;
7930 }
7931
7932 payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
7933 if (!payload) {
7934 /* Unknown payload type. */
7936 }
7937
7938 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
7939 if (!payload->asterisk_format) {
7940 struct ast_frame *f = NULL;
7941 if (payload->rtp_code == AST_RTP_DTMF) {
7942 /* process_dtmf_rfc2833 may need to return multiple frames. We do this
7943 * by passing the pointer to the frame list to it so that the method
7944 * can append frames to the list as needed.
7945 */
7946 process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames);
7947 } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
7948 f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
7949 } else if (payload->rtp_code == AST_RTP_CN) {
7950 f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
7951 } else {
7952 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
7953 payloadtype,
7954 ast_sockaddr_stringify(remote_address));
7955 }
7956
7957 if (f) {
7959 }
7960 /* Even if no frame was returned by one of the above methods,
7961 * we may have a frame to return in our frame list
7962 */
7964 }
7965
7966 ao2_replace(rtp->lastrxformat, payload->format);
7967 ao2_replace(rtp->f.subclass.format, payload->format);
7968 switch (ast_format_get_type(rtp->f.subclass.format)) {
7971 break;
7974 break;
7976 rtp->f.frametype = AST_FRAME_TEXT;
7977 break;
7979 /* Fall through */
7980 default:
7981 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
7983 return &ast_null_frame;
7984 }
7985
7986 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
7987 rtp->dtmf_timeout = 0;
7988
7989 if (rtp->resp) {
7990 struct ast_frame *f;
7991 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
7993 rtp->resp = 0;
7994 rtp->dtmf_timeout = rtp->dtmf_duration = 0;
7996 return AST_LIST_FIRST(&frames);
7997 }
7998 }
7999
8000 rtp->f.src = "RTP";
8001 rtp->f.mallocd = 0;
8002 rtp->f.datalen = res - hdrlen;
8003 rtp->f.data.ptr = read_area + hdrlen;
8004 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
8006 rtp->f.seqno = seqno;
8007 rtp->f.stream_num = rtp->stream_num;
8008
8010 && ((int)seqno - (prev_seqno + 1) > 0)
8011 && ((int)seqno - (prev_seqno + 1) < 10)) {
8012 unsigned char *data = rtp->f.data.ptr;
8013
8014 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
8015 rtp->f.datalen +=3;
8016 *data++ = 0xEF;
8017 *data++ = 0xBF;
8018 *data = 0xBD;
8019 }
8020
8022 unsigned char *data = rtp->f.data.ptr;
8023 unsigned char *header_end;
8024 int num_generations;
8025 int header_length;
8026 int len;
8027 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
8028 int x;
8029
8031 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
8032 if (header_end == NULL) {
8034 }
8035 header_end++;
8036
8037 header_length = header_end - data;
8038 num_generations = header_length / 4;
8039 len = header_length;
8040
8041 if (!diff) {
8042 for (x = 0; x < num_generations; x++)
8043 len += data[x * 4 + 3];
8044
8045 if (!(rtp->f.datalen - len))
8047
8048 rtp->f.data.ptr += len;
8049 rtp->f.datalen -= len;
8050 } else if (diff > num_generations && diff < 10) {
8051 len -= 3;
8052 rtp->f.data.ptr += len;
8053 rtp->f.datalen -= len;
8054
8055 data = rtp->f.data.ptr;
8056 *data++ = 0xEF;
8057 *data++ = 0xBF;
8058 *data = 0xBD;
8059 } else {
8060 for ( x = 0; x < num_generations - diff; x++)
8061 len += data[x * 4 + 3];
8062
8063 rtp->f.data.ptr += len;
8064 rtp->f.datalen -= len;
8065 }
8066 }
8067
8069 rtp->f.samples = ast_codec_samples_count(&rtp->f);
8071 ast_frame_byteswap_be(&rtp->f);
8072 }
8073 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8074 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
8076 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8077 rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
8079 /* Video -- samples is # of samples vs. 90000 */
8080 if (!rtp->lastividtimestamp)
8081 rtp->lastividtimestamp = timestamp;
8082 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8084 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8085 rtp->f.samples = timestamp - rtp->lastividtimestamp;
8086 rtp->lastividtimestamp = timestamp;
8087 rtp->f.delivery.tv_sec = 0;
8088 rtp->f.delivery.tv_usec = 0;
8089 /* Pass the RTP marker bit as bit */
8090 rtp->f.subclass.frame_ending = mark ? 1 : 0;
8092 /* TEXT -- samples is # of samples vs. 1000 */
8093 if (!rtp->lastitexttimestamp)
8094 rtp->lastitexttimestamp = timestamp;
8095 rtp->f.samples = timestamp - rtp->lastitexttimestamp;
8096 rtp->lastitexttimestamp = timestamp;
8097 rtp->f.delivery.tv_sec = 0;
8098 rtp->f.delivery.tv_usec = 0;
8099 } else {
8100 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8102 return &ast_null_frame;
8103 }
8104
8106 return AST_LIST_FIRST(&frames);
8107}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
@ AST_MEDIA_TYPE_IMAGE
Definition: codec.h:34
@ AST_MEDIA_TYPE_TEXT
Definition: codec.h:35
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Definition: codec.c:379
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
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
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
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
Definition: format_cache.c:534
struct ast_format * ast_format_t140_red
Built-in cached t140 red format.
Definition: format_cache.c:236
struct ast_format * ast_format_t140
Built-in cached t140 format.
Definition: format_cache.c:231
const char * ext
Definition: http.c:150
#define ast_frame_byteswap_be(fr)
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
@ AST_FRAME_VIDEO
@ AST_FRAME_DTMF_END
@ AST_FRAME_VOICE
@ AST_FRAME_TEXT
@ AST_FRFLAG_HAS_SEQUENCE_NUMBER
@ AST_FRFLAG_HAS_TIMING_INFO
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define LOG_NOTICE
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
static int frames
Definition: parser.c:51
static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, struct ast_rtp_instance *instance1, unsigned int *rtpheader, int len, int hdrlen)
static void calc_rxstamp_and_jitter(struct timeval *tv, struct ast_rtp *rtp, unsigned int rx_rtp_ts, int mark)
static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark, struct frame_list *frames)
static struct ast_frame * process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
static void rtp_instance_parse_extmap_extensions(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *extension, int len)
static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
static struct ast_frame * process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
#define RTP_SEQ_MOD
static struct ast_frame * create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
static int ast_rtcp_write(const void *data)
Write a RTCP packet to the far end.
struct ast_rtp_instance * ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
Get the other RTP instance that an instance is bridged to.
Definition: rtp_engine.c:2416
#define AST_RTP_CN
Definition: rtp_engine.h:296
#define AST_RTP_CISCO_DTMF
Definition: rtp_engine.h:298
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:567
unsigned int lastividtimestamp
unsigned int dtmf_duration
unsigned short seedrxseqno
unsigned int last_seqno
unsigned int dtmf_timeout
optional_ts last_end_timestamp
unsigned int lastitexttimestamp
unsigned int ts
unsigned char is_set
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
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

References ao2_cleanup, ao2_ref, ao2_replace, ast_codec_media_type2str(), ast_codec_samples_count(), AST_CONTROL_SRCCHANGE, ast_debug, ast_debug_rtp_packet_is_allowed, ast_format_cache_is_slinear(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_sample_rate(), ast_format_get_type(), ast_format_t140, ast_format_t140_red, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_SEQUENCE_NUMBER, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, AST_FRIENDLY_OFFSET, ast_frisolate, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_IMAGE, AST_MEDIA_TYPE_TEXT, AST_MEDIA_TYPE_VIDEO, ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, ast_rtp_codecs_get_payload(), AST_RTP_DTMF, ast_rtp_dtmf_continuation(), ast_rtp_get_rate(), ast_rtp_instance_get_bridged(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), bridge_p2p_rtp_write(), calc_rxstamp_and_jitter(), create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, DEBUG_ATLEAST, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtcp::expected_prior, ext, ast_rtp::f, ast_frame_subclass::format, ast_frame_subclass::frame_ending, frames, ast_frame::frametype, optional_ts::is_set, ast_rtp::last_end_timestamp, ast_rtp::last_seqno, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, len(), ast_frame::len, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, NULL, ast_frame::offset, process_cn_rfc3389(), process_dtmf_cisco(), process_dtmf_rfc2833(), ast_frame::ptr, RAII_VAR, ast_rtcp::received_prior, res_srtp, ast_rtp::resp, ast_rtp::rtcp, rtp_instance_parse_extmap_extensions(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxoctetcount, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, srtp_replay_protection, ast_frame::stream_num, ast_rtp::stream_num, ast_frame::subclass, ast_rtcp::them, ast_rtp::themssrc, ast_rtp::themssrc_valid, ast_frame::ts, optional_ts::ts, and ast_srtp_res::unprotect.

Referenced by ast_rtp_read().

◆ ast_rtp_local_bridge()

static int ast_rtp_local_bridge ( struct ast_rtp_instance instance0,
struct ast_rtp_instance instance1 
)
static
Precondition
Neither instance0 nor instance1 are locked

Definition at line 9228 of file res_rtp_asterisk.c.

9229{
9230 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
9231
9232 ao2_lock(instance0);
9234 if (rtp->smoother) {
9236 rtp->smoother = NULL;
9237 }
9238
9239 /* We must use a new SSRC when local bridge ends */
9240 if (!instance1) {
9241 rtp->ssrc = rtp->ssrc_orig;
9242 rtp->ssrc_orig = 0;
9243 rtp->ssrc_saved = 0;
9244 } else if (!rtp->ssrc_saved) {
9245 /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
9246 rtp->ssrc_orig = rtp->ssrc;
9247 rtp->ssrc_saved = 1;
9248 }
9249
9250 ao2_unlock(instance0);
9251
9252 return 0;
9253}
#define FLAG_REQ_LOCAL_BRIDGE_BIT
unsigned int ssrc_orig
unsigned char ssrc_saved

References ao2_lock, ao2_unlock, ast_rtp_instance_get_data(), ast_set_flag, ast_smoother_free(), FLAG_NEED_MARKER_BIT, FLAG_REQ_LOCAL_BRIDGE_BIT, NULL, ast_rtp::smoother, ast_rtp::ssrc, ast_rtp::ssrc_orig, and ast_rtp::ssrc_saved.

◆ ast_rtp_new()

static int ast_rtp_new ( struct ast_rtp_instance instance,
struct ast_sched_context sched,
struct ast_sockaddr addr,
void *  data 
)
static
Precondition
instance is locked

Definition at line 4209 of file res_rtp_asterisk.c.

4212{
4213 struct ast_rtp *rtp = NULL;
4214
4215 /* Create a new RTP structure to hold all of our data */
4216 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
4217 return -1;
4218 }
4219 rtp->owner = instance;
4220 /* Set default parameters on the newly created RTP structure */
4221 rtp->ssrc = ast_random();
4222 ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname));
4223 rtp->seqno = ast_random() & 0xffff;
4224 rtp->expectedrxseqno = -1;
4225 rtp->expectedseqno = -1;
4226 rtp->rxstart = -1;
4227 rtp->sched = sched;
4228 ast_sockaddr_copy(&rtp->bind_address, addr);
4229 /* Transport creation operations can grab the RTP data from the instance, so set it */
4230 ast_rtp_instance_set_data(instance, rtp);
4231
4232 if (rtp_allocate_transport(instance, rtp)) {
4233 return -1;
4234 }
4235
4236 if (AST_VECTOR_INIT(&rtp->ssrc_mapping, 1)) {
4237 return -1;
4238 }
4239
4241 return -1;
4242 }
4243 rtp->transport_wide_cc.schedid = -1;
4244
4248 rtp->stream_num = -1;
4249
4250 return 0;
4251}
static struct ast_sched_context * sched
Definition: chan_ooh323.c:400
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition: rtp_engine.c:586
double rxstart
struct ast_sockaddr bind_address
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:124

References ao2_bump, ast_calloc, ast_format_none, ast_random(), ast_rtp_instance_set_data(), ast_sockaddr_copy(), ast_uuid_generate_str(), AST_VECTOR_INIT, ast_rtp::bind_address, ast_rtp::cname, ast_rtp::expectedrxseqno, ast_rtp::expectedseqno, ast_rtp::f, ast_frame_subclass::format, ast_rtp::lastrxformat, ast_rtp::lasttxformat, NULL, ast_rtp::owner, rtp_transport_wide_cc_statistics::packet_statistics, rtp_allocate_transport(), ast_rtp::rxstart, sched, ast_rtp::sched, rtp_transport_wide_cc_statistics::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::ssrc_mapping, ast_rtp::stream_num, ast_frame::subclass, and ast_rtp::transport_wide_cc.

◆ ast_rtp_prop_set()

static void ast_rtp_prop_set ( struct ast_rtp_instance instance,
enum ast_rtp_property  property,
int  value 
)
static
Precondition
instance is locked

Definition at line 8886 of file res_rtp_asterisk.c.

8887{
8888 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8889
8890 if (property == AST_RTP_PROPERTY_RTCP) {
8891 if (value) {
8892 struct ast_sockaddr local_addr;
8893
8894 if (rtp->rtcp && rtp->rtcp->type == value) {
8895 ast_debug_rtcp(1, "(%p) RTCP ignoring duplicate property\n", instance);
8896 return;
8897 }
8898
8899 if (!rtp->rtcp) {
8900 rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
8901 if (!rtp->rtcp) {
8902 return;
8903 }
8904 rtp->rtcp->s = -1;
8905#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8906 rtp->rtcp->dtls.timeout_timer = -1;
8907#endif
8908 rtp->rtcp->schedid = -1;
8909 }
8910
8911 rtp->rtcp->type = value;
8912
8913 /* Grab the IP address and port we are going to use */
8914 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
8917 ast_sockaddr_port(&rtp->rtcp->us) + 1);
8918 }
8919
8920 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
8921 if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
8922 ast_sockaddr_set_port(&local_addr, ast_sockaddr_port(&rtp->rtcp->us));
8923 } else {
8924 /* Failed to get local address reset to use default. */
8925 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
8926 }
8927
8930 if (!rtp->rtcp->local_addr_str) {
8931 ast_free(rtp->rtcp);
8932 rtp->rtcp = NULL;
8933 return;
8934 }
8935
8937 /* We're either setting up RTCP from scratch or
8938 * switching from MUX. Either way, we won't have
8939 * a socket set up, and we need to set it up
8940 */
8941 if ((rtp->rtcp->s =
8942 create_new_socket("RTCP",
8943 ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
8944 AF_INET :
8945 ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
8946 AF_INET6 : -1)) < 0) {
8947 ast_debug_rtcp(1, "(%p) RTCP failed to create a new socket\n", instance);
8949 ast_free(rtp->rtcp);
8950 rtp->rtcp = NULL;
8951 return;
8952 }
8953
8954 /* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
8955 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
8956 ast_debug_rtcp(1, "(%p) RTCP failed to setup RTP instance\n", instance);
8957 close(rtp->rtcp->s);
8959 ast_free(rtp->rtcp);
8960 rtp->rtcp = NULL;
8961 return;
8962 }
8963#ifdef HAVE_PJPROJECT
8964 if (rtp->ice) {
8965 rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
8966 }
8967#endif
8968#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8969 dtls_setup_rtcp(instance);
8970#endif
8971 } else {
8972 struct ast_sockaddr addr;
8973 /* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
8974 * then close the socket we previously created.
8975 *
8976 * It may seem as though there is a possible race condition here where we might try
8977 * to close the RTCP socket while it is being used to send data. However, this is not
8978 * a problem in practice since setting and adjusting of RTCP properties happens prior
8979 * to activating RTP. It is not until RTP is activated that timers start for RTCP
8980 * transmission
8981 */
8982 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
8983 close(rtp->rtcp->s);
8984 }
8985 rtp->rtcp->s = rtp->s;
8986 ast_rtp_instance_get_remote_address(instance, &addr);
8987 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
8988#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8989 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
8990 SSL_free(rtp->rtcp->dtls.ssl);
8991 }
8992 rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
8993#endif
8994 }
8995
8996 ast_debug_rtcp(1, "(%s) RTCP setup on RTP instance\n",
8998 } else {
8999 if (rtp->rtcp) {
9000 if (rtp->rtcp->schedid > -1) {
9001 ao2_unlock(instance);
9002 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9003 /* Successfully cancelled scheduler entry. */
9004 ao2_ref(instance, -1);
9005 } else {
9006 /* Unable to cancel scheduler entry */
9007 ast_debug_rtcp(1, "(%p) RTCP failed to tear down RTCP\n", instance);
9008 ao2_lock(instance);
9009 return;
9010 }
9011 ao2_lock(instance);
9012 rtp->rtcp->schedid = -1;
9013 }
9014 if (rtp->transport_wide_cc.schedid > -1) {
9015 ao2_unlock(instance);
9016 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9017 ao2_ref(instance, -1);
9018 } else {
9019 ast_debug_rtcp(1, "(%p) RTCP failed to tear down transport-cc feedback\n", instance);
9020 ao2_lock(instance);
9021 return;
9022 }
9023 ao2_lock(instance);
9024 rtp->transport_wide_cc.schedid = -1;
9025 }
9026 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9027 close(rtp->rtcp->s);
9028 }
9029#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9030 ao2_unlock(instance);
9031 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9032 ao2_lock(instance);
9033
9034 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9035 SSL_free(rtp->rtcp->dtls.ssl);
9036 }
9037#endif
9039 ast_free(rtp->rtcp);
9040 rtp->rtcp = NULL;
9041 ast_debug_rtcp(1, "(%s) RTCP torn down on RTP instance\n",
9043 }
9044 }
9045 } else if (property == AST_RTP_PROPERTY_ASYMMETRIC_CODEC) {
9046 rtp->asymmetric_codec = value;
9047 } else if (property == AST_RTP_PROPERTY_RETRANS_SEND) {
9048 if (value) {
9049 if (!rtp->send_buffer) {
9051 }
9052 } else {
9053 if (rtp->send_buffer) {
9055 rtp->send_buffer = NULL;
9056 }
9057 }
9058 } else if (property == AST_RTP_PROPERTY_RETRANS_RECV) {
9059 if (value) {
9060 if (!rtp->recv_buffer) {
9063 }
9064 } else {
9065 if (rtp->recv_buffer) {
9067 rtp->recv_buffer = NULL;
9069 }
9070 }
9071 }
9072}
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
Definition: acl.c:1068
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
struct ast_data_buffer * ast_data_buffer_alloc(ast_data_buffer_free_callback free_fn, size_t size)
Allocate a data buffer.
Definition: data_buffer.c:145
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
#define DEFAULT_RTP_RECV_BUFFER_SIZE
static int create_new_socket(const char *type, int af)
#define DEFAULT_RTP_SEND_BUFFER_SIZE
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition: rtp_engine.h:287
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:671
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition: rtp_engine.h:130
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition: rtp_engine.h:132
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:126
@ AST_RTP_PROPERTY_ASYMMETRIC_CODEC
Definition: rtp_engine.h:128
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:614
enum ast_rtp_instance_rtcp type
struct ast_sockaddr us
unsigned int asymmetric_codec
int value
Definition: syslog.c:37

References ao2_lock, ao2_ref, ao2_unlock, ast_bind(), ast_calloc, ast_data_buffer_alloc(), ast_data_buffer_free(), ast_debug_rtcp, ast_find_ourip(), ast_free, ast_free_ptr(), AST_RTP_ICE_COMPONENT_RTCP, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, AST_RTP_INSTANCE_RTCP_STANDARD, AST_RTP_PROPERTY_ASYMMETRIC_CODEC, AST_RTP_PROPERTY_RETRANS_RECV, AST_RTP_PROPERTY_RETRANS_SEND, AST_RTP_PROPERTY_RTCP, ast_sched_del(), ast_sockaddr_copy(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdup, AST_VECTOR_FREE, AST_VECTOR_INIT, ast_rtp::asymmetric_codec, create_new_socket(), DEFAULT_RTP_RECV_BUFFER_SIZE, DEFAULT_RTP_SEND_BUFFER_SIZE, ast_rtcp::local_addr_str, ast_rtp::missing_seqno, NULL, ast_rtp::recv_buffer, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, ast_rtp::sched, rtp_transport_wide_cc_statistics::schedid, ast_rtcp::schedid, ast_rtp::send_buffer, ast_rtcp::them, TRANSPORT_SOCKET_RTCP, ast_rtp::transport_wide_cc, ast_rtcp::type, ast_rtcp::us, and value.

◆ ast_rtp_qos_set()

static int ast_rtp_qos_set ( struct ast_rtp_instance instance,
int  tos,
int  cos,
const char *  desc 
)
static
Precondition
instance is locked

Definition at line 9404 of file res_rtp_asterisk.c.

9405{
9406 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9407
9408 return ast_set_qos(rtp->s, tos, cos, desc);
9409}
static const char desc[]
Definition: cdr_radius.c:84
unsigned int tos
Definition: chan_iax2.c:379
unsigned int cos
Definition: chan_iax2.c:380
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621

References ast_rtp_instance_get_data(), ast_set_qos(), cos, desc, ast_rtp::s, and tos.

◆ ast_rtp_read()

static struct ast_frame * ast_rtp_read ( struct ast_rtp_instance instance,
int  rtcp 
)
static
Precondition
instance is locked

Definition at line 8219 of file res_rtp_asterisk.c.

8220{
8221 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8222 struct ast_srtp *srtp;
8224 struct ast_sockaddr addr;
8225 int res, hdrlen = 12, version, payloadtype;
8226 unsigned char *read_area = rtp->rawdata + AST_FRIENDLY_OFFSET;
8227 size_t read_area_size = sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET;
8228 unsigned int *rtpheader = (unsigned int*)(read_area), seqno, ssrc, timestamp, prev_seqno;
8229 struct ast_sockaddr remote_address = { {0,} };
8230 struct frame_list frames;
8231 struct ast_frame *frame;
8232 unsigned int bundled;
8233
8234 /* If this is actually RTCP let's hop on over and handle it */
8235 if (rtcp) {
8236 if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
8237 return ast_rtcp_read(instance);
8238 }
8239 return &ast_null_frame;
8240 }
8241
8242 /* Actually read in the data from the socket */
8243 if ((res = rtp_recvfrom(instance, read_area, read_area_size, 0,
8244 &addr)) < 0) {
8245 if (res == RTP_DTLS_ESTABLISHED) {
8248 return &rtp->f;
8249 }
8250
8251 ast_assert(errno != EBADF);
8252 if (errno != EAGAIN) {
8253 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n",
8254 (errno) ? strerror(errno) : "Unspecified");
8255 return NULL;
8256 }
8257 return &ast_null_frame;
8258 }
8259
8260 /* If this was handled by the ICE session don't do anything */
8261 if (!res) {
8262 return &ast_null_frame;
8263 }
8264
8265 /* This could be a multiplexed RTCP packet. If so, be sure to interpret it correctly */
8266 if (rtcp_mux(rtp, read_area)) {
8267 return ast_rtcp_interpret(instance, ast_rtp_instance_get_srtp(instance, 1), read_area, res, &addr);
8268 }
8269
8270 /* Make sure the data that was read in is actually enough to make up an RTP packet */
8271 if (res < hdrlen) {
8272 /* If this is a keepalive containing only nulls, don't bother with a warning */
8273 int i;
8274 for (i = 0; i < res; ++i) {
8275 if (read_area[i] != '\0') {
8276 ast_log(LOG_WARNING, "RTP Read too short\n");
8277 return &ast_null_frame;
8278 }
8279 }
8280 return &ast_null_frame;
8281 }
8282
8283 /* Get fields and verify this is an RTP packet */
8284 seqno = ntohl(rtpheader[0]);
8285
8286 ast_rtp_instance_get_remote_address(instance, &remote_address);
8287
8288 if (!(version = (seqno & 0xC0000000) >> 30)) {
8289 struct sockaddr_in addr_tmp;
8290 struct ast_sockaddr addr_v4;
8291 if (ast_sockaddr_is_ipv4(&addr)) {
8292 ast_sockaddr_to_sin(&addr, &addr_tmp);
8293 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
8294 ast_debug_stun(1, "(%p) STUN using IPv6 mapped address %s\n",
8295 instance, ast_sockaddr_stringify(&addr));
8296 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
8297 } else {
8298 ast_debug_stun(1, "(%p) STUN cannot do for non IPv4 address %s\n",
8299 instance, ast_sockaddr_stringify(&addr));
8300 return &ast_null_frame;
8301 }
8302 if ((ast_stun_handle_packet(rtp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT) &&
8303 ast_sockaddr_isnull(&remote_address)) {
8304 ast_sockaddr_from_sin(&addr, &addr_tmp);
8305 ast_rtp_instance_set_remote_address(instance, &addr);
8306 }
8307 return &ast_null_frame;
8308 }
8309
8310 /* If the version is not what we expected by this point then just drop the packet */
8311 if (version != 2) {
8312 return &ast_null_frame;
8313 }
8314
8315 /* We use the SSRC to determine what RTP instance this packet is actually for */
8316 ssrc = ntohl(rtpheader[2]);
8317
8318 /* We use the SRTP data from the provided instance that it came in on, not the child */
8319 srtp = ast_rtp_instance_get_srtp(instance, 0);
8320
8321 /* Determine the appropriate instance for this */
8322 child = rtp_find_instance_by_packet_source_ssrc(instance, rtp, ssrc);
8323 if (!child) {
8324 /* Neither the bundled parent nor any child has this SSRC */
8325 return &ast_null_frame;
8326 }
8327 if (child != instance) {
8328 /* It is safe to hold the child lock while holding the parent lock, we guarantee that the locking order
8329 * is always parent->child or that the child lock is not held when acquiring the parent lock.
8330 */
8331 ao2_lock(child);
8332 instance = child;
8333 rtp = ast_rtp_instance_get_data(instance);
8334 } else {
8335 /* The child is the parent! We don't need to unlock it. */
8336 child = NULL;
8337 }
8338
8339 /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
8340 switch (rtp->strict_rtp_state) {
8341 case STRICT_RTP_LEARN:
8342 /*
8343 * Scenario setup:
8344 * PartyA -- Ast1 -- Ast2 -- PartyB
8345 *
8346 * The learning timeout is necessary for Ast1 to handle the above
8347 * setup where PartyA calls PartyB and Ast2 initiates direct media
8348 * between Ast1 and PartyB. Ast1 may lock onto the Ast2 stream and
8349 * never learn the PartyB stream when it starts. The timeout makes
8350 * Ast1 stay in the learning state long enough to see and learn the
8351 * RTP stream from PartyB.
8352 *
8353 * To mitigate against attack, the learning state cannot switch
8354 * streams while there are competing streams. The competing streams
8355 * interfere with each other's qualification. Once we accept a
8356 * stream and reach the timeout, an attacker cannot interfere
8357 * anymore.
8358 *
8359 * Here are a few scenarios and each one assumes that the streams
8360 * are continuous:
8361 *
8362 * 1) We already have a known stream source address and the known
8363 * stream wants to change to a new source address. An attacking
8364 * stream will block learning the new stream source. After the
8365 * timeout we re-lock onto the original stream source address which
8366 * likely went away. The result is one way audio.
8367 *
8368 * 2) We already have a known stream source address and the known
8369 * stream doesn't want to change source addresses. An attacking
8370 * stream will not be able to replace the known stream. After the
8371 * timeout we re-lock onto the known stream. The call is not
8372 * affected.
8373 *
8374 * 3) We don't have a known stream source address. This presumably
8375 * is the start of a call. Competing streams will result in staying
8376 * in learning mode until a stream becomes the victor and we reach
8377 * the timeout. We cannot exit learning if we have no known stream
8378 * to lock onto. The result is one way audio until there is a victor.
8379 *
8380 * If we learn a stream source address before the timeout we will be
8381 * in scenario 1) or 2) when a competing stream starts.
8382 */
8385 ast_verb(4, "%p -- Strict RTP learning complete - Locking on source address %s\n",
8387 ast_test_suite_event_notify("STRICT_RTP_LEARN", "Source: %s",
8390 } else {
8391 struct ast_sockaddr target_address;
8392
8393 if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
8394 /*
8395 * We are open to learning a new address but have received
8396 * traffic from the current address, accept it and reset
8397 * the learning counts for a new source. When no more
8398 * current source packets arrive a new source can take over
8399 * once sufficient traffic is received.
8400 */
8402 break;
8403 }
8404
8405 /*
8406 * We give preferential treatment to the requested target address
8407 * (negotiated SDP address) where we are to send our RTP. However,
8408 * the other end has no obligation to send from that address even
8409 * though it is practically a requirement when NAT is involved.
8410 */
8411 ast_rtp_instance_get_requested_target_address(instance, &target_address);
8412 if (!ast_sockaddr_cmp(&target_address, &addr)) {
8413 /* Accept the negotiated target RTP stream as the source */
8414 ast_verb(4, "%p -- Strict RTP switching to RTP target address %s as source\n",
8415 rtp, ast_sockaddr_stringify(&addr));
8418 break;
8419 }
8420
8421 /*
8422 * Trying to learn a new address. If we pass a probationary period
8423 * with it, that means we've stopped getting RTP from the original
8424 * source and we should switch to it.
8425 */
8428 struct ast_rtp_codecs *codecs;
8429
8433 ast_verb(4, "%p -- Strict RTP qualifying stream type: %s\n",
8435 }
8436 if (!rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
8437 /* Accept the new RTP stream */
8438 ast_verb(4, "%p -- Strict RTP switching source address to %s\n",
8439 rtp, ast_sockaddr_stringify(&addr));
8442 break;
8443 }
8444 /* Not ready to accept the RTP stream candidate */
8445 ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection. Will switch to it in %d packets.\n",
8446 instance, rtp, ast_sockaddr_stringify(&addr), rtp->rtp_source_learn.packets);
8447 } else {
8448 /*
8449 * This is either an attacking stream or
8450 * the start of the expected new stream.
8451 */
8454 ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection. Qualifying new stream.\n",
8455 instance, rtp, ast_sockaddr_stringify(&addr));
8456 }
8457 return &ast_null_frame;
8458 }
8459 /* Fall through */
8460 case STRICT_RTP_CLOSED:
8461 /*
8462 * We should not allow a stream address change if the SSRC matches
8463 * once strictrtp learning is closed. Any kind of address change
8464 * like this should have happened while we were in the learning
8465 * state. We do not want to allow the possibility of an attacker
8466 * interfering with the RTP stream after the learning period.
8467 * An attacker could manage to get an RTCP packet redirected to
8468 * them which can contain the SSRC value.
8469 */
8470 if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
8471 break;
8472 }
8473 ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection.\n",
8474 instance, rtp, ast_sockaddr_stringify(&addr));
8475#ifdef TEST_FRAMEWORK
8476 {
8477 static int strict_rtp_test_event = 1;
8478 if (strict_rtp_test_event) {
8479 ast_test_suite_event_notify("STRICT_RTP_CLOSED", "Source: %s",
8480 ast_sockaddr_stringify(&addr));
8481 strict_rtp_test_event = 0; /* Only run this event once to prevent possible spam */
8482 }
8483 }
8484#endif
8485 return &ast_null_frame;
8486 case STRICT_RTP_OPEN:
8487 break;
8488 }
8489
8490 /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
8492 if (ast_sockaddr_cmp(&remote_address, &addr)) {
8493 /* do not update the originally given address, but only the remote */
8495 ast_sockaddr_copy(&remote_address, &addr);
8496 if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
8497 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
8499 }
8502 ast_debug(0, "(%p) RTP NAT: Got audio from other end. Now sending to address %s\n",
8503 instance, ast_sockaddr_stringify(&remote_address));
8504 }
8505 }
8506
8507 /* Pull out the various other fields we will need */
8508 payloadtype = (seqno & 0x7f0000) >> 16;
8509 seqno &= 0xffff;
8510 timestamp = ntohl(rtpheader[1]);
8511
8512#ifdef AST_DEVMODE
8513 if (should_drop_packets(&addr)) {
8514 ast_debug(0, "(%p) RTP: drop received packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
8515 instance, ast_sockaddr_stringify(&addr), payloadtype, seqno, timestamp, res - hdrlen);
8516 return &ast_null_frame;
8517 }
8518#endif
8519
8520 if (rtp_debug_test_addr(&addr)) {
8521 ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
8523 payloadtype, seqno, timestamp, res - hdrlen);
8524 }
8525
8527
8528 bundled = (child || AST_VECTOR_SIZE(&rtp->ssrc_mapping)) ? 1 : 0;
8529
8530 prev_seqno = rtp->lastrxseqno;
8531 /* We need to save lastrxseqno for use by jitter before resetting it. */
8532 rtp->prevrxseqno = rtp->lastrxseqno;
8533 rtp->lastrxseqno = seqno;
8534
8535 if (!rtp->recv_buffer) {
8536 /* If there is no receive buffer then we can pass back the frame directly */
8537 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8539 return AST_LIST_FIRST(&frames);
8540 } else if (rtp->expectedrxseqno == -1 || seqno == rtp->expectedrxseqno) {
8541 rtp->expectedrxseqno = seqno + 1;
8542
8543 /* We've cycled over, so go back to 0 */
8544 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8545 rtp->expectedrxseqno = 0;
8546 }
8547
8548 /* If there are no buffered packets that will be placed after this frame then we can
8549 * return it directly without duplicating it.
8550 */
8552 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8554 return AST_LIST_FIRST(&frames);
8555 }
8556
8559 ast_debug_rtp(2, "(%p) RTP Packet with sequence number '%d' on instance is no longer missing\n",
8560 instance, seqno);
8561 }
8562
8563 /* If we don't have the next packet after this we can directly return the frame, as there is no
8564 * chance it will be overwritten.
8565 */
8567 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8569 return AST_LIST_FIRST(&frames);
8570 }
8571
8572 /* Otherwise we need to dupe the frame so that the potential processing of frames placed after
8573 * it do not overwrite the data. You may be thinking that we could just add the current packet
8574 * to the head of the frames list and avoid having to duplicate it but this would result in out
8575 * of order packet processing by libsrtp which we are trying to avoid.
8576 */
8577 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled));
8578 if (frame) {
8580 prev_seqno = seqno;
8581 }
8582
8583 /* Add any additional packets that we have buffered and that are available */
8584 while (ast_data_buffer_count(rtp->recv_buffer)) {
8585 struct ast_rtp_rtcp_nack_payload *payload;
8586
8588 if (!payload) {
8589 break;
8590 }
8591
8592 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled));
8593 ast_free(payload);
8594
8595 if (!frame) {
8596 /* If this packet can't be interpreted due to being out of memory we return what we have and assume
8597 * that we will determine it is a missing packet later and NACK for it.
8598 */
8599 return AST_LIST_FIRST(&frames);
8600 }
8601
8602 ast_debug_rtp(2, "(%p) RTP pulled buffered packet with sequence number '%d' to additionally return\n",
8603 instance, frame->seqno);
8605 prev_seqno = rtp->expectedrxseqno;
8606 rtp->expectedrxseqno++;
8607 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8608 rtp->expectedrxseqno = 0;
8609 }
8610 }
8611
8612 return AST_LIST_FIRST(&frames);
8613 } else if ((((seqno - rtp->expectedrxseqno) > 100) && timestamp > rtp->lastividtimestamp) ||
8615 int inserted = 0;
8616
8617 /* We have a large number of outstanding buffered packets or we've jumped far ahead in time.
8618 * To compensate we dump what we have in the buffer and place the current packet in a logical
8619 * spot. In the case of video we also require a full frame to give the decoding side a fighting
8620 * chance.
8621 */
8622
8624 ast_debug_rtp(2, "(%p) RTP source has wild gap or packet loss, sending FIR\n",
8625 instance);
8626 rtp_write_rtcp_fir(instance, rtp, &remote_address);
8627 }
8628
8629 /* This works by going through the progression of the sequence number retrieving buffered packets
8630 * or inserting the current received packet until we've run out of packets. This ensures that the
8631 * packets are in the correct sequence number order.
8632 */
8633 while (ast_data_buffer_count(rtp->recv_buffer)) {
8634 struct ast_rtp_rtcp_nack_payload *payload;
8635
8636 /* If the packet we received is the one we are expecting at this point then add it in */
8637 if (rtp->expectedrxseqno == seqno) {
8638 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled));
8639 if (frame) {
8641 prev_seqno = seqno;
8642 ast_debug_rtp(2, "(%p) RTP inserted just received packet with sequence number '%d' in correct order\n",
8643 instance, seqno);
8644 }
8645 /* It is possible due to packet retransmission for this packet to also exist in the receive
8646 * buffer so we explicitly remove it in case this occurs, otherwise the receive buffer will
8647 * never be empty.
8648 */
8649 payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_remove(rtp->recv_buffer, seqno);
8650 if (payload) {
8651 ast_free(payload);
8652 }
8653 rtp->expectedrxseqno++;
8654 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8655 rtp->expectedrxseqno = 0;
8656 }
8657 inserted = 1;
8658 continue;
8659 }
8660
8662 if (payload) {
8663 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled));
8664 if (frame) {
8666 prev_seqno = rtp->expectedrxseqno;
8667 ast_debug_rtp(2, "(%p) RTP emptying queue and returning packet with sequence number '%d'\n",
8668 instance, frame->seqno);
8669 }
8670 ast_free(payload);
8671 }
8672
8673 rtp->expectedrxseqno++;
8674 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8675 rtp->expectedrxseqno = 0;
8676 }
8677 }
8678
8679 if (!inserted) {
8680 /* This current packet goes after them, and we assume that packets going forward will follow
8681 * that new sequence number increment. It is okay for this to not be duplicated as it is guaranteed
8682 * to be the last packet processed right now and it is also guaranteed that it will always return
8683 * non-NULL.
8684 */
8685 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8687 rtp->expectedrxseqno = seqno + 1;
8688 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8689 rtp->expectedrxseqno = 0;
8690 }
8691
8692 ast_debug_rtp(2, "(%p) RTP adding just received packet with sequence number '%d' to end of dumped queue\n",
8693 instance, seqno);
8694 }
8695
8696 /* When we flush increase our chance for next time by growing the receive buffer when possible
8697 * by how many packets we missed, to give ourselves a bit more breathing room.
8698 */
8701 ast_debug_rtp(2, "(%p) RTP receive buffer is now at maximum of %zu\n", instance, ast_data_buffer_max(rtp->recv_buffer));
8702
8703 /* As there is such a large gap we don't want to flood the order side with missing packets, so we
8704 * give up and start anew.
8705 */
8707
8708 return AST_LIST_FIRST(&frames);
8709 }
8710
8711 /* We're finished with the frames list */
8713
8714 /* Determine if the received packet is from the last OLD_PACKET_COUNT (1000 by default) packets or not.
8715 * For the case where the received sequence number exceeds that of the expected sequence number we calculate
8716 * the past sequence number that would be 1000 sequence numbers ago. If the received sequence number
8717 * exceeds or meets that then it is within OLD_PACKET_COUNT packets ago. For example if the expected
8718 * sequence number is 100 and we receive 65530, then it would be considered old. This is because
8719 * 65535 - 1000 + 100 = 64635 which gives us the sequence number at which we would consider the packets
8720 * old. Since 65530 is above that, it would be considered old.
8721 * For the case where the received sequence number is less than the expected sequence number we can do
8722 * a simple subtraction to see if it is 1000 packets ago or not.
8723 */
8724 if ((seqno < rtp->expectedrxseqno && ((rtp->expectedrxseqno - seqno) <= OLD_PACKET_COUNT)) ||
8725 (seqno > rtp->expectedrxseqno && (seqno >= (65535 - OLD_PACKET_COUNT + rtp->expectedrxseqno)))) {
8726 /* If this is a packet from the past then we have received a duplicate packet, so just drop it */
8727 ast_debug_rtp(2, "(%p) RTP received an old packet with sequence number '%d', dropping it\n",
8728 instance, seqno);
8729 return &ast_null_frame;
8730 } else if (ast_data_buffer_get(rtp->recv_buffer, seqno)) {
8731 /* If this is a packet we already have buffered then it is a duplicate, so just drop it */
8732 ast_debug_rtp(2, "(%p) RTP received a duplicate transmission of packet with sequence number '%d', dropping it\n",
8733 instance, seqno);
8734 return &ast_null_frame;
8735 } else {
8736 /* This is an out of order packet from the future */
8737 struct ast_rtp_rtcp_nack_payload *payload;
8738 int missing_seqno;
8739 int remove_failed;
8740 unsigned int missing_seqnos_added = 0;
8741
8742 ast_debug_rtp(2, "(%p) RTP received an out of order packet with sequence number '%d' while expecting '%d' from the future\n",
8743 instance, seqno, rtp->expectedrxseqno);
8744
8745 payload = ast_malloc(sizeof(*payload) + res);
8746 if (!payload) {
8747 /* If the payload can't be allocated then we can't defer this packet right now.
8748 * Instead of dumping what we have we pretend we lost this packet. It will then
8749 * get NACKed later or the existing buffer will be returned entirely. Well, we may
8750 * try since we're seemingly out of memory. It's a bad situation all around and
8751 * packets are likely to get lost anyway.
8752 */
8753 return &ast_null_frame;
8754 }
8755
8756 payload->size = res;
8757 memcpy(payload->buf, rtpheader, res);
8758 if (ast_data_buffer_put(rtp->recv_buffer, seqno, payload) == -1) {
8759 ast_free(payload);
8760 }
8761
8762 /* If this sequence number is removed that means we had a gap and this packet has filled it in
8763 * some. Since it was part of the gap we will have already added any other missing sequence numbers
8764 * before it (and possibly after it) to the vector so we don't need to do that again. Note that
8765 * remove_failed will be set to -1 if the sequence number isn't removed, and 0 if it is.
8766 */
8767 remove_failed = AST_VECTOR_REMOVE_CMP_ORDERED(&rtp->missing_seqno, seqno, find_by_value,
8769 if (!remove_failed) {
8770 ast_debug_rtp(2, "(%p) RTP packet with sequence number '%d' is no longer missing\n",
8771 instance, seqno);
8772 }
8773
8774 /* The missing sequence number code works by taking the sequence number of the
8775 * packet we've just received and going backwards until we hit the sequence number
8776 * of the last packet we've received. While doing so we check to make sure that the
8777 * sequence number is not already missing and that it is not already buffered.
8778 */
8779 missing_seqno = seqno;
8780 while (remove_failed) {
8781 missing_seqno -= 1;
8782
8783 /* If we've cycled backwards then start back at the top */
8784 if (missing_seqno < 0) {
8785 missing_seqno = 65535;
8786 }
8787
8788 /* We've gone backwards enough such that we've hit the previous sequence number */
8789 if (missing_seqno == prev_seqno) {
8790 break;
8791 }
8792
8793 /* We don't want missing sequence number duplicates. If, for some reason,
8794 * packets are really out of order, we could end up in this scenario:
8795 *
8796 * We are expecting sequence number 100
8797 * We receive sequence number 105
8798 * Sequence numbers 100 through 104 get added to the vector
8799 * We receive sequence number 101 (this section is skipped)
8800 * We receive sequence number 103
8801 * Sequence number 102 is added to the vector
8802 *
8803 * This will prevent the duplicate from being added.
8804 */
8805 if (AST_VECTOR_GET_CMP(&rtp->missing_seqno, missing_seqno,
8806 find_by_value)) {
8807 continue;
8808 }
8809
8810 /* If this packet has been buffered already then don't count it amongst the
8811 * missing.
8812 */
8813 if (ast_data_buffer_get(rtp->recv_buffer, missing_seqno)) {
8814 continue;
8815 }
8816
8817 ast_debug_rtp(2, "(%p) RTP added missing sequence number '%d'\n",
8818 instance, missing_seqno);
8819 AST_VECTOR_ADD_SORTED(&rtp->missing_seqno, missing_seqno,
8821 missing_seqnos_added++;
8822 }
8823
8824 /* When we add a large number of missing sequence numbers we assume there was a substantial
8825 * gap in reception so we trigger an immediate NACK. When our data buffer is 1/4 full we
8826 * assume that the packets aren't just out of order but have actually been lost. At 1/2
8827 * full we get more aggressive and ask for retransmission when we get a new packet.
8828 * To get them back we construct and send a NACK causing the sender to retransmit them.
8829 */
8830 if (missing_seqnos_added >= MISSING_SEQNOS_ADDED_TRIGGER ||
8833 int packet_len = 0;
8834 int res = 0;
8835 int ice;
8836 int sr;
8837 size_t data_size = AST_UUID_STR_LEN + 128 + (AST_VECTOR_SIZE(&rtp->missing_seqno) * 4);
8838 RAII_VAR(unsigned char *, rtcpheader, NULL, ast_free_ptr);
8839 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
8841 ao2_cleanup);
8842
8843 /* Sufficient space for RTCP headers and report, SDES with CNAME, NACK header,
8844 * and worst case 4 bytes per missing sequence number.
8845 */
8846 rtcpheader = ast_malloc(sizeof(*rtcpheader) + data_size);
8847 if (!rtcpheader) {
8848 ast_debug_rtcp(1, "(%p) RTCP failed to allocate memory for NACK\n", instance);
8849 return &ast_null_frame;
8850 }
8851
8852 memset(rtcpheader, 0, data_size);
8853
8854 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
8855
8856 if (res == 0 || res == 1) {
8857 return &ast_null_frame;
8858 }
8859
8860 packet_len += res;
8861
8862 res = ast_rtcp_generate_nack(instance, rtcpheader + packet_len);
8863
8864 if (res == 0) {
8865 ast_debug_rtcp(1, "(%p) RTCP failed to construct NACK, stopping here\n", instance);
8866 return &ast_null_frame;
8867 }
8868
8869 packet_len += res;
8870
8871 res = rtcp_sendto(instance, rtcpheader, packet_len, 0, &remote_address, &ice);
8872 if (res < 0) {
8873 ast_debug_rtcp(1, "(%p) RTCP failed to send NACK request out\n", instance);
8874 } else {
8875 ast_debug_rtcp(2, "(%p) RTCP sending a NACK request to get missing packets\n", instance);
8876 /* Update RTCP SR/RR statistics */
8877 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
8878 }
8879 }
8880 }
8881
8882 return &ast_null_frame;
8883}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
void * ast_data_buffer_get(const struct ast_data_buffer *buffer, size_t pos)
Retrieve a data payload from the data buffer.
Definition: data_buffer.c:269
size_t ast_data_buffer_count(const struct ast_data_buffer *buffer)
Return the number of payloads in a data buffer.
Definition: data_buffer.c:356
void ast_data_buffer_resize(struct ast_data_buffer *buffer, size_t size)
Resize a data buffer.
Definition: data_buffer.c:168
int ast_data_buffer_put(struct ast_data_buffer *buffer, size_t pos, void *payload)
Place a data payload at a position in the data buffer.
Definition: data_buffer.c:203
size_t ast_data_buffer_max(const struct ast_data_buffer *buffer)
Return the maximum number of payloads a data buffer can hold.
Definition: data_buffer.c:363
void * ast_data_buffer_remove(struct ast_data_buffer *buffer, size_t pos)
Remove a data payload from the data buffer.
Definition: data_buffer.c:299
void ast_frame_free(struct ast_frame *frame, int cache)
Frees a frame or list of frames.
Definition: main/frame.c:176
#define ast_frdup(fr)
Copies a frame.
#define ast_verb(level,...)
#define OLD_PACKET_COUNT
static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq)
static struct ast_frame * ast_rtcp_read(struct ast_rtp_instance *instance)
static int ast_rtcp_generate_nack(struct ast_rtp_instance *instance, unsigned char *rtcpheader)
static int compare_by_value(int elem, int value)
Helper function to compare an elem in a vector by value.
#define MAXIMUM_RTP_RECV_BUFFER_SIZE
#define STRICT_RTP_LEARN_TIMEOUT
Strict RTP learning timeout time in milliseconds.
static void rtp_instance_unlock(struct ast_rtp_instance *instance)
static int rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
#define MISSING_SEQNOS_ADDED_TRIGGER
#define FLAG_NAT_ACTIVE
static int rtcp_mux(struct ast_rtp *rtp, const unsigned char *packet)
static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq)
static struct ast_frame * ast_rtp_interpret(struct ast_rtp_instance *instance, struct ast_srtp *srtp, const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno, unsigned int bundled)
static void rtp_write_rtcp_fir(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)
enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs)
Determine the type of RTP stream media from the codecs mapped.
Definition: rtp_engine.c:1535
void ast_rtp_instance_get_requested_target_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the requested target address of the remote endpoint.
Definition: rtp_engine.c:701
int ast_rtp_instance_set_incoming_source_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the incoming source address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:634
Structure for storing RTP packets for retransmission.
struct ast_sockaddr strict_rtp_address
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
struct rtp_learning_info rtp_source_learn
enum ast_media_type stream_type
struct ast_sockaddr proposed_address
struct timeval start
#define MIN(a, b)
Definition: utils.h:249
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:636
#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison while maintaining order.
Definition: vector.h:551
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:382

References ao2_cleanup, ao2_lock, ast_assert, ast_codec_media_type2str(), AST_CONTROL_SRCCHANGE, ast_data_buffer_count(), ast_data_buffer_get(), ast_data_buffer_max(), ast_data_buffer_put(), ast_data_buffer_remove(), ast_data_buffer_resize(), ast_debug, ast_debug_rtcp, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, ast_debug_stun, AST_FRAME_CONTROL, ast_frame_free(), ast_frdup, ast_free, ast_free_ptr(), AST_FRIENDLY_OFFSET, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_log, ast_malloc, AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, ast_null_frame, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtcp_generate_nack(), ast_rtcp_interpret(), ast_rtcp_read(), ast_rtp_codecs_get_stream_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, ast_rtp_instance_get_requested_target_address(), ast_rtp_instance_get_srtp(), AST_RTP_INSTANCE_RTCP_STANDARD, ast_rtp_instance_set_incoming_source_address(), ast_rtp_instance_set_remote_address, ast_rtp_interpret(), AST_RTP_PROPERTY_NAT, ast_rtp_rtcp_report_alloc(), ast_set_flag, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_ipv4_mapped(), ast_sockaddr_is_ipv4(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_sockaddr_to_sin, AST_STUN_ACCEPT, ast_stun_handle_packet(), ast_test_suite_event_notify, ast_tvdiff_ms(), ast_tvnow(), AST_UUID_STR_LEN, AST_VECTOR_ADD_SORTED, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_GET_CMP, AST_VECTOR_REMOVE_CMP_ORDERED, AST_VECTOR_RESET, AST_VECTOR_SIZE, ast_verb, ast_verbose(), ast_rtp_rtcp_nack_payload::buf, codecs, compare_by_value(), errno, ast_rtp::expectedrxseqno, ast_rtp::f, find_by_value(), FLAG_NAT_ACTIVE, frames, ast_frame::frametype, ast_frame_subclass::integer, ast_rtp::lastividtimestamp, ast_rtp::lastrxseqno, LOG_WARNING, MAXIMUM_RTP_RECV_BUFFER_SIZE, MIN, ast_rtp::missing_seqno, MISSING_SEQNOS_ADDED_TRIGGER, NULL, OLD_PACKET_COUNT, rtp_learning_info::packets, ast_rtp::prevrxseqno, rtp_learning_info::proposed_address, RAII_VAR, ast_rtp::rawdata, ast_rtp::recv_buffer, ast_rtp::rtcp, rtcp_mux(), rtcp_sendto(), rtp_debug_test_addr(), RTP_DTLS_ESTABLISHED, rtp_find_instance_by_packet_source_ssrc(), rtp_instance_unlock(), rtp_learning_rtp_seq_update(), rtp_learning_seq_init(), rtp_recvfrom(), ast_rtp::rtp_source_learn, rtp_write_rtcp_fir(), ast_rtp::s, ast_frame::seqno, SEQNO_CYCLE_OVER, ast_rtp_rtcp_nack_payload::size, ast_rtp::ssrc_mapping, rtp_learning_info::start, rtp_learning_info::stream_type, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, STRICT_RTP_LEARN_TIMEOUT, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, ast_frame::subclass, ast_rtcp::them, ast_rtp::themssrc_valid, ast_rtcp::type, and version.

◆ ast_rtp_remote_address_set()

static void ast_rtp_remote_address_set ( struct ast_rtp_instance instance,
struct ast_sockaddr addr 
)
static
Precondition
instance is locked

Definition at line 9083 of file res_rtp_asterisk.c.

9084{
9085 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9086 struct ast_sockaddr local;
9087 int index;
9088
9089 ast_rtp_instance_get_local_address(instance, &local);
9090 if (!ast_sockaddr_isnull(addr)) {
9091 /* Update the local RTP address with what is being used */
9092 if (ast_ouraddrfor(addr, &local)) {
9093 /* Failed to update our address so reuse old local address */
9094 ast_rtp_instance_get_local_address(instance, &local);
9095 } else {
9096 ast_rtp_instance_set_local_address(instance, &local);
9097 }
9098 }
9099
9100 if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
9101 ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
9102 ast_sockaddr_copy(&rtp->rtcp->them, addr);
9103
9106
9107 /* Update the local RTCP address with what is being used */
9108 ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
9109 }
9110 ast_sockaddr_copy(&rtp->rtcp->us, &local);
9111
9114 }
9115
9116 /* Update any bundled RTP instances */
9117 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
9118 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
9119
9121 }
9122
9123 /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
9124 rtp->last_seqno = 0;
9125 rtp->last_end_timestamp.ts = 0;
9126 rtp->last_end_timestamp.is_set = 0;
9127
9129 && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
9130 /* We only need to learn a new strict source address if we've been told the source is
9131 * changing to something different.
9132 */
9133 ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
9134 rtp, ast_sockaddr_stringify(addr));
9135 rtp_learning_start(rtp);
9136 }
9137}
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:1021
static int strictrtp
static void rtp_learning_start(struct ast_rtp *rtp)
Start the strictrtp learning mode.
int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address that we are expecting to receive RTP on.
Definition: rtp_engine.c:616

References ast_debug_rtcp, ast_free, ast_ouraddrfor(), ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), AST_RTP_INSTANCE_RTCP_STANDARD, ast_rtp_instance_set_local_address(), ast_rtp_instance_set_remote_address, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdup, AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_verb, rtp_ssrc_mapping::instance, optional_ts::is_set, ast_rtp::last_end_timestamp, ast_rtp::last_seqno, ast_rtcp::local_addr_str, ast_rtp::rtcp, rtp_learning_start(), ast_rtp::ssrc_mapping, ast_rtp::strict_rtp_address, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, strictrtp, ast_rtcp::them, optional_ts::ts, ast_rtcp::type, and ast_rtcp::us.

◆ ast_rtp_rtcp_handle_nack()

static int ast_rtp_rtcp_handle_nack ( struct ast_rtp_instance instance,
unsigned int *  nackdata,
unsigned int  position,
unsigned int  length 
)
static
Precondition
instance is locked

Definition at line 6527 of file res_rtp_asterisk.c.

6529{
6530 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6531 int res = 0;
6532 int blp_index;
6533 int packet_index;
6534 int ice;
6535 struct ast_rtp_rtcp_nack_payload *payload;
6536 unsigned int current_word;
6537 unsigned int pid; /* Packet ID which refers to seqno of lost packet */
6538 unsigned int blp; /* Bitmask of following lost packets */
6539 struct ast_sockaddr remote_address = { {0,} };
6540 int abs_send_time_id;
6541 unsigned int now_msw = 0;
6542 unsigned int now_lsw = 0;
6543 unsigned int packets_not_found = 0;
6544
6545 if (!rtp->send_buffer) {
6546 ast_debug_rtcp(1, "(%p) RTCP tried to handle NACK request, "
6547 "but we don't have a RTP packet storage!\n", instance);
6548 return res;
6549 }
6550
6552 if (abs_send_time_id != -1) {
6553 timeval2ntp(ast_tvnow(), &now_msw, &now_lsw);
6554 }
6555
6556 ast_rtp_instance_get_remote_address(instance, &remote_address);
6557
6558 /*
6559 * We use index 3 because with feedback messages, the FCI (Feedback Control Information)
6560 * does not begin until after the version, packet SSRC, and media SSRC words.
6561 */
6562 for (packet_index = 3; packet_index < length; packet_index++) {
6563 current_word = ntohl(nackdata[position + packet_index]);
6564 pid = current_word >> 16;
6565 /* We know the remote end is missing this packet. Go ahead and send it if we still have it. */
6566 payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_get(rtp->send_buffer, pid);
6567 if (payload) {
6568 if (abs_send_time_id != -1) {
6569 /* On retransmission we need to update the timestamp within the packet, as it
6570 * is supposed to contain when the packet was actually sent.
6571 */
6572 put_unaligned_time24(payload->buf + 17, now_msw, now_lsw);
6573 }
6574 res += rtp_sendto(instance, payload->buf, payload->size, 0, &remote_address, &ice);
6575 } else {
6576 ast_debug_rtcp(1, "(%p) RTCP received NACK request for RTP packet with seqno %d, "
6577 "but we don't have it\n", instance, pid);
6578 packets_not_found++;
6579 }
6580 /*
6581 * The bitmask. Denoting the least significant bit as 1 and its most significant bit
6582 * as 16, then bit i of the bitmask is set to 1 if the receiver has not received RTP
6583 * packet (pid+i)(modulo 2^16). Otherwise, it is set to 0. We cannot assume bits set
6584 * to 0 after a bit set to 1 have actually been received.
6585 */
6586 blp = current_word & 0xffff;
6587 blp_index = 1;
6588 while (blp) {
6589 if (blp & 1) {
6590 /* Packet (pid + i)(modulo 2^16) is missing too. */
6591 unsigned int seqno = (pid + blp_index) % 65536;
6592 payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_get(rtp->send_buffer, seqno);
6593 if (payload) {
6594 if (abs_send_time_id != -1) {
6595 put_unaligned_time24(payload->buf + 17, now_msw, now_lsw);
6596 }
6597 res += rtp_sendto(instance, payload->buf, payload->size, 0, &remote_address, &ice);
6598 } else {
6599 ast_debug_rtcp(1, "(%p) RTCP remote end also requested RTP packet with seqno %d, "
6600 "but we don't have it\n", instance, seqno);
6601 packets_not_found++;
6602 }
6603 }
6604 blp >>= 1;
6605 blp_index++;
6606 }
6607 }
6608
6609 if (packets_not_found) {
6610 /* Grow the send buffer based on how many packets were not found in the buffer, but
6611 * enforce a maximum.
6612 */
6614 ast_data_buffer_max(rtp->send_buffer) + packets_not_found));
6615 ast_debug_rtcp(2, "(%p) RTCP send buffer on RTP instance is now at maximum of %zu\n",
6616 instance, ast_data_buffer_max(rtp->send_buffer));
6617 }
6618
6619 return res;
6620}
static void put_unaligned_time24(void *p, uint32_t time_msw, uint32_t time_lsw)
#define MAXIMUM_RTP_SEND_BUFFER_SIZE
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:914

References ast_data_buffer_get(), ast_data_buffer_max(), ast_data_buffer_resize(), ast_debug_rtcp, AST_RTP_EXTENSION_ABS_SEND_TIME, ast_rtp_instance_extmap_get_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_tvnow(), ast_rtp_rtcp_nack_payload::buf, MAXIMUM_RTP_SEND_BUFFER_SIZE, MIN, put_unaligned_time24(), rtp_sendto(), ast_rtp::send_buffer, ast_rtp_rtcp_nack_payload::size, and timeval2ntp().

Referenced by ast_rtcp_interpret().

◆ ast_rtp_sendcng()

static int ast_rtp_sendcng ( struct ast_rtp_instance instance,
int  level 
)
static

generate comfort noice (CNG)

Precondition
instance is locked

Definition at line 9416 of file res_rtp_asterisk.c.

9417{
9418 unsigned int *rtpheader;
9419 int hdrlen = 12;
9420 int res, payload = 0;
9421 char data[256];
9422 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9423 struct ast_sockaddr remote_address = { {0,} };
9424 int ice;
9425
9426 ast_rtp_instance_get_remote_address(instance, &remote_address);
9427
9428 if (ast_sockaddr_isnull(&remote_address)) {
9429 return -1;
9430 }
9431
9433
9434 level = 127 - (level & 0x7f);
9435
9436 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
9437
9438 /* Get a pointer to the header */
9439 rtpheader = (unsigned int *)data;
9440 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
9441 rtpheader[1] = htonl(rtp->lastts);
9442 rtpheader[2] = htonl(rtp->ssrc);
9443 data[12] = level;
9444
9445 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);
9446
9447 if (res < 0) {
9448 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
9449 return res;
9450 }
9451
9452 if (rtp_debug_test_addr(&remote_address)) {
9453 ast_verbose("Sent Comfort Noise RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
9454 ast_sockaddr_stringify(&remote_address),
9455 ice ? " (via ICE)" : "",
9456 AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
9457 }
9458
9459 rtp->seqno++;
9460
9461 return res;
9462}

References ast_log, AST_RTP_CN, ast_rtp_codecs_payload_code_tx(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, NULL, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::seqno, and ast_rtp::ssrc.

◆ ast_rtp_set_remote_ssrc()

static void ast_rtp_set_remote_ssrc ( struct ast_rtp_instance instance,
unsigned int  ssrc 
)
static
Precondition
instance is locked

Definition at line 9481 of file res_rtp_asterisk.c.

9482{
9483 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9484
9485 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
9486 return;
9487 }
9488
9489 rtp->themssrc = ssrc;
9490 rtp->themssrc_valid = 1;
9491
9492 /* If this is bundled we need to update the SSRC mapping */
9493 if (rtp->bundled) {
9494 struct ast_rtp *bundled_rtp;
9495 int index;
9496
9497 ao2_unlock(instance);
9498
9499 /* The child lock can't be held while accessing the parent */
9500 ao2_lock(rtp->bundled);
9501 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
9502
9503 for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
9504 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
9505
9506 if (mapping->instance == instance) {
9507 mapping->ssrc = ssrc;
9508 mapping->ssrc_valid = 1;
9509 break;
9510 }
9511 }
9512
9513 ao2_unlock(rtp->bundled);
9514
9516 }
9517}

References ao2_lock, ao2_unlock, ast_rtp_instance_get_data(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_rtp::bundled, rtp_ssrc_mapping::instance, rtp_ssrc_mapping::ssrc, ast_rtp::ssrc, ast_rtp::ssrc_mapping, rtp_ssrc_mapping::ssrc_valid, ast_rtp::themssrc, and ast_rtp::themssrc_valid.

◆ ast_rtp_set_stream_num()

static void ast_rtp_set_stream_num ( struct ast_rtp_instance instance,
int  stream_num 
)
static

Definition at line 9519 of file res_rtp_asterisk.c.

9520{
9521 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9522
9523 rtp->stream_num = stream_num;
9524}

References ast_rtp_instance_get_data(), and ast_rtp::stream_num.

◆ ast_rtp_stop()

static void ast_rtp_stop ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 9353 of file res_rtp_asterisk.c.

9354{
9355 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9356 struct ast_sockaddr addr = { {0,} };
9357
9358#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9359 ao2_unlock(instance);
9360 AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
9361
9362 dtls_srtp_stop_timeout_timer(instance, rtp, 0);
9363 if (rtp->rtcp) {
9364 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9365 }
9366 ao2_lock(instance);
9367#endif
9368 ast_debug_rtp(1, "(%s) RTP Stop\n",
9370
9371 if (rtp->rtcp && rtp->rtcp->schedid > -1) {
9372 ao2_unlock(instance);
9373 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9374 /* successfully cancelled scheduler entry. */
9375 ao2_ref(instance, -1);
9376 }
9377 ao2_lock(instance);
9378 rtp->rtcp->schedid = -1;
9379 }
9380
9381 if (rtp->transport_wide_cc.schedid > -1) {
9382 ao2_unlock(instance);
9383 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9384 ao2_ref(instance, -1);
9385 }
9386 ao2_lock(instance);
9387 rtp->transport_wide_cc.schedid = -1;
9388 }
9389
9390 if (rtp->red) {
9391 ao2_unlock(instance);
9392 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
9393 ao2_lock(instance);
9394 ast_free(rtp->red);
9395 rtp->red = NULL;
9396 }
9397
9398 ast_rtp_instance_set_remote_address(instance, &addr);
9399
9401}
#define AST_SCHED_DEL_UNREF(sched, id, refcall)
schedule task to get deleted and call unref function
Definition: sched.h:82

References ao2_lock, ao2_ref, ao2_unlock, ast_debug_rtp, ast_free, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_set_remote_address, AST_SCHED_DEL, ast_sched_del(), AST_SCHED_DEL_UNREF, ast_set_flag, FLAG_NEED_MARKER_BIT, NULL, ast_rtp::red, ast_rtp::rtcp, ast_rtp::sched, rtp_transport_wide_cc_statistics::schedid, ast_rtcp::schedid, rtp_red::schedid, and ast_rtp::transport_wide_cc.

◆ ast_rtp_stun_request()

static void ast_rtp_stun_request ( struct ast_rtp_instance instance,
struct ast_sockaddr suggestion,
const char *  username 
)
static
Precondition
instance is NOT locked

Definition at line 9338 of file res_rtp_asterisk.c.

9339{
9340 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9341 struct sockaddr_in suggestion_tmp;
9342
9343 /*
9344 * The instance should not be locked because we can block
9345 * waiting for a STUN respone.
9346 */
9347 ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
9348 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
9349 ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
9350}
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition: stun.c:415

References ast_rtp_instance_get_data(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_stun_request(), NULL, and ast_rtp::s.

◆ ast_rtp_update_source()

static void ast_rtp_update_source ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4606 of file res_rtp_asterisk.c.

4607{
4608 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4609
4610 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4612 ast_debug_rtp(3, "(%p) RTP setting the marker bit due to a source update\n", instance);
4613
4614 return;
4615}

References ast_debug_rtp, ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

◆ ast_rtp_write()

static int ast_rtp_write ( struct ast_rtp_instance instance,
struct ast_frame frame 
)
static
Precondition
instance is locked

Definition at line 5553 of file res_rtp_asterisk.c.

5554{
5555 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5556 struct ast_sockaddr remote_address = { {0,} };
5557 struct ast_format *format;
5558 int codec;
5559
5560 ast_rtp_instance_get_remote_address(instance, &remote_address);
5561
5562 /* If we don't actually know the remote address don't even bother doing anything */
5563 if (ast_sockaddr_isnull(&remote_address)) {
5564 ast_debug_rtp(1, "(%p) RTP no remote address on instance, so dropping frame\n", instance);
5565 return 0;
5566 }
5567
5568 /* VP8: is this a request to send a RTCP FIR? */
5570 rtp_write_rtcp_fir(instance, rtp, &remote_address);
5571 return 0;
5572 } else if (frame->frametype == AST_FRAME_RTCP) {
5573 if (frame->subclass.integer == AST_RTP_RTCP_PSFB) {
5574 rtp_write_rtcp_psfb(instance, rtp, frame, &remote_address);
5575 }
5576 return 0;
5577 }
5578
5579 /* If there is no data length we can't very well send the packet */
5580 if (!frame->datalen) {
5581 ast_debug_rtp(1, "(%p) RTP received frame with no data for instance, so dropping frame\n", instance);
5582 return 0;
5583 }
5584
5585 /* If the packet is not one our RTP stack supports bail out */
5586 if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
5587 ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
5588 return -1;
5589 }
5590
5591 if (rtp->red) {
5592 /* return 0; */
5593 /* no primary data or generations to send */
5594 if ((frame = red_t140_to_red(rtp->red)) == NULL)
5595 return 0;
5596 }
5597
5598 /* Grab the subclass and look up the payload we are going to use */
5600 1, frame->subclass.format, 0);
5601 if (codec < 0) {
5602 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n",
5604 return -1;
5605 }
5606
5607 /* Note that we do not increase the ref count here as this pointer
5608 * will not be held by any thing explicitly. The format variable is
5609 * merely a convenience reference to frame->subclass.format */
5610 format = frame->subclass.format;
5612 /* Oh dear, if the format changed we will have to set up a new smoother */
5613 ast_debug_rtp(1, "(%s) RTP ooh, format changed from %s to %s\n",
5617 ao2_replace(rtp->lasttxformat, format);
5618 if (rtp->smoother) {
5620 rtp->smoother = NULL;
5621 }
5622 }
5623
5624 /* If no smoother is present see if we have to set one up */
5625 if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
5626 unsigned int smoother_flags = ast_format_get_smoother_flags(format);
5627 unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
5628
5629 if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
5630 framing_ms = ast_format_get_default_ms(format);
5631 }
5632
5633 if (framing_ms) {
5635 if (!rtp->smoother) {
5636 ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len: %u\n",
5637 ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
5638 return -1;
5639 }
5640 ast_smoother_set_flags(rtp->smoother, smoother_flags);
5641 }
5642 }
5643
5644 /* Feed audio frames into the actual function that will create a frame and send it */
5645 if (rtp->smoother) {
5646 struct ast_frame *f;
5647
5649 ast_smoother_feed_be(rtp->smoother, frame);
5650 } else {
5651 ast_smoother_feed(rtp->smoother, frame);
5652 }
5653
5654 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
5655 rtp_raw_write(instance, f, codec);
5656 }
5657 } else {
5658 int hdrlen = 12;
5659 struct ast_frame *f = NULL;
5660
5661 if (frame->offset < hdrlen) {
5662 f = ast_frdup(frame);
5663 } else {
5664 f = frame;
5665 }
5666 if (f->data.ptr) {
5667 rtp_raw_write(instance, f, codec);
5668 }
5669 if (f != frame) {
5670 ast_frfree(f);
5671 }
5672
5673 }
5674
5675 return 0;
5676}
int ast_format_get_smoother_flags(const struct ast_format *format)
Get smoother flags for this format.
Definition: format.c:349
int ast_format_can_be_smoothed(const struct ast_format *format)
Get whether or not the format can be smoothed.
Definition: format.c:344
unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
Get the minimum number of bytes expected in a frame for this format.
Definition: format.c:374
unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
Get the minimum amount of media carried in this format.
Definition: format.c:364
@ 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
unsigned int ast_format_get_default_ms(const struct ast_format *format)
Get the default framing size (in milliseconds) for a format.
Definition: format.c:359
static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
static struct ast_frame * red_t140_to_red(struct rtp_red *red)
static void rtp_write_rtcp_psfb(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_frame *frame, struct ast_sockaddr *remote_address)
#define AST_RTP_RTCP_PSFB
Definition: rtp_engine.h:329
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1688
void ast_smoother_set_flags(struct ast_smoother *smoother, int flags)
Definition: smoother.c:123
#define ast_smoother_feed_be(s, f)
Definition: smoother.h:80
int ast_smoother_test_flag(struct ast_smoother *s, int flag)
Definition: smoother.c:128
#define AST_SMOOTHER_FLAG_FORCED
Definition: smoother.h:36
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
#define ast_smoother_feed(s, f)
Definition: smoother.h:75
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
#define AST_SMOOTHER_FLAG_BE
Definition: smoother.h:35
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47

References ao2_replace, AST_CONTROL_VIDUPDATE, ast_debug_rtp, ast_format_can_be_smoothed(), ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_default_ms(), ast_format_get_minimum_bytes(), ast_format_get_minimum_ms(), ast_format_get_name(), ast_format_get_smoother_flags(), AST_FRAME_CONTROL, AST_FRAME_RTCP, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup, ast_frfree, ast_log, ast_rtp_codecs_get_framing(), ast_rtp_codecs_payload_code_tx(), ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, AST_RTP_RTCP_PSFB, ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, AST_SMOOTHER_FLAG_FORCED, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_sockaddr_isnull(), ast_format::codec, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, ast_rtp::lasttxformat, LOG_WARNING, NULL, ast_frame::offset, ast_frame::ptr, ast_rtp::red, red_t140_to_red(), rtp_raw_write(), rtp_write_rtcp_fir(), rtp_write_rtcp_psfb(), ast_rtp::smoother, and ast_frame::subclass.

Referenced by red_write(), and rtp_red_buffer().

◆ bridge_p2p_rtp_write()

static int bridge_p2p_rtp_write ( struct ast_rtp_instance instance,
struct ast_rtp_instance instance1,
unsigned int *  rtpheader,
int  len,
int  hdrlen 
)
static
Precondition
instance is locked

Definition at line 7229 of file res_rtp_asterisk.c.

7231{
7232 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7233 struct ast_rtp *bridged;
7234 int res = 0, payload = 0, bridged_payload = 0, mark;
7235 RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
7236 int reconstruct = ntohl(rtpheader[0]);
7237 struct ast_sockaddr remote_address = { {0,} };
7238 int ice;
7239 unsigned int timestamp = ntohl(rtpheader[1]);
7240
7241 /* Get fields from packet */
7242 payload = (reconstruct & 0x7f0000) >> 16;
7243 mark = (reconstruct & 0x800000) >> 23;
7244
7245 /* Check what the payload value should be */
7246 payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
7247 if (!payload_type) {
7248 return -1;
7249 }
7250
7251 /* Otherwise adjust bridged payload to match */
7253 payload_type->asterisk_format, payload_type->format, payload_type->rtp_code, payload_type->sample_rate);
7254
7255 /* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
7256 if (bridged_payload < 0) {
7257 return -1;
7258 }
7259
7260 /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
7261 if (ast_rtp_codecs_find_payload_code(ast_rtp_instance_get_codecs(instance1), bridged_payload) == -1) {
7262 ast_debug_rtp(1, "(%p, %p) RTP unsupported payload type received\n", instance, instance1);
7263 return -1;
7264 }
7265
7266 /*
7267 * Even if we are no longer in dtmf, we could still be receiving
7268 * re-transmissions of the last dtmf end still. Feed those to the
7269 * core so they can be filtered accordingly.
7270 */
7271 if (rtp->last_end_timestamp.is_set && rtp->last_end_timestamp.ts == timestamp) {
7272 ast_debug_rtp(1, "(%p, %p) RTP feeding packet with duplicate timestamp to core\n", instance, instance1);
7273 return -1;
7274 }
7275
7276 if (payload_type->asterisk_format) {
7277 ao2_replace(rtp->lastrxformat, payload_type->format);
7278 }
7279
7280 /*
7281 * We have now determined that we need to send the RTP packet
7282 * out the bridged instance to do local bridging so we must unlock
7283 * the receiving instance to prevent deadlock with the bridged
7284 * instance.
7285 *
7286 * Technically we should grab a ref to instance1 so it won't go
7287 * away on us. However, we should be safe because the bridged
7288 * instance won't change without both channels involved being
7289 * locked and we currently have the channel lock for the receiving
7290 * instance.
7291 */
7292 ao2_unlock(instance);
7293 ao2_lock(instance1);
7294
7295 /*
7296 * Get the peer rtp pointer now to emphasize that using it
7297 * must happen while instance1 is locked.
7298 */
7299 bridged = ast_rtp_instance_get_data(instance1);
7300
7301
7302 /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
7303 if (bridged->sending_digit) {
7304 ast_debug_rtp(1, "(%p, %p) RTP Feeding packet to core until DTMF finishes\n", instance, instance1);
7305 ao2_unlock(instance1);
7306 ao2_lock(instance);
7307 return -1;
7308 }
7309
7310 if (payload_type->asterisk_format) {
7311 /*
7312 * If bridged peer has already received rtp, perform the asymmetric codec check
7313 * if that feature has been activated
7314 */
7315 if (!bridged->asymmetric_codec
7316 && bridged->lastrxformat != ast_format_none
7317 && ast_format_cmp(payload_type->format, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
7318 ast_debug_rtp(1, "(%p, %p) RTP asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
7319 instance, instance1, ast_format_get_name(payload_type->format),
7321 ao2_unlock(instance1);
7322 ao2_lock(instance);
7323 return -1;
7324 }
7325
7326 ao2_replace(bridged->lasttxformat, payload_type->format);
7327 }
7328
7329 ast_rtp_instance_get_remote_address(instance1, &remote_address);
7330
7331 if (ast_sockaddr_isnull(&remote_address)) {
7332 ast_debug_rtp(5, "(%p, %p) RTP remote address is null, most likely RTP has been stopped\n",
7333 instance, instance1);
7334 ao2_unlock(instance1);
7335 ao2_lock(instance);
7336 return 0;
7337 }
7338
7339 /* If the marker bit has been explicitly set turn it on */
7340 if (ast_test_flag(bridged, FLAG_NEED_MARKER_BIT)) {
7341 mark = 1;
7343 }
7344
7345 /* Set the marker bit for the first local bridged packet which has the first bridged peer's SSRC. */
7347 mark = 1;
7349 }
7350
7351 /* Reconstruct part of the packet */
7352 reconstruct &= 0xFF80FFFF;
7353 reconstruct |= (bridged_payload << 16);
7354 reconstruct |= (mark << 23);
7355 rtpheader[0] = htonl(reconstruct);
7356
7357 if (mark) {
7358 /* make this rtp instance aware of the new ssrc it is sending */
7359 bridged->ssrc = ntohl(rtpheader[2]);
7360 }
7361
7362 /* Send the packet back out */
7363 res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address, &ice);
7364 if (res < 0) {
7367 "RTP Transmission error of packet to %s: %s\n",
7368 ast_sockaddr_stringify(&remote_address),
7369 strerror(errno));
7373 "RTP NAT: Can't write RTP to private "
7374 "address %s, waiting for other end to "
7375 "send audio...\n",
7376 ast_sockaddr_stringify(&remote_address));
7377 }
7379 }
7380 ao2_unlock(instance1);
7381 ao2_lock(instance);
7382 return 0;
7383 }
7384
7385 if (rtp_debug_test_addr(&remote_address)) {
7386 ast_verbose("Sent RTP P2P packet to %s%s (type %-2.2d, len %-6.6d)\n",
7387 ast_sockaddr_stringify(&remote_address),
7388 ice ? " (via ICE)" : "",
7389 bridged_payload, len - hdrlen);
7390 }
7391
7392 ao2_unlock(instance1);
7393 ao2_lock(instance);
7394 return 0;
7395}
static int reconstruct(int sign, int dqln, int y)
Definition: codec_g726.c:331
#define FLAG_NAT_INACTIVE
#define FLAG_NAT_INACTIVE_NOWARN
int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int payload)
Search for the tx payload type in the ast_rtp_codecs structure.
Definition: rtp_engine.c:2157
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_clear_flag(p, flag)
Definition: utils.h:77

References ao2_cleanup, ao2_lock, ao2_replace, ao2_unlock, ast_clear_flag, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), ast_format_none, ast_log, ast_rtp_codecs_find_payload_code(), ast_rtp_codecs_get_payload(), ast_rtp_codecs_payload_code_tx_sample_rate(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_NAT, ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_verbose(), ast_rtp::asymmetric_codec, DEBUG_ATLEAST, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, FLAG_REQ_LOCAL_BRIDGE_BIT, optional_ts::is_set, ast_rtp::last_end_timestamp, ast_rtp::lastrxformat, ast_rtp::lasttxformat, len(), LOG_WARNING, NULL, RAII_VAR, reconstruct(), rtp_debug_test_addr(), rtp_sendto(), ast_rtp::sending_digit, ast_rtp::ssrc, and optional_ts::ts.

Referenced by ast_rtp_interpret().

◆ calc_mean_and_standard_deviation()

static void calc_mean_and_standard_deviation ( double  new_sample,
double *  mean,
double *  std_dev,
unsigned int *  count 
)
static

Definition at line 3540 of file res_rtp_asterisk.c.

3541{
3542 double delta1;
3543 double delta2;
3544
3545 /* First convert the standard deviation back into a sum of squares. */
3546 double last_sum_of_squares = (*std_dev) * (*std_dev) * (*count ?: 1);
3547
3548 if (++(*count) == 0) {
3549 /* Avoid potential divide by zero on an overflow */
3550 *count = 1;
3551 }
3552
3553 /*
3554 * Below is an implementation of Welford's online algorithm [1] for calculating
3555 * mean and variance in a single pass.
3556 *
3557 * [1] https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
3558 */
3559
3560 delta1 = new_sample - *mean;
3561 *mean += (delta1 / *count);
3562 delta2 = new_sample - *mean;
3563
3564 /* Now calculate the new variance, and subsequent standard deviation */
3565 *std_dev = sqrt((last_sum_of_squares + (delta1 * delta2)) / *count);
3566}

Referenced by calc_rxstamp_and_jitter(), calculate_lost_packet_statistics(), update_jitter_stats(), update_local_mes_stats(), update_lost_stats(), update_reported_mes_stats(), and update_rtt_stats().

◆ calc_media_experience_score()

static double calc_media_experience_score ( struct ast_rtp_instance instance,
double  normdevrtt,
double  normdev_rxjitter,
double  stdev_rxjitter,
double  normdev_rxlost 
)
static

Calculate a "media experience score" based on given data.

Technically, a mean opinion score (MOS) cannot be calculated without the involvement of human eyes (video) and ears (audio). Thus instead we'll approximate an opinion using the given parameters, and call it a media experience score.

The tallied score is based upon recommendations and formulas from ITU-T G.107, ITU-T G.109, ITU-T G.113, and other various internet sources.

Parameters
instanceRTP instance
normdevrttThe average round trip time
normdev_rxjitterThe smoothed jitter
stdev_rxjitterThe jitter standard deviation value
normdev_rxlostThe average number of packets lost since last check
Returns
A media experience score.
Note
The calculations in this function could probably be simplified but calculating a MOS using the information available publicly, then re-scaling it to 0.0 -> 100.0 makes the process clearer and easier to troubleshoot or change.

Definition at line 6303 of file res_rtp_asterisk.c.

6306{
6307 double r_value;
6308 double pseudo_mos;
6309 double mes = 0;
6310
6311 /*
6312 * While the media itself might be okay, a significant enough delay could make
6313 * for an unpleasant user experience.
6314 *
6315 * Calculate the effective latency by using the given round trip time, and adding
6316 * jitter scaled according to its standard deviation. The scaling is done in order
6317 * to increase jitter's weight since a higher deviation can result in poorer overall
6318 * quality.
6319 */
6320 double effective_latency = (normdevrtt * 1000)
6321 + ((normdev_rxjitter * 2) * (stdev_rxjitter / 3))
6322 + 10;
6323
6324 /*
6325 * Using the defaults for the standard transmission rating factor ("R" value)
6326 * one arrives at 93.2 (see ITU-T G.107 for more details), so we'll use that
6327 * as the starting value and subtract deficiencies that could affect quality.
6328 *
6329 * Calculate the impact of the effective latency. Influence increases with
6330 * values over 160 as the significant "lag" can degrade user experience.
6331 */
6332 if (effective_latency < 160) {
6333 r_value = 93.2 - (effective_latency / 40);
6334 } else {
6335 r_value = 93.2 - (effective_latency - 120) / 10;
6336 }
6337
6338 /* Next evaluate the impact of lost packets */
6339 r_value = r_value - (normdev_rxlost * 2.0);
6340
6341 /*
6342 * Finally convert the "R" value into a opinion/quality score between 1 (really anything
6343 * below 3 should be considered poor) and 4.5 (the highest achievable for VOIP).
6344 */
6345 if (r_value < 0) {
6346 pseudo_mos = 1.0;
6347 } else if (r_value > 100) {
6348 pseudo_mos = 4.5;
6349 } else {
6350 pseudo_mos = 1 + (0.035 * r_value) + (r_value * (r_value - 60) * (100 - r_value) * 0.000007);
6351 }
6352
6353 /*
6354 * We're going to rescale the 0.0->5.0 pseudo_mos to the 0.0->100.0 MES.
6355 * For those ranges, we could actually just multiply the pseudo_mos
6356 * by 20 but we may want to change the scale later.
6357 */
6358 mes = RESCALE(pseudo_mos, 0.0, 5.0, 0.0, 100.0);
6359
6360 return mes;
6361}
#define RESCALE(in, inmin, inmax, outmin, outmax)

References RESCALE.

Referenced by update_local_mes_stats(), and update_reported_mes_stats().

◆ calc_rxstamp_and_jitter()

static void calc_rxstamp_and_jitter ( struct timeval *  tv,
struct ast_rtp rtp,
unsigned int  rx_rtp_ts,
int  mark 
)
static

Definition at line 5678 of file res_rtp_asterisk.c.

5681{
5682 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
5683
5684 double jitter = 0.0;
5685 double prev_jitter = 0.0;
5686 struct timeval now;
5687 struct timeval tmp;
5688 double rxnow;
5689 double arrival_sec;
5690 unsigned int arrival;
5691 int transit;
5692 int d;
5693
5694 gettimeofday(&now,NULL);
5695
5696 if (rtp->rxcount == 1 || mark) {
5697 rtp->rxstart = ast_tv2double(&now);
5698 rtp->remote_seed_rx_rtp_ts = rx_rtp_ts;
5699
5700 /*
5701 * "tv" is placed in the received frame's
5702 * "delivered" field and when this frame is
5703 * sent out again on the other side, it's
5704 * used to calculate the timestamp on the
5705 * outgoing RTP packets.
5706 *
5707 * NOTE: We need to do integer math here
5708 * because double math rounding issues can
5709 * generate incorrect timestamps.
5710 */
5711 rtp->rxcore = now;
5712 tmp = ast_samp2tv(rx_rtp_ts, rate);
5713 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
5714 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
5715 *tv = ast_tvadd(rtp->rxcore, tmp);
5716
5717 ast_debug_rtcp(3, "%s: "
5718 "Seed ts: %u current time: %f\n",
5720 , rx_rtp_ts
5721 , rtp->rxstart
5722 );
5723
5724 return;
5725 }
5726
5727 tmp = ast_samp2tv(rx_rtp_ts, rate);
5728 /* See the comment about "tv" above. Even if
5729 * we don't use this received packet for jitter
5730 * calculations, we still need to set tv so the
5731 * timestamp will be correct when this packet is
5732 * sent out again.
5733 */
5734 *tv = ast_tvadd(rtp->rxcore, tmp);
5735
5736 /*
5737 * The first few packets are generally unstable so let's
5738 * not use them in the calculations.
5739 */
5741 ast_debug_rtcp(3, "%s: Packet %d < %d. Ignoring\n",
5743 , rtp->rxcount
5745 );
5746
5747 return;
5748 }
5749
5750 /*
5751 * First good packet. Capture the start time and timestamp
5752 * but don't actually use this packet for calculation.
5753 */
5755 rtp->rxstart_stable = ast_tv2double(&now);
5756 rtp->remote_seed_rx_rtp_ts_stable = rx_rtp_ts;
5757 rtp->last_transit_time_samples = -rx_rtp_ts;
5758
5759 ast_debug_rtcp(3, "%s: "
5760 "pkt: %5u Stable Seed ts: %u current time: %f\n",
5762 , rtp->rxcount
5763 , rx_rtp_ts
5764 , rtp->rxstart_stable
5765 );
5766
5767 return;
5768 }
5769
5770 /*
5771 * If the current packet isn't in sequence, don't
5772 * use it in any calculations as remote_current_rx_rtp_ts
5773 * is not going to be correct.
5774 */
5775 if (rtp->lastrxseqno != rtp->prevrxseqno + 1) {
5776 ast_debug_rtcp(3, "%s: Current packet seq %d != last packet seq %d + 1. Ignoring\n",
5778 , rtp->lastrxseqno
5779 , rtp->prevrxseqno
5780 );
5781
5782 return;
5783 }
5784
5785 /*
5786 * The following calculations are taken from
5787 * https://www.rfc-editor.org/rfc/rfc3550#appendix-A.8
5788 *
5789 * The received rtp timestamp is the random "seed"
5790 * timestamp chosen by the sender when they sent the
5791 * first packet, plus the number of samples since then.
5792 *
5793 * To get our arrival time in the same units, we
5794 * calculate the time difference in seconds between
5795 * when we received the first packet and when we
5796 * received this packet and convert that to samples.
5797 */
5798 rxnow = ast_tv2double(&now);
5799 arrival_sec = rxnow - rtp->rxstart_stable;
5800 arrival = ast_sec2samp(arrival_sec, rate);
5801
5802 /*
5803 * Now we can use the exact formula in
5804 * https://www.rfc-editor.org/rfc/rfc3550#appendix-A.8 :
5805 *
5806 * int transit = arrival - r->ts;
5807 * int d = transit - s->transit;
5808 * s->transit = transit;
5809 * if (d < 0) d = -d;
5810 * s->jitter += (1./16.) * ((double)d - s->jitter);
5811 *
5812 * Our rx_rtp_ts is their r->ts.
5813 * Our rtp->last_transit_time_samples is their s->transit.
5814 * Our rtp->rxjitter is their s->jitter.
5815 */
5816 transit = arrival - rx_rtp_ts;
5817 d = transit - rtp->last_transit_time_samples;
5818
5819 if (d < 0) {
5820 d = -d;
5821 }
5822
5823 prev_jitter = rtp->rxjitter_samples;
5824 jitter = (1.0/16.0) * (((double)d) - prev_jitter);
5825 rtp->rxjitter_samples = prev_jitter + jitter;
5826
5827 /*
5828 * We need to hang on to jitter in both samples and seconds.
5829 */
5830 rtp->rxjitter = ast_samp2sec(rtp->rxjitter_samples, rate);
5831
5832 ast_debug_rtcp(3, "%s: pkt: %5u "
5833 "Arrival sec: %7.3f Arrival ts: %10u RX ts: %10u "
5834 "Transit samp: %6d Last transit samp: %6d d: %4d "
5835 "Curr jitter: %7.0f(%7.3f) Prev Jitter: %7.0f(%7.3f) New Jitter: %7.0f(%7.3f)\n",
5837 , rtp->rxcount
5838 , arrival_sec
5839 , arrival
5840 , rx_rtp_ts
5841 , transit
5843 , d
5844 , jitter
5845 , ast_samp2sec(jitter, rate)
5846 , prev_jitter
5847 , ast_samp2sec(prev_jitter, rate)
5848 , rtp->rxjitter_samples
5849 , rtp->rxjitter
5850 );
5851
5852 rtp->last_transit_time_samples = transit;
5853
5854 /*
5855 * Update all the stats.
5856 */
5857 if (rtp->rtcp) {
5858 if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
5859 rtp->rtcp->maxrxjitter = rtp->rxjitter;
5860 if (rtp->rtcp->rxjitter_count == 1)
5861 rtp->rtcp->minrxjitter = rtp->rxjitter;
5862 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
5863 rtp->rtcp->minrxjitter = rtp->rxjitter;
5864
5867 &rtp->rtcp->rxjitter_count);
5868 }
5869
5870 return;
5871}
#define RTP_IGNORE_FIRST_PACKETS_COUNT
static void calc_mean_and_standard_deviation(double new_sample, double *mean, double *std_dev, unsigned int *count)
unsigned int rxjitter_count
unsigned int remote_seed_rx_rtp_ts_stable
double rxstart_stable
struct timeval rxcore
unsigned int last_transit_time_samples
unsigned int remote_seed_rx_rtp_ts
static struct test_val d
unsigned int ast_sec2samp(double _seconds, int _rate)
Returns the number of samples at _rate in the duration in _seconds.
Definition: time.h:333
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
double ast_tv2double(const struct timeval *tv)
Returns a double corresponding to the number of seconds in the timeval tv.
Definition: time.h:270

References ast_debug_rtcp, ast_rtp_get_rate(), ast_rtp_instance_get_channel_id(), ast_samp2sec(), ast_samp2tv(), ast_sec2samp(), ast_tv2double(), ast_tvadd(), ast_tvsub(), calc_mean_and_standard_deviation(), d, ast_rtp::f, ast_frame_subclass::format, ast_rtp::last_transit_time_samples, ast_rtp::lastrxseqno, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtcp::normdev_rxjitter, NULL, ast_rtp::owner, ast_rtp::prevrxseqno, ast_rtp::remote_seed_rx_rtp_ts, ast_rtp::remote_seed_rx_rtp_ts_stable, ast_rtp::rtcp, RTP_IGNORE_FIRST_PACKETS_COUNT, ast_rtp::rxcore, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxjitter_samples, ast_rtp::rxstart, ast_rtp::rxstart_stable, ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

Referenced by ast_rtp_interpret().

◆ calc_txstamp()

static unsigned int calc_txstamp ( struct ast_rtp rtp,
struct timeval *  delivery 
)
static

Definition at line 3925 of file res_rtp_asterisk.c.

3926{
3927 struct timeval t;
3928 long ms;
3929
3930 if (ast_tvzero(rtp->txcore)) {
3931 rtp->txcore = ast_tvnow();
3932 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
3933 }
3934
3935 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
3936 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
3937 ms = 0;
3938 }
3939 rtp->txcore = t;
3940
3941 return (unsigned int) ms;
3942}
struct timeval txcore

References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.

Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), and rtp_raw_write().

◆ calculate_lost_packet_statistics()

static void calculate_lost_packet_statistics ( struct ast_rtp rtp,
unsigned int *  lost_packets,
int *  fraction_lost 
)
static

Definition at line 4686 of file res_rtp_asterisk.c.

4689{
4690 unsigned int extended_seq_no;
4691 unsigned int expected_packets;
4692 unsigned int expected_interval;
4693 unsigned int received_interval;
4694 int lost_interval;
4695
4696 /* Compute statistics */
4697 extended_seq_no = rtp->cycles + rtp->lastrxseqno;
4698 expected_packets = extended_seq_no - rtp->seedrxseqno + 1;
4699 if (rtp->rxcount > expected_packets) {
4700 expected_packets += rtp->rxcount - expected_packets;
4701 }
4702 *lost_packets = expected_packets - rtp->rxcount;
4703 expected_interval = expected_packets - rtp->rtcp->expected_prior;
4704 received_interval = rtp->rxcount - rtp->rtcp->received_prior;
4705 if (received_interval > expected_interval) {
4706 /* If we receive some late packets it is possible for the packets
4707 * we received in this interval to exceed the number we expected.
4708 * We update the expected so that the packet loss calculations
4709 * show that no packets are lost.
4710 */
4711 expected_interval = received_interval;
4712 }
4713 lost_interval = expected_interval - received_interval;
4714 if (expected_interval == 0 || lost_interval <= 0) {
4715 *fraction_lost = 0;
4716 } else {
4717 *fraction_lost = (lost_interval << 8) / expected_interval;
4718 }
4719
4720 /* Update RTCP statistics */
4721 rtp->rtcp->received_prior = rtp->rxcount;
4722 rtp->rtcp->expected_prior = expected_packets;
4723
4724 /*
4725 * While rxlost represents the number of packets lost since the last report was sent, for
4726 * the calculations below it should be thought of as a single sample. Thus min/max are the
4727 * lowest/highest sample value seen, and the mean is the average number of packets lost
4728 * between each report. As such rxlost_count only needs to be incremented per report.
4729 */
4730 if (lost_interval <= 0) {
4731 rtp->rtcp->rxlost = 0;
4732 } else {
4733 rtp->rtcp->rxlost = lost_interval;
4734 }
4735 if (rtp->rtcp->rxlost_count == 0) {
4736 rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4737 }
4738 if (lost_interval && lost_interval < rtp->rtcp->minrxlost) {
4739 rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4740 }
4741 if (lost_interval > rtp->rtcp->maxrxlost) {
4742 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
4743 }
4744
4746 &rtp->rtcp->stdev_rxlost, &rtp->rtcp->rxlost_count);
4747}
unsigned int rxlost_count

References calc_mean_and_standard_deviation(), and ast_srtp::rtp.

Referenced by ast_rtcp_generate_report().

◆ compare_by_value()

static int compare_by_value ( int  elem,
int  value 
)
static

Helper function to compare an elem in a vector by value.

Definition at line 3184 of file res_rtp_asterisk.c.

3185{
3186 return elem - value;
3187}

References value.

Referenced by ast_rtp_read().

◆ create_dtmf_frame()

static struct ast_frame * create_dtmf_frame ( struct ast_rtp_instance instance,
enum ast_frame_type  type,
int  compensate 
)
static

Definition at line 5873 of file res_rtp_asterisk.c.

5874{
5875 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5876 struct ast_sockaddr remote_address = { {0,} };
5877
5878 ast_rtp_instance_get_remote_address(instance, &remote_address);
5879
5880 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
5881 ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
5882 instance, ast_sockaddr_stringify(&remote_address));
5883 rtp->resp = 0;
5884 rtp->dtmfsamples = 0;
5885 return &ast_null_frame;
5886 } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
5887 ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
5888 instance, ast_sockaddr_stringify(&remote_address));
5889 rtp->resp = 0;
5890 rtp->dtmfsamples = 0;
5891 return &ast_null_frame;
5892 }
5893
5894 if (rtp->resp == 'X') {
5895 ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
5896 instance, ast_sockaddr_stringify(&remote_address));
5899 } else {
5900 ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
5901 instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
5902 rtp->resp, rtp->resp,
5903 ast_sockaddr_stringify(&remote_address));
5904 rtp->f.frametype = type;
5905 rtp->f.subclass.integer = rtp->resp;
5906 }
5907 rtp->f.datalen = 0;
5908 rtp->f.samples = 0;
5909 rtp->f.mallocd = 0;
5910 rtp->f.src = "RTP";
5911 AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
5912
5913 return &rtp->f;
5914}
static const char type[]
Definition: chan_ooh323.c:109
@ AST_FRAME_DTMF_BEGIN
@ AST_CONTROL_FLASH
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
unsigned int dtmfsamples
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition: time.h:137

References AST_CONTROL_FLASH, ast_debug_rtp, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_stringify(), ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, NULL, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and type.

Referenced by ast_rtp_interpret(), process_dtmf_cisco(), and process_dtmf_rfc2833().

◆ create_new_socket()

static int create_new_socket ( const char *  type,
int  af 
)
static

Definition at line 3568 of file res_rtp_asterisk.c.

3569{
3570 int sock = ast_socket_nonblock(af, SOCK_DGRAM, 0);
3571
3572 if (sock < 0) {
3573 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
3574 return sock;
3575 }
3576
3577#ifdef SO_NO_CHECK
3578 if (nochecksums) {
3579 setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
3580 }
3581#endif
3582
3583 return sock;
3584}
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1110

References ast_log, ast_socket_nonblock, errno, LOG_WARNING, and type.

Referenced by ast_rtp_prop_set(), and rtp_allocate_transport().

◆ find_by_value()

static int find_by_value ( int  elem,
int  value 
)
static

Helper function to find an elem in a vector by value.

Definition at line 3190 of file res_rtp_asterisk.c.

3191{
3192 return elem == value;
3193}

References value.

Referenced by ast_rtcp_generate_nack(), and ast_rtp_read().

◆ handle_cli_rtcp_set_debug()

static char * handle_cli_rtcp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 9821 of file res_rtp_asterisk.c.

9822{
9823 switch (cmd) {
9824 case CLI_INIT:
9825 e->command = "rtcp set debug {on|off|ip}";
9826 e->usage =
9827 "Usage: rtcp set debug {on|off|ip host[:port]}\n"
9828 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
9829 " specified, limit the dumped packets to those to and from\n"
9830 " the specified 'host' with optional port.\n";
9831 return NULL;
9832 case CLI_GENERATE:
9833 return NULL;
9834 }
9835
9836 if (a->argc == e->args) { /* set on or off */
9837 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9839 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
9840 ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
9841 return CLI_SUCCESS;
9842 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9844 ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
9845 return CLI_SUCCESS;
9846 }
9847 } else if (a->argc == e->args +1) { /* ip */
9848 return rtcp_do_debug_ip(a);
9849 }
9850
9851 return CLI_SHOWUSAGE; /* default, failure */
9852}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define AST_LOG_CATEGORY_DISABLED
#define AST_LOG_CATEGORY_ENABLED
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category's sublevel.
static char * rtcp_do_debug_ip(struct ast_cli_args *a)
static struct ast_sockaddr rtcpdebugaddr
#define AST_LOG_CATEGORY_RTCP_PACKET
Definition: rtp_engine.h:3069
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ast_cli_entry::args, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_DISABLED, AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTCP_PACKET, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, rtcp_do_debug_ip(), rtcpdebugaddr, and ast_cli_entry::usage.

◆ handle_cli_rtcp_set_stats()

static char * handle_cli_rtcp_set_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 9854 of file res_rtp_asterisk.c.

9855{
9856 switch (cmd) {
9857 case CLI_INIT:
9858 e->command = "rtcp set stats {on|off}";
9859 e->usage =
9860 "Usage: rtcp set stats {on|off}\n"
9861 " Enable/Disable dumping of RTCP stats.\n";
9862 return NULL;
9863 case CLI_GENERATE:
9864 return NULL;
9865 }
9866
9867 if (a->argc != e->args)
9868 return CLI_SHOWUSAGE;
9869
9870 if (!strncasecmp(a->argv[e->args-1], "on", 2))
9871 rtcpstats = 1;
9872 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
9873 rtcpstats = 0;
9874 else
9875 return CLI_SHOWUSAGE;
9876
9877 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
9878 return CLI_SUCCESS;
9879}
static int rtcpstats

References a, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, rtcpstats, and ast_cli_entry::usage.

◆ handle_cli_rtp_set_debug()

static char * handle_cli_rtp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 9740 of file res_rtp_asterisk.c.

9741{
9742 switch (cmd) {
9743 case CLI_INIT:
9744 e->command = "rtp set debug {on|off|ip}";
9745 e->usage =
9746 "Usage: rtp set debug {on|off|ip host[:port]}\n"
9747 " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9748 " specified, limit the dumped packets to those to and from\n"
9749 " the specified 'host' with optional port.\n";
9750 return NULL;
9751 case CLI_GENERATE:
9752 return NULL;
9753 }
9754
9755 if (a->argc == e->args) { /* set on or off */
9756 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9758 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
9759 ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
9760 return CLI_SUCCESS;
9761 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9763 ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
9764 return CLI_SUCCESS;
9765 }
9766 } else if (a->argc == e->args +1) { /* ip */
9767 return rtp_do_debug_ip(a);
9768 }
9769
9770 return CLI_SHOWUSAGE; /* default, failure */
9771}
static struct ast_sockaddr rtpdebugaddr
static char * rtp_do_debug_ip(struct ast_cli_args *a)
#define AST_LOG_CATEGORY_RTP_PACKET
Definition: rtp_engine.h:3065

References a, ast_cli_entry::args, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_DISABLED, AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTP_PACKET, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, rtp_do_debug_ip(), rtpdebugaddr, and ast_cli_entry::usage.

◆ handle_cli_rtp_settings()

static char * handle_cli_rtp_settings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 9774 of file res_rtp_asterisk.c.

9775{
9776#ifdef HAVE_PJPROJECT
9777 struct sockaddr_in stunaddr_copy;
9778#endif
9779 switch (cmd) {
9780 case CLI_INIT:
9781 e->command = "rtp show settings";
9782 e->usage =
9783 "Usage: rtp show settings\n"
9784 " Display RTP configuration settings\n";
9785 return NULL;
9786 case CLI_GENERATE:
9787 return NULL;
9788 }
9789
9790 if (a->argc != 3) {
9791 return CLI_SHOWUSAGE;
9792 }
9793
9794 ast_cli(a->fd, "\n\nGeneral Settings:\n");
9795 ast_cli(a->fd, "----------------\n");
9796 ast_cli(a->fd, " Port start: %d\n", rtpstart);
9797 ast_cli(a->fd, " Port end: %d\n", rtpend);
9798#ifdef SO_NO_CHECK
9799 ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
9800#endif
9801 ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
9802 ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
9803
9804 if (strictrtp) {
9805 ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
9806 }
9807
9808 ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
9809#ifdef HAVE_PJPROJECT
9810 ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
9811
9812 ast_rwlock_rdlock(&stunaddr_lock);
9813 memcpy(&stunaddr_copy, &stunaddr, sizeof(stunaddr));
9814 ast_rwlock_unlock(&stunaddr_lock);
9815 ast_cli(a->fd, " STUN address: %s:%d\n", ast_inet_ntoa(stunaddr_copy.sin_addr), htons(stunaddr_copy.sin_port));
9816#endif
9817 return CLI_SUCCESS;
9818}
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
#define ast_rwlock_rdlock(a)
Definition: lock.h:242
#define ast_rwlock_unlock(a)
Definition: lock.h:241
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:964
static int rtpend
static int learning_min_sequential
static int rtpstart
static int dtmftimeout

References a, ast_cli(), AST_CLI_YESNO, ast_inet_ntoa(), ast_rwlock_rdlock, ast_rwlock_unlock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dtmftimeout, learning_min_sequential, NULL, rtpend, rtpstart, srtp_replay_protection, strictrtp, and ast_cli_entry::usage.

◆ load_module()

static int load_module ( void  )
static

Definition at line 10333 of file res_rtp_asterisk.c.

10334{
10335#ifdef HAVE_PJPROJECT
10336 pj_lock_t *lock;
10337
10339
10341 if (pj_init() != PJ_SUCCESS) {
10343 }
10344
10345 if (pjlib_util_init() != PJ_SUCCESS) {
10346 rtp_terminate_pjproject();
10348 }
10349
10350 if (pjnath_init() != PJ_SUCCESS) {
10351 rtp_terminate_pjproject();
10353 }
10354
10355 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10356
10357 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10358
10359 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10360 rtp_terminate_pjproject();
10362 }
10363
10364 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10365 rtp_terminate_pjproject();
10367 }
10368
10369 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10370
10371 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10372 rtp_terminate_pjproject();
10374 }
10375
10376#endif
10377
10378#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10379 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10380 if (!dtls_bio_methods) {
10381#ifdef HAVE_PJPROJECT
10382 rtp_terminate_pjproject();
10383#endif
10385 }
10386 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10387 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10388 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10389 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10390#endif
10391
10393#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10394 BIO_meth_free(dtls_bio_methods);
10395#endif
10396#ifdef HAVE_PJPROJECT
10397 rtp_terminate_pjproject();
10398#endif
10400 }
10401
10403#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10404 BIO_meth_free(dtls_bio_methods);
10405#endif
10406#ifdef HAVE_PJPROJECT
10408 rtp_terminate_pjproject();
10409#endif
10411 }
10412
10413 rtp_reload(0, 0);
10414
10416}
ast_mutex_t lock
Definition: app_sla.c:337
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define AST_PJPROJECT_INIT_LOG_LEVEL()
Get maximum log level pjproject was compiled with.
Definition: options.h:177
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static int rtp_reload(int reload, int by_external_config)
static struct ast_rtp_engine asterisk_rtp_engine
static struct ast_cli_entry cli_rtp[]
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:370
#define ast_rtp_engine_register(engine)
Definition: rtp_engine.h:852
#define ARRAY_LEN(a)
Definition: utils.h:703

References ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_pjproject_caching_pool_init(), AST_PJPROJECT_INIT_LOG_LEVEL, ast_rtp_engine_register, ast_rtp_engine_unregister(), ast_sockaddr_parse(), asterisk_rtp_engine, cachingpool, cli_rtp, lock, NULL, PARSE_PORT_IGNORE, and rtp_reload().

◆ ntp2timeval()

static void ntp2timeval ( unsigned int  msw,
unsigned int  lsw,
struct timeval *  tv 
)
static

Definition at line 4679 of file res_rtp_asterisk.c.

4680{
4681 tv->tv_sec = msw - 2208988800u;
4682 /* Reverse the sequence in timeval2ntp() */
4683 tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
4684}

Referenced by ast_rtcp_interpret().

◆ process_cn_rfc3389()

static struct ast_frame * process_cn_rfc3389 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
int  payloadtype,
int  mark 
)
static

Definition at line 6134 of file res_rtp_asterisk.c.

6135{
6136 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6137
6138 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
6139 totally help us out because we don't have an engine to keep it going and we are not
6140 guaranteed to have it every 20ms or anything */
6142 ast_debug(0, "- RTP 3389 Comfort noise event: Format %s (len = %d)\n",
6144 }
6145
6146 if (!ast_test_flag(rtp, FLAG_3389_WARNING)) {
6147 struct ast_sockaddr remote_address = { {0,} };
6148
6149 ast_rtp_instance_get_remote_address(instance, &remote_address);
6150
6151 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
6152 ast_sockaddr_stringify(&remote_address));
6154 }
6155
6156 /* Must have at least one byte */
6157 if (!len) {
6158 return NULL;
6159 }
6160 if (len < 24) {
6161 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
6162 rtp->f.datalen = len - 1;
6164 memcpy(rtp->f.data.ptr, data + 1, len - 1);
6165 } else {
6166 rtp->f.data.ptr = NULL;
6167 rtp->f.offset = 0;
6168 rtp->f.datalen = 0;
6169 }
6170 rtp->f.frametype = AST_FRAME_CNG;
6171 rtp->f.subclass.integer = data[0] & 0x7f;
6172 rtp->f.samples = 0;
6173 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
6174
6175 return &rtp->f;
6176}
#define FLAG_3389_WARNING

References ast_debug, ast_debug_rtp_packet_is_allowed, ast_format_get_name(), AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_log, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_set_flag, ast_sockaddr_stringify(), ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_3389_WARNING, ast_frame::frametype, ast_frame_subclass::integer, ast_rtp::lastrxformat, len(), LOG_NOTICE, NULL, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, ast_frame::samples, and ast_frame::subclass.

Referenced by ast_rtp_interpret().

◆ process_dtmf_cisco()

static struct ast_frame * process_dtmf_cisco ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
int  payloadtype,
int  mark 
)
static

Definition at line 6054 of file res_rtp_asterisk.c.

6055{
6056 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6057 unsigned int event, flags, power;
6058 char resp = 0;
6059 unsigned char seq;
6060 struct ast_frame *f = NULL;
6061
6062 if (len < 4) {
6063 return NULL;
6064 }
6065
6066 /* The format of Cisco RTP DTMF packet looks like next:
6067 +0 - sequence number of DTMF RTP packet (begins from 1,
6068 wrapped to 0)
6069 +1 - set of flags
6070 +1 (bit 0) - flaps by different DTMF digits delimited by audio
6071 or repeated digit without audio???
6072 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
6073 then falls to 0 at its end)
6074 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
6075 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
6076 by each new packet and thus provides some redundancy.
6077
6078 Sample of Cisco RTP DTMF packet is (all data in hex):
6079 19 07 00 02 12 02 20 02
6080 showing end of DTMF digit '2'.
6081
6082 The packets
6083 27 07 00 02 0A 02 20 02
6084 28 06 20 02 00 02 0A 02
6085 shows begin of new digit '2' with very short pause (20 ms) after
6086 previous digit '2'. Bit +1.0 flips at begin of new digit.
6087
6088 Cisco RTP DTMF packets comes as replacement of audio RTP packets
6089 so its uses the same sequencing and timestamping rules as replaced
6090 audio packets. Repeat interval of DTMF packets is 20 ms and not rely
6091 on audio framing parameters. Marker bit isn't used within stream of
6092 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
6093 are not sequential at borders between DTMF and audio streams,
6094 */
6095
6096 seq = data[0];
6097 flags = data[1];
6098 power = data[2];
6099 event = data[3] & 0x1f;
6100
6102 ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%u, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
6103 if (event < 10) {
6104 resp = '0' + event;
6105 } else if (event < 11) {
6106 resp = '*';
6107 } else if (event < 12) {
6108 resp = '#';
6109 } else if (event < 16) {
6110 resp = 'A' + (event - 12);
6111 } else if (event < 17) {
6112 resp = 'X';
6113 }
6114 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
6115 rtp->resp = resp;
6116 /* Why we should care on DTMF compensation at reception? */
6118 f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
6119 rtp->dtmfsamples = 0;
6120 }
6121 } else if ((rtp->resp == resp) && !power) {
6123 f->samples = rtp->dtmfsamples * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
6124 rtp->resp = 0;
6125 } else if (rtp->resp == resp) {
6126 rtp->dtmfsamples += 20 * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
6127 }
6128
6129 rtp->dtmf_timeout = 0;
6130
6131 return f;
6132}
static volatile unsigned int seq
Definition: app_sms.c:126
@ AST_RTP_PROPERTY_DTMF_COMPENSATE
Definition: rtp_engine.h:122
unsigned int flags
unsigned int flags
Definition: astman.c:222

References ast_debug, ast_debug_rtp_packet_is_allowed, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_DTMF_COMPENSATE, create_dtmf_frame(), ast_frame::data, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, ast_frame::flags, ast_rtp::flags, ast_rtp::lastrxformat, len(), NULL, ast_rtp::resp, ast_frame::samples, and seq.

Referenced by ast_rtp_interpret().

◆ process_dtmf_rfc2833()

static void process_dtmf_rfc2833 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
int  payloadtype,
int  mark,
struct frame_list frames 
)
static

Definition at line 5916 of file res_rtp_asterisk.c.

5917{
5918 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5919 struct ast_sockaddr remote_address = { {0,} };
5920 unsigned int event, event_end, samples;
5921 char resp = 0;
5922 struct ast_frame *f = NULL;
5923
5924 ast_rtp_instance_get_remote_address(instance, &remote_address);
5925
5926 /* Figure out event, event end, and samples */
5927 event = ntohl(*((unsigned int *)(data)));
5928 event >>= 24;
5929 event_end = ntohl(*((unsigned int *)(data)));
5930 event_end <<= 8;
5931 event_end >>= 24;
5932 samples = ntohl(*((unsigned int *)(data)));
5933 samples &= 0xFFFF;
5934
5935 if (rtp_debug_test_addr(&remote_address)) {
5936 ast_verbose("Got RTP RFC2833 from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d, mark %d, event %08x, end %d, duration %-5.5u) \n",
5937 ast_sockaddr_stringify(&remote_address),
5938 payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
5939 }
5940
5941 /* Print out debug if turned on */
5943 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
5944
5945 /* Figure out what digit was pressed */
5946 if (event < 10) {
5947 resp = '0' + event;
5948 } else if (event < 11) {
5949 resp = '*';
5950 } else if (event < 12) {
5951 resp = '#';
5952 } else if (event < 16) {
5953 resp = 'A' + (event - 12);
5954 } else if (event < 17) { /* Event 16: Hook flash */
5955 resp = 'X';
5956 } else {
5957 /* Not a supported event */
5958 ast_debug_rtp(1, "(%p) RTP ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", instance, event);
5959 return;
5960 }
5961
5963 if (!rtp->last_end_timestamp.is_set || rtp->last_end_timestamp.ts != timestamp || (rtp->resp && rtp->resp != resp)) {
5964 rtp->resp = resp;
5965 rtp->dtmf_timeout = 0;
5967 f->len = 0;
5968 rtp->last_end_timestamp.ts = timestamp;
5969 rtp->last_end_timestamp.is_set = 1;
5971 }
5972 } else {
5973 /* The duration parameter measures the complete
5974 duration of the event (from the beginning) - RFC2833.
5975 Account for the fact that duration is only 16 bits long
5976 (about 8 seconds at 8000 Hz) and can wrap is digit
5977 is hold for too long. */
5978 unsigned int new_duration = rtp->dtmf_duration;
5979 unsigned int last_duration = new_duration & 0xFFFF;
5980
5981 if (last_duration > 64000 && samples < last_duration) {
5982 new_duration += 0xFFFF + 1;
5983 }
5984 new_duration = (new_duration & ~0xFFFF) | samples;
5985
5986 if (event_end & 0x80) {
5987 /* End event */
5988 if (rtp->last_seqno != seqno && (!rtp->last_end_timestamp.is_set || timestamp > rtp->last_end_timestamp.ts)) {
5989 rtp->last_end_timestamp.ts = timestamp;
5990 rtp->last_end_timestamp.is_set = 1;
5991 rtp->dtmf_duration = new_duration;
5992 rtp->resp = resp;
5995 rtp->resp = 0;
5996 rtp->dtmf_duration = rtp->dtmf_timeout = 0;
5999 ast_debug_rtp(1, "(%p) RTP dropping duplicate or out of order DTMF END frame (seqno: %u, ts %u, digit %c)\n",
6000 instance, seqno, timestamp, resp);
6001 }
6002 } else {
6003 /* Begin/continuation */
6004
6005 /* The second portion of the seqno check is to not mistakenly
6006 * stop accepting DTMF if the seqno rolls over beyond
6007 * 65535.
6008 */
6009 if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
6010 || (rtp->last_end_timestamp.is_set
6011 && timestamp <= rtp->last_end_timestamp.ts)) {
6012 /* Out of order frame. Processing this can cause us to
6013 * improperly duplicate incoming DTMF, so just drop
6014 * this.
6015 */
6017 ast_debug(0, "Dropping out of order DTMF frame (seqno %u, ts %u, digit %c)\n",
6018 seqno, timestamp, resp);
6019 }
6020 return;
6021 }
6022
6023 if (rtp->resp && rtp->resp != resp) {
6024 /* Another digit already began. End it */
6027 rtp->resp = 0;
6028 rtp->dtmf_duration = rtp->dtmf_timeout = 0;
6030 }
6031
6032 if (rtp->resp) {
6033 /* Digit continues */
6034 rtp->dtmf_duration = new_duration;
6035 } else {
6036 /* New digit began */
6037 rtp->resp = resp;
6039 rtp->dtmf_duration = samples;
6041 }
6042
6043 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
6044 }
6045
6046 rtp->last_seqno = seqno;
6047 }
6048
6049 rtp->dtmfsamples = samples;
6050
6051 return;
6052}

References ast_debug, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup, AST_LIST_INSERT_TAIL, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), ast_verbose(), create_dtmf_frame(), ast_frame::data, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, dtmftimeout, ast_frame_subclass::format, frames, optional_ts::is_set, ast_rtp::last_end_timestamp, ast_rtp::last_seqno, len(), ast_frame::len, NULL, ast_rtp::resp, rtp_debug_test_addr(), ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and optional_ts::ts.

Referenced by ast_rtp_interpret().

◆ put_unaligned_time24()

static void put_unaligned_time24 ( void *  p,
uint32_t  time_msw,
uint32_t  time_lsw 
)
static

Definition at line 5141 of file res_rtp_asterisk.c.

5142{
5143 unsigned char *cp = p;
5144 uint32_t datum;
5145
5146 /* Convert the time to 6.18 format */
5147 datum = (time_msw << 18) & 0x00fc0000;
5148 datum |= (time_lsw >> 14) & 0x0003ffff;
5149
5150 cp[0] = datum >> 16;
5151 cp[1] = datum >> 8;
5152 cp[2] = datum;
5153}

Referenced by ast_rtp_rtcp_handle_nack(), rtp_raw_write(), and rtp_transport_wide_cc_feedback_produce().

◆ red_t140_to_red()

static struct ast_frame * red_t140_to_red ( struct rtp_red red)
static

Definition at line 5386 of file res_rtp_asterisk.c.

5387{
5388 unsigned char *data = red->t140red.data.ptr;
5389 int len = 0;
5390 int i;
5391
5392 /* replace most aged generation */
5393 if (red->len[0]) {
5394 for (i = 1; i < red->num_gen+1; i++)
5395 len += red->len[i];
5396
5397 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
5398 }
5399
5400 /* Store length of each generation and primary data length*/
5401 for (i = 0; i < red->num_gen; i++)
5402 red->len[i] = red->len[i+1];
5403 red->len[i] = red->t140.datalen;
5404
5405 /* write each generation length in red header */
5406 len = red->hdrlen;
5407 for (i = 0; i < red->num_gen; i++) {
5408 len += data[i*4+3] = red->len[i];
5409 }
5410
5411 /* add primary data to buffer */
5412 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
5413 red->t140red.datalen = len + red->t140.datalen;
5414
5415 /* no primary data and no generations to send */
5416 if (len == red->hdrlen && !red->t140.datalen) {
5417 return NULL;
5418 }
5419
5420 /* reset t.140 buffer */
5421 red->t140.datalen = 0;
5422
5423 return &red->t140red;
5424}
struct ast_frame t140
unsigned char len[AST_RED_MAX_GENERATION]
struct ast_frame t140red

References ast_frame::data, ast_frame::datalen, rtp_red::hdrlen, len(), rtp_red::len, NULL, rtp_red::num_gen, ast_frame::ptr, rtp_red::t140, and rtp_red::t140red.

Referenced by ast_rtp_write().

◆ red_write()

static int red_write ( const void *  data)
static

Write t140 redundancy frame.

Parameters
dataprimary data to be buffered

Scheduler callback

Definition at line 9146 of file res_rtp_asterisk.c.

9147{
9148 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
9149 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9150
9151 ao2_lock(instance);
9152 if (rtp->red->t140.datalen > 0) {
9153 ast_rtp_write(instance, &rtp->red->t140);
9154 }
9155 ao2_unlock(instance);
9156
9157 return 1;
9158}
static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)

References ao2_lock, ao2_unlock, ast_rtp_instance_get_data(), ast_rtp_write(), ast_rtp_instance::data, ast_frame::datalen, ast_rtp::red, and rtp_red::t140.

Referenced by rtp_red_init().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 10301 of file res_rtp_asterisk.c.

10302{
10303 rtp_reload(1, 0);
10304 return 0;
10305}

References rtp_reload().

◆ rtcp_debug_test_addr()

static int rtcp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2846 of file res_rtp_asterisk.c.

2847{
2849 return 0;
2850 }
2852 if (rtcpdebugport) {
2853 return (ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0); /* look for RTCP packets from IP+Port */
2854 } else {
2855 return (ast_sockaddr_cmp_addr(&rtcpdebugaddr, addr) == 0); /* only look for RTCP packets from IP */
2856 }
2857 }
2858
2859 return 1;
2860}
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413
static int rtcpdebugport
#define ast_debug_rtcp_packet_is_allowed
Definition: rtp_engine.h:3124

References ast_debug_rtcp_packet_is_allowed, ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), rtcpdebugaddr, and rtcpdebugport.

Referenced by ast_rtcp_calculate_sr_rr_statistics(), and ast_rtcp_interpret().

◆ rtcp_do_debug_ip()

static char * rtcp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9723 of file res_rtp_asterisk.c.

9724{
9725 char *arg = ast_strdupa(a->argv[4]);
9726 char *debughost = NULL;
9727 char *debugport = NULL;
9728
9729 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9730 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9731 return CLI_FAILURE;
9732 }
9733 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9734 ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9737 return CLI_SUCCESS;
9738}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define CLI_FAILURE
Definition: cli.h:46
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition: netsock2.c:164
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References a, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTCP_PACKET, ast_sockaddr_parse(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify(), ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_SUCCESS, NULL, rtcpdebugaddr, and rtcpdebugport.

Referenced by handle_cli_rtcp_set_debug().

◆ rtcp_mux()

static int rtcp_mux ( struct ast_rtp rtp,
const unsigned char *  packet 
)
static

Definition at line 3195 of file res_rtp_asterisk.c.

3196{
3197 uint8_t version;
3198 uint8_t pt;
3199 uint8_t m;
3200
3201 if (!rtp->rtcp || rtp->rtcp->type != AST_RTP_INSTANCE_RTCP_MUX) {
3202 return 0;
3203 }
3204
3205 version = (packet[0] & 0XC0) >> 6;
3206 if (version == 0) {
3207 /* version 0 indicates this is a STUN packet and shouldn't
3208 * be interpreted as a possible RTCP packet
3209 */
3210 return 0;
3211 }
3212
3213 /* The second octet of a packet will be one of the following:
3214 * For RTP: The marker bit (1 bit) and the RTP payload type (7 bits)
3215 * For RTCP: The payload type (8)
3216 *
3217 * RTP has a forbidden range of payload types (64-95) since these
3218 * will conflict with RTCP payload numbers if the marker bit is set.
3219 */
3220 m = packet[1] & 0x80;
3221 pt = packet[1] & 0x7F;
3222 if (m && pt >= 64 && pt <= 95) {
3223 return 1;
3224 }
3225 return 0;
3226}
@ AST_RTP_INSTANCE_RTCP_MUX
Definition: rtp_engine.h:289

References AST_RTP_INSTANCE_RTCP_MUX, ast_rtp::rtcp, ast_rtcp::type, and version.

Referenced by ast_rtp_read().

◆ rtcp_payload_subtype2str()

static const char * rtcp_payload_subtype2str ( unsigned int  pt,
unsigned int  subtype 
)
static

Definition at line 6506 of file res_rtp_asterisk.c.

6507{
6508 switch (pt) {
6509 case AST_RTP_RTCP_RTPFB:
6510 if (subtype == AST_RTP_RTCP_FMT_NACK) {
6511 return "NACK";
6512 }
6513 break;
6514 case RTCP_PT_PSFB:
6515 if (subtype == AST_RTP_RTCP_FMT_REMB) {
6516 return "REMB";
6517 }
6518 break;
6519 default:
6520 break;
6521 }
6522
6523 return NULL;
6524}

References AST_RTP_RTCP_FMT_NACK, AST_RTP_RTCP_FMT_REMB, AST_RTP_RTCP_RTPFB, NULL, and RTCP_PT_PSFB.

Referenced by ast_rtcp_interpret().

◆ rtcp_payload_type2str()

static const char * rtcp_payload_type2str ( unsigned int  pt)
static

Definition at line 6474 of file res_rtp_asterisk.c.

6475{
6476 const char *str;
6477
6478 switch (pt) {
6479 case RTCP_PT_SR:
6480 str = "Sender Report";
6481 break;
6482 case RTCP_PT_RR:
6483 str = "Receiver Report";
6484 break;
6485 case RTCP_PT_FUR:
6486 /* Full INTRA-frame Request / Fast Update Request */
6487 str = "H.261 FUR";
6488 break;
6489 case RTCP_PT_PSFB:
6490 /* Payload Specific Feed Back */
6491 str = "PSFB";
6492 break;
6493 case RTCP_PT_SDES:
6494 str = "Source Description";
6495 break;
6496 case RTCP_PT_BYE:
6497 str = "BYE";
6498 break;
6499 default:
6500 str = "Unknown";
6501 break;
6502 }
6503 return str;
6504}
const char * str
Definition: app_jack.c:150

References RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_PSFB, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, and str.

Referenced by ast_rtcp_interpret().

◆ rtcp_recvfrom()

static int rtcp_recvfrom ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa 
)
static
Precondition
instance is locked

Definition at line 3433 of file res_rtp_asterisk.c.

3434{
3435 return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
3436}
static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)

References __rtp_recvfrom(), and buf.

Referenced by ast_rtcp_read().

◆ rtcp_sendto()

static int rtcp_sendto ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa,
int *  ice 
)
static
Precondition
instance is locked

Definition at line 3511 of file res_rtp_asterisk.c.

3512{
3513 return __rtp_sendto(instance, buf, size, flags, sa, 1, ice, 1);
3514}
static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *via_ice, int use_srtp)

References __rtp_sendto(), and buf.

Referenced by ast_rtcp_write(), ast_rtp_read(), rtp_transport_wide_cc_feedback_produce(), rtp_write_rtcp_fir(), and rtp_write_rtcp_psfb().

◆ rtp_allocate_transport()

static int rtp_allocate_transport ( struct ast_rtp_instance instance,
struct ast_rtp rtp 
)
static

Definition at line 4037 of file res_rtp_asterisk.c.

4038{
4039 int x, startplace, i, maxloops;
4040
4042
4043 /* Create a new socket for us to listen on and use */
4044 if ((rtp->s =
4045 create_new_socket("RTP",
4046 ast_sockaddr_is_ipv4(&rtp->bind_address) ? AF_INET :
4047 ast_sockaddr_is_ipv6(&rtp->bind_address) ? AF_INET6 : -1)) < 0) {
4048 ast_log(LOG_WARNING, "Failed to create a new socket for RTP instance '%p'\n", instance);
4049 return -1;
4050 }
4051
4052 /* Now actually find a free RTP port to use */
4053 x = (ast_random() % (rtpend - rtpstart)) + rtpstart;
4054 x = x & ~1;
4055 startplace = x;
4056
4057 /* Protection against infinite loops in the case there is a potential case where the loop is not broken such as an odd
4058 start port sneaking in (even though this condition is checked at load.) */
4059 maxloops = rtpend - rtpstart;
4060 for (i = 0; i <= maxloops; i++) {
4062 /* Try to bind, this will tell us whether the port is available or not */
4063 if (!ast_bind(rtp->s, &rtp->bind_address)) {
4064 ast_debug_rtp(1, "(%p) RTP allocated port %d\n", instance, x);
4066 ast_test_suite_event_notify("RTP_PORT_ALLOCATED", "Port: %d", x);
4067 break;
4068 }
4069
4070 x += 2;
4071 if (x > rtpend) {
4072 x = (rtpstart + 1) & ~1;
4073 }
4074
4075 /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
4076 if (x == startplace || (errno != EADDRINUSE && errno != EACCES)) {
4077 ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
4078 close(rtp->s);
4079 rtp->s = -1;
4080 return -1;
4081 }
4082 }
4083
4084#ifdef HAVE_PJPROJECT
4085 /* Initialize synchronization aspects */
4086 ast_cond_init(&rtp->cond, NULL);
4087
4088 generate_random_string(rtp->local_ufrag, sizeof(rtp->local_ufrag));
4089 generate_random_string(rtp->local_passwd, sizeof(rtp->local_passwd));
4090
4091 /* Create an ICE session for ICE negotiation */
4092 if (icesupport) {
4093 rtp->ice_num_components = 2;
4094 ast_debug_ice(2, "(%p) ICE creating session %s (%d)\n", instance,
4096 if (ice_create(instance, &rtp->bind_address, x, 0)) {
4097 ast_log(LOG_NOTICE, "(%p) ICE failed to create session\n", instance);
4098 } else {
4099 rtp->ice_port = x;
4100 ast_sockaddr_copy(&rtp->ice_original_rtp_addr, &rtp->bind_address);
4101 }
4102 }
4103#endif
4104
4105#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
4106 rtp->rekeyid = -1;
4107 rtp->dtls.timeout_timer = -1;
4108#endif
4109
4110 return 0;
4111}
#define ast_cond_init(cond, attr)
Definition: lock.h:208
static char * generate_random_string(char *buf, size_t size)
Generate 32 byte random string (stolen from chan_sip.c)
Definition: res_calendar.c:734
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:3145

References ast_bind(), ast_cond_init, ast_debug_ice, ast_debug_rtp, ast_log, ast_random(), ast_rtp_instance_set_local_address(), ast_sockaddr_copy(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_test_suite_event_notify, ast_rtp::bind_address, create_new_socket(), errno, generate_random_string(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, rtpend, rtpstart, ast_rtp::s, STRICT_RTP_CLOSED, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, and strictrtp.

Referenced by ast_rtp_bundle(), and ast_rtp_new().

◆ rtp_deallocate_transport()

static void rtp_deallocate_transport ( struct ast_rtp_instance instance,
struct ast_rtp rtp 
)
static

Definition at line 4113 of file res_rtp_asterisk.c.

4114{
4115 int saved_rtp_s = rtp->s;
4116#ifdef HAVE_PJPROJECT
4117 struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
4118 struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
4119#endif
4120
4121#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
4122 ast_rtp_dtls_stop(instance);
4123#endif
4124
4125 /* Close our own socket so we no longer get packets */
4126 if (rtp->s > -1) {
4127 close(rtp->s);
4128 rtp->s = -1;
4129 }
4130
4131 /* Destroy RTCP if it was being used */
4132 if (rtp->rtcp && rtp->rtcp->s > -1) {
4133 if (saved_rtp_s != rtp->rtcp->s) {
4134 close(rtp->rtcp->s);
4135 }
4136 rtp->rtcp->s = -1;
4137 }
4138
4139#ifdef HAVE_PJPROJECT
4140 pj_thread_register_check();
4141
4142 /*
4143 * The instance lock is already held.
4144 *
4145 * Destroy the RTP TURN relay if being used
4146 */
4147 if (rtp->turn_rtp) {
4148 rtp->turn_state = PJ_TURN_STATE_NULL;
4149
4150 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
4151 ao2_unlock(instance);
4152 pj_turn_sock_destroy(rtp->turn_rtp);
4153 ao2_lock(instance);
4154 while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
4155 ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
4156 }
4157 rtp->turn_rtp = NULL;
4158 }
4159
4160 /* Destroy the RTCP TURN relay if being used */
4161 if (rtp->turn_rtcp) {
4162 rtp->turn_state = PJ_TURN_STATE_NULL;
4163
4164 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
4165 ao2_unlock(instance);
4166 pj_turn_sock_destroy(rtp->turn_rtcp);
4167 ao2_lock(instance);
4168 while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
4169 ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
4170 }
4171 rtp->turn_rtcp = NULL;
4172 }
4173
4174 ast_debug_ice(2, "(%p) ICE RTP transport deallocating\n", instance);
4175 /* Destroy any ICE session */
4176 ast_rtp_ice_stop(instance);
4177
4178 /* Destroy any candidates */
4179 if (rtp->ice_local_candidates) {
4180 ao2_ref(rtp->ice_local_candidates, -1);
4181 rtp->ice_local_candidates = NULL;
4182 }
4183
4184 if (rtp->ice_active_remote_candidates) {
4185 ao2_ref(rtp->ice_active_remote_candidates, -1);
4186 rtp->ice_active_remote_candidates = NULL;
4187 }
4188
4189 if (rtp->ice_proposed_remote_candidates) {
4190 ao2_ref(rtp->ice_proposed_remote_candidates, -1);
4191 rtp->ice_proposed_remote_candidates = NULL;
4192 }
4193
4194 if (rtp->ioqueue) {
4195 /*
4196 * We cannot hold the instance lock because we could wait
4197 * for the ioqueue thread to die and we might deadlock as
4198 * a result.
4199 */
4200 ao2_unlock(instance);
4201 rtp_ioqueue_thread_remove(rtp->ioqueue);
4202 ao2_lock(instance);
4203 rtp->ioqueue = NULL;
4204 }
4205#endif
4206}
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:213
#define TURN_STATE_WAIT_TIME

References ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, ast_cond_timedwait, ast_debug_ice, ast_samp2tv(), ast_tvadd(), ast_tvnow(), NULL, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, and TURN_STATE_WAIT_TIME.

Referenced by ast_rtp_bundle(), and ast_rtp_destroy().

◆ rtp_debug_test_addr()

static int rtp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2830 of file res_rtp_asterisk.c.

2831{
2833 return 0;
2834 }
2836 if (rtpdebugport) {
2837 return (ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0); /* look for RTP packets from IP+Port */
2838 } else {
2839 return (ast_sockaddr_cmp_addr(&rtpdebugaddr, addr) == 0); /* only look for RTP packets from IP */
2840 }
2841 }
2842
2843 return 1;
2844}
static int rtpdebugport

References ast_debug_rtp_packet_is_allowed, ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), rtpdebugaddr, and rtpdebugport.

Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), ast_rtp_read(), ast_rtp_sendcng(), bridge_p2p_rtp_write(), process_dtmf_rfc2833(), and rtp_raw_write().

◆ rtp_do_debug_ip()

static char * rtp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9706 of file res_rtp_asterisk.c.

9707{
9708 char *arg = ast_strdupa(a->argv[4]);
9709 char *debughost = NULL;
9710 char *debugport = NULL;
9711
9712 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9713 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9714 return CLI_FAILURE;
9715 }
9716 rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9717 ast_cli(a->fd, "RTP Packet Debugging Enabled for address: %s\n",
9720 return CLI_SUCCESS;
9721}

References a, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTP_PACKET, ast_sockaddr_parse(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify(), ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_SUCCESS, NULL, rtpdebugaddr, and rtpdebugport.

Referenced by handle_cli_rtp_set_debug().

◆ rtp_find_instance_by_media_source_ssrc()

static struct ast_rtp_instance * rtp_find_instance_by_media_source_ssrc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned int  ssrc 
)
static
Precondition
instance is locked

Definition at line 6468 of file res_rtp_asterisk.c.

6470{
6471 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
6472}
static struct ast_rtp_instance * __rtp_find_instance_by_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc, int source)

References __rtp_find_instance_by_ssrc().

Referenced by ast_rtcp_interpret().

◆ rtp_find_instance_by_packet_source_ssrc()

static struct ast_rtp_instance * rtp_find_instance_by_packet_source_ssrc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned int  ssrc 
)
static
Precondition
instance is locked

Definition at line 6461 of file res_rtp_asterisk.c.

6463{
6464 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6465}

References __rtp_find_instance_by_ssrc().

Referenced by ast_rtcp_interpret(), and ast_rtp_read().

◆ rtp_instance_parse_extmap_extensions()

static void rtp_instance_parse_extmap_extensions ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned char *  extension,
int  len 
)
static

Definition at line 7722 of file res_rtp_asterisk.c.

7724{
7725 int transport_wide_cc_id = ast_rtp_instance_extmap_get_id(instance, AST_RTP_EXTENSION_TRANSPORT_WIDE_CC);
7726 int pos = 0;
7727
7728 /* We currently only care about the transport-cc extension, so if that's not negotiated then do nothing */
7729 if (transport_wide_cc_id == -1) {
7730 return;
7731 }
7732
7733 /* Only while we do not exceed available extension data do we continue */
7734 while (pos < len) {
7735 int id = extension[pos] >> 4;
7736 int extension_len = (extension[pos] & 0xF) + 1;
7737
7738 /* We've handled the first byte as it contains the extension id and length, so always
7739 * skip ahead now
7740 */
7741 pos += 1;
7742
7743 if (id == 0) {
7744 /* From the RFC:
7745 * In both forms, padding bytes have the value of 0 (zero). They may be
7746 * placed between extension elements, if desired for alignment, or after
7747 * the last extension element, if needed for padding. A padding byte
7748 * does not supply the ID of an element, nor the length field. When a
7749 * padding byte is found, it is ignored and the parser moves on to
7750 * interpreting the next byte.
7751 */
7752 continue;
7753 } else if (id == 15) {
7754 /* From the RFC:
7755 * The local identifier value 15 is reserved for future extension and
7756 * MUST NOT be used as an identifier. If the ID value 15 is
7757 * encountered, its length field should be ignored, processing of the
7758 * entire extension should terminate at that point, and only the
7759 * extension elements present prior to the element with ID 15
7760 * considered.
7761 */
7762 break;
7763 } else if ((pos + extension_len) > len) {
7764 /* The extension is corrupted and is stating that it contains more data than is
7765 * available in the extensions data.
7766 */
7767 break;
7768 }
7769
7770 /* If this is transport-cc then we need to parse it further */
7771 if (id == transport_wide_cc_id) {
7772 rtp_instance_parse_transport_wide_cc(instance, rtp, extension + pos, extension_len);
7773 }
7774
7775 /* Skip ahead to the next extension */
7776 pos += extension_len;
7777 }
7778}
static void rtp_instance_parse_transport_wide_cc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *data, int len)

References AST_RTP_EXTENSION_TRANSPORT_WIDE_CC, ast_rtp_instance_extmap_get_id(), len(), and rtp_instance_parse_transport_wide_cc().

Referenced by ast_rtp_interpret().

◆ rtp_instance_parse_transport_wide_cc()

static void rtp_instance_parse_transport_wide_cc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned char *  data,
int  len 
)
static

Definition at line 7667 of file res_rtp_asterisk.c.

7669{
7670 uint16_t *seqno = (uint16_t *)data;
7672 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
7673 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
7674
7675 /* If the sequence number has cycled over then record it as such */
7676 if (((int)transport_rtp->transport_wide_cc.last_seqno - (int)ntohs(*seqno)) > 100) {
7677 transport_rtp->transport_wide_cc.cycles += RTP_SEQ_MOD;
7678 }
7679
7680 /* Populate the statistics information for this packet */
7681 statistics.seqno = transport_rtp->transport_wide_cc.cycles + ntohs(*seqno);
7682 statistics.received = ast_tvnow();
7683
7684 /* We allow at a maximum 1000 packet statistics in play at a time, if we hit the
7685 * limit we give up and start fresh.
7686 */
7687 if (AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) > 1000) {
7689 }
7690
7691 if (!AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) ||
7692 statistics.seqno > transport_rtp->transport_wide_cc.last_extended_seqno) {
7693 /* This is the expected path */
7695 return;
7696 }
7697
7698 transport_rtp->transport_wide_cc.last_extended_seqno = statistics.seqno;
7699 transport_rtp->transport_wide_cc.last_seqno = ntohs(*seqno);
7700 } else {
7701 /* This packet was out of order, so reorder it within the vector accordingly */
7704 return;
7705 }
7706 }
7707
7708 /* If we have not yet scheduled the periodic sending of feedback for this transport then do so */
7709 if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
7710 ast_debug_rtcp(1, "(%p) RTCP starting transport-cc feedback transmission on RTP instance '%p'\n", instance, transport);
7711 ao2_ref(transport, +1);
7712 transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
7714 if (transport_rtp->transport_wide_cc.schedid < 0) {
7715 ao2_ref(transport, -1);
7716 ast_log(LOG_WARNING, "Scheduling RTCP transport-cc feedback transmission failed on RTP instance '%p'\n",
7717 transport);
7718 }
7719 }
7720}
static int rtp_transport_wide_cc_feedback_produce(const void *data)
static int rtp_transport_wide_cc_packet_statistics_cmp(struct rtp_transport_wide_cc_packet_statistics a, struct rtp_transport_wide_cc_packet_statistics b)
Packet statistics (used for transport-cc)
static void statistics(void)
Definition: utils/frame.c:287

References ao2_ref, ast_debug_rtcp, ast_log, ast_rtp_instance_get_data(), ast_sched_add(), ast_tvnow(), AST_VECTOR_ADD_SORTED, AST_VECTOR_APPEND, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_RESET, AST_VECTOR_SIZE, ast_rtp::bundled, rtp_transport_wide_cc_statistics::cycles, rtp_transport_wide_cc_statistics::last_extended_seqno, rtp_transport_wide_cc_statistics::last_seqno, LOG_WARNING, rtp_transport_wide_cc_statistics::packet_statistics, ast_rtp::rtcp, RTP_SEQ_MOD, rtp_transport_wide_cc_feedback_produce(), rtp_transport_wide_cc_packet_statistics_cmp(), ast_rtp::sched, rtp_transport_wide_cc_statistics::schedid, rtp_transport_wide_cc_packet_statistics::seqno, ast_rtp::seqno, statistics(), and ast_rtp::transport_wide_cc.

Referenced by rtp_instance_parse_extmap_extensions().

◆ rtp_instance_unlock()

static void rtp_instance_unlock ( struct ast_rtp_instance instance)
static

Definition at line 7397 of file res_rtp_asterisk.c.

7398{
7399 if (instance) {
7400 ao2_unlock(instance);
7401 }
7402}

References ao2_unlock.

Referenced by ast_rtp_read().

◆ rtp_learning_rtp_seq_update()

static int rtp_learning_rtp_seq_update ( struct rtp_learning_info info,
uint16_t  seq 
)
static

Definition at line 3611 of file res_rtp_asterisk.c.

3612{
3613 if (seq == (uint16_t) (info->max_seq + 1)) {
3614 /* packet is in sequence */
3615 info->packets--;
3616 } else {
3617 /* Sequence discontinuity; reset */
3618 info->packets = learning_min_sequential - 1;
3619 info->received = ast_tvnow();
3620 }
3621
3622 /* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */
3623 if (strictrtp == STRICT_RTP_YES) {
3624 switch (info->stream_type) {
3627 /*
3628 * Protect against packet floods by checking that we
3629 * received the packet sequence in at least the minimum
3630 * allowed time.
3631 */
3632 if (ast_tvzero(info->received)) {
3633 info->received = ast_tvnow();
3634 } else if (!info->packets
3636 /* Packet flood; reset */
3637 info->packets = learning_min_sequential - 1;
3638 info->received = ast_tvnow();
3639 }
3640 break;
3644 case AST_MEDIA_TYPE_END:
3645 break;
3646 }
3647 }
3648
3649 info->max_seq = seq;
3650
3651 return info->packets;
3652}
@ AST_MEDIA_TYPE_END
Definition: codec.h:36
def info(msg)
static int learning_min_duration

References AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_END, AST_MEDIA_TYPE_IMAGE, AST_MEDIA_TYPE_TEXT, AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), sip_to_pjsip::info(), learning_min_duration, learning_min_sequential, seq, STRICT_RTP_YES, and strictrtp.

Referenced by ast_rtp_read().

◆ rtp_learning_seq_init()

static void rtp_learning_seq_init ( struct rtp_learning_info info,
uint16_t  seq 
)
static

Definition at line 3594 of file res_rtp_asterisk.c.

3595{
3596 info->max_seq = seq;
3597 info->packets = learning_min_sequential;
3598 memset(&info->received, 0, sizeof(info->received));
3599}

References sip_to_pjsip::info(), learning_min_sequential, and seq.

Referenced by ast_rtp_read(), and rtp_learning_start().

◆ rtp_learning_start()

static void rtp_learning_start ( struct ast_rtp rtp)
static

Start the strictrtp learning mode.

Parameters
rtpRTP session description

Definition at line 3659 of file res_rtp_asterisk.c.

3660{
3662 memset(&rtp->rtp_source_learn.proposed_address, 0,
3663 sizeof(rtp->rtp_source_learn.proposed_address));
3665 rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t) rtp->lastrxseqno);
3666}

References ast_tvnow(), ast_rtp::lastrxseqno, rtp_learning_info::proposed_address, rtp_learning_seq_init(), ast_rtp::rtp_source_learn, rtp_learning_info::start, STRICT_RTP_LEARN, and ast_rtp::strict_rtp_state.

Referenced by ast_rtp_remote_address_set().

◆ rtp_raw_write()

static int rtp_raw_write ( struct ast_rtp_instance instance,
struct ast_frame frame,
int  codec 
)
static
Precondition
instance is locked

Definition at line 5156 of file res_rtp_asterisk.c.

5157{
5158 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5159 int pred, mark = 0;
5160 unsigned int ms = calc_txstamp(rtp, &frame->delivery);
5161 struct ast_sockaddr remote_address = { {0,} };
5162 int rate = ast_rtp_get_rate(frame->subclass.format) / 1000;
5163 unsigned int seqno;
5164#ifdef TEST_FRAMEWORK
5165 struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
5166#endif
5167
5169 frame->samples /= 2;
5170 }
5171
5172 if (rtp->sending_digit) {
5173 return 0;
5174 }
5175
5176#ifdef TEST_FRAMEWORK
5177 if (test && test->send_report) {
5178 test->send_report = 0;
5179 ast_rtcp_write(instance);
5180 return 0;
5181 }
5182#endif
5183
5184 if (frame->frametype == AST_FRAME_VOICE) {
5185 pred = rtp->lastts + frame->samples;
5186
5187 /* Re-calculate last TS */
5188 rtp->lastts = rtp->lastts + ms * rate;
5189 if (ast_tvzero(frame->delivery)) {
5190 /* If this isn't an absolute delivery time, Check if it is close to our prediction,
5191 and if so, go with our prediction */
5192 if (abs((int)rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
5193 rtp->lastts = pred;
5194 } else {
5195 ast_debug_rtp(3, "(%p) RTP audio difference is %d, ms is %u\n",
5196 instance, abs((int)rtp->lastts - pred), ms);
5197 mark = 1;
5198 }
5199 }
5200 } else if (frame->frametype == AST_FRAME_VIDEO) {
5201 mark = frame->subclass.frame_ending;
5202 pred = rtp->lastovidtimestamp + frame->samples;
5203 /* Re-calculate last TS */
5204 rtp->lastts = rtp->lastts + ms * 90;
5205 /* If it's close to our prediction, go for it */
5206 if (ast_tvzero(frame->delivery)) {
5207 if (abs((int)rtp->lastts - pred) < 7200) {
5208 rtp->lastts = pred;
5209 rtp->lastovidtimestamp += frame->samples;
5210 } else {
5211 ast_debug_rtp(3, "(%p) RTP video difference is %d, ms is %u (%u), pred/ts/samples %u/%d/%d\n",
5212 instance, abs((int)rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
5213 rtp->lastovidtimestamp = rtp->lastts;
5214 }
5215 }
5216 } else {
5217 pred = rtp->lastotexttimestamp + frame->samples;
5218 /* Re-calculate last TS */
5219 rtp->lastts = rtp->lastts + ms;
5220 /* If it's close to our prediction, go for it */
5221 if (ast_tvzero(frame->delivery)) {
5222 if (abs((int)rtp->lastts - pred) < 7200) {
5223 rtp->lastts = pred;
5224 rtp->lastotexttimestamp += frame->samples;
5225 } else {
5226 ast_debug_rtp(3, "(%p) RTP other difference is %d, ms is %u, pred/ts/samples %u/%d/%d\n",
5227 instance, abs((int)rtp->lastts - pred), ms, rtp->lastts, pred, frame->samples);
5228 rtp->lastotexttimestamp = rtp->lastts;
5229 }
5230 }
5231 }
5232
5233 /* If we have been explicitly told to set the marker bit then do so */
5235 mark = 1;
5237 }
5238
5239 /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
5240 if (rtp->lastts > rtp->lastdigitts) {
5241 rtp->lastdigitts = rtp->lastts;
5242 }
5243
5244 /* Assume that the sequence number we expect to use is what will be used until proven otherwise */
5245 seqno = rtp->seqno;
5246
5247 /* If the frame contains sequence number information use it to influence our sequence number */
5249 if (rtp->expectedseqno != -1) {
5250 /* Determine where the frame from the core is in relation to where we expected */
5251 int difference = frame->seqno - rtp->expectedseqno;
5252
5253 /* If there is a substantial difference then we've either got packets really out
5254 * of order, or the source is RTP and it has cycled. If this happens we resync
5255 * the sequence number adjustments to this frame. If we also have packet loss
5256 * things won't be reflected correctly but it will sort itself out after a bit.
5257 */
5258 if (abs(difference) > 100) {
5259 difference = 0;
5260 }
5261
5262 /* Adjust the sequence number being used for this packet accordingly */
5263 seqno += difference;
5264
5265 if (difference >= 0) {
5266 /* This frame is on time or in the future */
5267 rtp->expectedseqno = frame->seqno + 1;
5268 rtp->seqno += difference;
5269 }
5270 } else {
5271 /* This is the first frame with sequence number we've seen, so start keeping track */
5272 rtp->expectedseqno = frame->seqno + 1;
5273 }
5274 } else {
5275 rtp->expectedseqno = -1;
5276 }
5277
5279 rtp->lastts = frame->ts * rate;
5280 }
5281
5282 ast_rtp_instance_get_remote_address(instance, &remote_address);
5283
5284 /* If we know the remote address construct a packet and send it out */
5285 if (!ast_sockaddr_isnull(&remote_address)) {
5286 int hdrlen = 12;
5287 int res;
5288 int ice;
5289 int ext = 0;
5290 int abs_send_time_id;
5291 int packet_len;
5292 unsigned char *rtpheader;
5293
5294 /* If the abs-send-time extension has been negotiated determine how much space we need */
5296 if (abs_send_time_id != -1) {
5297 /* 4 bytes for the shared information, 1 byte for identifier, 3 bytes for abs-send-time */
5298 hdrlen += 8;
5299 ext = 1;
5300 }
5301
5302 packet_len = frame->datalen + hdrlen;
5303 rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
5304
5305 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (ext << 28) | (codec << 16) | (seqno) | (mark << 23)));
5306 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
5307 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
5308
5309 /* We assume right now that we will only ever have the abs-send-time extension in the packet
5310 * which simplifies things a bit.
5311 */
5312 if (abs_send_time_id != -1) {
5313 unsigned int now_msw;
5314 unsigned int now_lsw;
5315
5316 /* This happens before being placed into the retransmission buffer so that when we
5317 * retransmit we only have to update the timestamp, not everything else.
5318 */
5319 put_unaligned_uint32(rtpheader + 12, htonl((0xBEDE << 16) | 1));
5320 rtpheader[16] = (abs_send_time_id << 4) | 2;
5321
5322 timeval2ntp(ast_tvnow(), &now_msw, &now_lsw);
5323 put_unaligned_time24(rtpheader + 17, now_msw, now_lsw);
5324 }
5325
5326 /* If retransmissions are enabled, we need to store this packet for future use */
5327 if (rtp->send_buffer) {
5328 struct ast_rtp_rtcp_nack_payload *payload;
5329
5330 payload = ast_malloc(sizeof(*payload) + packet_len);
5331 if (payload) {
5332 payload->size = packet_len;
5333 memcpy(payload->buf, rtpheader, packet_len);
5334 if (ast_data_buffer_put(rtp->send_buffer, rtp->seqno, payload) == -1) {
5335 ast_free(payload);
5336 }
5337 }
5338 }
5339
5340 res = rtp_sendto(instance, (void *)rtpheader, packet_len, 0, &remote_address, &ice);
5341 if (res < 0) {
5343 ast_debug_rtp(1, "(%p) RTP transmission error of packet %d to %s: %s\n",
5344 instance, rtp->seqno,
5345 ast_sockaddr_stringify(&remote_address),
5346 strerror(errno));
5348 /* Only give this error message once if we are not RTP debugging */
5350 ast_debug(0, "(%p) RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
5351 instance, ast_sockaddr_stringify(&remote_address));
5353 }
5354 } else {
5355 if (rtp->rtcp && rtp->rtcp->schedid < 0) {
5356 ast_debug_rtcp(2, "(%s) RTCP starting transmission in %u ms\n",
5358 ao2_ref(instance, +1);
5360 if (rtp->rtcp->schedid < 0) {
5361 ao2_ref(instance, -1);
5362 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
5363 }
5364 }
5365 }
5366
5367 if (rtp_debug_test_addr(&remote_address)) {
5368 ast_verbose("Sent RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
5369 ast_sockaddr_stringify(&remote_address),
5370 ice ? " (via ICE)" : "",
5371 codec, rtp->seqno, rtp->lastts, res - hdrlen);
5372 }
5373 }
5374
5375 /* If the sequence number that has been used doesn't match what we expected then this is an out of
5376 * order late packet, so we don't need to increment as we haven't yet gotten the expected frame from
5377 * the core.
5378 */
5379 if (seqno == rtp->seqno) {
5380 rtp->seqno++;
5381 }
5382
5383 return 0;
5384}
#define abs(x)
Definition: f2c.h:195
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:106
#define MAX_TIMESTAMP_SKEW
unsigned int lastovidtimestamp
unsigned int lastotexttimestamp

References abs, ao2_ref, ast_clear_flag, ast_data_buffer_put(), ast_debug, ast_debug_rtcp, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_g722, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_free, AST_FRFLAG_HAS_SEQUENCE_NUMBER, AST_FRFLAG_HAS_TIMING_INFO, ast_log, ast_malloc, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_EXTENSION_ABS_SEND_TIME, ast_rtp_get_rate(), ast_rtp_instance_extmap_get_id(), ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_NAT, ast_sched_add(), ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_tvnow(), ast_tvzero(), ast_verbose(), ast_rtp_rtcp_nack_payload::buf, calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, ast_rtp::expectedseqno, ext, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_frame_subclass::format, ast_frame_subclass::frame_ending, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_WARNING, MAX_TIMESTAMP_SKEW, ast_frame::ptr, put_unaligned_time24(), put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_sendto(), ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::send_buffer, ast_rtp::sending_digit, ast_frame::seqno, ast_rtp::seqno, ast_rtp_rtcp_nack_payload::size, ast_rtp::ssrc, ast_frame::subclass, timeval2ntp(), and ast_frame::ts.

Referenced by ast_rtp_write().

◆ rtp_recvfrom()

static int rtp_recvfrom ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa 
)
static
Precondition
instance is locked

Definition at line 3439 of file res_rtp_asterisk.c.

3440{
3441 return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
3442}

References __rtp_recvfrom(), and buf.

Referenced by ast_rtp_read().

◆ rtp_red_buffer()

static int rtp_red_buffer ( struct ast_rtp_instance instance,
struct ast_frame frame 
)
static
Precondition
instance is locked

Definition at line 9193 of file res_rtp_asterisk.c.

9194{
9195 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9196 struct rtp_red *red = rtp->red;
9197
9198 if (!red) {
9199 return 0;
9200 }
9201
9202 if (frame->datalen > 0) {
9203 if (red->t140.datalen > 0) {
9204 const unsigned char *primary = red->buf_data;
9205
9206 /* There is something already in the T.140 buffer */
9207 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9208 /* Flush the previous T.140 packet if it is a command */
9209 ast_rtp_write(instance, &rtp->red->t140);
9210 } else {
9211 primary = frame->data.ptr;
9212 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9213 /* Flush the previous T.140 packet if we are buffering a command now */
9214 ast_rtp_write(instance, &rtp->red->t140);
9215 }
9216 }
9217 }
9218
9219 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
9220 red->t140.datalen += frame->datalen;
9221 red->t140.ts = frame->ts;
9222 }
9223
9224 return 0;
9225}
unsigned char buf_data[64000]

References ast_rtp_instance_get_data(), ast_rtp_write(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::ptr, ast_rtp::red, rtp_red::t140, and ast_frame::ts.

◆ rtp_red_init()

static int rtp_red_init ( struct ast_rtp_instance instance,
int  buffer_time,
int *  payloads,
int  generations 
)
static
Precondition
instance is locked

Definition at line 9161 of file res_rtp_asterisk.c.

9162{
9163 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9164 int x;
9165
9166 rtp->red = ast_calloc(1, sizeof(*rtp->red));
9167 if (!rtp->red) {
9168 return -1;
9169 }
9170
9173 rtp->red->t140.data.ptr = &rtp->red->buf_data;
9174
9175 rtp->red->t140red = rtp->red->t140;
9176 rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
9177
9178 rtp->red->num_gen = generations;
9179 rtp->red->hdrlen = generations * 4 + 1;
9180
9181 for (x = 0; x < generations; x++) {
9182 rtp->red->pt[x] = payloads[x];
9183 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
9184 rtp->red->t140red_data[x*4] = rtp->red->pt[x];
9185 }
9186 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
9187 rtp->red->schedid = ast_sched_add(rtp->sched, buffer_time, red_write, instance);
9188
9189 return 0;
9190}
static int red_write(const void *data)
Write t140 redundancy frame.
unsigned char t140red_data[64000]
unsigned char pt[AST_RED_MAX_GENERATION]

References ast_calloc, ast_format_t140_red, AST_FRAME_TEXT, ast_rtp_instance_get_data(), ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame_subclass::format, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, and rtp_red::t140red_data.

◆ rtp_reload()

static int rtp_reload ( int  reload,
int  by_external_config 
)
static

This resource is not "reloaded" so much as unloaded and loaded again. In the case of the TURN related variables, the memory referenced by a previously loaded instance should have been released when the corresponding pool was destroyed. If at some point in the future this resource were to support ACTUAL live reconfiguration and did NOT release the pool this will cause a small memory leak.

Definition at line 10022 of file res_rtp_asterisk.c.

10023{
10024 struct ast_config *cfg;
10025 const char *s;
10026 struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10027
10028#ifdef HAVE_PJPROJECT
10029 struct ast_variable *var;
10030 struct ast_ice_host_candidate *candidate;
10031 int acl_subscription_flag = 0;
10032#endif
10033
10034 cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
10035 if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
10036 return 0;
10037 }
10038
10039#ifdef SO_NO_CHECK
10040 nochecksums = 0;
10041#endif
10042
10051
10052 /** This resource is not "reloaded" so much as unloaded and loaded again.
10053 * In the case of the TURN related variables, the memory referenced by a
10054 * previously loaded instance *should* have been released when the
10055 * corresponding pool was destroyed. If at some point in the future this
10056 * resource were to support ACTUAL live reconfiguration and did NOT release
10057 * the pool this will cause a small memory leak.
10058 */
10059
10060#ifdef HAVE_PJPROJECT
10061 icesupport = DEFAULT_ICESUPPORT;
10062 stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE;
10063 turnport = DEFAULT_TURN_PORT;
10064 clean_stunaddr();
10065 turnaddr = pj_str(NULL);
10066 turnusername = pj_str(NULL);
10067 turnpassword = pj_str(NULL);
10068 host_candidate_overrides_clear();
10069#endif
10070
10071#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10072 dtls_mtu = DEFAULT_DTLS_MTU;
10073#endif
10074
10075 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
10076 rtpstart = atoi(s);
10081 }
10082 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
10083 rtpend = atoi(s);
10088 }
10089 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
10090 rtcpinterval = atoi(s);
10091 if (rtcpinterval == 0)
10092 rtcpinterval = 0; /* Just so we're clear... it's zero */
10094 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
10097 }
10098 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
10099#ifdef SO_NO_CHECK
10100 nochecksums = ast_false(s) ? 1 : 0;
10101#else
10102 if (ast_false(s))
10103 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10104#endif
10105 }
10106 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
10107 dtmftimeout = atoi(s);
10108 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
10109 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
10112 };
10113 }
10114 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
10115 if (ast_true(s)) {
10117 } else if (!strcasecmp(s, "seqno")) {
10119 } else {
10121 }
10122 }
10123 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
10124 if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
10125 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
10128 }
10130 }
10131 if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
10133 }
10134#ifdef HAVE_PJPROJECT
10135 if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
10136 icesupport = ast_true(s);
10137 }
10138 if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
10139 stun_software_attribute = ast_true(s);
10140 }
10141 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
10142 char *hostport, *host, *port;
10143 unsigned int port_parsed = STANDARD_STUN_PORT;
10144 struct ast_sockaddr stunaddr_parsed;
10145
10146 hostport = ast_strdupa(s);
10147
10148 if (!ast_parse_arg(hostport, PARSE_ADDR, &stunaddr_parsed)) {
10149 ast_debug_stun(3, "stunaddr = '%s' does not need name resolution\n",
10150 ast_sockaddr_stringify_host(&stunaddr_parsed));
10151 if (!ast_sockaddr_port(&stunaddr_parsed)) {
10152 ast_sockaddr_set_port(&stunaddr_parsed, STANDARD_STUN_PORT);
10153 }
10154 ast_rwlock_wrlock(&stunaddr_lock);
10155 ast_sockaddr_to_sin(&stunaddr_parsed, &stunaddr);
10156 ast_rwlock_unlock(&stunaddr_lock);
10157 } else if (ast_sockaddr_split_hostport(hostport, &host, &port, 0)) {
10158 if (port) {
10159 ast_parse_arg(port, PARSE_UINT32|PARSE_IN_RANGE, &port_parsed, 1, 65535);
10160 }
10161 stunaddr.sin_port = htons(port_parsed);
10162
10163 stunaddr_resolver = ast_dns_resolve_recurring(host, T_A, C_IN,
10164 &stunaddr_resolve_callback, NULL);
10165 if (!stunaddr_resolver) {
10166 ast_log(LOG_ERROR, "Failed to setup recurring DNS resolution of stunaddr '%s'",
10167 host);
10168 }
10169 } else {
10170 ast_log(LOG_ERROR, "Failed to parse stunaddr '%s'", hostport);
10171 }
10172 }
10173 if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
10174 struct sockaddr_in addr;
10175 addr.sin_port = htons(DEFAULT_TURN_PORT);
10176 if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
10177 ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
10178 } else {
10179 pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
10180 /* ntohs() is not a bug here. The port number is used in host byte order with
10181 * a pjnat API. */
10182 turnport = ntohs(addr.sin_port);
10183 }
10184 }
10185 if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
10186 pj_strdup2_with_null(pool, &turnusername, s);
10187 }
10188 if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
10189 pj_strdup2_with_null(pool, &turnpassword, s);
10190 }
10191
10192 AST_RWLIST_WRLOCK(&host_candidates);
10193 for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
10194 struct ast_sockaddr local_addr, advertised_addr;
10195 unsigned int include_local_address = 0;
10196 char *sep;
10197
10198 ast_sockaddr_setnull(&local_addr);
10199 ast_sockaddr_setnull(&advertised_addr);
10200
10201 if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
10202 ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
10203 continue;
10204 }
10205
10206 sep = strchr(var->value,',');
10207 if (sep) {
10208 *sep = '\0';
10209 sep++;
10210 sep = ast_skip_blanks(sep);
10211 include_local_address = strcmp(sep, "include_local_address") == 0;
10212 }
10213
10214 if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
10215 ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
10216 continue;
10217 }
10218
10219 if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
10220 ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
10221 break;
10222 }
10223
10224 candidate->include_local = include_local_address;
10225
10226 ast_sockaddr_copy(&candidate->local, &local_addr);
10227 ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
10228
10229 AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
10230 }
10231 AST_RWLIST_UNLOCK(&host_candidates);
10232
10233 ast_rwlock_wrlock(&ice_acl_lock);
10234 ast_rwlock_wrlock(&stun_acl_lock);
10235
10236 ice_acl = ast_free_acl_list(ice_acl);
10237 stun_acl = ast_free_acl_list(stun_acl);
10238
10239 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
10240 const char* sense = NULL;
10241 struct ast_acl_list **acl = NULL;
10242 if (strncasecmp(var->name, "ice_", 4) == 0) {
10243 sense = var->name + 4;
10244 acl = &ice_acl;
10245 } else if (strncasecmp(var->name, "stun_", 5) == 0) {
10246 sense = var->name + 5;
10247 acl = &stun_acl;
10248 } else {
10249 continue;
10250 }
10251
10252 if (strcasecmp(sense, "blacklist") == 0) {
10253 sense = "deny";
10254 }
10255
10256 if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
10257 continue;
10258 }
10259
10260 ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
10261 }
10262 ast_rwlock_unlock(&ice_acl_lock);
10263 ast_rwlock_unlock(&stun_acl_lock);
10264
10265 if (acl_subscription_flag && !acl_change_sub) {
10269 } else if (!acl_subscription_flag && acl_change_sub) {
10271 }
10272#endif
10273#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10274 if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
10275 if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
10276 ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
10278 dtls_mtu = DEFAULT_DTLS_MTU;
10279 }
10280 }
10281#endif
10282
10283 ast_config_destroy(cfg);
10284
10285 /* Choosing an odd start port casues issues (like a potential infinite loop) and as odd parts are not
10286 chosen anyway, we are going to round up and issue a warning */
10287 if (rtpstart & 1) {
10288 rtpstart++;
10289 ast_log(LOG_WARNING, "Odd start value for RTP port in rtp.conf, rounding up to %d\n", rtpstart);
10290 }
10291
10292 if (rtpstart >= rtpend) {
10293 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
10296 }
10297 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
10298 return 0;
10299}
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
Definition: acl.c:429
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition: acl.c:233
#define var
Definition: ast_expr2f.c:605
static struct stasis_subscription * acl_change_sub
Definition: chan_iax2.c:352
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: chan_iax2.c:1584
struct ast_dns_query_recurring * ast_dns_resolve_recurring(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query, and continue resolving it according to the lowest TTL available.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3541
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:4059
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:869
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#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_INSERT_TAIL
Definition: linkedlists.h:741
#define ast_rwlock_wrlock(a)
Definition: lock.h:243
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:327
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:138
static int reload(void)
#define DEFAULT_ICESUPPORT
#define DEFAULT_LEARNING_MIN_SEQUENTIAL
#define DEFAULT_RTP_END
#define RTCP_DEFAULT_INTERVALMS
#define DEFAULT_DTMF_TIMEOUT
#define RTCP_MAX_INTERVALMS
#define DEFAULT_SRTP_REPLAY_PROTECTION
#define DEFAULT_DTLS_MTU
#define DEFAULT_RTP_START
#define MINIMUM_RTP_PORT
#define RTCP_MIN_INTERVALMS
#define CALC_LEARNING_MIN_DURATION(count)
Calculate the min learning duration in ms.
#define MAXIMUM_RTP_PORT
#define DEFAULT_STRICT_RTP
#define DEFAULT_TURN_PORT
#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE
#define DEFAULT_LEARNING_MIN_DURATION
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1050
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1104
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1161
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649
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:2235
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2252
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Definition: test_acl.c:111
Wrapper for an ast_acl linked list.
Definition: acl.h:76
Structure used to handle boolean flags.
Definition: utils.h:217
Structure for variables, used for configurations and for channel variables.
static const int STANDARD_STUN_PORT
Definition: stun.h:61

References acl_change_stasis_cb(), acl_change_sub, ast_append_acl(), ast_calloc, ast_config_destroy(), ast_config_load2(), ast_debug_stun, ast_dns_resolve_recurring(), ast_false(), ast_free_acl_list(), ast_inet_ntoa(), ast_log, ast_named_acl_change_type(), ast_parse_arg(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rwlock_unlock, ast_rwlock_wrlock, ast_security_topic(), ast_skip_blanks(), ast_sockaddr_copy(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_setnull(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify_host(), ast_sockaddr_to_sin, ast_strdupa, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CALC_LEARNING_MIN_DURATION, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTLS_MTU, DEFAULT_DTMF_TIMEOUT, DEFAULT_ICESUPPORT, DEFAULT_LEARNING_MIN_DURATION, DEFAULT_LEARNING_MIN_SEQUENTIAL, DEFAULT_RTP_END, DEFAULT_RTP_START, DEFAULT_SRTP_REPLAY_PROTECTION, DEFAULT_STRICT_RTP, DEFAULT_STUN_SOFTWARE_ATTRIBUTE, DEFAULT_TURN_PORT, dtmftimeout, learning_min_duration, learning_min_sequential, LOG_ERROR, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, NULL, PARSE_ADDR, PARSE_IN_RANGE, PARSE_INADDR, PARSE_PORT_IGNORE, PARSE_UINT32, reload(), RTCP_DEFAULT_INTERVALMS, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, srtp_replay_protection, STANDARD_STUN_PORT, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), stasis_unsubscribe_and_join(), STRICT_RTP_NO, STRICT_RTP_SEQNO, STRICT_RTP_YES, strictrtp, and var.

Referenced by load_module(), and reload_module().

◆ rtp_sendto()

static int rtp_sendto ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa,
int *  ice 
)
static
Precondition
instance is locked

Definition at line 3517 of file res_rtp_asterisk.c.

3518{
3519 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3520 int hdrlen = 12;
3521 int res;
3522
3523 if ((res = __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1)) > 0) {
3524 rtp->txcount++;
3525 rtp->txoctetcount += (res - hdrlen);
3526 }
3527
3528 return res;
3529}

References __rtp_sendto(), ast_rtp_instance_get_data(), buf, ast_rtp::flags, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), ast_rtp_rtcp_handle_nack(), ast_rtp_sendcng(), bridge_p2p_rtp_write(), and rtp_raw_write().

◆ rtp_transport_wide_cc_feedback_produce()

static int rtp_transport_wide_cc_feedback_produce ( const void *  data)
static

Definition at line 7480 of file res_rtp_asterisk.c.

7481{
7482 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
7483 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7484 unsigned char *rtcpheader;
7485 char bdata[1024];
7486 struct rtp_transport_wide_cc_packet_statistics *first_packet;
7487 struct rtp_transport_wide_cc_packet_statistics *previous_packet;
7488 int i;
7489 int status_vector_chunk_bits = 14;
7490 uint16_t status_vector_chunk = (1 << 15) | (1 << 14);
7491 int run_length_chunk_count = 0;
7492 int run_length_chunk_status = -1;
7493 int packet_len = 20;
7494 int delta_len = 0;
7495 int packet_count = 0;
7496 unsigned int received_msw;
7497 unsigned int received_lsw;
7498 struct ast_sockaddr remote_address = { { 0, } };
7499 int res;
7500 int ice;
7501 unsigned int large_delta_count = 0;
7502 unsigned int small_delta_count = 0;
7503 unsigned int lost_count = 0;
7504
7505 if (!rtp || !rtp->rtcp || rtp->transport_wide_cc.schedid == -1) {
7506 ao2_ref(instance, -1);
7507 return 0;
7508 }
7509
7510 ao2_lock(instance);
7511
7512 /* If no packets have been received then do nothing */
7514 ao2_unlock(instance);
7515 return 1000;
7516 }
7517
7518 rtcpheader = (unsigned char *)bdata;
7519
7520 /* The first packet in the vector acts as our base sequence number and reference time */
7522 previous_packet = first_packet;
7523
7524 /* We go through each packet that we have statistics for, adding it either to a status
7525 * vector chunk or a run length chunk. The code tries to be as efficient as possible to
7526 * reduce packet size and will favor run length chunks when it makes sense.
7527 */
7528 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7530 int lost = 0;
7531 int res = 0;
7532
7534
7535 packet_count++;
7536
7537 if (first_packet != statistics) {
7538 /* The vector stores statistics in a sorted fashion based on the sequence
7539 * number. This ensures we can detect any packets that have been lost/not
7540 * received by comparing the sequence numbers.
7541 */
7542 lost = statistics->seqno - (previous_packet->seqno + 1);
7543 lost_count += lost;
7544 }
7545
7546 while (lost) {
7547 /* We append a not received status until all the lost packets have been accounted for */
7548 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7549 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 0);
7550 packet_count++;
7551
7552 /* If there is no more room left for storing packets stop now, we leave 20
7553 * extra bits at the end just in case.
7554 */
7555 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7556 res = -1;
7557 break;
7558 }
7559
7560 lost--;
7561 }
7562
7563 /* If the lost packet appending bailed out because we have no more space, then exit here too */
7564 if (res) {
7565 break;
7566 }
7567
7568 /* Per the spec the delta is in increments of 250 */
7569 statistics->delta = ast_tvdiff_us(statistics->received, previous_packet->received) / 250;
7570
7571 /* Based on the delta determine the status of this packet */
7572 if (statistics->delta < 0 || statistics->delta > 127) {
7573 /* Large or negative delta */
7574 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7575 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 2);
7576 delta_len += 2;
7577 large_delta_count++;
7578 } else {
7579 /* Small delta */
7580 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7581 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 1);
7582 delta_len += 1;
7583 small_delta_count++;
7584 }
7585
7586 previous_packet = statistics;
7587
7588 /* If there is no more room left in the packet stop handling of any subsequent packets */
7589 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7590 break;
7591 }
7592 }
7593
7594 if (status_vector_chunk_bits != 14) {
7595 /* If the status vector chunk has packets in it then place it in the RTCP packet */
7596 put_unaligned_uint16(rtcpheader + packet_len, htons(status_vector_chunk));
7597 packet_len += 2;
7598 } else if (run_length_chunk_count) {
7599 /* If there is a run length chunk in progress then place it in the RTCP packet */
7600 put_unaligned_uint16(rtcpheader + packet_len, htons((0 << 15) | (run_length_chunk_status << 13) | run_length_chunk_count));
7601 packet_len += 2;
7602 }
7603
7604 /* We iterate again to build delta chunks */
7605 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7607
7609
7610 if (statistics->delta < 0 || statistics->delta > 127) {
7611 /* We need 2 bytes to store this delta */
7612 put_unaligned_uint16(rtcpheader + packet_len, htons(statistics->delta));
7613 packet_len += 2;
7614 } else {
7615 /* We can store this delta in 1 byte */
7616 rtcpheader[packet_len] = statistics->delta;
7617 packet_len += 1;
7618 }
7619
7620 /* If this is the last packet handled by the run length chunk or status vector chunk code
7621 * then we can go no further.
7622 */
7623 if (statistics == previous_packet) {
7624 break;
7625 }
7626 }
7627
7628 /* Zero pad the end of the packet */
7629 while (packet_len % 4) {
7630 rtcpheader[packet_len++] = 0;
7631 }
7632
7633 /* Add the general RTCP header information */
7634 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC << 24)
7635 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
7636 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
7637 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
7638
7639 /* Add the transport-cc specific header information */
7640 put_unaligned_uint32(rtcpheader + 12, htonl((first_packet->seqno << 16) | packet_count));
7641
7642 timeval2ntp(first_packet->received, &received_msw, &received_lsw);
7643 put_unaligned_time24(rtcpheader + 16, received_msw, received_lsw);
7644 rtcpheader[19] = rtp->transport_wide_cc.feedback_count;
7645
7646 /* The packet is now fully constructed so send it out */
7647 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
7648
7649 ast_debug_rtcp(2, "(%p) RTCP sending transport-cc feedback packet of size '%d' on '%s' with packet count of %d (small = %d, large = %d, lost = %d)\n",
7650 instance, packet_len, ast_rtp_instance_get_channel_id(instance), packet_count, small_delta_count, large_delta_count, lost_count);
7651
7652 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
7653 if (res < 0) {
7654 ast_log(LOG_ERROR, "RTCP transport-cc feedback error to %s due to %s\n",
7655 ast_sockaddr_stringify(&remote_address), strerror(errno));
7656 }
7657
7659
7661
7662 ao2_unlock(instance);
7663
7664 return 1000;
7665}
static void rtp_transport_wide_cc_feedback_status_append(unsigned char *rtcpheader, int *packet_len, int *status_vector_chunk_bits, uint16_t *status_vector_chunk, int *run_length_chunk_count, int *run_length_chunk_status, int status)
#define AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC
Definition: rtp_engine.h:341
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:87
static void put_unaligned_uint16(void *p, unsigned short datum)
Definition: unaligned.h:65

References ao2_lock, ao2_ref, ao2_unlock, ast_debug_rtcp, ast_log, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC, AST_RTP_RTCP_RTPFB, ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_tvdiff_us(), AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_GET_ADDR, AST_VECTOR_RESET, AST_VECTOR_SIZE, ast_rtp_instance::data, errno, rtp_transport_wide_cc_statistics::feedback_count, LOG_ERROR, rtp_transport_wide_cc_statistics::packet_statistics, put_unaligned_time24(), put_unaligned_uint16(), put_unaligned_uint32(), rtp_transport_wide_cc_packet_statistics::received, ast_rtp::rtcp, rtcp_sendto(), rtp_transport_wide_cc_feedback_status_append(), rtp_transport_wide_cc_statistics::schedid, rtp_transport_wide_cc_packet_statistics::seqno, ast_rtp::ssrc, statistics(), ast_rtcp::them, ast_rtp::themssrc, timeval2ntp(), and ast_rtp::transport_wide_cc.

Referenced by rtp_instance_parse_transport_wide_cc().

◆ rtp_transport_wide_cc_feedback_status_append()

static void rtp_transport_wide_cc_feedback_status_append ( unsigned char *  rtcpheader,
int *  packet_len,
int *  status_vector_chunk_bits,
uint16_t *  status_vector_chunk,
int *  run_length_chunk_count,
int *  run_length_chunk_status,
int  status 
)
static

Definition at line 7439 of file res_rtp_asterisk.c.

7441{
7442 if (*run_length_chunk_status != status) {
7443 while (*run_length_chunk_count > 0 && *run_length_chunk_count < 8) {
7444 /* Realistically it only makes sense to use a run length chunk if there were 8 or more
7445 * consecutive packets of the same type, otherwise we could end up making the packet larger
7446 * if we have lots of small blocks of the same type. To help with this we backfill the status
7447 * vector (since it always represents 7 packets). Best case we end up with only that single
7448 * status vector and the rest are run length chunks.
7449 */
7450 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7451 status_vector_chunk, *run_length_chunk_status);
7452 *run_length_chunk_count -= 1;
7453 }
7454
7455 if (*run_length_chunk_count) {
7456 /* There is a run length chunk which needs to be written out */
7457 put_unaligned_uint16(rtcpheader + *packet_len, htons((0 << 15) | (*run_length_chunk_status << 13) | *run_length_chunk_count));
7458 *packet_len += 2;
7459 }
7460
7461 /* In all cases the run length chunk has to be reset */
7462 *run_length_chunk_count = 0;
7463 *run_length_chunk_status = -1;
7464
7465 if (*status_vector_chunk_bits == 14) {
7466 /* We aren't in the middle of a status vector so we can try for a run length chunk */
7467 *run_length_chunk_status = status;
7468 *run_length_chunk_count = 1;
7469 } else {
7470 /* We're doing a status vector so populate it accordingly */
7471 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7472 status_vector_chunk, status);
7473 }
7474 } else {
7475 /* This is easy, the run length chunk count can just get bumped up */
7476 *run_length_chunk_count += 1;
7477 }
7478}
static void rtp_transport_wide_cc_feedback_status_vector_append(unsigned char *rtcpheader, int *packet_len, int *status_vector_chunk_bits, uint16_t *status_vector_chunk, int status)

References put_unaligned_uint16(), rtp_transport_wide_cc_feedback_status_vector_append(), and status.

Referenced by rtp_transport_wide_cc_feedback_produce().

◆ rtp_transport_wide_cc_feedback_status_vector_append()

static void rtp_transport_wide_cc_feedback_status_vector_append ( unsigned char *  rtcpheader,
int *  packet_len,
int *  status_vector_chunk_bits,
uint16_t *  status_vector_chunk,
int  status 
)
static

Definition at line 7410 of file res_rtp_asterisk.c.

7412{
7413 /* Appending this status will use up 2 bits */
7414 *status_vector_chunk_bits -= 2;
7415
7416 /* We calculate which bits we want to update the status of. Since a status vector
7417 * is 16 bits we take away 2 (for the header), and then we take away any that have
7418 * already been used.
7419 */
7420 *status_vector_chunk |= (status << (16 - 2 - (14 - *status_vector_chunk_bits)));
7421
7422 /* If there are still bits available we can return early */
7423 if (*status_vector_chunk_bits) {
7424 return;
7425 }
7426
7427 /* Otherwise we have to place this chunk into the packet */
7428 put_unaligned_uint16(rtcpheader + *packet_len, htons(*status_vector_chunk));
7429 *status_vector_chunk_bits = 14;
7430
7431 /* The first bit being 1 indicates that this is a status vector chunk and the second
7432 * bit being 1 indicates that we are using 2 bits to represent each status for a
7433 * packet.
7434 */
7435 *status_vector_chunk = (1 << 15) | (1 << 14);
7436 *packet_len += 2;
7437}

References put_unaligned_uint16(), and status.

Referenced by rtp_transport_wide_cc_feedback_status_append().

◆ rtp_transport_wide_cc_packet_statistics_cmp()

static int rtp_transport_wide_cc_packet_statistics_cmp ( struct rtp_transport_wide_cc_packet_statistics  a,
struct rtp_transport_wide_cc_packet_statistics  b 
)
static

Definition at line 7404 of file res_rtp_asterisk.c.

7406{
7407 return a.seqno - b.seqno;
7408}
static struct test_val b

References a, and b.

Referenced by rtp_instance_parse_transport_wide_cc().

◆ rtp_write_rtcp_fir()

static void rtp_write_rtcp_fir ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
struct ast_sockaddr remote_address 
)
static

Definition at line 5426 of file res_rtp_asterisk.c.

5427{
5428 unsigned char *rtcpheader;
5429 unsigned char bdata[1024];
5430 int packet_len = 0;
5431 int fir_len = 20;
5432 int ice;
5433 int res;
5434 int sr;
5435 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5436
5437 if (!rtp || !rtp->rtcp) {
5438 return;
5439 }
5440
5441 if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5442 /*
5443 * RTCP was stopped.
5444 */
5445 return;
5446 }
5447
5448 if (!rtp->themssrc_valid) {
5449 /* We don't know their SSRC value so we don't know who to update. */
5450 return;
5451 }
5452
5453 /* Prepare RTCP FIR (PT=206, FMT=4) */
5454 rtp->rtcp->firseq++;
5455 if(rtp->rtcp->firseq == 256) {
5456 rtp->rtcp->firseq = 0;
5457 }
5458
5459 rtcpheader = bdata;
5460
5461 ao2_lock(instance);
5462 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5463 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5464
5465 if (res == 0 || res == 1) {
5466 ao2_unlock(instance);
5467 return;
5468 }
5469
5470 packet_len += res;
5471
5472 put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((fir_len/4)-1)));
5473 put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5474 put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(rtp->themssrc));
5475 put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(rtp->themssrc)); /* FCI: SSRC */
5476 put_unaligned_uint32(rtcpheader + packet_len + 16, htonl(rtp->rtcp->firseq << 24)); /* FCI: Sequence number */
5477 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + fir_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5478 if (res < 0) {
5479 ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
5480 } else {
5481 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5482 }
5483
5484 ao2_unlock(instance);
5485}

References ao2_cleanup, ao2_lock, ao2_unlock, ast_log, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtp_rtcp_report_alloc(), ast_sockaddr_isnull(), ast_rtp::bundled, errno, ast_rtcp::firseq, LOG_ERROR, NULL, put_unaligned_uint32(), RAII_VAR, ast_rtp::rtcp, RTCP_PT_PSFB, rtcp_sendto(), ast_rtcp::schedid, ast_rtp::ssrc, ast_rtcp::them, ast_rtp::themssrc, and ast_rtp::themssrc_valid.

Referenced by ast_rtp_read(), and ast_rtp_write().

◆ rtp_write_rtcp_psfb()

static void rtp_write_rtcp_psfb ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
struct ast_frame frame,
struct ast_sockaddr remote_address 
)
static

Definition at line 5487 of file res_rtp_asterisk.c.

5488{
5489 struct ast_rtp_rtcp_feedback *feedback = frame->data.ptr;
5490 unsigned char *rtcpheader;
5491 unsigned char bdata[1024];
5492 int remb_len = 24;
5493 int ice;
5494 int res;
5495 int sr = 0;
5496 int packet_len = 0;
5497 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5498
5499 if (feedback->fmt != AST_RTP_RTCP_FMT_REMB) {
5500 ast_debug_rtcp(1, "(%p) RTCP provided feedback frame of format %d to write, but only REMB is supported\n",
5501 instance, feedback->fmt);
5502 return;
5503 }
5504
5505 if (!rtp || !rtp->rtcp) {
5506 return;
5507 }
5508
5509 /* If REMB support is not enabled don't send this RTCP packet */
5511 ast_debug_rtcp(1, "(%p) RTCP provided feedback REMB report to write, but REMB support not enabled\n",
5512 instance);
5513 return;
5514 }
5515
5516 if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5517 /*
5518 * RTCP was stopped.
5519 */
5520 return;
5521 }
5522
5523 rtcpheader = bdata;
5524
5525 ao2_lock(instance);
5526 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5527 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5528
5529 if (res == 0 || res == 1) {
5530 ao2_unlock(instance);
5531 return;
5532 }
5533
5534 packet_len += res;
5535
5536 put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (AST_RTP_RTCP_FMT_REMB << 24) | (RTCP_PT_PSFB << 16) | ((remb_len/4)-1)));
5537 put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5538 put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(0)); /* Per the draft, this should always be 0 */
5539 put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(('R' << 24) | ('E' << 16) | ('M' << 8) | ('B'))); /* Unique identifier 'R' 'E' 'M' 'B' */
5540 put_unaligned_uint32(rtcpheader + packet_len + 16, htonl((1 << 24) | (feedback->remb.br_exp << 18) | (feedback->remb.br_mantissa))); /* Number of SSRCs / BR Exp / BR Mantissa */
5541 put_unaligned_uint32(rtcpheader + packet_len + 20, htonl(rtp->ssrc)); /* The SSRC this feedback message applies to */
5542 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + remb_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5543 if (res < 0) {
5544 ast_log(LOG_ERROR, "RTCP PSFB transmission error: %s\n", strerror(errno));
5545 } else {
5546 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5547 }
5548
5549 ao2_unlock(instance);
5550}

References ao2_cleanup, ao2_lock, ao2_unlock, ast_debug_rtcp, ast_log, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_REMB, AST_RTP_RTCP_FMT_REMB, ast_rtp_rtcp_report_alloc(), ast_sockaddr_isnull(), ast_rtp_rtcp_feedback_remb::br_exp, ast_rtp_rtcp_feedback_remb::br_mantissa, ast_rtp::bundled, ast_frame::data, errno, ast_rtp_rtcp_feedback::fmt, LOG_ERROR, NULL, ast_frame::ptr, put_unaligned_uint32(), RAII_VAR, ast_rtp_rtcp_feedback::remb, ast_rtp::rtcp, RTCP_PT_PSFB, rtcp_sendto(), ast_rtcp::schedid, ast_rtp::ssrc, ast_rtcp::them, and ast_rtp::themssrc_valid.

Referenced by ast_rtp_write().

◆ timeval2ntp()

static void timeval2ntp ( struct timeval  tv,
unsigned int *  msw,
unsigned int *  lsw 
)
static

Definition at line 4650 of file res_rtp_asterisk.c.

4651{
4652 unsigned int sec, usec, frac;
4653 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
4654 usec = tv.tv_usec;
4655 /*
4656 * Convert usec to 0.32 bit fixed point without overflow.
4657 *
4658 * = usec * 2^32 / 10^6
4659 * = usec * 2^32 / (2^6 * 5^6)
4660 * = usec * 2^26 / 5^6
4661 *
4662 * The usec value needs 20 bits to represent 999999 usec. So
4663 * splitting the 2^26 to get the most precision using 32 bit
4664 * values gives:
4665 *
4666 * = ((usec * 2^12) / 5^6) * 2^14
4667 *
4668 * Splitting the division into two stages preserves all the
4669 * available significant bits of usec over doing the division
4670 * all at once.
4671 *
4672 * = ((((usec * 2^12) / 5^3) * 2^7) / 5^3) * 2^7
4673 */
4674 frac = ((((usec << 12) / 125) << 7) / 125) << 7;
4675 *msw = sec;
4676 *lsw = frac;
4677}

Referenced by ast_rtcp_generate_report(), ast_rtcp_interpret(), ast_rtp_rtcp_handle_nack(), rtp_raw_write(), rtp_transport_wide_cc_feedback_produce(), and update_rtt_stats().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 10418 of file res_rtp_asterisk.c.

10419{
10422
10423#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10424 if (dtls_bio_methods) {
10425 BIO_meth_free(dtls_bio_methods);
10426 }
10427#endif
10428
10429#ifdef HAVE_PJPROJECT
10430 host_candidate_overrides_clear();
10431 pj_thread_register_check();
10432 rtp_terminate_pjproject();
10433
10435 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10436 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10437 clean_stunaddr();
10438#endif
10439
10440 return 0;
10441}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30

References acl_change_sub, ARRAY_LEN, ast_cli_unregister_multiple(), ast_rtp_engine_unregister(), asterisk_rtp_engine, cli_rtp, and stasis_unsubscribe_and_join().

◆ update_jitter_stats()

static void update_jitter_stats ( struct ast_rtp rtp,
unsigned int  ia_jitter 
)
static

◆ update_local_mes_stats()

static void update_local_mes_stats ( struct ast_rtp rtp)
static

Definition at line 6403 of file res_rtp_asterisk.c.

6404{
6406 rtp->rtcp->normdevrtt,
6407 rtp->rxjitter,
6408 rtp->rtcp->stdev_rxjitter,
6409 rtp->rtcp->normdev_rxlost);
6410
6411 if (rtp->rtcp->rxmes_count == 0) {
6412 rtp->rtcp->minrxmes = rtp->rxmes;
6413 }
6414 if (rtp->rxmes < rtp->rtcp->minrxmes) {
6415 rtp->rtcp->minrxmes = rtp->rxmes;
6416 }
6417 if (rtp->rxmes > rtp->rtcp->maxrxmes) {
6418 rtp->rtcp->maxrxmes = rtp->rxmes;
6419 }
6420
6422 &rtp->rtcp->stdev_rxmes, &rtp->rtcp->rxmes_count);
6423
6424 ast_debug_rtcp(2, " %s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6426 rtp->rtcp->normdevrtt,
6427 rtp->rxjitter,
6428 rtp->rtcp->stdev_rxjitter,
6429 rtp->rtcp->normdev_rxlost, rtp->rxmes);
6430}
static double calc_media_experience_score(struct ast_rtp_instance *instance, double normdevrtt, double normdev_rxjitter, double stdev_rxjitter, double normdev_rxlost)
Calculate a "media experience score" based on given data.
unsigned int rxmes_count
double stdev_rxmes

References ast_debug_rtcp, ast_rtp_instance_get_channel_id(), calc_mean_and_standard_deviation(), calc_media_experience_score(), ast_rtcp::maxrxmes, ast_rtcp::minrxmes, ast_rtcp::normdev_rxlost, ast_rtcp::normdev_rxmes, ast_rtcp::normdevrtt, ast_rtp::owner, ast_rtp::rtcp, ast_rtp::rxjitter, ast_rtp::rxmes, ast_rtcp::rxmes_count, ast_rtcp::stdev_rxjitter, and ast_rtcp::stdev_rxmes.

Referenced by ast_rtcp_generate_report().

◆ update_lost_stats()

static void update_lost_stats ( struct ast_rtp rtp,
unsigned int  lost_packets 
)
static

Definition at line 6259 of file res_rtp_asterisk.c.

6260{
6261 double reported_lost;
6262
6263 rtp->rtcp->reported_lost = lost_packets;
6264 reported_lost = (double)rtp->rtcp->reported_lost;
6265 if (rtp->rtcp->reported_lost_count == 0) {
6266 rtp->rtcp->reported_minlost = reported_lost;
6267 }
6268 if (reported_lost < rtp->rtcp->reported_minlost) {
6269 rtp->rtcp->reported_minlost = reported_lost;
6270 }
6271 if (reported_lost > rtp->rtcp->reported_maxlost) {
6272 rtp->rtcp->reported_maxlost = reported_lost;
6273 }
6274
6277}
unsigned int reported_lost_count

References calc_mean_and_standard_deviation(), if(), ast_rtcp::reported_lost, ast_rtcp::reported_lost_count, ast_rtcp::reported_maxlost, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_lost, and ast_rtp::rtcp.

Referenced by ast_rtcp_interpret().

◆ update_reported_mes_stats()

static void update_reported_mes_stats ( struct ast_rtp rtp)
static

Definition at line 6368 of file res_rtp_asterisk.c.

6369{
6370 double mes = calc_media_experience_score(rtp->owner,
6371 rtp->rtcp->normdevrtt,
6372 rtp->rtcp->reported_jitter,
6375
6376 rtp->rtcp->reported_mes = mes;
6377 if (rtp->rtcp->reported_mes_count == 0) {
6378 rtp->rtcp->reported_minmes = mes;
6379 }
6380 if (mes < rtp->rtcp->reported_minmes) {
6381 rtp->rtcp->reported_minmes = mes;
6382 }
6383 if (mes > rtp->rtcp->reported_maxmes) {
6384 rtp->rtcp->reported_maxmes = mes;
6385 }
6386
6389
6390 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6392 rtp->rtcp->normdevrtt,
6393 rtp->rtcp->reported_jitter,
6395 rtp->rtcp->reported_normdev_lost, mes);
6396}
unsigned int reported_mes_count

References ast_debug_rtcp, ast_rtp_instance_get_channel_id(), calc_mean_and_standard_deviation(), calc_media_experience_score(), ast_rtcp::normdevrtt, ast_rtp::owner, ast_rtcp::reported_jitter, ast_rtcp::reported_maxmes, ast_rtcp::reported_mes, ast_rtcp::reported_mes_count, ast_rtcp::reported_minmes, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_normdev_mes, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_mes, and ast_rtp::rtcp.

Referenced by ast_rtcp_interpret().

◆ update_rtt_stats()

static int update_rtt_stats ( struct ast_rtp rtp,
unsigned int  lsr,
unsigned int  dlsr 
)
static

Definition at line 6178 of file res_rtp_asterisk.c.

6179{
6180 struct timeval now;
6181 struct timeval rtt_tv;
6182 unsigned int msw;
6183 unsigned int lsw;
6184 unsigned int rtt_msw;
6185 unsigned int rtt_lsw;
6186 unsigned int lsr_a;
6187 unsigned int rtt;
6188
6189 gettimeofday(&now, NULL);
6190 timeval2ntp(now, &msw, &lsw);
6191
6192 lsr_a = ((msw & 0x0000ffff) << 16) | ((lsw & 0xffff0000) >> 16);
6193 rtt = lsr_a - lsr - dlsr;
6194 rtt_msw = (rtt & 0xffff0000) >> 16;
6195 rtt_lsw = (rtt & 0x0000ffff);
6196 rtt_tv.tv_sec = rtt_msw;
6197 /*
6198 * Convert 16.16 fixed point rtt_lsw to usec without
6199 * overflow.
6200 *
6201 * = rtt_lsw * 10^6 / 2^16
6202 * = rtt_lsw * (2^6 * 5^6) / 2^16
6203 * = rtt_lsw * 5^6 / 2^10
6204 *
6205 * The rtt_lsw value is in 16.16 fixed point format and 5^6
6206 * requires 14 bits to represent. We have enough space to
6207 * directly do the conversion because there is no integer
6208 * component in rtt_lsw.
6209 */
6210 rtt_tv.tv_usec = (rtt_lsw * 15625) >> 10;
6211 rtp->rtcp->rtt = (double)rtt_tv.tv_sec + ((double)rtt_tv.tv_usec / 1000000);
6212 if (lsr_a - dlsr < lsr) {
6213 return 1;
6214 }
6215
6216 rtp->rtcp->accumulated_transit += rtp->rtcp->rtt;
6217 if (rtp->rtcp->rtt_count == 0 || rtp->rtcp->minrtt > rtp->rtcp->rtt) {
6218 rtp->rtcp->minrtt = rtp->rtcp->rtt;
6219 }
6220 if (rtp->rtcp->maxrtt < rtp->rtcp->rtt) {
6221 rtp->rtcp->maxrtt = rtp->rtcp->rtt;
6222 }
6223
6225 &rtp->rtcp->stdevrtt, &rtp->rtcp->rtt_count);
6226
6227 return 0;
6228}
double accumulated_transit
unsigned int rtt_count

References ast_rtcp::accumulated_transit, calc_mean_and_standard_deviation(), ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtcp::normdevrtt, NULL, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::stdevrtt, and timeval2ntp().

Referenced by ast_rtcp_interpret().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, #ifdef HAVE_PJPROJECT .requires = "res_pjproject", #endif }
static

Definition at line 10452 of file res_rtp_asterisk.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 10452 of file res_rtp_asterisk.c.

◆ asterisk_rtp_engine

struct ast_rtp_engine asterisk_rtp_engine
static

Definition at line 2568 of file res_rtp_asterisk.c.

Referenced by load_module(), and unload_module().

◆ cli_rtp

struct ast_cli_entry cli_rtp[]
static

Definition at line 10012 of file res_rtp_asterisk.c.

Referenced by load_module(), and unload_module().

◆ dtmftimeout

int dtmftimeout = DEFAULT_DTMF_TIMEOUT
static

Definition at line 208 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), process_dtmf_rfc2833(), and rtp_reload().

◆ learning_min_duration

int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION
static

Lowest acceptable timeout between the first and the last sequential RTP frame.

Definition at line 223 of file res_rtp_asterisk.c.

Referenced by rtp_learning_rtp_seq_update(), and rtp_reload().

◆ learning_min_sequential

int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL
static

Number of sequential RTP frames needed from a single source during learning mode to accept new source.

Definition at line 222 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), rtp_learning_rtp_seq_update(), rtp_learning_seq_init(), and rtp_reload().

◆ res_srtp

struct ast_srtp_res* res_srtp
extern

◆ res_srtp_policy

struct ast_srtp_policy_res* res_srtp_policy
extern

◆ rtcpdebugaddr

struct ast_sockaddr rtcpdebugaddr
static

Debug RTCP packets to/from this host

Definition at line 215 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_debug(), rtcp_debug_test_addr(), and rtcp_do_debug_ip().

◆ rtcpdebugport

int rtcpdebugport
static

Debug only RTCP packets from IP or IP+Port if port is > 0

Definition at line 217 of file res_rtp_asterisk.c.

Referenced by rtcp_debug_test_addr(), and rtcp_do_debug_ip().

◆ rtcpinterval

int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static

Time between rtcp reports in millisecs

Definition at line 213 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_calc_interval(), and rtp_reload().

◆ rtcpstats

int rtcpstats
static

Are we debugging RTCP?

Definition at line 212 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_stats().

◆ rtpdebugaddr

struct ast_sockaddr rtpdebugaddr
static

Debug packets to/from this host

Definition at line 214 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_set_debug(), rtp_debug_test_addr(), and rtp_do_debug_ip().

◆ rtpdebugport

int rtpdebugport
static

Debug only RTP packets from IP or IP+Port if port is > 0

Definition at line 216 of file res_rtp_asterisk.c.

Referenced by rtp_debug_test_addr(), and rtp_do_debug_ip().

◆ rtpend

int rtpend = DEFAULT_RTP_END
static

Last port for RTP sessions (set in rtp.conf)

Definition at line 211 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), rtp_allocate_transport(), and rtp_reload().

◆ rtpstart

int rtpstart = DEFAULT_RTP_START
static

First port for RTP sessions (set in rtp.conf)

Definition at line 210 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), rtp_allocate_transport(), and rtp_reload().

◆ srtp_replay_protection

int srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION
static

◆ strictrtp

int strictrtp = DEFAULT_STRICT_RTP
static

Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode.

Definition at line 221 of file res_rtp_asterisk.c.

Referenced by ast_rtp_remote_address_set(), handle_cli_rtp_settings(), rtp_allocate_transport(), rtp_learning_rtp_seq_update(), and rtp_reload().