Asterisk - The Open Source Telephony Project GIT-master-4f2b068
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 6289 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 6672 of file res_rtp_asterisk.c.

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6671 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6670 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6635 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

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

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6647 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6636 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

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

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6646 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6669 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6668 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 6665 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 6666 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6650 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6639 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6652 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6648 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6651 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 4272 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 10457 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 6443 of file res_rtp_asterisk.c.

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

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

Referenced by rtp_find_instance_by_media_source_ssrc(), and rtp_find_instance_by_packet_source_ssrc().

◆ __rtp_recvfrom()

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

Definition at line 3229 of file res_rtp_asterisk.c.

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

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

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 10457 of file res_rtp_asterisk.c.

◆ ast_rtcp_calc_interval()

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

Definition at line 3531 of file res_rtp_asterisk.c.

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

References rtcpinterval.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

◆ ast_rtcp_calculate_sr_rr_statistics()

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

Definition at line 4852 of file res_rtp_asterisk.c.

4854{
4855 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4856 struct ast_rtp_rtcp_report_block *report_block = NULL;
4857 RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
4858
4859 if (!rtp || !rtp->rtcp) {
4860 return 0;
4861 }
4862
4863 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4864 return 0;
4865 }
4866
4867 if (!rtcp_report) {
4868 return -1;
4869 }
4870
4871 report_block = rtcp_report->report_block[0];
4872
4873 if (sr) {
4874 rtp->rtcp->txlsr = rtcp_report->sender_information.ntp_timestamp;
4875 rtp->rtcp->sr_count++;
4876 rtp->rtcp->lastsrtxcount = rtp->txcount;
4877 } else {
4878 rtp->rtcp->rr_count++;
4879 }
4880
4881 if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
4882 ast_verbose("* Sent RTCP %s to %s%s\n", sr ? "SR" : "RR",
4883 ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
4884 ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
4885 if (sr) {
4886 ast_verbose(" Sent(NTP): %u.%06u\n",
4887 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
4888 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
4889 ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
4890 ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
4891 ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
4892 }
4893 if (report_block) {
4894 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
4895 ast_verbose(" Report block:\n");
4896 ast_verbose(" Their SSRC: %u\n", report_block->source_ssrc);
4897 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
4898 ast_verbose(" Cumulative loss: %u\n", report_block->lost_count.packets);
4899 ast_verbose(" Highest seq no: %u\n", report_block->highest_seq_no);
4900 ast_verbose(" IA jitter (samp): %u\n", report_block->ia_jitter);
4901 ast_verbose(" IA jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
4902 ast_verbose(" Their last SR: %u\n", report_block->lsr);
4903 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
4904 }
4905 }
4906
4907 message_blob = ast_json_pack("{s: s, s: s, s: f}",
4908 "to", ast_sockaddr_stringify(&remote_address),
4909 "from", rtp->rtcp->local_addr_str,
4910 "mes", rtp->rxmes);
4911
4913 rtcp_report, message_blob);
4914
4915 return 1;
4916}
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
struct ast_rtp_rtcp_report_block::@291 lost_count
unsigned short fraction
Definition rtp_engine.h:349
struct ast_rtp_rtcp_report::@292 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 4976 of file res_rtp_asterisk.c.

4978{
4979 int packet_len = 0;
4980 int res;
4981
4982 /* Every RTCP packet needs to be sent out with a SR/RR and SDES prefixing it.
4983 * At the end of this function, rtcpheader should contain both of those packets,
4984 * and will return the length of the overall packet. This can be used to determine
4985 * where further packets can be inserted in the compound packet.
4986 */
4987 res = ast_rtcp_generate_report(instance, rtcpheader, report, sr);
4988
4989 if (res == 0 || res == 1) {
4990 ast_debug_rtcp(1, "(%p) RTCP failed to generate %s report!\n", instance, sr ? "SR" : "RR");
4991 return 0;
4992 }
4993
4994 packet_len += res;
4995
4996 res = ast_rtcp_generate_sdes(instance, rtcpheader + packet_len, report);
4997
4998 if (res == 0 || res == 1) {
4999 ast_debug_rtcp(1, "(%p) RTCP failed to generate SDES!\n", instance);
5000 return 0;
5001 }
5002
5003 return packet_len + res;
5004}
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 5006 of file res_rtp_asterisk.c.

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

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

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

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

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

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

9544{
9545 struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child);
9546 struct ast_rtp *parent_rtp;
9547 struct rtp_ssrc_mapping mapping;
9548 struct ast_sockaddr them = { { 0, } };
9549
9550 if (child_rtp->bundled == parent) {
9551 return 0;
9552 }
9553
9554 /* If this instance was already bundled then remove the SSRC mapping */
9555 if (child_rtp->bundled) {
9556 struct ast_rtp *bundled_rtp;
9557
9558 ao2_unlock(child);
9559
9560 /* The child lock can't be held while accessing the parent */
9561 ao2_lock(child_rtp->bundled);
9562 bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled);
9564 ao2_unlock(child_rtp->bundled);
9565
9566 ao2_lock(child);
9567 ao2_ref(child_rtp->bundled, -1);
9568 child_rtp->bundled = NULL;
9569 }
9570
9571 if (!parent) {
9572 /* We transitioned away from bundle so we need our own transport resources once again */
9573 rtp_allocate_transport(child, child_rtp);
9574 return 0;
9575 }
9576
9577 parent_rtp = ast_rtp_instance_get_data(parent);
9578
9579 /* We no longer need any transport related resources as we will use our parent RTP instance instead */
9580 rtp_deallocate_transport(child, child_rtp);
9581
9582 /* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
9583 child_rtp->bundled = ao2_bump(parent);
9584
9585 mapping.ssrc = child_rtp->themssrc;
9586 mapping.ssrc_valid = child_rtp->themssrc_valid;
9587 mapping.instance = child;
9588
9589 ao2_unlock(child);
9590
9591 ao2_lock(parent);
9592
9593 AST_VECTOR_APPEND(&parent_rtp->ssrc_mapping, mapping);
9594
9595#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9596 /* If DTLS-SRTP is already in use then add the local SSRC to it, otherwise it will get added once DTLS
9597 * negotiation has been completed.
9598 */
9599 if (parent_rtp->dtls.connection == AST_RTP_DTLS_CONNECTION_EXISTING) {
9600 dtls_srtp_add_local_ssrc(parent_rtp, parent, 0, child_rtp->ssrc, 0);
9601 }
9602#endif
9603
9604 /* Bundle requires that RTCP-MUX be in use so only the main remote address needs to match */
9606
9607 ao2_unlock(parent);
9608
9609 ao2_lock(child);
9610
9612
9613 return 0;
9614}
#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 4628 of file res_rtp_asterisk.c.

