Asterisk - The Open Source Telephony Project GIT-master-5467495
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_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 6407 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 6790 of file res_rtp_asterisk.c.

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6789 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6788 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6753 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

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

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6765 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6754 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

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

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6764 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6787 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6786 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 6783 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 6784 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6768 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6757 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6770 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6766 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6769 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 4375 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 10725 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 6561 of file res_rtp_asterisk.c.

6563{
6564 int index;
6565
6566 if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
6567 /* This instance is not bundled */
6568 return instance;
6569 }
6570
6571 /* Find the bundled child instance */
6572 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
6573 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
6574 unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
6575
6576 if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
6577 return mapping->instance;
6578 }
6579 }
6580
6581 /* Does the SSRC match the bundled parent? */
6582 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
6583 return instance;
6584 }
6585 return NULL;
6586}
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 3236 of file res_rtp_asterisk.c.

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

3465{
3466 int len = size;
3467 void *temp = buf;
3468 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3469 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
3470 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
3471 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(transport, rtcp);
3472 int res;
3473#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3474 char *out = buf;
3475 struct dtls_details *dtls = (!rtcp || rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_MUX) ? &rtp->dtls : &rtp->rtcp->dtls;
3476
3477 /* Don't send RTP if DTLS hasn't finished yet */
3478 if (dtls->ssl && ((*out < 20) || (*out > 63)) && dtls->connection == AST_RTP_DTLS_CONNECTION_NEW) {
3479 *via_ice = 0;
3480 return 0;
3481 }
3482#endif
3483
3484 *via_ice = 0;
3485
3486 if (use_srtp && res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
3487 return -1;
3488 }
3489
3490#ifdef HAVE_PJPROJECT
3491 if (transport_rtp->ice) {
3493 pj_status_t status;
3494 struct ice_wrap *ice;
3495
3496 /* If RTCP is sharing the same socket then use the same component */
3497 if (rtcp && rtp->rtcp->s == rtp->s) {
3498 component = AST_RTP_ICE_COMPONENT_RTP;
3499 }
3500
3501 pj_thread_register_check();
3502
3503 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3504 ice = transport_rtp->ice;
3505 ao2_ref(ice, +1);
3506 if (instance == transport) {
3507 ao2_unlock(instance);
3508 }
3509 status = pj_ice_sess_send_data(ice->real_ice, component, temp, len);
3510 ao2_ref(ice, -1);
3511 if (instance == transport) {
3512 ao2_lock(instance);
3513 }
3514 if (status == PJ_SUCCESS) {
3515 *via_ice = 1;
3516 return len;
3517 }
3518 }
3519#endif
3520
3521 res = ast_sendto(rtcp ? transport_rtp->rtcp->s : transport_rtp->s, temp, len, flags, sa);
3522 if (res > 0) {
3523 ast_rtp_instance_set_last_tx(instance, time(NULL));
3524 }
3525
3526 return res;
3527}
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 10725 of file res_rtp_asterisk.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

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

3551{
3552 unsigned int interval;
3553 /*! \todo XXX Do a more reasonable calculation on this one
3554 * Look in RFC 3550 Section A.7 for an example*/
3555 interval = rtcpinterval;
3556 return interval;
3557}
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 4959 of file res_rtp_asterisk.c.

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

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

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

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

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

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

7299{
7300 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7301 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 1);
7302 struct ast_sockaddr addr;
7303 unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
7304 unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
7305 size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
7306 int res;
7307
7308 /* Read in RTCP data from the socket */
7309 if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
7310 0, &addr)) < 0) {
7311 if (res == RTP_DTLS_ESTABLISHED) {
7314 return &rtp->f;
7315 }
7316
7317 ast_assert(errno != EBADF);
7318 if (errno != EAGAIN) {
7319 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n",
7320 (errno) ? strerror(errno) : "Unspecified");
7321 return NULL;
7322 }
7323 return &ast_null_frame;
7324 }
7325
7326 /* If this was handled by the ICE session don't do anything further */
7327 if (!res) {
7328 return &ast_null_frame;
7329 }
7330
7331 if (!*read_area) {
7332 struct sockaddr_in addr_tmp;
7333 struct ast_sockaddr addr_v4;
7334
7335 if (ast_sockaddr_is_ipv4(&addr)) {
7336 ast_sockaddr_to_sin(&addr, &addr_tmp);
7337 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
7338 ast_debug_stun(2, "(%p) STUN using IPv6 mapped address %s\n",
7339 instance, ast_sockaddr_stringify(&addr));
7340 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
7341 } else {
7342 ast_debug_stun(2, "(%p) STUN cannot do for non IPv4 address %s\n",
7343 instance, ast_sockaddr_stringify(&addr));
7344 return &ast_null_frame;
7345 }
7346 if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
7347 ast_sockaddr_from_sin(&addr, &addr_tmp);
7348 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
7349 }
7350 return &ast_null_frame;
7351 }
7352
7353 return ast_rtcp_interpret(instance, srtp, read_area, res, &addr);
7354}
@ 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 5198 of file res_rtp_asterisk.c.

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

9695{
9696 struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child);
9697 struct ast_rtp *parent_rtp;
9698 struct rtp_ssrc_mapping mapping;
9699 struct ast_sockaddr them = { { 0, } };
9700
9701 if (child_rtp->bundled == parent) {
9702 return 0;
9703 }
9704
9705 /* If this instance was already bundled then remove the SSRC mapping */
9706 if (child_rtp->bundled) {
9707 struct ast_rtp *bundled_rtp;
9708
9709 ao2_unlock(child);
9710
9711 /* The child lock can't be held while accessing the parent */
9712 ao2_lock(child_rtp->bundled);
9713 bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled);
9715 ao2_unlock(child_rtp->bundled);
9716
9717 ao2_lock(child);
9718 ao2_ref(child_rtp->bundled, -1);
9719 child_rtp->bundled = NULL;
9720 }
9721
9722 if (!parent) {
9723 /* We transitioned away from bundle so we need our own transport resources once again */
9724 rtp_allocate_transport(child, child_rtp);
9725 return 0;
9726 }
9727
9728 parent_rtp = ast_rtp_instance_get_data(parent);
9729
9730 /* We no longer need any transport related resources as we will use our parent RTP instance instead */
9731 rtp_deallocate_transport(child, child_rtp);
9732
9733 /* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
9734 child_rtp->bundled = ao2_bump(parent);
9735
9736 mapping.ssrc = child_rtp->themssrc;
9737 mapping.ssrc_valid = child_rtp->themssrc_valid;
9738 mapping.instance = child;
9739
9740 ao2_unlock(child);
9741
9742 ao2_lock(parent);
9743
9744 AST_VECTOR_APPEND(&parent_rtp->ssrc_mapping, mapping);
9745
9746#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9747 /* If DTLS-SRTP is already in use then add the local SSRC to it, otherwise it will get added once DTLS
9748 * negotiation has been completed.
9749 */
9750 if (parent_rtp->dtls.connection == AST_RTP_DTLS_CONNECTION_EXISTING) {
9751 dtls_srtp_add_local_ssrc(parent_rtp, parent, 0, child_rtp->ssrc, 0);
9752 }
9753#endif
9754
9755 /* Bundle requires that RTCP-MUX be in use so only the main remote address needs to match */
9757
9758 ao2_unlock(parent);
9759
9760 ao2_lock(child);
9761
9763
9764 return 0;
9765}
#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 4735 of file res_rtp_asterisk.c.

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

4379{
4380 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4381
4382 if (rtp->bundled) {
4383 struct ast_rtp *bundled_rtp;
4384
4385 /* We can't hold our instance lock while removing ourselves from the parent */
4386 ao2_unlock(instance);
4387
4388 ao2_lock(rtp->bundled);
4389 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
4391 ao2_unlock(rtp->bundled);
4392
4393 ao2_lock(instance);
4394 ao2_ref(rtp->bundled, -1);
4395 }
4396
4397 rtp_deallocate_transport(instance, rtp);
4398
4399 /* Destroy the smoother that was smoothing out audio if present */
4400 if (rtp->smoother) {
4402 }
4403
4404 /* Destroy RTCP if it was being used */
4405 if (rtp->rtcp) {
4406 /*
4407 * It is not possible for there to be an active RTCP scheduler
4408 * entry at this point since it holds a reference to the
4409 * RTP instance while it's active.
4410 */
4412 ast_free(rtp->rtcp);
4413 }
4414
4415 /* Destroy RED if it was being used */
4416 if (rtp->red) {
4417 ao2_unlock(instance);
4418 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
4419 ao2_lock(instance);
4420 ast_free(rtp->red);
4421 rtp->red = NULL;
4422 }
4423
4424 /* Destroy the send buffer if it was being used */
4425 if (rtp->send_buffer) {
4427 }
4428
4429 /* Destroy the recv buffer if it was being used */
4430 if (rtp->recv_buffer) {
4432 }
4433
4435
4441
4442 /* Finally destroy ourselves */
4443 rtp->owner = NULL;
4444 ast_free(rtp);
4445
4446 return 0;
4447}
#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 4465 of file res_rtp_asterisk.c.

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

9478{
9479 /* If both sides are not using the same method of DTMF transmission
9480 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9481 * --------------------------------------------------
9482 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9483 * |-----------|------------|-----------------------|
9484 * | Inband | False | True |
9485 * | RFC2833 | True | True |
9486 * | SIP INFO | False | False |
9487 * --------------------------------------------------
9488 */
9490 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9491}
@ 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 4581 of file res_rtp_asterisk.c.

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

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

4718{
4719 return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
4720}
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 4627 of file res_rtp_asterisk.c.

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

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

4459{
4460 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4461 return rtp->dtmfmode;
4462}
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 4450 of file res_rtp_asterisk.c.

4451{
4452 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4453 rtp->dtmfmode = dtmf_mode;
4454 return 0;
4455}

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

9683{
9684 switch (extension) {
9687 return 1;
9688 default:
9689 return 0;
9690 }
9691}
@ 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 9198 of file res_rtp_asterisk.c.

9199{
9200 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9201
9202 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9203}

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

9630{
9631 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9632
9633 return rtp->cname;
9634}

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

9622{
9623 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9624
9625 return rtp->ssrc;
9626}

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

9413{
9414 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9415
9416 if (!rtp->rtcp) {
9417 return -1;
9418 }
9419
9424
9436
9448
9455
9467
9468
9472
9473 return 0;
9474}
#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 7908 of file res_rtp_asterisk.c.

