Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
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.
 
#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()
 
#define STRICT_RTP_LEARN_TIMEOUT   5000
 Strict RTP learning timeout time in milliseconds.
 
#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_module * AST_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_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 struct ast_frame * ast_rtcp_read (struct ast_rtp_instance *instance)
 
static int ast_rtcp_write (const void *data)
 Write a RTCP packet to the far end.
 
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_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 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_frame * ast_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_rtcp_handle_nack_locking (struct ast_rtp_instance *instance, struct ast_rtp_instance *transport, 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)
 
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.
 
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.
 
static struct ast_frame * create_dtmf_frame (struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
 
static int create_new_socket (const char *type, struct ast_sockaddr *bind_addr)
 
static int find_by_value (int elem, int value)
 Helper function to find an elem in a vector by value.
 
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_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 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 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_frame * red_t140_to_red (struct rtp_red *red)
 
static int red_write (const void *data)
 Write t140 redundancy frame.
 
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_instance * rtp_find_instance_by_media_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int 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 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.
 
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 = ASTERISK_GPL_KEY , .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_info * ast_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_res * res_srtp
 
struct ast_srtp_policy_res * res_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 308 of file res_rtp_asterisk.c.

◆ FLAG_DTMF_COMPENSATE

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 313 of file res_rtp_asterisk.c.

◆ FLAG_NAT_ACTIVE

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 309 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 310 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE_NOWARN

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 311 of file res_rtp_asterisk.c.

◆ FLAG_NEED_MARKER_BIT

#define FLAG_NEED_MARKER_BIT   (1 << 3)

Definition at line 312 of file res_rtp_asterisk.c.

◆ FLAG_REQ_LOCAL_BRIDGE_BIT

#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)

Definition at line 314 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 6434 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 6861 of file res_rtp_asterisk.c.

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6860 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6859 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6824 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

Definition at line 6833 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 6827 of file res_rtp_asterisk.c.

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6836 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6825 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

Definition at line 6834 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 6826 of file res_rtp_asterisk.c.

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6835 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6858 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6857 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 6854 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 6855 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6839 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6828 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6841 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6837 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6840 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 4385 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 317 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTP

#define TRANSPORT_SOCKET_RTP   0

Definition at line 316 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTCP

#define TRANSPORT_TURN_RTCP   3

Definition at line 319 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTP

#define TRANSPORT_TURN_RTP   2

Definition at line 318 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 10798 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 6595 of file res_rtp_asterisk.c.

6597{
6598 int index;
6599
6600 if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
6601 /* This instance is not bundled */
6602 return instance;
6603 }
6604
6605 /* Find the bundled child instance */
6606 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
6607 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
6608 unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
6609
6610 if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
6611 return mapping->instance;
6612 }
6613 }
6614
6615 /* Does the SSRC match the bundled parent? */
6616 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
6617 return instance;
6618 }
6619 return NULL;
6620}
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::@514 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:637
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition vector.h:696

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 3237 of file res_rtp_asterisk.c.

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

3466{
3467 int len = size;
3468 void *temp = buf;
3469 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3470 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
3471 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
3472 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(transport, rtcp);
3473 int res;
3474#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3475 char *out = buf;
3476 struct dtls_details *dtls = (!rtcp || rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_MUX) ? &rtp->dtls : &rtp->rtcp->dtls;
3477
3478 /* Don't send RTP if DTLS hasn't finished yet */
3479 if (dtls->ssl && ((*out < 20) || (*out > 63)) && dtls->connection == AST_RTP_DTLS_CONNECTION_NEW) {
3480 *via_ice = 0;
3481 return 0;
3482 }
3483#endif
3484
3485 *via_ice = 0;
3486
3487 if (use_srtp && res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
3488 return -1;
3489 }
3490
3491#ifdef HAVE_PJPROJECT
3492 if (transport_rtp->ice) {
3494 pj_status_t status;
3495 struct ice_wrap *ice;
3496
3497 /* If RTCP is sharing the same socket then use the same component */
3498 if (rtcp && rtp->rtcp->s == rtp->s) {
3499 component = AST_RTP_ICE_COMPONENT_RTP;
3500 }
3501
3502 pj_thread_register_check();
3503
3504 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3505 ice = transport_rtp->ice;
3506 ao2_ref(ice, +1);
3507 ao2_ref(transport, +1);
3508 ao2_unlock(instance);
3509 status = pj_ice_sess_send_data(ice->real_ice, component, temp, len);
3510 ao2_ref(ice, -1);
3511 ao2_lock(instance);
3512 if (status == PJ_SUCCESS) {
3513 *via_ice = 1;
3514 ao2_ref(transport, -1);
3515 return len;
3516 }
3517 if (transport != (rtp->bundled ? rtp->bundled : instance)) {
3518 /*
3519 * In case the transport was bundled or un-bundled while we were unlocked don't
3520 * fall through to sending using the transport instance as we may no longer be
3521 * associated with it.
3522 */
3523 ao2_ref(transport, -1);
3524 return 0;
3525 }
3526 ao2_ref(transport, -1);
3527 }
3528#endif
3529
3530 res = ast_sendto(rtcp ? transport_rtp->rtcp->s : transport_rtp->s, temp, len, flags, sa);
3531 if (res > 0) {
3532 ast_rtp_instance_set_last_tx(instance, time(NULL));
3533 }
3534
3535 return res;
3536}
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
@ AST_RTP_INSTANCE_RTCP_MUX
Definition rtp_engine.h:289
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP transmission time.
@ AST_RTP_DTLS_CONNECTION_NEW
Definition rtp_engine.h:573
enum ast_rtp_instance_rtcp type
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_RTCP_MUX, 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, status, and ast_rtcp::type.

Referenced by rtcp_sendto(), and rtp_sendto().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 10798 of file res_rtp_asterisk.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 10798 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 3559 of file res_rtp_asterisk.c.

3560{
3561 unsigned int interval;
3562 /*! \todo XXX Do a more reasonable calculation on this one
3563 * Look in RFC 3550 Section A.7 for an example*/
3564 interval = rtcpinterval;
3565 return interval;
3566}
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 4969 of file res_rtp_asterisk.c.

4971{
4972 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4973 struct ast_rtp_rtcp_report_block *report_block = NULL;
4974 RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
4975
4976 if (!rtp || !rtp->rtcp) {
4977 return 0;
4978 }
4979
4980 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4981 return 0;
4982 }
4983
4984 if (!rtcp_report) {
4985 return -1;
4986 }
4987
4988 report_block = rtcp_report->report_block[0];
4989
4990 if (sr) {
4991 rtp->rtcp->txlsr = rtcp_report->sender_information.ntp_timestamp;
4992 rtp->rtcp->sr_count++;
4993 rtp->rtcp->lastsrtxcount = rtp->txcount;
4994 } else {
4995 rtp->rtcp->rr_count++;
4996 }
4997
4998 if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
4999 ast_verbose("* Sent RTCP %s to %s%s\n", sr ? "SR" : "RR",
5000 ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
5001 ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
5002 if (sr) {
5003 ast_verbose(" Sent(NTP): %u.%06u\n",
5004 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
5005 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
5006 ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
5007 ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
5008 ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
5009 }
5010 if (report_block) {
5011 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
5012 ast_verbose(" Report block:\n");
5013 ast_verbose(" Their SSRC: %u\n", report_block->source_ssrc);
5014 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
5015 ast_verbose(" Cumulative loss: %u\n", report_block->lost_count.packets);
5016 ast_verbose(" Highest seq no: %u\n", report_block->highest_seq_no);
5017 ast_verbose(" IA jitter (samp): %u\n", report_block->ia_jitter);
5018 ast_verbose(" IA jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
5019 ast_verbose(" Their last SR: %u\n", report_block->lsr);
5020 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
5021 }
5022 }
5023
5024 message_blob = ast_json_pack("{s: s, s: s, s: f}",
5025 "to", ast_sockaddr_stringify(&remote_address),
5026 "from", rtp->rtcp->local_addr_str,
5027 "mes", rtp->rxmes);
5028
5030 rtcp_report, message_blob);
5031
5032 return 1;
5033}
struct stasis_message_type * ast_rtp_rtcp_sent_type(void)
Message type for an RTCP message sent from this Asterisk instance.
#define ast_verbose(...)
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.
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
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
unsigned short fraction
Definition rtp_engine.h:349
struct ast_rtp_rtcp_report_block::@289 lost_count
unsigned int rtp_timestamp
Definition rtp_engine.h:367
struct ast_rtp_rtcp_report_block * report_block[0]
Definition rtp_engine.h:374
struct timeval ntp_timestamp
Definition rtp_engine.h:366
struct ast_rtp_rtcp_report::@290 sender_information
unsigned int octet_count
Definition rtp_engine.h:369
unsigned int ssrc
Definition rtp_engine.h:363
unsigned int packet_count
Definition rtp_engine.h:368
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:981

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 5093 of file res_rtp_asterisk.c.

5095{
5096 int packet_len = 0;
5097 int res;
5098
5099 /* Every RTCP packet needs to be sent out with a SR/RR and SDES prefixing it.
5100 * At the end of this function, rtcpheader should contain both of those packets,
5101 * and will return the length of the overall packet. This can be used to determine
5102 * where further packets can be inserted in the compound packet.
5103 */
5104 res = ast_rtcp_generate_report(instance, rtcpheader, report, sr);
5105
5106 if (res == 0 || res == 1) {
5107 ast_debug_rtcp(1, "(%p) RTCP failed to generate %s report!\n", instance, sr ? "SR" : "RR");
5108 return 0;
5109 }
5110
5111 packet_len += res;
5112
5113 res = ast_rtcp_generate_sdes(instance, rtcpheader + packet_len, report);
5114
5115 if (res == 0 || res == 1) {
5116 ast_debug_rtcp(1, "(%p) RTCP failed to generate SDES!\n", instance);
5117 return 0;
5118 }
5119
5120 return packet_len + res;
5121}
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.

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 5123 of file res_rtp_asterisk.c.

5124{
5125 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5126 int packet_len;
5127 int blp_index = -1;
5128 int current_seqno;
5129 unsigned int fci = 0;
5130 size_t remaining_missing_seqno;
5131
5132 if (!rtp || !rtp->rtcp) {
5133 return 0;
5134 }
5135
5136 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
5137 return 0;
5138 }
5139
5140 current_seqno = rtp->expectedrxseqno;
5141 remaining_missing_seqno = AST_VECTOR_SIZE(&rtp->missing_seqno);
5142 packet_len = 12; /* The header length is 12 (version line, packet source SSRC, media source SSRC) */
5143
5144 /* If there are no missing sequence numbers then don't bother sending a NACK needlessly */
5145 if (!remaining_missing_seqno) {
5146 return 0;
5147 }
5148
5149 /* This iterates through the possible forward sequence numbers seeing which ones we
5150 * have no packet for, adding it to the NACK until we are out of missing packets.
5151 */
5152 while (remaining_missing_seqno) {
5153 int *missing_seqno;
5154
5155 /* On the first entry to this loop blp_index will be -1, so this will become 0
5156 * and the sequence number will be placed into the packet as the PID.
5157 */
5158 blp_index++;
5159
5160 missing_seqno = AST_VECTOR_GET_CMP(&rtp->missing_seqno, current_seqno,
5162 if (missing_seqno) {
5163 /* We hit the max blp size, reset */
5164 if (blp_index >= 17) {
5165 put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
5166 fci = 0;
5167 blp_index = 0;
5168 packet_len += 4;
5169 }
5170
5171 if (blp_index == 0) {
5172 fci |= (current_seqno << 16);
5173 } else {
5174 fci |= (1 << (blp_index - 1));
5175 }
5176
5177 /* Since we've used a missing sequence number, we're down one */
5178 remaining_missing_seqno--;
5179 }
5180
5181 /* Handle cycling of the sequence number */
5182 current_seqno++;
5183 if (current_seqno == SEQNO_CYCLE_OVER) {
5184 current_seqno = 0;
5185 }
5186 }
5187
5188 put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
5189 packet_len += 4;
5190
5191 /* Length MUST be 2+n, where n is the number of NACKs. Same as length in words minus 1 */
5192 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_NACK << 24)
5193 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
5194 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
5195 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
5196
5197 return packet_len;
5198}
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
unsigned int ssrc
struct ast_rtp::@513 missing_seqno
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:759

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 4876 of file res_rtp_asterisk.c.

4878{
4879 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4880 int len = 0;
4881 struct timeval now;
4882 unsigned int now_lsw;
4883 unsigned int now_msw;
4884 unsigned int lost_packets;
4885 int fraction_lost;
4886 struct timeval dlsr = { 0, };
4887 struct ast_rtp_rtcp_report_block *report_block = NULL;
4888
4889 if (!rtp || !rtp->rtcp) {
4890 return 0;
4891 }
4892
4893 if (ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */
4894 /* RTCP was stopped. */
4895 return 0;
4896 }
4897
4898 if (!rtcp_report) {
4899 return 1;
4900 }
4901
4902 *sr = rtp->txcount > rtp->rtcp->lastsrtxcount ? 1 : 0;
4903
4904 /* Compute statistics */
4905 calculate_lost_packet_statistics(rtp, &lost_packets, &fraction_lost);
4906 /*
4907 * update_local_mes_stats must be called AFTER
4908 * calculate_lost_packet_statistics
4909 */
4911
4912 gettimeofday(&now, NULL);
4913 rtcp_report->reception_report_count = rtp->themssrc_valid ? 1 : 0;
4914 rtcp_report->ssrc = rtp->ssrc;
4915 rtcp_report->type = *sr ? RTCP_PT_SR : RTCP_PT_RR;
4916 if (*sr) {
4917 rtcp_report->sender_information.ntp_timestamp = now;
4918 rtcp_report->sender_information.rtp_timestamp = rtp->lastts;
4919 rtcp_report->sender_information.packet_count = rtp->txcount;
4920 rtcp_report->sender_information.octet_count = rtp->txoctetcount;
4921 }
4922
4923 if (rtp->themssrc_valid) {
4924 report_block = ast_calloc(1, sizeof(*report_block));
4925 if (!report_block) {
4926 return 1;
4927 }
4928
4929 rtcp_report->report_block[0] = report_block;
4930 report_block->source_ssrc = rtp->themssrc;
4931 report_block->lost_count.fraction = (fraction_lost & 0xff);
4932 report_block->lost_count.packets = (lost_packets & 0xffffff);
4933 report_block->highest_seq_no = (rtp->cycles | (rtp->lastrxseqno & 0xffff));
4934 report_block->ia_jitter = (unsigned int)rtp->rxjitter_samples;
4935 report_block->lsr = rtp->rtcp->themrxlsr;
4936 /* If we haven't received an SR report, DLSR should be 0 */
4937 if (!ast_tvzero(rtp->rtcp->rxlsr)) {
4938 timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
4939 report_block->dlsr = (((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000;
4940 }
4941 }
4942 timeval2ntp(rtcp_report->sender_information.ntp_timestamp, &now_msw, &now_lsw);
4943 put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc)); /* Our SSRC */
4944 len += 8;
4945 if (*sr) {
4946 put_unaligned_uint32(rtcpheader + len, htonl(now_msw)); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970 */
4947 put_unaligned_uint32(rtcpheader + len + 4, htonl(now_lsw)); /* now, LSW */
4948 put_unaligned_uint32(rtcpheader + len + 8, htonl(rtcp_report->sender_information.rtp_timestamp));
4949 put_unaligned_uint32(rtcpheader + len + 12, htonl(rtcp_report->sender_information.packet_count));
4950 put_unaligned_uint32(rtcpheader + len + 16, htonl(rtcp_report->sender_information.octet_count));
4951 len += 20;
4952 }
4953 if (report_block) {
4954 put_unaligned_uint32(rtcpheader + len, htonl(report_block->source_ssrc)); /* Their SSRC */
4955 put_unaligned_uint32(rtcpheader + len + 4, htonl((report_block->lost_count.fraction << 24) | report_block->lost_count.packets));
4956 put_unaligned_uint32(rtcpheader + len + 8, htonl(report_block->highest_seq_no));
4957 put_unaligned_uint32(rtcpheader + len + 12, htonl(report_block->ia_jitter));
4958 put_unaligned_uint32(rtcpheader + len + 16, htonl(report_block->lsr));
4959 put_unaligned_uint32(rtcpheader + len + 20, htonl(report_block->dlsr));
4960 len += 24;
4961 }
4962
4963 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (rtcp_report->reception_report_count << 24)
4964 | ((*sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1)));
4965
4966 return len;
4967}
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, 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 5035 of file res_rtp_asterisk.c.

5037{
5038 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5039 int len = 0;
5040 uint16_t sdes_packet_len_bytes;
5041 uint16_t sdes_packet_len_rounded;
5042
5043 if (!rtp || !rtp->rtcp) {
5044 return 0;
5045 }
5046
5047 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
5048 return 0;
5049 }
5050
5051 if (!rtcp_report) {
5052 return -1;
5053 }
5054
5055 sdes_packet_len_bytes =
5056 4 + /* RTCP Header */
5057 4 + /* SSRC */
5058 1 + /* Type (CNAME) */
5059 1 + /* Text Length */
5060 AST_UUID_STR_LEN /* Text and NULL terminator */
5061 ;
5062
5063 /* Round to 32 bit boundary */
5064 sdes_packet_len_rounded = (sdes_packet_len_bytes + 3) & ~0x3;
5065
5066 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((sdes_packet_len_rounded / 4) - 1)));
5067 put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc));
5068 rtcpheader[8] = 0x01; /* CNAME */
5069 rtcpheader[9] = AST_UUID_STR_LEN - 1; /* Number of bytes of text */
5070 memcpy(rtcpheader + 10, rtp->cname, AST_UUID_STR_LEN);
5071 len += 10 + AST_UUID_STR_LEN;
5072
5073 /* Padding - Note that we don't set the padded bit on the packet. From
5074 * RFC 3550 Section 6.5:
5075 *
5076 * No length octet follows the null item type octet, but additional null
5077 * octets MUST be included if needd to pad until the next 32-bit
5078 * boundary. Note that this padding is separate from that indicated by
5079 * the P bit in the RTCP header.
5080 *
5081 * These bytes will already be zeroed out during array initialization.
5082 */
5083 len += (sdes_packet_len_rounded - sdes_packet_len_bytes);
5084
5085 return len;
5086}
#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 6863 of file res_rtp_asterisk.c.