4629{
4630 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4631 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 0);
4632 struct ast_srtp *rtcp_srtp = ast_rtp_instance_get_srtp(instance, 1);
4633 unsigned int ssrc = ast_random();
4634
4635 if (rtp->lastts) {
4636 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4638 }
4639
4640 ast_debug_rtp(3, "(%p) RTP changing ssrc from %u to %u due to a source change\n",
4641 instance, rtp->ssrc, ssrc);
4642
4643 if (srtp) {
4644 ast_debug_rtp(3, "(%p) RTP changing ssrc for SRTP from %u to %u\n",
4645 instance, rtp->ssrc, ssrc);
4646 res_srtp->change_source(srtp, rtp->ssrc, ssrc);
4647 if (rtcp_srtp != srtp) {
4648 res_srtp->change_source(rtcp_srtp, rtp->ssrc, ssrc);
4649 }
4650 }
4651
4652 rtp->ssrc = ssrc;
4653
4654 /* Since the source is changing, we don't know what sequence number to expect next */
4655 rtp->expectedrxseqno = -1;
4656
4657 return;
4658}
#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:2348
#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 4275 of file res_rtp_asterisk.c.

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

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

◆ ast_rtp_dtmf_begin()

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

Definition at line 4362 of file res_rtp_asterisk.c.

