Asterisk - The Open Source Telephony Project GIT-master-80b953f
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 302 of file res_rtp_asterisk.c.

◆ FLAG_DTMF_COMPENSATE

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 307 of file res_rtp_asterisk.c.

◆ FLAG_NAT_ACTIVE

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 303 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 304 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE_NOWARN

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 305 of file res_rtp_asterisk.c.

◆ FLAG_NEED_MARKER_BIT

#define FLAG_NEED_MARKER_BIT   (1 << 3)

Definition at line 306 of file res_rtp_asterisk.c.

◆ FLAG_REQ_LOCAL_BRIDGE_BIT

#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)

Definition at line 308 of file res_rtp_asterisk.c.

◆ MAX_TIMESTAMP_SKEW

#define MAX_TIMESTAMP_SKEW   640

Definition at line 98 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_PORT

#define MAXIMUM_RTP_PORT   65535

Maximum port number to accept

Definition at line 109 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_RECV_BUFFER_SIZE

#define MAXIMUM_RTP_RECV_BUFFER_SIZE   (DEFAULT_RTP_RECV_BUFFER_SIZE + 20)

Maximum RTP receive buffer size

Definition at line 118 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_SEND_BUFFER_SIZE

#define MAXIMUM_RTP_SEND_BUFFER_SIZE   (DEFAULT_RTP_SEND_BUFFER_SIZE + 200)

Maximum RTP send buffer size

Definition at line 116 of file res_rtp_asterisk.c.

◆ MINIMUM_RTP_PORT

#define MINIMUM_RTP_PORT   1024

Minimum port number to accept

Definition at line 108 of file res_rtp_asterisk.c.

◆ MISSING_SEQNOS_ADDED_TRIGGER

#define MISSING_SEQNOS_ADDED_TRIGGER   2

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

Definition at line 120 of file res_rtp_asterisk.c.

◆ OLD_PACKET_COUNT

#define OLD_PACKET_COUNT   1000

The number of previous packets that are considered old

Definition at line 119 of file res_rtp_asterisk.c.

◆ RESCALE

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

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

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6687 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6686 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6651 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

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

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6663 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6652 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

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

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6662 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6685 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6684 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 6681 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 6682 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6666 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6655 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6668 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6664 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

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

◆ STRICT_RTP_LEARN_TIMEOUT

#define STRICT_RTP_LEARN_TIMEOUT   5000

Strict RTP learning timeout time in milliseconds.

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

Definition at line 187 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTCP

#define TRANSPORT_SOCKET_RTCP   1

Definition at line 311 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTP

#define TRANSPORT_SOCKET_RTP   0

Definition at line 310 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTCP

#define TRANSPORT_TURN_RTCP   3

Definition at line 313 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTP

#define TRANSPORT_TURN_RTP   2

Definition at line 312 of file res_rtp_asterisk.c.

◆ TURN_STATE_WAIT_TIME

#define TURN_STATE_WAIT_TIME   2000

Definition at line 113 of file res_rtp_asterisk.c.

◆ ZFONE_PROFILE_ID

#define ZFONE_PROFILE_ID   0x505a

Definition at line 144 of file res_rtp_asterisk.c.

Enumeration Type Documentation

◆ strict_rtp_mode

Enumerator
STRICT_RTP_NO 
STRICT_RTP_YES 

Don't adhere to any strict RTP rules

STRICT_RTP_SEQNO 

Strict RTP that restricts packets based on time and sequence number

Definition at line 174 of file res_rtp_asterisk.c.

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

◆ strict_rtp_state

Enumerator
STRICT_RTP_OPEN 
STRICT_RTP_LEARN 

No RTP packets should be dropped, all sources accepted

STRICT_RTP_CLOSED 

Accept next packet as source

Definition at line 168 of file res_rtp_asterisk.c.

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

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

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

6461{
6462 int index;
6463
6464 if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
6465 /* This instance is not bundled */
6466 return instance;
6467 }
6468
6469 /* Find the bundled child instance */
6470 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
6471 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
6472 unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
6473
6474 if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
6475 return mapping->instance;
6476 }
6477 }
6478
6479 /* Does the SSRC match the bundled parent? */
6480 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
6481 return instance;
6482 }
6483 return NULL;
6484}
static unsigned int ast_rtp_get_ssrc(struct ast_rtp_instance *instance)
#define NULL
Definition resample.c:96
struct ast_rtp::@512 ssrc_mapping
unsigned int themssrc_valid
unsigned int themssrc
Structure used for mapping an incoming SSRC to an RTP instance.
unsigned int ssrc
The received SSRC.
unsigned int ssrc_valid
struct ast_rtp_instance * instance
The RTP instance this SSRC belongs to.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:620
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition vector.h:679

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

Referenced by rtp_find_instance_by_media_source_ssrc(), and rtp_find_instance_by_packet_source_ssrc().

◆ __rtp_recvfrom()

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

Definition at line 3229 of file res_rtp_asterisk.c.

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

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

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

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

3544{
3545 unsigned int interval;
3546 /*! \todo XXX Do a more reasonable calculation on this one
3547 * Look in RFC 3550 Section A.7 for an example*/
3548 interval = rtcpinterval;
3549 return interval;
3550}
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 4868 of file res_rtp_asterisk.c.

4870{
4871 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4872 struct ast_rtp_rtcp_report_block *report_block = NULL;
4873 RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
4874
4875 if (!rtp || !rtp->rtcp) {
4876 return 0;
4877 }
4878
4879 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4880 return 0;
4881 }
4882
4883 if (!rtcp_report) {
4884 return -1;
4885 }
4886
4887 report_block = rtcp_report->report_block[0];
4888
4889 if (sr) {
4890 rtp->rtcp->txlsr = rtcp_report->sender_information.ntp_timestamp;
4891 rtp->rtcp->sr_count++;
4892 rtp->rtcp->lastsrtxcount = rtp->txcount;
4893 } else {
4894 rtp->rtcp->rr_count++;
4895 }
4896
4897 if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
4898 ast_verbose("* Sent RTCP %s to %s%s\n", sr ? "SR" : "RR",
4899 ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
4900 ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
4901 if (sr) {
4902 ast_verbose(" Sent(NTP): %u.%06u\n",
4903 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
4904 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
4905 ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
4906 ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
4907 ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
4908 }
4909 if (report_block) {
4910 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
4911 ast_verbose(" Report block:\n");
4912 ast_verbose(" Their SSRC: %u\n", report_block->source_ssrc);
4913 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
4914 ast_verbose(" Cumulative loss: %u\n", report_block->lost_count.packets);
4915 ast_verbose(" Highest seq no: %u\n", report_block->highest_seq_no);
4916 ast_verbose(" IA jitter (samp): %u\n", report_block->ia_jitter);
4917 ast_verbose(" IA jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
4918 ast_verbose(" Their last SR: %u\n", report_block->lsr);
4919 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
4920 }
4921 }
4922
4923 message_blob = ast_json_pack("{s: s, s: s, s: f}",
4924 "to", ast_sockaddr_stringify(&remote_address),
4925 "from", rtp->rtcp->local_addr_str,
4926 "mes", rtp->rxmes);
4927
4929 rtcp_report, message_blob);
4930
4931 return 1;
4932}
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::@287 lost_count
struct ast_rtp_rtcp_report::@288 sender_information
unsigned int rtp_timestamp
Definition rtp_engine.h:367
struct ast_rtp_rtcp_report_block * report_block[0]
Definition rtp_engine.h:374
struct timeval ntp_timestamp
Definition rtp_engine.h:366
unsigned int octet_count
Definition rtp_engine.h:369
unsigned int ssrc
Definition rtp_engine.h:363
unsigned int packet_count
Definition rtp_engine.h:368
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 4992 of file res_rtp_asterisk.c.

4994{
4995 int packet_len = 0;
4996 int res;
4997
4998 /* Every RTCP packet needs to be sent out with a SR/RR and SDES prefixing it.
4999 * At the end of this function, rtcpheader should contain both of those packets,
5000 * and will return the length of the overall packet. This can be used to determine
5001 * where further packets can be inserted in the compound packet.
5002 */
5003 res = ast_rtcp_generate_report(instance, rtcpheader, report, sr);
5004
5005 if (res == 0 || res == 1) {
5006 ast_debug_rtcp(1, "(%p) RTCP failed to generate %s report!\n", instance, sr ? "SR" : "RR");
5007 return 0;
5008 }
5009
5010 packet_len += res;
5011
5012 res = ast_rtcp_generate_sdes(instance, rtcpheader + packet_len, report);
5013
5014 if (res == 0 || res == 1) {
5015 ast_debug_rtcp(1, "(%p) RTCP failed to generate SDES!\n", instance);
5016 return 0;
5017 }
5018
5019 return packet_len + res;
5020}
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 5022 of file res_rtp_asterisk.c.

5023{
5024 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5025 int packet_len;
5026 int blp_index = -1;
5027 int current_seqno;
5028 unsigned int fci = 0;
5029 size_t remaining_missing_seqno;
5030
5031 if (!rtp || !rtp->rtcp) {
5032 return 0;
5033 }
5034
5035 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
5036 return 0;
5037 }
5038
5039 current_seqno = rtp->expectedrxseqno;
5040 remaining_missing_seqno = AST_VECTOR_SIZE(&rtp->missing_seqno);
5041 packet_len = 12; /* The header length is 12 (version line, packet source SSRC, media source SSRC) */
5042
5043 /* If there are no missing sequence numbers then don't bother sending a NACK needlessly */
5044 if (!remaining_missing_seqno) {
5045 return 0;
5046 }
5047
5048 /* This iterates through the possible forward sequence numbers seeing which ones we
5049 * have no packet for, adding it to the NACK until we are out of missing packets.
5050 */
5051 while (remaining_missing_seqno) {
5052 int *missing_seqno;
5053
5054 /* On the first entry to this loop blp_index will be -1, so this will become 0
5055 * and the sequence number will be placed into the packet as the PID.
5056 */
5057 blp_index++;
5058
5059 missing_seqno = AST_VECTOR_GET_CMP(&rtp->missing_seqno, current_seqno,
5061 if (missing_seqno) {
5062 /* We hit the max blp size, reset */
5063 if (blp_index >= 17) {
5064 put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
5065 fci = 0;
5066 blp_index = 0;
5067 packet_len += 4;
5068 }
5069
5070 if (blp_index == 0) {
5071 fci |= (current_seqno << 16);
5072 } else {
5073 fci |= (1 << (blp_index - 1));
5074 }
5075
5076 /* Since we've used a missing sequence number, we're down one */
5077 remaining_missing_seqno--;
5078 }
5079
5080 /* Handle cycling of the sequence number */
5081 current_seqno++;
5082 if (current_seqno == SEQNO_CYCLE_OVER) {
5083 current_seqno = 0;
5084 }
5085 }
5086
5087 put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
5088 packet_len += 4;
5089
5090 /* Length MUST be 2+n, where n is the number of NACKs. Same as length in words minus 1 */
5091 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_NACK << 24)
5092 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
5093 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
5094 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
5095
5096 return packet_len;
5097}
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
struct ast_rtp::@511 missing_seqno
unsigned int ssrc
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition unaligned.h:58
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition vector.h:742

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

Referenced by ast_rtp_read().

◆ ast_rtcp_generate_report()

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

Definition at line 4775 of file res_rtp_asterisk.c.

4777{
4778 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4779 int len = 0;
4780 struct timeval now;
4781 unsigned int now_lsw;
4782 unsigned int now_msw;
4783 unsigned int lost_packets;
4784 int fraction_lost;
4785 struct timeval dlsr = { 0, };
4786 struct ast_rtp_rtcp_report_block *report_block = NULL;
4787
4788 if (!rtp || !rtp->rtcp) {
4789 return 0;
4790 }
4791
4792 if (ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */
4793 /* RTCP was stopped. */
4794 return 0;
4795 }
4796
4797 if (!rtcp_report) {
4798 return 1;
4799 }
4800
4801 *sr = rtp->txcount > rtp->rtcp->lastsrtxcount ? 1 : 0;
4802
4803 /* Compute statistics */
4804 calculate_lost_packet_statistics(rtp, &lost_packets, &fraction_lost);
4805 /*
4806 * update_local_mes_stats must be called AFTER
4807 * calculate_lost_packet_statistics
4808 */
4810
4811 gettimeofday(&now, NULL);
4812 rtcp_report->reception_report_count = rtp->themssrc_valid ? 1 : 0;
4813 rtcp_report->ssrc = rtp->ssrc;
4814 rtcp_report->type = *sr ? RTCP_PT_SR : RTCP_PT_RR;
4815 if (*sr) {
4816 rtcp_report->sender_information.ntp_timestamp = now;
4817 rtcp_report->sender_information.rtp_timestamp = rtp->lastts;
4818 rtcp_report->sender_information.packet_count = rtp->txcount;
4819 rtcp_report->sender_information.octet_count = rtp->txoctetcount;
4820 }
4821
4822 if (rtp->themssrc_valid) {
4823 report_block = ast_calloc(1, sizeof(*report_block));
4824 if (!report_block) {
4825 return 1;
4826 }
4827
4828 rtcp_report->report_block[0] = report_block;
4829 report_block->source_ssrc = rtp->themssrc;
4830 report_block->lost_count.fraction = (fraction_lost & 0xff);
4831 report_block->lost_count.packets = (lost_packets & 0xffffff);
4832 report_block->highest_seq_no = (rtp->cycles | (rtp->lastrxseqno & 0xffff));
4833 report_block->ia_jitter = (unsigned int)rtp->rxjitter_samples;
4834 report_block->lsr = rtp->rtcp->themrxlsr;
4835 /* If we haven't received an SR report, DLSR should be 0 */
4836 if (!ast_tvzero(rtp->rtcp->rxlsr)) {
4837 timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
4838 report_block->dlsr = (((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000;
4839 }
4840 }
4841 timeval2ntp(rtcp_report->sender_information.ntp_timestamp, &now_msw, &now_lsw);
4842 put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc)); /* Our SSRC */
4843 len += 8;
4844 if (*sr) {
4845 put_unaligned_uint32(rtcpheader + len, htonl(now_msw)); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970 */
4846 put_unaligned_uint32(rtcpheader + len + 4, htonl(now_lsw)); /* now, LSW */
4847 put_unaligned_uint32(rtcpheader + len + 8, htonl(rtcp_report->sender_information.rtp_timestamp));
4848 put_unaligned_uint32(rtcpheader + len + 12, htonl(rtcp_report->sender_information.packet_count));
4849 put_unaligned_uint32(rtcpheader + len + 16, htonl(rtcp_report->sender_information.octet_count));
4850 len += 20;
4851 }
4852 if (report_block) {
4853 put_unaligned_uint32(rtcpheader + len, htonl(report_block->source_ssrc)); /* Their SSRC */
4854 put_unaligned_uint32(rtcpheader + len + 4, htonl((report_block->lost_count.fraction << 24) | report_block->lost_count.packets));
4855 put_unaligned_uint32(rtcpheader + len + 8, htonl(report_block->highest_seq_no));
4856 put_unaligned_uint32(rtcpheader + len + 12, htonl(report_block->ia_jitter));
4857 put_unaligned_uint32(rtcpheader + len + 16, htonl(report_block->lsr));
4858 put_unaligned_uint32(rtcpheader + len + 20, htonl(report_block->dlsr));
4859 len += 24;
4860 }
4861
4862 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (rtcp_report->reception_report_count << 24)
4863 | ((*sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1)));
4864
4865 return len;
4866}
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 4934 of file res_rtp_asterisk.c.

4936{
4937 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4938 int len = 0;
4939 uint16_t sdes_packet_len_bytes;
4940 uint16_t sdes_packet_len_rounded;
4941
4942 if (!rtp || !rtp->rtcp) {
4943 return 0;
4944 }
4945
4946 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4947 return 0;
4948 }
4949
4950 if (!rtcp_report) {
4951 return -1;
4952 }
4953
4954 sdes_packet_len_bytes =
4955 4 + /* RTCP Header */
4956 4 + /* SSRC */
4957 1 + /* Type (CNAME) */
4958 1 + /* Text Length */
4959 AST_UUID_STR_LEN /* Text and NULL terminator */
4960 ;
4961
4962 /* Round to 32 bit boundary */
4963 sdes_packet_len_rounded = (sdes_packet_len_bytes + 3) & ~0x3;
4964
4965 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((sdes_packet_len_rounded / 4) - 1)));
4966 put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc));
4967 rtcpheader[8] = 0x01; /* CNAME */
4968 rtcpheader[9] = AST_UUID_STR_LEN - 1; /* Number of bytes of text */
4969 memcpy(rtcpheader + 10, rtp->cname, AST_UUID_STR_LEN);
4970 len += 10 + AST_UUID_STR_LEN;
4971
4972 /* Padding - Note that we don't set the padded bit on the packet. From
4973 * RFC 3550 Section 6.5:
4974 *
4975 * No length octet follows the null item type octet, but additional null
4976 * octets MUST be included if needd to pad until the next 32-bit
4977 * boundary. Note that this padding is separate from that indicated by
4978 * the P bit in the RTCP header.
4979 *
4980 * These bytes will already be zeroed out during array initialization.
4981 */
4982 len += (sdes_packet_len_rounded - sdes_packet_len_bytes);
4983
4984 return len;
4985}
#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 6690 of file res_rtp_asterisk.c.

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