6865{
6866 struct ast_rtp_instance *transport = instance;
6867 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(instance);
6868 int len = size;
6869 unsigned int *rtcpheader = (unsigned int *)(rtcpdata);
6870 unsigned int packetwords;
6871 unsigned int position;
6872 unsigned int first_word;
6873 /*! True if we have seen an acceptable SSRC to learn the remote RTCP address */
6874 unsigned int ssrc_seen;
6875 struct ast_rtp_rtcp_report_block *report_block;
6876 struct ast_frame *f = &ast_null_frame;
6877#ifdef TEST_FRAMEWORK
6878 struct ast_rtp_engine_test *test_engine;
6879#endif
6880
6881 /* If this is encrypted then decrypt the payload */
6882 if ((*rtcpheader & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
6883 srtp, rtcpheader, &len, 1 | (srtp_replay_protection << 1)) < 0) {
6884 return &ast_null_frame;
6885 }
6886
6887 packetwords = len / 4;
6888
6889 ast_debug_rtcp(2, "(%s) RTCP got report of %d bytes from %s\n",
6892
6893 /*
6894 * Validate the RTCP packet according to an adapted and slightly
6895 * modified RFC3550 validation algorithm.
6896 */
6897 if (packetwords < RTCP_HEADER_SSRC_LENGTH) {
6898 ast_debug_rtcp(2, "(%s) RTCP %p -- from %s: Frame size (%u words) is too short\n",
6900 transport_rtp, ast_sockaddr_stringify(addr), packetwords);
6901 return &ast_null_frame;
6902 }
6903 position = 0;
6904 first_word = ntohl(rtcpheader[position]);
6905 if ((first_word & RTCP_VALID_MASK) != RTCP_VALID_VALUE) {
6906 ast_debug_rtcp(2, "(%s) RTCP %p -- from %s: Failed first packet validity check\n",
6908 transport_rtp, ast_sockaddr_stringify(addr));
6909 return &ast_null_frame;
6910 }
6911 do {
6912 position += ((first_word >> RTCP_LENGTH_SHIFT) & RTCP_LENGTH_MASK) + 1;
6913 if (packetwords <= position) {
6914 break;
6915 }
6916 first_word = ntohl(rtcpheader[position]);
6917 } while ((first_word & RTCP_VERSION_MASK_SHIFTED) == RTCP_VERSION_SHIFTED);
6918 if (position != packetwords) {
6919 ast_debug_rtcp(2, "(%s) RTCP %p -- from %s: Failed packet version or length check\n",
6921 transport_rtp, ast_sockaddr_stringify(addr));
6922 return &ast_null_frame;
6923 }
6924
6925 /*
6926 * Note: RFC3605 points out that true NAT (vs NAPT) can cause RTCP
6927 * to have a different IP address and port than RTP. Otherwise, when
6928 * strictrtp is enabled we could reject RTCP packets not coming from
6929 * the learned RTP IP address if it is available.
6930 */
6931
6932 /*
6933 * strictrtp safety needs SSRC to match before we use the
6934 * sender's address for symmetrical RTP to send our RTCP
6935 * reports.
6936 *
6937 * If strictrtp is not enabled then claim to have already seen
6938 * a matching SSRC so we'll accept this packet's address for
6939 * symmetrical RTP.
6940 */
6941 ssrc_seen = transport_rtp->strict_rtp_state == STRICT_RTP_OPEN;
6942
6943 position = 0;
6944 while (position < packetwords) {
6945 unsigned int i;
6946 unsigned int pt;
6947 unsigned int rc;
6948 unsigned int ssrc;
6949 /*! True if the ssrc value we have is valid and not garbage because it doesn't exist. */
6950 unsigned int ssrc_valid;
6951 unsigned int length;
6952 unsigned int min_length;
6953 /*! Always use packet source SSRC to find the rtp instance unless explicitly told not to. */
6954 unsigned int use_packet_source = 1;
6955
6956 struct ast_json *message_blob;
6957 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
6958 struct ast_rtp_instance *child;
6959 struct ast_rtp *rtp;
6960 struct ast_rtp_rtcp_feedback *feedback;
6961
6962 i = position;
6963 first_word = ntohl(rtcpheader[i]);
6964 pt = (first_word >> RTCP_PAYLOAD_TYPE_SHIFT) & RTCP_PAYLOAD_TYPE_MASK;
6965 rc = (first_word >> RTCP_REPORT_COUNT_SHIFT) & RTCP_REPORT_COUNT_MASK;
6966 /* RFC3550 says 'length' is the number of words in the packet - 1 */
6967 length = ((first_word >> RTCP_LENGTH_SHIFT) & RTCP_LENGTH_MASK) + 1;
6968
6969 /* Check expected RTCP packet record length */
6970 min_length = RTCP_HEADER_SSRC_LENGTH;
6971 switch (pt) {
6972 case RTCP_PT_SR:
6973 min_length += RTCP_SR_BLOCK_WORD_LENGTH;
6974 /* fall through */
6975 case RTCP_PT_RR:
6976 min_length += (rc * RTCP_RR_BLOCK_WORD_LENGTH);
6977 use_packet_source = 0;
6978 break;
6979 case RTCP_PT_FUR:
6980 break;
6981 case AST_RTP_RTCP_RTPFB:
6982 switch (rc) {
6984 min_length += RTCP_FB_NACK_BLOCK_WORD_LENGTH;
6985 break;
6986 default:
6987 break;
6988 }
6989 use_packet_source = 0;
6990 break;
6991 case RTCP_PT_PSFB:
6992 switch (rc) {
6994 min_length += RTCP_FB_REMB_BLOCK_WORD_LENGTH;
6995 break;
6996 default:
6997 break;
6998 }
6999 break;
7000 case RTCP_PT_SDES:
7001 case RTCP_PT_BYE:
7002 /*
7003 * There may not be a SSRC/CSRC present. The packet is
7004 * useless but still valid if it isn't present.
7005 *
7006 * We don't know what min_length should be so disable the check
7007 */
7008 min_length = length;
7009 break;
7010 default:
7011 ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: %u(%s) skipping record\n",
7012 instance, transport_rtp, ast_sockaddr_stringify(addr), pt, rtcp_payload_type2str(pt));
7013 if (rtcp_debug_test_addr(addr)) {
7014 ast_verbose("\n");
7015 ast_verbose("RTCP from %s: %u(%s) skipping record\n",
7017 }
7018 position += length;
7019 continue;
7020 }
7021 if (length < min_length) {
7022 ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: %u(%s) length field less than expected minimum. Min:%u Got:%u\n",
7023 instance, transport_rtp, ast_sockaddr_stringify(addr), pt, rtcp_payload_type2str(pt),
7024 min_length - 1, length - 1);
7025 return &ast_null_frame;
7026 }
7027
7028 /* Get the RTCP record SSRC if defined for the record */
7029 ssrc_valid = 1;
7030 switch (pt) {
7031 case RTCP_PT_SR:
7032 case RTCP_PT_RR:
7033 rtcp_report = ast_rtp_rtcp_report_alloc(rc);
7034 if (!rtcp_report) {
7035 return &ast_null_frame;
7036 }
7037 rtcp_report->reception_report_count = rc;
7038
7039 ssrc = ntohl(rtcpheader[i + 2]);
7040 rtcp_report->ssrc = ssrc;
7041 break;
7042 case RTCP_PT_FUR:
7043 case RTCP_PT_PSFB:
7044 ssrc = ntohl(rtcpheader[i + 1]);
7045 break;
7046 case AST_RTP_RTCP_RTPFB:
7047 ssrc = ntohl(rtcpheader[i + 2]);
7048 break;
7049 case RTCP_PT_SDES:
7050 case RTCP_PT_BYE:
7051 default:
7052 ssrc = 0;
7053 ssrc_valid = 0;
7054 break;
7055 }
7056
7057 if (rtcp_debug_test_addr(addr)) {
7058 const char *subtype = rtcp_payload_subtype2str(pt, rc);
7059
7060 ast_verbose("\n");
7061 ast_verbose("RTCP from %s\n", ast_sockaddr_stringify(addr));
7062 ast_verbose("PT: %u (%s)\n", pt, rtcp_payload_type2str(pt));
7063 if (subtype) {
7064 ast_verbose("Packet Subtype: %u (%s)\n", rc, subtype);
7065 } else {
7066 ast_verbose("Reception reports: %u\n", rc);
7067 }
7068 ast_verbose("SSRC of sender: %u\n", ssrc);
7069 }
7070
7071 /* Determine the appropriate instance for this */
7072 if (ssrc_valid) {
7073 /*
7074 * Depending on the payload type, either the packet source or media source
7075 * SSRC is used.
7076 */
7077 if (use_packet_source) {
7078 child = rtp_find_instance_by_packet_source_ssrc(transport, transport_rtp, ssrc);
7079 } else {
7080 child = rtp_find_instance_by_media_source_ssrc(transport, transport_rtp, ssrc);
7081 }
7082 if (child && child != transport) {
7083 /*
7084 * It is safe to hold the child lock while holding the parent lock.
7085 * We guarantee that the locking order is always parent->child or
7086 * that the child lock is not held when acquiring the parent lock.
7087 */
7088 ao2_lock(child);
7089 instance = child;
7090 rtp = ast_rtp_instance_get_data(instance);
7091 } else {
7092 /* The child is the parent! We don't need to unlock it. */
7093 child = NULL;
7094 rtp = transport_rtp;
7095 }
7096 } else {
7097 child = NULL;
7098 rtp = transport_rtp;
7099 }
7100
7101 if (ssrc_valid && rtp->themssrc_valid) {
7102 /*
7103 * If the SSRC is 1, we still need to handle RTCP since this could be a
7104 * special case. For example, if we have a unidirectional video stream, the
7105 * SSRC may be set to 1 by the browser (in the case of chromium), and requests
7106 * will still need to be processed so that video can flow as expected. This
7107 * should only be done for PLI and FUR, since there is not a way to get the
7108 * appropriate rtp instance when the SSRC is 1.
7109 */
7110 int exception = (ssrc == 1 && !((pt == RTCP_PT_PSFB && rc == AST_RTP_RTCP_FMT_PLI) || pt == RTCP_PT_FUR));
7111 if ((ssrc != rtp->themssrc && use_packet_source && ssrc != 1)
7112 || exception) {
7113 /*
7114 * Skip over this RTCP record as it does not contain the
7115 * correct SSRC. We should not act upon RTCP records
7116 * for a different stream.
7117 */
7118 position += length;
7119 ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: Skipping record, received SSRC '%u' != expected '%u'\n",
7120 instance, rtp, ast_sockaddr_stringify(addr), ssrc, rtp->themssrc);
7121 if (child) {
7122 ao2_unlock(child);
7123 }
7124 continue;
7125 }
7126 ssrc_seen = 1;
7127 }
7128
7129 if (ssrc_seen && ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
7130 /* Send to whoever sent to us */
7131 if (ast_sockaddr_cmp(&rtp->rtcp->them, addr)) {
7132 ast_sockaddr_copy(&rtp->rtcp->them, addr);
7134 ast_debug(0, "(%p) RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
7135 instance, ast_sockaddr_stringify(addr));
7136 }
7137 }
7138 }
7139
7140 i += RTCP_HEADER_SSRC_LENGTH; /* Advance past header and ssrc */
7141 switch (pt) {
7142 case RTCP_PT_SR:
7143 gettimeofday(&rtp->rtcp->rxlsr, NULL);
7144 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16);
7145 rtp->rtcp->spc = ntohl(rtcpheader[i + 3]);
7146 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
7147
7148 rtcp_report->type = RTCP_PT_SR;
7149 rtcp_report->sender_information.packet_count = rtp->rtcp->spc;
7150 rtcp_report->sender_information.octet_count = rtp->rtcp->soc;
7151 ntp2timeval((unsigned int)ntohl(rtcpheader[i]),
7152 (unsigned int)ntohl(rtcpheader[i + 1]),
7153 &rtcp_report->sender_information.ntp_timestamp);
7154 rtcp_report->sender_information.rtp_timestamp = ntohl(rtcpheader[i + 2]);
7155 if (rtcp_debug_test_addr(addr)) {
7156 ast_verbose("NTP timestamp: %u.%06u\n",
7157 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
7158 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
7159 ast_verbose("RTP timestamp: %u\n", rtcp_report->sender_information.rtp_timestamp);
7160 ast_verbose("SPC: %u\tSOC: %u\n",
7161 rtcp_report->sender_information.packet_count,
7162 rtcp_report->sender_information.octet_count);
7163 }
7165 /* Intentional fall through */
7166 case RTCP_PT_RR:
7167 if (rtcp_report->type != RTCP_PT_SR) {
7168 rtcp_report->type = RTCP_PT_RR;
7169 }
7170
7171 if (rc > 0) {
7172 /* Don't handle multiple reception reports (rc > 1) yet */
7173 report_block = ast_calloc(1, sizeof(*report_block));
7174 if (!report_block) {
7175 if (child) {
7176 ao2_unlock(child);
7177 }
7178 return &ast_null_frame;
7179 }
7180 rtcp_report->report_block[0] = report_block;
7181 report_block->source_ssrc = ntohl(rtcpheader[i]);
7182 report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
7183 report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
7184 report_block->highest_seq_no = ntohl(rtcpheader[i + 2]);
7185 report_block->ia_jitter = ntohl(rtcpheader[i + 3]);
7186 report_block->lsr = ntohl(rtcpheader[i + 4]);
7187 report_block->dlsr = ntohl(rtcpheader[i + 5]);
7188 if (report_block->lsr) {
7189 int skewed = update_rtt_stats(rtp, report_block->lsr, report_block->dlsr);
7190 if (skewed && rtcp_debug_test_addr(addr)) {
7191 struct timeval now;
7192 unsigned int lsr_now, lsw, msw;
7193 gettimeofday(&now, NULL);
7194 timeval2ntp(now, &msw, &lsw);
7195 lsr_now = (((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16));
7196 ast_verbose("Internal RTCP NTP clock skew detected: "
7197 "lsr=%u, now=%u, dlsr=%u (%u:%03ums), "
7198 "diff=%u\n",
7199 report_block->lsr, lsr_now, report_block->dlsr, report_block->dlsr / 65536,
7200 (report_block->dlsr % 65536) * 1000 / 65536,
7201 report_block->dlsr - (lsr_now - report_block->lsr));
7202 }
7203 }
7204 update_jitter_stats(rtp, report_block->ia_jitter);
7205 update_lost_stats(rtp, report_block->lost_count.packets);
7206 /*
7207 * update_reported_mes_stats must be called AFTER
7208 * update_rtt_stats, update_jitter_stats and
7209 * update_lost_stats.
7210 */
7212
7213 if (rtcp_debug_test_addr(addr)) {
7214 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
7215
7216 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
7217 ast_verbose(" Packets lost so far: %u\n", report_block->lost_count.packets);
7218 ast_verbose(" Highest sequence number: %u\n", report_block->highest_seq_no & 0x0000ffff);
7219 ast_verbose(" Sequence number cycles: %u\n", report_block->highest_seq_no >> 16);
7220 ast_verbose(" Interarrival jitter (samp): %u\n", report_block->ia_jitter);
7221 ast_verbose(" Interarrival jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
7222 ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long)(report_block->lsr) >> 16,((unsigned long)(report_block->lsr) << 16) * 4096);
7223 ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
7224 ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
7225 ast_verbose(" MES: %4.1f\n", rtp->rtcp->reported_mes);
7226 }
7227 }
7228 /* If and when we handle more than one report block, this should occur outside
7229 * this loop.
7230 */
7231
7232 message_blob = ast_json_pack("{s: s, s: s, s: f, s: f}",
7233 "from", ast_sockaddr_stringify(addr),
7234 "to", transport_rtp->rtcp->local_addr_str,
7235 "rtt", rtp->rtcp->rtt,
7236 "mes", rtp->rtcp->reported_mes);
7238 rtcp_report,
7239 message_blob);
7240 ast_json_unref(message_blob);
7241
7242 /* Return an AST_FRAME_RTCP frame with the ast_rtp_rtcp_report
7243 * object as a its data */
7244 transport_rtp->f.frametype = AST_FRAME_RTCP;
7245 transport_rtp->f.subclass.integer = pt;
7246 transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
7247 memcpy(transport_rtp->f.data.ptr, rtcp_report, sizeof(struct ast_rtp_rtcp_report));
7248 transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_report);
7249 if (rc > 0) {
7250 /* There's always a single report block stored, here */
7251 struct ast_rtp_rtcp_report *rtcp_report2;
7252 report_block = transport_rtp->f.data.ptr + transport_rtp->f.datalen + sizeof(struct ast_rtp_rtcp_report_block *);
7253 memcpy(report_block, rtcp_report->report_block[0], sizeof(struct ast_rtp_rtcp_report_block));
7254 rtcp_report2 = (struct ast_rtp_rtcp_report *)transport_rtp->f.data.ptr;
7255 rtcp_report2->report_block[0] = report_block;
7256 transport_rtp->f.datalen += sizeof(struct ast_rtp_rtcp_report_block);
7257 }
7258 transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
7259 transport_rtp->f.samples = 0;
7260 transport_rtp->f.mallocd = 0;
7261 transport_rtp->f.delivery.tv_sec = 0;
7262 transport_rtp->f.delivery.tv_usec = 0;
7263 transport_rtp->f.src = "RTP";
7264 transport_rtp->f.stream_num = rtp->stream_num;
7265 f = &transport_rtp->f;
7266 break;
7267 case AST_RTP_RTCP_RTPFB:
7268 switch (rc) {
7270 /* If retransmissions are not enabled ignore this message */
7271 if (!rtp->send_buffer) {
7272 break;
7273 }
7274
7275 if (rtcp_debug_test_addr(addr)) {
7276 ast_verbose("Received generic RTCP NACK message\n");
7277 }
7278
7280 child ? transport : NULL, rtcpheader, position, length);
7281
7282 break;
7283 default:
7284 break;
7285 }
7286 break;
7287 case RTCP_PT_FUR:
7288 /* Handle RTCP FUR as FIR by setting the format to 4 */
7290 case RTCP_PT_PSFB:
7291 switch (rc) {
7294 if (rtcp_debug_test_addr(addr)) {
7295 ast_verbose("Received an RTCP Fast Update Request\n");
7296 }
7297 transport_rtp->f.frametype = AST_FRAME_CONTROL;
7298 transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
7299 transport_rtp->f.datalen = 0;
7300 transport_rtp->f.samples = 0;
7301 transport_rtp->f.mallocd = 0;
7302 transport_rtp->f.src = "RTP";
7303 f = &transport_rtp->f;
7304 break;
7306 /* If REMB support is not enabled ignore this message */
7308 break;
7309 }
7310
7311 if (rtcp_debug_test_addr(addr)) {
7312 ast_verbose("Received REMB report\n");
7313 }
7314 transport_rtp->f.frametype = AST_FRAME_RTCP;
7315 transport_rtp->f.subclass.integer = pt;
7316 transport_rtp->f.stream_num = rtp->stream_num;
7317 transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
7318 feedback = transport_rtp->f.data.ptr;
7319 feedback->fmt = rc;
7320
7321 /* We don't actually care about the SSRC information in the feedback message */
7322 first_word = ntohl(rtcpheader[i + 2]);
7323 feedback->remb.br_exp = (first_word >> 18) & ((1 << 6) - 1);
7324 feedback->remb.br_mantissa = first_word & ((1 << 18) - 1);
7325
7326 transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_feedback);
7327 transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
7328 transport_rtp->f.samples = 0;
7329 transport_rtp->f.mallocd = 0;
7330 transport_rtp->f.delivery.tv_sec = 0;
7331 transport_rtp->f.delivery.tv_usec = 0;
7332 transport_rtp->f.src = "RTP";
7333 f = &transport_rtp->f;
7334 break;
7335 default:
7336 break;
7337 }
7338 break;
7339 case RTCP_PT_SDES:
7340 if (rtcp_debug_test_addr(addr)) {
7341 ast_verbose("Received an SDES from %s\n",
7343 }
7344#ifdef TEST_FRAMEWORK
7345 if ((test_engine = ast_rtp_instance_get_test(instance))) {
7346 test_engine->sdes_received = 1;
7347 }
7348#endif
7349 break;
7350 case RTCP_PT_BYE:
7351 if (rtcp_debug_test_addr(addr)) {
7352 ast_verbose("Received a BYE from %s\n",
7354 }
7355 break;
7356 default:
7357 break;
7358 }
7359 position += length;
7360 rtp->rtcp->rtcp_info = 1;
7361
7362 if (child) {
7363 ao2_unlock(child);
7364 }
7365 }
7366
7367 return f;
7368}
#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_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
#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)
static int ast_rtp_rtcp_handle_nack_locking(struct ast_rtp_instance *instance, struct ast_rtp_instance *transport, unsigned int *nackdata, unsigned int position, unsigned int length)
#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.
int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
Get the value of an RTP instance property.
Definition rtp_engine.c:767
#define ast_debug_rtp_packet_is_allowed
#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::@237 data
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
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_locking(), 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 7371 of file res_rtp_asterisk.c.

7372{
7373 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7374 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 1);
7375 struct ast_sockaddr addr;
7376 unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
7377 unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
7378 size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
7379 int res;
7380
7381 /* Read in RTCP data from the socket */
7382 if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
7383 0, &addr)) < 0) {
7384 if (res == RTP_DTLS_ESTABLISHED) {
7387 return &rtp->f;
7388 }
7389
7390 ast_assert(errno != EBADF);
7391 if (errno != EAGAIN) {
7392 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n",
7393 (errno) ? strerror(errno) : "Unspecified");
7394 return NULL;
7395 }
7396 return &ast_null_frame;
7397 }
7398
7399 /* If this was handled by the ICE session don't do anything further */
7400 if (!res) {
7401 return &ast_null_frame;
7402 }
7403
7404 if (!*read_area) {
7405 struct sockaddr_in addr_tmp;
7406 struct ast_sockaddr addr_v4;
7407
7408 if (ast_sockaddr_is_ipv4(&addr)) {
7409 ast_sockaddr_to_sin(&addr, &addr_tmp);
7410 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
7411 ast_debug_stun(2, "(%p) STUN using IPv6 mapped address %s\n",
7412 instance, ast_sockaddr_stringify(&addr));
7413 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
7414 } else {
7415 ast_debug_stun(2, "(%p) STUN cannot do for non IPv4 address %s\n",
7416 instance, ast_sockaddr_stringify(&addr));
7417 return &ast_null_frame;
7418 }
7419 if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
7420 ast_sockaddr_from_sin(&addr, &addr_tmp);
7421 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
7422 }
7423 return &ast_null_frame;
7424 }
7425
7426 return ast_rtcp_interpret(instance, srtp, read_area, res, &addr);
7427}
@ 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:779

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 5208 of file res_rtp_asterisk.c.

5209{
5210 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
5211 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5212 int res;
5213 int sr = 0;
5214 int packet_len = 0;
5215 int ice;
5216 struct ast_sockaddr remote_address = { { 0, } };
5217 unsigned char *rtcpheader;
5218 unsigned char bdata[AST_UUID_STR_LEN + 128] = ""; /* More than enough */
5219 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5220
5221 if (!rtp || !rtp->rtcp || rtp->rtcp->schedid == -1) {
5222 ao2_ref(instance, -1);
5223 return 0;
5224 }
5225
5226 ao2_lock(instance);
5227 rtcpheader = bdata;
5228 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5229 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5230
5231 if (res == 0 || res == 1) {
5232 goto cleanup;
5233 }
5234
5235 packet_len += res;
5236
5237 if (rtp->bundled) {
5238 ast_rtp_instance_get_remote_address(instance, &remote_address);
5239 } else {
5240 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
5241 }
5242
5243 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
5244 if (res < 0) {
5245 ast_log(LOG_ERROR, "RTCP %s transmission error to %s, rtcp halted %s\n",
5246 sr ? "SR" : "RR",
5247 ast_sockaddr_stringify(&rtp->rtcp->them),
5248 strerror(errno));
5249 res = 0;
5250 } else {
5251 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
5252 }
5253
5254cleanup:
5255 ao2_unlock(instance);
5256
5257 if (!res) {
5258 /*
5259 * Not being rescheduled.
5260 */
5261 rtp->rtcp->schedid = -1;
5262 ao2_ref(instance, -1);
5263 }
5264
5265 return res;
5266}
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)
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition res_stasis.c:327

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 9767 of file res_rtp_asterisk.c.

9768{
9769 struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child);
9770 struct ast_rtp *parent_rtp;
9771 struct rtp_ssrc_mapping mapping;
9772 struct ast_sockaddr them = { { 0, } };
9773
9774 if (child_rtp->bundled == parent) {
9775 return 0;
9776 }
9777
9778 /* If this instance was already bundled then remove the SSRC mapping */
9779 if (child_rtp->bundled) {
9780 struct ast_rtp *bundled_rtp;
9781
9782 ao2_unlock(child);
9783
9784 /* The child lock can't be held while accessing the parent */
9785 ao2_lock(child_rtp->bundled);
9786 bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled);
9788 ao2_unlock(child_rtp->bundled);
9789
9790 ao2_lock(child);
9791 ao2_ref(child_rtp->bundled, -1);
9792 child_rtp->bundled = NULL;
9793 }
9794
9795 if (!parent) {
9796 /* We transitioned away from bundle so we need our own transport resources once again */
9797 rtp_allocate_transport(child, child_rtp);
9798 return 0;
9799 }
9800
9801 parent_rtp = ast_rtp_instance_get_data(parent);
9802
9803 /* We no longer need any transport related resources as we will use our parent RTP instance instead */
9804 rtp_deallocate_transport(child, child_rtp);
9805
9806 /* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
9807 child_rtp->bundled = ao2_bump(parent);
9808
9809 mapping.ssrc = child_rtp->themssrc;
9810 mapping.ssrc_valid = child_rtp->themssrc_valid;
9811 mapping.instance = child;
9812
9813 ao2_unlock(child);
9814
9815 ao2_lock(parent);
9816
9817 AST_VECTOR_APPEND(&parent_rtp->ssrc_mapping, mapping);
9818
9819#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9820 /* If DTLS-SRTP is already in use then add the local SSRC to it, otherwise it will get added once DTLS
9821 * negotiation has been completed.
9822 */
9823 if (parent_rtp->dtls.connection == AST_RTP_DTLS_CONNECTION_EXISTING) {
9824 dtls_srtp_add_local_ssrc(parent_rtp, parent, 0, child_rtp->ssrc, 0);
9825 }
9826#endif
9827
9828 /* Bundle requires that RTCP-MUX be in use so only the main remote address needs to match */
9830
9831 ao2_unlock(parent);
9832
9833 ao2_lock(child);
9834
9836
9837 return 0;
9838}
#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:599
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition vector.h:516
#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 4745 of file res_rtp_asterisk.c.

4746{
4747 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4748 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 0);
4749 struct ast_srtp *rtcp_srtp = ast_rtp_instance_get_srtp(instance, 1);
4750 unsigned int ssrc = ast_random();
4751
4752 if (rtp->lastts) {
4753 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4755 }
4756
4757 ast_debug_rtp(3, "(%p) RTP changing ssrc from %u to %u due to a source change\n",
4758 instance, rtp->ssrc, ssrc);
4759
4760 if (srtp) {
4761 ast_debug_rtp(3, "(%p) RTP changing ssrc for SRTP from %u to %u\n",
4762 instance, rtp->ssrc, ssrc);
4763 res_srtp->change_source(srtp, rtp->ssrc, ssrc);
4764 if (rtcp_srtp != srtp) {
4765 res_srtp->change_source(rtcp_srtp, rtp->ssrc, ssrc);
4766 }
4767 }
4768
4769 rtp->ssrc = ssrc;
4770
4771 /* Since the source is changing, we don't know what sequence number to expect next */
4772 rtp->expectedrxseqno = -1;
4773
4774 return;
4775}
#define FLAG_NEED_MARKER_BIT
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
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:2346
#define ast_set_flag(p, flag)
Definition utils.h:71

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 4388 of file res_rtp_asterisk.c.

4389{
4390 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4391
4392 if (rtp->bundled) {
4393 struct ast_rtp *bundled_rtp;
4394
4395 /* We can't hold our instance lock while removing ourselves from the parent */
4396 ao2_unlock(instance);
4397
4398 ao2_lock(rtp->bundled);
4399 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
4401 ao2_unlock(rtp->bundled);
4402
4403 ao2_lock(instance);
4404 ao2_ref(rtp->bundled, -1);
4405 }
4406
4407 rtp_deallocate_transport(instance, rtp);
4408
4409 /* Destroy the smoother that was smoothing out audio if present */
4410 if (rtp->smoother) {
4412 }
4413
4414 /* Destroy RTCP if it was being used */
4415 if (rtp->rtcp) {
4416 /*
4417 * It is not possible for there to be an active RTCP scheduler
4418 * entry at this point since it holds a reference to the
4419 * RTP instance while it's active.
4420 */
4422 ast_free(rtp->rtcp);
4423 }
4424
4425 /* Destroy RED if it was being used */
4426 if (rtp->red) {
4427 ao2_unlock(instance);
4428 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
4429 ao2_lock(instance);
4430 ast_free(rtp->red);
4431 rtp->red = NULL;
4432 }
4433
4434 /* Destroy the send buffer if it was being used */
4435 if (rtp->send_buffer) {
4437 }
4438
4439 /* Destroy the recv buffer if it was being used */
4440 if (rtp->recv_buffer) {
4442 }
4443
4445
4451
4452 /* Finally destroy ourselves */
4453 rtp->owner = NULL;
4454 ast_free(rtp);
4455
4456 return 0;
4457}
#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)
#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::@512 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 4475 of file res_rtp_asterisk.c.

4476{
4477 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4478 struct ast_sockaddr remote_address = { {0,} };
4479 int hdrlen = 12, res = 0, i = 0, payload = -1, sample_rate = -1;
4480 char data[256];
4481 unsigned int *rtpheader = (unsigned int*)data;
4482 RAII_VAR(struct ast_format *, payload_format, NULL, ao2_cleanup);
4483
4484 ast_rtp_instance_get_remote_address(instance, &remote_address);
4485
4486 /* If we have no remote address information bail out now */
4487 if (ast_sockaddr_isnull(&remote_address)) {
4488 return -1;
4489 }
4490
4491 /* Convert given digit into what we want to transmit */
4492 if ((digit <= '9') && (digit >= '0')) {
4493 digit -= '0';
4494 } else if (digit == '*') {
4495 digit = 10;
4496 } else if (digit == '#') {
4497 digit = 11;
4498 } else if ((digit >= 'A') && (digit <= 'D')) {
4499 digit = digit - 'A' + 12;
4500 } else if ((digit >= 'a') && (digit <= 'd')) {
4501 digit = digit - 'a' + 12;
4502 } else {
4503 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4504 return -1;
4505 }
4506
4507
4508 /* g722 is a 16K codec that masquerades as an 8K codec within RTP. ast_rtp_get_rate was written specifically to
4509 handle this. If we use the actual sample rate of g722 in this scenario and there is a 16K telephone-event on
4510 offer, we will end up using that instead of the 8K rate telephone-event that is expected with g722. */
4511 if (rtp->lasttxformat == ast_format_none) {
4512 /* No audio frames have been written yet so we have to lookup both the preferred payload type and bitrate. */
4514 if (payload_format) {
4515 /* If we have a preferred type, use that. Otherwise default to 8K. */
4516 sample_rate = ast_rtp_get_rate(payload_format);
4517 }
4518 } else {
4519 sample_rate = ast_rtp_get_rate(rtp->lasttxformat);
4520 }
4521
4522 if (sample_rate != -1) {
4524 }
4525
4526 if (payload == -1 ||
4529 /* Fall back to the preferred DTMF payload type and sample rate as either we couldn't find an audio codec to try and match
4530 sample rates with or we could, but a telephone-event matching that audio codec's sample rate was not included in the
4531 sdp negotiated by the far end. */
4534 }
4535
4536 /* The sdp negotiation has not yeilded a usable RFC 2833/4733 format. Try a default-rate one as a last resort. */
4537 if (payload == -1 || sample_rate == -1) {
4538 sample_rate = DEFAULT_DTMF_SAMPLE_RATE_MS;
4540 }
4541 /* Even trying a default payload has failed. We are trying to send a digit outside of what was negotiated for. */
4542 if (payload == -1) {
4543 return -1;
4544 }
4545
4546 ast_test_suite_event_notify("DTMF_BEGIN", "Digit: %d\r\nPayload: %d\r\nRate: %d\r\n", digit, payload, sample_rate);
4547 ast_debug(1, "Sending digit '%d' at rate %d with payload %d\n", digit, sample_rate, payload);
4548
4549 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4550 rtp->send_duration = 160;
4551 rtp->dtmf_samplerate_ms = (sample_rate / 1000);
4552 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4553 rtp->lastdigitts = rtp->lastts + rtp->send_duration;
4554
4555 /* Create the actual packet that we will be sending */
4556 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
4557 rtpheader[1] = htonl(rtp->lastdigitts);
4558 rtpheader[2] = htonl(rtp->ssrc);
4559
4560 /* Actually send the packet */
4561 for (i = 0; i < 2; i++) {
4562 int ice;
4563
4564 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4565 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4566 if (res < 0) {
4567 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4568 ast_sockaddr_stringify(&remote_address),
4569 strerror(errno));
4570 }
4571 if (rtp_debug_test_addr(&remote_address)) {
4572 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4573 ast_sockaddr_stringify(&remote_address),
4574 ice ? " (via ICE)" : "",
4575 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4576 }
4577 rtp->seqno++;
4578 rtp->send_duration += 160;
4579 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
4580 }
4581
4582 /* Record that we are in the process of sending a digit and information needed to continue doing so */
4583 rtp->sending_digit = 1;
4584 rtp->send_digit = digit;
4585 rtp->send_payload = payload;
4586
4587 return 0;
4588}
char digit
struct ast_format * ast_format_none
Built-in "null" format.
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.
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.
#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.
int ast_rtp_codecs_get_preferred_dtmf_format_rate(struct ast_rtp_codecs *codecs)
Retrieve rx preferred dtmf format sample rate.
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.
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.
int ast_rtp_codecs_get_preferred_dtmf_format_pt(struct ast_rtp_codecs *codecs)
Retrieve rx preferred dtmf format payload type.
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition rtp_engine.c:778
#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
#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:2278
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_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_get_rate(), 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 9550 of file res_rtp_asterisk.c.

9551{
9552 /* If both sides are not using the same method of DTMF transmission
9553 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9554 * --------------------------------------------------
9555 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9556 * |-----------|------------|-----------------------|
9557 * | Inband | False | True |
9558 * | RFC2833 | True | True |
9559 * | SIP INFO | False | False |
9560 * --------------------------------------------------
9561 */
9563 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9564}
@ AST_RTP_PROPERTY_DTMF
Definition rtp_engine.h:120
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648

References 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 4591 of file res_rtp_asterisk.c.

4592{
4593 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4594 struct ast_sockaddr remote_address = { {0,} };
4595 int hdrlen = 12, res = 0;
4596 char data[256];
4597 unsigned int *rtpheader = (unsigned int*)data;
4598 int ice;
4599
4600 ast_rtp_instance_get_remote_address(instance, &remote_address);
4601
4602 /* Make sure we know where the other side is so we can send them the packet */
4603 if (ast_sockaddr_isnull(&remote_address)) {
4604 return -1;
4605 }
4606
4607 /* Actually create the packet we will be sending */
4608 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4609 rtpheader[1] = htonl(rtp->lastdigitts);
4610 rtpheader[2] = htonl(rtp->ssrc);
4611 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
4612
4613 /* Boom, send it on out */
4614 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4615 if (res < 0) {
4616 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4617 ast_sockaddr_stringify(&remote_address),
4618 strerror(errno));
4619 }
4620
4621 if (rtp_debug_test_addr(&remote_address)) {
4622 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4623 ast_sockaddr_stringify(&remote_address),
4624 ice ? " (via ICE)" : "",
4625 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4626 }
4627
4628 /* And now we increment some values for the next time we swing by */
4629 rtp->seqno++;
4630 rtp->send_duration += 160;
4631 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4632
4633 return 0;
4634}

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 4727 of file res_rtp_asterisk.c.

4728{
4729 return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
4730}
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 4637 of file res_rtp_asterisk.c.