4363{
4364 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4365 struct ast_sockaddr remote_address = { {0,} };
4366 int hdrlen = 12, res = 0, i = 0, payload = -1, sample_rate = -1;
4367 char data[256];
4368 unsigned int *rtpheader = (unsigned int*)data;
4369 RAII_VAR(struct ast_format *, payload_format, NULL, ao2_cleanup);
4370
4371 ast_rtp_instance_get_remote_address(instance, &remote_address);
4372
4373 /* If we have no remote address information bail out now */
4374 if (ast_sockaddr_isnull(&remote_address)) {
4375 return -1;
4376 }
4377
4378 /* Convert given digit into what we want to transmit */
4379 if ((digit <= '9') && (digit >= '0')) {
4380 digit -= '0';
4381 } else if (digit == '*') {
4382 digit = 10;
4383 } else if (digit == '#') {
4384 digit = 11;
4385 } else if ((digit >= 'A') && (digit <= 'D')) {
4386 digit = digit - 'A' + 12;
4387 } else if ((digit >= 'a') && (digit <= 'd')) {
4388 digit = digit - 'a' + 12;
4389 } else {
4390 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4391 return -1;
4392 }
4393
4394 if (rtp->lasttxformat == ast_format_none) {
4395 /* No audio frames have been written yet so we have to lookup both the preferred payload type and bitrate. */
4397 if (payload_format) {
4398 /* If we have a preferred type, use that. Otherwise default to 8K. */
4399 sample_rate = ast_format_get_sample_rate(payload_format);
4400 }
4401 } else {
4402 sample_rate = ast_format_get_sample_rate(rtp->lasttxformat);
4403 }
4404
4405 if (sample_rate != -1) {
4407 }
4408
4409 if (payload == -1 ||
4412 /* Fall back to the preferred DTMF payload type and sample rate as either we couldn't find an audio codec to try and match
4413 sample rates with or we could, but a telephone-event matching that audio codec's sample rate was not included in the
4414 sdp negotiated by the far end. */
4417 }
4418
4419 /* The sdp negotiation has not yeilded a usable RFC 2833/4733 format. Try a default-rate one as a last resort. */
4420 if (payload == -1 || sample_rate == -1) {
4421 sample_rate = DEFAULT_DTMF_SAMPLE_RATE_MS;
4423 }
4424 /* Even trying a default payload has failed. We are trying to send a digit outside of what was negotiated for. */
4425 if (payload == -1) {
4426 return -1;
4427 }
4428
4429 ast_test_suite_event_notify("DTMF_BEGIN", "Digit: %d\r\nPayload: %d\r\nRate: %d\r\n", digit, payload, sample_rate);
4430 ast_debug(1, "Sending digit '%d' at rate %d with payload %d\n", digit, sample_rate, payload);
4431
4432 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4433 rtp->send_duration = 160;
4434 rtp->dtmf_samplerate_ms = (sample_rate / 1000);
4435 rtp->lastts += calc_txstamp(rtp, NULL) * rtp->dtmf_samplerate_ms;
4436 rtp->lastdigitts = rtp->lastts + rtp->send_duration;
4437
4438 /* Create the actual packet that we will be sending */
4439 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
4440 rtpheader[1] = htonl(rtp->lastdigitts);
4441 rtpheader[2] = htonl(rtp->ssrc);
4442
4443 /* Actually send the packet */
4444 for (i = 0; i < 2; i++) {
4445 int ice;
4446
4447 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4448 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4449 if (res < 0) {
4450 ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4451 ast_sockaddr_stringify(&remote_address),
4452 strerror(errno));
4453 }
4454 if (rtp_debug_test_addr(&remote_address)) {
4455 ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4456 ast_sockaddr_stringify(&remote_address),
4457 ice ? " (via ICE)" : "",
4458 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4459 }
4460 rtp->seqno++;
4461 rtp->send_duration += 160;
4462 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
4463 }
4464
4465 /* Record that we are in the process of sending a digit and information needed to continue doing so */
4466 rtp->sending_digit = 1;
4467 rtp->send_digit = digit;
4468 rtp->send_payload = payload;
4469
4470 return 0;
4471}
char digit
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition format.c:379
struct ast_format * ast_format_none
Built-in "null" format.
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_get_sample_rate(), ast_format_none, ast_log, ast_rtp_codecs_get_payload(), ast_rtp_codecs_get_preferred_dtmf_format_pt(), ast_rtp_codecs_get_preferred_dtmf_format_rate(), ast_rtp_codecs_get_preferred_format(), ast_rtp_codecs_payload_code_tx(), ast_rtp_codecs_payload_code_tx_sample_rate(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_payload_mapping_tx_is_present(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_suite_event_notify, ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, calc_txstamp(), DEFAULT_DTMF_SAMPLE_RATE_MS, digit, ast_rtp::dtmf_samplerate_ms, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, ast_rtp::lasttxformat, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.

◆ ast_rtp_dtmf_compatible()

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

Definition at line 9326 of file res_rtp_asterisk.c.

9327{
9328 /* If both sides are not using the same method of DTMF transmission
9329 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9330 * --------------------------------------------------
9331 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9332 * |-----------|------------|-----------------------|
9333 * | Inband | False | True |
9334 * | RFC2833 | True | True |
9335 * | SIP INFO | False | False |
9336 * --------------------------------------------------
9337 */
9339 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9340}
@ 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 4474 of file res_rtp_asterisk.c.

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

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

4611{
4612 return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
4613}
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 4520 of file res_rtp_asterisk.c.

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

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

4356{
4357 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4358 return rtp->dtmfmode;
4359}
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 4347 of file res_rtp_asterisk.c.

4348{
4349 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4350 rtp->dtmfmode = dtmf_mode;
4351 return 0;
4352}

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

9532{
9533 switch (extension) {
9536 return 1;
9537 default:
9538 return 0;
9539 }
9540}
@ 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 9080 of file res_rtp_asterisk.c.

9081{
9082 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9083
9084 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9085}

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

9479{
9480 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9481
9482 return rtp->cname;
9483}

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

9471{
9472 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9473
9474 return rtp->ssrc;
9475}

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

9262{
9263 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9264
9265 if (!rtp->rtcp) {
9266 return -1;
9267 }
9268
9273
9285
9297
9304
9316
9317
9321
9322 return 0;
9323}
#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 7790 of file res_rtp_asterisk.c.

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

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

Referenced by ast_rtp_read().

◆ ast_rtp_local_bridge()

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

Definition at line 9233 of file res_rtp_asterisk.c.

9234{
9235 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
9236
9237 ao2_lock(instance0);
9239 if (rtp->smoother) {
9241 rtp->smoother = NULL;
9242 }
9243
9244 /* We must use a new SSRC when local bridge ends */
9245 if (!instance1) {
9246 rtp->ssrc = rtp->ssrc_orig;
9247 rtp->ssrc_orig = 0;
9248 rtp->ssrc_saved = 0;
9249 } else if (!rtp->ssrc_saved) {
9250 /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
9251 rtp->ssrc_orig = rtp->ssrc;
9252 rtp->ssrc_saved = 1;
9253 }
9254
9255 ao2_unlock(instance0);
9256
9257 return 0;
9258}
#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 4219 of file res_rtp_asterisk.c.

4222{
4223 struct ast_rtp *rtp = NULL;
4224
4225 /* Create a new RTP structure to hold all of our data */
4226 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
4227 return -1;
4228 }
4229 rtp->owner = instance;
4230 /* Set default parameters on the newly created RTP structure */
4231 rtp->ssrc = ast_random();
4232 ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname));
4233 rtp->seqno = ast_random() & 0xffff;
4234 rtp->expectedrxseqno = -1;
4235 rtp->expectedseqno = -1;
4236 rtp->rxstart = -1;
4237 rtp->sched = sched;
4238 ast_sockaddr_copy(&rtp->bind_address, addr);
4239 /* Transport creation operations can grab the RTP data from the instance, so set it */
4240 ast_rtp_instance_set_data(instance, rtp);
4241
4242 if (rtp_allocate_transport(instance, rtp)) {
4243 return -1;
4244 }
4245
4246 if (AST_VECTOR_INIT(&rtp->ssrc_mapping, 1)) {
4247 return -1;
4248 }
4249
4251 return -1;
4252 }
4253 rtp->transport_wide_cc.schedid = -1;
4254
4258 rtp->stream_num = -1;
4259
4260 return 0;
4261}
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 8896 of file res_rtp_asterisk.c.

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

9410{
9411 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9412
9413 return ast_set_qos(rtp->s, tos, cos, desc);
9414}
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 8229 of file res_rtp_asterisk.c.

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

9089{
9090 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9091 struct ast_sockaddr local;
9092 int index;
9093
9094 ast_rtp_instance_get_local_address(instance, &local);
9095 if (!ast_sockaddr_isnull(addr)) {
9096 /* Update the local RTP address with what is being used */
9097 if (ast_ouraddrfor(addr, &local)) {
9098 /* Failed to update our address so reuse old local address */
9099 ast_rtp_instance_get_local_address(instance, &local);
9100 } else {
9101 ast_rtp_instance_set_local_address(instance, &local);
9102 }
9103 }
9104
9105 if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
9106 ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
9107 ast_sockaddr_copy(&rtp->rtcp->them, addr);
9108
9111
9112 /* Update the local RTCP address with what is being used */
9113 ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
9114 }
9115 ast_sockaddr_copy(&rtp->rtcp->us, &local);
9116
9119 }
9120
9121 /* Update any bundled RTP instances */
9122 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
9123 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
9124
9126 }
9127
9128 /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
9129 rtp->last_seqno = 0;
9130 rtp->last_end_timestamp.ts = 0;
9131 rtp->last_end_timestamp.is_set = 0;
9132
9134 && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
9135 /* We only need to learn a new strict source address if we've been told the source is
9136 * changing to something different.
9137 */
9138 ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
9139 rtp, ast_sockaddr_stringify(addr));
9140 rtp_learning_start(rtp);
9141 }
9142}
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 6537 of file res_rtp_asterisk.c.

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

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

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

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

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