7197{
7198 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7199 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 1);
7200 struct ast_sockaddr addr;
7201 unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
7202 unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
7203 size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
7204 int res;
7205
7206 /* Read in RTCP data from the socket */
7207 if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
7208 0, &addr)) < 0) {
7209 if (res == RTP_DTLS_ESTABLISHED) {
7212 return &rtp->f;
7213 }
7214
7215 ast_assert(errno != EBADF);
7216 if (errno != EAGAIN) {
7217 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n",
7218 (errno) ? strerror(errno) : "Unspecified");
7219 return NULL;
7220 }
7221 return &ast_null_frame;
7222 }
7223
7224 /* If this was handled by the ICE session don't do anything further */
7225 if (!res) {
7226 return &ast_null_frame;
7227 }
7228
7229 if (!*read_area) {
7230 struct sockaddr_in addr_tmp;
7231 struct ast_sockaddr addr_v4;
7232
7233 if (ast_sockaddr_is_ipv4(&addr)) {
7234 ast_sockaddr_to_sin(&addr, &addr_tmp);
7235 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
7236 ast_debug_stun(2, "(%p) STUN using IPv6 mapped address %s\n",
7237 instance, ast_sockaddr_stringify(&addr));
7238 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
7239 } else {
7240 ast_debug_stun(2, "(%p) STUN cannot do for non IPv4 address %s\n",
7241 instance, ast_sockaddr_stringify(&addr));
7242 return &ast_null_frame;
7243 }
7244 if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
7245 ast_sockaddr_from_sin(&addr, &addr_tmp);
7246 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
7247 }
7248 return &ast_null_frame;
7249 }
7250
7251 return ast_rtcp_interpret(instance, srtp, read_area, res, &addr);
7252}
@ 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 5107 of file res_rtp_asterisk.c.

5108{
5109 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
5110 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5111 int res;
5112 int sr = 0;
5113 int packet_len = 0;
5114 int ice;
5115 struct ast_sockaddr remote_address = { { 0, } };
5116 unsigned char *rtcpheader;
5117 unsigned char bdata[AST_UUID_STR_LEN + 128] = ""; /* More than enough */
5118 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5119
5120 if (!rtp || !rtp->rtcp || rtp->rtcp->schedid == -1) {
5121 ao2_ref(instance, -1);
5122 return 0;
5123 }
5124
5125 ao2_lock(instance);
5126 rtcpheader = bdata;
5127 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5128 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5129
5130 if (res == 0 || res == 1) {
5131 goto cleanup;
5132 }
5133
5134 packet_len += res;
5135
5136 if (rtp->bundled) {
5137 ast_rtp_instance_get_remote_address(instance, &remote_address);
5138 } else {
5139 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
5140 }
5141
5142 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
5143 if (res < 0) {
5144 ast_log(LOG_ERROR, "RTCP %s transmission error to %s, rtcp halted %s\n",
5145 sr ? "SR" : "RR",
5146 ast_sockaddr_stringify(&rtp->rtcp->them),
5147 strerror(errno));
5148 res = 0;
5149 } else {
5150 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
5151 }
5152
5153cleanup:
5154 ao2_unlock(instance);
5155
5156 if (!res) {
5157 /*
5158 * Not being rescheduled.
5159 */
5160 rtp->rtcp->schedid = -1;
5161 ao2_ref(instance, -1);
5162 }
5163
5164 return res;
5165}
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 9559 of file res_rtp_asterisk.c.

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

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

◆ ast_rtp_change_source()

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

Definition at line 4644 of file res_rtp_asterisk.c.

4645{
4646 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4647 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 0);
4648 struct ast_srtp *rtcp_srtp = ast_rtp_instance_get_srtp(instance, 1);
4649 unsigned int ssrc = ast_random();
4650
4651 if (rtp->lastts) {
4652 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4654 }
4655
4656 ast_debug_rtp(3, "(%p) RTP changing ssrc from %u to %u due to a source change\n",
4657 instance, rtp->ssrc, ssrc);
4658
4659 if (srtp) {
4660 ast_debug_rtp(3, "(%p) RTP changing ssrc for SRTP from %u to %u\n",
4661 instance, rtp->ssrc, ssrc);
4662 res_srtp->change_source(srtp, rtp->ssrc, ssrc);
4663 if (rtcp_srtp != srtp) {
4664 res_srtp->change_source(rtcp_srtp, rtp->ssrc, ssrc);
4665 }
4666 }
4667
4668 rtp->ssrc = ssrc;
4669
4670 /* Since the source is changing, we don't know what sequence number to expect next */
4671 rtp->expectedrxseqno = -1;
4672
4673 return;
4674}
#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 4287 of file res_rtp_asterisk.c.

4288{
4289 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4290
4291 if (rtp->bundled) {
4292 struct ast_rtp *bundled_rtp;
4293
4294 /* We can't hold our instance lock while removing ourselves from the parent */
4295 ao2_unlock(instance);
4296
4297 ao2_lock(rtp->bundled);
4298 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
4300 ao2_unlock(rtp->bundled);
4301
4302 ao2_lock(instance);
4303 ao2_ref(rtp->bundled, -1);
4304 }
4305
4306 rtp_deallocate_transport(instance, rtp);
4307
4308 /* Destroy the smoother that was smoothing out audio if present */
4309 if (rtp->smoother) {
4311 }
4312
4313 /* Destroy RTCP if it was being used */
4314 if (rtp->rtcp) {
4315 /*
4316 * It is not possible for there to be an active RTCP scheduler
4317 * entry at this point since it holds a reference to the
4318 * RTP instance while it's active.
4319 */
4321 ast_free(rtp->rtcp);
4322 }
4323
4324 /* Destroy RED if it was being used */
4325 if (rtp->red) {
4326 ao2_unlock(instance);
4327 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
4328 ao2_lock(instance);
4329 ast_free(rtp->red);
4330 rtp->red = NULL;
4331 }
4332
4333 /* Destroy the send buffer if it was being used */
4334 if (rtp->send_buffer) {
4336 }
4337
4338 /* Destroy the recv buffer if it was being used */
4339 if (rtp->recv_buffer) {
4341 }
4342
4344
4350
4351 /* Finally destroy ourselves */
4352 rtp->owner = NULL;
4353 ast_free(rtp);
4354
4355 return 0;
4356}
#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::@510 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 4374 of file res_rtp_asterisk.c.

4375{
4376 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4377 struct ast_sockaddr remote_address = { {0,} };
4378 int hdrlen = 12, res = 0, i = 0, payload = -1, sample_rate = -1;
4379 char data[256];
4380 unsigned int *rtpheader = (unsigned int*)data;
4381 RAII_VAR(struct ast_format *, payload_format, NULL, ao2_cleanup);
4382
4383 ast_rtp_instance_get_remote_address(instance, &remote_address);
4384
4385 /* If we have no remote address information bail out now */
4386 if (ast_sockaddr_isnull(&remote_address)) {
4387 return -1;
4388 }
4389
4390 /* Convert given digit into what we want to transmit */
4391 if ((digit <= '9') && (digit >= '0')) {
4392 digit -= '0';
4393 } else if (digit == '*') {
4394 digit = 10;
4395 } else if (digit == '#') {
4396 digit = 11;
4397 } else if ((digit >= 'A') && (digit <= 'D')) {
4398 digit = digit - 'A' + 12;
4399 } else if ((digit >= 'a') && (digit <= 'd')) {
4400 digit = digit - 'a' + 12;
4401 } else {
4402 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4403 return -1;
4404 }
4405
4406
4407 /* g722 is a 16K codec that masquerades as an 8K codec within RTP. ast_rtp_get_rate was written specifically to
4408 handle this. If we use the actual sample rate of g722 in this scenario and there is a 16K telephone-event on
4409 offer, we will end up using that instead of the 8K rate telephone-event that is expected with g722. */
4410 if (rtp->lasttxformat == ast_format_none) {
4411 /* No audio frames have been written yet so we have to lookup both the preferred payload type and bitrate. */
4413 if (payload_format) {
4414 /* If we have a preferred type, use that. Otherwise default to 8K. */
4415 sample_rate = ast_rtp_get_rate(payload_format);
4416 }
4417 } else {
4418 sample_rate = ast_rtp_get_rate(rtp->lasttxformat);
4419 }
4420
4421 if (sample_rate != -1) {
4423 }
4424
4425 if (payload == -1 ||
4428 /* Fall back to the preferred DTMF payload type and sample rate as either we couldn't find an audio codec to try and match
4429 sample rates with or we could, but a telephone-event matching that audio codec's sample rate was not included in the
4430 sdp negotiated by the far end. */
4433 }
4434
4435 /* The sdp negotiation has not yeilded a usable RFC 2833/4733 format. Try a default-rate one as a last resort. */
4436 if (payload == -1 || sample_rate == -1) {
4437 sample_rate = DEFAULT_DTMF_SAMPLE_RATE_MS;
4439 }
4440 /* Even trying a default payload has failed. We are trying to send a digit outside of what was negotiated for. */
4441 if (payload == -1) {
4442 return -1;
4443 }
4444
4445 ast_test_suite_event_notify("DTMF_BEGIN", "Digit: %d\r\nPayload: %d\r\nRate: %d\r\n", digit, payload, sample_rate);
4446 ast_debug(1, "Sending digit '%d' at rate %d with payload %d\n", digit, sample_rate, payload);
4447
4448 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4449 rtp->send_duration = 160;
4450 rtp->dtmf_samplerate_ms = (sample_rate / 1000);
4451 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4452 rtp->lastdigitts = rtp->lastts + rtp->send_duration;
4453
4454 /* Create the actual packet that we will be sending */
4455 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
4456 rtpheader[1] = htonl(rtp->lastdigitts);
4457 rtpheader[2] = htonl(rtp->ssrc);
4458
4459 /* Actually send the packet */
4460 for (i = 0; i < 2; i++) {
4461 int ice;
4462
4463 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4464 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4465 if (res < 0) {
4466 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4467 ast_sockaddr_stringify(&remote_address),
4468 strerror(errno));
4469 }
4470 if (rtp_debug_test_addr(&remote_address)) {
4471 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4472 ast_sockaddr_stringify(&remote_address),
4473 ice ? " (via ICE)" : "",
4474 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4475 }
4476 rtp->seqno++;
4477 rtp->send_duration += 160;
4478 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
4479 }
4480
4481 /* Record that we are in the process of sending a digit and information needed to continue doing so */
4482 rtp->sending_digit = 1;
4483 rtp->send_digit = digit;
4484 rtp->send_payload = payload;
4485
4486 return 0;
4487}
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:755
#define DEFAULT_DTMF_SAMPLE_RATE_MS
Definition rtp_engine.h:110
Definition of a media format.
Definition format.c:43
unsigned short seqno
struct timeval dtmfmute
unsigned int dtmf_samplerate_ms
unsigned int lastdigitts
#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 9342 of file res_rtp_asterisk.c.

9343{
9344 /* If both sides are not using the same method of DTMF transmission
9345 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9346 * --------------------------------------------------
9347 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9348 * |-----------|------------|-----------------------|
9349 * | Inband | False | True |
9350 * | RFC2833 | True | True |
9351 * | SIP INFO | False | False |
9352 * --------------------------------------------------
9353 */
9355 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9356}
@ 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 4490 of file res_rtp_asterisk.c.

4491{
4492 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4493 struct ast_sockaddr remote_address = { {0,} };
4494 int hdrlen = 12, res = 0;
4495 char data[256];
4496 unsigned int *rtpheader = (unsigned int*)data;
4497 int ice;
4498
4499 ast_rtp_instance_get_remote_address(instance, &remote_address);
4500
4501 /* Make sure we know where the other side is so we can send them the packet */
4502 if (ast_sockaddr_isnull(&remote_address)) {
4503 return -1;
4504 }
4505
4506 /* Actually create the packet we will be sending */
4507 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4508 rtpheader[1] = htonl(rtp->lastdigitts);
4509 rtpheader[2] = htonl(rtp->ssrc);
4510 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
4511
4512 /* Boom, send it on out */
4513 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4514 if (res < 0) {
4515 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4516 ast_sockaddr_stringify(&remote_address),
4517 strerror(errno));
4518 }
4519
4520 if (rtp_debug_test_addr(&remote_address)) {
4521 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4522 ast_sockaddr_stringify(&remote_address),
4523 ice ? " (via ICE)" : "",
4524 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4525 }
4526
4527 /* And now we increment some values for the next time we swing by */
4528 rtp->seqno++;
4529 rtp->send_duration += 160;
4530 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4531
4532 return 0;
4533}

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

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

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

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

4368{
4369 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4370 return rtp->dtmfmode;
4371}
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 4359 of file res_rtp_asterisk.c.

4360{
4361 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4362 rtp->dtmfmode = dtmf_mode;
4363 return 0;
4364}

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

9548{
9549 switch (extension) {
9552 return 1;
9553 default:
9554 return 0;
9555 }
9556}
@ 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 9096 of file res_rtp_asterisk.c.

9097{
9098 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9099
9100 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9101}

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

9495{
9496 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9497
9498 return rtp->cname;
9499}

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

9487{
9488 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9489
9490 return rtp->ssrc;
9491}

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

9278{
9279 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9280
9281 if (!rtp->rtcp) {
9282 return -1;
9283 }
9284
9289
9301
9313
9320
9332
9333
9337
9338 return 0;
9339}
#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 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_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 7806 of file res_rtp_asterisk.c.

