Asterisk - The Open Source Telephony Project GIT-master-70eff7f
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_moduleAST_MODULE_SELF_SYM (void)
 
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
 
static int ast_rtcp_calculate_sr_rr_statistics (struct ast_rtp_instance *instance, struct ast_rtp_rtcp_report *rtcp_report, struct ast_sockaddr remote_address, int ice, int sr)
 
static int ast_rtcp_generate_compound_prefix (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
 
static int ast_rtcp_generate_nack (struct ast_rtp_instance *instance, unsigned char *rtcpheader)
 
static int ast_rtcp_generate_report (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report, int *sr)
 
static int ast_rtcp_generate_sdes (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report)
 
static struct ast_frameast_rtcp_interpret (struct ast_rtp_instance *instance, struct ast_srtp *srtp, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
 
static struct ast_frameast_rtcp_read (struct ast_rtp_instance *instance)
 
static int ast_rtcp_write (const void *data)
 Write a RTCP packet to the far end.
 
static int ast_rtp_bundle (struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
 
static void ast_rtp_change_source (struct ast_rtp_instance *instance)
 
static int ast_rtp_destroy (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_begin (struct ast_rtp_instance *instance, char digit)
 
static int ast_rtp_dtmf_compatible (struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
 
static int ast_rtp_dtmf_continuation (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_end (struct ast_rtp_instance *instance, char digit)
 
static int ast_rtp_dtmf_end_with_duration (struct ast_rtp_instance *instance, char digit, unsigned int duration)
 
static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_mode_set (struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
 
static int ast_rtp_extension_enable (struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
 
static int ast_rtp_fd (struct ast_rtp_instance *instance, int rtcp)
 
static const char * ast_rtp_get_cname (struct ast_rtp_instance *instance)
 
static unsigned int ast_rtp_get_ssrc (struct ast_rtp_instance *instance)
 
static int ast_rtp_get_stat (struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
 
static struct ast_frameast_rtp_interpret (struct ast_rtp_instance *instance, struct ast_srtp *srtp, const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno, unsigned int bundled)
 
static int ast_rtp_local_bridge (struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
 
static int ast_rtp_new (struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
 
static void ast_rtp_prop_set (struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
 
static int ast_rtp_qos_set (struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
 
static struct ast_frameast_rtp_read (struct ast_rtp_instance *instance, int rtcp)
 
static void ast_rtp_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
 
static int ast_rtp_rtcp_handle_nack (struct ast_rtp_instance *instance, unsigned int *nackdata, unsigned int position, unsigned int length)
 
static int ast_rtp_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_framecreate_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_frameprocess_cn_rfc3389 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
 
static struct ast_frameprocess_dtmf_cisco (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
 
static void process_dtmf_rfc2833 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark, struct frame_list *frames)
 
static void put_unaligned_time24 (void *p, uint32_t time_msw, uint32_t time_lsw)
 
static struct ast_framered_t140_to_red (struct rtp_red *red)
 
static int red_write (const void *data)
 Write t140 redundancy frame.
 
static int reload_module (void)
 
static int rtcp_debug_test_addr (struct ast_sockaddr *addr)
 
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
 
static int rtcp_mux (struct ast_rtp *rtp, const unsigned char *packet)
 
static const char * rtcp_payload_subtype2str (unsigned int pt, unsigned int subtype)
 
static const char * rtcp_payload_type2str (unsigned int pt)
 
static int rtcp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
 
static int rtcp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 
static int rtp_allocate_transport (struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 
static void rtp_deallocate_transport (struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 
static int rtp_debug_test_addr (struct ast_sockaddr *addr)
 
static char * rtp_do_debug_ip (struct ast_cli_args *a)
 
static struct ast_rtp_instancertp_find_instance_by_media_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
 
static struct ast_rtp_instancertp_find_instance_by_packet_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
 
static void rtp_instance_parse_extmap_extensions (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *extension, int len)
 
static void rtp_instance_parse_transport_wide_cc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *data, int len)
 
static void rtp_instance_unlock (struct ast_rtp_instance *instance)
 
static int rtp_learning_rtp_seq_update (struct rtp_learning_info *info, uint16_t seq)
 
static void rtp_learning_seq_init (struct rtp_learning_info *info, uint16_t seq)
 
static void rtp_learning_start (struct ast_rtp *rtp)
 Start the strictrtp learning mode.
 
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_infoast_module_info = &__mod_info
 
static struct ast_rtp_engine asterisk_rtp_engine
 
static struct ast_cli_entry cli_rtp []
 
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
 
static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION
 
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL
 
struct ast_srtp_resres_srtp
 
struct ast_srtp_policy_resres_srtp_policy
 
static struct ast_sockaddr rtcpdebugaddr
 
static int rtcpdebugport
 
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
 
static int rtcpstats
 
static struct ast_sockaddr rtpdebugaddr
 
static int rtpdebugport
 
static int rtpend = DEFAULT_RTP_END
 
static int rtpstart = DEFAULT_RTP_START
 
static int srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION
 
static int strictrtp = DEFAULT_STRICT_RTP
 

Detailed Description

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

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

Definition in file res_rtp_asterisk.c.

Macro Definition Documentation

◆ CALC_LEARNING_MIN_DURATION

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

Calculate the min learning duration in ms.

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

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

Definition at line 159 of file res_rtp_asterisk.c.

◆ DEFAULT_DTLS_MTU

#define DEFAULT_DTLS_MTU   1200

Definition at line 193 of file res_rtp_asterisk.c.

◆ DEFAULT_DTMF_TIMEOUT

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

samples

Definition at line 142 of file res_rtp_asterisk.c.

◆ DEFAULT_ICESUPPORT

#define DEFAULT_ICESUPPORT   1

Definition at line 191 of file res_rtp_asterisk.c.

◆ DEFAULT_LEARNING_MIN_DURATION

#define DEFAULT_LEARNING_MIN_DURATION   CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)

Definition at line 160 of file res_rtp_asterisk.c.

◆ DEFAULT_LEARNING_MIN_SEQUENTIAL

#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4

Definition at line 146 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_END

#define DEFAULT_RTP_END   31000

Default maximum port number to end allocating RTP ports at

Definition at line 106 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_RECV_BUFFER_SIZE

#define DEFAULT_RTP_RECV_BUFFER_SIZE   20

The initial size of the RTP receiver buffer

Definition at line 117 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_SEND_BUFFER_SIZE

#define DEFAULT_RTP_SEND_BUFFER_SIZE   250

The initial size of the RTP send buffer

Definition at line 115 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_START

#define DEFAULT_RTP_START   5000

Default port number to start allocating RTP ports from

Definition at line 105 of file res_rtp_asterisk.c.

◆ DEFAULT_SRTP_REPLAY_PROTECTION

#define DEFAULT_SRTP_REPLAY_PROTECTION   1

Definition at line 190 of file res_rtp_asterisk.c.

◆ DEFAULT_STRICT_RTP

#define DEFAULT_STRICT_RTP   STRICT_RTP_YES

Enabled by default

Definition at line 189 of file res_rtp_asterisk.c.

◆ DEFAULT_STUN_SOFTWARE_ATTRIBUTE

#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE   1

Definition at line 192 of file res_rtp_asterisk.c.

◆ DEFAULT_TURN_PORT

#define DEFAULT_TURN_PORT   3478

Definition at line 111 of file res_rtp_asterisk.c.

◆ FLAG_3389_WARNING

#define FLAG_3389_WARNING   (1 << 0)

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

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6856 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6855 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6820 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

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

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6832 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6821 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

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

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6831 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6854 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6853 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 6850 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 6851 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6835 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6824 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6837 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6833 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6836 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 4384 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 10794 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 6591 of file res_rtp_asterisk.c.

6593{
6594 int index;
6595
6596 if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
6597 /* This instance is not bundled */
6598 return instance;
6599 }
6600
6601 /* Find the bundled child instance */
6602 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
6603 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
6604 unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
6605
6606 if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
6607 return mapping->instance;
6608 }
6609 }
6610
6611 /* Does the SSRC match the bundled parent? */
6612 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
6613 return instance;
6614 }
6615 return NULL;
6616}
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::@513 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 10794 of file res_rtp_asterisk.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

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

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

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

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

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

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

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

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

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

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

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

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

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

9547{
9548 /* If both sides are not using the same method of DTMF transmission
9549 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9550 * --------------------------------------------------
9551 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9552 * |-----------|------------|-----------------------|
9553 * | Inband | False | True |
9554 * | RFC2833 | True | True |
9555 * | SIP INFO | False | False |
9556 * --------------------------------------------------
9557 */
9559 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9560}
@ 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 4590 of file res_rtp_asterisk.c.

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

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

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

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

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

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

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

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

9752{
9753 switch (extension) {
9756 return 1;
9757 default:
9758 return 0;
9759 }
9760}
@ 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 9267 of file res_rtp_asterisk.c.

9268{
9269 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9270
9271 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9272}

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

9699{
9700 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9701
9702 return rtp->cname;
9703}

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

9691{
9692 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9693
9694 return rtp->ssrc;
9695}

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

9482{
9483 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9484
9485 if (!rtp->rtcp) {
9486 return -1;
9487 }
9488
9493
9505
9517
9524
9536
9537
9541
9542 return 0;
9543}
#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 7977 of file res_rtp_asterisk.c.

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

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

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

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

9630{
9631 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9632
9633 return ast_set_qos(rtp->s, tos, cos, desc);
9634}
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 8416 of file res_rtp_asterisk.c.

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

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

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

6790{
6791 int res;
6792
6793 if (!transport || transport == instance) {
6794 return ast_rtp_rtcp_handle_nack(instance, nackdata, position, length);
6795 }
6796
6797 ao2_ref(instance, +1);
6798 ao2_ref(transport, +1);
6799
6800 /* Release child then parent; reacquire parent then child. */
6801 ao2_unlock(instance);
6802 ao2_unlock(transport);
6803 ao2_lock(instance);
6804
6805 res = ast_rtp_rtcp_handle_nack(instance, nackdata, position, length);
6806
6807 ao2_unlock(instance);
6808 ao2_lock(transport);
6809 ao2_lock(instance);
6810
6811 ao2_ref(transport, -1);
6812 ao2_ref(instance, -1);
6813
6814 return res;
6815}
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 9641 of file res_rtp_asterisk.c.

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

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

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

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

9745{
9746 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9747
9748 rtp->stream_num = stream_num;
9749}

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

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

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

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

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

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

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

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

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

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

6011{
6012 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6013 struct ast_sockaddr remote_address = { {0,} };
6014
6015 ast_rtp_instance_get_remote_address(instance, &remote_address);
6016
6017 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
6018 ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
6019 instance, ast_sockaddr_stringify(&remote_address));
6020 rtp->resp = 0;
6021 rtp->dtmfsamples = 0;
6022 return &ast_null_frame;
6023 } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
6024 ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
6025 instance, ast_sockaddr_stringify(&remote_address));
6026 rtp->resp = 0;
6027 rtp->dtmfsamples = 0;
6028 return &ast_null_frame;
6029 }
6030
6031 if (rtp->resp == 'X') {
6032 ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
6033 instance, ast_sockaddr_stringify(&remote_address));
6036 } else {
6037 ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
6038 instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
6039 rtp->resp, rtp->resp,
6040 ast_sockaddr_stringify(&remote_address));
6041 rtp->f.frametype = type;
6042 rtp->f.subclass.integer = rtp->resp;
6043 }
6044 rtp->f.datalen = 0;
6045 rtp->f.samples = 0;
6046 rtp->f.mallocd = 0;
6047 rtp->f.src = "RTP";
6048 AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
6049
6050 return &rtp->f;
6051}
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 10086 of file res_rtp_asterisk.c.

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

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

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

10020{
10021#ifdef HAVE_PJPROJECT
10022 struct sockaddr_in stunaddr_copy;
10023 const char *stun_hostname_copy = NULL;
10024 int stunaddr_ttl_copy = 0;
10025#endif
10026 switch (cmd) {
10027 case CLI_INIT:
10028 e->command = "rtp show settings";
10029 e->usage =
10030 "Usage: rtp show settings\n"
10031 " Display RTP configuration settings\n";
10032 return NULL;
10033 case CLI_GENERATE:
10034 return NULL;
10035 }
10036
10037 if (a->argc != 3) {
10038 return CLI_SHOWUSAGE;
10039 }
10040
10041 ast_cli(a->fd, "\n\nGeneral Settings:\n");
10042 ast_cli(a->fd, "----------------\n");
10043 ast_cli(a->fd, " Port start: %d\n", rtpstart);
10044 ast_cli(a->fd, " Port end: %d\n", rtpend);
10045#ifdef SO_NO_CHECK
10046 ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
10047#endif
10048 ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
10049 ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
10050
10051 if (strictrtp) {
10052 ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
10053 }
10054
10055 ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
10056#ifdef HAVE_PJPROJECT
10057 ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
10058
10059 ast_rwlock_rdlock(&stunaddr_lock);
10060 memcpy(&stunaddr_copy, &stunaddr, sizeof(stunaddr));
10061 stun_hostname_copy = ast_strdupa(S_OR(stun_hostname, ""));
10062 stunaddr_ttl_copy = stunaddr_ttl;
10063 ast_rwlock_unlock(&stunaddr_lock);
10064
10065 ast_cli(a->fd, " STUN: %s\n", stunaddr_copy.sin_addr.s_addr ? "enbabled" : "disabled");
10066 if (ast_strlen_zero(stun_hostname_copy)) {
10067 ast_cli(a->fd, " Address: %s:%d\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
10068 htons(stunaddr_copy.sin_port));
10069 } else {
10070 ast_cli(a->fd, " Hostname: %s:%d\n", stun_hostname_copy, htons(stunaddr_copy.sin_port));
10071 ast_cli(a->fd, " Resolved Addr: %s:%d%s\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
10072 htons(stunaddr_copy.sin_port),
10073 stunaddr_copy.sin_addr.s_addr ? stunaddr_resolver ? "" : " (possibly stale)" : " (lookup failed)");
10074 ast_cli(a->fd, " Last TTL: %d (periodic resolution %s)\n", stunaddr_ttl_copy,
10075 stunaddr_resolver ? "enabled" : "disabled");
10076 ast_cli(a->fd, " Reresove TTL 0: %s\n", AST_CLI_YESNO(stunaddr_reresolve_ttl_0));
10077 }
10078 if (stun_acl) {
10079 ast_acl_output(a->fd, stun_acl, " ");
10080 }
10081#endif
10082 return CLI_SUCCESS;
10083}
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 10675 of file res_rtp_asterisk.c.

10676{
10677#ifdef HAVE_PJPROJECT
10678 pj_lock_t *lock;
10679
10681
10683 if (pj_init() != PJ_SUCCESS) {
10685 }
10686
10687 if (pjlib_util_init() != PJ_SUCCESS) {
10688 rtp_terminate_pjproject();
10690 }
10691
10692 if (pjnath_init() != PJ_SUCCESS) {
10693 rtp_terminate_pjproject();
10695 }
10696
10697 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10698
10699 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10700
10701 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10702 rtp_terminate_pjproject();
10704 }
10705
10706 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10707 rtp_terminate_pjproject();
10709 }
10710
10711 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10712
10713 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10714 rtp_terminate_pjproject();
10716 }
10717
10718#endif
10719
10720#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10721 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10722 if (!dtls_bio_methods) {
10723#ifdef HAVE_PJPROJECT
10724 rtp_terminate_pjproject();
10725#endif
10727 }
10728 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10729 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10730 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10731 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10732#endif
10733
10735#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10736 BIO_meth_free(dtls_bio_methods);
10737#endif
10738#ifdef HAVE_PJPROJECT
10739 rtp_terminate_pjproject();
10740#endif
10742 }
10743
10745#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10746 BIO_meth_free(dtls_bio_methods);
10747#endif
10748#ifdef HAVE_PJPROJECT
10750 rtp_terminate_pjproject();
10751#endif
10753 }
10754
10755 rtp_reload(0, 0);
10756
10758}
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 4805 of file res_rtp_asterisk.c.

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

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

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

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

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

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

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

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

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

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