9525{
9526 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9527
9528 rtp->stream_num = stream_num;
9529}

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

9359{
9360 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9361 struct ast_sockaddr addr = { {0,} };
9362
9363#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9364 ao2_unlock(instance);
9365 AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
9366
9367 dtls_srtp_stop_timeout_timer(instance, rtp, 0);
9368 if (rtp->rtcp) {
9369 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9370 }
9371 ao2_lock(instance);
9372#endif
9373 ast_debug_rtp(1, "(%s) RTP Stop\n",
9375
9376 if (rtp->rtcp && rtp->rtcp->schedid > -1) {
9377 ao2_unlock(instance);
9378 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9379 /* successfully cancelled scheduler entry. */
9380 ao2_ref(instance, -1);
9381 }
9382 ao2_lock(instance);
9383 rtp->rtcp->schedid = -1;
9384 }
9385
9386 if (rtp->transport_wide_cc.schedid > -1) {
9387 ao2_unlock(instance);
9388 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9389 ao2_ref(instance, -1);
9390 }
9391 ao2_lock(instance);
9392 rtp->transport_wide_cc.schedid = -1;
9393 }
9394
9395 if (rtp->red) {
9396 ao2_unlock(instance);
9397 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
9398 ao2_lock(instance);
9399 ast_free(rtp->red);
9400 rtp->red = NULL;
9401 }
9402
9403 ast_rtp_instance_set_remote_address(instance, &addr);
9404
9406}
#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 9343 of file res_rtp_asterisk.c.

9344{
9345 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9346 struct sockaddr_in suggestion_tmp;
9347
9348 /*
9349 * The instance should not be locked because we can block
9350 * waiting for a STUN respone.
9351 */
9352 ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
9353 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
9354 ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
9355}
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 4616 of file res_rtp_asterisk.c.

4617{
4618 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4619
4620 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4622 ast_debug_rtp(3, "(%p) RTP setting the marker bit due to a source update\n", instance);
4623
4624 return;
4625}

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

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

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

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

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

◆ calc_media_experience_score()

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

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

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

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

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

Definition at line 6313 of file res_rtp_asterisk.c.

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

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

3939{
3940 struct timeval t;
3941 long ms;
3942
3943 if (ast_tvzero(rtp->txcore)) {
3944 rtp->txcore = ast_tvnow();
3945 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
3946 }
3947
3948 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
3949 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
3950 ms = 0;
3951 }
3952 rtp->txcore = t;
3953
3954 return (unsigned int) ms;
3955}
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 4696 of file res_rtp_asterisk.c.

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

5884{
5885 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5886 struct ast_sockaddr remote_address = { {0,} };
5887
5888 ast_rtp_instance_get_remote_address(instance, &remote_address);
5889
5890 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
5891 ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
5892 instance, ast_sockaddr_stringify(&remote_address));
5893 rtp->resp = 0;
5894 rtp->dtmfsamples = 0;
5895 return &ast_null_frame;
5896 } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
5897 ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
5898 instance, ast_sockaddr_stringify(&remote_address));
5899 rtp->resp = 0;
5900 rtp->dtmfsamples = 0;
5901 return &ast_null_frame;
5902 }
5903
5904 if (rtp->resp == 'X') {
5905 ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
5906 instance, ast_sockaddr_stringify(&remote_address));
5909 } else {
5910 ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
5911 instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
5912 rtp->resp, rtp->resp,
5913 ast_sockaddr_stringify(&remote_address));
5914 rtp->f.frametype = type;
5915 rtp->f.subclass.integer = rtp->resp;
5916 }
5917 rtp->f.datalen = 0;
5918 rtp->f.samples = 0;
5919 rtp->f.mallocd = 0;
5920 rtp->f.src = "RTP";
5921 AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
5922
5923 return &rtp->f;
5924}
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 3568 of file res_rtp_asterisk.c.

3569{
3570 int af, sock;
3571
3572 af = ast_sockaddr_is_ipv4(bind_addr) ? AF_INET :
3573 ast_sockaddr_is_ipv6(bind_addr) ? AF_INET6 : -1;
3574 sock = ast_socket_nonblock(af, SOCK_DGRAM, 0);
3575
3576 if (sock < 0) {
3577 ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
3578 return sock;
3579 }
3580
3581#ifdef SO_NO_CHECK
3582 if (nochecksums) {
3583 setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
3584 }
3585#endif
3586
3587#ifdef HAVE_SOCK_IPV6_V6ONLY
3588 if (AF_INET6 == af && ast_sockaddr_is_any(bind_addr)) {
3589 /* ICE relies on dual-stack behavior. Ensure it is enabled. */
3590 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof(int)) != 0) {
3591 ast_log(LOG_WARNING, "setsockopt IPV6_V6ONLY=0 failed: %s\n", strerror(errno));
3592 }
3593 }
3594#endif
3595
3596 return sock;
3597}
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 9826 of file res_rtp_asterisk.c.

9827{
9828 switch (cmd) {
9829 case CLI_INIT:
9830 e->command = "rtcp set debug {on|off|ip}";
9831 e->usage =
9832 "Usage: rtcp set debug {on|off|ip host[:port]}\n"
9833 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
9834 " specified, limit the dumped packets to those to and from\n"
9835 " the specified 'host' with optional port.\n";
9836 return NULL;
9837 case CLI_GENERATE:
9838 return NULL;
9839 }
9840
9841 if (a->argc == e->args) { /* set on or off */
9842 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9844 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
9845 ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
9846 return CLI_SUCCESS;
9847 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9849 ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
9850 return CLI_SUCCESS;
9851 }
9852 } else if (a->argc == e->args +1) { /* ip */
9853 return rtcp_do_debug_ip(a);
9854 }
9855
9856 return CLI_SHOWUSAGE; /* default, failure */
9857}
#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 9859 of file res_rtp_asterisk.c.