7809{
7810 unsigned int *rtpheader = (unsigned int*)(read_area);
7811 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7812 struct ast_rtp_instance *instance1;
7813 int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc;
7814 unsigned int timestamp;
7815 RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
7816 struct frame_list frames;
7817
7818 /* If this payload is encrypted then decrypt it using the given SRTP instance */
7819 if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
7820 srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
7821 return &ast_null_frame;
7822 }
7823
7824 /* If we are currently sending DTMF to the remote party send a continuation packet */
7825 if (rtp->sending_digit) {
7826 ast_rtp_dtmf_continuation(instance);
7827 }
7828
7829 /* Pull out the various other fields we will need */
7830 ssrc = ntohl(rtpheader[2]);
7831 seqno = ntohl(rtpheader[0]);
7832 payloadtype = (seqno & 0x7f0000) >> 16;
7833 padding = seqno & (1 << 29);
7834 mark = seqno & (1 << 23);
7835 ext = seqno & (1 << 28);
7836 cc = (seqno & 0xF000000) >> 24;
7837 seqno &= 0xffff;
7838 timestamp = ntohl(rtpheader[1]);
7839
7841
7842 /* Remove any padding bytes that may be present */
7843 if (padding) {
7844 res -= read_area[res - 1];
7845 }
7846
7847 /* Skip over any CSRC fields */
7848 if (cc) {
7849 hdrlen += cc * 4;
7850 }
7851
7852 /* Look for any RTP extensions, currently we do not support any */
7853 if (ext) {
7854 int extensions_size = (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
7855 unsigned int profile;
7856 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
7857
7858 if (profile == 0xbede) {
7859 /* We skip over the first 4 bytes as they are just for the one byte extension header */
7860 rtp_instance_parse_extmap_extensions(instance, rtp, read_area + hdrlen + 4, extensions_size);
7861 } else if (DEBUG_ATLEAST(1)) {
7862 if (profile == 0x505a) {
7863 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
7864 } else {
7865 /* SDP negotiated RTP extensions can not currently be output in logging */
7866 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
7867 }
7868 }
7869
7870 hdrlen += extensions_size;
7871 hdrlen += 4;
7872 }
7873
7874 /* Make sure after we potentially mucked with the header length that it is once again valid */
7875 if (res < hdrlen) {
7876 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
7878 }
7879
7880 /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
7881 if (!bundled) {
7882 /* Force a marker bit and change SSRC if the SSRC changes */
7883 if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
7884 struct ast_frame *f, srcupdate = {
7887 };
7888
7889 if (!mark) {
7891 ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance);
7892 }
7893 mark = 1;
7894 }
7895
7896 f = ast_frisolate(&srcupdate);
7898
7899 rtp->seedrxseqno = 0;
7900 rtp->rxcount = 0;
7901 rtp->rxoctetcount = 0;
7902 rtp->cycles = 0;
7903 prev_seqno = 0;
7904 rtp->last_seqno = 0;
7905 rtp->last_end_timestamp.ts = 0;
7906 rtp->last_end_timestamp.is_set = 0;
7907 if (rtp->rtcp) {
7908 rtp->rtcp->expected_prior = 0;
7909 rtp->rtcp->received_prior = 0;
7910 }
7911 }
7912
7913 rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
7914 rtp->themssrc_valid = 1;
7915 }
7916
7917 rtp->rxcount++;
7918 rtp->rxoctetcount += (res - hdrlen);
7919 if (rtp->rxcount == 1) {
7920 rtp->seedrxseqno = seqno;
7921 }
7922
7923 /* Do not schedule RR if RTCP isn't run */
7924 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 0) {
7925 /* Schedule transmission of Receiver Report */
7926 ao2_ref(instance, +1);
7928 if (rtp->rtcp->schedid < 0) {
7929 ao2_ref(instance, -1);
7930 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
7931 }
7932 }
7933 if ((int)prev_seqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
7934 rtp->cycles += RTP_SEQ_MOD;
7935
7936 /* If we are directly bridged to another instance send the audio directly out,
7937 * but only after updating core information about the received traffic so that
7938 * outgoing RTCP reflects it.
7939 */
7940 instance1 = ast_rtp_instance_get_bridged(instance);
7941 if (instance1
7942 && !bridge_p2p_rtp_write(instance, instance1, rtpheader, res, hdrlen)) {
7943 struct timeval rxtime;
7944 struct ast_frame *f;
7945
7946 /* Update statistics for jitter so they are correct in RTCP */
7947 calc_rxstamp_and_jitter(&rxtime, rtp, timestamp, mark);
7948
7949
7950 /* When doing P2P we don't need to raise any frames about SSRC change to the core */
7951 while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list)) != NULL) {
7952 ast_frfree(f);
7953 }
7954
7955 return &ast_null_frame;
7956 }
7957
7958 payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
7959 if (!payload) {
7960 /* Unknown payload type. */
7962 }
7963
7964 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
7965 if (!payload->asterisk_format) {
7966 struct ast_frame *f = NULL;
7967 if (payload->rtp_code == AST_RTP_DTMF) {
7968 /* process_dtmf_rfc2833 may need to return multiple frames. We do this
7969 * by passing the pointer to the frame list to it so that the method
7970 * can append frames to the list as needed.
7971 */
7972 process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames);
7973 } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
7974 f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
7975 } else if (payload->rtp_code == AST_RTP_CN) {
7976 f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
7977 } else {
7978 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
7979 payloadtype,
7980 ast_sockaddr_stringify(remote_address));
7981 }
7982
7983 if (f) {
7985 }
7986 /* Even if no frame was returned by one of the above methods,
7987 * we may have a frame to return in our frame list
7988 */
7990 }
7991
7992 ao2_replace(rtp->lastrxformat, payload->format);
7993 ao2_replace(rtp->f.subclass.format, payload->format);
7994 switch (ast_format_get_type(rtp->f.subclass.format)) {
7997 break;
8000 break;
8002 rtp->f.frametype = AST_FRAME_TEXT;
8003 break;
8005 /* Fall through */
8006 default:
8007 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8009 return &ast_null_frame;
8010 }
8011
8012 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
8013 rtp->dtmf_timeout = 0;
8014
8015 if (rtp->resp) {
8016 struct ast_frame *f;
8017 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
8019 rtp->resp = 0;
8020 rtp->dtmf_timeout = rtp->dtmf_duration = 0;
8022 return AST_LIST_FIRST(&frames);
8023 }
8024 }
8025
8026 rtp->f.src = "RTP";
8027 rtp->f.mallocd = 0;
8028 rtp->f.datalen = res - hdrlen;
8029 rtp->f.data.ptr = read_area + hdrlen;
8030 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
8032 rtp->f.seqno = seqno;
8033 rtp->f.stream_num = rtp->stream_num;
8034
8036 && ((int)seqno - (prev_seqno + 1) > 0)
8037 && ((int)seqno - (prev_seqno + 1) < 10)) {
8038 unsigned char *data = rtp->f.data.ptr;
8039
8040 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
8041 rtp->f.datalen +=3;
8042 *data++ = 0xEF;
8043 *data++ = 0xBF;
8044 *data = 0xBD;
8045 }
8046
8048 unsigned char *data = rtp->f.data.ptr;
8049 unsigned char *header_end;
8050 int num_generations;
8051 int header_length;
8052 int len;
8053 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
8054 int x;
8055
8057 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
8058 if (header_end == NULL) {
8060 }
8061 header_end++;
8062
8063 header_length = header_end - data;
8064 num_generations = header_length / 4;
8065 len = header_length;
8066
8067 if (!diff) {
8068 for (x = 0; x < num_generations; x++)
8069 len += data[x * 4 + 3];
8070
8071 if (!(rtp->f.datalen - len))
8073
8074 rtp->f.data.ptr += len;
8075 rtp->f.datalen -= len;
8076 } else if (diff > num_generations && diff < 10) {
8077 len -= 3;
8078 rtp->f.data.ptr += len;
8079 rtp->f.datalen -= len;
8080
8081 data = rtp->f.data.ptr;
8082 *data++ = 0xEF;
8083 *data++ = 0xBF;
8084 *data = 0xBD;
8085 } else {
8086 for ( x = 0; x < num_generations - diff; x++)
8087 len += data[x * 4 + 3];
8088
8089 rtp->f.data.ptr += len;
8090 rtp->f.datalen -= len;
8091 }
8092 }
8093
8095 rtp->f.samples = ast_codec_samples_count(&rtp->f);
8097 ast_frame_byteswap_be(&rtp->f);
8098 }
8099 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8100 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
8102 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8103 rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
8105 /* Video -- samples is # of samples vs. 90000 */
8106 if (!rtp->lastividtimestamp)
8107 rtp->lastividtimestamp = timestamp;
8108 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8110 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8111 rtp->f.samples = timestamp - rtp->lastividtimestamp;
8112 rtp->lastividtimestamp = timestamp;
8113 rtp->f.delivery.tv_sec = 0;
8114 rtp->f.delivery.tv_usec = 0;
8115 /* Pass the RTP marker bit as bit */
8116 rtp->f.subclass.frame_ending = mark ? 1 : 0;
8118 /* TEXT -- samples is # of samples vs. 1000 */
8119 if (!rtp->lastitexttimestamp)
8120 rtp->lastitexttimestamp = timestamp;
8121 rtp->f.samples = timestamp - rtp->lastitexttimestamp;
8122 rtp->lastitexttimestamp = timestamp;
8123 rtp->f.delivery.tv_sec = 0;
8124 rtp->f.delivery.tv_usec = 0;
8125 } else {
8126 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8128 return &ast_null_frame;
8129 }
8130
8132 return AST_LIST_FIRST(&frames);
8133}
#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)
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
@ AST_FRFLAG_HAS_SEQUENCE_NUMBER
@ AST_FRFLAG_HAS_TIMING_INFO
@ 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 9249 of file res_rtp_asterisk.c.

9250{
9251 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
9252
9253 ao2_lock(instance0);
9255 if (rtp->smoother) {
9257 rtp->smoother = NULL;
9258 }
9259
9260 /* We must use a new SSRC when local bridge ends */
9261 if (!instance1) {
9262 rtp->ssrc = rtp->ssrc_orig;
9263 rtp->ssrc_orig = 0;
9264 rtp->ssrc_saved = 0;
9265 } else if (!rtp->ssrc_saved) {
9266 /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
9267 rtp->ssrc_orig = rtp->ssrc;
9268 rtp->ssrc_saved = 1;
9269 }
9270
9271 ao2_unlock(instance0);
9272
9273 return 0;
9274}
#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 4231 of file res_rtp_asterisk.c.

4234{
4235 struct ast_rtp *rtp = NULL;
4236
4237 /* Create a new RTP structure to hold all of our data */
4238 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
4239 return -1;
4240 }
4241 rtp->owner = instance;
4242 /* Set default parameters on the newly created RTP structure */
4243 rtp->ssrc = ast_random();
4244 ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname));
4245 rtp->seqno = ast_random() & 0xffff;
4246 rtp->expectedrxseqno = -1;
4247 rtp->expectedseqno = -1;
4248 rtp->rxstart = -1;
4249 rtp->sched = sched;
4250 ast_sockaddr_copy(&rtp->bind_address, addr);
4251 /* Transport creation operations can grab the RTP data from the instance, so set it */
4252 ast_rtp_instance_set_data(instance, rtp);
4253
4254 if (rtp_allocate_transport(instance, rtp)) {
4255 return -1;
4256 }
4257
4258 if (AST_VECTOR_INIT(&rtp->ssrc_mapping, 1)) {
4259 return -1;
4260 }
4261
4263 return -1;
4264 }
4265 rtp->transport_wide_cc.schedid = -1;
4266
4270 rtp->stream_num = -1;
4271
4272 return 0;
4273}
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition rtp_engine.c:586
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 8912 of file res_rtp_asterisk.c.

8913{
8914 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8915
8916 if (property == AST_RTP_PROPERTY_RTCP) {
8917 if (value) {
8918 struct ast_sockaddr local_addr;
8919
8920 if (rtp->rtcp && rtp->rtcp->type == value) {
8921 ast_debug_rtcp(1, "(%p) RTCP ignoring duplicate property\n", instance);
8922 return;
8923 }
8924
8925 if (!rtp->rtcp) {
8926 rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
8927 if (!rtp->rtcp) {
8928 return;
8929 }
8930 rtp->rtcp->s = -1;
8931#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8932 rtp->rtcp->dtls.timeout_timer = -1;
8933#endif
8934 rtp->rtcp->schedid = -1;
8935 }
8936
8937 rtp->rtcp->type = value;
8938
8939 /* Grab the IP address and port we are going to use */
8940 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
8943 ast_sockaddr_port(&rtp->rtcp->us) + 1);
8944 }
8945
8946 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
8947 if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
8948 ast_sockaddr_set_port(&local_addr, ast_sockaddr_port(&rtp->rtcp->us));
8949 } else {
8950 /* Failed to get local address reset to use default. */
8951 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
8952 }
8953
8956 if (!rtp->rtcp->local_addr_str) {
8957 ast_free(rtp->rtcp);
8958 rtp->rtcp = NULL;
8959 return;
8960 }
8961
8963 /* We're either setting up RTCP from scratch or
8964 * switching from MUX. Either way, we won't have
8965 * a socket set up, and we need to set it up
8966 */
8967 if ((rtp->rtcp->s = create_new_socket("RTCP", &rtp->rtcp->us)) < 0) {
8968 ast_debug_rtcp(1, "(%p) RTCP failed to create a new socket\n", instance);
8970 ast_free(rtp->rtcp);
8971 rtp->rtcp = NULL;
8972 return;
8973 }
8974
8975 /* 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 */
8976 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
8977 ast_debug_rtcp(1, "(%p) RTCP failed to setup RTP instance\n", instance);
8978 close(rtp->rtcp->s);
8980 ast_free(rtp->rtcp);
8981 rtp->rtcp = NULL;
8982 return;
8983 }
8984#ifdef HAVE_PJPROJECT
8985 if (rtp->ice) {
8986 rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
8987 }
8988#endif
8989#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8990 dtls_setup_rtcp(instance);
8991#endif
8992 } else {
8993 struct ast_sockaddr addr;
8994 /* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
8995 * then close the socket we previously created.
8996 *
8997 * It may seem as though there is a possible race condition here where we might try
8998 * to close the RTCP socket while it is being used to send data. However, this is not
8999 * a problem in practice since setting and adjusting of RTCP properties happens prior
9000 * to activating RTP. It is not until RTP is activated that timers start for RTCP
9001 * transmission
9002 */
9003 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9004 close(rtp->rtcp->s);
9005 }
9006 rtp->rtcp->s = rtp->s;
9007 ast_rtp_instance_get_remote_address(instance, &addr);
9008 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
9009#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9010 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9011 SSL_free(rtp->rtcp->dtls.ssl);
9012 }
9013 rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
9014#endif
9015 }
9016
9017 ast_debug_rtcp(1, "(%s) RTCP setup on RTP instance\n",
9019 } else {
9020 if (rtp->rtcp) {
9021 if (rtp->rtcp->schedid > -1) {
9022 ao2_unlock(instance);
9023 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9024 /* Successfully cancelled scheduler entry. */
9025 ao2_ref(instance, -1);
9026 } else {
9027 /* Unable to cancel scheduler entry */
9028 ast_debug_rtcp(1, "(%p) RTCP failed to tear down RTCP\n", instance);
9029 ao2_lock(instance);
9030 return;
9031 }
9032 ao2_lock(instance);
9033 rtp->rtcp->schedid = -1;
9034 }
9035 if (rtp->transport_wide_cc.schedid > -1) {
9036 ao2_unlock(instance);
9037 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9038 ao2_ref(instance, -1);
9039 } else {
9040 ast_debug_rtcp(1, "(%p) RTCP failed to tear down transport-cc feedback\n", instance);
9041 ao2_lock(instance);
9042 return;
9043 }
9044 ao2_lock(instance);
9045 rtp->transport_wide_cc.schedid = -1;
9046 }
9047 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9048 close(rtp->rtcp->s);
9049 }
9050#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9051 ao2_unlock(instance);
9052 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9053 ao2_lock(instance);
9054
9055 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9056 SSL_free(rtp->rtcp->dtls.ssl);
9057 }
9058#endif
9060 ast_free(rtp->rtcp);
9061 rtp->rtcp = NULL;
9062 ast_debug_rtcp(1, "(%s) RTCP torn down on RTP instance\n",
9064 }
9065 }
9066 } else if (property == AST_RTP_PROPERTY_ASYMMETRIC_CODEC) {
9067 rtp->asymmetric_codec = value;
9068 } else if (property == AST_RTP_PROPERTY_RETRANS_SEND) {
9069 if (value) {
9070 if (!rtp->send_buffer) {
9072 }
9073 } else {
9074 if (rtp->send_buffer) {
9076 rtp->send_buffer = NULL;
9077 }
9078 }
9079 } else if (property == AST_RTP_PROPERTY_RETRANS_RECV) {
9080 if (value) {
9081 if (!rtp->recv_buffer) {
9084 }
9085 } else {
9086 if (rtp->recv_buffer) {
9088 rtp->recv_buffer = NULL;
9090 }
9091 }
9092 }
9093}
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:671
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition rtp_engine.h:130
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition rtp_engine.h:132
@ AST_RTP_PROPERTY_RTCP
Definition rtp_engine.h:126
@ AST_RTP_PROPERTY_ASYMMETRIC_CODEC
Definition rtp_engine.h:128
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition sched.c:614
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 9425 of file res_rtp_asterisk.c.

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

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

◆ ast_rtp_read()

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

Definition at line 8245 of file res_rtp_asterisk.c.

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

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

◆ ast_rtp_remote_address_set()

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

Definition at line 9104 of file res_rtp_asterisk.c.

9105{
9106 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9107 struct ast_sockaddr local;
9108 int index;
9109
9110 ast_rtp_instance_get_local_address(instance, &local);
9111 if (!ast_sockaddr_isnull(addr)) {
9112 /* Update the local RTP address with what is being used */
9113 if (ast_ouraddrfor(addr, &local)) {
9114 /* Failed to update our address so reuse old local address */
9115 ast_rtp_instance_get_local_address(instance, &local);
9116 } else {
9117 ast_rtp_instance_set_local_address(instance, &local);
9118 }
9119 }
9120
9121 if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
9122 ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
9123 ast_sockaddr_copy(&rtp->rtcp->them, addr);
9124
9127
9128 /* Update the local RTCP address with what is being used */
9129 ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
9130 }
9131 ast_sockaddr_copy(&rtp->rtcp->us, &local);
9132
9135 }
9136
9137 /* Update any bundled RTP instances */
9138 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
9139 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
9140
9142 }
9143
9144 /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
9145 rtp->last_seqno = 0;
9146 rtp->last_end_timestamp.ts = 0;
9147 rtp->last_end_timestamp.is_set = 0;
9148
9150 && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
9151 /* We only need to learn a new strict source address if we've been told the source is
9152 * changing to something different.
9153 */
9154 ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
9155 rtp, ast_sockaddr_stringify(addr));
9156 rtp_learning_start(rtp);
9157 }
9158}
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition acl.c:1021
static int strictrtp
static void rtp_learning_start(struct ast_rtp *rtp)
Start the strictrtp learning mode.
int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address that we are expecting to receive RTP on.
Definition rtp_engine.c:616

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

◆ ast_rtp_rtcp_handle_nack()

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

Definition at line 6553 of file res_rtp_asterisk.c.

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

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

Referenced by ast_rtcp_interpret().

◆ ast_rtp_sendcng()

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

generate comfort noice (CNG)

Precondition
instance is locked

Definition at line 9437 of file res_rtp_asterisk.c.

9438{
9439 unsigned int *rtpheader;
9440 int hdrlen = 12;
9441 int res, payload = 0;
9442 char data[256];
9443 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9444 struct ast_sockaddr remote_address = { {0,} };
9445 int ice;
9446
9447 ast_rtp_instance_get_remote_address(instance, &remote_address);
9448
9449 if (ast_sockaddr_isnull(&remote_address)) {
9450 return -1;
9451 }
9452
9454
9455 level = 127 - (level & 0x7f);
9456
9457 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
9458
9459 /* Get a pointer to the header */
9460 rtpheader = (unsigned int *)data;
9461 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
9462 rtpheader[1] = htonl(rtp->lastts);
9463 rtpheader[2] = htonl(rtp->ssrc);
9464 data[12] = level;
9465
9466 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);
9467
9468 if (res < 0) {
9469 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
9470 return res;
9471 }
9472
9473 if (rtp_debug_test_addr(&remote_address)) {
9474 ast_verbose("Sent Comfort Noise RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
9475 ast_sockaddr_stringify(&remote_address),
9476 ice ? " (via ICE)" : "",
9477 AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
9478 }
9479
9480 rtp->seqno++;
9481
9482 return res;
9483}

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