4638{
4639 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4640 struct ast_sockaddr remote_address = { {0,} };
4641 int hdrlen = 12, res = -1, i = 0;
4642 char data[256];
4643 unsigned int *rtpheader = (unsigned int*)data;
4644 unsigned int measured_samples;
4645
4646 ast_rtp_instance_get_remote_address(instance, &remote_address);
4647
4648 /* Make sure we know where the remote side is so we can send them the packet we construct */
4649 if (ast_sockaddr_isnull(&remote_address)) {
4650 goto cleanup;
4651 }
4652
4653 /* Convert the given digit to the one we are going to send */
4654 if ((digit <= '9') && (digit >= '0')) {
4655 digit -= '0';
4656 } else if (digit == '*') {
4657 digit = 10;
4658 } else if (digit == '#') {
4659 digit = 11;
4660 } else if ((digit >= 'A') && (digit <= 'D')) {
4661 digit = digit - 'A' + 12;
4662 } else if ((digit >= 'a') && (digit <= 'd')) {
4663 digit = digit - 'a' + 12;
4664 } else {
4665 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4666 goto cleanup;
4667 }
4668
4669 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4670
4671 if (duration > 0 && (measured_samples = duration * ast_rtp_get_rate(rtp->f.subclass.format) / 1000) > rtp->send_duration) {
4672 ast_debug_rtp(2, "(%p) RTP adjusting final end duration from %d to %u\n",
4673 instance, rtp->send_duration, measured_samples);
4674 rtp->send_duration = measured_samples;
4675 }
4676
4677 /* Construct the packet we are going to send */
4678 rtpheader[1] = htonl(rtp->lastdigitts);
4679 rtpheader[2] = htonl(rtp->ssrc);
4680 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4681 rtpheader[3] |= htonl((1 << 23));
4682
4683 /* Send it 3 times, that's the magical number */
4684 for (i = 0; i < 3; i++) {
4685 int ice;
4686
4687 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4688
4689 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4690
4691 if (res < 0) {
4692 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4693 ast_sockaddr_stringify(&remote_address),
4694 strerror(errno));
4695 }
4696
4697 if (rtp_debug_test_addr(&remote_address)) {
4698 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4699 ast_sockaddr_stringify(&remote_address),
4700 ice ? " (via ICE)" : "",
4701 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4702 }
4703
4704 rtp->seqno++;
4705 }
4706 res = 0;
4707
4708 /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
4709 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4710
4711 /* Reset the smoother as the delivery time stored in it is now out of date */
4712 if (rtp->smoother) {
4714 rtp->smoother = NULL;
4715 }
4716cleanup:
4717 rtp->sending_digit = 0;
4718 rtp->send_digit = 0;
4719
4720 /* Re-Learn expected seqno */
4721 rtp->expectedseqno = -1;
4722
4723 return res;
4724}

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 4468 of file res_rtp_asterisk.c.

4469{
4470 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4471 return rtp->dtmfmode;
4472}
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 4460 of file res_rtp_asterisk.c.

4461{
4462 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4463 rtp->dtmfmode = dtmf_mode;
4464 return 0;
4465}

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 9755 of file res_rtp_asterisk.c.

9756{
9757 switch (extension) {
9760 return 1;
9761 default:
9762 return 0;
9763 }
9764}
@ 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 9271 of file res_rtp_asterisk.c.

9272{
9273 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9274
9275 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9276}

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 9702 of file res_rtp_asterisk.c.

9703{
9704 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9705
9706 return rtp->cname;
9707}

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 9694 of file res_rtp_asterisk.c.

9695{
9696 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9697
9698 return rtp->ssrc;
9699}

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 9485 of file res_rtp_asterisk.c.

9486{
9487 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9488
9489 if (!rtp->rtcp) {
9490 return -1;
9491 }
9492
9497
9509
9521
9528
9540
9541
9545
9546 return 0;
9547}
#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
unsigned int received_prior
double reported_maxjitter
double reported_normdev_lost
double reported_minlost
double normdevrtt
double reported_normdev_mes
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 stdev_rxmes
double reported_minjitter
unsigned int expected_prior
double reported_minmes
double stdev_rxlost
unsigned int remote_ssrc
Definition rtp_engine.h:454
unsigned int local_ssrc
Definition rtp_engine.h:452
unsigned int rxoctetcount
Definition rtp_engine.h:460
unsigned int txoctetcount
Definition rtp_engine.h:458
char channel_uniqueid[MAX_CHANNEL_ID]
Definition rtp_engine.h:456
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_rtcp::stdev_rxmes, 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 7981 of file res_rtp_asterisk.c.

7984{
7985 unsigned int *rtpheader = (unsigned int*)(read_area);
7986 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7987 struct ast_rtp_instance *instance1;
7988 int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc;
7989 unsigned int timestamp;
7990 RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
7991 struct frame_list frames;
7992
7993 /* If this payload is encrypted then decrypt it using the given SRTP instance */
7994 if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
7995 srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
7996 return &ast_null_frame;
7997 }
7998
7999 /* If we are currently sending DTMF to the remote party send a continuation packet */
8000 if (rtp->sending_digit) {
8001 ast_rtp_dtmf_continuation(instance);
8002 }
8003
8004 /* Pull out the various other fields we will need */
8005 ssrc = ntohl(rtpheader[2]);
8006 seqno = ntohl(rtpheader[0]);
8007 payloadtype = (seqno & 0x7f0000) >> 16;
8008 padding = seqno & (1 << 29);
8009 mark = seqno & (1 << 23);
8010 ext = seqno & (1 << 28);
8011 cc = (seqno & 0xF000000) >> 24;
8012 seqno &= 0xffff;
8013 timestamp = ntohl(rtpheader[1]);
8014
8016
8017 /* Remove any padding bytes that may be present */
8018 if (padding) {
8019 res -= read_area[res - 1];
8020 }
8021
8022 /* Skip over any CSRC fields */
8023 if (cc) {
8024 hdrlen += cc * 4;
8025 }
8026
8027 /* Look for any RTP extensions, currently we do not support any */
8028 if (ext) {
8029 int extensions_size = (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
8030 unsigned int profile;
8031 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
8032
8033 if (profile == 0xbede) {
8034 /* We skip over the first 4 bytes as they are just for the one byte extension header */
8035 rtp_instance_parse_extmap_extensions(instance, rtp, read_area + hdrlen + 4, extensions_size);
8036 } else if (DEBUG_ATLEAST(1)) {
8037 if (profile == 0x505a) {
8038 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
8039 } else {
8040 /* SDP negotiated RTP extensions can not currently be output in logging */
8041 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
8042 }
8043 }
8044
8045 hdrlen += extensions_size;
8046 hdrlen += 4;
8047 }
8048
8049 /* Make sure after we potentially mucked with the header length that it is once again valid */
8050 if (res < hdrlen) {
8051 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
8053 }
8054
8055 /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
8056 if (!bundled) {
8057 /* Force a marker bit and change SSRC if the SSRC changes */
8058 if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
8059 struct ast_frame *f, srcupdate = {
8062 };
8063
8064 if (!mark) {
8066 ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance);
8067 }
8068 mark = 1;
8069 }
8070
8071 f = ast_frisolate(&srcupdate);
8073
8074 rtp->seedrxseqno = 0;
8075 rtp->rxcount = 0;
8076 rtp->rxoctetcount = 0;
8077 rtp->cycles = 0;
8078 prev_seqno = 0;
8079 rtp->last_seqno = 0;
8080 rtp->last_end_timestamp.ts = 0;
8081 rtp->last_end_timestamp.is_set = 0;
8082 if (rtp->rtcp) {
8083 rtp->rtcp->expected_prior = 0;
8084 rtp->rtcp->received_prior = 0;
8085 }
8086 }
8087
8088 rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
8089 rtp->themssrc_valid = 1;
8090 }
8091
8092 rtp->rxcount++;
8093 rtp->rxoctetcount += (res - hdrlen);
8094 if (rtp->rxcount == 1) {
8095 rtp->seedrxseqno = seqno;
8096 }
8097
8098 /* Do not schedule RR if RTCP isn't run */
8099 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 0) {
8100 /* Schedule transmission of Receiver Report */
8101 ao2_ref(instance, +1);
8103 if (rtp->rtcp->schedid < 0) {
8104 ao2_ref(instance, -1);
8105 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
8106 }
8107 }
8108 if ((int)prev_seqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
8109 rtp->cycles += RTP_SEQ_MOD;
8110
8111 /* If we are directly bridged to another instance send the audio directly out,
8112 * but only after updating core information about the received traffic so that
8113 * outgoing RTCP reflects it.
8114 */
8115 instance1 = ast_rtp_instance_get_bridged(instance);
8116 if (instance1
8117 && !bridge_p2p_rtp_write(instance, instance1, rtpheader, res, hdrlen)) {
8118 struct timeval rxtime;
8119 struct ast_frame *f;
8120
8121 /* Update statistics for jitter so they are correct in RTCP */
8122 calc_rxstamp_and_jitter(&rxtime, rtp, timestamp, mark);
8123
8124
8125 /* When doing P2P we don't need to raise any frames about SSRC change to the core */
8126 while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list)) != NULL) {
8127 ast_frfree(f);
8128 }
8129
8130 return &ast_null_frame;
8131 }
8132
8133 payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
8134 if (!payload) {
8135 /* Unknown payload type. */
8137 }
8138
8139 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
8140 if (!payload->asterisk_format) {
8141 struct ast_frame *f = NULL;
8142 if (payload->rtp_code == AST_RTP_DTMF) {
8143 /* process_dtmf_rfc2833 may need to return multiple frames. We do this
8144 * by passing the pointer to the frame list to it so that the method
8145 * can append frames to the list as needed.
8146 */
8147 process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames);
8148 } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
8149 f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
8150 } else if (payload->rtp_code == AST_RTP_CN) {
8151 f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
8152 } else {
8153 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
8154 payloadtype,
8155 ast_sockaddr_stringify(remote_address));
8156 }
8157
8158 if (f) {
8160 }
8161 /* Even if no frame was returned by one of the above methods,
8162 * we may have a frame to return in our frame list
8163 */
8165 }
8166
8167 ao2_replace(rtp->lastrxformat, payload->format);
8168 ao2_replace(rtp->f.subclass.format, payload->format);
8169 switch (ast_format_get_type(rtp->f.subclass.format)) {
8172 break;
8175 break;
8177 rtp->f.frametype = AST_FRAME_TEXT;
8178 break;
8180 /* Fall through */
8181 default:
8182 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8184 return &ast_null_frame;
8185 }
8186
8187 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
8188 rtp->dtmf_timeout = 0;
8189
8190 if (rtp->resp) {
8191 struct ast_frame *f;
8192 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
8194 rtp->resp = 0;
8195 rtp->dtmf_timeout = rtp->dtmf_duration = 0;
8197 return AST_LIST_FIRST(&frames);
8198 }
8199 }
8200
8201 rtp->f.src = "RTP";
8202 rtp->f.mallocd = 0;
8203 rtp->f.datalen = res - hdrlen;
8204 rtp->f.data.ptr = read_area + hdrlen;
8205 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
8207 rtp->f.seqno = seqno;
8208 rtp->f.stream_num = rtp->stream_num;
8209
8211 && ((int)seqno - (prev_seqno + 1) > 0)
8212 && ((int)seqno - (prev_seqno + 1) < 10)) {
8213 unsigned char *data = rtp->f.data.ptr;
8214
8215 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
8216 rtp->f.datalen +=3;
8217 *data++ = 0xEF;
8218 *data++ = 0xBF;
8219 *data = 0xBD;
8220 }
8221
8223 unsigned char *data = rtp->f.data.ptr;
8224 unsigned char *header_end;
8225 int num_generations;
8226 int header_length;
8227 int len;
8228 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
8229 int x;
8230
8232 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
8233 if (header_end == NULL) {
8235 }
8236 header_end++;
8237
8238 header_length = header_end - data;
8239 num_generations = header_length / 4;
8240 len = header_length;
8241
8242 if (!diff) {
8243 for (x = 0; x < num_generations; x++)
8244 len += data[x * 4 + 3];
8245
8246 if (!(rtp->f.datalen - len))
8248
8249 rtp->f.data.ptr += len;
8250 rtp->f.datalen -= len;
8251 } else if (diff > num_generations && diff < 10) {
8252 len -= 3;
8253 rtp->f.data.ptr += len;
8254 rtp->f.datalen -= len;
8255
8256 data = rtp->f.data.ptr;
8257 *data++ = 0xEF;
8258 *data++ = 0xBF;
8259 *data = 0xBD;
8260 } else {
8261 for ( x = 0; x < num_generations - diff; x++)
8262 len += data[x * 4 + 3];
8263
8264 rtp->f.data.ptr += len;
8265 rtp->f.datalen -= len;
8266 }
8267 }
8268
8270 rtp->f.samples = ast_codec_samples_count(&rtp->f);
8272 ast_frame_byteswap_be(&rtp->f);
8273 }
8274 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8275 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
8277 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8278 rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
8280 /* Video -- samples is # of samples vs. 90000 */
8281 if (!rtp->lastividtimestamp)
8282 rtp->lastividtimestamp = timestamp;
8283 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8285 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8286 rtp->f.samples = timestamp - rtp->lastividtimestamp;
8287 rtp->lastividtimestamp = timestamp;
8288 rtp->f.delivery.tv_sec = 0;
8289 rtp->f.delivery.tv_usec = 0;
8290 /* Pass the RTP marker bit as bit */
8291 rtp->f.subclass.frame_ending = mark ? 1 : 0;
8293 /* TEXT -- samples is # of samples vs. 1000 */
8294 if (!rtp->lastitexttimestamp)
8295 rtp->lastitexttimestamp = timestamp;
8296 rtp->f.samples = timestamp - rtp->lastitexttimestamp;
8297 rtp->lastitexttimestamp = timestamp;
8298 rtp->f.delivery.tv_sec = 0;
8299 rtp->f.delivery.tv_usec = 0;
8300 } else {
8301 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8303 return &ast_null_frame;
8304 }
8305
8307 return AST_LIST_FIRST(&frames);
8308}
#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
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition format.c:379
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
struct ast_format * ast_format_t140_red
Built-in cached t140 red format.
struct ast_format * ast_format_t140
Built-in cached t140 format.
const char * ext
Definition http.c:151
#define ast_frame_byteswap_be(fr)
@ AST_FRFLAG_HAS_SEQUENCE_NUMBER
@ AST_FRFLAG_HAS_TIMING_INFO
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
@ AST_FRAME_DTMF_END
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define LOG_NOTICE
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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.
#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, ast_frame_subclass::integer, 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 9457 of file res_rtp_asterisk.c.

9458{
9459 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
9460
9461 ao2_lock(instance0);
9463 if (rtp->smoother) {
9465 rtp->smoother = NULL;
9466 }
9467
9468 /* We must use a new SSRC when local bridge ends */
9469 if (!instance1) {
9470 rtp->ssrc = rtp->ssrc_orig;
9471 rtp->ssrc_orig = 0;
9472 rtp->ssrc_saved = 0;
9473 } else if (!rtp->ssrc_saved) {
9474 /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
9475 rtp->ssrc_orig = rtp->ssrc;
9476 rtp->ssrc_saved = 1;
9477 }
9478
9479 ao2_unlock(instance0);
9480
9481 return 0;
9482}
#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 4332 of file res_rtp_asterisk.c.

4335{
4336 struct ast_rtp *rtp = NULL;
4337
4338 /* Create a new RTP structure to hold all of our data */
4339 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
4340 return -1;
4341 }
4342 rtp->owner = instance;
4343 /* Set default parameters on the newly created RTP structure */
4344 rtp->ssrc = ast_random();
4345 ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname));
4346 rtp->seqno = ast_random() & 0xffff;
4347 rtp->expectedrxseqno = -1;
4348 rtp->expectedseqno = -1;
4349 rtp->rxstart = -1;
4350 rtp->sched = sched;
4351 ast_sockaddr_copy(&rtp->bind_address, addr);
4352 /* Transport creation operations can grab the RTP data from the instance, so set it */
4353 ast_rtp_instance_set_data(instance, rtp);
4354
4355 if (rtp_allocate_transport(instance, rtp)) {
4356 return -1;
4357 }
4358
4359 if (AST_VECTOR_INIT(&rtp->ssrc_mapping, 1)) {
4360 return -1;
4361 }
4362
4364 return -1;
4365 }
4366 rtp->transport_wide_cc.schedid = -1;
4367
4371 rtp->stream_num = -1;
4372
4373 return 0;
4374}
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition rtp_engine.c:609
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, 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 9087 of file res_rtp_asterisk.c.

9088{
9089 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9090
9091 if (property == AST_RTP_PROPERTY_RTCP) {
9092 if (value) {
9093 struct ast_sockaddr local_addr;
9094
9095 if (rtp->rtcp && rtp->rtcp->type == value) {
9096 ast_debug_rtcp(1, "(%p) RTCP ignoring duplicate property\n", instance);
9097 return;
9098 }
9099
9100 if (!rtp->rtcp) {
9101 rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
9102 if (!rtp->rtcp) {
9103 return;
9104 }
9105 rtp->rtcp->s = -1;
9106#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9107 rtp->rtcp->dtls.timeout_timer = -1;
9108#endif
9109 rtp->rtcp->schedid = -1;
9110 }
9111
9112 rtp->rtcp->type = value;
9113
9114 /* Grab the IP address and port we are going to use */
9115 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
9118 ast_sockaddr_port(&rtp->rtcp->us) + 1);
9119 }
9120
9121 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
9122 if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
9123 ast_sockaddr_set_port(&local_addr, ast_sockaddr_port(&rtp->rtcp->us));
9124 } else {
9125 /* Failed to get local address reset to use default. */
9126 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
9127 }
9128
9131 if (!rtp->rtcp->local_addr_str) {
9132 ast_free(rtp->rtcp);
9133 rtp->rtcp = NULL;
9134 return;
9135 }
9136
9138 /* We're either setting up RTCP from scratch or
9139 * switching from MUX. Either way, we won't have
9140 * a socket set up, and we need to set it up
9141 */
9142 if ((rtp->rtcp->s = create_new_socket("RTCP", &rtp->rtcp->us)) < 0) {
9143 ast_debug_rtcp(1, "(%p) RTCP failed to create a new socket\n", instance);
9145 ast_free(rtp->rtcp);
9146 rtp->rtcp = NULL;
9147 return;
9148 }
9149
9150 /* 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 */
9151 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
9152 ast_debug_rtcp(1, "(%p) RTCP failed to setup RTP instance\n", instance);
9153 close(rtp->rtcp->s);
9155 ast_free(rtp->rtcp);
9156 rtp->rtcp = NULL;
9157 return;
9158 }
9159#ifdef HAVE_PJPROJECT
9160 if (rtp->ice) {
9161 rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
9162 }
9163#endif
9164#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9165 dtls_setup_rtcp(instance);
9166#endif
9167 } else {
9168 struct ast_sockaddr addr;
9169 /* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
9170 * then close the socket we previously created.
9171 *
9172 * It may seem as though there is a possible race condition here where we might try
9173 * to close the RTCP socket while it is being used to send data. However, this is not
9174 * a problem in practice since setting and adjusting of RTCP properties happens prior
9175 * to activating RTP. It is not until RTP is activated that timers start for RTCP
9176 * transmission
9177 */
9178 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9179 close(rtp->rtcp->s);
9180 }
9181 rtp->rtcp->s = rtp->s;
9182 ast_rtp_instance_get_remote_address(instance, &addr);
9183 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
9184#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9185 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9186 SSL_free(rtp->rtcp->dtls.ssl);
9187 }
9188 rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
9189#endif
9190 }
9191
9192 ast_debug_rtcp(1, "(%s) RTCP setup on RTP instance\n",
9194 } else {
9195 if (rtp->rtcp) {
9196 if (rtp->rtcp->schedid > -1) {
9197 ao2_unlock(instance);
9198 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9199 /* Successfully cancelled scheduler entry. */
9200 ao2_ref(instance, -1);
9201 } else {
9202 /* Unable to cancel scheduler entry */
9203 ast_debug_rtcp(1, "(%p) RTCP failed to tear down RTCP\n", instance);
9204 ao2_lock(instance);
9205 return;
9206 }
9207 ao2_lock(instance);
9208 rtp->rtcp->schedid = -1;
9209 }
9210 if (rtp->transport_wide_cc.schedid > -1) {
9211 ao2_unlock(instance);
9212 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9213 ao2_ref(instance, -1);
9214 } else {
9215 ast_debug_rtcp(1, "(%p) RTCP failed to tear down transport-cc feedback\n", instance);
9216 ao2_lock(instance);
9217 return;
9218 }
9219 ao2_lock(instance);
9220 rtp->transport_wide_cc.schedid = -1;
9221 }
9222 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9223 close(rtp->rtcp->s);
9224 }
9225#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9226 ao2_unlock(instance);
9227 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9228 ao2_lock(instance);
9229
9230 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9231 SSL_free(rtp->rtcp->dtls.ssl);
9232 }
9233#endif
9235 ast_free(rtp->rtcp);
9236 rtp->rtcp = NULL;
9237 ast_debug_rtcp(1, "(%s) RTCP torn down on RTP instance\n",
9239 }
9240 }
9241 } else if (property == AST_RTP_PROPERTY_ASYMMETRIC_CODEC) {
9242 rtp->asymmetric_codec = value;
9243 } else if (property == AST_RTP_PROPERTY_RETRANS_SEND) {
9244 if (value) {
9245 if (!rtp->send_buffer) {
9247 }
9248 } else {
9249 if (rtp->send_buffer) {
9251 rtp->send_buffer = NULL;
9252 }
9253 }
9254 } else if (property == AST_RTP_PROPERTY_RETRANS_RECV) {
9255 if (value) {
9256 if (!rtp->recv_buffer) {
9259 }
9260 } else {
9261 if (rtp->recv_buffer) {
9263 rtp->recv_buffer = NULL;
9265 }
9266 }
9267 }
9268}
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.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition netsock2.h:517
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, struct ast_sockaddr *bind_addr)
#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:694
@ 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
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_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 9633 of file res_rtp_asterisk.c.

9634{
9635 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9636
9637 return ast_set_qos(rtp->s, tos, cos, desc);
9638}
static const char desc[]
Definition cdr_radius.c:84
unsigned int tos
Definition chan_iax2.c:392
unsigned int cos
Definition chan_iax2.c:393
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 8420 of file res_rtp_asterisk.c.