9860{
9861 switch (cmd) {
9862 case CLI_INIT:
9863 e->command = "rtcp set stats {on|off}";
9864 e->usage =
9865 "Usage: rtcp set stats {on|off}\n"
9866 " Enable/Disable dumping of RTCP stats.\n";
9867 return NULL;
9868 case CLI_GENERATE:
9869 return NULL;
9870 }
9871
9872 if (a->argc != e->args)
9873 return CLI_SHOWUSAGE;
9874
9875 if (!strncasecmp(a->argv[e->args-1], "on", 2))
9876 rtcpstats = 1;
9877 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
9878 rtcpstats = 0;
9879 else
9880 return CLI_SHOWUSAGE;
9881
9882 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
9883 return CLI_SUCCESS;
9884}
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 9745 of file res_rtp_asterisk.c.

9746{
9747 switch (cmd) {
9748 case CLI_INIT:
9749 e->command = "rtp set debug {on|off|ip}";
9750 e->usage =
9751 "Usage: rtp set debug {on|off|ip host[:port]}\n"
9752 " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9753 " specified, limit the dumped packets to those to and from\n"
9754 " the specified 'host' with optional port.\n";
9755 return NULL;
9756 case CLI_GENERATE:
9757 return NULL;
9758 }
9759
9760 if (a->argc == e->args) { /* set on or off */
9761 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9763 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
9764 ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
9765 return CLI_SUCCESS;
9766 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9768 ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
9769 return CLI_SUCCESS;
9770 }
9771 } else if (a->argc == e->args +1) { /* ip */
9772 return rtp_do_debug_ip(a);
9773 }
9774
9775 return CLI_SHOWUSAGE; /* default, failure */
9776}
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 9779 of file res_rtp_asterisk.c.

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

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 10338 of file res_rtp_asterisk.c.

10339{
10340#ifdef HAVE_PJPROJECT
10341 pj_lock_t *lock;
10342
10344
10346 if (pj_init() != PJ_SUCCESS) {
10348 }
10349
10350 if (pjlib_util_init() != PJ_SUCCESS) {
10351 rtp_terminate_pjproject();
10353 }
10354
10355 if (pjnath_init() != PJ_SUCCESS) {
10356 rtp_terminate_pjproject();
10358 }
10359
10360 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10361
10362 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10363
10364 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10365 rtp_terminate_pjproject();
10367 }
10368
10369 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10370 rtp_terminate_pjproject();
10372 }
10373
10374 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10375
10376 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10377 rtp_terminate_pjproject();
10379 }
10380
10381#endif
10382
10383#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10384 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10385 if (!dtls_bio_methods) {
10386#ifdef HAVE_PJPROJECT
10387 rtp_terminate_pjproject();
10388#endif
10390 }
10391 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10392 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10393 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10394 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10395#endif
10396
10398#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10399 BIO_meth_free(dtls_bio_methods);
10400#endif
10401#ifdef HAVE_PJPROJECT
10402 rtp_terminate_pjproject();
10403#endif
10405 }
10406
10408#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10409 BIO_meth_free(dtls_bio_methods);
10410#endif
10411#ifdef HAVE_PJPROJECT
10413 rtp_terminate_pjproject();
10414#endif
10416 }
10417
10418 rtp_reload(0, 0);
10419
10421}
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 4689 of file res_rtp_asterisk.c.

4690{
4691 tv->tv_sec = msw - 2208988800u;
4692 /* Reverse the sequence in timeval2ntp() */
4693 tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
4694}

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

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

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

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

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

5152{
5153 unsigned char *cp = p;
5154 uint32_t datum;
5155
5156 /* Convert the time to 6.18 format */
5157 datum = (time_msw << 18) & 0x00fc0000;
5158 datum |= (time_lsw >> 14) & 0x0003ffff;
5159
5160 cp[0] = datum >> 16;
5161 cp[1] = datum >> 8;
5162 cp[2] = datum;
5163}

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

5397{
5398 unsigned char *data = red->t140red.data.ptr;
5399 int len = 0;
5400 int i;
5401
5402 /* replace most aged generation */
5403 if (red->len[0]) {
5404 for (i = 1; i < red->num_gen+1; i++)
5405 len += red->len[i];
5406
5407 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
5408 }
5409
5410 /* Store length of each generation and primary data length*/
5411 for (i = 0; i < red->num_gen; i++)
5412 red->len[i] = red->len[i+1];
5413 red->len[i] = red->t140.datalen;
5414
5415 /* write each generation length in red header */
5416 len = red->hdrlen;
5417 for (i = 0; i < red->num_gen; i++) {
5418 len += data[i*4+3] = red->len[i];
5419 }
5420
5421 /* add primary data to buffer */
5422 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
5423 red->t140red.datalen = len + red->t140.datalen;
5424
5425 /* no primary data and no generations to send */
5426 if (len == red->hdrlen && !red->t140.datalen) {
5427 return NULL;
5428 }
5429
5430 /* reset t.140 buffer */
5431 red->t140.datalen = 0;
5432
5433 return &red->t140red;
5434}
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 9151 of file res_rtp_asterisk.c.

9152{
9153 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
9154 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9155
9156 ao2_lock(instance);
9157 if (rtp->red->t140.datalen > 0) {
9158 ast_rtp_write(instance, &rtp->red->t140);
9159 }
9160 ao2_unlock(instance);
9161
9162 return 1;
9163}
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 10306 of file res_rtp_asterisk.c.

10307{
10308 rtp_reload(1, 0);
10309 return 0;
10310}

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

9729{
9730 char *arg = ast_strdupa(a->argv[4]);
9731 char *debughost = NULL;
9732 char *debugport = NULL;
9733
9734 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9735 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9736 return CLI_FAILURE;
9737 }
9738 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9739 ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9742 return CLI_SUCCESS;
9743}
#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 6516 of file res_rtp_asterisk.c.

6517{
6518 switch (pt) {
6519 case AST_RTP_RTCP_RTPFB:
6520 if (subtype == AST_RTP_RTCP_FMT_NACK) {
6521 return "NACK";
6522 }
6523 break;
6524 case RTCP_PT_PSFB:
6525 if (subtype == AST_RTP_RTCP_FMT_REMB) {
6526 return "REMB";
6527 }
6528 break;
6529 default:
6530 break;
6531 }
6532
6533 return NULL;
6534}

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