9503{
9504 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9505
9506 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
9507 return;
9508 }
9509
9510 rtp->themssrc = ssrc;
9511 rtp->themssrc_valid = 1;
9512
9513 /* If this is bundled we need to update the SSRC mapping */
9514 if (rtp->bundled) {
9515 struct ast_rtp *bundled_rtp;
9516 int index;
9517
9518 ao2_unlock(instance);
9519
9520 /* The child lock can't be held while accessing the parent */
9521 ao2_lock(rtp->bundled);
9522 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
9523
9524 for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
9525 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
9526
9527 if (mapping->instance == instance) {
9528 mapping->ssrc = ssrc;
9529 mapping->ssrc_valid = 1;
9530 break;
9531 }
9532 }
9533
9534 ao2_unlock(rtp->bundled);
9535
9537 }
9538}

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

9541{
9542 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9543
9544 rtp->stream_num = stream_num;
9545}

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

9375{
9376 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9377 struct ast_sockaddr addr = { {0,} };
9378
9379#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9380 ao2_unlock(instance);
9381 AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
9382
9383 dtls_srtp_stop_timeout_timer(instance, rtp, 0);
9384 if (rtp->rtcp) {
9385 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9386 }
9387 ao2_lock(instance);
9388#endif
9389 ast_debug_rtp(1, "(%s) RTP Stop\n",
9391
9392 if (rtp->rtcp && rtp->rtcp->schedid > -1) {
9393 ao2_unlock(instance);
9394 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9395 /* successfully cancelled scheduler entry. */
9396 ao2_ref(instance, -1);
9397 }
9398 ao2_lock(instance);
9399 rtp->rtcp->schedid = -1;
9400 }
9401
9402 if (rtp->transport_wide_cc.schedid > -1) {
9403 ao2_unlock(instance);
9404 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9405 ao2_ref(instance, -1);
9406 }
9407 ao2_lock(instance);
9408 rtp->transport_wide_cc.schedid = -1;
9409 }
9410
9411 if (rtp->red) {
9412 ao2_unlock(instance);
9413 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
9414 ao2_lock(instance);
9415 ast_free(rtp->red);
9416 rtp->red = NULL;
9417 }
9418
9419 ast_rtp_instance_set_remote_address(instance, &addr);
9420
9422}
#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 9359 of file res_rtp_asterisk.c.

9360{
9361 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9362 struct sockaddr_in suggestion_tmp;
9363
9364 /*
9365 * The instance should not be locked because we can block
9366 * waiting for a STUN respone.
9367 */
9368 ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
9369 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
9370 ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
9371}
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 4632 of file res_rtp_asterisk.c.

4633{
4634 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4635
4636 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4638 ast_debug_rtp(3, "(%p) RTP setting the marker bit due to a source update\n", instance);
4639
4640 return;
4641}

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

5580{
5581 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5582 struct ast_sockaddr remote_address = { {0,} };
5583 struct ast_format *format;
5584 int codec;
5585
5586 ast_rtp_instance_get_remote_address(instance, &remote_address);
5587
5588 /* If we don't actually know the remote address don't even bother doing anything */
5589 if (ast_sockaddr_isnull(&remote_address)) {
5590 ast_debug_rtp(1, "(%p) RTP no remote address on instance, so dropping frame\n", instance);
5591 return 0;
5592 }
5593
5594 /* VP8: is this a request to send a RTCP FIR? */
5596 rtp_write_rtcp_fir(instance, rtp, &remote_address);
5597 return 0;
5598 } else if (frame->frametype == AST_FRAME_RTCP) {
5599 if (frame->subclass.integer == AST_RTP_RTCP_PSFB) {
5600 rtp_write_rtcp_psfb(instance, rtp, frame, &remote_address);
5601 }
5602 return 0;
5603 }
5604
5605 /* If there is no data length we can't very well send the packet */
5606 if (!frame->datalen) {
5607 ast_debug_rtp(1, "(%p) RTP received frame with no data for instance, so dropping frame\n", instance);
5608 return 0;
5609 }
5610
5611 /* If the packet is not one our RTP stack supports bail out */
5612 if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
5613 ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
5614 return -1;
5615 }
5616
5617 if (rtp->red) {
5618 /* return 0; */
5619 /* no primary data or generations to send */
5620 if ((frame = red_t140_to_red(rtp->red)) == NULL)
5621 return 0;
5622 }
5623
5624 /* Grab the subclass and look up the payload we are going to use */
5626 1, frame->subclass.format, 0);
5627 if (codec < 0) {
5628 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n",
5630 return -1;
5631 }
5632
5633 /* Note that we do not increase the ref count here as this pointer
5634 * will not be held by any thing explicitly. The format variable is
5635 * merely a convenience reference to frame->subclass.format */
5636 format = frame->subclass.format;
5638 /* Oh dear, if the format changed we will have to set up a new smoother */
5639 ast_debug_rtp(1, "(%s) RTP ooh, format changed from %s to %s\n",
5643 ao2_replace(rtp->lasttxformat, format);
5644 if (rtp->smoother) {
5646 rtp->smoother = NULL;
5647 }
5648 }
5649
5650 /* If no smoother is present see if we have to set one up */
5651 if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
5652 unsigned int smoother_flags = ast_format_get_smoother_flags(format);
5653 unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
5654
5655 if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
5656 framing_ms = ast_format_get_default_ms(format);
5657 }
5658
5659 if (framing_ms) {
5661 if (!rtp->smoother) {
5662 ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len: %u\n",
5663 ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
5664 return -1;
5665 }
5666 ast_smoother_set_flags(rtp->smoother, smoother_flags);
5667 }
5668 }
5669
5670 /* Feed audio frames into the actual function that will create a frame and send it */
5671 if (rtp->smoother) {
5672 struct ast_frame *f;
5673
5675 ast_smoother_feed_be(rtp->smoother, frame);
5676 } else {
5677 ast_smoother_feed(rtp->smoother, frame);
5678 }
5679
5680 while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
5681 rtp_raw_write(instance, f, codec);
5682 }
5683 } else {
5684 int hdrlen = 12;
5685 struct ast_frame *f = NULL;
5686
5687 if (frame->offset < hdrlen) {
5688 f = ast_frdup(frame);
5689 } else {
5690 f = frame;
5691 }
5692 if (f->data.ptr) {
5693 rtp_raw_write(instance, f, codec);
5694 }
5695 if (f != frame) {
5696 ast_frfree(f);
5697 }
5698
5699 }
5700
5701 return 0;
5702}
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 7255 of file res_rtp_asterisk.c.

7257{
7258 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7259 struct ast_rtp *bridged;
7260 int res = 0, payload = 0, bridged_payload = 0, mark;
7261 RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
7262 int reconstruct = ntohl(rtpheader[0]);
7263 struct ast_sockaddr remote_address = { {0,} };
7264 int ice;
7265 unsigned int timestamp = ntohl(rtpheader[1]);
7266
7267 /* Get fields from packet */
7268 payload = (reconstruct & 0x7f0000) >> 16;
7269 mark = (reconstruct & 0x800000) >> 23;
7270
7271 /* Check what the payload value should be */
7272 payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
7273 if (!payload_type) {
7274 return -1;
7275 }
7276
7277 /* Otherwise adjust bridged payload to match */
7279 payload_type->asterisk_format, payload_type->format, payload_type->rtp_code, payload_type->sample_rate);
7280
7281 /* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
7282 if (bridged_payload < 0) {
7283 return -1;
7284 }
7285
7286 /* 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 */
7287 if (ast_rtp_codecs_find_payload_code(ast_rtp_instance_get_codecs(instance1), bridged_payload) == -1) {
7288 ast_debug_rtp(1, "(%p, %p) RTP unsupported payload type received\n", instance, instance1);
7289 return -1;
7290 }
7291
7292 /*
7293 * Even if we are no longer in dtmf, we could still be receiving
7294 * re-transmissions of the last dtmf end still. Feed those to the
7295 * core so they can be filtered accordingly.
7296 */
7297 if (rtp->last_end_timestamp.is_set && rtp->last_end_timestamp.ts == timestamp) {
7298 ast_debug_rtp(1, "(%p, %p) RTP feeding packet with duplicate timestamp to core\n", instance, instance1);
7299 return -1;
7300 }
7301
7302 if (payload_type->asterisk_format) {
7303 ao2_replace(rtp->lastrxformat, payload_type->format);
7304 }
7305
7306 /*
7307 * We have now determined that we need to send the RTP packet
7308 * out the bridged instance to do local bridging so we must unlock
7309 * the receiving instance to prevent deadlock with the bridged
7310 * instance.
7311 *
7312 * Technically we should grab a ref to instance1 so it won't go
7313 * away on us. However, we should be safe because the bridged
7314 * instance won't change without both channels involved being
7315 * locked and we currently have the channel lock for the receiving
7316 * instance.
7317 */
7318 ao2_unlock(instance);
7319 ao2_lock(instance1);
7320
7321 /*
7322 * Get the peer rtp pointer now to emphasize that using it
7323 * must happen while instance1 is locked.
7324 */
7325 bridged = ast_rtp_instance_get_data(instance1);
7326
7327
7328 /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
7329 if (bridged->sending_digit) {
7330 ast_debug_rtp(1, "(%p, %p) RTP Feeding packet to core until DTMF finishes\n", instance, instance1);
7331 ao2_unlock(instance1);
7332 ao2_lock(instance);
7333 return -1;
7334 }
7335
7336 if (payload_type->asterisk_format) {
7337 /*
7338 * If bridged peer has already received rtp, perform the asymmetric codec check
7339 * if that feature has been activated
7340 */
7341 if (!bridged->asymmetric_codec
7342 && bridged->lastrxformat != ast_format_none
7343 && ast_format_cmp(payload_type->format, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
7344 ast_debug_rtp(1, "(%p, %p) RTP asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
7345 instance, instance1, ast_format_get_name(payload_type->format),
7347 ao2_unlock(instance1);
7348 ao2_lock(instance);
7349 return -1;
7350 }
7351
7352 ao2_replace(bridged->lasttxformat, payload_type->format);
7353 }
7354
7355 ast_rtp_instance_get_remote_address(instance1, &remote_address);
7356
7357 if (ast_sockaddr_isnull(&remote_address)) {
7358 ast_debug_rtp(5, "(%p, %p) RTP remote address is null, most likely RTP has been stopped\n",
7359 instance, instance1);
7360 ao2_unlock(instance1);
7361 ao2_lock(instance);
7362 return 0;
7363 }
7364
7365 /* If the marker bit has been explicitly set turn it on */
7366 if (ast_test_flag(bridged, FLAG_NEED_MARKER_BIT)) {
7367 mark = 1;
7369 }
7370
7371 /* Set the marker bit for the first local bridged packet which has the first bridged peer's SSRC. */
7373 mark = 1;
7375 }
7376
7377 /* Reconstruct part of the packet */
7378 reconstruct &= 0xFF80FFFF;
7379 reconstruct |= (bridged_payload << 16);
7380 reconstruct |= (mark << 23);
7381 rtpheader[0] = htonl(reconstruct);
7382
7383 if (mark) {
7384 /* make this rtp instance aware of the new ssrc it is sending */
7385 bridged->ssrc = ntohl(rtpheader[2]);
7386 }
7387
7388 /* Send the packet back out */
7389 res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address, &ice);
7390 if (res < 0) {
7393 "RTP Transmission error of packet to %s: %s\n",
7394 ast_sockaddr_stringify(&remote_address),
7395 strerror(errno));
7399 "RTP NAT: Can't write RTP to private "
7400 "address %s, waiting for other end to "
7401 "send audio...\n",
7402 ast_sockaddr_stringify(&remote_address));
7403 }
7405 }
7406 ao2_unlock(instance1);
7407 ao2_lock(instance);
7408 return 0;
7409 }
7410
7411 if (rtp_debug_test_addr(&remote_address)) {
7412 ast_verbose("Sent RTP P2P packet to %s%s (type %-2.2d, len %-6.6d)\n",
7413 ast_sockaddr_stringify(&remote_address),
7414 ice ? " (via ICE)" : "",
7415 bridged_payload, len - hdrlen);
7416 }
7417
7418 ao2_unlock(instance1);
7419 ao2_lock(instance);
7420 return 0;
7421}
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 3552 of file res_rtp_asterisk.c.

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

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

6332{
6333 double r_value;
6334 double pseudo_mos;
6335 double mes = 0;
6336
6337 /*
6338 * While the media itself might be okay, a significant enough delay could make
6339 * for an unpleasant user experience.
6340 *
6341 * Calculate the effective latency by using the given round trip time, and adding
6342 * jitter scaled according to its standard deviation. The scaling is done in order
6343 * to increase jitter's weight since a higher deviation can result in poorer overall
6344 * quality.
6345 */
6346 double effective_latency = (normdevrtt * 1000)
6347 + ((normdev_rxjitter * 2) * (stdev_rxjitter / 3))
6348 + 10;
6349
6350 /*
6351 * Using the defaults for the standard transmission rating factor ("R" value)
6352 * one arrives at 93.2 (see ITU-T G.107 for more details), so we'll use that
6353 * as the starting value and subtract deficiencies that could affect quality.
6354 *
6355 * Calculate the impact of the effective latency. Influence increases with
6356 * values over 160 as the significant "lag" can degrade user experience.
6357 */
6358 if (effective_latency < 160) {
6359 r_value = 93.2 - (effective_latency / 40);
6360 } else {
6361 r_value = 93.2 - (effective_latency - 120) / 10;
6362 }
6363
6364 /* Next evaluate the impact of lost packets */
6365 r_value = r_value - (normdev_rxlost * 2.0);
6366
6367 /*
6368 * Finally convert the "R" value into a opinion/quality score between 1 (really anything
6369 * below 3 should be considered poor) and 4.5 (the highest achievable for VOIP).
6370 */
6371 if (r_value < 0) {
6372 pseudo_mos = 1.0;
6373 } else if (r_value > 100) {
6374 pseudo_mos = 4.5;
6375 } else {
6376 pseudo_mos = 1 + (0.035 * r_value) + (r_value * (r_value - 60) * (100 - r_value) * 0.000007);
6377 }
6378
6379 /*
6380 * We're going to rescale the 0.0->5.0 pseudo_mos to the 0.0->100.0 MES.
6381 * For those ranges, we could actually just multiply the pseudo_mos
6382 * by 20 but we may want to change the scale later.
6383 */
6384 mes = RESCALE(pseudo_mos, 0.0, 5.0, 0.0, 100.0);
6385
6386 return mes;
6387}
#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 5704 of file res_rtp_asterisk.c.