8421{
8422 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8423 struct ast_srtp *srtp;
8425 struct ast_sockaddr addr;
8426 int res, hdrlen = 12, version, payloadtype;
8427 unsigned char *read_area = rtp->rawdata + AST_FRIENDLY_OFFSET;
8428 size_t read_area_size = sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET;
8429 unsigned int *rtpheader = (unsigned int*)(read_area), seqno, ssrc, timestamp, prev_seqno;
8430 struct ast_sockaddr remote_address = { {0,} };
8431 struct frame_list frames;
8432 struct ast_frame *frame;
8433 unsigned int bundled;
8434
8435 /* If this is actually RTCP let's hop on over and handle it */
8436 if (rtcp) {
8437 if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
8438 return ast_rtcp_read(instance);
8439 }
8440 return &ast_null_frame;
8441 }
8442
8443 /* Actually read in the data from the socket */
8444 if ((res = rtp_recvfrom(instance, read_area, read_area_size, 0,
8445 &addr)) < 0) {
8446 if (res == RTP_DTLS_ESTABLISHED) {
8449 return &rtp->f;
8450 }
8451
8452 ast_assert(errno != EBADF);
8453 if (errno != EAGAIN) {
8454 ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n",
8455 (errno) ? strerror(errno) : "Unspecified");
8456 return NULL;
8457 }
8458 return &ast_null_frame;
8459 }
8460
8461 /* If this was handled by the ICE session don't do anything */
8462 if (!res) {
8463 return &ast_null_frame;
8464 }
8465
8466 /* This could be a multiplexed RTCP packet. If so, be sure to interpret it correctly */
8467 if (rtcp_mux(rtp, read_area)) {
8468 return ast_rtcp_interpret(instance, ast_rtp_instance_get_srtp(instance, 1), read_area, res, &addr);
8469 }
8470
8471 /* Make sure the data that was read in is actually enough to make up an RTP packet */
8472 if (res < hdrlen) {
8473 /* If this is a keepalive containing only nulls, don't bother with a warning */
8474 int i;
8475 for (i = 0; i < res; ++i) {
8476 if (read_area[i] != '\0') {
8477 ast_log(LOG_WARNING, "RTP Read too short\n");
8478 return &ast_null_frame;
8479 }
8480 }
8481 return &ast_null_frame;
8482 }
8483
8484 /* Get fields and verify this is an RTP packet */
8485 seqno = ntohl(rtpheader[0]);
8486
8487 ast_rtp_instance_get_remote_address(instance, &remote_address);
8488
8489 if (!(version = (seqno & 0xC0000000) >> 30)) {
8490 struct sockaddr_in addr_tmp;
8491 struct ast_sockaddr addr_v4;
8492 if (ast_sockaddr_is_ipv4(&addr)) {
8493 ast_sockaddr_to_sin(&addr, &addr_tmp);
8494 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
8495 ast_debug_stun(1, "(%p) STUN using IPv6 mapped address %s\n",
8496 instance, ast_sockaddr_stringify(&addr));
8497 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
8498 } else {
8499 ast_debug_stun(1, "(%p) STUN cannot do for non IPv4 address %s\n",
8500 instance, ast_sockaddr_stringify(&addr));
8501 return &ast_null_frame;
8502 }
8503 if ((ast_stun_handle_packet(rtp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT) &&
8504 ast_sockaddr_isnull(&remote_address)) {
8505 ast_sockaddr_from_sin(&addr, &addr_tmp);
8506 ast_rtp_instance_set_remote_address(instance, &addr);
8507 }
8508 return &ast_null_frame;
8509 }
8510
8511 /* If the version is not what we expected by this point then just drop the packet */
8512 if (version != 2) {
8513 return &ast_null_frame;
8514 }
8515
8516 /* We use the SSRC to determine what RTP instance this packet is actually for */
8517 ssrc = ntohl(rtpheader[2]);
8518
8519 /* We use the SRTP data from the provided instance that it came in on, not the child */
8520 srtp = ast_rtp_instance_get_srtp(instance, 0);
8521
8522 /* Determine the appropriate instance for this */
8523 child = rtp_find_instance_by_packet_source_ssrc(instance, rtp, ssrc);
8524 if (!child) {
8525 /* Neither the bundled parent nor any child has this SSRC */
8526 return &ast_null_frame;
8527 }
8528 if (child != instance) {
8529 /* It is safe to hold the child lock while holding the parent lock, we guarantee that the locking order
8530 * is always parent->child or that the child lock is not held when acquiring the parent lock.
8531 */
8532 ao2_lock(child);
8533 instance = child;
8534 rtp = ast_rtp_instance_get_data(instance);
8535 } else {
8536 /* The child is the parent! We don't need to unlock it. */
8537 child = NULL;
8538 }
8539
8540 /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
8541 switch (rtp->strict_rtp_state) {
8542 case STRICT_RTP_LEARN:
8543 /*
8544 * Scenario setup:
8545 * PartyA -- Ast1 -- Ast2 -- PartyB
8546 *
8547 * The learning timeout is necessary for Ast1 to handle the above
8548 * setup where PartyA calls PartyB and Ast2 initiates direct media
8549 * between Ast1 and PartyB. Ast1 may lock onto the Ast2 stream and
8550 * never learn the PartyB stream when it starts. The timeout makes
8551 * Ast1 stay in the learning state long enough to see and learn the
8552 * RTP stream from PartyB.
8553 *
8554 * To mitigate against attack, the learning state cannot switch
8555 * streams while there are competing streams. The competing streams
8556 * interfere with each other's qualification. Once we accept a
8557 * stream and reach the timeout, an attacker cannot interfere
8558 * anymore.
8559 *
8560 * Here are a few scenarios and each one assumes that the streams
8561 * are continuous:
8562 *
8563 * 1) We already have a known stream source address and the known
8564 * stream wants to change to a new source address. An attacking
8565 * stream will block learning the new stream source. After the
8566 * timeout we re-lock onto the original stream source address which
8567 * likely went away. The result is one way audio.
8568 *
8569 * 2) We already have a known stream source address and the known
8570 * stream doesn't want to change source addresses. An attacking
8571 * stream will not be able to replace the known stream. After the
8572 * timeout we re-lock onto the known stream. The call is not
8573 * affected.
8574 *
8575 * 3) We don't have a known stream source address. This presumably
8576 * is the start of a call. Competing streams will result in staying
8577 * in learning mode until a stream becomes the victor and we reach
8578 * the timeout. We cannot exit learning if we have no known stream
8579 * to lock onto. The result is one way audio until there is a victor.
8580 *
8581 * If we learn a stream source address before the timeout we will be
8582 * in scenario 1) or 2) when a competing stream starts.
8583 */
8586 ast_verb(4, "%p -- Strict RTP learning complete - Locking on source address %s\n",
8588 ast_test_suite_event_notify("STRICT_RTP_LEARN", "Source: %s",
8591 } else {
8592 struct ast_sockaddr target_address;
8593
8594 if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
8595 /*
8596 * We are open to learning a new address but have received
8597 * traffic from the current address, accept it and reset
8598 * the learning counts for a new source. When no more
8599 * current source packets arrive a new source can take over
8600 * once sufficient traffic is received.
8601 */
8603 break;
8604 }
8605
8606 /*
8607 * We give preferential treatment to the requested target address
8608 * (negotiated SDP address) where we are to send our RTP. However,
8609 * the other end has no obligation to send from that address even
8610 * though it is practically a requirement when NAT is involved.
8611 */
8612 ast_rtp_instance_get_requested_target_address(instance, &target_address);
8613 if (!ast_sockaddr_cmp(&target_address, &addr)) {
8614 /* Accept the negotiated target RTP stream as the source */
8615 ast_verb(4, "%p -- Strict RTP switching to RTP target address %s as source\n",
8616 rtp, ast_sockaddr_stringify(&addr));
8619 break;
8620 }
8621
8622 /*
8623 * Trying to learn a new address. If we pass a probationary period
8624 * with it, that means we've stopped getting RTP from the original
8625 * source and we should switch to it.
8626 */
8629 struct ast_rtp_codecs *codecs;
8630
8634 ast_verb(4, "%p -- Strict RTP qualifying stream type: %s\n",
8636 }
8637 if (!rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
8638 /* Accept the new RTP stream */
8639 ast_verb(4, "%p -- Strict RTP switching source address to %s\n",
8640 rtp, ast_sockaddr_stringify(&addr));
8643 break;
8644 }
8645 /* Not ready to accept the RTP stream candidate */
8646 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",
8647 instance, rtp, ast_sockaddr_stringify(&addr), rtp->rtp_source_learn.packets);
8648 } else {
8649 /*
8650 * This is either an attacking stream or
8651 * the start of the expected new stream.
8652 */
8655 ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection. Qualifying new stream.\n",
8656 instance, rtp, ast_sockaddr_stringify(&addr));
8657 }
8658 return &ast_null_frame;
8659 }
8660 /* Fall through */
8661 case STRICT_RTP_CLOSED:
8662 /*
8663 * We should not allow a stream address change if the SSRC matches
8664 * once strictrtp learning is closed. Any kind of address change
8665 * like this should have happened while we were in the learning
8666 * state. We do not want to allow the possibility of an attacker
8667 * interfering with the RTP stream after the learning period.
8668 * An attacker could manage to get an RTCP packet redirected to
8669 * them which can contain the SSRC value.
8670 */
8671 if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
8672 break;
8673 }
8674 ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection.\n",
8675 instance, rtp, ast_sockaddr_stringify(&addr));
8676#ifdef TEST_FRAMEWORK
8677 {
8678 static int strict_rtp_test_event = 1;
8679 if (strict_rtp_test_event) {
8680 ast_test_suite_event_notify("STRICT_RTP_CLOSED", "Source: %s",
8681 ast_sockaddr_stringify(&addr));
8682 strict_rtp_test_event = 0; /* Only run this event once to prevent possible spam */
8683 }
8684 }
8685#endif
8686 return &ast_null_frame;
8687 case STRICT_RTP_OPEN:
8688 break;
8689 }
8690
8691 /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
8693 if (ast_sockaddr_cmp(&remote_address, &addr)) {
8694 /* do not update the originally given address, but only the remote */
8696 ast_sockaddr_copy(&remote_address, &addr);
8697 if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
8698 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
8700 }
8703 ast_debug(0, "(%p) RTP NAT: Got audio from other end. Now sending to address %s\n",
8704 instance, ast_sockaddr_stringify(&remote_address));
8705 }
8706 }
8707
8708 /* Pull out the various other fields we will need */
8709 payloadtype = (seqno & 0x7f0000) >> 16;
8710 seqno &= 0xffff;
8711 timestamp = ntohl(rtpheader[1]);
8712
8713#ifdef AST_DEVMODE
8714 if (should_drop_packets(&addr)) {
8715 ast_debug(0, "(%p) RTP: drop received packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
8716 instance, ast_sockaddr_stringify(&addr), payloadtype, seqno, timestamp, res - hdrlen);
8717 return &ast_null_frame;
8718 }
8719#endif
8720
8721 if (rtp_debug_test_addr(&addr)) {
8722 ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
8724 payloadtype, seqno, timestamp, res - hdrlen);
8725 }
8726
8728
8729 bundled = (child || AST_VECTOR_SIZE(&rtp->ssrc_mapping)) ? 1 : 0;
8730
8731 prev_seqno = rtp->lastrxseqno;
8732 /* We need to save lastrxseqno for use by jitter before resetting it. */
8733 rtp->prevrxseqno = rtp->lastrxseqno;
8734 rtp->lastrxseqno = seqno;
8735
8736 if (!rtp->recv_buffer) {
8737 /* If there is no receive buffer then we can pass back the frame directly */
8738 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8740 return AST_LIST_FIRST(&frames);
8741 } else if (rtp->expectedrxseqno == -1 || seqno == rtp->expectedrxseqno) {
8742 rtp->expectedrxseqno = seqno + 1;
8743
8744 /* We've cycled over, so go back to 0 */
8745 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8746 rtp->expectedrxseqno = 0;
8747 }
8748
8749 /* If there are no buffered packets that will be placed after this frame then we can
8750 * return it directly without duplicating it.
8751 */
8753 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8755 return AST_LIST_FIRST(&frames);
8756 }
8757
8760 ast_debug_rtp(2, "(%p) RTP Packet with sequence number '%d' on instance is no longer missing\n",
8761 instance, seqno);
8762 }
8763
8764 /* If we don't have the next packet after this we can directly return the frame, as there is no
8765 * chance it will be overwritten.
8766 */
8768 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8770 return AST_LIST_FIRST(&frames);
8771 }
8772
8773 /* Otherwise we need to dupe the frame so that the potential processing of frames placed after
8774 * it do not overwrite the data. You may be thinking that we could just add the current packet
8775 * to the head of the frames list and avoid having to duplicate it but this would result in out
8776 * of order packet processing by libsrtp which we are trying to avoid.
8777 */
8778 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled));
8779 if (frame) {
8781 prev_seqno = seqno;
8782 }
8783
8784 /* Add any additional packets that we have buffered and that are available */
8785 while (ast_data_buffer_count(rtp->recv_buffer)) {
8786 struct ast_rtp_rtcp_nack_payload *payload;
8787
8789 if (!payload) {
8790 break;
8791 }
8792
8793 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled));
8794 ast_free(payload);
8795
8796 if (!frame) {
8797 /* If this packet can't be interpreted due to being out of memory we return what we have and assume
8798 * that we will determine it is a missing packet later and NACK for it.
8799 */
8800 return AST_LIST_FIRST(&frames);
8801 }
8802
8803 ast_debug_rtp(2, "(%p) RTP pulled buffered packet with sequence number '%d' to additionally return\n",
8804 instance, frame->seqno);
8806 prev_seqno = rtp->expectedrxseqno;
8807 rtp->expectedrxseqno++;
8808 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8809 rtp->expectedrxseqno = 0;
8810 }
8811 }
8812
8813 return AST_LIST_FIRST(&frames);
8814 } else if ((((seqno - rtp->expectedrxseqno) > 100) && timestamp > rtp->lastividtimestamp) ||
8816 int inserted = 0;
8817
8818 /* We have a large number of outstanding buffered packets or we've jumped far ahead in time.
8819 * To compensate we dump what we have in the buffer and place the current packet in a logical
8820 * spot. In the case of video we also require a full frame to give the decoding side a fighting
8821 * chance.
8822 */
8823
8825 ast_debug_rtp(2, "(%p) RTP source has wild gap or packet loss, sending FIR\n",
8826 instance);
8827 rtp_write_rtcp_fir(instance, rtp, &remote_address);
8828 }
8829
8830 /* This works by going through the progression of the sequence number retrieving buffered packets
8831 * or inserting the current received packet until we've run out of packets. This ensures that the
8832 * packets are in the correct sequence number order.
8833 */
8834 while (ast_data_buffer_count(rtp->recv_buffer)) {
8835 struct ast_rtp_rtcp_nack_payload *payload;
8836
8837 /* If the packet we received is the one we are expecting at this point then add it in */
8838 if (rtp->expectedrxseqno == seqno) {
8839 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled));
8840 if (frame) {
8842 prev_seqno = seqno;
8843 ast_debug_rtp(2, "(%p) RTP inserted just received packet with sequence number '%d' in correct order\n",
8844 instance, seqno);
8845 }
8846 /* It is possible due to packet retransmission for this packet to also exist in the receive
8847 * buffer so we explicitly remove it in case this occurs, otherwise the receive buffer will
8848 * never be empty.
8849 */
8850 payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_remove(rtp->recv_buffer, seqno);
8851 if (payload) {
8852 ast_free(payload);
8853 }
8854 rtp->expectedrxseqno++;
8855 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8856 rtp->expectedrxseqno = 0;
8857 }
8858 inserted = 1;
8859 continue;
8860 }
8861
8863 if (payload) {
8864 frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled));
8865 if (frame) {
8867 prev_seqno = rtp->expectedrxseqno;
8868 ast_debug_rtp(2, "(%p) RTP emptying queue and returning packet with sequence number '%d'\n",
8869 instance, frame->seqno);
8870 }
8871 ast_free(payload);
8872 }
8873
8874 rtp->expectedrxseqno++;
8875 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8876 rtp->expectedrxseqno = 0;
8877 }
8878 }
8879
8880 if (!inserted) {
8881 /* This current packet goes after them, and we assume that packets going forward will follow
8882 * that new sequence number increment. It is okay for this to not be duplicated as it is guaranteed
8883 * to be the last packet processed right now and it is also guaranteed that it will always return
8884 * non-NULL.
8885 */
8886 frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8888 rtp->expectedrxseqno = seqno + 1;
8889 if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8890 rtp->expectedrxseqno = 0;
8891 }
8892
8893 ast_debug_rtp(2, "(%p) RTP adding just received packet with sequence number '%d' to end of dumped queue\n",
8894 instance, seqno);
8895 }
8896
8897 /* When we flush increase our chance for next time by growing the receive buffer when possible
8898 * by how many packets we missed, to give ourselves a bit more breathing room.
8899 */
8902 ast_debug_rtp(2, "(%p) RTP receive buffer is now at maximum of %zu\n", instance, ast_data_buffer_max(rtp->recv_buffer));
8903
8904 /* As there is such a large gap we don't want to flood the order side with missing packets, so we
8905 * give up and start anew.
8906 */
8908
8909 return AST_LIST_FIRST(&frames);
8910 }
8911
8912 /* We're finished with the frames list */
8914
8915 /* Determine if the received packet is from the last OLD_PACKET_COUNT (1000 by default) packets or not.
8916 * For the case where the received sequence number exceeds that of the expected sequence number we calculate
8917 * the past sequence number that would be 1000 sequence numbers ago. If the received sequence number
8918 * exceeds or meets that then it is within OLD_PACKET_COUNT packets ago. For example if the expected
8919 * sequence number is 100 and we receive 65530, then it would be considered old. This is because
8920 * 65535 - 1000 + 100 = 64635 which gives us the sequence number at which we would consider the packets
8921 * old. Since 65530 is above that, it would be considered old.
8922 * For the case where the received sequence number is less than the expected sequence number we can do
8923 * a simple subtraction to see if it is 1000 packets ago or not.
8924 */
8925 if ((seqno < rtp->expectedrxseqno && ((rtp->expectedrxseqno - seqno) <= OLD_PACKET_COUNT)) ||
8926 (seqno > rtp->expectedrxseqno && (seqno >= (65535 - OLD_PACKET_COUNT + rtp->expectedrxseqno)))) {
8927 /* If this is a packet from the past then we have received a duplicate packet, so just drop it */
8928 ast_debug_rtp(2, "(%p) RTP received an old packet with sequence number '%d', dropping it\n",
8929 instance, seqno);
8930 return &ast_null_frame;
8931 } else if (ast_data_buffer_get(rtp->recv_buffer, seqno)) {
8932 /* If this is a packet we already have buffered then it is a duplicate, so just drop it */
8933 ast_debug_rtp(2, "(%p) RTP received a duplicate transmission of packet with sequence number '%d', dropping it\n",
8934 instance, seqno);
8935 return &ast_null_frame;
8936 } else {
8937 /* This is an out of order packet from the future */
8938 struct ast_rtp_rtcp_nack_payload *payload;
8939 int missing_seqno;
8940 int remove_failed;
8941 unsigned int missing_seqnos_added = 0;
8942
8943 ast_debug_rtp(2, "(%p) RTP received an out of order packet with sequence number '%d' while expecting '%d' from the future\n",
8944 instance, seqno, rtp->expectedrxseqno);
8945
8946 payload = ast_malloc(sizeof(*payload) + res);
8947 if (!payload) {
8948 /* If the payload can't be allocated then we can't defer this packet right now.
8949 * Instead of dumping what we have we pretend we lost this packet. It will then
8950 * get NACKed later or the existing buffer will be returned entirely. Well, we may
8951 * try since we're seemingly out of memory. It's a bad situation all around and
8952 * packets are likely to get lost anyway.
8953 */
8954 return &ast_null_frame;
8955 }
8956
8957 payload->size = res;
8958 memcpy(payload->buf, rtpheader, res);
8959 if (ast_data_buffer_put(rtp->recv_buffer, seqno, payload) == -1) {
8960 ast_free(payload);
8961 }
8962
8963 /* If this sequence number is removed that means we had a gap and this packet has filled it in
8964 * some. Since it was part of the gap we will have already added any other missing sequence numbers
8965 * before it (and possibly after it) to the vector so we don't need to do that again. Note that
8966 * remove_failed will be set to -1 if the sequence number isn't removed, and 0 if it is.
8967 */
8968 remove_failed = AST_VECTOR_REMOVE_CMP_ORDERED(&rtp->missing_seqno, seqno, find_by_value,
8970 if (!remove_failed) {
8971 ast_debug_rtp(2, "(%p) RTP packet with sequence number '%d' is no longer missing\n",
8972 instance, seqno);
8973 }
8974
8975 /* The missing sequence number code works by taking the sequence number of the
8976 * packet we've just received and going backwards until we hit the sequence number
8977 * of the last packet we've received. While doing so we check to make sure that the
8978 * sequence number is not already missing and that it is not already buffered.
8979 */
8980 missing_seqno = seqno;
8981 while (remove_failed) {
8982 missing_seqno -= 1;
8983
8984 /* If we've cycled backwards then start back at the top */
8985 if (missing_seqno < 0) {
8986 missing_seqno = 65535;
8987 }
8988
8989 /* We've gone backwards enough such that we've hit the previous sequence number */
8990 if (missing_seqno == prev_seqno) {
8991 break;
8992 }
8993
8994 /* We don't want missing sequence number duplicates. If, for some reason,
8995 * packets are really out of order, we could end up in this scenario:
8996 *
8997 * We are expecting sequence number 100
8998 * We receive sequence number 105
8999 * Sequence numbers 100 through 104 get added to the vector
9000 * We receive sequence number 101 (this section is skipped)
9001 * We receive sequence number 103
9002 * Sequence number 102 is added to the vector
9003 *
9004 * This will prevent the duplicate from being added.
9005 */
9006 if (AST_VECTOR_GET_CMP(&rtp->missing_seqno, missing_seqno,
9007 find_by_value)) {
9008 continue;
9009 }
9010
9011 /* If this packet has been buffered already then don't count it amongst the
9012 * missing.
9013 */
9014 if (ast_data_buffer_get(rtp->recv_buffer, missing_seqno)) {
9015 continue;
9016 }
9017
9018 ast_debug_rtp(2, "(%p) RTP added missing sequence number '%d'\n",
9019 instance, missing_seqno);
9020 AST_VECTOR_ADD_SORTED(&rtp->missing_seqno, missing_seqno,
9022 missing_seqnos_added++;
9023 }
9024
9025 /* When we add a large number of missing sequence numbers we assume there was a substantial
9026 * gap in reception so we trigger an immediate NACK. When our data buffer is 1/4 full we
9027 * assume that the packets aren't just out of order but have actually been lost. At 1/2
9028 * full we get more aggressive and ask for retransmission when we get a new packet.
9029 * To get them back we construct and send a NACK causing the sender to retransmit them.
9030 */
9031 if (missing_seqnos_added >= MISSING_SEQNOS_ADDED_TRIGGER ||
9034 int packet_len = 0;
9035 int res = 0;
9036 int ice;
9037 int sr;
9038 size_t data_size = AST_UUID_STR_LEN + 128 + (AST_VECTOR_SIZE(&rtp->missing_seqno) * 4);
9039 RAII_VAR(unsigned char *, rtcpheader, NULL, ast_free_ptr);
9040 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
9042 ao2_cleanup);
9043
9044 /* Sufficient space for RTCP headers and report, SDES with CNAME, NACK header,
9045 * and worst case 4 bytes per missing sequence number.
9046 */
9047 rtcpheader = ast_malloc(sizeof(*rtcpheader) + data_size);
9048 if (!rtcpheader) {
9049 ast_debug_rtcp(1, "(%p) RTCP failed to allocate memory for NACK\n", instance);
9050 return &ast_null_frame;
9051 }
9052
9053 memset(rtcpheader, 0, data_size);
9054
9055 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
9056
9057 if (res == 0 || res == 1) {
9058 return &ast_null_frame;
9059 }
9060
9061 packet_len += res;
9062
9063 res = ast_rtcp_generate_nack(instance, rtcpheader + packet_len);
9064
9065 if (res == 0) {
9066 ast_debug_rtcp(1, "(%p) RTCP failed to construct NACK, stopping here\n", instance);
9067 return &ast_null_frame;
9068 }
9069
9070 packet_len += res;
9071
9072 res = rtcp_sendto(instance, rtcpheader, packet_len, 0, &remote_address, &ice);
9073 if (res < 0) {
9074 ast_debug_rtcp(1, "(%p) RTCP failed to send NACK request out\n", instance);
9075 } else {
9076 ast_debug_rtcp(2, "(%p) RTCP sending a NACK request to get missing packets\n", instance);
9077 /* Update RTCP SR/RR statistics */
9078 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
9079 }
9080 }
9081 }
9082
9083 return &ast_null_frame;
9084}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
static char version[AST_MAX_EXTENSION]
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.
size_t ast_data_buffer_count(const struct ast_data_buffer *buffer)
Return the number of payloads in a data buffer.
void ast_data_buffer_resize(struct ast_data_buffer *buffer, size_t size)
Resize a data buffer.
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.
size_t ast_data_buffer_max(const struct ast_data_buffer *buffer)
Return the maximum number of payloads a data buffer can hold.
void * ast_data_buffer_remove(struct ast_data_buffer *buffer, size_t pos)
Remove a data payload from the data buffer.
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.
void ast_rtp_instance_get_requested_target_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the requested target address of the remote endpoint.
Definition rtp_engine.c:724
int ast_rtp_instance_set_incoming_source_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the incoming source address of the remote endpoint that we are sending RTP to.
Definition rtp_engine.c:657
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:252
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition vector.h:653
#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:568
#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 9279 of file res_rtp_asterisk.c.

9280{
9281 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9282 struct ast_sockaddr local;
9283 int index;
9284
9285 ast_rtp_instance_get_local_address(instance, &local);
9286 if (!ast_sockaddr_isnull(addr)) {
9287 /* Update the local RTP address with what is being used */
9288 if (ast_ouraddrfor(addr, &local)) {
9289 /* Failed to update our address so reuse old local address */
9290 ast_rtp_instance_get_local_address(instance, &local);
9291 } else {
9292 ast_rtp_instance_set_local_address(instance, &local);
9293 }
9294 }
9295
9296 if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
9297 ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
9298 ast_sockaddr_copy(&rtp->rtcp->them, addr);
9299
9302
9303 /* Update the local RTCP address with what is being used */
9304 ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
9305 }
9306 ast_sockaddr_copy(&rtp->rtcp->us, &local);
9307
9310 }
9311
9312 /* Update any bundled RTP instances */
9313 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
9314 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
9315
9317 }
9318
9319 /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
9320 rtp->last_seqno = 0;
9321 rtp->last_end_timestamp.ts = 0;
9322 rtp->last_end_timestamp.is_set = 0;
9323
9325 && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
9326 /* We only need to learn a new strict source address if we've been told the source is
9327 * changing to something different.
9328 */
9329 ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
9330 rtp, ast_sockaddr_stringify(addr));
9331 rtp_learning_start(rtp);
9332 }
9333}
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:639

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 6689 of file res_rtp_asterisk.c.

6691{
6692 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6693 int res = 0;
6694 int blp_index;
6695 int packet_index;
6696 int ice;
6697 struct ast_rtp_rtcp_nack_payload *payload;
6698 unsigned int current_word;
6699 unsigned int pid; /* Packet ID which refers to seqno of lost packet */
6700 unsigned int blp; /* Bitmask of following lost packets */
6701 struct ast_sockaddr remote_address = { {0,} };
6702 int abs_send_time_id;
6703 unsigned int now_msw = 0;
6704 unsigned int now_lsw = 0;
6705 unsigned int packets_not_found = 0;
6706
6707 if (!rtp->send_buffer) {
6708 ast_debug_rtcp(1, "(%p) RTCP tried to handle NACK request, "
6709 "but we don't have a RTP packet storage!\n", instance);
6710 return res;
6711 }
6712
6714 if (abs_send_time_id != -1) {
6715 timeval2ntp(ast_tvnow(), &now_msw, &now_lsw);
6716 }
6717
6718 ast_rtp_instance_get_remote_address(instance, &remote_address);
6719
6720 /*
6721 * We use index 3 because with feedback messages, the FCI (Feedback Control Information)
6722 * does not begin until after the version, packet SSRC, and media SSRC words.
6723 */
6724 for (packet_index = 3; packet_index < length; packet_index++) {
6725 current_word = ntohl(nackdata[position + packet_index]);
6726 pid = current_word >> 16;
6727 /* We know the remote end is missing this packet. Go ahead and send it if we still have it. */
6728 payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_get(rtp->send_buffer, pid);
6729 if (payload) {
6730 if (abs_send_time_id != -1) {
6731 /* On retransmission we need to update the timestamp within the packet, as it
6732 * is supposed to contain when the packet was actually sent.
6733 */
6734 put_unaligned_time24(payload->buf + 17, now_msw, now_lsw);
6735 }
6736 res += rtp_sendto(instance, payload->buf, payload->size, 0, &remote_address, &ice);
6737 } else {
6738 ast_debug_rtcp(1, "(%p) RTCP received NACK request for RTP packet with seqno %d, "
6739 "but we don't have it\n", instance, pid);
6740 packets_not_found++;
6741 }
6742 /*
6743 * The bitmask. Denoting the least significant bit as 1 and its most significant bit
6744 * as 16, then bit i of the bitmask is set to 1 if the receiver has not received RTP
6745 * packet (pid+i)(modulo 2^16). Otherwise, it is set to 0. We cannot assume bits set
6746 * to 0 after a bit set to 1 have actually been received.
6747 */
6748 blp = current_word & 0xffff;
6749 blp_index = 1;
6750 while (blp) {
6751 if (blp & 1) {
6752 /* Packet (pid + i)(modulo 2^16) is missing too. */
6753 unsigned int seqno = (pid + blp_index) % 65536;
6754 payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_get(rtp->send_buffer, seqno);
6755 if (payload) {
6756 if (abs_send_time_id != -1) {
6757 put_unaligned_time24(payload->buf + 17, now_msw, now_lsw);
6758 }
6759 res += rtp_sendto(instance, payload->buf, payload->size, 0, &remote_address, &ice);
6760 } else {
6761 ast_debug_rtcp(1, "(%p) RTCP remote end also requested RTP packet with seqno %d, "
6762 "but we don't have it\n", instance, seqno);
6763 packets_not_found++;
6764 }
6765 }
6766 blp >>= 1;
6767 blp_index++;
6768 }
6769 }
6770
6771 if (packets_not_found) {
6772 /* Grow the send buffer based on how many packets were not found in the buffer, but
6773 * enforce a maximum.
6774 */
6776 ast_data_buffer_max(rtp->send_buffer) + packets_not_found));
6777 ast_debug_rtcp(2, "(%p) RTCP send buffer on RTP instance is now at maximum of %zu\n",
6778 instance, ast_data_buffer_max(rtp->send_buffer));
6779 }
6780
6781 return res;
6782}
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:937

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_rtp_rtcp_handle_nack_locking().

◆ ast_rtp_rtcp_handle_nack_locking()

static int ast_rtp_rtcp_handle_nack_locking ( struct ast_rtp_instance *  instance,
struct ast_rtp_instance *  transport,
unsigned int *  nackdata,
unsigned int  position,
unsigned int  length 
)
static

Definition at line 6788 of file res_rtp_asterisk.c.

6794{
6795 int res;
6796
6797 if (!transport || transport == instance) {
6798 return ast_rtp_rtcp_handle_nack(instance, nackdata, position, length);
6799 }
6800
6801 ao2_ref(instance, +1);
6802 ao2_ref(transport, +1);
6803
6804 /* Release child then parent; reacquire parent then child. */
6805 ao2_unlock(instance);
6806 ao2_unlock(transport);
6807 ao2_lock(instance);
6808
6809 res = ast_rtp_rtcp_handle_nack(instance, nackdata, position, length);
6810
6811 ao2_unlock(instance);
6812 ao2_lock(transport);
6813 ao2_lock(instance);
6814
6815 ao2_ref(transport, -1);
6816 ao2_ref(instance, -1);
6817
6818 return res;
6819}
static int ast_rtp_rtcp_handle_nack(struct ast_rtp_instance *instance, unsigned int *nackdata, unsigned int position, unsigned int length)