7911{
7912 unsigned int *rtpheader = (unsigned int*)(read_area);
7913 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7914 struct ast_rtp_instance *instance1;
7915 int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc;
7916 unsigned int timestamp;
7917 RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
7918 struct frame_list frames;
7919
7920 /* If this payload is encrypted then decrypt it using the given SRTP instance */
7921 if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
7922 srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
7923 return &ast_null_frame;
7924 }
7925
7926 /* If we are currently sending DTMF to the remote party send a continuation packet */
7927 if (rtp->sending_digit) {
7928 ast_rtp_dtmf_continuation(instance);
7929 }
7930
7931 /* Pull out the various other fields we will need */
7932 ssrc = ntohl(rtpheader[2]);
7933 seqno = ntohl(rtpheader[0]);
7934 payloadtype = (seqno & 0x7f0000) >> 16;
7935 padding = seqno & (1 << 29);
7936 mark = seqno & (1 << 23);
7937 ext = seqno & (1 << 28);
7938 cc = (seqno & 0xF000000) >> 24;
7939 seqno &= 0xffff;
7940 timestamp = ntohl(rtpheader[1]);
7941
7943
7944 /* Remove any padding bytes that may be present */
7945 if (padding) {
7946 res -= read_area[res - 1];
7947 }
7948
7949 /* Skip over any CSRC fields */
7950 if (cc) {
7951 hdrlen += cc * 4;
7952 }
7953
7954 /* Look for any RTP extensions, currently we do not support any */
7955 if (ext) {
7956 int extensions_size = (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
7957 unsigned int profile;
7958 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
7959
7960 if (profile == 0xbede) {
7961 /* We skip over the first 4 bytes as they are just for the one byte extension header */
7962 rtp_instance_parse_extmap_extensions(instance, rtp, read_area + hdrlen + 4, extensions_size);
7963 } else if (DEBUG_ATLEAST(1)) {
7964 if (profile == 0x505a) {
7965 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
7966 } else {
7967 /* SDP negotiated RTP extensions can not currently be output in logging */
7968 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
7969 }
7970 }
7971
7972 hdrlen += extensions_size;
7973 hdrlen += 4;
7974 }
7975
7976 /* Make sure after we potentially mucked with the header length that it is once again valid */
7977 if (res < hdrlen) {
7978 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
7980 }
7981
7982 /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
7983 if (!bundled) {
7984 /* Force a marker bit and change SSRC if the SSRC changes */
7985 if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
7986 struct ast_frame *f, srcupdate = {
7989 };
7990
7991 if (!mark) {
7993 ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance);
7994 }
7995 mark = 1;
7996 }
7997
7998 f = ast_frisolate(&srcupdate);
8000
8001 rtp->seedrxseqno = 0;
8002 rtp->rxcount = 0;
8003 rtp->rxoctetcount = 0;
8004 rtp->cycles = 0;
8005 prev_seqno = 0;
8006 rtp->last_seqno = 0;
8007 rtp->last_end_timestamp.ts = 0;
8008 rtp->last_end_timestamp.is_set = 0;
8009 if (rtp->rtcp) {
8010 rtp->rtcp->expected_prior = 0;
8011 rtp->rtcp->received_prior = 0;
8012 }
8013 }
8014
8015 rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
8016 rtp->themssrc_valid = 1;
8017 }
8018
8019 rtp->rxcount++;
8020 rtp->rxoctetcount += (res - hdrlen);
8021 if (rtp->rxcount == 1) {
8022 rtp->seedrxseqno = seqno;
8023 }
8024
8025 /* Do not schedule RR if RTCP isn't run */
8026 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 0) {
8027 /* Schedule transmission of Receiver Report */
8028 ao2_ref(instance, +1);
8030 if (rtp->rtcp->schedid < 0) {
8031 ao2_ref(instance, -1);
8032 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
8033 }
8034 }
8035 if ((int)prev_seqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
8036 rtp->cycles += RTP_SEQ_MOD;
8037
8038 /* If we are directly bridged to another instance send the audio directly out,
8039 * but only after updating core information about the received traffic so that
8040 * outgoing RTCP reflects it.
8041 */
8042 instance1 = ast_rtp_instance_get_bridged(instance);
8043 if (instance1
8044 && !bridge_p2p_rtp_write(instance, instance1, rtpheader, res, hdrlen)) {
8045 struct timeval rxtime;
8046 struct ast_frame *f;
8047
8048 /* Update statistics for jitter so they are correct in RTCP */
8049 calc_rxstamp_and_jitter(&rxtime, rtp, timestamp, mark);
8050
8051
8052 /* When doing P2P we don't need to raise any frames about SSRC change to the core */
8053 while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list)) != NULL) {
8054 ast_frfree(f);
8055 }
8056
8057 return &ast_null_frame;
8058 }
8059
8060 payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
8061 if (!payload) {
8062 /* Unknown payload type. */
8064 }
8065
8066 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
8067 if (!payload->asterisk_format) {
8068 struct ast_frame *f = NULL;
8069 if (payload->rtp_code == AST_RTP_DTMF) {
8070 /* process_dtmf_rfc2833 may need to return multiple frames. We do this
8071 * by passing the pointer to the frame list to it so that the method
8072 * can append frames to the list as needed.
8073 */
8074 process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames);
8075 } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
8076 f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
8077 } else if (payload->rtp_code == AST_RTP_CN) {
8078 f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
8079 } else {
8080 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
8081 payloadtype,
8082 ast_sockaddr_stringify(remote_address));
8083 }
8084
8085 if (f) {
8087 }
8088 /* Even if no frame was returned by one of the above methods,
8089 * we may have a frame to return in our frame list
8090 */
8092 }
8093
8094 ao2_replace(rtp->lastrxformat, payload->format);
8095 ao2_replace(rtp->f.subclass.format, payload->format);
8096 switch (ast_format_get_type(rtp->f.subclass.format)) {
8099 break;
8102 break;
8104 rtp->f.frametype = AST_FRAME_TEXT;
8105 break;
8107 /* Fall through */
8108 default:
8109 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8111 return &ast_null_frame;
8112 }
8113
8114 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
8115 rtp->dtmf_timeout = 0;
8116
8117 if (rtp->resp) {
8118 struct ast_frame *f;
8119 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
8121 rtp->resp = 0;
8122 rtp->dtmf_timeout = rtp->dtmf_duration = 0;
8124 return AST_LIST_FIRST(&frames);
8125 }
8126 }
8127
8128 rtp->f.src = "RTP";
8129 rtp->f.mallocd = 0;
8130 rtp->f.datalen = res - hdrlen;
8131 rtp->f.data.ptr = read_area + hdrlen;
8132 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
8134 rtp->f.seqno = seqno;
8135 rtp->f.stream_num = rtp->stream_num;
8136
8138 && ((int)seqno - (prev_seqno + 1) > 0)
8139 && ((int)seqno - (prev_seqno + 1) < 10)) {
8140 unsigned char *data = rtp->f.data.ptr;
8141
8142 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
8143 rtp->f.datalen +=3;
8144 *data++ = 0xEF;
8145 *data++ = 0xBF;
8146 *data = 0xBD;
8147 }
8148
8150 unsigned char *data = rtp->f.data.ptr;
8151 unsigned char *header_end;
8152 int num_generations;
8153 int header_length;
8154 int len;
8155 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
8156 int x;
8157
8159 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
8160 if (header_end == NULL) {
8162 }
8163 header_end++;
8164
8165 header_length = header_end - data;
8166 num_generations = header_length / 4;
8167 len = header_length;
8168
8169 if (!diff) {
8170 for (x = 0; x < num_generations; x++)
8171 len += data[x * 4 + 3];
8172
8173 if (!(rtp->f.datalen - len))
8175
8176 rtp->f.data.ptr += len;
8177 rtp->f.datalen -= len;
8178 } else if (diff > num_generations && diff < 10) {
8179 len -= 3;
8180 rtp->f.data.ptr += len;
8181 rtp->f.datalen -= len;
8182
8183 data = rtp->f.data.ptr;
8184 *data++ = 0xEF;
8185 *data++ = 0xBF;
8186 *data = 0xBD;
8187 } else {
8188 for ( x = 0; x < num_generations - diff; x++)
8189 len += data[x * 4 + 3];
8190
8191 rtp->f.data.ptr += len;
8192 rtp->f.datalen -= len;
8193 }
8194 }
8195
8197 rtp->f.samples = ast_codec_samples_count(&rtp->f);
8199 ast_frame_byteswap_be(&rtp->f);
8200 }
8201 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8202 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
8204 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8205 rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
8207 /* Video -- samples is # of samples vs. 90000 */
8208 if (!rtp->lastividtimestamp)
8209 rtp->lastividtimestamp = timestamp;
8210 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8212 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8213 rtp->f.samples = timestamp - rtp->lastividtimestamp;
8214 rtp->lastividtimestamp = timestamp;
8215 rtp->f.delivery.tv_sec = 0;
8216 rtp->f.delivery.tv_usec = 0;
8217 /* Pass the RTP marker bit as bit */
8218 rtp->f.subclass.frame_ending = mark ? 1 : 0;
8220 /* TEXT -- samples is # of samples vs. 1000 */
8221 if (!rtp->lastitexttimestamp)
8222 rtp->lastitexttimestamp = timestamp;
8223 rtp->f.samples = timestamp - rtp->lastitexttimestamp;
8224 rtp->lastitexttimestamp = timestamp;
8225 rtp->f.delivery.tv_sec = 0;
8226 rtp->f.delivery.tv_usec = 0;
8227 } else {
8228 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8230 return &ast_null_frame;
8231 }
8232
8234 return AST_LIST_FIRST(&frames);
8235}
#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 9384 of file res_rtp_asterisk.c.

9385{
9386 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
9387
9388 ao2_lock(instance0);
9390 if (rtp->smoother) {
9392 rtp->smoother = NULL;
9393 }
9394
9395 /* We must use a new SSRC when local bridge ends */
9396 if (!instance1) {
9397 rtp->ssrc = rtp->ssrc_orig;
9398 rtp->ssrc_orig = 0;
9399 rtp->ssrc_saved = 0;
9400 } else if (!rtp->ssrc_saved) {
9401 /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
9402 rtp->ssrc_orig = rtp->ssrc;
9403 rtp->ssrc_saved = 1;
9404 }
9405
9406 ao2_unlock(instance0);
9407
9408 return 0;
9409}
#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 4322 of file res_rtp_asterisk.c.

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