5707{
5708 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
5709
5710 double jitter = 0.0;
5711 double prev_jitter = 0.0;
5712 struct timeval now;
5713 struct timeval tmp;
5714 double rxnow;
5715 double arrival_sec;
5716 unsigned int arrival;
5717 int transit;
5718 int d;
5719
5720 gettimeofday(&now,NULL);
5721
5722 if (rtp->rxcount == 1 || mark) {
5723 rtp->rxstart = ast_tv2double(&now);
5724 rtp->remote_seed_rx_rtp_ts = rx_rtp_ts;
5725
5726 /*
5727 * "tv" is placed in the received frame's
5728 * "delivered" field and when this frame is
5729 * sent out again on the other side, it's
5730 * used to calculate the timestamp on the
5731 * outgoing RTP packets.
5732 *
5733 * NOTE: We need to do integer math here
5734 * because double math rounding issues can
5735 * generate incorrect timestamps.
5736 */
5737 rtp->rxcore = now;
5738 tmp = ast_samp2tv(rx_rtp_ts, rate);
5739 rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
5740 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
5741 *tv = ast_tvadd(rtp->rxcore, tmp);
5742
5743 ast_debug_rtcp(3, "%s: "
5744 "Seed ts: %u current time: %f\n",
5746 , rx_rtp_ts
5747 , rtp->rxstart
5748 );
5749
5750 return;
5751 }
5752
5753 tmp = ast_samp2tv(rx_rtp_ts, rate);
5754 /* See the comment about "tv" above. Even if
5755 * we don't use this received packet for jitter
5756 * calculations, we still need to set tv so the
5757 * timestamp will be correct when this packet is
5758 * sent out again.
5759 */
5760 *tv = ast_tvadd(rtp->rxcore, tmp);
5761
5762 /*
5763 * The first few packets are generally unstable so let's
5764 * not use them in the calculations.
5765 */
5767 ast_debug_rtcp(3, "%s: Packet %d < %d. Ignoring\n",
5769 , rtp->rxcount
5771 );
5772
5773 return;
5774 }
5775
5776 /*
5777 * First good packet. Capture the start time and timestamp
5778 * but don't actually use this packet for calculation.
5779 */
5781 rtp->rxstart_stable = ast_tv2double(&now);
5782 rtp->remote_seed_rx_rtp_ts_stable = rx_rtp_ts;
5783 rtp->last_transit_time_samples = -rx_rtp_ts;
5784
5785 ast_debug_rtcp(3, "%s: "
5786 "pkt: %5u Stable Seed ts: %u current time: %f\n",
5788 , rtp->rxcount
5789 , rx_rtp_ts
5790 , rtp->rxstart_stable
5791 );
5792
5793 return;
5794 }
5795
5796 /*
5797 * If the current packet isn't in sequence, don't
5798 * use it in any calculations as remote_current_rx_rtp_ts
5799 * is not going to be correct.
5800 */
5801 if (rtp->lastrxseqno != rtp->prevrxseqno + 1) {
5802 ast_debug_rtcp(3, "%s: Current packet seq %d != last packet seq %d + 1. Ignoring\n",
5804 , rtp->lastrxseqno
5805 , rtp->prevrxseqno
5806 );
5807
5808 return;
5809 }
5810
5811 /*
5812 * The following calculations are taken from
5813 * https://www.rfc-editor.org/rfc/rfc3550#appendix-A.8
5814 *
5815 * The received rtp timestamp is the random "seed"
5816 * timestamp chosen by the sender when they sent the
5817 * first packet, plus the number of samples since then.
5818 *
5819 * To get our arrival time in the same units, we
5820 * calculate the time difference in seconds between
5821 * when we received the first packet and when we
5822 * received this packet and convert that to samples.
5823 */
5824 rxnow = ast_tv2double(&now);
5825 arrival_sec = rxnow - rtp->rxstart_stable;
5826 arrival = ast_sec2samp(arrival_sec, rate);
5827
5828 /*
5829 * Now we can use the exact formula in
5830 * https://www.rfc-editor.org/rfc/rfc3550#appendix-A.8 :
5831 *
5832 * int transit = arrival - r->ts;
5833 * int d = transit - s->transit;
5834 * s->transit = transit;
5835 * if (d < 0) d = -d;
5836 * s->jitter += (1./16.) * ((double)d - s->jitter);
5837 *
5838 * Our rx_rtp_ts is their r->ts.
5839 * Our rtp->last_transit_time_samples is their s->transit.
5840 * Our rtp->rxjitter is their s->jitter.
5841 */
5842 transit = arrival - rx_rtp_ts;
5843 d = transit - rtp->last_transit_time_samples;
5844
5845 if (d < 0) {
5846 d = -d;
5847 }
5848
5849 prev_jitter = rtp->rxjitter_samples;
5850 jitter = (1.0/16.0) * (((double)d) - prev_jitter);
5851 rtp->rxjitter_samples = prev_jitter + jitter;
5852
5853 /*
5854 * We need to hang on to jitter in both samples and seconds.
5855 */
5856 rtp->rxjitter = ast_samp2sec(rtp->rxjitter_samples, rate);
5857
5858 ast_debug_rtcp(3, "%s: pkt: %5u "
5859 "Arrival sec: %7.3f Arrival ts: %10u RX ts: %10u "
5860 "Transit samp: %6d Last transit samp: %6d d: %4d "
5861 "Curr jitter: %7.0f(%7.3f) Prev Jitter: %7.0f(%7.3f) New Jitter: %7.0f(%7.3f)\n",
5863 , rtp->rxcount
5864 , arrival_sec
5865 , arrival
5866 , rx_rtp_ts
5867 , transit
5869 , d
5870 , jitter
5871 , ast_samp2sec(jitter, rate)
5872 , prev_jitter
5873 , ast_samp2sec(prev_jitter, rate)
5874 , rtp->rxjitter_samples
5875 , rtp->rxjitter
5876 );
5877
5878 rtp->last_transit_time_samples = transit;
5879
5880 /*
5881 * Update all the stats.
5882 */
5883 if (rtp->rtcp) {
5884 if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
5885 rtp->rtcp->maxrxjitter = rtp->rxjitter;
5886 if (rtp->rtcp->rxjitter_count == 1)
5887 rtp->rtcp->minrxjitter = rtp->rxjitter;
5888 if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
5889 rtp->rtcp->minrxjitter = rtp->rxjitter;
5890
5893 &rtp->rtcp->rxjitter_count);
5894 }
5895
5896 return;
5897}
#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 3950 of file res_rtp_asterisk.c.

3951{
3952 struct timeval t;
3953 long ms;
3954
3955 if (ast_tvzero(rtp->txcore)) {
3956 rtp->txcore = ast_tvnow();
3957 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
3958 }
3959
3960 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
3961 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
3962 ms = 0;
3963 }
3964 rtp->txcore = t;
3965
3966 return (unsigned int) ms;
3967}
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 4712 of file res_rtp_asterisk.c.

4715{
4716 unsigned int extended_seq_no;
4717 unsigned int expected_packets;
4718 unsigned int expected_interval;
4719 unsigned int received_interval;
4720 int lost_interval;
4721
4722 /* Compute statistics */
4723 extended_seq_no = rtp->cycles + rtp->lastrxseqno;
4724 expected_packets = extended_seq_no - rtp->seedrxseqno + 1;
4725 if (rtp->rxcount > expected_packets) {
4726 expected_packets += rtp->rxcount - expected_packets;
4727 }
4728 *lost_packets = expected_packets - rtp->rxcount;
4729 expected_interval = expected_packets - rtp->rtcp->expected_prior;
4730 received_interval = rtp->rxcount - rtp->rtcp->received_prior;
4731 if (received_interval > expected_interval) {
4732 /* If we receive some late packets it is possible for the packets
4733 * we received in this interval to exceed the number we expected.
4734 * We update the expected so that the packet loss calculations
4735 * show that no packets are lost.
4736 */
4737 expected_interval = received_interval;
4738 }
4739 lost_interval = expected_interval - received_interval;
4740 if (expected_interval == 0 || lost_interval <= 0) {
4741 *fraction_lost = 0;
4742 } else {
4743 *fraction_lost = (lost_interval << 8) / expected_interval;
4744 }
4745
4746 /* Update RTCP statistics */
4747 rtp->rtcp->received_prior = rtp->rxcount;
4748 rtp->rtcp->expected_prior = expected_packets;
4749
4750 /*
4751 * While rxlost represents the number of packets lost since the last report was sent, for
4752 * the calculations below it should be thought of as a single sample. Thus min/max are the
4753 * lowest/highest sample value seen, and the mean is the average number of packets lost
4754 * between each report. As such rxlost_count only needs to be incremented per report.
4755 */
4756 if (lost_interval <= 0) {
4757 rtp->rtcp->rxlost = 0;
4758 } else {
4759 rtp->rtcp->rxlost = lost_interval;
4760 }
4761 if (rtp->rtcp->rxlost_count == 0) {
4762 rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4763 }
4764 if (lost_interval && lost_interval < rtp->rtcp->minrxlost) {
4765 rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4766 }
4767 if (lost_interval > rtp->rtcp->maxrxlost) {
4768 rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
4769 }
4770
4772 &rtp->rtcp->stdev_rxlost, &rtp->rtcp->rxlost_count);
4773}
unsigned int rxlost_count

References calc_mean_and_standard_deviation(), and ast_srtp::rtp.

Referenced by ast_rtcp_generate_report().

◆ compare_by_value()

static int compare_by_value ( int  elem,
int  value 
)
static

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

Definition at line 3184 of file res_rtp_asterisk.c.

3185{
3186 return elem - value;
3187}

References value.

Referenced by ast_rtp_read().

◆ create_dtmf_frame()

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

Definition at line 5899 of file res_rtp_asterisk.c.

5900{
5901 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5902 struct ast_sockaddr remote_address = { {0,} };
5903
5904 ast_rtp_instance_get_remote_address(instance, &remote_address);
5905
5906 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
5907 ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
5908 instance, ast_sockaddr_stringify(&remote_address));
5909 rtp->resp = 0;
5910 rtp->dtmfsamples = 0;
5911 return &ast_null_frame;
5912 } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
5913 ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
5914 instance, ast_sockaddr_stringify(&remote_address));
5915 rtp->resp = 0;
5916 rtp->dtmfsamples = 0;
5917 return &ast_null_frame;
5918 }
5919
5920 if (rtp->resp == 'X') {
5921 ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
5922 instance, ast_sockaddr_stringify(&remote_address));
5925 } else {
5926 ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
5927 instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
5928 rtp->resp, rtp->resp,
5929 ast_sockaddr_stringify(&remote_address));
5930 rtp->f.frametype = type;
5931 rtp->f.subclass.integer = rtp->resp;
5932 }
5933 rtp->f.datalen = 0;
5934 rtp->f.samples = 0;
5935 rtp->f.mallocd = 0;
5936 rtp->f.src = "RTP";
5937 AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
5938
5939 return &rtp->f;
5940}
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 3580 of file res_rtp_asterisk.c.

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

3191{
3192 return elem == value;
3193}

References value.

Referenced by ast_rtcp_generate_nack(), and ast_rtp_read().

◆ handle_cli_rtcp_set_debug()

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

Definition at line 9842 of file res_rtp_asterisk.c.

9843{
9844 switch (cmd) {
9845 case CLI_INIT:
9846 e->command = "rtcp set debug {on|off|ip}";
9847 e->usage =
9848 "Usage: rtcp set debug {on|off|ip host[:port]}\n"
9849 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
9850 " specified, limit the dumped packets to those to and from\n"
9851 " the specified 'host' with optional port.\n";
9852 return NULL;
9853 case CLI_GENERATE:
9854 return NULL;
9855 }
9856
9857 if (a->argc == e->args) { /* set on or off */
9858 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9860 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
9861 ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
9862 return CLI_SUCCESS;
9863 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9865 ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
9866 return CLI_SUCCESS;
9867 }
9868 } else if (a->argc == e->args +1) { /* ip */
9869 return rtcp_do_debug_ip(a);
9870 }
9871
9872 return CLI_SHOWUSAGE; /* default, failure */
9873}
#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 9875 of file res_rtp_asterisk.c.

9876{
9877 switch (cmd) {
9878 case CLI_INIT:
9879 e->command = "rtcp set stats {on|off}";
9880 e->usage =
9881 "Usage: rtcp set stats {on|off}\n"
9882 " Enable/Disable dumping of RTCP stats.\n";
9883 return NULL;
9884 case CLI_GENERATE:
9885 return NULL;
9886 }
9887
9888 if (a->argc != e->args)
9889 return CLI_SHOWUSAGE;
9890
9891 if (!strncasecmp(a->argv[e->args-1], "on", 2))
9892 rtcpstats = 1;
9893 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
9894 rtcpstats = 0;
9895 else
9896 return CLI_SHOWUSAGE;
9897
9898 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
9899 return CLI_SUCCESS;
9900}
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 9761 of file res_rtp_asterisk.c.

9762{
9763 switch (cmd) {
9764 case CLI_INIT:
9765 e->command = "rtp set debug {on|off|ip}";
9766 e->usage =
9767 "Usage: rtp set debug {on|off|ip host[:port]}\n"
9768 " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9769 " specified, limit the dumped packets to those to and from\n"
9770 " the specified 'host' with optional port.\n";
9771 return NULL;
9772 case CLI_GENERATE:
9773 return NULL;
9774 }
9775
9776 if (a->argc == e->args) { /* set on or off */
9777 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9779 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
9780 ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
9781 return CLI_SUCCESS;
9782 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9784 ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
9785 return CLI_SUCCESS;
9786 }
9787 } else if (a->argc == e->args +1) { /* ip */
9788 return rtp_do_debug_ip(a);
9789 }
9790
9791 return CLI_SHOWUSAGE; /* default, failure */
9792}
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 9795 of file res_rtp_asterisk.c.

9796{
9797#ifdef HAVE_PJPROJECT
9798 struct sockaddr_in stunaddr_copy;
9799#endif
9800 switch (cmd) {
9801 case CLI_INIT:
9802 e->command = "rtp show settings";
9803 e->usage =
9804 "Usage: rtp show settings\n"
9805 " Display RTP configuration settings\n";
9806 return NULL;
9807 case CLI_GENERATE:
9808 return NULL;
9809 }
9810
9811 if (a->argc != 3) {
9812 return CLI_SHOWUSAGE;
9813 }
9814
9815 ast_cli(a->fd, "\n\nGeneral Settings:\n");
9816 ast_cli(a->fd, "----------------\n");
9817 ast_cli(a->fd, " Port start: %d\n", rtpstart);
9818 ast_cli(a->fd, " Port end: %d\n", rtpend);
9819#ifdef SO_NO_CHECK
9820 ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
9821#endif
9822 ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
9823 ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
9824
9825 if (strictrtp) {
9826 ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
9827 }
9828
9829 ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
9830#ifdef HAVE_PJPROJECT
9831 ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
9832
9833 ast_rwlock_rdlock(&stunaddr_lock);
9834 memcpy(&stunaddr_copy, &stunaddr, sizeof(stunaddr));
9835 ast_rwlock_unlock(&stunaddr_lock);
9836 ast_cli(a->fd, " STUN address: %s:%d\n", ast_inet_ntoa(stunaddr_copy.sin_addr), htons(stunaddr_copy.sin_port));
9837#endif
9838 return CLI_SUCCESS;
9839}
#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

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 10354 of file res_rtp_asterisk.c.

10355{
10356#ifdef HAVE_PJPROJECT
10357 pj_lock_t *lock;
10358
10360
10362 if (pj_init() != PJ_SUCCESS) {
10364 }
10365
10366 if (pjlib_util_init() != PJ_SUCCESS) {
10367 rtp_terminate_pjproject();
10369 }
10370
10371 if (pjnath_init() != PJ_SUCCESS) {
10372 rtp_terminate_pjproject();
10374 }
10375
10376 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10377
10378 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10379
10380 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10381 rtp_terminate_pjproject();
10383 }
10384
10385 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10386 rtp_terminate_pjproject();
10388 }
10389
10390 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10391
10392 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10393 rtp_terminate_pjproject();
10395 }
10396
10397#endif
10398
10399#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10400 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10401 if (!dtls_bio_methods) {
10402#ifdef HAVE_PJPROJECT
10403 rtp_terminate_pjproject();
10404#endif
10406 }
10407 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10408 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10409 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10410 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10411#endif
10412
10414#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10415 BIO_meth_free(dtls_bio_methods);
10416#endif
10417#ifdef HAVE_PJPROJECT
10418 rtp_terminate_pjproject();
10419#endif
10421 }
10422
10424#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10425 BIO_meth_free(dtls_bio_methods);
10426#endif
10427#ifdef HAVE_PJPROJECT
10429 rtp_terminate_pjproject();
10430#endif
10432 }
10433
10434 rtp_reload(0, 0);
10435
10437}
ast_mutex_t lock
Definition app_sla.c:337
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition netsock2.c:230
#define AST_PJPROJECT_INIT_LOG_LEVEL()
Get maximum log level pjproject was compiled with.
Definition options.h:177
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static int rtp_reload(int reload, int by_external_config)
static struct ast_rtp_engine asterisk_rtp_engine
static struct ast_cli_entry cli_rtp[]
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition rtp_engine.c:370
#define ast_rtp_engine_register(engine)
Definition rtp_engine.h:852
#define ARRAY_LEN(a)
Definition utils.h: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 4705 of file res_rtp_asterisk.c.

4706{
4707 tv->tv_sec = msw - 2208988800u;
4708 /* Reverse the sequence in timeval2ntp() */
4709 tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
4710}

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

6161{
6162 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6163
6164 /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
6165 totally help us out because we don't have an engine to keep it going and we are not
6166 guaranteed to have it every 20ms or anything */
6168 ast_debug(0, "- RTP 3389 Comfort noise event: Format %s (len = %d)\n",
6170 }
6171
6172 if (!ast_test_flag(rtp, FLAG_3389_WARNING)) {
6173 struct ast_sockaddr remote_address = { {0,} };
6174
6175 ast_rtp_instance_get_remote_address(instance, &remote_address);
6176
6177 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
6178 ast_sockaddr_stringify(&remote_address));
6180 }
6181
6182 /* Must have at least one byte */
6183 if (!len) {
6184 return NULL;
6185 }
6186 if (len < 24) {
6187 rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
6188 rtp->f.datalen = len - 1;
6190 memcpy(rtp->f.data.ptr, data + 1, len - 1);
6191 } else {
6192 rtp->f.data.ptr = NULL;
6193 rtp->f.offset = 0;
6194 rtp->f.datalen = 0;
6195 }
6196 rtp->f.frametype = AST_FRAME_CNG;
6197 rtp->f.subclass.integer = data[0] & 0x7f;
6198 rtp->f.samples = 0;
6199 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
6200
6201 return &rtp->f;
6202}
#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 6080 of file res_rtp_asterisk.c.