References ao2_lock, ao2_ref, ao2_unlock, and ast_rtp_rtcp_handle_nack().

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 9645 of file res_rtp_asterisk.c.

9646{
9647 unsigned int *rtpheader;
9648 int hdrlen = 12;
9649 int res, payload = 0;
9650 char data[256];
9651 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9652 struct ast_sockaddr remote_address = { {0,} };
9653 int ice;
9654
9655 ast_rtp_instance_get_remote_address(instance, &remote_address);
9656
9657 if (ast_sockaddr_isnull(&remote_address)) {
9658 return -1;
9659 }
9660
9662
9663 level = 127 - (level & 0x7f);
9664
9665 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
9666
9667 /* Get a pointer to the header */
9668 rtpheader = (unsigned int *)data;
9669 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
9670 rtpheader[1] = htonl(rtp->lastts);
9671 rtpheader[2] = htonl(rtp->ssrc);
9672 data[12] = level;
9673
9674 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);
9675
9676 if (res < 0) {
9677 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
9678 return res;
9679 }
9680
9681 if (rtp_debug_test_addr(&remote_address)) {
9682 ast_verbose("Sent Comfort Noise RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
9683 ast_sockaddr_stringify(&remote_address),
9684 ice ? " (via ICE)" : "",
9685 AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
9686 }
9687
9688 rtp->seqno++;
9689
9690 return res;
9691}

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 9710 of file res_rtp_asterisk.c.

9711{
9712 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9713
9714 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
9715 return;
9716 }
9717
9718 rtp->themssrc = ssrc;
9719 rtp->themssrc_valid = 1;
9720
9721 /* If this is bundled we need to update the SSRC mapping */
9722 if (rtp->bundled) {
9723 struct ast_rtp *bundled_rtp;
9724 int index;
9725
9726 ao2_unlock(instance);
9727
9728 /* The child lock can't be held while accessing the parent */
9729 ao2_lock(rtp->bundled);
9730 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
9731
9732 for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
9733 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
9734
9735 if (mapping->instance == instance) {
9736 mapping->ssrc = ssrc;
9737 mapping->ssrc_valid = 1;
9738 break;
9739 }
9740 }
9741
9742 ao2_unlock(rtp->bundled);
9743
9745 }
9746}

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 9748 of file res_rtp_asterisk.c.

9749{
9750 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9751
9752 rtp->stream_num = stream_num;
9753}

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 9582 of file res_rtp_asterisk.c.

9583{
9584 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9585 struct ast_sockaddr addr = { {0,} };
9586
9587#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9588 ao2_unlock(instance);
9589 AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
9590
9591 dtls_srtp_stop_timeout_timer(instance, rtp, 0);
9592 if (rtp->rtcp) {
9593 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9594 }
9595 ao2_lock(instance);
9596#endif
9597 ast_debug_rtp(1, "(%s) RTP Stop\n",
9599
9600 if (rtp->rtcp && rtp->rtcp->schedid > -1) {
9601 ao2_unlock(instance);
9602 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9603 /* successfully cancelled scheduler entry. */
9604 ao2_ref(instance, -1);
9605 }
9606 ao2_lock(instance);
9607 rtp->rtcp->schedid = -1;
9608 }
9609
9610 if (rtp->transport_wide_cc.schedid > -1) {
9611 ao2_unlock(instance);
9612 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9613 ao2_ref(instance, -1);
9614 }
9615 ao2_lock(instance);
9616 rtp->transport_wide_cc.schedid = -1;
9617 }
9618
9619 if (rtp->red) {
9620 ao2_unlock(instance);
9621 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
9622 ao2_lock(instance);
9623 ast_free(rtp->red);
9624 rtp->red = NULL;
9625 }
9626
9627 ast_rtp_instance_set_remote_address(instance, &addr);
9628
9630}
#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 9567 of file res_rtp_asterisk.c.

9568{
9569 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9570 struct sockaddr_in suggestion_tmp;
9571
9572 /*
9573 * The instance should not be locked because we can block
9574 * waiting for a STUN respone.
9575 */
9576 ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
9577 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
9578 ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
9579}
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 4733 of file res_rtp_asterisk.c.

4734{
4735 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4736
4737 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4739 ast_debug_rtp(3, "(%p) RTP setting the marker bit due to a source update\n", instance);
4740
4741 return;
4742}

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 5694 of file res_rtp_asterisk.c.

5695{
5696 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5697 struct ast_sockaddr remote_address = { {0,} };
5698 struct ast_format *format;
5699 int codec;
5700
5701 ast_rtp_instance_get_remote_address(instance, &remote_address);
5702
5703 /* If we don't actually know the remote address don't even bother doing anything */
5704 if (ast_sockaddr_isnull(&remote_address)) {
5705 ast_debug_rtp(1, "(%p) RTP no remote address on instance, so dropping frame\n", instance);
5706 return 0;
5707 }
5708
5709 /* VP8: is this a request to send a RTCP FIR? */
5711 rtp_write_rtcp_fir(instance, rtp, &remote_address);
5712 return 0;
5713 } else if (frame->frametype == AST_FRAME_RTCP) {
5714 if (frame->subclass.integer == AST_RTP_RTCP_PSFB) {
5715 rtp_write_rtcp_psfb(instance, rtp, frame, &remote_address);
5716 }
5717 return 0;
5718 }
5719
5720 /* If there is no data length we can't very well send the packet */
5721 if (!frame->datalen) {
5722 ast_debug_rtp(1, "(%p) RTP received frame with no data for instance, so dropping frame\n", instance);
5723 return 0;
5724 }
5725
5726 /* If the packet is not one our RTP stack supports bail out */
5727 if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
5728 ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
5729 return -1;
5730 }
5731
5732 if (rtp->red) {
5733 /* return 0; */
5734 /* no primary data or generations to send */
5735 if ((frame = red_t140_to_red(rtp->red)) == NULL)
5736 return 0;
5737 }
5738
5739 /* Grab the subclass and look up the payload we are going to use */
5741 1, frame->subclass.format, 0);
5742 if (codec < 0) {
5743 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n",
5745 return -1;
5746 }
5747
5748 /* Note that we do not increase the ref count here as this pointer
5749 * will not be held by any thing explicitly. The format variable is
5750 * merely a convenience reference to frame->subclass.format */
5751 format = frame->subclass.format;
5753 /* Oh dear, if the format changed we will have to set up a new smoother */
5754 ast_debug_rtp(3, "(%s) RTP ooh, format changed from %s to %s\n",
5758 ao2_replace(rtp->lasttxformat, format);
5759 if (rtp->smoother) {
5761 rtp->smoother = NULL;
5762 }
5763 }
5764
5765 /* If no smoother is present see if we have to set one up */
5766 if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
5767 unsigned int smoother_flags = ast_format_get_smoother_flags(format);
5768 unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
5769
5770 if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
5771 framing_ms = ast_format_get_default_ms(format);
5772 }
5773
5774 if (framing_ms) {
5776 if (!rtp->smoother) {
5777 ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len: %u\n",
5778 ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
5779 return -1;
5780 }
5781 ast_smoother_set_flags(rtp->smoother, smoother_flags);
5782 }
5783 }
5784
5785 /* Feed audio frames into the actual function that will create a frame and send it */
5786 if (rtp->smoother) {
5787 struct ast_frame *f;
5788
5790 ast_smoother_feed_be(rtp->smoother, frame);
5791 } else {
5792 ast_smoother_feed(rtp->smoother, frame);
5793 }
5794
5795 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
5796 rtp_raw_write(instance, f, codec);
5797 }
5798 } else {
5799 int hdrlen = 12;
5800 struct ast_frame *f = NULL;
5801
5802 if (frame->offset < hdrlen) {
5803 f = ast_frdup(frame);
5804 } else {
5805 f = frame;
5806 }
5807 if (f->data.ptr) {
5808 rtp_raw_write(instance, f, codec);
5809 }
5810 if (f != frame) {
5811 ast_frfree(f);
5812 }
5813
5814 }
5815
5816 return 0;
5817}
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.
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:77
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 7430 of file res_rtp_asterisk.c.

7432{
7433 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7434 struct ast_rtp *bridged;
7435 int res = 0, payload = 0, bridged_payload = 0, mark;
7436 RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
7437 int reconstruct = ntohl(rtpheader[0]);
7438 struct ast_sockaddr remote_address = { {0,} };
7439 int ice;
7440 unsigned int timestamp = ntohl(rtpheader[1]);
7441
7442 /* Get fields from packet */
7443 payload = (reconstruct & 0x7f0000) >> 16;
7444 mark = (reconstruct & 0x800000) >> 23;
7445
7446 /* Check what the payload value should be */
7447 payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
7448 if (!payload_type) {
7449 return -1;
7450 }
7451
7452 /* Otherwise adjust bridged payload to match */
7454 payload_type->asterisk_format, payload_type->format, payload_type->rtp_code, payload_type->sample_rate);
7455
7456 /* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
7457 if (bridged_payload < 0) {
7458 return -1;
7459 }
7460
7461 /* 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 */
7462 if (ast_rtp_codecs_find_payload_code(ast_rtp_instance_get_codecs(instance1), bridged_payload) == -1) {
7463 ast_debug_rtp(1, "(%p, %p) RTP unsupported payload type received\n", instance, instance1);
7464 return -1;
7465 }
7466
7467 /*
7468 * Even if we are no longer in dtmf, we could still be receiving
7469 * re-transmissions of the last dtmf end still. Feed those to the
7470 * core so they can be filtered accordingly.
7471 */
7472 if (rtp->last_end_timestamp.is_set && rtp->last_end_timestamp.ts == timestamp) {
7473 ast_debug_rtp(1, "(%p, %p) RTP feeding packet with duplicate timestamp to core\n", instance, instance1);
7474 return -1;
7475 }
7476
7477 if (payload_type->asterisk_format) {
7478 ao2_replace(rtp->lastrxformat, payload_type->format);
7479 }
7480
7481 /*
7482 * We have now determined that we need to send the RTP packet
7483 * out the bridged instance to do local bridging so we must unlock
7484 * the receiving instance to prevent deadlock with the bridged
7485 * instance.
7486 *
7487 * Technically we should grab a ref to instance1 so it won't go
7488 * away on us. However, we should be safe because the bridged
7489 * instance won't change without both channels involved being
7490 * locked and we currently have the channel lock for the receiving
7491 * instance.
7492 */
7493 ao2_unlock(instance);
7494 ao2_lock(instance1);
7495
7496 /*
7497 * Get the peer rtp pointer now to emphasize that using it
7498 * must happen while instance1 is locked.
7499 */
7500 bridged = ast_rtp_instance_get_data(instance1);
7501
7502
7503 /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
7504 if (bridged->sending_digit) {
7505 ast_debug_rtp(1, "(%p, %p) RTP Feeding packet to core until DTMF finishes\n", instance, instance1);
7506 ao2_unlock(instance1);
7507 ao2_lock(instance);
7508 return -1;
7509 }
7510
7511 if (payload_type->asterisk_format) {
7512 /*
7513 * If bridged peer has already received rtp, perform the asymmetric codec check
7514 * if that feature has been activated
7515 */
7516 if (!bridged->asymmetric_codec
7517 && bridged->lastrxformat != ast_format_none
7518 && ast_format_cmp(payload_type->format, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
7519 ast_debug_rtp(1, "(%p, %p) RTP asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
7520 instance, instance1, ast_format_get_name(payload_type->format),
7522 ao2_unlock(instance1);
7523 ao2_lock(instance);
7524 return -1;
7525 }
7526
7527 ao2_replace(bridged->lasttxformat, payload_type->format);
7528 }
7529
7530 ast_rtp_instance_get_remote_address(instance1, &remote_address);
7531
7532 if (ast_sockaddr_isnull(&remote_address)) {
7533 ast_debug_rtp(5, "(%p, %p) RTP remote address is null, most likely RTP has been stopped\n",
7534 instance, instance1);
7535 ao2_unlock(instance1);
7536 ao2_lock(instance);
7537 return 0;
7538 }
7539
7540 /* If the marker bit has been explicitly set turn it on */
7541 if (ast_test_flag(bridged, FLAG_NEED_MARKER_BIT)) {
7542 mark = 1;
7544 }
7545
7546 /* Set the marker bit for the first local bridged packet which has the first bridged peer's SSRC. */
7548 mark = 1;
7550 }
7551
7552 /* Reconstruct part of the packet */
7553 reconstruct &= 0xFF80FFFF;
7554 reconstruct |= (bridged_payload << 16);
7555 reconstruct |= (mark << 23);
7556 rtpheader[0] = htonl(reconstruct);
7557
7558 if (mark) {
7559 /* make this rtp instance aware of the new ssrc it is sending */
7560 bridged->ssrc = ntohl(rtpheader[2]);
7561 }
7562
7563 /* Send the packet back out */
7564 res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address, &ice);
7565 if (res < 0) {
7568 "RTP Transmission error of packet to %s: %s\n",
7569 ast_sockaddr_stringify(&remote_address),
7570 strerror(errno));
7574 "RTP NAT: Can't write RTP to private "
7575 "address %s, waiting for other end to "
7576 "send audio...\n",
7577 ast_sockaddr_stringify(&remote_address));
7578 }
7580 }
7581 ao2_unlock(instance1);
7582 ao2_lock(instance);
7583 return 0;
7584 }
7585
7586 if (rtp_debug_test_addr(&remote_address)) {
7587 ast_verbose("Sent RTP P2P packet to %s%s (type %-2.2d, len %-6.6d)\n",
7588 ast_sockaddr_stringify(&remote_address),
7589 ice ? " (via ICE)" : "",
7590 bridged_payload, len - hdrlen);
7591 }
7592
7593 ao2_unlock(instance1);
7594 ao2_lock(instance);
7595 return 0;
7596}
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.
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_clear_flag(p, flag)
Definition utils.h:78

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 3568 of file res_rtp_asterisk.c.

3569{
3570 double delta1;
3571 double delta2;
3572
3573 /* First convert the standard deviation back into a sum of squares. */
3574 double last_sum_of_squares = (*std_dev) * (*std_dev) * (*count ?: 1);
3575
3576 if (++(*count) == 0) {
3577 /* Avoid potential divide by zero on an overflow */
3578 *count = 1;
3579 }
3580
3581 /*
3582 * Below is an implementation of Welford's online algorithm [1] for calculating
3583 * mean and variance in a single pass.
3584 *
3585 * [1] https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
3586 */
3587
3588 delta1 = new_sample - *mean;
3589 *mean += (delta1 / *count);
3590 delta2 = new_sample - *mean;
3591
3592 /* Now calculate the new variance, and subsequent standard deviation */
3593 *std_dev = sqrt((last_sum_of_squares + (delta1 * delta2)) / *count);
3594}

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 6458 of file res_rtp_asterisk.c.

6461{
6462 double r_value;
6463 double pseudo_mos;
6464 double mes = 0;
6465
6466 /*
6467 * While the media itself might be okay, a significant enough delay could make
6468 * for an unpleasant user experience.
6469 *
6470 * Calculate the effective latency by using the given round trip time, and adding
6471 * jitter scaled according to its standard deviation. The scaling is done in order
6472 * to increase jitter's weight since a higher deviation can result in poorer overall
6473 * quality.
6474 *
6475 * normdevrtt is the mean round trip time in seconds. The G.107's delay-impairment
6476 * model is based on one-way so we need to cut it in half before converting to
6477 * milliseconds.
6478 *
6479 * normdev_rxjitter and stdev_rxjitter are also in seconds and are converted to
6480 * milliseconds to match.
6481 */
6482 double effective_latency = ((normdevrtt / 2) * 1000)
6483 + ((normdev_rxjitter * 1000 * 2) * (stdev_rxjitter * 1000 / 3))
6484 + 10;
6485
6486 /*
6487 * Using the defaults for the standard transmission rating factor ("R" value)
6488 * one arrives at 93.2 (see ITU-T G.107 for more details), so we'll use that
6489 * as the starting value and subtract deficiencies that could affect quality.
6490 *
6491 * Calculate the impact of the effective latency. Influence increases with
6492 * values over 160 as the significant "lag" can degrade user experience.
6493 */
6494 if (effective_latency < 160) {
6495 r_value = 93.2 - (effective_latency / 40);
6496 } else {
6497 r_value = 93.2 - (effective_latency - 120) / 10;
6498 }
6499
6500 /* Next evaluate the impact of lost packets */
6501 r_value = r_value - (normdev_rxlost * 2.0);
6502
6503 /*
6504 * Finally convert the "R" value into a opinion/quality score between 1 (really anything
6505 * below 3 should be considered poor) and 4.5 (the highest achievable for VOIP).
6506 */
6507 if (r_value < 0) {
6508 pseudo_mos = 1.0;
6509 } else if (r_value > 100) {
6510 pseudo_mos = 4.5;
6511 } else {
6512 pseudo_mos = 1 + (0.035 * r_value) + (r_value * (r_value - 60) * (100 - r_value) * 0.000007);
6513 }
6514
6515 /*
6516 * We're going to rescale the 0.0->5.0 pseudo_mos to the 0.0->100.0 MES.
6517 * For those ranges, we could actually just multiply the pseudo_mos
6518 * by 20 but we may want to change the scale later.
6519 */
6520 mes = RESCALE(pseudo_mos, 0.0, 5.0, 0.0, 100.0);
6521
6522 return mes;
6523}
#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 5819 of file res_rtp_asterisk.c.

5822{
5823 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
5824
5825 double jitter = 0.0;
5826 double prev_jitter = 0.0;
5827 struct timeval now;
5828 struct timeval tmp;
5829 double rxnow;
5830 double arrival_sec;
5831 unsigned int arrival;
5832 int transit;
5833 int d;
5834
5835 gettimeofday(&now,NULL);
5836
5837 if (rtp->rxcount == 1 || mark) {
5838 rtp->rxstart = ast_tv2double(&now);
5839 rtp->remote_seed_rx_rtp_ts = rx_rtp_ts;
5840
5841 /*
5842 * "tv" is placed in the received frame's
5843 * "delivered" field and when this frame is
5844 * sent out again on the other side, it's
5845 * used to calculate the timestamp on the
5846 * outgoing RTP packets.
5847 *
5848 * NOTE: We need to do integer math here
5849 * because double math rounding issues can
5850 * generate incorrect timestamps.
5851 */
5852 rtp->rxcore = now;
5853 tmp = ast_samp2tv(rx_rtp_ts, rate);
5854 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
5855 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
5856 *tv = ast_tvadd(rtp->rxcore, tmp);
5857
5858 ast_debug_rtcp(3, "%s: "
5859 "Seed ts: %u current time: %f\n",
5861 , rx_rtp_ts
5862 , rtp->rxstart
5863 );
5864
5865 return;
5866 }
5867
5868 tmp = ast_samp2tv(rx_rtp_ts, rate);
5869 /* See the comment about "tv" above. Even if
5870 * we don't use this received packet for jitter
5871 * calculations, we still need to set tv so the
5872 * timestamp will be correct when this packet is
5873 * sent out again.
5874 */
5875 *tv = ast_tvadd(rtp->rxcore, tmp);
5876
5877 /*
5878 * The first few packets are generally unstable so let's
5879 * not use them in the calculations.
5880 */
5882 ast_debug_rtcp(3, "%s: Packet %d < %d. Ignoring\n",
5884 , rtp->rxcount
5886 );
5887
5888 return;
5889 }
5890
5891 /*
5892 * First good packet. Capture the start time and timestamp
5893 * but don't actually use this packet for calculation.
5894 */
5896 rtp->rxstart_stable = ast_tv2double(&now);
5897 rtp->remote_seed_rx_rtp_ts_stable = rx_rtp_ts;
5898 rtp->last_transit_time_samples = -rx_rtp_ts;
5899
5900 ast_debug_rtcp(3, "%s: "
5901 "pkt: %5u Stable Seed ts: %u current time: %f\n",
5903 , rtp->rxcount
5904 , rx_rtp_ts
5905 , rtp->rxstart_stable
5906 );
5907
5908 return;
5909 }
5910
5911 /*
5912 * If the current packet isn't in sequence, don't
5913 * use it in any calculations as remote_current_rx_rtp_ts
5914 * is not going to be correct.
5915 */
5916 if (rtp->lastrxseqno != rtp->prevrxseqno + 1) {
5917 ast_debug_rtcp(3, "%s: Current packet seq %d != last packet seq %d + 1. Ignoring\n",
5919 , rtp->lastrxseqno
5920 , rtp->prevrxseqno
5921 );
5922
5923 return;
5924 }
5925
5926 /*
5927 * The following calculations are taken from
5928 * https://www.rfc-editor.org/rfc/rfc3550#appendix-A.8
5929 *
5930 * The received rtp timestamp is the random "seed"
5931 * timestamp chosen by the sender when they sent the
5932 * first packet, plus the number of samples since then.
5933 *
5934 * To get our arrival time in the same units, we
5935 * calculate the time difference in seconds between
5936 * when we received the first packet and when we
5937 * received this packet and convert that to samples.
5938 */
5939 rxnow = ast_tv2double(&now);
5940 arrival_sec = rxnow - rtp->rxstart_stable;
5941 arrival = ast_sec2samp(arrival_sec, rate);
5942
5943 /*
5944 * Now we can use the exact formula in
5945 * https://www.rfc-editor.org/rfc/rfc3550#appendix-A.8 :
5946 *
5947 * int transit = arrival - r->ts;
5948 * int d = transit - s->transit;
5949 * s->transit = transit;
5950 * if (d < 0) d = -d;
5951 * s->jitter += (1./16.) * ((double)d - s->jitter);
5952 *
5953 * Our rx_rtp_ts is their r->ts.
5954 * Our rtp->last_transit_time_samples is their s->transit.
5955 * Our rtp->rxjitter is their s->jitter.
5956 */
5957 transit = arrival - rx_rtp_ts;
5958 d = transit - rtp->last_transit_time_samples;
5959
5960 if (d < 0) {
5961 d = -d;
5962 }
5963
5964 prev_jitter = rtp->rxjitter_samples;
5965 jitter = (1.0/16.0) * (((double)d) - prev_jitter);
5966 rtp->rxjitter_samples = prev_jitter + jitter;
5967
5968 /*
5969 * We need to hang on to jitter in both samples and seconds.
5970 */
5971 rtp->rxjitter = ast_samp2sec(rtp->rxjitter_samples, rate);
5972
5973 ast_debug_rtcp(3, "%s: pkt: %5u "
5974 "Arrival sec: %7.3f Arrival ts: %10u RX ts: %10u "
5975 "Transit samp: %6d Last transit samp: %6d d: %4d "
5976 "Curr jitter: %7.0f(%7.3f) Prev Jitter: %7.0f(%7.3f) New Jitter: %7.0f(%7.3f)\n",
5978 , rtp->rxcount
5979 , arrival_sec
5980 , arrival
5981 , rx_rtp_ts
5982 , transit
5984 , d
5985 , jitter
5986 , ast_samp2sec(jitter, rate)
5987 , prev_jitter
5988 , ast_samp2sec(prev_jitter, rate)
5989 , rtp->rxjitter_samples
5990 , rtp->rxjitter
5991 );
5992
5993 rtp->last_transit_time_samples = transit;
5994
5995 /*
5996 * Update all the stats.
5997 */
5998 if (rtp->rtcp) {
5999 if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
6000 rtp->rtcp->maxrxjitter = rtp->rxjitter;
6001 if (rtp->rtcp->rxjitter_count == 1)
6002 rtp->rtcp->minrxjitter = rtp->rxjitter;
6003 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
6004 rtp->rtcp->minrxjitter = rtp->rxjitter;
6005
6008 &rtp->rtcp->rxjitter_count);
6009 }
6010
6011 return;
6012}
#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:2293
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 4038 of file res_rtp_asterisk.c.

4039{
4040 struct timeval t;
4041 long ms;
4042
4043 if (ast_tvzero(rtp->txcore)) {
4044 rtp->txcore = ast_tvnow();
4045 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
4046 }
4047
4048 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
4049 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
4050 ms = 0;
4051 }
4052 rtp->txcore = t;
4053
4054 return (unsigned int) ms;
4055}
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 4813 of file res_rtp_asterisk.c.

4816{
4817 unsigned int extended_seq_no;
4818 unsigned int expected_packets;
4819 unsigned int expected_interval;
4820 unsigned int received_interval;
4821 int lost_interval;
4822
4823 /* Compute statistics */
4824 extended_seq_no = rtp->cycles + rtp->lastrxseqno;
4825 expected_packets = extended_seq_no - rtp->seedrxseqno + 1;
4826 if (rtp->rxcount > expected_packets) {
4827 expected_packets += rtp->rxcount - expected_packets;
4828 }
4829 *lost_packets = expected_packets - rtp->rxcount;
4830 expected_interval = expected_packets - rtp->rtcp->expected_prior;
4831 received_interval = rtp->rxcount - rtp->rtcp->received_prior;
4832 if (received_interval > expected_interval) {
4833 /* If we receive some late packets it is possible for the packets
4834 * we received in this interval to exceed the number we expected.
4835 * We update the expected so that the packet loss calculations
4836 * show that no packets are lost.
4837 */
4838 expected_interval = received_interval;
4839 }
4840 lost_interval = expected_interval - received_interval;
4841 if (expected_interval == 0 || lost_interval <= 0) {
4842 *fraction_lost = 0;
4843 } else {
4844 *fraction_lost = (lost_interval << 8) / expected_interval;
4845 }
4846
4847 /* Update RTCP statistics */
4848 rtp->rtcp->received_prior = rtp->rxcount;
4849 rtp->rtcp->expected_prior = expected_packets;
4850
4851 /*
4852 * While rxlost represents the number of packets lost since the last report was sent, for
4853 * the calculations below it should be thought of as a single sample. Thus min/max are the
4854 * lowest/highest sample value seen, and the mean is the average number of packets lost
4855 * between each report. As such rxlost_count only needs to be incremented per report.
4856 */
4857 if (lost_interval <= 0) {
4858 rtp->rtcp->rxlost = 0;
4859 } else {
4860 rtp->rtcp->rxlost = lost_interval;
4861 }
4862 if (rtp->rtcp->rxlost_count == 0) {
4863 rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4864 }
4865 if (lost_interval && lost_interval < rtp->rtcp->minrxlost) {
4866 rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4867 }
4868 if (lost_interval > rtp->rtcp->maxrxlost) {
4869 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
4870 }
4871
4873 &rtp->rtcp->stdev_rxlost, &rtp->rtcp->rxlost_count);
4874}
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 3192 of file res_rtp_asterisk.c.

3193{
3194 return elem - value;
3195}

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 6014 of file res_rtp_asterisk.c.

6015{
6016 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6017 struct ast_sockaddr remote_address = { {0,} };
6018
6019 ast_rtp_instance_get_remote_address(instance, &remote_address);
6020
6021 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
6022 ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
6023 instance, ast_sockaddr_stringify(&remote_address));
6024 rtp->resp = 0;
6025 rtp->dtmfsamples = 0;
6026 return &ast_null_frame;
6027 } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
6028 ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
6029 instance, ast_sockaddr_stringify(&remote_address));
6030 rtp->resp = 0;
6031 rtp->dtmfsamples = 0;
6032 return &ast_null_frame;
6033 }
6034
6035 if (rtp->resp == 'X') {
6036 ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
6037 instance, ast_sockaddr_stringify(&remote_address));
6040 } else {
6041 ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
6042 instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
6043 rtp->resp, rtp->resp,
6044 ast_sockaddr_stringify(&remote_address));
6045 rtp->f.frametype = type;
6046 rtp->f.subclass.integer = rtp->resp;
6047 }
6048 rtp->f.datalen = 0;
6049 rtp->f.samples = 0;
6050 rtp->f.mallocd = 0;
6051 rtp->f.src = "RTP";
6052 AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
6053
6054 return &rtp->f;
6055}
static const char type[]
@ AST_FRAME_DTMF_BEGIN
@ AST_CONTROL_FLASH
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
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,
struct ast_sockaddr *  bind_addr 
)
static