9015{
9016 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9017
9018 if (property == AST_RTP_PROPERTY_RTCP) {
9019 if (value) {
9020 struct ast_sockaddr local_addr;
9021
9022 if (rtp->rtcp && rtp->rtcp->type == value) {
9023 ast_debug_rtcp(1, "(%p) RTCP ignoring duplicate property\n", instance);
9024 return;
9025 }
9026
9027 if (!rtp->rtcp) {
9028 rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
9029 if (!rtp->rtcp) {
9030 return;
9031 }
9032 rtp->rtcp->s = -1;
9033#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9034 rtp->rtcp->dtls.timeout_timer = -1;
9035#endif
9036 rtp->rtcp->schedid = -1;
9037 }
9038
9039 rtp->rtcp->type = value;
9040
9041 /* Grab the IP address and port we are going to use */
9042 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
9045 ast_sockaddr_port(&rtp->rtcp->us) + 1);
9046 }
9047
9048 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
9049 if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
9050 ast_sockaddr_set_port(&local_addr, ast_sockaddr_port(&rtp->rtcp->us));
9051 } else {
9052 /* Failed to get local address reset to use default. */
9053 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
9054 }
9055
9058 if (!rtp->rtcp->local_addr_str) {
9059 ast_free(rtp->rtcp);
9060 rtp->rtcp = NULL;
9061 return;
9062 }
9063
9065 /* We're either setting up RTCP from scratch or
9066 * switching from MUX. Either way, we won't have
9067 * a socket set up, and we need to set it up
9068 */
9069 if ((rtp->rtcp->s = create_new_socket("RTCP", &rtp->rtcp->us)) < 0) {
9070 ast_debug_rtcp(1, "(%p) RTCP failed to create a new socket\n", instance);
9072 ast_free(rtp->rtcp);
9073 rtp->rtcp = NULL;
9074 return;
9075 }
9076
9077 /* 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 */
9078 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
9079 ast_debug_rtcp(1, "(%p) RTCP failed to setup RTP instance\n", instance);
9080 close(rtp->rtcp->s);
9082 ast_free(rtp->rtcp);
9083 rtp->rtcp = NULL;
9084 return;
9085 }
9086#ifdef HAVE_PJPROJECT
9087 if (rtp->ice) {
9088 rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
9089 }
9090#endif
9091#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9092 dtls_setup_rtcp(instance);
9093#endif
9094 } else {
9095 struct ast_sockaddr addr;
9096 /* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
9097 * then close the socket we previously created.
9098 *
9099 * It may seem as though there is a possible race condition here where we might try
9100 * to close the RTCP socket while it is being used to send data. However, this is not
9101 * a problem in practice since setting and adjusting of RTCP properties happens prior
9102 * to activating RTP. It is not until RTP is activated that timers start for RTCP
9103 * transmission
9104 */
9105 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9106 close(rtp->rtcp->s);
9107 }
9108 rtp->rtcp->s = rtp->s;
9109 ast_rtp_instance_get_remote_address(instance, &addr);
9110 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
9111#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9112 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9113 SSL_free(rtp->rtcp->dtls.ssl);
9114 }
9115 rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
9116#endif
9117 }
9118
9119 ast_debug_rtcp(1, "(%s) RTCP setup on RTP instance\n",
9121 } else {
9122 if (rtp->rtcp) {
9123 if (rtp->rtcp->schedid > -1) {
9124 ao2_unlock(instance);
9125 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9126 /* Successfully cancelled scheduler entry. */
9127 ao2_ref(instance, -1);
9128 } else {
9129 /* Unable to cancel scheduler entry */
9130 ast_debug_rtcp(1, "(%p) RTCP failed to tear down RTCP\n", instance);
9131 ao2_lock(instance);
9132 return;
9133 }
9134 ao2_lock(instance);
9135 rtp->rtcp->schedid = -1;
9136 }
9137 if (rtp->transport_wide_cc.schedid > -1) {
9138 ao2_unlock(instance);
9139 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9140 ao2_ref(instance, -1);
9141 } else {
9142 ast_debug_rtcp(1, "(%p) RTCP failed to tear down transport-cc feedback\n", instance);
9143 ao2_lock(instance);
9144 return;
9145 }
9146 ao2_lock(instance);
9147 rtp->transport_wide_cc.schedid = -1;
9148 }
9149 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9150 close(rtp->rtcp->s);
9151 }
9152#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9153 ao2_unlock(instance);
9154 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9155 ao2_lock(instance);
9156
9157 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9158 SSL_free(rtp->rtcp->dtls.ssl);
9159 }
9160#endif
9162 ast_free(rtp->rtcp);
9163 rtp->rtcp = NULL;
9164 ast_debug_rtcp(1, "(%s) RTCP torn down on RTP instance\n",
9166 }
9167 }
9168 } else if (property == AST_RTP_PROPERTY_ASYMMETRIC_CODEC) {
9169 rtp->asymmetric_codec = value;
9170 } else if (property == AST_RTP_PROPERTY_RETRANS_SEND) {
9171 if (value) {
9172 if (!rtp->send_buffer) {
9174 }
9175 } else {
9176 if (rtp->send_buffer) {
9178 rtp->send_buffer = NULL;
9179 }
9180 }
9181 } else if (property == AST_RTP_PROPERTY_RETRANS_RECV) {
9182 if (value) {
9183 if (!rtp->recv_buffer) {
9186 }
9187 } else {
9188 if (rtp->recv_buffer) {
9190 rtp->recv_buffer = NULL;
9192 }
9193 }
9194 }
9195}
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 9560 of file res_rtp_asterisk.c.

9561{
9562 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9563
9564 return ast_set_qos(rtp->s, tos, cos, desc);
9565}
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 8347 of file res_rtp_asterisk.c.

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

9207{
9208 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9209 struct ast_sockaddr local;
9210 int index;
9211
9212 ast_rtp_instance_get_local_address(instance, &local);
9213 if (!ast_sockaddr_isnull(addr)) {
9214 /* Update the local RTP address with what is being used */
9215 if (ast_ouraddrfor(addr, &local)) {
9216 /* Failed to update our address so reuse old local address */
9217 ast_rtp_instance_get_local_address(instance, &local);
9218 } else {
9219 ast_rtp_instance_set_local_address(instance, &local);
9220 }
9221 }
9222
9223 if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
9224 ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
9225 ast_sockaddr_copy(&rtp->rtcp->them, addr);
9226
9229
9230 /* Update the local RTCP address with what is being used */
9231 ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
9232 }
9233 ast_sockaddr_copy(&rtp->rtcp->us, &local);
9234
9237 }
9238
9239 /* Update any bundled RTP instances */
9240 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
9241 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
9242
9244 }
9245
9246 /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
9247 rtp->last_seqno = 0;
9248 rtp->last_end_timestamp.ts = 0;
9249 rtp->last_end_timestamp.is_set = 0;
9250
9252 && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
9253 /* We only need to learn a new strict source address if we've been told the source is
9254 * changing to something different.
9255 */
9256 ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
9257 rtp, ast_sockaddr_stringify(addr));
9258 rtp_learning_start(rtp);
9259 }
9260}
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 6655 of file res_rtp_asterisk.c.

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

9573{
9574 unsigned int *rtpheader;
9575 int hdrlen = 12;
9576 int res, payload = 0;
9577 char data[256];
9578 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9579 struct ast_sockaddr remote_address = { {0,} };
9580 int ice;
9581
9582 ast_rtp_instance_get_remote_address(instance, &remote_address);
9583
9584 if (ast_sockaddr_isnull(&remote_address)) {
9585 return -1;
9586 }
9587
9589
9590 level = 127 - (level & 0x7f);
9591
9592 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
9593
9594 /* Get a pointer to the header */
9595 rtpheader = (unsigned int *)data;
9596 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
9597 rtpheader[1] = htonl(rtp->lastts);
9598 rtpheader[2] = htonl(rtp->ssrc);
9599 data[12] = level;
9600
9601 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);
9602
9603 if (res < 0) {
9604 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
9605 return res;
9606 }
9607
9608 if (rtp_debug_test_addr(&remote_address)) {
9609 ast_verbose("Sent Comfort Noise RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
9610 ast_sockaddr_stringify(&remote_address),
9611 ice ? " (via ICE)" : "",
9612 AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
9613 }
9614
9615 rtp->seqno++;
9616
9617 return res;
9618}

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

9638{
9639 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9640
9641 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
9642 return;
9643 }
9644
9645 rtp->themssrc = ssrc;
9646 rtp->themssrc_valid = 1;
9647
9648 /* If this is bundled we need to update the SSRC mapping */
9649 if (rtp->bundled) {
9650 struct ast_rtp *bundled_rtp;
9651 int index;
9652
9653 ao2_unlock(instance);
9654
9655 /* The child lock can't be held while accessing the parent */
9656 ao2_lock(rtp->bundled);
9657 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
9658
9659 for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
9660 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
9661
9662 if (mapping->instance == instance) {
9663 mapping->ssrc = ssrc;
9664 mapping->ssrc_valid = 1;
9665 break;
9666 }
9667 }
9668
9669 ao2_unlock(rtp->bundled);
9670
9672 }
9673}

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

9676{
9677 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9678
9679 rtp->stream_num = stream_num;
9680}

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

9510{
9511 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9512 struct ast_sockaddr addr = { {0,} };
9513
9514#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9515 ao2_unlock(instance);
9516 AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
9517
9518 dtls_srtp_stop_timeout_timer(instance, rtp, 0);
9519 if (rtp->rtcp) {
9520 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9521 }
9522 ao2_lock(instance);
9523#endif
9524 ast_debug_rtp(1, "(%s) RTP Stop\n",
9526
9527 if (rtp->rtcp && rtp->rtcp->schedid > -1) {
9528 ao2_unlock(instance);
9529 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9530 /* successfully cancelled scheduler entry. */
9531 ao2_ref(instance, -1);
9532 }
9533 ao2_lock(instance);
9534 rtp->rtcp->schedid = -1;
9535 }
9536
9537 if (rtp->transport_wide_cc.schedid > -1) {
9538 ao2_unlock(instance);
9539 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9540 ao2_ref(instance, -1);
9541 }
9542 ao2_lock(instance);
9543 rtp->transport_wide_cc.schedid = -1;
9544 }
9545
9546 if (rtp->red) {
9547 ao2_unlock(instance);
9548 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
9549 ao2_lock(instance);
9550 ast_free(rtp->red);
9551 rtp->red = NULL;
9552 }
9553
9554 ast_rtp_instance_set_remote_address(instance, &addr);
9555
9557}
#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 9494 of file res_rtp_asterisk.c.

9495{
9496 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9497 struct sockaddr_in suggestion_tmp;
9498
9499 /*
9500 * The instance should not be locked because we can block
9501 * waiting for a STUN respone.
9502 */
9503 ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
9504 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
9505 ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
9506}
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 4723 of file res_rtp_asterisk.c.

4724{
4725 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4726
4727 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4729 ast_debug_rtp(3, "(%p) RTP setting the marker bit due to a source update\n", instance);
4730
4731 return;
4732}

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

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