6485{
6486 const char *str;
6487
6488 switch (pt) {
6489 case RTCP_PT_SR:
6490 str = "Sender Report";
6491 break;
6492 case RTCP_PT_RR:
6493 str = "Receiver Report";
6494 break;
6495 case RTCP_PT_FUR:
6496 /* Full INTRA-frame Request / Fast Update Request */
6497 str = "H.261 FUR";
6498 break;
6499 case RTCP_PT_PSFB:
6500 /* Payload Specific Feed Back */
6501 str = "PSFB";
6502 break;
6503 case RTCP_PT_SDES:
6504 str = "Source Description";
6505 break;
6506 case RTCP_PT_BYE:
6507 str = "BYE";
6508 break;
6509 default:
6510 str = "Unknown";
6511 break;
6512 }
6513 return str;
6514}
const char * str
Definition app_jack.c:150

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

Referenced by ast_rtcp_interpret().

◆ rtcp_recvfrom()

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

Definition at line 3433 of file res_rtp_asterisk.c.

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

References __rtp_recvfrom(), and buf.

Referenced by ast_rtcp_read().

◆ rtcp_sendto()

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

Definition at line 3511 of file res_rtp_asterisk.c.

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

References __rtp_sendto(), and buf.

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

◆ rtp_allocate_transport()

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

Definition at line 4050 of file res_rtp_asterisk.c.

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

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

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

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

6480{
6481 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
6482}
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 6471 of file res_rtp_asterisk.c.

6473{
6474 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6475}

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

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

7679{
7680 uint16_t *seqno = (uint16_t *)data;
7682 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
7683 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
7684
7685 /* If the sequence number has cycled over then record it as such */
7686 if (((int)transport_rtp->transport_wide_cc.last_seqno - (int)ntohs(*seqno)) > 100) {
7687 transport_rtp->transport_wide_cc.cycles += RTP_SEQ_MOD;
7688 }
7689
7690 /* Populate the statistics information for this packet */
7691 statistics.seqno = transport_rtp->transport_wide_cc.cycles + ntohs(*seqno);
7692 statistics.received = ast_tvnow();
7693
7694 /* We allow at a maximum 1000 packet statistics in play at a time, if we hit the
7695 * limit we give up and start fresh.
7696 */
7697 if (AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) > 1000) {
7699 }
7700
7701 if (!AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) ||
7702 statistics.seqno > transport_rtp->transport_wide_cc.last_extended_seqno) {
7703 /* This is the expected path */
7705 return;
7706 }
7707
7708 transport_rtp->transport_wide_cc.last_extended_seqno = statistics.seqno;
7709 transport_rtp->transport_wide_cc.last_seqno = ntohs(*seqno);
7710 } else {
7711 /* This packet was out of order, so reorder it within the vector accordingly */
7714 return;
7715 }
7716 }
7717
7718 /* If we have not yet scheduled the periodic sending of feedback for this transport then do so */
7719 if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
7720 ast_debug_rtcp(1, "(%p) RTCP starting transport-cc feedback transmission on RTP instance '%p'\n", instance, transport);
7721 ao2_ref(transport, +1);
7722 transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
7724 if (transport_rtp->transport_wide_cc.schedid < 0) {
7725 ao2_ref(transport, -1);
7726 ast_log(LOG_WARNING, "Scheduling RTCP transport-cc feedback transmission failed on RTP instance '%p'\n",
7727 transport);
7728 }
7729 }
7730}
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 7407 of file res_rtp_asterisk.c.

7408{
7409 if (instance) {
7410 ao2_unlock(instance);
7411 }
7412}

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

3625{
3626 if (seq == (uint16_t) (info->max_seq + 1)) {
3627 /* packet is in sequence */
3628 info->packets--;
3629 } else {
3630 /* Sequence discontinuity; reset */
3631 info->packets = learning_min_sequential - 1;
3632 info->received = ast_tvnow();
3633 }
3634
3635 /* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */
3636 if (strictrtp == STRICT_RTP_YES) {
3637 switch (info->stream_type) {
3640 /*
3641 * Protect against packet floods by checking that we
3642 * received the packet sequence in at least the minimum
3643 * allowed time.
3644 */
3645 if (ast_tvzero(info->received)) {
3646 info->received = ast_tvnow();
3647 } else if (!info->packets
3649 /* Packet flood; reset */
3650 info->packets = learning_min_sequential - 1;
3651 info->received = ast_tvnow();
3652 }
3653 break;
3657 case AST_MEDIA_TYPE_END:
3658 break;
3659 }
3660 }
3661
3662 info->max_seq = seq;
3663
3664 return info->packets;
3665}
@ 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 3607 of file res_rtp_asterisk.c.

3608{
3609 info->max_seq = seq;
3610 info->packets = learning_min_sequential;
3611 memset(&info->received, 0, sizeof(info->received));
3612}

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

3673{
3675 memset(&rtp->rtp_source_learn.proposed_address, 0,
3676 sizeof(rtp->rtp_source_learn.proposed_address));
3678 rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t) rtp->lastrxseqno);
3679}

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

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

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

References __rtp_recvfrom(), and buf.

Referenced by ast_rtp_read().

◆ rtp_red_buffer()

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

Definition at line 9198 of file res_rtp_asterisk.c.

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

9167{
9168 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9169 int x;
9170
9171 rtp->red = ast_calloc(1, sizeof(*rtp->red));
9172 if (!rtp->red) {
9173 return -1;
9174 }
9175
9178 rtp->red->t140.data.ptr = &rtp->red->buf_data;
9179
9180 rtp->red->t140red = rtp->red->t140;
9181 rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
9182
9183 rtp->red->num_gen = generations;
9184 rtp->red->hdrlen = generations * 4 + 1;
9185
9186 for (x = 0; x < generations; x++) {
9187 rtp->red->pt[x] = payloads[x];
9188 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
9189 rtp->red->t140red_data[x*4] = rtp->red->pt[x];
9190 }
9191 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
9192 rtp->red->schedid = ast_sched_add(rtp->sched, buffer_time, red_write, instance);
9193
9194 return 0;
9195}
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 10027 of file res_rtp_asterisk.c.