Definition at line 3596 of file res_rtp_asterisk.c.

3597{
3598 int af, sock;
3599
3600 af = ast_sockaddr_is_ipv4(bind_addr) ? AF_INET :
3601 ast_sockaddr_is_ipv6(bind_addr) ? AF_INET6 : -1;
3602 sock = ast_socket_nonblock(af, SOCK_DGRAM, 0);
3603
3604 if (sock < 0) {
3605 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
3606 return sock;
3607 }
3608
3609#ifdef SO_NO_CHECK
3610 if (nochecksums) {
3611 setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
3612 }
3613#endif
3614
3615#ifdef HAVE_SOCK_IPV6_V6ONLY
3616 if (AF_INET6 == af && ast_sockaddr_is_any(bind_addr)) {
3617 /* ICE relies on dual-stack behavior. Ensure it is enabled. */
3618 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof(int)) != 0) {
3619 ast_log(LOG_WARNING, "setsockopt IPV6_V6ONLY=0 failed: %s\n", strerror(errno));
3620 }
3621 }
3622#endif
3623
3624 return sock;
3625}
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition netsock2.c:524
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition netsock2.c:534
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition utils.h:1113

References ast_log, ast_sockaddr_is_any(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), 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 3198 of file res_rtp_asterisk.c.

3199{
3200 return elem == value;
3201}

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 10090 of file res_rtp_asterisk.c.

10091{
10092 switch (cmd) {
10093 case CLI_INIT:
10094 e->command = "rtcp set debug {on|off|ip}";
10095 e->usage =
10096 "Usage: rtcp set debug {on|off|ip host[:port]}\n"
10097 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
10098 " specified, limit the dumped packets to those to and from\n"
10099 " the specified 'host' with optional port.\n";
10100 return NULL;
10101 case CLI_GENERATE:
10102 return NULL;
10103 }
10104
10105 if (a->argc == e->args) { /* set on or off */
10106 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
10108 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
10109 ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
10110 return CLI_SUCCESS;
10111 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
10113 ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
10114 return CLI_SUCCESS;
10115 }
10116 } else if (a->argc == e->args +1) { /* ip */
10117 return rtcp_do_debug_ip(a);
10118 }
10119
10120 return CLI_SHOWUSAGE; /* default, failure */
10121}
#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
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 10123 of file res_rtp_asterisk.c.

10124{
10125 switch (cmd) {
10126 case CLI_INIT:
10127 e->command = "rtcp set stats {on|off}";
10128 e->usage =
10129 "Usage: rtcp set stats {on|off}\n"
10130 " Enable/Disable dumping of RTCP stats.\n";
10131 return NULL;
10132 case CLI_GENERATE:
10133 return NULL;
10134 }
10135
10136 if (a->argc != e->args)
10137 return CLI_SHOWUSAGE;
10138
10139 if (!strncasecmp(a->argv[e->args-1], "on", 2))
10140 rtcpstats = 1;
10141 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
10142 rtcpstats = 0;
10143 else
10144 return CLI_SHOWUSAGE;
10145
10146 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
10147 return CLI_SUCCESS;
10148}
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 9989 of file res_rtp_asterisk.c.

9990{
9991 switch (cmd) {
9992 case CLI_INIT:
9993 e->command = "rtp set debug {on|off|ip}";
9994 e->usage =
9995 "Usage: rtp set debug {on|off|ip host[:port]}\n"
9996 " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9997 " specified, limit the dumped packets to those to and from\n"
9998 " the specified 'host' with optional port.\n";
9999 return NULL;
10000 case CLI_GENERATE:
10001 return NULL;
10002 }
10003
10004 if (a->argc == e->args) { /* set on or off */
10005 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
10007 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
10008 ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
10009 return CLI_SUCCESS;
10010 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
10012 ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
10013 return CLI_SUCCESS;
10014 }
10015 } else if (a->argc == e->args +1) { /* ip */
10016 return rtp_do_debug_ip(a);
10017 }
10018
10019 return CLI_SHOWUSAGE; /* default, failure */
10020}
static struct ast_sockaddr rtpdebugaddr
static char * rtp_do_debug_ip(struct ast_cli_args *a)
#define AST_LOG_CATEGORY_RTP_PACKET

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 10023 of file res_rtp_asterisk.c.

10024{
10025#ifdef HAVE_PJPROJECT
10026 struct sockaddr_in stunaddr_copy;
10027 const char *stun_hostname_copy = NULL;
10028 int stunaddr_ttl_copy = 0;
10029#endif
10030 switch (cmd) {
10031 case CLI_INIT:
10032 e->command = "rtp show settings";
10033 e->usage =
10034 "Usage: rtp show settings\n"
10035 " Display RTP configuration settings\n";
10036 return NULL;
10037 case CLI_GENERATE:
10038 return NULL;
10039 }
10040
10041 if (a->argc != 3) {
10042 return CLI_SHOWUSAGE;
10043 }
10044
10045 ast_cli(a->fd, "\n\nGeneral Settings:\n");
10046 ast_cli(a->fd, "----------------\n");
10047 ast_cli(a->fd, " Port start: %d\n", rtpstart);
10048 ast_cli(a->fd, " Port end: %d\n", rtpend);
10049#ifdef SO_NO_CHECK
10050 ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
10051#endif
10052 ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
10053 ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
10054
10055 if (strictrtp) {
10056 ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
10057 }
10058
10059 ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
10060#ifdef HAVE_PJPROJECT
10061 ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
10062
10063 ast_rwlock_rdlock(&stunaddr_lock);
10064 memcpy(&stunaddr_copy, &stunaddr, sizeof(stunaddr));
10065 stun_hostname_copy = ast_strdupa(S_OR(stun_hostname, ""));
10066 stunaddr_ttl_copy = stunaddr_ttl;
10067 ast_rwlock_unlock(&stunaddr_lock);
10068
10069 ast_cli(a->fd, " STUN: %s\n", stunaddr_copy.sin_addr.s_addr ? "enbabled" : "disabled");
10070 if (ast_strlen_zero(stun_hostname_copy)) {
10071 ast_cli(a->fd, " Address: %s:%d\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
10072 htons(stunaddr_copy.sin_port));
10073 } else {
10074 ast_cli(a->fd, " Hostname: %s:%d\n", stun_hostname_copy, htons(stunaddr_copy.sin_port));
10075 ast_cli(a->fd, " Resolved Addr: %s:%d%s\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
10076 htons(stunaddr_copy.sin_port),
10077 stunaddr_copy.sin_addr.s_addr ? stunaddr_resolver ? "" : " (possibly stale)" : " (lookup failed)");
10078 ast_cli(a->fd, " Last TTL: %d (periodic resolution %s)\n", stunaddr_ttl_copy,
10079 stunaddr_resolver ? "enabled" : "disabled");
10080 ast_cli(a->fd, " Reresove TTL 0: %s\n", AST_CLI_YESNO(stunaddr_reresolve_ttl_0));
10081 }
10082 if (stun_acl) {
10083 ast_acl_output(a->fd, stun_acl, " ");
10084 }
10085#endif
10086 return CLI_SUCCESS;
10087}
void ast_acl_output(int fd, struct ast_acl_list *acl, const char *prefix)
output an ACL to the provided fd
Definition acl.c:1115
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#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:962
static int rtpend
static int learning_min_sequential
static int rtpstart
static int dtmftimeout
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 10679 of file res_rtp_asterisk.c.

10680{
10681#ifdef HAVE_PJPROJECT
10682 pj_lock_t *lock;
10683
10685
10687 if (pj_init() != PJ_SUCCESS) {
10689 }
10690
10691 if (pjlib_util_init() != PJ_SUCCESS) {
10692 rtp_terminate_pjproject();
10694 }
10695
10696 if (pjnath_init() != PJ_SUCCESS) {
10697 rtp_terminate_pjproject();
10699 }
10700
10701 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10702
10703 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10704
10705 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10706 rtp_terminate_pjproject();
10708 }
10709
10710 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10711 rtp_terminate_pjproject();
10713 }
10714
10715 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10716
10717 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10718 rtp_terminate_pjproject();
10720 }
10721
10722#endif
10723
10724#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10725 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10726 if (!dtls_bio_methods) {
10727#ifdef HAVE_PJPROJECT
10728 rtp_terminate_pjproject();
10729#endif
10731 }
10732 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10733 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10734 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10735 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10736#endif
10737
10739#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10740 BIO_meth_free(dtls_bio_methods);
10741#endif
10742#ifdef HAVE_PJPROJECT
10743 rtp_terminate_pjproject();
10744#endif
10746 }
10747
10749#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10750 BIO_meth_free(dtls_bio_methods);
10751#endif
10752#ifdef HAVE_PJPROJECT
10754 rtp_terminate_pjproject();
10755#endif
10757 }
10758
10759 rtp_reload(0, 0);
10760
10762}
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:374
#define ast_rtp_engine_register(engine)
Definition rtp_engine.h:852
#define ARRAY_LEN(a)
Definition utils.h:706

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 4806 of file res_rtp_asterisk.c.

4807{
4808 tv->tv_sec = msw - 2208988800u;
4809 /* Reverse the sequence in timeval2ntp() */
4810 tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
4811}

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 6275 of file res_rtp_asterisk.c.

6276{
6277 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6278
6279 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
6280 totally help us out because we don't have an engine to keep it going and we are not
6281 guaranteed to have it every 20ms or anything */
6283 ast_debug(0, "- RTP 3389 Comfort noise event: Format %s (len = %d)\n",
6285 }
6286
6287 if (!ast_test_flag(rtp, FLAG_3389_WARNING)) {
6288 struct ast_sockaddr remote_address = { {0,} };
6289
6290 ast_rtp_instance_get_remote_address(instance, &remote_address);
6291
6292 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
6293 ast_sockaddr_stringify(&remote_address));
6295 }
6296
6297 /* Must have at least one byte */
6298 if (!len) {
6299 return NULL;
6300 }
6301 if (len < 24) {
6302 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
6303 rtp->f.datalen = len - 1;
6305 memcpy(rtp->f.data.ptr, data + 1, len - 1);
6306 } else {
6307 rtp->f.data.ptr = NULL;
6308 rtp->f.offset = 0;
6309 rtp->f.datalen = 0;
6310 }
6311 rtp->f.frametype = AST_FRAME_CNG;
6312 rtp->f.subclass.integer = data[0] & 0x7f;
6313 rtp->f.samples = 0;
6314 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
6315
6316 return &rtp->f;
6317}
#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 6195 of file res_rtp_asterisk.c.

6196{
6197 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6198 unsigned int event, flags, power;
6199 char resp = 0;
6200 unsigned char seq;
6201 struct ast_frame *f = NULL;
6202
6203 if (len < 4) {
6204 return NULL;
6205 }
6206
6207 /* The format of Cisco RTP DTMF packet looks like next:
6208 +0 - sequence number of DTMF RTP packet (begins from 1,
6209 wrapped to 0)
6210 +1 - set of flags
6211 +1 (bit 0) - flaps by different DTMF digits delimited by audio
6212 or repeated digit without audio???
6213 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
6214 then falls to 0 at its end)
6215 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
6216 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
6217 by each new packet and thus provides some redundancy.
6218
6219 Sample of Cisco RTP DTMF packet is (all data in hex):
6220 19 07 00 02 12 02 20 02
6221 showing end of DTMF digit '2'.
6222
6223 The packets
6224 27 07 00 02 0A 02 20 02
6225 28 06 20 02 00 02 0A 02
6226 shows begin of new digit '2' with very short pause (20 ms) after
6227 previous digit '2'. Bit +1.0 flips at begin of new digit.
6228
6229 Cisco RTP DTMF packets comes as replacement of audio RTP packets
6230 so its uses the same sequencing and timestamping rules as replaced
6231 audio packets. Repeat interval of DTMF packets is 20 ms and not rely
6232 on audio framing parameters. Marker bit isn't used within stream of
6233 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
6234 are not sequential at borders between DTMF and audio streams,
6235 */
6236
6237 seq = data[0];
6238 flags = data[1];
6239 power = data[2];
6240 event = data[3] & 0x1f;
6241
6243 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);
6244 if (event < 10) {
6245 resp = '0' + event;
6246 } else if (event < 11) {
6247 resp = '*';
6248 } else if (event < 12) {
6249 resp = '#';
6250 } else if (event < 16) {
6251 resp = 'A' + (event - 12);
6252 } else if (event < 17) {
6253 resp = 'X';
6254 }
6255 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
6256 rtp->resp = resp;
6257 /* Why we should care on DTMF compensation at reception? */
6259 f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
6260 rtp->dtmfsamples = 0;
6261 }
6262 } else if ((rtp->resp == resp) && !power) {
6264 f->samples = rtp->dtmfsamples * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
6265 rtp->resp = 0;
6266 } else if (rtp->resp == resp) {
6267 rtp->dtmfsamples += 20 * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
6268 }
6269
6270 rtp->dtmf_timeout = 0;
6271
6272 return f;
6273}
static volatile unsigned int seq
Definition app_sms.c:126
@ AST_RTP_PROPERTY_DTMF_COMPENSATE
Definition rtp_engine.h:122
unsigned int flags

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 6057 of file res_rtp_asterisk.c.

6058{
6059 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6060 struct ast_sockaddr remote_address = { {0,} };
6061 unsigned int event, event_end, samples;
6062 char resp = 0;
6063 struct ast_frame *f = NULL;
6064
6065 ast_rtp_instance_get_remote_address(instance, &remote_address);
6066
6067 /* Figure out event, event end, and samples */
6068 event = ntohl(*((unsigned int *)(data)));
6069 event >>= 24;
6070 event_end = ntohl(*((unsigned int *)(data)));
6071 event_end <<= 8;
6072 event_end >>= 24;
6073 samples = ntohl(*((unsigned int *)(data)));
6074 samples &= 0xFFFF;
6075
6076 if (rtp_debug_test_addr(&remote_address)) {
6077 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",
6078 ast_sockaddr_stringify(&remote_address),
6079 payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
6080 }
6081
6082 /* Print out debug if turned on */
6084 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
6085
6086 /* Figure out what digit was pressed */
6087 if (event < 10) {
6088 resp = '0' + event;
6089 } else if (event < 11) {
6090 resp = '*';
6091 } else if (event < 12) {
6092 resp = '#';
6093 } else if (event < 16) {
6094 resp = 'A' + (event - 12);
6095 } else if (event < 17) { /* Event 16: Hook flash */
6096 resp = 'X';
6097 } else {
6098 /* Not a supported event */
6099 ast_debug_rtp(1, "(%p) RTP ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", instance, event);
6100 return;
6101 }
6102
6104 if (!rtp->last_end_timestamp.is_set || rtp->last_end_timestamp.ts != timestamp || (rtp->resp && rtp->resp != resp)) {
6105 rtp->resp = resp;
6106 rtp->dtmf_timeout = 0;
6108 f->len = 0;
6109 rtp->last_end_timestamp.ts = timestamp;
6110 rtp->last_end_timestamp.is_set = 1;
6112 }
6113 } else {
6114 /* The duration parameter measures the complete
6115 duration of the event (from the beginning) - RFC2833.
6116 Account for the fact that duration is only 16 bits long
6117 (about 8 seconds at 8000 Hz) and can wrap is digit
6118 is hold for too long. */
6119 unsigned int new_duration = rtp->dtmf_duration;
6120 unsigned int last_duration = new_duration & 0xFFFF;
6121
6122 if (last_duration > 64000 && samples < last_duration) {
6123 new_duration += 0xFFFF + 1;
6124 }
6125 new_duration = (new_duration & ~0xFFFF) | samples;
6126
6127 if (event_end & 0x80) {
6128 /* End event */
6129 if (rtp->last_seqno != seqno && (!rtp->last_end_timestamp.is_set || timestamp > rtp->last_end_timestamp.ts)) {
6130 rtp->last_end_timestamp.ts = timestamp;
6131 rtp->last_end_timestamp.is_set = 1;
6132 rtp->dtmf_duration = new_duration;
6133 rtp->resp = resp;
6136 rtp->resp = 0;
6137 rtp->dtmf_duration = rtp->dtmf_timeout = 0;
6140 ast_debug_rtp(1, "(%p) RTP dropping duplicate or out of order DTMF END frame (seqno: %u, ts %u, digit %c)\n",
6141 instance, seqno, timestamp, resp);
6142 }
6143 } else {
6144 /* Begin/continuation */
6145
6146 /* The second portion of the seqno check is to not mistakenly
6147 * stop accepting DTMF if the seqno rolls over beyond
6148 * 65535.
6149 */
6150 if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
6151 || (rtp->last_end_timestamp.is_set
6152 && timestamp <= rtp->last_end_timestamp.ts)) {
6153 /* Out of order frame. Processing this can cause us to
6154 * improperly duplicate incoming DTMF, so just drop
6155 * this.
6156 */
6158 ast_debug(0, "Dropping out of order DTMF frame (seqno %u, ts %u, digit %c)\n",
6159 seqno, timestamp, resp);
6160 }
6161 return;
6162 }
6163
6164 if (rtp->resp && rtp->resp != resp) {
6165 /* Another digit already began. End it */
6168 rtp->resp = 0;
6169 rtp->dtmf_duration = rtp->dtmf_timeout = 0;
6171 }
6172
6173 if (rtp->resp) {
6174 /* Digit continues */
6175 rtp->dtmf_duration = new_duration;
6176 } else {
6177 /* New digit began */
6178 rtp->resp = resp;
6180 rtp->dtmf_duration = samples;
6182 }
6183
6184 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
6185 }
6186
6187 rtp->last_seqno = seqno;
6188 }
6189
6190 rtp->dtmfsamples = samples;
6191
6192 return;
6193}

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 5268 of file res_rtp_asterisk.c.

5269{
5270 unsigned char *cp = p;
5271 uint32_t datum;
5272
5273 /* Convert the time to 6.18 format */
5274 datum = (time_msw << 18) & 0x00fc0000;
5275 datum |= (time_lsw >> 14) & 0x0003ffff;
5276
5277 cp[0] = datum >> 16;
5278 cp[1] = datum >> 8;
5279 cp[2] = datum;
5280}

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 5516 of file res_rtp_asterisk.c.

5517{
5518 unsigned char *data = red->t140red.data.ptr;
5519 int len = 0;
5520 int i;
5521
5522 /* replace most aged generation */
5523 if (red->len[0]) {
5524 for (i = 1; i < red->num_gen+1; i++)
5525 len += red->len[i];
5526
5527 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
5528 }
5529
5530 /* Store length of each generation and primary data length*/
5531 for (i = 0; i < red->num_gen; i++)
5532 red->len[i] = red->len[i+1];
5533
5534 /*
5535 * RED generation payload sizes are limited to 255 (UCHAR_MAX) bytes by virtue of
5536 * red->len being an array of usigned chars. If the new primary payload exceeds that,
5537 * we're going to truncate it to 255.
5538 */
5539 if (red->t140.datalen > UCHAR_MAX) {
5540 ast_log(LOG_WARNING, "New T.140 frame of %d bytes exceeds max of %u. Discarding %d bytes.\n",
5541 red->t140.datalen, UCHAR_MAX, red->t140.datalen - UCHAR_MAX);
5542 red->t140.datalen = UCHAR_MAX;
5543 }
5544 red->len[i] = red->t140.datalen;
5545
5546 /* write each generation length in red header */
5547 len = red->hdrlen;
5548 for (i = 0; i < red->num_gen; i++) {
5549 len += data[i*4+3] = red->len[i];
5550 }
5551
5552 /* add primary data to buffer */
5553 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
5554 red->t140red.datalen = len + red->t140.datalen;
5555
5556 /* no primary data and no generations to send */
5557 if (len == red->hdrlen && !red->t140.datalen) {
5558 return NULL;
5559 }
5560
5561 /* reset t.140 buffer */
5562 red->t140.datalen = 0;
5563
5564 return &red->t140red;
5565}
struct ast_frame t140
unsigned char len[AST_RED_MAX_GENERATION]
struct ast_frame t140red

References ast_log, ast_frame::data, ast_frame::datalen, rtp_red::hdrlen, len(), rtp_red::len, LOG_WARNING, 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 9342 of file res_rtp_asterisk.c.

9343{
9344 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
9345 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9346
9347 ao2_lock(instance);
9348 if (rtp->red->t140.datalen > 0) {
9349 ast_rtp_write(instance, &rtp->red->t140);
9350 }
9351 ao2_unlock(instance);
9352
9353 return 1;
9354}
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 10647 of file res_rtp_asterisk.c.

10648{
10649 rtp_reload(1, 0);
10650 return 0;
10651}

References rtp_reload().

◆ rtcp_debug_test_addr()

static int rtcp_debug_test_addr ( struct ast_sockaddr *  addr)
inlinestatic

Definition at line 2854 of file res_rtp_asterisk.c.

2855{
2857 return 0;
2858 }
2860 if (rtcpdebugport) {
2861 return (ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0); /* look for RTCP packets from IP+Port */
2862 } else {
2863 return (ast_sockaddr_cmp_addr(&rtcpdebugaddr, addr) == 0); /* only look for RTCP packets from IP */
2864 }
2865 }
2866
2867 return 1;
2868}
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

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 9972 of file res_rtp_asterisk.c.

9973{
9974 char *arg = ast_strdupa(a->argv[4]);
9975 char *debughost = NULL;
9976 char *debugport = NULL;
9977
9978 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9979 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9980 return CLI_FAILURE;
9981 }
9982 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9983 ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9986 return CLI_SUCCESS;
9987}
#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

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 3203 of file res_rtp_asterisk.c.

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

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 6668 of file res_rtp_asterisk.c.

6669{
6670 switch (pt) {
6671 case AST_RTP_RTCP_RTPFB:
6672 if (subtype == AST_RTP_RTCP_FMT_NACK) {
6673 return "NACK";
6674 }
6675 break;
6676 case RTCP_PT_PSFB:
6677 if (subtype == AST_RTP_RTCP_FMT_REMB) {
6678 return "REMB";
6679 }
6680 break;
6681 default:
6682 break;
6683 }
6684
6685 return NULL;
6686}

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 6636 of file res_rtp_asterisk.c.

6637{
6638 const char *str;
6639
6640 switch (pt) {
6641 case RTCP_PT_SR:
6642 str = "Sender Report";
6643 break;
6644 case RTCP_PT_RR:
6645 str = "Receiver Report";
6646 break;
6647 case RTCP_PT_FUR:
6648 /* Full INTRA-frame Request / Fast Update Request */
6649 str = "H.261 FUR";
6650 break;
6651 case RTCP_PT_PSFB:
6652 /* Payload Specific Feed Back */
6653 str = "PSFB";
6654 break;
6655 case RTCP_PT_SDES:
6656 str = "Source Description";
6657 break;
6658 case RTCP_PT_BYE:
6659 str = "BYE";
6660 break;
6661 default:
6662 str = "Unknown";
6663 break;
6664 }
6665 return str;
6666}
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 3453 of file res_rtp_asterisk.c.

3454{
3455 return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
3456}
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 3539 of file res_rtp_asterisk.c.

3540{
3541 return __rtp_sendto(instance, buf, size, flags, sa, 1, ice, 1);
3542}
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 4151 of file res_rtp_asterisk.c.

4152{
4153 int x, startplace, i, maxloops;
4154 unsigned int port_start, port_end;
4155
4156#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
4157 rtp->rekeyid = -1;
4158 rtp->dtls.timeout_timer = -1;
4159#endif
4160
4162
4163 /* Determine the port range to use: per-instance override or global */
4164 port_start = ast_rtp_instance_get_port_start(instance);
4165 port_end = ast_rtp_instance_get_port_end(instance);
4166 if (port_start > 0 && port_end > 0 && port_end > port_start) {
4167 ast_debug_rtp(1, "(%p) RTP using per-instance port range %d-%d\n",
4168 instance, port_start, port_end);
4169 } else {
4170 port_start = rtpstart;
4171 port_end = rtpend;
4172 }
4173
4174 /* Create a new socket for us to listen on and use */
4175 if ((rtp->s = create_new_socket("RTP", &rtp->bind_address)) < 0) {
4176 ast_log(LOG_WARNING, "Failed to create a new socket for RTP instance '%p'\n", instance);
4177 return -1;
4178 }
4179
4180 /* Now actually find a free RTP port to use */
4181 x = (ast_random() % (port_end - port_start)) + port_start;
4182 x = x & ~1;
4183 startplace = x;
4184
4185 /* Protection against infinite loops in the case there is a potential case where the loop is not broken such as an odd
4186 start port sneaking in (even though this condition is checked at load.) */
4187 maxloops = port_end - port_start;
4188 for (i = 0; i <= maxloops; i++) {
4190 /* Try to bind, this will tell us whether the port is available or not */
4191 if (!ast_bind(rtp->s, &rtp->bind_address)) {
4192 ast_debug_rtp(1, "(%p) RTP allocated port %d\n", instance, x);
4194 ast_test_suite_event_notify("RTP_PORT_ALLOCATED", "Port: %d", x);
4195 break;
4196 }
4197
4198 x += 2;
4199 if (x > port_end) {
4200 x = (port_start + 1) & ~1;
4201 }
4202
4203 /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
4204 if (x == startplace || (errno != EADDRINUSE && errno != EACCES)) {
4205 ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
4206 close(rtp->s);
4207 rtp->s = -1;
4208 return -1;
4209 }
4210 }
4211
4212#ifdef HAVE_PJPROJECT
4213 /* Initialize synchronization aspects */
4214 ast_cond_init(&rtp->cond, NULL);
4215
4216 generate_random_string(rtp->local_ufrag, sizeof(rtp->local_ufrag));
4217 generate_random_string(rtp->local_passwd, sizeof(rtp->local_passwd));
4218
4219 /* Create an ICE session for ICE negotiation */
4220 if (icesupport) {
4221 rtp->ice_num_components = 2;
4222 ast_debug_ice(2, "(%p) ICE creating session %s (%d)\n", instance,
4224 if (ice_create(instance, &rtp->bind_address, x, 0)) {
4225 ast_log(LOG_NOTICE, "(%p) ICE failed to create session\n", instance);
4226 } else {
4227 rtp->ice_port = x;
4228 ast_sockaddr_copy(&rtp->ice_original_rtp_addr, &rtp->bind_address);
4229 }
4230 }
4231#endif
4232
4233 return 0;
4234}
#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)
unsigned int ast_rtp_instance_get_port_end(struct ast_rtp_instance *instance)
Get the per-instance RTP port range end.
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
unsigned int ast_rtp_instance_get_port_start(struct ast_rtp_instance *instance)
Get the per-instance RTP port range start.

References ast_bind(), ast_cond_init, ast_debug_ice, ast_debug_rtp, ast_log, ast_random(), ast_rtp_instance_get_port_end(), ast_rtp_instance_get_port_start(), ast_rtp_instance_set_local_address(), ast_sockaddr_copy(), 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 4236 of file res_rtp_asterisk.c.

4237{
4238 int saved_rtp_s = rtp->s;
4239#ifdef HAVE_PJPROJECT
4240 struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
4241 struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
4242#endif
4243
4244#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
4245 ast_rtp_dtls_stop(instance);
4246#endif
4247
4248 /* Close our own socket so we no longer get packets */
4249 if (rtp->s > -1) {
4250 close(rtp->s);
4251 rtp->s = -1;
4252 }
4253
4254 /* Destroy RTCP if it was being used */
4255 if (rtp->rtcp && rtp->rtcp->s > -1) {
4256 if (saved_rtp_s != rtp->rtcp->s) {
4257 close(rtp->rtcp->s);
4258 }
4259 rtp->rtcp->s = -1;
4260 }
4261
4262#ifdef HAVE_PJPROJECT
4263 pj_thread_register_check();
4264
4265 /*
4266 * The instance lock is already held.
4267 *
4268 * Destroy the RTP TURN relay if being used
4269 */
4270 if (rtp->turn_rtp) {
4271 rtp->turn_state = PJ_TURN_STATE_NULL;
4272
4273 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
4274 ao2_unlock(instance);
4275 pj_turn_sock_destroy(rtp->turn_rtp);
4276 ao2_lock(instance);
4277 while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
4278 ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
4279 }
4280 rtp->turn_rtp = NULL;
4281 }
4282
4283 /* Destroy the RTCP TURN relay if being used */
4284 if (rtp->turn_rtcp) {
4285 rtp->turn_state = PJ_TURN_STATE_NULL;
4286
4287 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
4288 ao2_unlock(instance);
4289 pj_turn_sock_destroy(rtp->turn_rtcp);
4290 ao2_lock(instance);
4291 while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
4292 ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
4293 }
4294 rtp->turn_rtcp = NULL;
4295 }
4296
4297 ast_debug_ice(2, "(%p) ICE RTP transport deallocating\n", instance);
4298 /* Destroy any ICE session */
4299 ast_rtp_ice_stop(instance);
4300
4301 /* Destroy any candidates */
4302 if (rtp->ice_local_candidates) {
4303 ao2_ref(rtp->ice_local_candidates, -1);
4304 rtp->ice_local_candidates = NULL;
4305 }
4306
4307 if (rtp->ice_active_remote_candidates) {
4308 ao2_ref(rtp->ice_active_remote_candidates, -1);
4309 rtp->ice_active_remote_candidates = NULL;
4310 }
4311
4312 if (rtp->ice_proposed_remote_candidates) {
4313 ao2_ref(rtp->ice_proposed_remote_candidates, -1);
4314 rtp->ice_proposed_remote_candidates = NULL;
4315 }
4316
4317 if (rtp->ioqueue) {
4318 /*
4319 * We cannot hold the instance lock because we could wait
4320 * for the ioqueue thread to die and we might deadlock as
4321 * a result.
4322 */
4323 ao2_unlock(instance);
4324 rtp_ioqueue_thread_remove(rtp->ioqueue);
4325 ao2_lock(instance);
4326 rtp->ioqueue = NULL;
4327 }
4328#endif
4329}
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 2838 of file res_rtp_asterisk.c.