6081{
6082 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6083 unsigned int event, flags, power;
6084 char resp = 0;
6085 unsigned char seq;
6086 struct ast_frame *f = NULL;
6087
6088 if (len < 4) {
6089 return NULL;
6090 }
6091
6092 /* The format of Cisco RTP DTMF packet looks like next:
6093 +0 - sequence number of DTMF RTP packet (begins from 1,
6094 wrapped to 0)
6095 +1 - set of flags
6096 +1 (bit 0) - flaps by different DTMF digits delimited by audio
6097 or repeated digit without audio???
6098 +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
6099 then falls to 0 at its end)
6100 +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
6101 Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
6102 by each new packet and thus provides some redundancy.
6103
6104 Sample of Cisco RTP DTMF packet is (all data in hex):
6105 19 07 00 02 12 02 20 02
6106 showing end of DTMF digit '2'.
6107
6108 The packets
6109 27 07 00 02 0A 02 20 02
6110 28 06 20 02 00 02 0A 02
6111 shows begin of new digit '2' with very short pause (20 ms) after
6112 previous digit '2'. Bit +1.0 flips at begin of new digit.
6113
6114 Cisco RTP DTMF packets comes as replacement of audio RTP packets
6115 so its uses the same sequencing and timestamping rules as replaced
6116 audio packets. Repeat interval of DTMF packets is 20 ms and not rely
6117 on audio framing parameters. Marker bit isn't used within stream of
6118 DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
6119 are not sequential at borders between DTMF and audio streams,
6120 */
6121
6122 seq = data[0];
6123 flags = data[1];
6124 power = data[2];
6125 event = data[3] & 0x1f;
6126
6128 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);
6129 if (event < 10) {
6130 resp = '0' + event;
6131 } else if (event < 11) {
6132 resp = '*';
6133 } else if (event < 12) {
6134 resp = '#';
6135 } else if (event < 16) {
6136 resp = 'A' + (event - 12);
6137 } else if (event < 17) {
6138 resp = 'X';
6139 }
6140 if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
6141 rtp->resp = resp;
6142 /* Why we should care on DTMF compensation at reception? */
6144 f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
6145 rtp->dtmfsamples = 0;
6146 }
6147 } else if ((rtp->resp == resp) && !power) {
6149 f->samples = rtp->dtmfsamples * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
6150 rtp->resp = 0;
6151 } else if (rtp->resp == resp) {
6152 rtp->dtmfsamples += 20 * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
6153 }
6154
6155 rtp->dtmf_timeout = 0;
6156
6157 return f;
6158}
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 5942 of file res_rtp_asterisk.c.

5943{
5944 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5945 struct ast_sockaddr remote_address = { {0,} };
5946 unsigned int event, event_end, samples;
5947 char resp = 0;
5948 struct ast_frame *f = NULL;
5949
5950 ast_rtp_instance_get_remote_address(instance, &remote_address);
5951
5952 /* Figure out event, event end, and samples */
5953 event = ntohl(*((unsigned int *)(data)));
5954 event >>= 24;
5955 event_end = ntohl(*((unsigned int *)(data)));
5956 event_end <<= 8;
5957 event_end >>= 24;
5958 samples = ntohl(*((unsigned int *)(data)));
5959 samples &= 0xFFFF;
5960
5961 if (rtp_debug_test_addr(&remote_address)) {
5962 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",
5963 ast_sockaddr_stringify(&remote_address),
5964 payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
5965 }
5966
5967 /* Print out debug if turned on */
5969 ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
5970
5971 /* Figure out what digit was pressed */
5972 if (event < 10) {
5973 resp = '0' + event;
5974 } else if (event < 11) {
5975 resp = '*';
5976 } else if (event < 12) {
5977 resp = '#';
5978 } else if (event < 16) {
5979 resp = 'A' + (event - 12);
5980 } else if (event < 17) { /* Event 16: Hook flash */
5981 resp = 'X';
5982 } else {
5983 /* Not a supported event */
5984 ast_debug_rtp(1, "(%p) RTP ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", instance, event);
5985 return;
5986 }
5987
5989 if (!rtp->last_end_timestamp.is_set || rtp->last_end_timestamp.ts != timestamp || (rtp->resp && rtp->resp != resp)) {
5990 rtp->resp = resp;
5991 rtp->dtmf_timeout = 0;
5993 f->len = 0;
5994 rtp->last_end_timestamp.ts = timestamp;
5995 rtp->last_end_timestamp.is_set = 1;
5997 }
5998 } else {
5999 /* The duration parameter measures the complete
6000 duration of the event (from the beginning) - RFC2833.
6001 Account for the fact that duration is only 16 bits long
6002 (about 8 seconds at 8000 Hz) and can wrap is digit
6003 is hold for too long. */
6004 unsigned int new_duration = rtp->dtmf_duration;
6005 unsigned int last_duration = new_duration & 0xFFFF;
6006
6007 if (last_duration > 64000 && samples < last_duration) {
6008 new_duration += 0xFFFF + 1;
6009 }
6010 new_duration = (new_duration & ~0xFFFF) | samples;
6011
6012 if (event_end & 0x80) {
6013 /* End event */
6014 if (rtp->last_seqno != seqno && (!rtp->last_end_timestamp.is_set || timestamp > rtp->last_end_timestamp.ts)) {
6015 rtp->last_end_timestamp.ts = timestamp;
6016 rtp->last_end_timestamp.is_set = 1;
6017 rtp->dtmf_duration = new_duration;
6018 rtp->resp = resp;
6021 rtp->resp = 0;
6022 rtp->dtmf_duration = rtp->dtmf_timeout = 0;
6025 ast_debug_rtp(1, "(%p) RTP dropping duplicate or out of order DTMF END frame (seqno: %u, ts %u, digit %c)\n",
6026 instance, seqno, timestamp, resp);
6027 }
6028 } else {
6029 /* Begin/continuation */
6030
6031 /* The second portion of the seqno check is to not mistakenly
6032 * stop accepting DTMF if the seqno rolls over beyond
6033 * 65535.
6034 */
6035 if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
6036 || (rtp->last_end_timestamp.is_set
6037 && timestamp <= rtp->last_end_timestamp.ts)) {
6038 /* Out of order frame. Processing this can cause us to
6039 * improperly duplicate incoming DTMF, so just drop
6040 * this.
6041 */
6043 ast_debug(0, "Dropping out of order DTMF frame (seqno %u, ts %u, digit %c)\n",
6044 seqno, timestamp, resp);
6045 }
6046 return;
6047 }
6048
6049 if (rtp->resp && rtp->resp != resp) {
6050 /* Another digit already began. End it */
6053 rtp->resp = 0;
6054 rtp->dtmf_duration = rtp->dtmf_timeout = 0;
6056 }
6057
6058 if (rtp->resp) {
6059 /* Digit continues */
6060 rtp->dtmf_duration = new_duration;
6061 } else {
6062 /* New digit began */
6063 rtp->resp = resp;
6065 rtp->dtmf_duration = samples;
6067 }
6068
6069 rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
6070 }
6071
6072 rtp->last_seqno = seqno;
6073 }
6074
6075 rtp->dtmfsamples = samples;
6076
6077 return;
6078}

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

5168{
5169 unsigned char *cp = p;
5170 uint32_t datum;
5171
5172 /* Convert the time to 6.18 format */
5173 datum = (time_msw << 18) & 0x00fc0000;
5174 datum |= (time_lsw >> 14) & 0x0003ffff;
5175
5176 cp[0] = datum >> 16;
5177 cp[1] = datum >> 8;
5178 cp[2] = datum;
5179}

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

5413{
5414 unsigned char *data = red->t140red.data.ptr;
5415 int len = 0;
5416 int i;
5417
5418 /* replace most aged generation */
5419 if (red->len[0]) {
5420 for (i = 1; i < red->num_gen+1; i++)
5421 len += red->len[i];
5422
5423 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
5424 }
5425
5426 /* Store length of each generation and primary data length*/
5427 for (i = 0; i < red->num_gen; i++)
5428 red->len[i] = red->len[i+1];
5429 red->len[i] = red->t140.datalen;
5430
5431 /* write each generation length in red header */
5432 len = red->hdrlen;
5433 for (i = 0; i < red->num_gen; i++) {
5434 len += data[i*4+3] = red->len[i];
5435 }
5436
5437 /* add primary data to buffer */
5438 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
5439 red->t140red.datalen = len + red->t140.datalen;
5440
5441 /* no primary data and no generations to send */
5442 if (len == red->hdrlen && !red->t140.datalen) {
5443 return NULL;
5444 }
5445
5446 /* reset t.140 buffer */
5447 red->t140.datalen = 0;
5448
5449 return &red->t140red;
5450}
struct ast_frame t140
unsigned char len[AST_RED_MAX_GENERATION]
struct ast_frame t140red

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

Referenced by ast_rtp_write().

◆ red_write()

static int red_write ( const void *  data)
static

Write t140 redundancy frame.

Parameters
dataprimary data to be buffered

Scheduler callback

Definition at line 9167 of file res_rtp_asterisk.c.

9168{
9169 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
9170 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9171
9172 ao2_lock(instance);
9173 if (rtp->red->t140.datalen > 0) {
9174 ast_rtp_write(instance, &rtp->red->t140);
9175 }
9176 ao2_unlock(instance);
9177
9178 return 1;
9179}
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 10322 of file res_rtp_asterisk.c.

10323{
10324 rtp_reload(1, 0);
10325 return 0;
10326}

References rtp_reload().

◆ rtcp_debug_test_addr()

static int rtcp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2846 of file res_rtp_asterisk.c.

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

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

9745{
9746 char *arg = ast_strdupa(a->argv[4]);
9747 char *debughost = NULL;
9748 char *debugport = NULL;
9749
9750 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9751 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9752 return CLI_FAILURE;
9753 }
9754 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9755 ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9758 return CLI_SUCCESS;
9759}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define CLI_FAILURE
Definition cli.h:46
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition netsock2.c:164
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65

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

Referenced by handle_cli_rtcp_set_debug().

◆ rtcp_mux()

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

Definition at line 3195 of file res_rtp_asterisk.c.

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

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

6533{
6534 switch (pt) {
6535 case AST_RTP_RTCP_RTPFB:
6536 if (subtype == AST_RTP_RTCP_FMT_NACK) {
6537 return "NACK";
6538 }
6539 break;
6540 case RTCP_PT_PSFB:
6541 if (subtype == AST_RTP_RTCP_FMT_REMB) {
6542 return "REMB";
6543 }
6544 break;
6545 default:
6546 break;
6547 }
6548
6549 return NULL;
6550}

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

6501{
6502 const char *str;
6503
6504 switch (pt) {
6505 case RTCP_PT_SR:
6506 str = "Sender Report";
6507 break;
6508 case RTCP_PT_RR:
6509 str = "Receiver Report";
6510 break;
6511 case RTCP_PT_FUR:
6512 /* Full INTRA-frame Request / Fast Update Request */
6513 str = "H.261 FUR";
6514 break;
6515 case RTCP_PT_PSFB:
6516 /* Payload Specific Feed Back */
6517 str = "PSFB";
6518 break;
6519 case RTCP_PT_SDES:
6520 str = "Source Description";
6521 break;
6522 case RTCP_PT_BYE:
6523 str = "BYE";
6524 break;
6525 default:
6526 str = "Unknown";
6527 break;
6528 }
6529 return str;
6530}
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 3445 of file res_rtp_asterisk.c.

3446{
3447 return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
3448}
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 3523 of file res_rtp_asterisk.c.

3524{
3525 return __rtp_sendto(instance, buf, size, flags, sa, 1, ice, 1);
3526}
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 4062 of file res_rtp_asterisk.c.

4063{
4064 int x, startplace, i, maxloops;
4065
4067
4068 /* Create a new socket for us to listen on and use */
4069 if ((rtp->s = create_new_socket("RTP", &rtp->bind_address)) < 0) {
4070 ast_log(LOG_WARNING, "Failed to create a new socket for RTP instance '%p'\n", instance);
4071 return -1;
4072 }
4073
4074 /* Now actually find a free RTP port to use */
4075 x = (ast_random() % (rtpend - rtpstart)) + rtpstart;
4076 x = x & ~1;
4077 startplace = x;
4078
4079 /* Protection against infinite loops in the case there is a potential case where the loop is not broken such as an odd
4080 start port sneaking in (even though this condition is checked at load.) */
4081 maxloops = rtpend - rtpstart;
4082 for (i = 0; i <= maxloops; i++) {
4084 /* Try to bind, this will tell us whether the port is available or not */
4085 if (!ast_bind(rtp->s, &rtp->bind_address)) {
4086 ast_debug_rtp(1, "(%p) RTP allocated port %d\n", instance, x);
4088 ast_test_suite_event_notify("RTP_PORT_ALLOCATED", "Port: %d", x);
4089 break;
4090 }
4091
4092 x += 2;
4093 if (x > rtpend) {
4094 x = (rtpstart + 1) & ~1;
4095 }
4096
4097 /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
4098 if (x == startplace || (errno != EADDRINUSE && errno != EACCES)) {
4099 ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
4100 close(rtp->s);
4101 rtp->s = -1;
4102 return -1;
4103 }
4104 }
4105
4106#ifdef HAVE_PJPROJECT
4107 /* Initialize synchronization aspects */
4108 ast_cond_init(&rtp->cond, NULL);
4109
4110 generate_random_string(rtp->local_ufrag, sizeof(rtp->local_ufrag));
4111 generate_random_string(rtp->local_passwd, sizeof(rtp->local_passwd));
4112
4113 /* Create an ICE session for ICE negotiation */
4114 if (icesupport) {
4115 rtp->ice_num_components = 2;
4116 ast_debug_ice(2, "(%p) ICE creating session %s (%d)\n", instance,
4118 if (ice_create(instance, &rtp->bind_address, x, 0)) {
4119 ast_log(LOG_NOTICE, "(%p) ICE failed to create session\n", instance);
4120 } else {
4121 rtp->ice_port = x;
4122 ast_sockaddr_copy(&rtp->ice_original_rtp_addr, &rtp->bind_address);
4123 }
4124 }
4125#endif
4126
4127#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
4128 rtp->rekeyid = -1;
4129 rtp->dtls.timeout_timer = -1;
4130#endif
4131
4132 return 0;
4133}
#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)
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.

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

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

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

Referenced by ast_rtp_bundle(), and ast_rtp_destroy().

◆ rtp_debug_test_addr()

static int rtp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2830 of file res_rtp_asterisk.c.

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

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

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

◆ rtp_do_debug_ip()

static char * rtp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9727 of file res_rtp_asterisk.c.

9728{
9729 char *arg = ast_strdupa(a->argv[4]);
9730 char *debughost = NULL;
9731 char *debugport = NULL;
9732
9733 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9734 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9735 return CLI_FAILURE;
9736 }
9737 rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9738 ast_cli(a->fd, "RTP Packet Debugging Enabled for address: %s\n",
9741 return CLI_SUCCESS;
9742}

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

6496{
6497 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
6498}
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 6487 of file res_rtp_asterisk.c.

6489{
6490 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6491}

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

7750{
7751 int transport_wide_cc_id = ast_rtp_instance_extmap_get_id(instance, AST_RTP_EXTENSION_TRANSPORT_WIDE_CC);
7752 int pos = 0;
7753
7754 /* We currently only care about the transport-cc extension, so if that's not negotiated then do nothing */
7755 if (transport_wide_cc_id == -1) {
7756 return;
7757 }
7758
7759 /* Only while we do not exceed available extension data do we continue */
7760 while (pos < len) {
7761 int id = extension[pos] >> 4;
7762 int extension_len = (extension[pos] & 0xF) + 1;
7763
7764 /* We've handled the first byte as it contains the extension id and length, so always
7765 * skip ahead now
7766 */
7767 pos += 1;
7768
7769 if (id == 0) {
7770 /* From the RFC:
7771 * In both forms, padding bytes have the value of 0 (zero). They may be
7772 * placed between extension elements, if desired for alignment, or after
7773 * the last extension element, if needed for padding. A padding byte
7774 * does not supply the ID of an element, nor the length field. When a
7775 * padding byte is found, it is ignored and the parser moves on to
7776 * interpreting the next byte.
7777 */
7778 continue;
7779 } else if (id == 15) {
7780 /* From the RFC:
7781 * The local identifier value 15 is reserved for future extension and
7782 * MUST NOT be used as an identifier. If the ID value 15 is
7783 * encountered, its length field should be ignored, processing of the
7784 * entire extension should terminate at that point, and only the
7785 * extension elements present prior to the element with ID 15
7786 * considered.
7787 */
7788 break;
7789 } else if ((pos + extension_len) > len) {
7790 /* The extension is corrupted and is stating that it contains more data than is
7791 * available in the extensions data.
7792 */
7793 break;
7794 }
7795
7796 /* If this is transport-cc then we need to parse it further */
7797 if (id == transport_wide_cc_id) {
7798 rtp_instance_parse_transport_wide_cc(instance, rtp, extension + pos, extension_len);
7799 }
7800
7801 /* Skip ahead to the next extension */
7802 pos += extension_len;
7803 }
7804}
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 7693 of file res_rtp_asterisk.c.

7695{
7696 uint16_t *seqno = (uint16_t *)data;
7698 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
7699 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
7700
7701 /* If the sequence number has cycled over then record it as such */
7702 if (((int)transport_rtp->transport_wide_cc.last_seqno - (int)ntohs(*seqno)) > 100) {
7703 transport_rtp->transport_wide_cc.cycles += RTP_SEQ_MOD;
7704 }
7705
7706 /* Populate the statistics information for this packet */
7707 statistics.seqno = transport_rtp->transport_wide_cc.cycles + ntohs(*seqno);
7708 statistics.received = ast_tvnow();
7709
7710 /* We allow at a maximum 1000 packet statistics in play at a time, if we hit the
7711 * limit we give up and start fresh.
7712 */
7713 if (AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) > 1000) {
7715 }
7716
7717 if (!AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) ||
7718 statistics.seqno > transport_rtp->transport_wide_cc.last_extended_seqno) {
7719 /* This is the expected path */
7721 return;
7722 }
7723
7724 transport_rtp->transport_wide_cc.last_extended_seqno = statistics.seqno;
7725 transport_rtp->transport_wide_cc.last_seqno = ntohs(*seqno);
7726 } else {
7727 /* This packet was out of order, so reorder it within the vector accordingly */
7730 return;
7731 }
7732 }
7733
7734 /* If we have not yet scheduled the periodic sending of feedback for this transport then do so */
7735 if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
7736 ast_debug_rtcp(1, "(%p) RTCP starting transport-cc feedback transmission on RTP instance '%p'\n", instance, transport);
7737 ao2_ref(transport, +1);
7738 transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
7740 if (transport_rtp->transport_wide_cc.schedid < 0) {
7741 ao2_ref(transport, -1);
7742 ast_log(LOG_WARNING, "Scheduling RTCP transport-cc feedback transmission failed on RTP instance '%p'\n",
7743 transport);
7744 }
7745 }
7746}
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 7423 of file res_rtp_asterisk.c.