7359{
7360 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7361 struct ast_rtp *bridged;
7362 int res = 0, payload = 0, bridged_payload = 0, mark;
7363 RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
7364 int reconstruct = ntohl(rtpheader[0]);
7365 struct ast_sockaddr remote_address = { {0,} };
7366 int ice;
7367 unsigned int timestamp = ntohl(rtpheader[1]);
7368
7369 /* Get fields from packet */
7370 payload = (reconstruct & 0x7f0000) >> 16;
7371 mark = (reconstruct & 0x800000) >> 23;
7372
7373 /* Check what the payload value should be */
7374 payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
7375 if (!payload_type) {
7376 return -1;
7377 }
7378
7379 /* Otherwise adjust bridged payload to match */
7381 payload_type->asterisk_format, payload_type->format, payload_type->rtp_code, payload_type->sample_rate);
7382
7383 /* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
7384 if (bridged_payload < 0) {
7385 return -1;
7386 }
7387
7388 /* 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 */
7389 if (ast_rtp_codecs_find_payload_code(ast_rtp_instance_get_codecs(instance1), bridged_payload) == -1) {
7390 ast_debug_rtp(1, "(%p, %p) RTP unsupported payload type received\n", instance, instance1);
7391 return -1;
7392 }
7393
7394 /*
7395 * Even if we are no longer in dtmf, we could still be receiving
7396 * re-transmissions of the last dtmf end still. Feed those to the
7397 * core so they can be filtered accordingly.
7398 */
7399 if (rtp->last_end_timestamp.is_set && rtp->last_end_timestamp.ts == timestamp) {
7400 ast_debug_rtp(1, "(%p, %p) RTP feeding packet with duplicate timestamp to core\n", instance, instance1);
7401 return -1;
7402 }
7403
7404 if (payload_type->asterisk_format) {
7405 ao2_replace(rtp->lastrxformat, payload_type->format);
7406 }
7407
7408 /*
7409 * We have now determined that we need to send the RTP packet
7410 * out the bridged instance to do local bridging so we must unlock
7411 * the receiving instance to prevent deadlock with the bridged
7412 * instance.
7413 *
7414 * Technically we should grab a ref to instance1 so it won't go
7415 * away on us. However, we should be safe because the bridged
7416 * instance won't change without both channels involved being
7417 * locked and we currently have the channel lock for the receiving
7418 * instance.
7419 */
7420 ao2_unlock(instance);
7421 ao2_lock(instance1);
7422
7423 /*
7424 * Get the peer rtp pointer now to emphasize that using it
7425 * must happen while instance1 is locked.
7426 */
7427 bridged = ast_rtp_instance_get_data(instance1);
7428
7429
7430 /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
7431 if (bridged->sending_digit) {
7432 ast_debug_rtp(1, "(%p, %p) RTP Feeding packet to core until DTMF finishes\n", instance, instance1);
7433 ao2_unlock(instance1);
7434 ao2_lock(instance);
7435 return -1;
7436 }
7437
7438 if (payload_type->asterisk_format) {
7439 /*
7440 * If bridged peer has already received rtp, perform the asymmetric codec check
7441 * if that feature has been activated
7442 */
7443 if (!bridged->asymmetric_codec
7444 && bridged->lastrxformat != ast_format_none
7445 && ast_format_cmp(payload_type->format, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
7446 ast_debug_rtp(1, "(%p, %p) RTP asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
7447 instance, instance1, ast_format_get_name(payload_type->format),
7449 ao2_unlock(instance1);
7450 ao2_lock(instance);
7451 return -1;
7452 }
7453
7454 ao2_replace(bridged->lasttxformat, payload_type->format);
7455 }
7456
7457 ast_rtp_instance_get_remote_address(instance1, &remote_address);
7458
7459 if (ast_sockaddr_isnull(&remote_address)) {
7460 ast_debug_rtp(5, "(%p, %p) RTP remote address is null, most likely RTP has been stopped\n",
7461 instance, instance1);
7462 ao2_unlock(instance1);
7463 ao2_lock(instance);
7464 return 0;
7465 }
7466
7467 /* If the marker bit has been explicitly set turn it on */
7468 if (ast_test_flag(bridged, FLAG_NEED_MARKER_BIT)) {
7469 mark = 1;
7471 }
7472
7473 /* Set the marker bit for the first local bridged packet which has the first bridged peer's SSRC. */
7475 mark = 1;
7477 }
7478
7479 /* Reconstruct part of the packet */
7480 reconstruct &= 0xFF80FFFF;
7481 reconstruct |= (bridged_payload << 16);
7482 reconstruct |= (mark << 23);
7483 rtpheader[0] = htonl(reconstruct);
7484
7485 if (mark) {
7486 /* make this rtp instance aware of the new ssrc it is sending */
7487 bridged->ssrc = ntohl(rtpheader[2]);
7488 }
7489
7490 /* Send the packet back out */
7491 res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address, &ice);
7492 if (res < 0) {
7495 "RTP Transmission error of packet to %s: %s\n",
7496 ast_sockaddr_stringify(&remote_address),
7497 strerror(errno));
7501 "RTP NAT: Can't write RTP to private "
7502 "address %s, waiting for other end to "
7503 "send audio...\n",
7504 ast_sockaddr_stringify(&remote_address));
7505 }
7507 }
7508 ao2_unlock(instance1);
7509 ao2_lock(instance);
7510 return 0;
7511 }
7512
7513 if (rtp_debug_test_addr(&remote_address)) {
7514 ast_verbose("Sent RTP P2P packet to %s%s (type %-2.2d, len %-6.6d)\n",
7515 ast_sockaddr_stringify(&remote_address),
7516 ice ? " (via ICE)" : "",
7517 bridged_payload, len - hdrlen);
7518 }
7519
7520 ao2_unlock(instance1);
7521 ao2_lock(instance);
7522 return 0;
7523}
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 3559 of file res_rtp_asterisk.c.

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

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

6434{
6435 double r_value;
6436 double pseudo_mos;
6437 double mes = 0;
6438
6439 /*
6440 * While the media itself might be okay, a significant enough delay could make
6441 * for an unpleasant user experience.
6442 *
6443 * Calculate the effective latency by using the given round trip time, and adding
6444 * jitter scaled according to its standard deviation. The scaling is done in order
6445 * to increase jitter's weight since a higher deviation can result in poorer overall
6446 * quality.
6447 */
6448 double effective_latency = (normdevrtt * 1000)
6449 + ((normdev_rxjitter * 2) * (stdev_rxjitter / 3))
6450 + 10;
6451
6452 /*
6453 * Using the defaults for the standard transmission rating factor ("R" value)
6454 * one arrives at 93.2 (see ITU-T G.107 for more details), so we'll use that
6455 * as the starting value and subtract deficiencies that could affect quality.
6456 *
6457 * Calculate the impact of the effective latency. Influence increases with
6458 * values over 160 as the significant "lag" can degrade user experience.
6459 */
6460 if (effective_latency < 160) {
6461 r_value = 93.2 - (effective_latency / 40);
6462 } else {
6463 r_value = 93.2 - (effective_latency - 120) / 10;
6464 }
6465
6466 /* Next evaluate the impact of lost packets */
6467 r_value = r_value - (normdev_rxlost * 2.0);
6468
6469 /*
6470 * Finally convert the "R" value into a opinion/quality score between 1 (really anything
6471 * below 3 should be considered poor) and 4.5 (the highest achievable for VOIP).
6472 */
6473 if (r_value < 0) {
6474 pseudo_mos = 1.0;
6475 } else if (r_value > 100) {
6476 pseudo_mos = 4.5;
6477 } else {
6478 pseudo_mos = 1 + (0.035 * r_value) + (r_value * (r_value - 60) * (100 - r_value) * 0.000007);
6479 }
6480
6481 /*
6482 * We're going to rescale the 0.0->5.0 pseudo_mos to the 0.0->100.0 MES.
6483 * For those ranges, we could actually just multiply the pseudo_mos
6484 * by 20 but we may want to change the scale later.
6485 */
6486 mes = RESCALE(pseudo_mos, 0.0, 5.0, 0.0, 100.0);
6487
6488 return mes;
6489}
#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 5806 of file res_rtp_asterisk.c.

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

4030{
4031 struct timeval t;
4032 long ms;
4033
4034 if (ast_tvzero(rtp->txcore)) {
4035 rtp->txcore = ast_tvnow();
4036 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
4037 }
4038
4039 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
4040 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
4041 ms = 0;
4042 }
4043 rtp->txcore = t;
4044
4045 return (unsigned int) ms;
4046}
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 4803 of file res_rtp_asterisk.c.

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

3192{
3193 return elem - value;
3194}

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

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

3588{
3589 int af, sock;
3590
3591 af = ast_sockaddr_is_ipv4(bind_addr) ? AF_INET :
3592 ast_sockaddr_is_ipv6(bind_addr) ? AF_INET6 : -1;
3593 sock = ast_socket_nonblock(af, SOCK_DGRAM, 0);
3594
3595 if (sock < 0) {
3596 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
3597 return sock;
3598 }
3599
3600#ifdef SO_NO_CHECK
3601 if (nochecksums) {
3602 setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
3603 }
3604#endif
3605
3606#ifdef HAVE_SOCK_IPV6_V6ONLY
3607 if (AF_INET6 == af && ast_sockaddr_is_any(bind_addr)) {
3608 /* ICE relies on dual-stack behavior. Ensure it is enabled. */
3609 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof(int)) != 0) {
3610 ast_log(LOG_WARNING, "setsockopt IPV6_V6ONLY=0 failed: %s\n", strerror(errno));
3611 }
3612 }
3613#endif
3614
3615 return sock;
3616}
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 3197 of file res_rtp_asterisk.c.

3198{
3199 return elem == value;
3200}

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

10018{
10019 switch (cmd) {
10020 case CLI_INIT:
10021 e->command = "rtcp set debug {on|off|ip}";
10022 e->usage =
10023 "Usage: rtcp set debug {on|off|ip host[:port]}\n"
10024 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
10025 " specified, limit the dumped packets to those to and from\n"
10026 " the specified 'host' with optional port.\n";
10027 return NULL;
10028 case CLI_GENERATE:
10029 return NULL;
10030 }
10031
10032 if (a->argc == e->args) { /* set on or off */
10033 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
10035 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
10036 ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
10037 return CLI_SUCCESS;
10038 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
10040 ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
10041 return CLI_SUCCESS;
10042 }
10043 } else if (a->argc == e->args +1) { /* ip */
10044 return rtcp_do_debug_ip(a);
10045 }
10046
10047 return CLI_SHOWUSAGE; /* default, failure */
10048}
#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 10050 of file res_rtp_asterisk.c.