2839{
2841 return 0;
2842 }
2844 if (rtpdebugport) {
2845 return (ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0); /* look for RTP packets from IP+Port */
2846 } else {
2847 return (ast_sockaddr_cmp_addr(&rtpdebugaddr, addr) == 0); /* only look for RTP packets from IP */
2848 }
2849 }
2850
2851 return 1;
2852}
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 9955 of file res_rtp_asterisk.c.

9956{
9957 char *arg = ast_strdupa(a->argv[4]);
9958 char *debughost = NULL;
9959 char *debugport = NULL;
9960
9961 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9962 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9963 return CLI_FAILURE;
9964 }
9965 rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9966 ast_cli(a->fd, "RTP Packet Debugging Enabled for address: %s\n",
9969 return CLI_SUCCESS;
9970}

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 6630 of file res_rtp_asterisk.c.

6632{
6633 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
6634}
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 6623 of file res_rtp_asterisk.c.

6625{
6626 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6627}

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 7923 of file res_rtp_asterisk.c.

7925{
7926 int transport_wide_cc_id = ast_rtp_instance_extmap_get_id(instance, AST_RTP_EXTENSION_TRANSPORT_WIDE_CC);
7927 int pos = 0;
7928
7929 /* We currently only care about the transport-cc extension, so if that's not negotiated then do nothing */
7930 if (transport_wide_cc_id == -1) {
7931 return;
7932 }
7933
7934 /* Only while we do not exceed available extension data do we continue */
7935 while (pos < len) {
7936 int id = extension[pos] >> 4;
7937 int extension_len = (extension[pos] & 0xF) + 1;
7938
7939 /* We've handled the first byte as it contains the extension id and length, so always
7940 * skip ahead now
7941 */
7942 pos += 1;
7943
7944 if (id == 0) {
7945 /* From the RFC:
7946 * In both forms, padding bytes have the value of 0 (zero). They may be
7947 * placed between extension elements, if desired for alignment, or after
7948 * the last extension element, if needed for padding. A padding byte
7949 * does not supply the ID of an element, nor the length field. When a
7950 * padding byte is found, it is ignored and the parser moves on to
7951 * interpreting the next byte.
7952 */
7953 continue;
7954 } else if (id == 15) {
7955 /* From the RFC:
7956 * The local identifier value 15 is reserved for future extension and
7957 * MUST NOT be used as an identifier. If the ID value 15 is
7958 * encountered, its length field should be ignored, processing of the
7959 * entire extension should terminate at that point, and only the
7960 * extension elements present prior to the element with ID 15
7961 * considered.
7962 */
7963 break;
7964 } else if ((pos + extension_len) > len) {
7965 /* The extension is corrupted and is stating that it contains more data than is
7966 * available in the extensions data.
7967 */
7968 break;
7969 }
7970
7971 /* If this is transport-cc then we need to parse it further */
7972 if (id == transport_wide_cc_id) {
7973 rtp_instance_parse_transport_wide_cc(instance, rtp, extension + pos, extension_len);
7974 }
7975
7976 /* Skip ahead to the next extension */
7977 pos += extension_len;
7978 }
7979}
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 7868 of file res_rtp_asterisk.c.

7870{
7871 uint16_t *seqno = (uint16_t *)data;
7873 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
7874 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
7875
7876 /* If the sequence number has cycled over then record it as such */
7877 if (((int)transport_rtp->transport_wide_cc.last_seqno - (int)ntohs(*seqno)) > 100) {
7878 transport_rtp->transport_wide_cc.cycles += RTP_SEQ_MOD;
7879 }
7880
7881 /* Populate the statistics information for this packet */
7882 statistics.seqno = transport_rtp->transport_wide_cc.cycles + ntohs(*seqno);
7883 statistics.received = ast_tvnow();
7884
7885 /* We allow at a maximum 1000 packet statistics in play at a time, if we hit the
7886 * limit we give up and start fresh.
7887 */
7888 if (AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) > 1000) {
7890 }
7891
7892 if (!AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) ||
7893 statistics.seqno > transport_rtp->transport_wide_cc.last_extended_seqno) {
7894 /* This is the expected path */
7896 return;
7897 }
7898
7899 transport_rtp->transport_wide_cc.last_extended_seqno = statistics.seqno;
7900 transport_rtp->transport_wide_cc.last_seqno = ntohs(*seqno);
7901 } else {
7902 /* This packet was out of order, so reorder it within the vector accordingly */
7905 return;
7906 }
7907 }
7908
7909 /* If we have not yet scheduled the periodic sending of feedback for this transport then do so */
7910 if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
7911 ast_debug_rtcp(1, "(%p) RTCP starting transport-cc feedback transmission on RTP instance '%p'\n", instance, transport);
7912 ao2_ref(transport, +1);
7913 transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
7915 if (transport_rtp->transport_wide_cc.schedid < 0) {
7916 ao2_ref(transport, -1);
7917 ast_log(LOG_WARNING, "Scheduling RTCP transport-cc feedback transmission failed on RTP instance '%p'\n",
7918 transport);
7919 }
7920 }
7921}
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)

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 7598 of file res_rtp_asterisk.c.

7599{
7600 if (instance) {
7601 ao2_unlock(instance);
7602 }
7603}

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 3652 of file res_rtp_asterisk.c.

3653{
3654 if (seq == (uint16_t) (info->max_seq + 1)) {
3655 /* packet is in sequence */
3656 info->packets--;
3657 } else {
3658 /* Sequence discontinuity; reset */
3659 info->packets = learning_min_sequential - 1;
3660 info->received = ast_tvnow();
3661 }
3662
3663 /* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */
3664 if (strictrtp == STRICT_RTP_YES) {
3665 switch (info->stream_type) {
3668 /*
3669 * Protect against packet floods by checking that we
3670 * received the packet sequence in at least the minimum
3671 * allowed time.
3672 */
3673 if (ast_tvzero(info->received)) {
3674 info->received = ast_tvnow();
3675 } else if (!info->packets
3677 /* Packet flood; reset */
3678 info->packets = learning_min_sequential - 1;
3679 info->received = ast_tvnow();
3680 }
3681 break;
3685 case AST_MEDIA_TYPE_END:
3686 break;
3687 }
3688 }
3689
3690 info->max_seq = seq;
3691
3692 return info->packets;
3693}
@ AST_MEDIA_TYPE_END
Definition codec.h:36
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(), 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 3635 of file res_rtp_asterisk.c.

3636{
3637 info->max_seq = seq;
3638 info->packets = learning_min_sequential;
3639 memset(&info->received, 0, sizeof(info->received));
3640}

References 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 3700 of file res_rtp_asterisk.c.

3701{
3703 memset(&rtp->rtp_source_learn.proposed_address, 0,
3704 sizeof(rtp->rtp_source_learn.proposed_address));
3706 rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t) rtp->lastrxseqno);
3707}

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 5283 of file res_rtp_asterisk.c.

5284{
5285 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5286 int pred, mark = 0;
5287 unsigned int ms;
5288 struct ast_sockaddr remote_address = { {0,} };
5289 int rate = ast_rtp_get_rate(frame->subclass.format) / 1000;
5290 unsigned int seqno;
5291#ifdef TEST_FRAMEWORK
5292 struct ast_rtp_engine_test *test = ast_rtp_instance_get_test(instance);
5293#endif
5294
5296 frame->samples /= 2;
5297 }
5298
5299 if (rtp->sending_digit) {
5300 return 0;
5301 }
5302
5303 /* Suppressed audio must not consume elapsed transmit time. */
5304 ms = calc_txstamp(rtp, &frame->delivery);
5305
5306#ifdef TEST_FRAMEWORK
5307 if (test && test->send_report) {
5308 test->send_report = 0;
5309 ast_rtcp_write(instance);
5310 return 0;
5311 }
5312#endif
5313
5314 if (frame->frametype == AST_FRAME_VOICE) {
5315 pred = rtp->lastts + frame->samples;
5316
5317 /* Re-calculate last TS */
5318 rtp->lastts = rtp->lastts + ms * rate;
5319 if (ast_tvzero(frame->delivery)) {
5320 /* If this isn't an absolute delivery time, Check if it is close to our prediction,
5321 and if so, go with our prediction */
5322 if (abs((int)rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
5323 rtp->lastts = pred;
5324 } else {
5325 ast_debug_rtp(3, "(%p) RTP audio difference is %d, ms is %u\n",
5326 instance, abs((int)rtp->lastts - pred), ms);
5327 mark = 1;
5328 }
5329 }
5330 } else if (frame->frametype == AST_FRAME_VIDEO) {
5331 mark = frame->subclass.frame_ending;
5332 pred = rtp->lastovidtimestamp + frame->samples;
5333 /* Re-calculate last TS */
5334 rtp->lastts = rtp->lastts + ms * 90;
5335 /* If it's close to our prediction, go for it */
5336 if (ast_tvzero(frame->delivery)) {
5337 if (abs((int)rtp->lastts - pred) < 7200) {
5338 rtp->lastts = pred;
5339 rtp->lastovidtimestamp += frame->samples;
5340 } else {
5341 ast_debug_rtp(3, "(%p) RTP video difference is %d, ms is %u (%u), pred/ts/samples %u/%d/%d\n",
5342 instance, abs((int)rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
5343 rtp->lastovidtimestamp = rtp->lastts;
5344 }
5345 }
5346 } else {
5347 pred = rtp->lastotexttimestamp + frame->samples;
5348 /* Re-calculate last TS */
5349 rtp->lastts = rtp->lastts + ms;
5350 /* If it's close to our prediction, go for it */
5351 if (ast_tvzero(frame->delivery)) {
5352 if (abs((int)rtp->lastts - pred) < 7200) {
5353 rtp->lastts = pred;
5354 rtp->lastotexttimestamp += frame->samples;
5355 } else {
5356 ast_debug_rtp(3, "(%p) RTP other difference is %d, ms is %u, pred/ts/samples %u/%d/%d\n",
5357 instance, abs((int)rtp->lastts - pred), ms, rtp->lastts, pred, frame->samples);
5358 rtp->lastotexttimestamp = rtp->lastts;
5359 }
5360 }
5361 }
5362
5363 /* If we have been explicitly told to set the marker bit then do so */
5365 mark = 1;
5367 }
5368
5369 /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
5370 if (rtp->lastts > rtp->lastdigitts) {
5371 rtp->lastdigitts = rtp->lastts;
5372 }
5373
5374 /* Assume that the sequence number we expect to use is what will be used until proven otherwise */
5375 seqno = rtp->seqno;
5376
5377 /* If the frame contains sequence number information use it to influence our sequence number */
5379 if (rtp->expectedseqno != -1) {
5380 /* Determine where the frame from the core is in relation to where we expected */
5381 int difference = frame->seqno - rtp->expectedseqno;
5382
5383 /* If there is a substantial difference then we've either got packets really out
5384 * of order, or the source is RTP and it has cycled. If this happens we resync
5385 * the sequence number adjustments to this frame. If we also have packet loss
5386 * things won't be reflected correctly but it will sort itself out after a bit.
5387 */
5388 if (abs(difference) > 100) {
5389 difference = 0;
5390 }
5391
5392 /* Adjust the sequence number being used for this packet accordingly */
5393 seqno += difference;
5394
5395 if (difference >= 0) {
5396 /* This frame is on time or in the future */
5397 rtp->expectedseqno = frame->seqno + 1;
5398 rtp->seqno += difference;
5399 }
5400 } else {
5401 /* This is the first frame with sequence number we've seen, so start keeping track */
5402 rtp->expectedseqno = frame->seqno + 1;
5403 }
5404 } else {
5405 rtp->expectedseqno = -1;
5406 }
5407
5409 rtp->lastts = frame->ts * rate;
5410 }
5411
5412 ast_rtp_instance_get_remote_address(instance, &remote_address);
5413
5414 /* If we know the remote address construct a packet and send it out */
5415 if (!ast_sockaddr_isnull(&remote_address)) {
5416 int hdrlen = 12;
5417 int res;
5418 int ice;
5419 int ext = 0;
5420 int abs_send_time_id;
5421 int packet_len;
5422 unsigned char *rtpheader;
5423
5424 /* If the abs-send-time extension has been negotiated determine how much space we need */
5426 if (abs_send_time_id != -1) {
5427 /* 4 bytes for the shared information, 1 byte for identifier, 3 bytes for abs-send-time */
5428 hdrlen += 8;
5429 ext = 1;
5430 }
5431
5432 packet_len = frame->datalen + hdrlen;
5433 rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
5434
5435 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (ext << 28) | (codec << 16) | (seqno) | (mark << 23)));
5436 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
5437 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
5438
5439 /* We assume right now that we will only ever have the abs-send-time extension in the packet
5440 * which simplifies things a bit.
5441 */
5442 if (abs_send_time_id != -1) {
5443 unsigned int now_msw;
5444 unsigned int now_lsw;
5445
5446 /* This happens before being placed into the retransmission buffer so that when we
5447 * retransmit we only have to update the timestamp, not everything else.
5448 */
5449 put_unaligned_uint32(rtpheader + 12, htonl((0xBEDE << 16) | 1));
5450 rtpheader[16] = (abs_send_time_id << 4) | 2;
5451
5452 timeval2ntp(ast_tvnow(), &now_msw, &now_lsw);
5453 put_unaligned_time24(rtpheader + 17, now_msw, now_lsw);
5454 }
5455
5456 /* If retransmissions are enabled, we need to store this packet for future use */
5457 if (rtp->send_buffer) {
5458 struct ast_rtp_rtcp_nack_payload *payload;
5459
5460 payload = ast_malloc(sizeof(*payload) + packet_len);
5461 if (payload) {
5462 payload->size = packet_len;
5463 memcpy(payload->buf, rtpheader, packet_len);
5464 if (ast_data_buffer_put(rtp->send_buffer, rtp->seqno, payload) == -1) {
5465 ast_free(payload);
5466 }
5467 }
5468 }
5469
5470 res = rtp_sendto(instance, (void *)rtpheader, packet_len, 0, &remote_address, &ice);
5471 if (res < 0) {
5473 ast_debug_rtp(1, "(%p) RTP transmission error of packet %d to %s: %s\n",
5474 instance, rtp->seqno,
5475 ast_sockaddr_stringify(&remote_address),
5476 strerror(errno));
5478 /* Only give this error message once if we are not RTP debugging */
5480 ast_debug(0, "(%p) RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
5481 instance, ast_sockaddr_stringify(&remote_address));
5483 }
5484 } else {
5485 if (rtp->rtcp && rtp->rtcp->schedid < 0) {
5486 ast_debug_rtcp(2, "(%s) RTCP starting transmission in %u ms\n",
5488 ao2_ref(instance, +1);
5490 if (rtp->rtcp->schedid < 0) {
5491 ao2_ref(instance, -1);
5492 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
5493 }
5494 }
5495 }
5496
5497 if (rtp_debug_test_addr(&remote_address)) {
5498 ast_verbose("Sent RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
5499 ast_sockaddr_stringify(&remote_address),
5500 ice ? " (via ICE)" : "",
5501 codec, rtp->seqno, rtp->lastts, res - hdrlen);
5502 }
5503 }
5504
5505 /* If the sequence number that has been used doesn't match what we expected then this is an out of
5506 * order late packet, so we don't need to increment as we haven't yet gotten the expected frame from
5507 * the core.
5508 */
5509 if (seqno == rtp->seqno) {
5510 rtp->seqno++;
5511 }
5512
5513 return 0;
5514}
#define abs(x)
Definition f2c.h:195
struct ast_format * ast_format_g722
Built-in cached g722 format.
#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 3459 of file res_rtp_asterisk.c.

3460{
3461 return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
3462}

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
Warning
This code was written many years ago and it's unclear why we actually buffer OUTGOING T.140 text frames until a command is encountered but we do.

This may change in the future.

Definition at line 9395 of file res_rtp_asterisk.c.

9396{
9397 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9398 struct rtp_red *red = rtp->red;
9399
9400 if (!red) {
9401 return 0;
9402 }
9403
9404 if (frame->datalen > 0) {
9405 int space_available = 0;
9406
9407 if (red->t140.datalen > 0) {
9408 const unsigned char *primary = red->buf_data;
9409
9410 /* There is something already in the T.140 buffer */
9411 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9412 /* Flush the previous T.140 packet if it is a command */
9413 ast_rtp_write(instance, &rtp->red->t140);
9414 } else {
9415 primary = frame->data.ptr;
9416 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9417 /* Flush the previous T.140 packet if we are buffering a command now */
9418 ast_rtp_write(instance, &rtp->red->t140);
9419 }
9420 }
9421 }
9422
9423 /*
9424 * RED generation payload sizes are limited to 255 (UCHAR_MAX) bytes by virtue of
9425 * red->len being an array of usigned chars. If adding the current frame will
9426 * exceed that, we're going to flush the saved frame then try again. If the new
9427 * frame fits, great otherwise we're going to toss it. Without understanding
9428 * the purpose of the buffering, that's all we can do now.
9429 */
9430 space_available = UCHAR_MAX - red->t140.datalen;
9431
9432 if (frame->datalen > space_available) {
9433 ast_rtp_write(instance, &rtp->red->t140);
9434 /*
9435 * ast_rtp_write() calls red_t140_to_red() which resets red->t140.datalen
9436 * back to 0 so we now have UCHAR_MAX space available.
9437 */
9438 space_available = UCHAR_MAX;
9439 }
9440
9441 if (frame->datalen > space_available) {
9442 ast_log(LOG_WARNING, "%s: T.140 frame of %d bytes exceeds max of %u. Discarding.\n",
9444 frame->datalen, UCHAR_MAX);
9445 return -1;
9446 }
9447
9448 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
9449 red->t140.datalen += frame->datalen;
9450 red->t140.ts = frame->ts;
9451 }
9452
9453 return 0;
9454}
unsigned char buf_data[64000]

References ast_log, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_write(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, LOG_WARNING, 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 9357 of file res_rtp_asterisk.c.

9358{
9359 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9360 int x;
9361
9362 rtp->red = ast_calloc(1, sizeof(*rtp->red));
9363 if (!rtp->red) {
9364 return -1;
9365 }
9366
9369 rtp->red->t140.data.ptr = &rtp->red->buf_data;
9370
9371 rtp->red->t140red = rtp->red->t140;
9372 rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
9373
9374 rtp->red->num_gen = generations;
9375 rtp->red->hdrlen = generations * 4 + 1;
9376
9377 for (x = 0; x < generations; x++) {
9378 rtp->red->pt[x] = payloads[x];
9379 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
9380 rtp->red->t140red_data[x*4] = rtp->red->pt[x];
9381 }
9382 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
9383 rtp->red->schedid = ast_sched_add(rtp->sched, buffer_time, red_write, instance);
9384
9385 return 0;
9386}
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 10343 of file res_rtp_asterisk.c.

10344{
10345 struct ast_config *cfg;
10346 const char *s;
10347 struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10348
10349#ifdef HAVE_PJPROJECT
10350 struct ast_variable *var;
10351 struct ast_ice_host_candidate *candidate;
10352 int acl_subscription_flag = 0;
10353#endif
10354
10355 cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
10356 if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
10357 return 0;
10358 }
10359
10360#ifdef SO_NO_CHECK
10361 nochecksums = 0;
10362#endif
10363
10372
10373 /** This resource is not "reloaded" so much as unloaded and loaded again.
10374 * In the case of the TURN related variables, the memory referenced by a
10375 * previously loaded instance *should* have been released when the
10376 * corresponding pool was destroyed. If at some point in the future this
10377 * resource were to support ACTUAL live reconfiguration and did NOT release
10378 * the pool this will cause a small memory leak.
10379 */
10380
10381#ifdef HAVE_PJPROJECT
10382 icesupport = DEFAULT_ICESUPPORT;
10383 stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE;
10384 turnport = DEFAULT_TURN_PORT;
10385 clean_stunaddr();
10386 turnaddr = pj_str(NULL);
10387 turnusername = pj_str(NULL);
10388 turnpassword = pj_str(NULL);
10389 host_candidate_overrides_clear();
10390#endif
10391
10392#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10393 dtls_mtu = DEFAULT_DTLS_MTU;
10394#endif
10395
10396 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
10397 rtpstart = atoi(s);
10402 }
10403 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
10404 rtpend = atoi(s);
10409 }
10410 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
10411 rtcpinterval = atoi(s);
10412 if (rtcpinterval == 0)
10413 rtcpinterval = 0; /* Just so we're clear... it's zero */
10415 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
10418 }
10419 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
10420#ifdef SO_NO_CHECK
10421 nochecksums = ast_false(s) ? 1 : 0;
10422#else
10423 if (ast_false(s))
10424 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10425#endif
10426 }
10427 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
10428 dtmftimeout = atoi(s);
10429 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
10430 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
10433 };
10434 }
10435 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
10436 if (ast_true(s)) {
10438 } else if (!strcasecmp(s, "seqno")) {
10440 } else {
10442 }
10443 }
10444 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
10445 if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
10446 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
10449 }
10451 }
10452 if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
10454 }
10455#ifdef HAVE_PJPROJECT
10456 if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
10457 icesupport = ast_true(s);
10458 }
10459 if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
10460 stun_software_attribute = ast_true(s);
10461 }
10462 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr_reresolve_ttl_0"))) {
10463 stunaddr_reresolve_ttl_0 = ast_true(s);
10464 }
10465 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
10466 char *hostport, *host, *port;
10467 unsigned int port_parsed = STANDARD_STUN_PORT;
10468 struct ast_sockaddr stunaddr_parsed;
10469
10470 hostport = ast_strdupa(s);
10471
10472 if (!ast_parse_arg(hostport, PARSE_ADDR, &stunaddr_parsed)) {
10473 ast_debug_stun(3, "stunaddr = '%s' does not need name resolution\n",
10474 ast_sockaddr_stringify_host(&stunaddr_parsed));
10475 if (!ast_sockaddr_port(&stunaddr_parsed)) {
10476 ast_sockaddr_set_port(&stunaddr_parsed, STANDARD_STUN_PORT);
10477 }
10478 ast_rwlock_wrlock(&stunaddr_lock);
10479 ast_sockaddr_to_sin(&stunaddr_parsed, &stunaddr);
10480 /* Set stunaddr_ttl = -1 to indicate no resolution required in the future */
10481 stunaddr_ttl = -1;
10482 ast_rwlock_unlock(&stunaddr_lock);
10483 } else if (ast_sockaddr_split_hostport(hostport, &host, &port, 0)) {
10484 if (port) {
10485 ast_parse_arg(port, PARSE_UINT32|PARSE_IN_RANGE, &port_parsed, 1, 65535);
10486 }
10487
10488 ast_rwlock_wrlock(&stunaddr_lock);
10489
10490 stunaddr.sin_port = htons(port_parsed);
10491 ast_free(stun_hostname);
10492 stun_hostname = ast_strdup(host);
10493 if (!stun_hostname) {
10494 ast_log(LOG_ERROR, "Failed to set stun_hostname from '%s'", host);
10495 } else {
10496 stunaddr_resolver = ast_dns_resolve_recurring(host, T_A, C_IN,
10497 &stunaddr_resolve_callback, NULL);
10498 if (!stunaddr_resolver) {
10499 ast_log(LOG_ERROR, "Failed to setup recurring DNS resolution of stunaddr '%s'",
10500 host);
10501 } else {
10502 ast_debug_stun(2, "Attemping to start recurring stun hostname resolution for '%s'\n", stun_hostname);
10503 }
10504 /*
10505 * Set stunaddr_ttl = 0 to indicate resolution is required.
10506 * If a later query returns a positive ttl, great. We'll use the results
10507 * of the last query until it expires. If it returns 0, we'll resolve
10508 * every time we need it.
10509 */
10510 stunaddr_ttl = 0;
10511 }
10512 ast_rwlock_unlock(&stunaddr_lock);
10513
10514
10515 } else {
10516 ast_log(LOG_ERROR, "Failed to parse stunaddr '%s'", hostport);
10517 }
10518 }
10519 if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
10520 struct sockaddr_in addr;
10521 addr.sin_port = htons(DEFAULT_TURN_PORT);
10522 if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
10523 ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
10524 } else {
10525 pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
10526 /* ntohs() is not a bug here. The port number is used in host byte order with
10527 * a pjnat API. */
10528 turnport = ntohs(addr.sin_port);
10529 }
10530 }
10531 if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
10532 pj_strdup2_with_null(pool, &turnusername, s);
10533 }
10534 if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
10535 pj_strdup2_with_null(pool, &turnpassword, s);
10536 }
10537
10538 AST_RWLIST_WRLOCK(&host_candidates);
10539 for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
10540 struct ast_sockaddr local_addr, advertised_addr;
10541 unsigned int include_local_address = 0;
10542 char *sep;
10543
10544 ast_sockaddr_setnull(&local_addr);
10545 ast_sockaddr_setnull(&advertised_addr);
10546
10547 if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
10548 ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
10549 continue;
10550 }
10551
10552 sep = strchr((char *)var->value,',');
10553 if (sep) {
10554 *sep = '\0';
10555 sep++;
10556 sep = ast_skip_blanks(sep);
10557 include_local_address = strcmp(sep, "include_local_address") == 0;
10558 }
10559
10560 if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
10561 ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
10562 continue;
10563 }
10564
10565 if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
10566 ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
10567 break;
10568 }
10569
10570 candidate->include_local = include_local_address;
10571
10572 ast_sockaddr_copy(&candidate->local, &local_addr);
10573 ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
10574
10575 AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
10576 }
10577 AST_RWLIST_UNLOCK(&host_candidates);
10578
10579 ast_rwlock_wrlock(&ice_acl_lock);
10580 ast_rwlock_wrlock(&stun_acl_lock);
10581
10582 ice_acl = ast_free_acl_list(ice_acl);
10583 stun_acl = ast_free_acl_list(stun_acl);
10584
10585 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
10586 const char* sense = NULL;
10587 struct ast_acl_list **acl = NULL;
10588 if (strncasecmp(var->name, "ice_", 4) == 0) {
10589 sense = var->name + 4;
10590 acl = &ice_acl;
10591 } else if (strncasecmp(var->name, "stun_", 5) == 0) {
10592 sense = var->name + 5;
10593 acl = &stun_acl;
10594 } else {
10595 continue;
10596 }
10597
10598 if (strcasecmp(sense, "blacklist") == 0) {
10599 sense = "deny";
10600 }
10601
10602 if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
10603 continue;
10604 }
10605
10606 ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
10607 }
10608 ast_rwlock_unlock(&ice_acl_lock);
10609 ast_rwlock_unlock(&stun_acl_lock);
10610
10611 if (acl_subscription_flag && !acl_change_sub) {
10615 } else if (!acl_subscription_flag && acl_change_sub) {
10617 }
10618#endif
10619#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10620 if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
10621 if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
10622 ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
10624 dtls_mtu = DEFAULT_DTLS_MTU;
10625 }
10626 }
10627#endif
10628
10629 ast_config_destroy(cfg);
10630
10631 /* Choosing an odd start port casues issues (like a potential infinite loop) and as odd parts are not
10632 chosen anyway, we are going to round up and issue a warning */
10633 if (rtpstart & 1) {
10634 rtpstart++;
10635 ast_log(LOG_WARNING, "Odd start value for RTP port in rtp.conf, rounding up to %d\n", rtpstart);
10636 }
10637
10638 if (rtpstart >= rtpend) {
10639 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
10642 }
10643 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
10644 return 0;
10645}
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:365
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition chan_iax2.c:1597
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.
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#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.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_INSERT_TAIL
#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:1101
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:1155
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1212
#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:2233
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:2250
char *attribute_pure ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition strings.h:161
Wrapper for an ast_acl linked list.
Definition acl.h:76
Structure used to handle boolean flags.
Definition utils.h:220
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
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, 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_strdup, 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, ast_variable::next, 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 3545 of file res_rtp_asterisk.c.