7424{
7425 if (instance) {
7426 ao2_unlock(instance);
7427 }
7428}

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

3637{
3638 if (seq == (uint16_t) (info->max_seq + 1)) {
3639 /* packet is in sequence */
3640 info->packets--;
3641 } else {
3642 /* Sequence discontinuity; reset */
3643 info->packets = learning_min_sequential - 1;
3644 info->received = ast_tvnow();
3645 }
3646
3647 /* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */
3648 if (strictrtp == STRICT_RTP_YES) {
3649 switch (info->stream_type) {
3652 /*
3653 * Protect against packet floods by checking that we
3654 * received the packet sequence in at least the minimum
3655 * allowed time.
3656 */
3657 if (ast_tvzero(info->received)) {
3658 info->received = ast_tvnow();
3659 } else if (!info->packets
3661 /* Packet flood; reset */
3662 info->packets = learning_min_sequential - 1;
3663 info->received = ast_tvnow();
3664 }
3665 break;
3669 case AST_MEDIA_TYPE_END:
3670 break;
3671 }
3672 }
3673
3674 info->max_seq = seq;
3675
3676 return info->packets;
3677}
@ 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 3619 of file res_rtp_asterisk.c.

3620{
3621 info->max_seq = seq;
3622 info->packets = learning_min_sequential;
3623 memset(&info->received, 0, sizeof(info->received));
3624}

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

3685{
3687 memset(&rtp->rtp_source_learn.proposed_address, 0,
3688 sizeof(rtp->rtp_source_learn.proposed_address));
3690 rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t) rtp->lastrxseqno);
3691}

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

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

3452{
3453 return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
3454}

References __rtp_recvfrom(), and buf.

Referenced by ast_rtp_read().

◆ rtp_red_buffer()

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

Definition at line 9214 of file res_rtp_asterisk.c.

9215{
9216 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9217 struct rtp_red *red = rtp->red;
9218
9219 if (!red) {
9220 return 0;
9221 }
9222
9223 if (frame->datalen > 0) {
9224 if (red->t140.datalen > 0) {
9225 const unsigned char *primary = red->buf_data;
9226
9227 /* There is something already in the T.140 buffer */
9228 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9229 /* Flush the previous T.140 packet if it is a command */
9230 ast_rtp_write(instance, &rtp->red->t140);
9231 } else {
9232 primary = frame->data.ptr;
9233 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9234 /* Flush the previous T.140 packet if we are buffering a command now */
9235 ast_rtp_write(instance, &rtp->red->t140);
9236 }
9237 }
9238 }
9239
9240 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
9241 red->t140.datalen += frame->datalen;
9242 red->t140.ts = frame->ts;
9243 }
9244
9245 return 0;
9246}
unsigned char buf_data[64000]

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

◆ rtp_red_init()

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

Definition at line 9182 of file res_rtp_asterisk.c.

9183{
9184 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9185 int x;
9186
9187 rtp->red = ast_calloc(1, sizeof(*rtp->red));
9188 if (!rtp->red) {
9189 return -1;
9190 }
9191
9194 rtp->red->t140.data.ptr = &rtp->red->buf_data;
9195
9196 rtp->red->t140red = rtp->red->t140;
9197 rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
9198
9199 rtp->red->num_gen = generations;
9200 rtp->red->hdrlen = generations * 4 + 1;
9201
9202 for (x = 0; x < generations; x++) {
9203 rtp->red->pt[x] = payloads[x];
9204 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
9205 rtp->red->t140red_data[x*4] = rtp->red->pt[x];
9206 }
9207 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
9208 rtp->red->schedid = ast_sched_add(rtp->sched, buffer_time, red_write, instance);
9209
9210 return 0;
9211}
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 10043 of file res_rtp_asterisk.c.

10044{
10045 struct ast_config *cfg;
10046 const char *s;
10047 struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10048
10049#ifdef HAVE_PJPROJECT
10050 struct ast_variable *var;
10051 struct ast_ice_host_candidate *candidate;
10052 int acl_subscription_flag = 0;
10053#endif
10054
10055 cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
10056 if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
10057 return 0;
10058 }
10059
10060#ifdef SO_NO_CHECK
10061 nochecksums = 0;
10062#endif
10063
10072
10073 /** This resource is not "reloaded" so much as unloaded and loaded again.
10074 * In the case of the TURN related variables, the memory referenced by a
10075 * previously loaded instance *should* have been released when the
10076 * corresponding pool was destroyed. If at some point in the future this
10077 * resource were to support ACTUAL live reconfiguration and did NOT release
10078 * the pool this will cause a small memory leak.
10079 */
10080
10081#ifdef HAVE_PJPROJECT
10082 icesupport = DEFAULT_ICESUPPORT;
10083 stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE;
10084 turnport = DEFAULT_TURN_PORT;
10085 clean_stunaddr();
10086 turnaddr = pj_str(NULL);
10087 turnusername = pj_str(NULL);
10088 turnpassword = pj_str(NULL);
10089 host_candidate_overrides_clear();
10090#endif
10091
10092#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10093 dtls_mtu = DEFAULT_DTLS_MTU;
10094#endif
10095
10096 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
10097 rtpstart = atoi(s);
10102 }
10103 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
10104 rtpend = atoi(s);
10109 }
10110 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
10111 rtcpinterval = atoi(s);
10112 if (rtcpinterval == 0)
10113 rtcpinterval = 0; /* Just so we're clear... it's zero */
10115 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
10118 }
10119 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
10120#ifdef SO_NO_CHECK
10121 nochecksums = ast_false(s) ? 1 : 0;
10122#else
10123 if (ast_false(s))
10124 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10125#endif
10126 }
10127 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
10128 dtmftimeout = atoi(s);
10129 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
10130 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
10133 };
10134 }
10135 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
10136 if (ast_true(s)) {
10138 } else if (!strcasecmp(s, "seqno")) {
10140 } else {
10142 }
10143 }
10144 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
10145 if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
10146 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
10149 }
10151 }
10152 if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
10154 }
10155#ifdef HAVE_PJPROJECT
10156 if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
10157 icesupport = ast_true(s);
10158 }
10159 if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
10160 stun_software_attribute = ast_true(s);
10161 }
10162 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
10163 char *hostport, *host, *port;
10164 unsigned int port_parsed = STANDARD_STUN_PORT;
10165 struct ast_sockaddr stunaddr_parsed;
10166
10167 hostport = ast_strdupa(s);
10168
10169 if (!ast_parse_arg(hostport, PARSE_ADDR, &stunaddr_parsed)) {
10170 ast_debug_stun(3, "stunaddr = '%s' does not need name resolution\n",
10171 ast_sockaddr_stringify_host(&stunaddr_parsed));
10172 if (!ast_sockaddr_port(&stunaddr_parsed)) {
10173 ast_sockaddr_set_port(&stunaddr_parsed, STANDARD_STUN_PORT);
10174 }
10175 ast_rwlock_wrlock(&stunaddr_lock);
10176 ast_sockaddr_to_sin(&stunaddr_parsed, &stunaddr);
10177 ast_rwlock_unlock(&stunaddr_lock);
10178 } else if (ast_sockaddr_split_hostport(hostport, &host, &port, 0)) {
10179 if (port) {
10180 ast_parse_arg(port, PARSE_UINT32|PARSE_IN_RANGE, &port_parsed, 1, 65535);
10181 }
10182 stunaddr.sin_port = htons(port_parsed);
10183
10184 stunaddr_resolver = ast_dns_resolve_recurring(host, T_A, C_IN,
10185 &stunaddr_resolve_callback, NULL);
10186 if (!stunaddr_resolver) {
10187 ast_log(LOG_ERROR, "Failed to setup recurring DNS resolution of stunaddr '%s'",
10188 host);
10189 }
10190 } else {
10191 ast_log(LOG_ERROR, "Failed to parse stunaddr '%s'", hostport);
10192 }
10193 }
10194 if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
10195 struct sockaddr_in addr;
10196 addr.sin_port = htons(DEFAULT_TURN_PORT);
10197 if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
10198 ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
10199 } else {
10200 pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
10201 /* ntohs() is not a bug here. The port number is used in host byte order with
10202 * a pjnat API. */
10203 turnport = ntohs(addr.sin_port);
10204 }
10205 }
10206 if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
10207 pj_strdup2_with_null(pool, &turnusername, s);
10208 }
10209 if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
10210 pj_strdup2_with_null(pool, &turnpassword, s);
10211 }
10212
10213 AST_RWLIST_WRLOCK(&host_candidates);
10214 for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
10215 struct ast_sockaddr local_addr, advertised_addr;
10216 unsigned int include_local_address = 0;
10217 char *sep;
10218
10219 ast_sockaddr_setnull(&local_addr);
10220 ast_sockaddr_setnull(&advertised_addr);
10221
10222 if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
10223 ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
10224 continue;
10225 }
10226
10227 sep = strchr((char *)var->value,',');
10228 if (sep) {
10229 *sep = '\0';
10230 sep++;
10231 sep = ast_skip_blanks(sep);
10232 include_local_address = strcmp(sep, "include_local_address") == 0;
10233 }
10234
10235 if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
10236 ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
10237 continue;
10238 }
10239
10240 if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
10241 ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
10242 break;
10243 }
10244
10245 candidate->include_local = include_local_address;
10246
10247 ast_sockaddr_copy(&candidate->local, &local_addr);
10248 ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
10249
10250 AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
10251 }
10252 AST_RWLIST_UNLOCK(&host_candidates);
10253
10254 ast_rwlock_wrlock(&ice_acl_lock);
10255 ast_rwlock_wrlock(&stun_acl_lock);
10256
10257 ice_acl = ast_free_acl_list(ice_acl);
10258 stun_acl = ast_free_acl_list(stun_acl);
10259
10260 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
10261 const char* sense = NULL;
10262 struct ast_acl_list **acl = NULL;
10263 if (strncasecmp(var->name, "ice_", 4) == 0) {
10264 sense = var->name + 4;
10265 acl = &ice_acl;
10266 } else if (strncasecmp(var->name, "stun_", 5) == 0) {
10267 sense = var->name + 5;
10268 acl = &stun_acl;
10269 } else {
10270 continue;
10271 }
10272
10273 if (strcasecmp(sense, "blacklist") == 0) {
10274 sense = "deny";
10275 }
10276
10277 if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
10278 continue;
10279 }
10280
10281 ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
10282 }
10283 ast_rwlock_unlock(&ice_acl_lock);
10284 ast_rwlock_unlock(&stun_acl_lock);
10285
10286 if (acl_subscription_flag && !acl_change_sub) {
10290 } else if (!acl_subscription_flag && acl_change_sub) {
10292 }
10293#endif
10294#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10295 if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
10296 if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
10297 ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
10299 dtls_mtu = DEFAULT_DTLS_MTU;
10300 }
10301 }
10302#endif
10303
10304 ast_config_destroy(cfg);
10305
10306 /* Choosing an odd start port casues issues (like a potential infinite loop) and as odd parts are not
10307 chosen anyway, we are going to round up and issue a warning */
10308 if (rtpstart & 1) {
10309 rtpstart++;
10310 ast_log(LOG_WARNING, "Odd start value for RTP port in rtp.conf, rounding up to %d\n", rtpstart);
10311 }
10312
10313 if (rtpstart >= rtpend) {
10314 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
10317 }
10318 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
10319 return 0;
10320}
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
Definition acl.c:429
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition acl.c:233
#define var
Definition ast_expr2f.c:605
static struct stasis_subscription * acl_change_sub
Definition chan_iax2.c:352
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition chan_iax2.c:1584
struct ast_dns_query_recurring * ast_dns_resolve_recurring(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query, and continue resolving it according to the lowest TTL available.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
@ CONFIG_FLAG_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:1090
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:1144
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1201
#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_acl_list(), ast_inet_ntoa(), ast_log, ast_named_acl_change_type(), ast_parse_arg(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rwlock_unlock, ast_rwlock_wrlock, ast_security_topic(), ast_skip_blanks(), ast_sockaddr_copy(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_setnull(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify_host(), ast_sockaddr_to_sin, ast_strdupa, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CALC_LEARNING_MIN_DURATION, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTLS_MTU, DEFAULT_DTMF_TIMEOUT, DEFAULT_ICESUPPORT, DEFAULT_LEARNING_MIN_DURATION, DEFAULT_LEARNING_MIN_SEQUENTIAL, DEFAULT_RTP_END, DEFAULT_RTP_START, DEFAULT_SRTP_REPLAY_PROTECTION, DEFAULT_STRICT_RTP, DEFAULT_STUN_SOFTWARE_ATTRIBUTE, DEFAULT_TURN_PORT, dtmftimeout, learning_min_duration, learning_min_sequential, LOG_ERROR, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, 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 3529 of file res_rtp_asterisk.c.

3530{
3531 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3532 int hdrlen = 12;
3533 int res;
3534
3535 if ((res = __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1)) > 0) {
3536 rtp->txcount++;
3537 rtp->txoctetcount += (res - hdrlen);
3538 }
3539
3540 return res;
3541}

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