10644{
10645 rtp_reload(1, 0);
10646 return 0;
10647}

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

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

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

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

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

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

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

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

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

6628{
6629 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
6630}
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 6619 of file res_rtp_asterisk.c.

6621{
6622 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6623}

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

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

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

7595{
7596 if (instance) {
7597 ao2_unlock(instance);
7598 }
7599}

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

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

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

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

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

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

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

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

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

7603{
7604 return a.seqno - b.seqno;
7605}
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 5563 of file res_rtp_asterisk.c.

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

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

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

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

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

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

10761{
10764
10765#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10766 if (dtls_bio_methods) {
10767 BIO_meth_free(dtls_bio_methods);
10768 }
10769#endif
10770
10771#ifdef HAVE_PJPROJECT
10772 host_candidate_overrides_clear();
10773 pj_thread_register_check();
10774 rtp_terminate_pjproject();
10775
10777 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10778 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10779 clean_stunaddr();
10780#endif
10781
10782 return 0;
10783}
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 6561 of file res_rtp_asterisk.c.

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

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

6527{
6528 double mes = calc_media_experience_score(rtp->owner,
6529 rtp->rtcp->normdevrtt,
6533
6534 rtp->rtcp->reported_mes = mes;
6535 if (rtp->rtcp->reported_mes_count == 0) {
6536 rtp->rtcp->reported_minmes = mes;
6537 }
6538 if (mes < rtp->rtcp->reported_minmes) {
6539 rtp->rtcp->reported_minmes = mes;
6540 }
6541 if (mes > rtp->rtcp->reported_maxmes) {
6542 rtp->rtcp->reported_maxmes = mes;
6543 }
6544
6547
6548 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6550 rtp->rtcp->normdevrtt,
6553 rtp->rtcp->reported_normdev_lost, mes);
6554}
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 6315 of file res_rtp_asterisk.c.

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

10326 {
10327 AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
10328 AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
10329 AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
10330 AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
10331#ifdef AST_DEVMODE
10332 AST_CLI_DEFINE(handle_cli_rtp_drop_incoming_packets, "Drop RTP incoming packets"),
10333#endif
10334#ifdef HAVE_PJPROJECT
10335 AST_CLI_DEFINE(handle_cli_rtp_refresh_stun, "Force a resolution of the STUN hostname"),
10336#endif
10337};
#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().