3546{
3547 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3548 int hdrlen = 12;
3549 int res;
3550
3551 if ((res = __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1)) > 0) {
3552 rtp->txcount++;
3553 rtp->txoctetcount += (res - hdrlen);
3554 }
3555
3556 return res;
3557}

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 7681 of file res_rtp_asterisk.c.

7682{
7683 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
7684 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7685 unsigned char *rtcpheader;
7686 char bdata[1024];
7687 struct rtp_transport_wide_cc_packet_statistics *first_packet;
7688 struct rtp_transport_wide_cc_packet_statistics *previous_packet;
7689 int i;
7690 int status_vector_chunk_bits = 14;
7691 uint16_t status_vector_chunk = (1 << 15) | (1 << 14);
7692 int run_length_chunk_count = 0;
7693 int run_length_chunk_status = -1;
7694 int packet_len = 20;
7695 int delta_len = 0;
7696 int packet_count = 0;
7697 unsigned int received_msw;
7698 unsigned int received_lsw;
7699 struct ast_sockaddr remote_address = { { 0, } };
7700 int res;
7701 int ice;
7702 unsigned int large_delta_count = 0;
7703 unsigned int small_delta_count = 0;
7704 unsigned int lost_count = 0;
7705
7706 if (!rtp || !rtp->rtcp || rtp->transport_wide_cc.schedid == -1) {
7707 ao2_ref(instance, -1);
7708 return 0;
7709 }
7710
7711 ao2_lock(instance);
7712
7713 /* If no packets have been received then do nothing */
7715 ao2_unlock(instance);
7716 return 1000;
7717 }
7718
7719 rtcpheader = (unsigned char *)bdata;
7720
7721 /* The first packet in the vector acts as our base sequence number and reference time */
7723 previous_packet = first_packet;
7724
7725 /* We go through each packet that we have statistics for, adding it either to a status
7726 * vector chunk or a run length chunk. The code tries to be as efficient as possible to
7727 * reduce packet size and will favor run length chunks when it makes sense.
7728 */
7729 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7731 int lost = 0;
7732 int res = 0;
7733
7735
7736 packet_count++;
7737
7738 if (first_packet != statistics) {
7739 /* The vector stores statistics in a sorted fashion based on the sequence
7740 * number. This ensures we can detect any packets that have been lost/not
7741 * received by comparing the sequence numbers.
7742 */
7743 lost = statistics->seqno - (previous_packet->seqno + 1);
7744 lost_count += lost;
7745 }
7746
7747 while (lost) {
7748 /* We append a not received status until all the lost packets have been accounted for */
7749 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7750 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 0);
7751 packet_count++;
7752
7753 /* If there is no more room left for storing packets stop now, we leave 20
7754 * extra bits at the end just in case.
7755 */
7756 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7757 res = -1;
7758 break;
7759 }
7760
7761 lost--;
7762 }
7763
7764 /* If the lost packet appending bailed out because we have no more space, then exit here too */
7765 if (res) {
7766 break;
7767 }
7768
7769 /* Per the spec the delta is in increments of 250 */
7770 statistics->delta = ast_tvdiff_us(statistics->received, previous_packet->received) / 250;
7771
7772 /* Based on the delta determine the status of this packet */
7773 if (statistics->delta < 0 || statistics->delta > 127) {
7774 /* Large or negative delta */
7775 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7776 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 2);
7777 delta_len += 2;
7778 large_delta_count++;
7779 } else {
7780 /* Small delta */
7781 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7782 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 1);
7783 delta_len += 1;
7784 small_delta_count++;
7785 }
7786
7787 previous_packet = statistics;
7788
7789 /* If there is no more room left in the packet stop handling of any subsequent packets */
7790 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7791 break;
7792 }
7793 }
7794
7795 if (status_vector_chunk_bits != 14) {
7796 /* If the status vector chunk has packets in it then place it in the RTCP packet */
7797 put_unaligned_uint16(rtcpheader + packet_len, htons(status_vector_chunk));
7798 packet_len += 2;
7799 } else if (run_length_chunk_count) {
7800 /* If there is a run length chunk in progress then place it in the RTCP packet */
7801 put_unaligned_uint16(rtcpheader + packet_len, htons((0 << 15) | (run_length_chunk_status << 13) | run_length_chunk_count));
7802 packet_len += 2;
7803 }
7804
7805 /* We iterate again to build delta chunks */
7806 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7808
7810
7811 if (statistics->delta < 0 || statistics->delta > 127) {
7812 /* We need 2 bytes to store this delta */
7813 put_unaligned_uint16(rtcpheader + packet_len, htons(statistics->delta));
7814 packet_len += 2;
7815 } else {
7816 /* We can store this delta in 1 byte */
7817 rtcpheader[packet_len] = statistics->delta;
7818 packet_len += 1;
7819 }
7820
7821 /* If this is the last packet handled by the run length chunk or status vector chunk code
7822 * then we can go no further.
7823 */
7824 if (statistics == previous_packet) {
7825 break;
7826 }
7827 }
7828
7829 /* Zero pad the end of the packet */
7830 while (packet_len % 4) {
7831 rtcpheader[packet_len++] = 0;
7832 }
7833
7834 /* Add the general RTCP header information */
7835 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC << 24)
7836 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
7837 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
7838 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
7839
7840 /* Add the transport-cc specific header information */
7841 put_unaligned_uint32(rtcpheader + 12, htonl((first_packet->seqno << 16) | packet_count));
7842
7843 timeval2ntp(first_packet->received, &received_msw, &received_lsw);
7844 put_unaligned_time24(rtcpheader + 16, received_msw, received_lsw);
7845 rtcpheader[19] = rtp->transport_wide_cc.feedback_count;
7846
7847 /* The packet is now fully constructed so send it out */
7848 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
7849
7850 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",
7851 instance, packet_len, ast_rtp_instance_get_channel_id(instance), packet_count, small_delta_count, large_delta_count, lost_count);
7852
7853 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
7854 if (res < 0) {
7855 ast_log(LOG_ERROR, "RTCP transport-cc feedback error to %s due to %s\n",
7856 ast_sockaddr_stringify(&remote_address), strerror(errno));
7857 }
7858
7860
7862
7863 ao2_unlock(instance);
7864
7865 return 1000;
7866}
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 7640 of file res_rtp_asterisk.c.

7642{
7643 if (*run_length_chunk_status != status) {
7644 while (*run_length_chunk_count > 0 && *run_length_chunk_count < 8) {
7645 /* Realistically it only makes sense to use a run length chunk if there were 8 or more
7646 * consecutive packets of the same type, otherwise we could end up making the packet larger
7647 * if we have lots of small blocks of the same type. To help with this we backfill the status
7648 * vector (since it always represents 7 packets). Best case we end up with only that single
7649 * status vector and the rest are run length chunks.
7650 */
7651 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7652 status_vector_chunk, *run_length_chunk_status);
7653 *run_length_chunk_count -= 1;
7654 }
7655
7656 if (*run_length_chunk_count) {
7657 /* There is a run length chunk which needs to be written out */
7658 put_unaligned_uint16(rtcpheader + *packet_len, htons((0 << 15) | (*run_length_chunk_status << 13) | *run_length_chunk_count));
7659 *packet_len += 2;
7660 }
7661
7662 /* In all cases the run length chunk has to be reset */
7663 *run_length_chunk_count = 0;
7664 *run_length_chunk_status = -1;
7665
7666 if (*status_vector_chunk_bits == 14) {
7667 /* We aren't in the middle of a status vector so we can try for a run length chunk */
7668 *run_length_chunk_status = status;
7669 *run_length_chunk_count = 1;
7670 } else {
7671 /* We're doing a status vector so populate it accordingly */
7672 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7673 status_vector_chunk, status);
7674 }
7675 } else {
7676 /* This is easy, the run length chunk count can just get bumped up */
7677 *run_length_chunk_count += 1;
7678 }
7679}
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 7611 of file res_rtp_asterisk.c.

7613{
7614 /* Appending this status will use up 2 bits */
7615 *status_vector_chunk_bits -= 2;
7616
7617 /* We calculate which bits we want to update the status of. Since a status vector
7618 * is 16 bits we take away 2 (for the header), and then we take away any that have
7619 * already been used.
7620 */
7621 *status_vector_chunk |= (status << (16 - 2 - (14 - *status_vector_chunk_bits)));
7622
7623 /* If there are still bits available we can return early */
7624 if (*status_vector_chunk_bits) {
7625 return;
7626 }
7627
7628 /* Otherwise we have to place this chunk into the packet */
7629 put_unaligned_uint16(rtcpheader + *packet_len, htons(*status_vector_chunk));
7630 *status_vector_chunk_bits = 14;
7631
7632 /* The first bit being 1 indicates that this is a status vector chunk and the second
7633 * bit being 1 indicates that we are using 2 bits to represent each status for a
7634 * packet.
7635 */
7636 *status_vector_chunk = (1 << 15) | (1 << 14);
7637 *packet_len += 2;
7638}

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 7605 of file res_rtp_asterisk.c.

7607{
7608 return a.seqno - b.seqno;
7609}
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 5567 of file res_rtp_asterisk.c.

5568{
5569 unsigned char *rtcpheader;
5570 unsigned char bdata[1024];
5571 int packet_len = 0;
5572 int fir_len = 20;
5573 int ice;
5574 int res;
5575 int sr;
5576 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5577
5578 if (!rtp || !rtp->rtcp) {
5579 return;
5580 }
5581
5582 if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5583 /*
5584 * RTCP was stopped.
5585 */
5586 return;
5587 }
5588
5589 if (!rtp->themssrc_valid) {
5590 /* We don't know their SSRC value so we don't know who to update. */
5591 return;
5592 }
5593
5594 /* Prepare RTCP FIR (PT=206, FMT=4) */
5595 rtp->rtcp->firseq++;
5596 if(rtp->rtcp->firseq == 256) {
5597 rtp->rtcp->firseq = 0;
5598 }
5599
5600 rtcpheader = bdata;
5601
5602 ao2_lock(instance);
5603 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5604 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5605
5606 if (res == 0 || res == 1) {
5607 ao2_unlock(instance);
5608 return;
5609 }
5610
5611 packet_len += res;
5612
5613 put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((fir_len/4)-1)));
5614 put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5615 put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(rtp->themssrc));
5616 put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(rtp->themssrc)); /* FCI: SSRC */
5617 put_unaligned_uint32(rtcpheader + packet_len + 16, htonl(rtp->rtcp->firseq << 24)); /* FCI: Sequence number */
5618 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + fir_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5619 if (res < 0) {
5620 ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
5621 } else {
5622 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5623 }
5624
5625 ao2_unlock(instance);
5626}

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 5628 of file res_rtp_asterisk.c.

5629{
5630 struct ast_rtp_rtcp_feedback *feedback = frame->data.ptr;
5631 unsigned char *rtcpheader;
5632 unsigned char bdata[1024];
5633 int remb_len = 24;
5634 int ice;
5635 int res;
5636 int sr = 0;
5637 int packet_len = 0;
5638 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5639
5640 if (feedback->fmt != AST_RTP_RTCP_FMT_REMB) {
5641 ast_debug_rtcp(1, "(%p) RTCP provided feedback frame of format %d to write, but only REMB is supported\n",
5642 instance, feedback->fmt);
5643 return;
5644 }
5645
5646 if (!rtp || !rtp->rtcp) {
5647 return;
5648 }
5649
5650 /* If REMB support is not enabled don't send this RTCP packet */
5652 ast_debug_rtcp(1, "(%p) RTCP provided feedback REMB report to write, but REMB support not enabled\n",
5653 instance);
5654 return;
5655 }
5656
5657 if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5658 /*
5659 * RTCP was stopped.
5660 */
5661 return;
5662 }
5663
5664 rtcpheader = bdata;
5665
5666 ao2_lock(instance);
5667 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5668 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5669
5670 if (res == 0 || res == 1) {
5671 ao2_unlock(instance);
5672 return;
5673 }
5674
5675 packet_len += res;
5676
5677 put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (AST_RTP_RTCP_FMT_REMB << 24) | (RTCP_PT_PSFB << 16) | ((remb_len/4)-1)));
5678 put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5679 put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(0)); /* Per the draft, this should always be 0 */
5680 put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(('R' << 24) | ('E' << 16) | ('M' << 8) | ('B'))); /* Unique identifier 'R' 'E' 'M' 'B' */
5681 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 */
5682 put_unaligned_uint32(rtcpheader + packet_len + 20, htonl(rtp->ssrc)); /* The SSRC this feedback message applies to */
5683 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + remb_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5684 if (res < 0) {
5685 ast_log(LOG_ERROR, "RTCP PSFB transmission error: %s\n", strerror(errno));
5686 } else {
5687 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5688 }
5689
5690 ao2_unlock(instance);
5691}

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 4777 of file res_rtp_asterisk.c.

4778{
4779 unsigned int sec, usec, frac;
4780 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
4781 usec = tv.tv_usec;
4782 /*
4783 * Convert usec to 0.32 bit fixed point without overflow.
4784 *
4785 * = usec * 2^32 / 10^6
4786 * = usec * 2^32 / (2^6 * 5^6)
4787 * = usec * 2^26 / 5^6
4788 *
4789 * The usec value needs 20 bits to represent 999999 usec. So
4790 * splitting the 2^26 to get the most precision using 32 bit
4791 * values gives:
4792 *
4793 * = ((usec * 2^12) / 5^6) * 2^14
4794 *
4795 * Splitting the division into two stages preserves all the
4796 * available significant bits of usec over doing the division
4797 * all at once.
4798 *
4799 * = ((((usec * 2^12) / 5^3) * 2^7) / 5^3) * 2^7
4800 */
4801 frac = ((((usec << 12) / 125) << 7) / 125) << 7;
4802 *msw = sec;
4803 *lsw = frac;
4804}

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 10764 of file res_rtp_asterisk.c.

10765{
10768
10769#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10770 if (dtls_bio_methods) {
10771 BIO_meth_free(dtls_bio_methods);
10772 }
10773#endif
10774
10775#ifdef HAVE_PJPROJECT
10776 host_candidate_overrides_clear();
10777 pj_thread_register_check();
10778 rtp_terminate_pjproject();
10779
10781 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10782 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10783 clean_stunaddr();
10784#endif
10785
10786 return 0;
10787}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408

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 6565 of file res_rtp_asterisk.c.

6566{
6568 rtp->rtcp->normdevrtt,
6569 rtp->rtcp->normdev_rxjitter,
6570 rtp->rtcp->stdev_rxjitter,
6571 rtp->rtcp->normdev_rxlost);
6572
6573 if (rtp->rtcp->rxmes_count == 0) {
6574 rtp->rtcp->minrxmes = rtp->rxmes;
6575 }
6576 if (rtp->rxmes < rtp->rtcp->minrxmes) {
6577 rtp->rtcp->minrxmes = rtp->rxmes;
6578 }
6579 if (rtp->rxmes > rtp->rtcp->maxrxmes) {
6580 rtp->rtcp->maxrxmes = rtp->rxmes;
6581 }
6582
6584 &rtp->rtcp->stdev_rxmes, &rtp->rtcp->rxmes_count);
6585
6586 ast_debug_rtcp(2, " %s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6588 rtp->rtcp->normdevrtt,
6589 rtp->rtcp->normdev_rxjitter,
6590 rtp->rtcp->stdev_rxjitter,
6591 rtp->rtcp->normdev_rxlost, rtp->rxmes);
6592}
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

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_rxjitter, ast_rtcp::normdev_rxlost, ast_rtcp::normdev_rxmes, ast_rtcp::normdevrtt, ast_rtp::owner, ast_rtp::rtcp, 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 6401 of file res_rtp_asterisk.c.

6402{
6403 double reported_lost;
6404
6405 rtp->rtcp->reported_lost = lost_packets;
6406
6407 /*
6408 * lost_packets contains the cumulative number of lost packets as reported in
6409 * the peer's RTCP RR/SR report block (RFC 3550). Calculate the number of lost
6410 * packets in the current interval based on the difference from the previous
6411 * count.
6412 */
6413 reported_lost = (double)lost_packets - (double)rtp->rtcp->last_reported_lost;
6414 rtp->rtcp->last_reported_lost = lost_packets;
6415
6416 if (reported_lost < 0) {
6417 reported_lost = 0;
6418 }
6419
6420 if (rtp->rtcp->reported_lost_count == 0) {
6421 rtp->rtcp->reported_minlost = reported_lost;
6422 }
6423 if (reported_lost < rtp->rtcp->reported_minlost) {
6424 rtp->rtcp->reported_minlost = reported_lost;
6425 }
6426 if (reported_lost > rtp->rtcp->reported_maxlost) {
6427 rtp->rtcp->reported_maxlost = reported_lost;
6428 }
6429
6432}
unsigned int last_reported_lost
unsigned int reported_lost_count

References calc_mean_and_standard_deviation(), ast_rtcp::last_reported_lost, 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 6530 of file res_rtp_asterisk.c.

6531{
6532 double mes = calc_media_experience_score(rtp->owner,
6533 rtp->rtcp->normdevrtt,
6537
6538 rtp->rtcp->reported_mes = mes;
6539 if (rtp->rtcp->reported_mes_count == 0) {
6540 rtp->rtcp->reported_minmes = mes;
6541 }
6542 if (mes < rtp->rtcp->reported_minmes) {
6543 rtp->rtcp->reported_minmes = mes;
6544 }
6545 if (mes > rtp->rtcp->reported_maxmes) {
6546 rtp->rtcp->reported_maxmes = mes;
6547 }
6548
6551
6552 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6554 rtp->rtcp->normdevrtt,
6557 rtp->rtcp->reported_normdev_lost, mes);
6558}
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_maxmes, ast_rtcp::reported_mes, ast_rtcp::reported_mes_count, 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_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 6319 of file res_rtp_asterisk.c.

6320{
6321 struct timeval now;
6322 struct timeval rtt_tv;
6323 unsigned int msw;
6324 unsigned int lsw;
6325 unsigned int rtt_msw;
6326 unsigned int rtt_lsw;
6327 unsigned int lsr_a;
6328 unsigned int rtt;
6329
6330 gettimeofday(&now, NULL);
6331 timeval2ntp(now, &msw, &lsw);
6332
6333 lsr_a = ((msw & 0x0000ffff) << 16) | ((lsw & 0xffff0000) >> 16);
6334 if (lsr_a - dlsr < lsr) {
6335 return 1;
6336 }
6337
6338 rtt = lsr_a - lsr - dlsr;
6339 rtt_msw = (rtt & 0xffff0000) >> 16;
6340 rtt_lsw = (rtt & 0x0000ffff);
6341 rtt_tv.tv_sec = rtt_msw;
6342 /*
6343 * Convert 16.16 fixed point rtt_lsw to usec without
6344 * overflow.
6345 *
6346 * = rtt_lsw * 10^6 / 2^16
6347 * = rtt_lsw * (2^6 * 5^6) / 2^16
6348 * = rtt_lsw * 5^6 / 2^10
6349 *
6350 * The rtt_lsw value is in 16.16 fixed point format and 5^6
6351 * requires 14 bits to represent. We have enough space to
6352 * directly do the conversion because there is no integer
6353 * component in rtt_lsw.
6354 */
6355 rtt_tv.tv_usec = (rtt_lsw * 15625) >> 10;
6356 rtp->rtcp->rtt = (double)rtt_tv.tv_sec + ((double)rtt_tv.tv_usec / 1000000);
6357 rtp->rtcp->accumulated_transit += rtp->rtcp->rtt;
6358
6359 if (rtp->rtcp->rtt_count == 0 || rtp->rtcp->minrtt > rtp->rtcp->rtt) {
6360 rtp->rtcp->minrtt = rtp->rtcp->rtt;
6361 }
6362 if (rtp->rtcp->maxrtt < rtp->rtcp->rtt) {
6363 rtp->rtcp->maxrtt = rtp->rtcp->rtt;
6364 }
6365
6367 &rtp->rtcp->stdevrtt, &rtp->rtcp->rtt_count);
6368
6369 return 0;
6370}
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 = ASTERISK_GPL_KEY , .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 10798 of file res_rtp_asterisk.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 10798 of file res_rtp_asterisk.c.

◆ asterisk_rtp_engine

struct ast_rtp_engine asterisk_rtp_engine
static

Definition at line 2576 of file res_rtp_asterisk.c.

2576 {
2577 .name = "asterisk",
2578 .new = ast_rtp_new,
2579 .destroy = ast_rtp_destroy,
2580 .dtmf_begin = ast_rtp_dtmf_begin,
2581 .dtmf_end = ast_rtp_dtmf_end,
2582 .dtmf_end_with_duration = ast_rtp_dtmf_end_with_duration,
2583 .dtmf_mode_set = ast_rtp_dtmf_mode_set,
2584 .dtmf_mode_get = ast_rtp_dtmf_mode_get,
2585 .update_source = ast_rtp_update_source,
2586 .change_source = ast_rtp_change_source,
2587 .write = ast_rtp_write,
2588 .read = ast_rtp_read,
2589 .prop_set = ast_rtp_prop_set,
2590 .fd = ast_rtp_fd,
2591 .remote_address_set = ast_rtp_remote_address_set,
2592 .red_init = rtp_red_init,
2593 .red_buffer = rtp_red_buffer,
2594 .local_bridge = ast_rtp_local_bridge,
2595 .get_stat = ast_rtp_get_stat,
2596 .dtmf_compatible = ast_rtp_dtmf_compatible,
2597 .stun_request = ast_rtp_stun_request,
2598 .stop = ast_rtp_stop,
2599 .qos = ast_rtp_qos_set,
2600 .sendcng = ast_rtp_sendcng,
2601#ifdef HAVE_PJPROJECT
2602 .ice = &ast_rtp_ice,
2603#endif
2604#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
2605 .dtls = &ast_rtp_dtls,
2606 .activate = ast_rtp_activate,
2607#endif
2608 .ssrc_get = ast_rtp_get_ssrc,
2609 .cname_get = ast_rtp_get_cname,
2610 .set_remote_ssrc = ast_rtp_set_remote_ssrc,
2611 .set_stream_num = ast_rtp_set_stream_num,
2612 .extension_enable = ast_rtp_extension_enable,
2613 .bundle = ast_rtp_bundle,
2614#ifdef TEST_FRAMEWORK
2615 .test = &ast_rtp_test,
2616#endif
2617};
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 void ast_rtp_update_source(struct ast_rtp_instance *instance)
static int ast_rtp_destroy(struct ast_rtp_instance *instance)
static int ast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
static struct ast_frame * ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
static void ast_rtp_set_stream_num(struct ast_rtp_instance *instance, int stream_num)
static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
static void ast_rtp_change_source(struct ast_rtp_instance *instance)
static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
static void ast_rtp_stop(struct ast_rtp_instance *instance)
static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
static void ast_rtp_set_remote_ssrc(struct ast_rtp_instance *instance, unsigned int ssrc)
static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
static int ast_rtp_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get(struct ast_rtp_instance *instance)
static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level)
generate comfort noice (CNG)
static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
static const char * ast_rtp_get_cname(struct ast_rtp_instance *instance)
static int ast_rtp_extension_enable(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)

Referenced by load_module(), and unload_module().

◆ cli_rtp

struct ast_cli_entry cli_rtp[]
static

Definition at line 10330 of file res_rtp_asterisk.c.

10330 {
10331 AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
10332 AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
10333 AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
10334 AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
10335#ifdef AST_DEVMODE
10336 AST_CLI_DEFINE(handle_cli_rtp_drop_incoming_packets, "Drop RTP incoming packets"),
10337#endif
10338#ifdef HAVE_PJPROJECT
10339 AST_CLI_DEFINE(handle_cli_rtp_refresh_stun, "Force a resolution of the STUN hostname"),
10340#endif
10341};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
static char * handle_cli_rtp_settings(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_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)

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().