7507{
7508 struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
7509 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7510 unsigned char *rtcpheader;
7511 char bdata[1024];
7512 struct rtp_transport_wide_cc_packet_statistics *first_packet;
7513 struct rtp_transport_wide_cc_packet_statistics *previous_packet;
7514 int i;
7515 int status_vector_chunk_bits = 14;
7516 uint16_t status_vector_chunk = (1 << 15) | (1 << 14);
7517 int run_length_chunk_count = 0;
7518 int run_length_chunk_status = -1;
7519 int packet_len = 20;
7520 int delta_len = 0;
7521 int packet_count = 0;
7522 unsigned int received_msw;
7523 unsigned int received_lsw;
7524 struct ast_sockaddr remote_address = { { 0, } };
7525 int res;
7526 int ice;
7527 unsigned int large_delta_count = 0;
7528 unsigned int small_delta_count = 0;
7529 unsigned int lost_count = 0;
7530
7531 if (!rtp || !rtp->rtcp || rtp->transport_wide_cc.schedid == -1) {
7532 ao2_ref(instance, -1);
7533 return 0;
7534 }
7535
7536 ao2_lock(instance);
7537
7538 /* If no packets have been received then do nothing */
7540 ao2_unlock(instance);
7541 return 1000;
7542 }
7543
7544 rtcpheader = (unsigned char *)bdata;
7545
7546 /* The first packet in the vector acts as our base sequence number and reference time */
7548 previous_packet = first_packet;
7549
7550 /* We go through each packet that we have statistics for, adding it either to a status
7551 * vector chunk or a run length chunk. The code tries to be as efficient as possible to
7552 * reduce packet size and will favor run length chunks when it makes sense.
7553 */
7554 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7556 int lost = 0;
7557 int res = 0;
7558
7560
7561 packet_count++;
7562
7563 if (first_packet != statistics) {
7564 /* The vector stores statistics in a sorted fashion based on the sequence
7565 * number. This ensures we can detect any packets that have been lost/not
7566 * received by comparing the sequence numbers.
7567 */
7568 lost = statistics->seqno - (previous_packet->seqno + 1);
7569 lost_count += lost;
7570 }
7571
7572 while (lost) {
7573 /* We append a not received status until all the lost packets have been accounted for */
7574 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7575 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 0);
7576 packet_count++;
7577
7578 /* If there is no more room left for storing packets stop now, we leave 20
7579 * extra bits at the end just in case.
7580 */
7581 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7582 res = -1;
7583 break;
7584 }
7585
7586 lost--;
7587 }
7588
7589 /* If the lost packet appending bailed out because we have no more space, then exit here too */
7590 if (res) {
7591 break;
7592 }
7593
7594 /* Per the spec the delta is in increments of 250 */
7595 statistics->delta = ast_tvdiff_us(statistics->received, previous_packet->received) / 250;
7596
7597 /* Based on the delta determine the status of this packet */
7598 if (statistics->delta < 0 || statistics->delta > 127) {
7599 /* Large or negative delta */
7600 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7601 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 2);
7602 delta_len += 2;
7603 large_delta_count++;
7604 } else {
7605 /* Small delta */
7606 rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7607 &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 1);
7608 delta_len += 1;
7609 small_delta_count++;
7610 }
7611
7612 previous_packet = statistics;
7613
7614 /* If there is no more room left in the packet stop handling of any subsequent packets */
7615 if (packet_len + delta_len + 20 > sizeof(bdata)) {
7616 break;
7617 }
7618 }
7619
7620 if (status_vector_chunk_bits != 14) {
7621 /* If the status vector chunk has packets in it then place it in the RTCP packet */
7622 put_unaligned_uint16(rtcpheader + packet_len, htons(status_vector_chunk));
7623 packet_len += 2;
7624 } else if (run_length_chunk_count) {
7625 /* If there is a run length chunk in progress then place it in the RTCP packet */
7626 put_unaligned_uint16(rtcpheader + packet_len, htons((0 << 15) | (run_length_chunk_status << 13) | run_length_chunk_count));
7627 packet_len += 2;
7628 }
7629
7630 /* We iterate again to build delta chunks */
7631 for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7633
7635
7636 if (statistics->delta < 0 || statistics->delta > 127) {
7637 /* We need 2 bytes to store this delta */
7638 put_unaligned_uint16(rtcpheader + packet_len, htons(statistics->delta));
7639 packet_len += 2;
7640 } else {
7641 /* We can store this delta in 1 byte */
7642 rtcpheader[packet_len] = statistics->delta;
7643 packet_len += 1;
7644 }
7645
7646 /* If this is the last packet handled by the run length chunk or status vector chunk code
7647 * then we can go no further.
7648 */
7649 if (statistics == previous_packet) {
7650 break;
7651 }
7652 }
7653
7654 /* Zero pad the end of the packet */
7655 while (packet_len % 4) {
7656 rtcpheader[packet_len++] = 0;
7657 }
7658
7659 /* Add the general RTCP header information */
7660 put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC << 24)
7661 | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
7662 put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
7663 put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
7664
7665 /* Add the transport-cc specific header information */
7666 put_unaligned_uint32(rtcpheader + 12, htonl((first_packet->seqno << 16) | packet_count));
7667
7668 timeval2ntp(first_packet->received, &received_msw, &received_lsw);
7669 put_unaligned_time24(rtcpheader + 16, received_msw, received_lsw);
7670 rtcpheader[19] = rtp->transport_wide_cc.feedback_count;
7671
7672 /* The packet is now fully constructed so send it out */
7673 ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
7674
7675 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",
7676 instance, packet_len, ast_rtp_instance_get_channel_id(instance), packet_count, small_delta_count, large_delta_count, lost_count);
7677
7678 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
7679 if (res < 0) {
7680 ast_log(LOG_ERROR, "RTCP transport-cc feedback error to %s due to %s\n",
7681 ast_sockaddr_stringify(&remote_address), strerror(errno));
7682 }
7683
7685
7687
7688 ao2_unlock(instance);
7689
7690 return 1000;
7691}
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 7465 of file res_rtp_asterisk.c.

7467{
7468 if (*run_length_chunk_status != status) {
7469 while (*run_length_chunk_count > 0 && *run_length_chunk_count < 8) {
7470 /* Realistically it only makes sense to use a run length chunk if there were 8 or more
7471 * consecutive packets of the same type, otherwise we could end up making the packet larger
7472 * if we have lots of small blocks of the same type. To help with this we backfill the status
7473 * vector (since it always represents 7 packets). Best case we end up with only that single
7474 * status vector and the rest are run length chunks.
7475 */
7476 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7477 status_vector_chunk, *run_length_chunk_status);
7478 *run_length_chunk_count -= 1;
7479 }
7480
7481 if (*run_length_chunk_count) {
7482 /* There is a run length chunk which needs to be written out */
7483 put_unaligned_uint16(rtcpheader + *packet_len, htons((0 << 15) | (*run_length_chunk_status << 13) | *run_length_chunk_count));
7484 *packet_len += 2;
7485 }
7486
7487 /* In all cases the run length chunk has to be reset */
7488 *run_length_chunk_count = 0;
7489 *run_length_chunk_status = -1;
7490
7491 if (*status_vector_chunk_bits == 14) {
7492 /* We aren't in the middle of a status vector so we can try for a run length chunk */
7493 *run_length_chunk_status = status;
7494 *run_length_chunk_count = 1;
7495 } else {
7496 /* We're doing a status vector so populate it accordingly */
7497 rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
7498 status_vector_chunk, status);
7499 }
7500 } else {
7501 /* This is easy, the run length chunk count can just get bumped up */
7502 *run_length_chunk_count += 1;
7503 }
7504}
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 7436 of file res_rtp_asterisk.c.

7438{
7439 /* Appending this status will use up 2 bits */
7440 *status_vector_chunk_bits -= 2;
7441
7442 /* We calculate which bits we want to update the status of. Since a status vector
7443 * is 16 bits we take away 2 (for the header), and then we take away any that have
7444 * already been used.
7445 */
7446 *status_vector_chunk |= (status << (16 - 2 - (14 - *status_vector_chunk_bits)));
7447
7448 /* If there are still bits available we can return early */
7449 if (*status_vector_chunk_bits) {
7450 return;
7451 }
7452
7453 /* Otherwise we have to place this chunk into the packet */
7454 put_unaligned_uint16(rtcpheader + *packet_len, htons(*status_vector_chunk));
7455 *status_vector_chunk_bits = 14;
7456
7457 /* The first bit being 1 indicates that this is a status vector chunk and the second
7458 * bit being 1 indicates that we are using 2 bits to represent each status for a
7459 * packet.
7460 */
7461 *status_vector_chunk = (1 << 15) | (1 << 14);
7462 *packet_len += 2;
7463}

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

7432{
7433 return a.seqno - b.seqno;
7434}
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 5452 of file res_rtp_asterisk.c.

5453{
5454 unsigned char *rtcpheader;
5455 unsigned char bdata[1024];
5456 int packet_len = 0;
5457 int fir_len = 20;
5458 int ice;
5459 int res;
5460 int sr;
5461 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5462
5463 if (!rtp || !rtp->rtcp) {
5464 return;
5465 }
5466
5467 if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5468 /*
5469 * RTCP was stopped.
5470 */
5471 return;
5472 }
5473
5474 if (!rtp->themssrc_valid) {
5475 /* We don't know their SSRC value so we don't know who to update. */
5476 return;
5477 }
5478
5479 /* Prepare RTCP FIR (PT=206, FMT=4) */
5480 rtp->rtcp->firseq++;
5481 if(rtp->rtcp->firseq == 256) {
5482 rtp->rtcp->firseq = 0;
5483 }
5484
5485 rtcpheader = bdata;
5486
5487 ao2_lock(instance);
5488 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5489 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5490
5491 if (res == 0 || res == 1) {
5492 ao2_unlock(instance);
5493 return;
5494 }
5495
5496 packet_len += res;
5497
5498 put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((fir_len/4)-1)));
5499 put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5500 put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(rtp->themssrc));
5501 put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(rtp->themssrc)); /* FCI: SSRC */
5502 put_unaligned_uint32(rtcpheader + packet_len + 16, htonl(rtp->rtcp->firseq << 24)); /* FCI: Sequence number */
5503 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + fir_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5504 if (res < 0) {
5505 ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
5506 } else {
5507 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5508 }
5509
5510 ao2_unlock(instance);
5511}

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

5514{
5515 struct ast_rtp_rtcp_feedback *feedback = frame->data.ptr;
5516 unsigned char *rtcpheader;
5517 unsigned char bdata[1024];
5518 int remb_len = 24;
5519 int ice;
5520 int res;
5521 int sr = 0;
5522 int packet_len = 0;
5523 RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
5524
5525 if (feedback->fmt != AST_RTP_RTCP_FMT_REMB) {
5526 ast_debug_rtcp(1, "(%p) RTCP provided feedback frame of format %d to write, but only REMB is supported\n",
5527 instance, feedback->fmt);
5528 return;
5529 }
5530
5531 if (!rtp || !rtp->rtcp) {
5532 return;
5533 }
5534
5535 /* If REMB support is not enabled don't send this RTCP packet */
5537 ast_debug_rtcp(1, "(%p) RTCP provided feedback REMB report to write, but REMB support not enabled\n",
5538 instance);
5539 return;
5540 }
5541
5542 if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5543 /*
5544 * RTCP was stopped.
5545 */
5546 return;
5547 }
5548
5549 rtcpheader = bdata;
5550
5551 ao2_lock(instance);
5552 rtcp_report = ast_rtp_rtcp_report_alloc(rtp->themssrc_valid ? 1 : 0);
5553 res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5554
5555 if (res == 0 || res == 1) {
5556 ao2_unlock(instance);
5557 return;
5558 }
5559
5560 packet_len += res;
5561
5562 put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (AST_RTP_RTCP_FMT_REMB << 24) | (RTCP_PT_PSFB << 16) | ((remb_len/4)-1)));
5563 put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5564 put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(0)); /* Per the draft, this should always be 0 */
5565 put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(('R' << 24) | ('E' << 16) | ('M' << 8) | ('B'))); /* Unique identifier 'R' 'E' 'M' 'B' */
5566 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 */
5567 put_unaligned_uint32(rtcpheader + packet_len + 20, htonl(rtp->ssrc)); /* The SSRC this feedback message applies to */
5568 res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + remb_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5569 if (res < 0) {
5570 ast_log(LOG_ERROR, "RTCP PSFB transmission error: %s\n", strerror(errno));
5571 } else {
5572 ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5573 }
5574
5575 ao2_unlock(instance);
5576}

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

4677{
4678 unsigned int sec, usec, frac;
4679 sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
4680 usec = tv.tv_usec;
4681 /*
4682 * Convert usec to 0.32 bit fixed point without overflow.
4683 *
4684 * = usec * 2^32 / 10^6
4685 * = usec * 2^32 / (2^6 * 5^6)
4686 * = usec * 2^26 / 5^6
4687 *
4688 * The usec value needs 20 bits to represent 999999 usec. So
4689 * splitting the 2^26 to get the most precision using 32 bit
4690 * values gives:
4691 *
4692 * = ((usec * 2^12) / 5^6) * 2^14
4693 *
4694 * Splitting the division into two stages preserves all the
4695 * available significant bits of usec over doing the division
4696 * all at once.
4697 *
4698 * = ((((usec * 2^12) / 5^3) * 2^7) / 5^3) * 2^7
4699 */
4700 frac = ((((usec << 12) / 125) << 7) / 125) << 7;
4701 *msw = sec;
4702 *lsw = frac;
4703}

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

10440{
10443
10444#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10445 if (dtls_bio_methods) {
10446 BIO_meth_free(dtls_bio_methods);
10447 }
10448#endif
10449
10450#ifdef HAVE_PJPROJECT
10451 host_candidate_overrides_clear();
10452 pj_thread_register_check();
10453 rtp_terminate_pjproject();
10454
10456 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10457 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10458 clean_stunaddr();
10459#endif
10460
10461 return 0;
10462}
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 6429 of file res_rtp_asterisk.c.

6430{
6432 rtp->rtcp->normdevrtt,
6433 rtp->rxjitter,
6434 rtp->rtcp->stdev_rxjitter,
6435 rtp->rtcp->normdev_rxlost);
6436
6437 if (rtp->rtcp->rxmes_count == 0) {
6438 rtp->rtcp->minrxmes = rtp->rxmes;
6439 }
6440 if (rtp->rxmes < rtp->rtcp->minrxmes) {
6441 rtp->rtcp->minrxmes = rtp->rxmes;
6442 }
6443 if (rtp->rxmes > rtp->rtcp->maxrxmes) {
6444 rtp->rtcp->maxrxmes = rtp->rxmes;
6445 }
6446
6448 &rtp->rtcp->stdev_rxmes, &rtp->rtcp->rxmes_count);
6449
6450 ast_debug_rtcp(2, " %s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6452 rtp->rtcp->normdevrtt,
6453 rtp->rxjitter,
6454 rtp->rtcp->stdev_rxjitter,
6455 rtp->rtcp->normdev_rxlost, rtp->rxmes);
6456}
static double calc_media_experience_score(struct ast_rtp_instance *instance, double normdevrtt, double normdev_rxjitter, double stdev_rxjitter, double normdev_rxlost)
Calculate a "media experience score" based on given data.
unsigned int rxmes_count
double stdev_rxmes

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

Referenced by ast_rtcp_generate_report().

◆ update_lost_stats()

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

Definition at line 6285 of file res_rtp_asterisk.c.

6286{
6287 double reported_lost;
6288
6289 rtp->rtcp->reported_lost = lost_packets;
6290 reported_lost = (double)rtp->rtcp->reported_lost;
6291 if (rtp->rtcp->reported_lost_count == 0) {
6292 rtp->rtcp->reported_minlost = reported_lost;
6293 }
6294 if (reported_lost < rtp->rtcp->reported_minlost) {
6295 rtp->rtcp->reported_minlost = reported_lost;
6296 }
6297 if (reported_lost > rtp->rtcp->reported_maxlost) {
6298 rtp->rtcp->reported_maxlost = reported_lost;
6299 }
6300
6303}
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 6394 of file res_rtp_asterisk.c.

6395{
6396 double mes = calc_media_experience_score(rtp->owner,
6397 rtp->rtcp->normdevrtt,
6398 rtp->rtcp->reported_jitter,
6401
6402 rtp->rtcp->reported_mes = mes;
6403 if (rtp->rtcp->reported_mes_count == 0) {
6404 rtp->rtcp->reported_minmes = mes;
6405 }
6406 if (mes < rtp->rtcp->reported_minmes) {
6407 rtp->rtcp->reported_minmes = mes;
6408 }
6409 if (mes > rtp->rtcp->reported_maxmes) {
6410 rtp->rtcp->reported_maxmes = mes;
6411 }
6412
6415
6416 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6418 rtp->rtcp->normdevrtt,
6419 rtp->rtcp->reported_jitter,
6421 rtp->rtcp->reported_normdev_lost, mes);
6422}
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 6204 of file res_rtp_asterisk.c.

6205{
6206 struct timeval now;
6207 struct timeval rtt_tv;
6208 unsigned int msw;
6209 unsigned int lsw;
6210 unsigned int rtt_msw;
6211 unsigned int rtt_lsw;
6212 unsigned int lsr_a;
6213 unsigned int rtt;
6214
6215 gettimeofday(&now, NULL);
6216 timeval2ntp(now, &msw, &lsw);
6217
6218 lsr_a = ((msw & 0x0000ffff) << 16) | ((lsw & 0xffff0000) >> 16);
6219 rtt = lsr_a - lsr - dlsr;
6220 rtt_msw = (rtt & 0xffff0000) >> 16;
6221 rtt_lsw = (rtt & 0x0000ffff);
6222 rtt_tv.tv_sec = rtt_msw;
6223 /*
6224 * Convert 16.16 fixed point rtt_lsw to usec without
6225 * overflow.
6226 *
6227 * = rtt_lsw * 10^6 / 2^16
6228 * = rtt_lsw * (2^6 * 5^6) / 2^16
6229 * = rtt_lsw * 5^6 / 2^10
6230 *
6231 * The rtt_lsw value is in 16.16 fixed point format and 5^6
6232 * requires 14 bits to represent. We have enough space to
6233 * directly do the conversion because there is no integer
6234 * component in rtt_lsw.
6235 */
6236 rtt_tv.tv_usec = (rtt_lsw * 15625) >> 10;
6237 rtp->rtcp->rtt = (double)rtt_tv.tv_sec + ((double)rtt_tv.tv_usec / 1000000);
6238 if (lsr_a - dlsr < lsr) {
6239 return 1;
6240 }
6241
6242 rtp->rtcp->accumulated_transit += rtp->rtcp->rtt;
6243 if (rtp->rtcp->rtt_count == 0 || rtp->rtcp->minrtt > rtp->rtcp->rtt) {
6244 rtp->rtcp->minrtt = rtp->rtcp->rtt;
6245 }
6246 if (rtp->rtcp->maxrtt < rtp->rtcp->rtt) {
6247 rtp->rtcp->maxrtt = rtp->rtcp->rtt;
6248 }
6249
6251 &rtp->rtcp->stdevrtt, &rtp->rtcp->rtt_count);
6252
6253 return 0;
6254}
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 10473 of file res_rtp_asterisk.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 10473 of file res_rtp_asterisk.c.

◆ asterisk_rtp_engine

struct ast_rtp_engine asterisk_rtp_engine
static

Definition at line 2568 of file res_rtp_asterisk.c.

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

10033 {
10034 AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
10035 AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
10036 AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
10037 AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
10038#ifdef AST_DEVMODE
10039 AST_CLI_DEFINE(handle_cli_rtp_drop_incoming_packets, "Drop RTP incoming packets"),
10040#endif
10041};
#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().