10051{
10052 switch (cmd) {
10053 case CLI_INIT:
10054 e->command = "rtcp set stats {on|off}";
10055 e->usage =
10056 "Usage: rtcp set stats {on|off}\n"
10057 " Enable/Disable dumping of RTCP stats.\n";
10058 return NULL;
10059 case CLI_GENERATE:
10060 return NULL;
10061 }
10062
10063 if (a->argc != e->args)
10064 return CLI_SHOWUSAGE;
10065
10066 if (!strncasecmp(a->argv[e->args-1], "on", 2))
10067 rtcpstats = 1;
10068 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
10069 rtcpstats = 0;
10070 else
10071 return CLI_SHOWUSAGE;
10072
10073 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
10074 return CLI_SUCCESS;
10075}
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 9916 of file res_rtp_asterisk.c.

9917{
9918 switch (cmd) {
9919 case CLI_INIT:
9920 e->command = "rtp set debug {on|off|ip}";
9921 e->usage =
9922 "Usage: rtp set debug {on|off|ip host[:port]}\n"
9923 " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9924 " specified, limit the dumped packets to those to and from\n"
9925 " the specified 'host' with optional port.\n";
9926 return NULL;
9927 case CLI_GENERATE:
9928 return NULL;
9929 }
9930
9931 if (a->argc == e->args) { /* set on or off */
9932 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9934 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
9935 ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
9936 return CLI_SUCCESS;
9937 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9939 ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
9940 return CLI_SUCCESS;
9941 }
9942 } else if (a->argc == e->args +1) { /* ip */
9943 return rtp_do_debug_ip(a);
9944 }
9945
9946 return CLI_SHOWUSAGE; /* default, failure */
9947}
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 9950 of file res_rtp_asterisk.c.

9951{
9952#ifdef HAVE_PJPROJECT
9953 struct sockaddr_in stunaddr_copy;
9954 const char *stun_hostname_copy = NULL;
9955 int stunaddr_ttl_copy = 0;
9956#endif
9957 switch (cmd) {
9958 case CLI_INIT:
9959 e->command = "rtp show settings";
9960 e->usage =
9961 "Usage: rtp show settings\n"
9962 " Display RTP configuration settings\n";
9963 return NULL;
9964 case CLI_GENERATE:
9965 return NULL;
9966 }
9967
9968 if (a->argc != 3) {
9969 return CLI_SHOWUSAGE;
9970 }
9971
9972 ast_cli(a->fd, "\n\nGeneral Settings:\n");
9973 ast_cli(a->fd, "----------------\n");
9974 ast_cli(a->fd, " Port start: %d\n", rtpstart);
9975 ast_cli(a->fd, " Port end: %d\n", rtpend);
9976#ifdef SO_NO_CHECK
9977 ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
9978#endif
9979 ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
9980 ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
9981
9982 if (strictrtp) {
9983 ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
9984 }
9985
9986 ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
9987#ifdef HAVE_PJPROJECT
9988 ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
9989
9990 ast_rwlock_rdlock(&stunaddr_lock);
9991 memcpy(&stunaddr_copy, &stunaddr, sizeof(stunaddr));
9992 stun_hostname_copy = ast_strdupa(S_OR(stun_hostname, ""));
9993 stunaddr_ttl_copy = stunaddr_ttl;
9994 ast_rwlock_unlock(&stunaddr_lock);
9995
9996 ast_cli(a->fd, " STUN: %s\n", stunaddr_copy.sin_addr.s_addr ? "enbabled" : "disabled");
9997 if (ast_strlen_zero(stun_hostname_copy)) {
9998 ast_cli(a->fd, " Address: %s:%d\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
9999 htons(stunaddr_copy.sin_port));
10000 } else {
10001 ast_cli(a->fd, " Hostname: %s:%d\n", stun_hostname_copy, htons(stunaddr_copy.sin_port));
10002 ast_cli(a->fd, " Resolved Addr: %s:%d%s\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
10003 htons(stunaddr_copy.sin_port),
10004 stunaddr_copy.sin_addr.s_addr ? stunaddr_resolver ? "" : " (possibly stale)" : " (lookup failed)");
10005 ast_cli(a->fd, " Last TTL: %d (periodic resolution %s)\n", stunaddr_ttl_copy,
10006 stunaddr_resolver ? "enabled" : "disabled");
10007 ast_cli(a->fd, " Reresove TTL 0: %s\n", AST_CLI_YESNO(stunaddr_reresolve_ttl_0));
10008 }
10009 if (stun_acl) {
10010 ast_acl_output(a->fd, stun_acl, " ");
10011 }
10012#endif
10013 return CLI_SUCCESS;
10014}
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 10606 of file res_rtp_asterisk.c.

10607{
10608#ifdef HAVE_PJPROJECT
10609 pj_lock_t *lock;
10610
10612
10614 if (pj_init() != PJ_SUCCESS) {
10616 }
10617
10618 if (pjlib_util_init() != PJ_SUCCESS) {
10619 rtp_terminate_pjproject();
10621 }
10622
10623 if (pjnath_init() != PJ_SUCCESS) {
10624 rtp_terminate_pjproject();
10626 }
10627
10628 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10629
10630 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10631
10632 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10633 rtp_terminate_pjproject();
10635 }
10636
10637 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10638 rtp_terminate_pjproject();
10640 }
10641
10642 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10643
10644 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10645 rtp_terminate_pjproject();
10647 }
10648
10649#endif
10650
10651#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10652 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10653 if (!dtls_bio_methods) {
10654#ifdef HAVE_PJPROJECT
10655 rtp_terminate_pjproject();
10656#endif
10658 }
10659 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10660 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10661 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10662 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10663#endif
10664
10666#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10667 BIO_meth_free(dtls_bio_methods);
10668#endif
10669#ifdef HAVE_PJPROJECT
10670 rtp_terminate_pjproject();
10671#endif
10673 }
10674
10676#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10677 BIO_meth_free(dtls_bio_methods);
10678#endif
10679#ifdef HAVE_PJPROJECT
10681 rtp_terminate_pjproject();
10682#endif
10684 }
10685
10686 rtp_reload(0, 0);
10687
10689}
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 4796 of file res_rtp_asterisk.c.

4797{
4798 tv->tv_sec = msw - 2208988800u;
4799 /* Reverse the sequence in timeval2ntp() */
4800 tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
4801}

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

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

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

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

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

5259{
5260 unsigned char *cp = p;
5261 uint32_t datum;
5262
5263 /* Convert the time to 6.18 format */
5264 datum = (time_msw << 18) & 0x00fc0000;
5265 datum |= (time_lsw >> 14) & 0x0003ffff;
5266
5267 cp[0] = datum >> 16;
5268 cp[1] = datum >> 8;
5269 cp[2] = datum;
5270}

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

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

9270{
9271 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
9272 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9273
9274 ao2_lock(instance);
9275 if (rtp->red->t140.datalen > 0) {
9276 ast_rtp_write(instance, &rtp->red->t140);
9277 }
9278 ao2_unlock(instance);
9279
9280 return 1;
9281}
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 10574 of file res_rtp_asterisk.c.

10575{
10576 rtp_reload(1, 0);
10577 return 0;
10578}

References rtp_reload().

◆ rtcp_debug_test_addr()

static int rtcp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2853 of file res_rtp_asterisk.c.

2854{
2856 return 0;
2857 }
2859 if (rtcpdebugport) {
2860 return (ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0); /* look for RTCP packets from IP+Port */
2861 } else {
2862 return (ast_sockaddr_cmp_addr(&rtcpdebugaddr, addr) == 0); /* only look for RTCP packets from IP */
2863 }
2864 }
2865
2866 return 1;
2867}
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 9899 of file res_rtp_asterisk.c.

9900{
9901 char *arg = ast_strdupa(a->argv[4]);
9902 char *debughost = NULL;
9903 char *debugport = NULL;
9904
9905 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9906 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9907 return CLI_FAILURE;
9908 }
9909 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9910 ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9913 return CLI_SUCCESS;
9914}
#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 3202 of file res_rtp_asterisk.c.

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

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

6635{
6636 switch (pt) {
6637 case AST_RTP_RTCP_RTPFB:
6638 if (subtype == AST_RTP_RTCP_FMT_NACK) {
6639 return "NACK";
6640 }
6641 break;
6642 case RTCP_PT_PSFB:
6643 if (subtype == AST_RTP_RTCP_FMT_REMB) {
6644 return "REMB";
6645 }
6646 break;
6647 default:
6648 break;
6649 }
6650
6651 return NULL;
6652}

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

6603{
6604 const char *str;
6605
6606 switch (pt) {
6607 case RTCP_PT_SR:
6608 str = "Sender Report";
6609 break;
6610 case RTCP_PT_RR:
6611 str = "Receiver Report";
6612 break;
6613 case RTCP_PT_FUR:
6614 /* Full INTRA-frame Request / Fast Update Request */
6615 str = "H.261 FUR";
6616 break;
6617 case RTCP_PT_PSFB:
6618 /* Payload Specific Feed Back */
6619 str = "PSFB";
6620 break;
6621 case RTCP_PT_SDES:
6622 str = "Source Description";
6623 break;
6624 case RTCP_PT_BYE:
6625 str = "BYE";
6626 break;
6627 default:
6628 str = "Unknown";
6629 break;
6630 }
6631 return str;
6632}
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 3452 of file res_rtp_asterisk.c.

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

3531{
3532 return __rtp_sendto(instance, buf, size, flags, sa, 1, ice, 1);
3533}
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 4141 of file res_rtp_asterisk.c.

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

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

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

9883{
9884 char *arg = ast_strdupa(a->argv[4]);
9885 char *debughost = NULL;
9886 char *debugport = NULL;
9887
9888 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9889 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9890 return CLI_FAILURE;
9891 }
9892 rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9893 ast_cli(a->fd, "RTP Packet Debugging Enabled for address: %s\n",
9896 return CLI_SUCCESS;
9897}

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

6598{
6599 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
6600}
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 6589 of file res_rtp_asterisk.c.

6591{
6592 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6593}

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