10028{
10029 struct ast_config *cfg;
10030 const char *s;
10031 struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10032
10033#ifdef HAVE_PJPROJECT
10034 struct ast_variable *var;
10035 struct ast_ice_host_candidate *candidate;
10036 int acl_subscription_flag = 0;
10037#endif
10038
10039 cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
10040 if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
10041 return 0;
10042 }
10043
10044#ifdef SO_NO_CHECK
10045 nochecksums = 0;
10046#endif
10047
10056
10057 /** This resource is not "reloaded" so much as unloaded and loaded again.
10058 * In the case of the TURN related variables, the memory referenced by a
10059 * previously loaded instance *should* have been released when the
10060 * corresponding pool was destroyed. If at some point in the future this
10061 * resource were to support ACTUAL live reconfiguration and did NOT release
10062 * the pool this will cause a small memory leak.
10063 */
10064
10065#ifdef HAVE_PJPROJECT
10066 icesupport = DEFAULT_ICESUPPORT;
10067 stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE;
10068 turnport = DEFAULT_TURN_PORT;
10069 clean_stunaddr();
10070 turnaddr = pj_str(NULL);
10071 turnusername = pj_str(NULL);
10072 turnpassword = pj_str(NULL);
10073 host_candidate_overrides_clear();
10074#endif
10075
10076#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10077 dtls_mtu = DEFAULT_DTLS_MTU;
10078#endif
10079
10080 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
10081 rtpstart = atoi(s);
10086 }
10087 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
10088 rtpend = atoi(s);
10093 }
10094 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
10095 rtcpinterval = atoi(s);
10096 if (rtcpinterval == 0)
10097 rtcpinterval = 0; /* Just so we're clear... it's zero */
10099 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
10102 }
10103 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
10104#ifdef SO_NO_CHECK
10105 nochecksums = ast_false(s) ? 1 : 0;
10106#else
10107 if (ast_false(s))
10108 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10109#endif
10110 }
10111 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
10112 dtmftimeout = atoi(s);
10113 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
10114 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
10117 };
10118 }
10119 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
10120 if (ast_true(s)) {
10122 } else if (!strcasecmp(s, "seqno")) {
10124 } else {
10126 }
10127 }
10128 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
10129 if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
10130 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
10133 }
10135 }
10136 if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
10138 }
10139#ifdef HAVE_PJPROJECT
10140 if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
10141 icesupport = ast_true(s);
10142 }
10143 if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
10144 stun_software_attribute = ast_true(s);
10145 }
10146 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
10147 char *hostport, *host, *port;
10148 unsigned int port_parsed = STANDARD_STUN_PORT;
10149 struct ast_sockaddr stunaddr_parsed;
10150
10151 hostport = ast_strdupa(s);
10152
10153 if (!ast_parse_arg(hostport, PARSE_ADDR, &stunaddr_parsed)) {
10154 ast_debug_stun(3, "stunaddr = '%s' does not need name resolution\n",
10155 ast_sockaddr_stringify_host(&stunaddr_parsed));
10156 if (!ast_sockaddr_port(&stunaddr_parsed)) {
10157 ast_sockaddr_set_port(&stunaddr_parsed, STANDARD_STUN_PORT);
10158 }
10159 ast_rwlock_wrlock(&stunaddr_lock);
10160 ast_sockaddr_to_sin(&stunaddr_parsed, &stunaddr);
10161 ast_rwlock_unlock(&stunaddr_lock);
10162 } else if (ast_sockaddr_split_hostport(hostport, &host, &port, 0)) {
10163 if (port) {
10164 ast_parse_arg(port, PARSE_UINT32|PARSE_IN_RANGE, &port_parsed, 1, 65535);
10165 }
10166 stunaddr.sin_port = htons(port_parsed);
10167
10168 stunaddr_resolver = ast_dns_resolve_recurring(host, T_A, C_IN,
10169 &stunaddr_resolve_callback, NULL);
10170 if (!stunaddr_resolver) {
10171 ast_log(LOG_ERROR, "Failed to setup recurring DNS resolution of stunaddr '%s'",
10172 host);
10173 }
10174 } else {
10175 ast_log(LOG_ERROR, "Failed to parse stunaddr '%s'", hostport);
10176 }
10177 }
10178 if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
10179 struct sockaddr_in addr;
10180 addr.sin_port = htons(DEFAULT_TURN_PORT);
10181 if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
10182 ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
10183 } else {
10184 pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
10185 /* ntohs() is not a bug here. The port number is used in host byte order with
10186 * a pjnat API. */
10187 turnport = ntohs(addr.sin_port);
10188 }
10189 }
10190 if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
10191 pj_strdup2_with_null(pool, &turnusername, s);
10192 }
10193 if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
10194 pj_strdup2_with_null(pool, &turnpassword, s);
10195 }
10196
10197 AST_RWLIST_WRLOCK(&host_candidates);
10198 for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
10199 struct ast_sockaddr local_addr, advertised_addr;
10200 unsigned int include_local_address = 0;
10201 char *sep;
10202
10203 ast_sockaddr_setnull(&local_addr);
10204 ast_sockaddr_setnull(&advertised_addr);
10205
10206 if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
10207 ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
10208 continue;
10209 }
10210
10211 sep = strchr(var->value,',');
10212 if (sep) {
10213 *sep = '\0';
10214 sep++;
10215 sep = ast_skip_blanks(sep);
10216 include_local_address = strcmp(sep, "include_local_address") == 0;
10217 }
10218
10219 if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
10220 ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
10221 continue;
10222 }
10223
10224 if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
10225 ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
10226 break;
10227 }
10228
10229 candidate->include_local = include_local_address;
10230
10231 ast_sockaddr_copy(&candidate->local, &local_addr);
10232 ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
10233
10234 AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
10235 }
10236 AST_RWLIST_UNLOCK(&host_candidates);
10237
10238 ast_rwlock_wrlock(&ice_acl_lock);
10239 ast_rwlock_wrlock(&stun_acl_lock);
10240
10241 ice_acl = ast_free_acl_list(ice_acl);
10242 stun_acl = ast_free_acl_list(stun_acl);
10243
10244 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
10245 const char* sense = NULL;
10246 struct ast_acl_list **acl = NULL;
10247 if (strncasecmp(var->name, "ice_", 4) == 0) {
10248 sense = var->name + 4;
10249 acl = &ice_acl;
10250 } else if (strncasecmp(var->name, "stun_", 5) == 0) {
10251 sense = var->name + 5;
10252 acl = &stun_acl;
10253 } else {
10254 continue;
10255 }
10256
10257 if (strcasecmp(sense, "blacklist") == 0) {
10258 sense = "deny";
10259 }
10260
10261 if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
10262 continue;
10263 }
10264
10265 ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
10266 }
10267 ast_rwlock_unlock(&ice_acl_lock);
10268 ast_rwlock_unlock(&stun_acl_lock);
10269
10270 if (acl_subscription_flag && !acl_change_sub) {
10274 } else if (!acl_subscription_flag && acl_change_sub) {
10276 }
10277#endif
10278#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10279 if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
10280 if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
10281 ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
10283 dtls_mtu = DEFAULT_DTLS_MTU;
10284 }
10285 }
10286#endif
10287
10288 ast_config_destroy(cfg);
10289
10290 /* Choosing an odd start port casues issues (like a potential infinite loop) and as odd parts are not
10291 chosen anyway, we are going to round up and issue a warning */
10292 if (rtpstart & 1) {
10293 rtpstart++;
10294 ast_log(LOG_WARNING, "Odd start value for RTP port in rtp.conf, rounding up to %d\n", rtpstart);
10295 }
10296
10297 if (rtpstart >= rtpend) {
10298 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
10301 }
10302 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
10303 return 0;
10304}
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
#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
@ CONFIG_FLAG_FILEUNCHANGED
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:2235
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition utils.c:2252
char *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 3517 of file res_rtp_asterisk.c.

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

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

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