7852{
7853 int transport_wide_cc_id = ast_rtp_instance_extmap_get_id(instance, AST_RTP_EXTENSION_TRANSPORT_WIDE_CC);
7854 int pos = 0;
7855
7856 /* We currently only care about the transport-cc extension, so if that's not negotiated then do nothing */
7857 if (transport_wide_cc_id == -1) {
7858 return;
7859 }
7860
7861 /* Only while we do not exceed available extension data do we continue */
7862 while (pos < len) {
7863 int id = extension[pos] >> 4;
7864 int extension_len = (extension[pos] & 0xF) + 1;
7865
7866 /* We've handled the first byte as it contains the extension id and length, so always
7867 * skip ahead now
7868 */
7869 pos += 1;
7870
7871 if (id == 0) {
7872 /* From the RFC:
7873 * In both forms, padding bytes have the value of 0 (zero). They may be
7874 * placed between extension elements, if desired for alignment, or after
7875 * the last extension element, if needed for padding. A padding byte
7876 * does not supply the ID of an element, nor the length field. When a
7877 * padding byte is found, it is ignored and the parser moves on to
7878 * interpreting the next byte.
7879 */
7880 continue;
7881 } else if (id == 15) {
7882 /* From the RFC:
7883 * The local identifier value 15 is reserved for future extension and
7884 * MUST NOT be used as an identifier. If the ID value 15 is
7885 * encountered, its length field should be ignored, processing of the
7886 * entire extension should terminate at that point, and only the
7887 * extension elements present prior to the element with ID 15
7888 * considered.
7889 */
7890 break;
7891 } else if ((pos + extension_len) > len) {
7892 /* The extension is corrupted and is stating that it contains more data than is
7893 * available in the extensions data.
7894 */
7895 break;
7896 }
7897
7898 /* If this is transport-cc then we need to parse it further */
7899 if (id == transport_wide_cc_id) {
7900 rtp_instance_parse_transport_wide_cc(instance, rtp, extension + pos, extension_len);
7901 }
7902
7903 /* Skip ahead to the next extension */
7904 pos += extension_len;
7905 }
7906}
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 7795 of file res_rtp_asterisk.c.

7797{
7798 uint16_t *seqno = (uint16_t *)data;
7800 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
7801 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
7802
7803 /* If the sequence number has cycled over then record it as such */
7804 if (((int)transport_rtp->transport_wide_cc.last_seqno - (int)ntohs(*seqno)) > 100) {
7805 transport_rtp->transport_wide_cc.cycles += RTP_SEQ_MOD;
7806 }
7807
7808 /* Populate the statistics information for this packet */
7809 statistics.seqno = transport_rtp->transport_wide_cc.cycles + ntohs(*seqno);
7810 statistics.received = ast_tvnow();
7811
7812 /* We allow at a maximum 1000 packet statistics in play at a time, if we hit the
7813 * limit we give up and start fresh.
7814 */
7815 if (AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) > 1000) {
7817 }
7818
7819 if (!AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) ||
7820 statistics.seqno > transport_rtp->transport_wide_cc.last_extended_seqno) {
7821 /* This is the expected path */
7823 return;
7824 }
7825
7826 transport_rtp->transport_wide_cc.last_extended_seqno = statistics.seqno;
7827 transport_rtp->transport_wide_cc.last_seqno = ntohs(*seqno);
7828 } else {
7829 /* This packet was out of order, so reorder it within the vector accordingly */
7832 return;
7833 }
7834 }
7835
7836 /* If we have not yet scheduled the periodic sending of feedback for this transport then do so */
7837 if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
7838 ast_debug_rtcp(1, "(%p) RTCP starting transport-cc feedback transmission on RTP instance '%p'\n", instance, transport);
7839 ao2_ref(transport, +1);
7840 transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
7842 if (transport_rtp->transport_wide_cc.schedid < 0) {
7843 ao2_ref(transport, -1);
7844 ast_log(LOG_WARNING, "Scheduling RTCP transport-cc feedback transmission failed on RTP instance '%p'\n",
7845 transport);
7846 }
7847 }
7848}
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 7525 of file res_rtp_asterisk.c.

7526{
7527 if (instance) {
7528 ao2_unlock(instance);
7529 }
7530}

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

3644{
3645 if (seq == (uint16_t) (info->max_seq + 1)) {
3646 /* packet is in sequence */
3647 info->packets--;
3648 } else {
3649 /* Sequence discontinuity; reset */
3650 info->packets = learning_min_sequential - 1;
3651 info->received = ast_tvnow();
3652 }
3653
3654 /* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */
3655 if (strictrtp == STRICT_RTP_YES) {
3656 switch (info->stream_type) {
3659 /*
3660 * Protect against packet floods by checking that we
3661 * received the packet sequence in at least the minimum
3662 * allowed time.
3663 */
3664 if (ast_tvzero(info->received)) {
3665 info->received = ast_tvnow();
3666 } else if (!info->packets
3668 /* Packet flood; reset */
3669 info->packets = learning_min_sequential - 1;
3670 info->received = ast_tvnow();
3671 }
3672 break;
3676 case AST_MEDIA_TYPE_END:
3677 break;
3678 }
3679 }
3680
3681 info->max_seq = seq;
3682
3683 return info->packets;
3684}
@ 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 3626 of file res_rtp_asterisk.c.

3627{
3628 info->max_seq = seq;
3629 info->packets = learning_min_sequential;
3630 memset(&info->received, 0, sizeof(info->received));
3631}

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

3692{
3694 memset(&rtp->rtp_source_learn.proposed_address, 0,
3695 sizeof(rtp->rtp_source_learn.proposed_address));
3697 rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t) rtp->lastrxseqno);
3698}

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

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

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

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

9323{
9324 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9325 struct rtp_red *red = rtp->red;
9326
9327 if (!red) {
9328 return 0;
9329 }
9330
9331 if (frame->datalen > 0) {
9332 int space_available = 0;
9333
9334 if (red->t140.datalen > 0) {
9335 const unsigned char *primary = red->buf_data;
9336
9337 /* There is something already in the T.140 buffer */
9338 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9339 /* Flush the previous T.140 packet if it is a command */
9340 ast_rtp_write(instance, &rtp->red->t140);
9341 } else {
9342 primary = frame->data.ptr;
9343 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9344 /* Flush the previous T.140 packet if we are buffering a command now */
9345 ast_rtp_write(instance, &rtp->red->t140);
9346 }
9347 }
9348 }
9349
9350 /*
9351 * RED generation payload sizes are limited to 255 (UCHAR_MAX) bytes by virtue of
9352 * red->len being an array of usigned chars. If adding the current frame will
9353 * exceed that, we're going to flush the saved frame then try again. If the new
9354 * frame fits, great otherwise we're going to toss it. Without understanding
9355 * the purpose of the buffering, that's all we can do now.
9356 */
9357 space_available = UCHAR_MAX - red->t140.datalen;
9358
9359 if (frame->datalen > space_available) {
9360 ast_rtp_write(instance, &rtp->red->t140);
9361 /*
9362 * ast_rtp_write() calls red_t140_to_red() which resets red->t140.datalen
9363 * back to 0 so we now have UCHAR_MAX space available.
9364 */
9365 space_available = UCHAR_MAX;
9366 }
9367
9368 if (frame->datalen > space_available) {
9369 ast_log(LOG_WARNING, "%s: T.140 frame of %d bytes exceeds max of %u. Discarding.\n",
9371 frame->datalen, UCHAR_MAX);
9372 return -1;
9373 }
9374
9375 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
9376 red->t140.datalen += frame->datalen;
9377 red->t140.ts = frame->ts;
9378 }
9379
9380 return 0;
9381}
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 9284 of file res_rtp_asterisk.c.

9285{
9286 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9287 int x;
9288
9289 rtp->red = ast_calloc(1, sizeof(*rtp->red));
9290 if (!rtp->red) {
9291 return -1;
9292 }
9293
9296 rtp->red->t140.data.ptr = &rtp->red->buf_data;
9297
9298 rtp->red->t140red = rtp->red->t140;
9299 rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
9300
9301 rtp->red->num_gen = generations;
9302 rtp->red->hdrlen = generations * 4 + 1;
9303
9304 for (x = 0; x < generations; x++) {
9305 rtp->red->pt[x] = payloads[x];
9306 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
9307 rtp->red->t140red_data[x*4] = rtp->red->pt[x];
9308 }
9309 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
9310 rtp->red->schedid = ast_sched_add(rtp->sched, buffer_time, red_write, instance);
9311
9312 return 0;
9313}
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 10270 of file res_rtp_asterisk.c.