◆ rtp_transport_wide_cc_feedback_produce()

static int rtp_transport_wide_cc_feedback_produce ( const void *  data)
static

Definition at line 7490 of file res_rtp_asterisk.c.

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

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

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

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

7416{
7417 return a.seqno - b.seqno;
7418}
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 5436 of file res_rtp_asterisk.c.

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

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

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

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

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

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

10424{
10427
10428#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10429 if (dtls_bio_methods) {
10430 BIO_meth_free(dtls_bio_methods);
10431 }
10432#endif
10433
10434#ifdef HAVE_PJPROJECT
10435 host_candidate_overrides_clear();
10436 pj_thread_register_check();
10437 rtp_terminate_pjproject();
10438
10440 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10441 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10442 clean_stunaddr();
10443#endif
10444
10445 return 0;
10446}
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 6413 of file res_rtp_asterisk.c.

6414{
6416 rtp->rtcp->normdevrtt,
6417 rtp->rxjitter,
6418 rtp->rtcp->stdev_rxjitter,
6419 rtp->rtcp->normdev_rxlost);
6420
6421 if (rtp->rtcp->rxmes_count == 0) {
6422 rtp->rtcp->minrxmes = rtp->rxmes;
6423 }
6424 if (rtp->rxmes < rtp->rtcp->minrxmes) {
6425 rtp->rtcp->minrxmes = rtp->rxmes;
6426 }
6427 if (rtp->rxmes > rtp->rtcp->maxrxmes) {
6428 rtp->rtcp->maxrxmes = rtp->rxmes;
6429 }
6430
6432 &rtp->rtcp->stdev_rxmes, &rtp->rtcp->rxmes_count);
6433
6434 ast_debug_rtcp(2, " %s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6436 rtp->rtcp->normdevrtt,
6437 rtp->rxjitter,
6438 rtp->rtcp->stdev_rxjitter,
6439 rtp->rtcp->normdev_rxlost, rtp->rxmes);
6440}
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 6269 of file res_rtp_asterisk.c.

6270{
6271 double reported_lost;
6272
6273 rtp->rtcp->reported_lost = lost_packets;
6274 reported_lost = (double)rtp->rtcp->reported_lost;
6275 if (rtp->rtcp->reported_lost_count == 0) {
6276 rtp->rtcp->reported_minlost = reported_lost;
6277 }
6278 if (reported_lost < rtp->rtcp->reported_minlost) {
6279 rtp->rtcp->reported_minlost = reported_lost;
6280 }
6281 if (reported_lost > rtp->rtcp->reported_maxlost) {
6282 rtp->rtcp->reported_maxlost = reported_lost;
6283 }
6284
6287}
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 6378 of file res_rtp_asterisk.c.

6379{
6380 double mes = calc_media_experience_score(rtp->owner,
6381 rtp->rtcp->normdevrtt,
6382 rtp->rtcp->reported_jitter,
6385
6386 rtp->rtcp->reported_mes = mes;
6387 if (rtp->rtcp->reported_mes_count == 0) {
6388 rtp->rtcp->reported_minmes = mes;
6389 }
6390 if (mes < rtp->rtcp->reported_minmes) {
6391 rtp->rtcp->reported_minmes = mes;
6392 }
6393 if (mes > rtp->rtcp->reported_maxmes) {
6394 rtp->rtcp->reported_maxmes = mes;
6395 }
6396
6399
6400 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6402 rtp->rtcp->normdevrtt,
6403 rtp->rtcp->reported_jitter,
6405 rtp->rtcp->reported_normdev_lost, mes);
6406}
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 6188 of file res_rtp_asterisk.c.

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

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

10017 {
10018 AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
10019 AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
10020 AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
10021 AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
10022#ifdef AST_DEVMODE
10023 AST_CLI_DEFINE(handle_cli_rtp_drop_incoming_packets, "Drop RTP incoming packets"),
10024#endif
10025};
#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().