10271{
10272 struct ast_config *cfg;
10273 const char *s;
10274 struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10275
10276#ifdef HAVE_PJPROJECT
10277 struct ast_variable *var;
10278 struct ast_ice_host_candidate *candidate;
10279 int acl_subscription_flag = 0;
10280#endif
10281
10282 cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
10283 if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
10284 return 0;
10285 }
10286
10287#ifdef SO_NO_CHECK
10288 nochecksums = 0;
10289#endif
10290
10299
10300 /** This resource is not "reloaded" so much as unloaded and loaded again.
10301 * In the case of the TURN related variables, the memory referenced by a
10302 * previously loaded instance *should* have been released when the
10303 * corresponding pool was destroyed. If at some point in the future this
10304 * resource were to support ACTUAL live reconfiguration and did NOT release
10305 * the pool this will cause a small memory leak.
10306 */
10307
10308#ifdef HAVE_PJPROJECT
10309 icesupport = DEFAULT_ICESUPPORT;
10310 stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE;
10311 turnport = DEFAULT_TURN_PORT;
10312 clean_stunaddr();
10313 turnaddr = pj_str(NULL);
10314 turnusername = pj_str(NULL);
10315 turnpassword = pj_str(NULL);
10316 host_candidate_overrides_clear();
10317#endif
10318
10319#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10320 dtls_mtu = DEFAULT_DTLS_MTU;
10321#endif
10322
10323 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
10324 rtpstart = atoi(s);
10329 }
10330 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
10331 rtpend = atoi(s);
10336 }
10337 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
10338 rtcpinterval = atoi(s);
10339 if (rtcpinterval == 0)
10340 rtcpinterval = 0; /* Just so we're clear... it's zero */
10342 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
10345 }
10346 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
10347#ifdef SO_NO_CHECK
10348 nochecksums = ast_false(s) ? 1 : 0;
10349#else
10350 if (ast_false(s))
10351 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10352#endif
10353 }
10354 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
10355 dtmftimeout = atoi(s);
10356 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
10357 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
10360 };
10361 }
10362 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
10363 if (ast_true(s)) {
10365 } else if (!strcasecmp(s, "seqno")) {
10367 } else {
10369 }
10370 }
10371 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
10372 if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
10373 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
10376 }
10378 }
10379 if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
10381 }
10382#ifdef HAVE_PJPROJECT
10383 if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
10384 icesupport = ast_true(s);
10385 }
10386 if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
10387 stun_software_attribute = ast_true(s);
10388 }
10389 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr_reresolve_ttl_0"))) {
10390 stunaddr_reresolve_ttl_0 = ast_true(s);
10391 }
10392 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
10393 char *hostport, *host, *port;
10394 unsigned int port_parsed = STANDARD_STUN_PORT;
10395 struct ast_sockaddr stunaddr_parsed;
10396
10397 hostport = ast_strdupa(s);
10398
10399 if (!ast_parse_arg(hostport, PARSE_ADDR, &stunaddr_parsed)) {
10400 ast_debug_stun(3, "stunaddr = '%s' does not need name resolution\n",
10401 ast_sockaddr_stringify_host(&stunaddr_parsed));
10402 if (!ast_sockaddr_port(&stunaddr_parsed)) {
10403 ast_sockaddr_set_port(&stunaddr_parsed, STANDARD_STUN_PORT);
10404 }
10405 ast_rwlock_wrlock(&stunaddr_lock);
10406 ast_sockaddr_to_sin(&stunaddr_parsed, &stunaddr);
10407 /* Set stunaddr_ttl = -1 to indicate no resolution required in the future */
10408 stunaddr_ttl = -1;
10409 ast_rwlock_unlock(&stunaddr_lock);
10410 } else if (ast_sockaddr_split_hostport(hostport, &host, &port, 0)) {
10411 if (port) {
10412 ast_parse_arg(port, PARSE_UINT32|PARSE_IN_RANGE, &port_parsed, 1, 65535);
10413 }
10414
10415 ast_rwlock_wrlock(&stunaddr_lock);
10416
10417 stunaddr.sin_port = htons(port_parsed);
10418 ast_free(stun_hostname);
10419 stun_hostname = ast_strdup(host);
10420 if (!stun_hostname) {
10421 ast_log(LOG_ERROR, "Failed to set stun_hostname from '%s'", host);
10422 } else {
10423 stunaddr_resolver = ast_dns_resolve_recurring(host, T_A, C_IN,
10424 &stunaddr_resolve_callback, NULL);
10425 if (!stunaddr_resolver) {
10426 ast_log(LOG_ERROR, "Failed to setup recurring DNS resolution of stunaddr '%s'",
10427 host);
10428 } else {
10429 ast_debug_stun(2, "Attemping to start recurring stun hostname resolution for '%s'\n", stun_hostname);
10430 }
10431 /*
10432 * Set stunaddr_ttl = 0 to indicate resolution is required.
10433 * If a later query returns a positive ttl, great. We'll use the results
10434 * of the last query until it expires. If it returns 0, we'll resolve
10435 * every time we need it.
10436 */
10437 stunaddr_ttl = 0;
10438 }
10439 ast_rwlock_unlock(&stunaddr_lock);
10440
10441
10442 } else {
10443 ast_log(LOG_ERROR, "Failed to parse stunaddr '%s'", hostport);
10444 }
10445 }
10446 if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
10447 struct sockaddr_in addr;
10448 addr.sin_port = htons(DEFAULT_TURN_PORT);
10449 if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
10450 ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
10451 } else {
10452 pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
10453 /* ntohs() is not a bug here. The port number is used in host byte order with
10454 * a pjnat API. */
10455 turnport = ntohs(addr.sin_port);
10456 }
10457 }
10458 if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
10459 pj_strdup2_with_null(pool, &turnusername, s);
10460 }
10461 if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
10462 pj_strdup2_with_null(pool, &turnpassword, s);
10463 }
10464
10465 AST_RWLIST_WRLOCK(&host_candidates);
10466 for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
10467 struct ast_sockaddr local_addr, advertised_addr;
10468 unsigned int include_local_address = 0;
10469 char *sep;
10470
10471 ast_sockaddr_setnull(&local_addr);
10472 ast_sockaddr_setnull(&advertised_addr);
10473
10474 if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
10475 ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
10476 continue;
10477 }
10478
10479 sep = strchr((char *)var->value,',');
10480 if (sep) {
10481 *sep = '\0';
10482 sep++;
10483 sep = ast_skip_blanks(sep);
10484 include_local_address = strcmp(sep, "include_local_address") == 0;
10485 }
10486
10487 if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
10488 ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
10489 continue;
10490 }
10491
10492 if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
10493 ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
10494 break;
10495 }
10496
10497 candidate->include_local = include_local_address;
10498
10499 ast_sockaddr_copy(&candidate->local, &local_addr);
10500 ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
10501
10502 AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
10503 }
10504 AST_RWLIST_UNLOCK(&host_candidates);
10505
10506 ast_rwlock_wrlock(&ice_acl_lock);
10507 ast_rwlock_wrlock(&stun_acl_lock);
10508
10509 ice_acl = ast_free_acl_list(ice_acl);
10510 stun_acl = ast_free_acl_list(stun_acl);
10511
10512 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
10513 const char* sense = NULL;
10514 struct ast_acl_list **acl = NULL;
10515 if (strncasecmp(var->name, "ice_", 4) == 0) {
10516 sense = var->name + 4;
10517 acl = &ice_acl;
10518 } else if (strncasecmp(var->name, "stun_", 5) == 0) {
10519 sense = var->name + 5;
10520 acl = &stun_acl;
10521 } else {
10522 continue;
10523 }
10524
10525 if (strcasecmp(sense, "blacklist") == 0) {
10526 sense = "deny";
10527 }
10528
10529 if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
10530 continue;
10531 }
10532
10533 ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
10534 }
10535 ast_rwlock_unlock(&ice_acl_lock);
10536 ast_rwlock_unlock(&stun_acl_lock);
10537
10538 if (acl_subscription_flag && !acl_change_sub) {
10542 } else if (!acl_subscription_flag && acl_change_sub) {
10544 }
10545#endif
10546#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10547 if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
10548 if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
10549 ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
10551 dtls_mtu = DEFAULT_DTLS_MTU;
10552 }
10553 }
10554#endif
10555
10556 ast_config_destroy(cfg);
10557
10558 /* Choosing an odd start port casues issues (like a potential infinite loop) and as odd parts are not
10559 chosen anyway, we are going to round up and issue a warning */
10560 if (rtpstart & 1) {
10561 rtpstart++;
10562 ast_log(LOG_WARNING, "Odd start value for RTP port in rtp.conf, rounding up to %d\n", rtpstart);
10563 }
10564
10565 if (rtpstart >= rtpend) {
10566 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
10569 }
10570 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
10571 return 0;
10572}
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 3536 of file res_rtp_asterisk.c.

3537{
3538 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3539 int hdrlen = 12;
3540 int res;
3541
3542 if ((res = __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1)) > 0) {
3543 rtp->txcount++;
3544 rtp->txoctetcount += (res - hdrlen);
3545 }
3546
3547 return res;
3548}

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

7609{
7610 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
7611 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7612 unsigned char *rtcpheader;
7613 char bdata[1024];
7614 struct rtp_transport_wide_cc_packet_statistics *first_packet;
7615 struct rtp_transport_wide_cc_packet_statistics *previous_packet;
7616 int i;
7617 int status_vector_chunk_bits = 14;
7618 uint16_t status_vector_chunk = (1 << 15) | (1 << 14);
7619 int run_length_chunk_count = 0;
7620 int run_length_chunk_status = -1;
7621 int packet_len = 20;
7622 int delta_len = 0;
7623 int packet_count = 0;
7624 unsigned int received_msw;
7625 unsigned int received_lsw;
7626 struct ast_sockaddr remote_address = { { 0, } };
7627 int res;
7628 int ice;
7629 unsigned int large_delta_count = 0;
7630 unsigned int small_delta_count = 0;
7631 unsigned int lost_count = 0;
7632
7633 if (!rtp || !rtp->rtcp || rtp->transport_wide_cc.schedid == -1) {
7634 ao2_ref(instance, -1);
7635 return 0;
7636 }
7637
7638 ao2_lock(instance);
7639
7640 /* If no packets have been received then do nothing */
7642 ao2_unlock(instance);
7643 return 1000;
7644 }
7645
7646 rtcpheader = (unsigned char *)bdata;
7647
7648 /* The first packet in the vector acts as our base sequence number and reference time */
7650 previous_packet = first_packet;
7651
7652 /* We go through each packet that we have statistics for, adding it either to a status
7653 * vector chunk or a run length chunk. The code tries to be as efficient as possible to
7654 * reduce packet size and will favor run length chunks when it makes sense.
7655 */
7656 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7658 int lost = 0;
7659 int res = 0;
7660
7662
7663 packet_count++;
7664
7665 if (first_packet != statistics) {
7666 /* The vector stores statistics in a sorted fashion based on the sequence
7667 * number. This ensures we can detect any packets that have been lost/not
7668 * received by comparing the sequence numbers.
7669 */
7670 lost = statistics->seqno - (previous_packet->seqno + 1);
7671 lost_count += lost;
7672 }
7673
7674 while (lost) {
7675 /* We append a not received status until all the lost packets have been accounted for */
7676 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7677 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 0);
7678 packet_count++;
7679
7680 /* If there is no more room left for storing packets stop now, we leave 20
7681 * extra bits at the end just in case.
7682 */
7683 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7684 res = -1;
7685 break;
7686 }
7687
7688 lost--;
7689 }
7690
7691 /* If the lost packet appending bailed out because we have no more space, then exit here too */
7692 if (res) {
7693 break;
7694 }
7695
7696 /* Per the spec the delta is in increments of 250 */
7697 statistics->delta = ast_tvdiff_us(statistics->received, previous_packet->received) / 250;
7698
7699 /* Based on the delta determine the status of this packet */
7700 if (statistics->delta < 0 || statistics->delta > 127) {
7701 /* Large or negative delta */
7702 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7703 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 2);
7704 delta_len += 2;
7705 large_delta_count++;
7706 } else {
7707 /* Small delta */
7708 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7709 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 1);
7710 delta_len += 1;
7711 small_delta_count++;
7712 }
7713
7714 previous_packet = statistics;
7715
7716 /* If there is no more room left in the packet stop handling of any subsequent packets */
7717 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7718 break;
7719 }
7720 }
7721
7722 if (status_vector_chunk_bits != 14) {
7723 /* If the status vector chunk has packets in it then place it in the RTCP packet */
7724 put_unaligned_uint16(rtcpheader + packet_len, htons(status_vector_chunk));
7725 packet_len += 2;
7726 } else if (run_length_chunk_count) {
7727 /* If there is a run length chunk in progress then place it in the RTCP packet */
7728 put_unaligned_uint16(rtcpheader + packet_len, htons((0 << 15) | (run_length_chunk_status << 13) | run_length_chunk_count));
7729 packet_len += 2;
7730 }
7731
7732 /* We iterate again to build delta chunks */
7733 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7735
7737
7738 if (statistics->delta < 0 || statistics->delta > 127) {
7739 /* We need 2 bytes to store this delta */
7740 put_unaligned_uint16(rtcpheader + packet_len, htons(statistics->delta));
7741 packet_len += 2;
7742 } else {
7743 /* We can store this delta in 1 byte */
7744 rtcpheader[packet_len] = statistics->delta;
7745 packet_len += 1;
7746 }
7747
7748 /* If this is the last packet handled by the run length chunk or status vector chunk code
7749 * then we can go no further.
7750 */
7751 if (statistics == previous_packet) {
7752 break;
7753 }
7754 }
7755
7756 /* Zero pad the end of the packet */
7757 while (packet_len % 4) {
7758 rtcpheader[packet_len++] = 0;
7759 }
7760
7761 /* Add the general RTCP header information */
7762 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC << 24)
7763 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
7764 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
7765 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
7766
7767 /* Add the transport-cc specific header information */
7768 put_unaligned_uint32(rtcpheader + 12, htonl((first_packet->seqno << 16) | packet_count));
7769
7770 timeval2ntp(first_packet->received, &received_msw, &received_lsw);
7771 put_unaligned_time24(rtcpheader + 16, received_msw, received_lsw);
7772 rtcpheader[19] = rtp->transport_wide_cc.feedback_count;
7773
7774 /* The packet is now fully constructed so send it out */
7775 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
7776
7777 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",
7778 instance, packet_len, ast_rtp_instance_get_channel_id(instance), packet_count, small_delta_count, large_delta_count, lost_count);
7779
7780 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
7781 if (res < 0) {
7782 ast_log(LOG_ERROR, "RTCP transport-cc feedback error to %s due to %s\n",
7783 ast_sockaddr_stringify(&remote_address), strerror(errno));
7784 }
7785
7787
7789
7790 ao2_unlock(instance);
7791
7792 return 1000;
7793}
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 7567 of file res_rtp_asterisk.c.

7569{
7570 if (*run_length_chunk_status != status) {
7571 while (*run_length_chunk_count > 0 && *run_length_chunk_count < 8) {
7572 /* Realistically it only makes sense to use a run length chunk if there were 8 or more
7573 * consecutive packets of the same type, otherwise we could end up making the packet larger
7574 * if we have lots of small blocks of the same type. To help with this we backfill the status
7575 * vector (since it always represents 7 packets). Best case we end up with only that single
7576 * status vector and the rest are run length chunks.
7577 */
7578 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7579 status_vector_chunk, *run_length_chunk_status);
7580 *run_length_chunk_count -= 1;
7581 }
7582
7583 if (*run_length_chunk_count) {
7584 /* There is a run length chunk which needs to be written out */
7585 put_unaligned_uint16(rtcpheader + *packet_len, htons((0 << 15) | (*run_length_chunk_status << 13) | *run_length_chunk_count));
7586 *packet_len += 2;
7587 }
7588
7589 /* In all cases the run length chunk has to be reset */
7590 *run_length_chunk_count = 0;
7591 *run_length_chunk_status = -1;
7592
7593 if (*status_vector_chunk_bits == 14) {
7594 /* We aren't in the middle of a status vector so we can try for a run length chunk */
7595 *run_length_chunk_status = status;
7596 *run_length_chunk_count = 1;
7597 } else {
7598 /* We're doing a status vector so populate it accordingly */
7599 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7600 status_vector_chunk, status);
7601 }
7602 } else {
7603 /* This is easy, the run length chunk count can just get bumped up */
7604 *run_length_chunk_count += 1;
7605 }
7606}
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 7538 of file res_rtp_asterisk.c.

7540{
7541 /* Appending this status will use up 2 bits */
7542 *status_vector_chunk_bits -= 2;
7543
7544 /* We calculate which bits we want to update the status of. Since a status vector
7545 * is 16 bits we take away 2 (for the header), and then we take away any that have
7546 * already been used.
7547 */
7548 *status_vector_chunk |= (status << (16 - 2 - (14 - *status_vector_chunk_bits)));
7549
7550 /* If there are still bits available we can return early */
7551 if (*status_vector_chunk_bits) {
7552 return;
7553 }
7554
7555 /* Otherwise we have to place this chunk into the packet */
7556 put_unaligned_uint16(rtcpheader + *packet_len, htons(*status_vector_chunk));
7557 *status_vector_chunk_bits = 14;
7558
7559 /* The first bit being 1 indicates that this is a status vector chunk and the second
7560 * bit being 1 indicates that we are using 2 bits to represent each status for a
7561 * packet.
7562 */
7563 *status_vector_chunk = (1 << 15) | (1 << 14);
7564 *packet_len += 2;
7565}

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

7534{
7535 return a.seqno - b.seqno;
7536}
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 5554 of file res_rtp_asterisk.c.

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

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

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

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

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

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

10692{
10695
10696#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10697 if (dtls_bio_methods) {
10698 BIO_meth_free(dtls_bio_methods);
10699 }
10700#endif
10701
10702#ifdef HAVE_PJPROJECT
10703 host_candidate_overrides_clear();
10704 pj_thread_register_check();
10705 rtp_terminate_pjproject();
10706
10708 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10709 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10710 clean_stunaddr();
10711#endif
10712
10713 return 0;
10714}
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 6531 of file res_rtp_asterisk.c.

6532{
6534 rtp->rtcp->normdevrtt,
6535 rtp->rxjitter,
6536 rtp->rtcp->stdev_rxjitter,
6537 rtp->rtcp->normdev_rxlost);
6538
6539 if (rtp->rtcp->rxmes_count == 0) {
6540 rtp->rtcp->minrxmes = rtp->rxmes;
6541 }
6542 if (rtp->rxmes < rtp->rtcp->minrxmes) {
6543 rtp->rtcp->minrxmes = rtp->rxmes;
6544 }
6545 if (rtp->rxmes > rtp->rtcp->maxrxmes) {
6546 rtp->rtcp->maxrxmes = rtp->rxmes;
6547 }
6548
6550 &rtp->rtcp->stdev_rxmes, &rtp->rtcp->rxmes_count);
6551
6552 ast_debug_rtcp(2, " %s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6554 rtp->rtcp->normdevrtt,
6555 rtp->rxjitter,
6556 rtp->rtcp->stdev_rxjitter,
6557 rtp->rtcp->normdev_rxlost, rtp->rxmes);
6558}
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_rxlost, ast_rtcp::normdev_rxmes, ast_rtcp::normdevrtt, ast_rtp::owner, ast_rtp::rtcp, ast_rtp::rxjitter, ast_rtp::rxmes, ast_rtcp::rxmes_count, ast_rtcp::stdev_rxjitter, and ast_rtcp::stdev_rxmes.

Referenced by ast_rtcp_generate_report().

◆ update_lost_stats()

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

Definition at line 6387 of file res_rtp_asterisk.c.

6388{
6389 double reported_lost;
6390
6391 rtp->rtcp->reported_lost = lost_packets;
6392 reported_lost = (double)rtp->rtcp->reported_lost;
6393 if (rtp->rtcp->reported_lost_count == 0) {
6394 rtp->rtcp->reported_minlost = reported_lost;
6395 }
6396 if (reported_lost < rtp->rtcp->reported_minlost) {
6397 rtp->rtcp->reported_minlost = reported_lost;
6398 }
6399 if (reported_lost > rtp->rtcp->reported_maxlost) {
6400 rtp->rtcp->reported_maxlost = reported_lost;
6401 }
6402
6405}
unsigned int reported_lost_count

References calc_mean_and_standard_deviation(), 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 6496 of file res_rtp_asterisk.c.

6497{
6498 double mes = calc_media_experience_score(rtp->owner,
6499 rtp->rtcp->normdevrtt,
6500 rtp->rtcp->reported_jitter,
6503
6504 rtp->rtcp->reported_mes = mes;
6505 if (rtp->rtcp->reported_mes_count == 0) {
6506 rtp->rtcp->reported_minmes = mes;
6507 }
6508 if (mes < rtp->rtcp->reported_minmes) {
6509 rtp->rtcp->reported_minmes = mes;
6510 }
6511 if (mes > rtp->rtcp->reported_maxmes) {
6512 rtp->rtcp->reported_maxmes = mes;
6513 }
6514
6517
6518 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6520 rtp->rtcp->normdevrtt,
6521 rtp->rtcp->reported_jitter,
6523 rtp->rtcp->reported_normdev_lost, mes);
6524}
unsigned int reported_mes_count

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

Referenced by ast_rtcp_interpret().

◆ update_rtt_stats()

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

Definition at line 6306 of file res_rtp_asterisk.c.

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 10725 of file res_rtp_asterisk.c.

◆ asterisk_rtp_engine

struct ast_rtp_engine asterisk_rtp_engine
static

Definition at line 2575 of file res_rtp_asterisk.c.

2575 {
2576 .name = "asterisk",
2577 .new = ast_rtp_new,
2578 .destroy = ast_rtp_destroy,
2579 .dtmf_begin = ast_rtp_dtmf_begin,
2580 .dtmf_end = ast_rtp_dtmf_end,
2581 .dtmf_end_with_duration = ast_rtp_dtmf_end_with_duration,
2582 .dtmf_mode_set = ast_rtp_dtmf_mode_set,
2583 .dtmf_mode_get = ast_rtp_dtmf_mode_get,
2584 .update_source = ast_rtp_update_source,
2585 .change_source = ast_rtp_change_source,
2586 .write = ast_rtp_write,
2587 .read = ast_rtp_read,
2588 .prop_set = ast_rtp_prop_set,
2589 .fd = ast_rtp_fd,
2590 .remote_address_set = ast_rtp_remote_address_set,
2591 .red_init = rtp_red_init,
2592 .red_buffer = rtp_red_buffer,
2593 .local_bridge = ast_rtp_local_bridge,
2594 .get_stat = ast_rtp_get_stat,
2595 .dtmf_compatible = ast_rtp_dtmf_compatible,
2596 .stun_request = ast_rtp_stun_request,
2597 .stop = ast_rtp_stop,
2598 .qos = ast_rtp_qos_set,
2599 .sendcng = ast_rtp_sendcng,
2600#ifdef HAVE_PJPROJECT
2601 .ice = &ast_rtp_ice,
2602#endif
2603#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
2604 .dtls = &ast_rtp_dtls,
2605 .activate = ast_rtp_activate,
2606#endif
2607 .ssrc_get = ast_rtp_get_ssrc,
2608 .cname_get = ast_rtp_get_cname,
2609 .set_remote_ssrc = ast_rtp_set_remote_ssrc,
2610 .set_stream_num = ast_rtp_set_stream_num,
2611 .extension_enable = ast_rtp_extension_enable,
2612 .bundle = ast_rtp_bundle,
2613#ifdef TEST_FRAMEWORK
2614 .test = &ast_rtp_test,
2615#endif
2616};
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 10257 of file res_rtp_asterisk.c.

10257 {
10258 AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
10259 AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
10260 AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
10261 AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
10262#ifdef AST_DEVMODE
10263 AST_CLI_DEFINE(handle_cli_rtp_drop_incoming_packets, "Drop RTP incoming packets"),
10264#endif
10265#ifdef HAVE_PJPROJECT
10266 AST_CLI_DEFINE(handle_cli_rtp_refresh_stun, "Force a resolution of the STUN hostname"),
10267#endif
10268};
#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().