Asterisk - The Open Source Telephony Project GIT-master-4c84066
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
res_rtp_asterisk.c File Reference

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

#include "asterisk.h"
#include <arpa/nameser.h>
#include "asterisk/dns_core.h"
#include "asterisk/dns_internal.h"
#include "asterisk/dns_recurring.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <math.h>
#include "asterisk/conversions.h"
#include "asterisk/options.h"
#include "asterisk/logger_category.h"
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/smoother.h"
#include "asterisk/uuid.h"
#include "asterisk/test.h"
#include "asterisk/data_buffer.h"
Include dependency graph for res_rtp_asterisk.c:

Go to the source code of this file.

Data Structures

struct  ast_rtcp
 Structure defining an RTCP session. More...
 
struct  ast_rtp
 RTP session description. More...
 
struct  ast_rtp_rtcp_nack_payload
 Structure for storing RTP packets for retransmission. More...
 
struct  frame_list
 
struct  optional_ts
 
struct  rtp_learning_info
 RTP learning mode tracking information. More...
 
struct  rtp_red
 
struct  rtp_ssrc_mapping
 Structure used for mapping an incoming SSRC to an RTP instance. More...
 
struct  rtp_transport_wide_cc_packet_statistics
 Packet statistics (used for transport-cc) More...
 
struct  rtp_transport_wide_cc_statistics
 Statistics information (used for transport-cc) More...
 

Macros

#define CALC_LEARNING_MIN_DURATION(count)   (((count) - 1) * 9 - 5)
 Calculate the min learning duration in ms.
 
#define DEFAULT_DTLS_MTU   1200
 
#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
 
#define DEFAULT_ICESUPPORT   1
 
#define DEFAULT_LEARNING_MIN_DURATION   CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)
 
#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4
 
#define DEFAULT_RTP_END   31000
 
#define DEFAULT_RTP_RECV_BUFFER_SIZE   20
 
#define DEFAULT_RTP_SEND_BUFFER_SIZE   250
 
#define DEFAULT_RTP_START   5000
 
#define DEFAULT_SRTP_REPLAY_PROTECTION   1
 
#define DEFAULT_STRICT_RTP   STRICT_RTP_YES
 
#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE   1
 
#define DEFAULT_TURN_PORT   3478
 
#define FLAG_3389_WARNING   (1 << 0)
 
#define FLAG_DTMF_COMPENSATE   (1 << 4)
 
#define FLAG_NAT_ACTIVE   (3 << 1)
 
#define FLAG_NAT_INACTIVE   (0 << 1)
 
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
 
#define FLAG_NEED_MARKER_BIT   (1 << 3)
 
#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)
 
#define MAX_TIMESTAMP_SKEW   640
 
#define MAXIMUM_RTP_PORT   65535
 
#define MAXIMUM_RTP_RECV_BUFFER_SIZE   (DEFAULT_RTP_RECV_BUFFER_SIZE + 20)
 
#define MAXIMUM_RTP_SEND_BUFFER_SIZE   (DEFAULT_RTP_SEND_BUFFER_SIZE + 200)
 
#define MINIMUM_RTP_PORT   1024
 
#define MISSING_SEQNOS_ADDED_TRIGGER   2
 
#define OLD_PACKET_COUNT   1000
 
#define RESCALE(in, inmin, inmax, outmin, outmax)   ((((in - inmin)/(inmax-inmin))*(outmax-outmin))+outmin)
 
#define RTCP_DEFAULT_INTERVALMS   5000
 
#define RTCP_FB_NACK_BLOCK_WORD_LENGTH   2
 
#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4
 
#define RTCP_HEADER_SSRC_LENGTH   2
 
#define RTCP_LENGTH_MASK   0xFFFF
 
#define RTCP_LENGTH_SHIFT   0
 
#define RTCP_MAX_INTERVALMS   60000
 
#define RTCP_MIN_INTERVALMS   500
 
#define RTCP_PADDING_MASK   0x01
 
#define RTCP_PADDING_SHIFT   29
 
#define RTCP_PAYLOAD_TYPE_MASK   0xFF
 
#define RTCP_PAYLOAD_TYPE_SHIFT   16
 
#define RTCP_PT_APP   204
 
#define RTCP_PT_BYE   203
 
#define RTCP_PT_FUR   192
 
#define RTCP_PT_PSFB   AST_RTP_RTCP_PSFB
 
#define RTCP_PT_RR   AST_RTP_RTCP_RR
 
#define RTCP_PT_SDES   202
 
#define RTCP_PT_SR   AST_RTP_RTCP_SR
 
#define RTCP_REPORT_COUNT_MASK   0x1F
 
#define RTCP_REPORT_COUNT_SHIFT   24
 
#define RTCP_RR_BLOCK_WORD_LENGTH   6
 
#define RTCP_SR_BLOCK_WORD_LENGTH   5
 
#define RTCP_VALID_MASK   (RTCP_VERSION_MASK_SHIFTED | (((RTCP_PAYLOAD_TYPE_MASK & ~0x1)) << RTCP_PAYLOAD_TYPE_SHIFT))
 
#define RTCP_VALID_VALUE   (RTCP_VERSION_SHIFTED | (RTCP_PT_SR << RTCP_PAYLOAD_TYPE_SHIFT))
 
#define RTCP_VERSION   2U
 
#define RTCP_VERSION_MASK   0x03
 
#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)
 
#define RTCP_VERSION_SHIFT   30
 
#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)
 
#define RTP_DTLS_ESTABLISHED   -37
 
#define RTP_IGNORE_FIRST_PACKETS_COUNT   15
 
#define RTP_MTU   1200
 
#define RTP_SEQ_MOD   (1<<16)
 
#define SEQNO_CYCLE_OVER   65536
 
#define SRTP_MASTER_KEY_LEN   16
 
#define SRTP_MASTER_LEN   (SRTP_MASTER_KEY_LEN + SRTP_MASTER_SALT_LEN)
 
#define SRTP_MASTER_SALT_LEN   14
 
#define SSRC_MAPPING_ELEM_CMP(elem, value)   ((elem).instance == (value))
 SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()
 
#define STRICT_RTP_LEARN_TIMEOUT   5000
 Strict RTP learning timeout time in milliseconds.
 
#define TRANSPORT_SOCKET_RTCP   1
 
#define TRANSPORT_SOCKET_RTP   0
 
#define TRANSPORT_TURN_RTCP   3
 
#define TRANSPORT_TURN_RTP   2
 
#define TURN_STATE_WAIT_TIME   2000
 
#define ZFONE_PROFILE_ID   0x505a
 

Enumerations

enum  strict_rtp_mode { STRICT_RTP_NO = 0 , STRICT_RTP_YES , STRICT_RTP_SEQNO }
 
enum  strict_rtp_state { STRICT_RTP_OPEN = 0 , STRICT_RTP_LEARN , STRICT_RTP_CLOSED }
 

Functions

static void __reg_module (void)
 
static struct ast_rtp_instance__rtp_find_instance_by_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc, int source)
 
static int __rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
 
static int __rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *via_ice, int use_srtp)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
 
static int ast_rtcp_calculate_sr_rr_statistics (struct ast_rtp_instance *instance, struct ast_rtp_rtcp_report *rtcp_report, struct ast_sockaddr remote_address, int ice, int sr)
 
static int ast_rtcp_generate_compound_prefix (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
 
static int ast_rtcp_generate_nack (struct ast_rtp_instance *instance, unsigned char *rtcpheader)
 
static int ast_rtcp_generate_report (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report, int *sr)
 
static int ast_rtcp_generate_sdes (struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *rtcp_report)
 
static struct ast_frameast_rtcp_interpret (struct ast_rtp_instance *instance, struct ast_srtp *srtp, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
 
static struct ast_frameast_rtcp_read (struct ast_rtp_instance *instance)
 
static int ast_rtcp_write (const void *data)
 Write a RTCP packet to the far end.
 
static int ast_rtp_bundle (struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
 
static void ast_rtp_change_source (struct ast_rtp_instance *instance)
 
static int ast_rtp_destroy (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_begin (struct ast_rtp_instance *instance, char digit)
 
static int ast_rtp_dtmf_compatible (struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
 
static int ast_rtp_dtmf_continuation (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_end (struct ast_rtp_instance *instance, char digit)
 
static int ast_rtp_dtmf_end_with_duration (struct ast_rtp_instance *instance, char digit, unsigned int duration)
 
static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get (struct ast_rtp_instance *instance)
 
static int ast_rtp_dtmf_mode_set (struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
 
static int ast_rtp_extension_enable (struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
 
static int ast_rtp_fd (struct ast_rtp_instance *instance, int rtcp)
 
static const char * ast_rtp_get_cname (struct ast_rtp_instance *instance)
 
static unsigned int ast_rtp_get_ssrc (struct ast_rtp_instance *instance)
 
static int ast_rtp_get_stat (struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
 
static struct ast_frameast_rtp_interpret (struct ast_rtp_instance *instance, struct ast_srtp *srtp, const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno, unsigned int bundled)
 
static int ast_rtp_local_bridge (struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
 
static int ast_rtp_new (struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
 
static void ast_rtp_prop_set (struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
 
static int ast_rtp_qos_set (struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
 
static struct ast_frameast_rtp_read (struct ast_rtp_instance *instance, int rtcp)
 
static void ast_rtp_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
 
static int ast_rtp_rtcp_handle_nack (struct ast_rtp_instance *instance, unsigned int *nackdata, unsigned int position, unsigned int length)
 
static int ast_rtp_sendcng (struct ast_rtp_instance *instance, int level)
 generate comfort noice (CNG)
 
static void ast_rtp_set_remote_ssrc (struct ast_rtp_instance *instance, unsigned int ssrc)
 
static void ast_rtp_set_stream_num (struct ast_rtp_instance *instance, int stream_num)
 
static void ast_rtp_stop (struct ast_rtp_instance *instance)
 
static void ast_rtp_stun_request (struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
 
static void ast_rtp_update_source (struct ast_rtp_instance *instance)
 
static int ast_rtp_write (struct ast_rtp_instance *instance, struct ast_frame *frame)
 
static int bridge_p2p_rtp_write (struct ast_rtp_instance *instance, struct ast_rtp_instance *instance1, unsigned int *rtpheader, int len, int hdrlen)
 
static void calc_mean_and_standard_deviation (double new_sample, double *mean, double *std_dev, unsigned int *count)
 
static double calc_media_experience_score (struct ast_rtp_instance *instance, double normdevrtt, double normdev_rxjitter, double stdev_rxjitter, double normdev_rxlost)
 Calculate a "media experience score" based on given data.
 
static void calc_rxstamp_and_jitter (struct timeval *tv, struct ast_rtp *rtp, unsigned int rx_rtp_ts, int mark)
 
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
 
static void calculate_lost_packet_statistics (struct ast_rtp *rtp, unsigned int *lost_packets, int *fraction_lost)
 
static int compare_by_value (int elem, int value)
 Helper function to compare an elem in a vector by value.
 
static struct ast_framecreate_dtmf_frame (struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
 
static int create_new_socket (const char *type, struct ast_sockaddr *bind_addr)
 
static int find_by_value (int elem, int value)
 Helper function to find an elem in a vector by value.
 
static char * handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_rtp_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int load_module (void)
 
static void ntp2timeval (unsigned int msw, unsigned int lsw, struct timeval *tv)
 
static struct ast_frameprocess_cn_rfc3389 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
 
static struct ast_frameprocess_dtmf_cisco (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
 
static void process_dtmf_rfc2833 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark, struct frame_list *frames)
 
static void put_unaligned_time24 (void *p, uint32_t time_msw, uint32_t time_lsw)
 
static struct ast_framered_t140_to_red (struct rtp_red *red)
 
static int red_write (const void *data)
 Write t140 redundancy frame.
 
static int reload_module (void)
 
static int rtcp_debug_test_addr (struct ast_sockaddr *addr)
 
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
 
static int rtcp_mux (struct ast_rtp *rtp, const unsigned char *packet)
 
static const char * rtcp_payload_subtype2str (unsigned int pt, unsigned int subtype)
 
static const char * rtcp_payload_type2str (unsigned int pt)
 
static int rtcp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
 
static int rtcp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 
static int rtp_allocate_transport (struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 
static void rtp_deallocate_transport (struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 
static int rtp_debug_test_addr (struct ast_sockaddr *addr)
 
static char * rtp_do_debug_ip (struct ast_cli_args *a)
 
static struct ast_rtp_instancertp_find_instance_by_media_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
 
static struct ast_rtp_instancertp_find_instance_by_packet_source_ssrc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
 
static void rtp_instance_parse_extmap_extensions (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *extension, int len)
 
static void rtp_instance_parse_transport_wide_cc (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *data, int len)
 
static void rtp_instance_unlock (struct ast_rtp_instance *instance)
 
static int rtp_learning_rtp_seq_update (struct rtp_learning_info *info, uint16_t seq)
 
static void rtp_learning_seq_init (struct rtp_learning_info *info, uint16_t seq)
 
static void rtp_learning_start (struct ast_rtp *rtp)
 Start the strictrtp learning mode.
 
static int rtp_raw_write (struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
 
static int rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
 
static int rtp_red_buffer (struct ast_rtp_instance *instance, struct ast_frame *frame)
 
static int rtp_red_init (struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
 
static int rtp_reload (int reload, int by_external_config)
 
static int rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 
static int rtp_transport_wide_cc_feedback_produce (const void *data)
 
static void rtp_transport_wide_cc_feedback_status_append (unsigned char *rtcpheader, int *packet_len, int *status_vector_chunk_bits, uint16_t *status_vector_chunk, int *run_length_chunk_count, int *run_length_chunk_status, int status)
 
static void rtp_transport_wide_cc_feedback_status_vector_append (unsigned char *rtcpheader, int *packet_len, int *status_vector_chunk_bits, uint16_t *status_vector_chunk, int status)
 
static int rtp_transport_wide_cc_packet_statistics_cmp (struct rtp_transport_wide_cc_packet_statistics a, struct rtp_transport_wide_cc_packet_statistics b)
 
static void rtp_write_rtcp_fir (struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)
 
static void rtp_write_rtcp_psfb (struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_frame *frame, struct ast_sockaddr *remote_address)
 
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)
 
static int unload_module (void)
 
static void update_jitter_stats (struct ast_rtp *rtp, unsigned int ia_jitter)
 
static void update_local_mes_stats (struct ast_rtp *rtp)
 
static void update_lost_stats (struct ast_rtp *rtp, unsigned int lost_packets)
 
static void update_reported_mes_stats (struct ast_rtp *rtp)
 
static int update_rtt_stats (struct ast_rtp *rtp, unsigned int lsr, unsigned int dlsr)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, #ifdef HAVE_PJPROJECT .requires = "res_pjproject", #endif }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_rtp_engine asterisk_rtp_engine
 
static struct ast_cli_entry cli_rtp []
 
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
 
static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION
 
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL
 
struct ast_srtp_resres_srtp
 
struct ast_srtp_policy_resres_srtp_policy
 
static struct ast_sockaddr rtcpdebugaddr
 
static int rtcpdebugport
 
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
 
static int rtcpstats
 
static struct ast_sockaddr rtpdebugaddr
 
static int rtpdebugport
 
static int rtpend = DEFAULT_RTP_END
 
static int rtpstart = DEFAULT_RTP_START
 
static int srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION
 
static int strictrtp = DEFAULT_STRICT_RTP
 

Detailed Description

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

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

Definition in file res_rtp_asterisk.c.

Macro Definition Documentation

◆ CALC_LEARNING_MIN_DURATION

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

Calculate the min learning duration in ms.

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

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

Definition at line 159 of file res_rtp_asterisk.c.

◆ DEFAULT_DTLS_MTU

#define DEFAULT_DTLS_MTU   1200

Definition at line 193 of file res_rtp_asterisk.c.

◆ DEFAULT_DTMF_TIMEOUT

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

samples

Definition at line 142 of file res_rtp_asterisk.c.

◆ DEFAULT_ICESUPPORT

#define DEFAULT_ICESUPPORT   1

Definition at line 191 of file res_rtp_asterisk.c.

◆ DEFAULT_LEARNING_MIN_DURATION

#define DEFAULT_LEARNING_MIN_DURATION   CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)

Definition at line 160 of file res_rtp_asterisk.c.

◆ DEFAULT_LEARNING_MIN_SEQUENTIAL

#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4

Definition at line 146 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_END

#define DEFAULT_RTP_END   31000

Default maximum port number to end allocating RTP ports at

Definition at line 106 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_RECV_BUFFER_SIZE

#define DEFAULT_RTP_RECV_BUFFER_SIZE   20

The initial size of the RTP receiver buffer

Definition at line 117 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_SEND_BUFFER_SIZE

#define DEFAULT_RTP_SEND_BUFFER_SIZE   250

The initial size of the RTP send buffer

Definition at line 115 of file res_rtp_asterisk.c.

◆ DEFAULT_RTP_START

#define DEFAULT_RTP_START   5000

Default port number to start allocating RTP ports from

Definition at line 105 of file res_rtp_asterisk.c.

◆ DEFAULT_SRTP_REPLAY_PROTECTION

#define DEFAULT_SRTP_REPLAY_PROTECTION   1

Definition at line 190 of file res_rtp_asterisk.c.

◆ DEFAULT_STRICT_RTP

#define DEFAULT_STRICT_RTP   STRICT_RTP_YES

Enabled by default

Definition at line 189 of file res_rtp_asterisk.c.

◆ DEFAULT_STUN_SOFTWARE_ATTRIBUTE

#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE   1

Definition at line 192 of file res_rtp_asterisk.c.

◆ DEFAULT_TURN_PORT

#define DEFAULT_TURN_PORT   3478

Definition at line 111 of file res_rtp_asterisk.c.

◆ FLAG_3389_WARNING

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 308 of file res_rtp_asterisk.c.

◆ FLAG_DTMF_COMPENSATE

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 313 of file res_rtp_asterisk.c.

◆ FLAG_NAT_ACTIVE

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 309 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 310 of file res_rtp_asterisk.c.

◆ FLAG_NAT_INACTIVE_NOWARN

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 311 of file res_rtp_asterisk.c.

◆ FLAG_NEED_MARKER_BIT

#define FLAG_NEED_MARKER_BIT   (1 << 3)

Definition at line 312 of file res_rtp_asterisk.c.

◆ FLAG_REQ_LOCAL_BRIDGE_BIT

#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)

Definition at line 314 of file res_rtp_asterisk.c.

◆ MAX_TIMESTAMP_SKEW

#define MAX_TIMESTAMP_SKEW   640

Definition at line 98 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_PORT

#define MAXIMUM_RTP_PORT   65535

Maximum port number to accept

Definition at line 109 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_RECV_BUFFER_SIZE

#define MAXIMUM_RTP_RECV_BUFFER_SIZE   (DEFAULT_RTP_RECV_BUFFER_SIZE + 20)

Maximum RTP receive buffer size

Definition at line 118 of file res_rtp_asterisk.c.

◆ MAXIMUM_RTP_SEND_BUFFER_SIZE

#define MAXIMUM_RTP_SEND_BUFFER_SIZE   (DEFAULT_RTP_SEND_BUFFER_SIZE + 200)

Maximum RTP send buffer size

Definition at line 116 of file res_rtp_asterisk.c.

◆ MINIMUM_RTP_PORT

#define MINIMUM_RTP_PORT   1024

Minimum port number to accept

Definition at line 108 of file res_rtp_asterisk.c.

◆ MISSING_SEQNOS_ADDED_TRIGGER

#define MISSING_SEQNOS_ADDED_TRIGGER   2

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

Definition at line 120 of file res_rtp_asterisk.c.

◆ OLD_PACKET_COUNT

#define OLD_PACKET_COUNT   1000

The number of previous packets that are considered old

Definition at line 119 of file res_rtp_asterisk.c.

◆ RESCALE

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

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

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6778 of file res_rtp_asterisk.c.

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6777 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6742 of file res_rtp_asterisk.c.

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

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

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6754 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6743 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

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

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6753 of file res_rtp_asterisk.c.

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6776 of file res_rtp_asterisk.c.

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6775 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 6772 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 6773 of file res_rtp_asterisk.c.

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6757 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6746 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6759 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6755 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6758 of file res_rtp_asterisk.c.

◆ RTP_DTLS_ESTABLISHED

#define RTP_DTLS_ESTABLISHED   -37

Definition at line 166 of file res_rtp_asterisk.c.

◆ RTP_IGNORE_FIRST_PACKETS_COUNT

#define RTP_IGNORE_FIRST_PACKETS_COUNT   15

Because both ends usually don't start sending RTP at the same time, some of the calculations like rtt and jitter will probably be unstable for a while so we'll skip some received packets before starting analyzing. This just affects analyzing; we still process the RTP as normal.

Definition at line 203 of file res_rtp_asterisk.c.

◆ RTP_MTU

#define RTP_MTU   1200

Definition at line 140 of file res_rtp_asterisk.c.

◆ RTP_SEQ_MOD

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 100 of file res_rtp_asterisk.c.

◆ SEQNO_CYCLE_OVER

#define SEQNO_CYCLE_OVER   65536

The number after the maximum allowed sequence number

Definition at line 122 of file res_rtp_asterisk.c.

◆ SRTP_MASTER_KEY_LEN

#define SRTP_MASTER_KEY_LEN   16

Definition at line 162 of file res_rtp_asterisk.c.

◆ SRTP_MASTER_LEN

#define SRTP_MASTER_LEN   (SRTP_MASTER_KEY_LEN + SRTP_MASTER_SALT_LEN)

Definition at line 164 of file res_rtp_asterisk.c.

◆ SRTP_MASTER_SALT_LEN

#define SRTP_MASTER_SALT_LEN   14

Definition at line 163 of file res_rtp_asterisk.c.

◆ SSRC_MAPPING_ELEM_CMP

#define SSRC_MAPPING_ELEM_CMP (   elem,
  value 
)    ((elem).instance == (value))

SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()

Parameters
elemElement to compare against
valueValue to compare with the vector element.
Return values
0if element does not match.
Non-zeroif element matches.

Definition at line 4375 of file res_rtp_asterisk.c.

◆ STRICT_RTP_LEARN_TIMEOUT

#define STRICT_RTP_LEARN_TIMEOUT   5000

Strict RTP learning timeout time in milliseconds.

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

Definition at line 187 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTCP

#define TRANSPORT_SOCKET_RTCP   1

Definition at line 317 of file res_rtp_asterisk.c.

◆ TRANSPORT_SOCKET_RTP

#define TRANSPORT_SOCKET_RTP   0

Definition at line 316 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTCP

#define TRANSPORT_TURN_RTCP   3

Definition at line 319 of file res_rtp_asterisk.c.

◆ TRANSPORT_TURN_RTP

#define TRANSPORT_TURN_RTP   2

Definition at line 318 of file res_rtp_asterisk.c.

◆ TURN_STATE_WAIT_TIME

#define TURN_STATE_WAIT_TIME   2000

Definition at line 113 of file res_rtp_asterisk.c.

◆ ZFONE_PROFILE_ID

#define ZFONE_PROFILE_ID   0x505a

Definition at line 144 of file res_rtp_asterisk.c.

Enumeration Type Documentation

◆ strict_rtp_mode

Enumerator
STRICT_RTP_NO 
STRICT_RTP_YES 

Don't adhere to any strict RTP rules

STRICT_RTP_SEQNO 

Strict RTP that restricts packets based on time and sequence number

Definition at line 174 of file res_rtp_asterisk.c.

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

◆ strict_rtp_state

Enumerator
STRICT_RTP_OPEN 
STRICT_RTP_LEARN 

No RTP packets should be dropped, all sources accepted

STRICT_RTP_CLOSED 

Accept next packet as source

Definition at line 168 of file res_rtp_asterisk.c.

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

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

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

6552{
6553 int index;
6554
6555 if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
6556 /* This instance is not bundled */
6557 return instance;
6558 }
6559
6560 /* Find the bundled child instance */
6561 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
6562 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
6563 unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
6564
6565 if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
6566 return mapping->instance;
6567 }
6568 }
6569
6570 /* Does the SSRC match the bundled parent? */
6571 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
6572 return instance;
6573 }
6574 return NULL;
6575}
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 3236 of file res_rtp_asterisk.c.

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

References ao2_lock, ao2_ref, ao2_unlock, ast_debug_dtls, ast_log, ast_recvfrom(), AST_RTP_DTLS_CONNECTION_EXISTING, AST_RTP_DTLS_SETUP_ACTPASS, AST_RTP_DTLS_SETUP_PASSIVE, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_instance_set_remote_address, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_pj_sockaddr_cmp(), ast_sockaddr_stringify(), buf, error(), in, len(), LOG_ERROR, LOG_WARNING, ast_rtp::rtcp, RTP_DTLS_ESTABLISHED, ast_rtp::s, ast_rtcp::s, status, ast_rtcp::them, TRANSPORT_SOCKET_RTCP, and TRANSPORT_SOCKET_RTP.

Referenced by rtcp_recvfrom(), and rtp_recvfrom().

◆ __rtp_sendto()

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

Definition at line 3464 of file res_rtp_asterisk.c.

3465{
3466 int len = size;
3467 void *temp = buf;
3468 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3469 struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
3470 struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
3471 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(transport, rtcp);
3472 int res;
3473#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3474 char *out = buf;
3475 struct dtls_details *dtls = (!rtcp || rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_MUX) ? &rtp->dtls : &rtp->rtcp->dtls;
3476
3477 /* Don't send RTP if DTLS hasn't finished yet */
3478 if (dtls->ssl && ((*out < 20) || (*out > 63)) && dtls->connection == AST_RTP_DTLS_CONNECTION_NEW) {
3479 *via_ice = 0;
3480 return 0;
3481 }
3482#endif
3483
3484 *via_ice = 0;
3485
3486 if (use_srtp && res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
3487 return -1;
3488 }
3489
3490#ifdef HAVE_PJPROJECT
3491 if (transport_rtp->ice) {
3493 pj_status_t status;
3494 struct ice_wrap *ice;
3495
3496 /* If RTCP is sharing the same socket then use the same component */
3497 if (rtcp && rtp->rtcp->s == rtp->s) {
3498 component = AST_RTP_ICE_COMPONENT_RTP;
3499 }
3500
3501 pj_thread_register_check();
3502
3503 /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3504 ice = transport_rtp->ice;
3505 ao2_ref(ice, +1);
3506 if (instance == transport) {
3507 ao2_unlock(instance);
3508 }
3509 status = pj_ice_sess_send_data(ice->real_ice, component, temp, len);
3510 ao2_ref(ice, -1);
3511 if (instance == transport) {
3512 ao2_lock(instance);
3513 }
3514 if (status == PJ_SUCCESS) {
3515 *via_ice = 1;
3516 return len;
3517 }
3518 }
3519#endif
3520
3521 res = ast_sendto(rtcp ? transport_rtp->rtcp->s : transport_rtp->s, temp, len, flags, sa);
3522 if (res > 0) {
3523 ast_rtp_instance_set_last_tx(instance, time(NULL));
3524 }
3525
3526 return res;
3527}
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition netsock2.c:614
struct ast_srtp_res * res_srtp
Definition rtp_engine.c:182
ast_rtp_ice_component_type
ICE component types.
Definition rtp_engine.h:513
@ AST_RTP_INSTANCE_RTCP_MUX
Definition rtp_engine.h:289
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP transmission time.
@ AST_RTP_DTLS_CONNECTION_NEW
Definition rtp_engine.h:573
enum ast_rtp_instance_rtcp type
struct ast_rtp_instance * bundled
int(* protect)(struct ast_srtp *srtp, void **buf, int *size, int rtcp)
Definition res_srtp.h:50
FILE * out
Definition utils/frame.c:33

References ao2_lock, ao2_ref, ao2_unlock, AST_RTP_DTLS_CONNECTION_NEW, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), AST_RTP_INSTANCE_RTCP_MUX, ast_rtp_instance_set_last_tx(), ast_sendto(), buf, ast_rtp::bundled, len(), NULL, out, ast_srtp_res::protect, res_srtp, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, status, and ast_rtcp::type.

Referenced by rtcp_sendto(), and rtp_sendto().

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 10681 of file res_rtp_asterisk.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 10681 of file res_rtp_asterisk.c.

◆ ast_rtcp_calc_interval()

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

Definition at line 3550 of file res_rtp_asterisk.c.

3551{
3552 unsigned int interval;
3553 /*! \todo XXX Do a more reasonable calculation on this one
3554 * Look in RFC 3550 Section A.7 for an example*/
3555 interval = rtcpinterval;
3556 return interval;
3557}
static int rtcpinterval

References rtcpinterval.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

◆ ast_rtcp_calculate_sr_rr_statistics()

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

Definition at line 4959 of file res_rtp_asterisk.c.

4961{
4962 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4963 struct ast_rtp_rtcp_report_block *report_block = NULL;
4964 RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
4965
4966 if (!rtp || !rtp->rtcp) {
4967 return 0;
4968 }
4969
4970 if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4971 return 0;
4972 }
4973
4974 if (!rtcp_report) {
4975 return -1;
4976 }
4977
4978 report_block = rtcp_report->report_block[0];
4979
4980 if (sr) {
4981 rtp->rtcp->txlsr = rtcp_report->sender_information.ntp_timestamp;
4982 rtp->rtcp->sr_count++;
4983 rtp->rtcp->lastsrtxcount = rtp->txcount;
4984 } else {
4985 rtp->rtcp->rr_count++;
4986 }
4987
4988 if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
4989 ast_verbose("* Sent RTCP %s to %s%s\n", sr ? "SR" : "RR",
4990 ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
4991 ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
4992 if (sr) {
4993 ast_verbose(" Sent(NTP): %u.%06u\n",
4994 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
4995 (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
4996 ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
4997 ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
4998 ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
4999 }
5000 if (report_block) {
5001 int rate = ast_rtp_get_rate(rtp->f.subclass.format);
5002 ast_verbose(" Report block:\n");
5003 ast_verbose(" Their SSRC: %u\n", report_block->source_ssrc);
5004 ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
5005 ast_verbose(" Cumulative loss: %u\n", report_block->lost_count.packets);
5006 ast_verbose(" Highest seq no: %u\n", report_block->highest_seq_no);
5007 ast_verbose(" IA jitter (samp): %u\n", report_block->ia_jitter);
5008 ast_verbose(" IA jitter (secs): %.6f\n", ast_samp2sec(report_block->ia_jitter, rate));
5009 ast_verbose(" Their last SR: %u\n", report_block->lsr);
5010 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
5011 }
5012 }
5013
5014 message_blob = ast_json_pack("{s: s, s: s, s: f}",
5015 "to", ast_sockaddr_stringify(&remote_address),
5016 "from", rtp->rtcp->local_addr_str,
5017 "mes", rtp->rxmes);
5018
5020 rtcp_report, message_blob);
5021
5022 return 1;
5023}
struct stasis_message_type * ast_rtp_rtcp_sent_type(void)
Message type for an RTCP message sent from this Asterisk instance.
#define ast_verbose(...)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
static int rtcp_debug_test_addr(struct ast_sockaddr *addr)
void ast_rtp_publish_rtcp_message(struct ast_rtp_instance *rtp, struct stasis_message_type *message_type, struct ast_rtp_rtcp_report *report, struct ast_json *blob)
Publish an RTCP message to Stasis Message Bus API.
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
struct ast_format * format
struct ast_frame_subclass subclass
Abstract JSON element (object, array, string, int, ...).
unsigned int sr_count
unsigned int lastsrtxcount
struct timeval txlsr
unsigned int rr_count
char * local_addr_str
A report block within a SR/RR report.
Definition rtp_engine.h:346
unsigned int highest_seq_no
Definition rtp_engine.h:352
unsigned short fraction
Definition rtp_engine.h:349
struct ast_rtp_rtcp_report_block::@287 lost_count
struct ast_rtp_rtcp_report::@288 sender_information
unsigned int rtp_timestamp
Definition rtp_engine.h:367
struct ast_rtp_rtcp_report_block * report_block[0]
Definition rtp_engine.h:374
struct timeval ntp_timestamp
Definition rtp_engine.h:366
unsigned int octet_count
Definition rtp_engine.h:369
unsigned int ssrc
Definition rtp_engine.h:363
unsigned int packet_count
Definition rtp_engine.h:368
struct ast_frame f
unsigned int txcount
double ast_samp2sec(unsigned int _nsamp, unsigned int _rate)
Returns the duration in seconds of _nsamp samples at rate _rate.
Definition time.h:316
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ast_json_pack(), ast_json_unref(), ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_publish_rtcp_message(), ast_rtp_rtcp_sent_type(), ast_samp2sec(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, ast_rtp_rtcp_report_block::dlsr, ast_rtp::f, ast_frame_subclass::format, ast_rtp_rtcp_report_block::fraction, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, ast_rtcp::lastsrtxcount, ast_rtcp::local_addr_str, ast_rtp_rtcp_report_block::lost_count, ast_rtp_rtcp_report_block::lsr, ast_rtp_rtcp_report::ntp_timestamp, NULL, ast_rtp_rtcp_report::octet_count, ast_rtp_rtcp_report::packet_count, ast_rtp_rtcp_report_block::packets, RAII_VAR, ast_rtp_rtcp_report::report_block, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtp_rtcp_report::rtp_timestamp, ast_rtp::rxmes, ast_rtp_rtcp_report::sender_information, ast_rtp_rtcp_report_block::source_ssrc, ast_rtcp::sr_count, ast_rtp_rtcp_report::ssrc, ast_frame::subclass, ast_rtcp::them, ast_rtp::txcount, and ast_rtcp::txlsr.

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

◆ ast_rtcp_generate_compound_prefix()

static int ast_rtcp_generate_compound_prefix ( struct ast_rtp_instance instance,
unsigned char *  rtcpheader,
struct ast_rtp_rtcp_report report,
int *  sr 
)
static

Definition at line 5083 of file res_rtp_asterisk.c.

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

References ast_debug_rtcp, ast_rtcp_generate_report(), and ast_rtcp_generate_sdes().

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

◆ ast_rtcp_generate_nack()

static int ast_rtcp_generate_nack ( struct ast_rtp_instance instance,
unsigned char *  rtcpheader 
)
static

Definition at line 5113 of file res_rtp_asterisk.c.

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

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

References ast_calloc, ast_rtp_instance_get_data(), ast_sockaddr_isnull(), ast_tvzero(), calculate_lost_packet_statistics(), ast_rtp::cycles, ast_rtp_rtcp_report_block::dlsr, ast_rtp_rtcp_report_block::fraction, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), ast_rtp_rtcp_report_block::lost_count, ast_rtp_rtcp_report_block::lsr, ast_rtp_rtcp_report::ntp_timestamp, NULL, ast_rtp_rtcp_report::octet_count, ast_rtp_rtcp_report::packet_count, ast_rtp_rtcp_report_block::packets, put_unaligned_uint32(), ast_rtp_rtcp_report::reception_report_count, ast_rtp_rtcp_report::report_block, ast_rtp::rtcp, RTCP_PT_RR, RTCP_PT_SR, ast_rtp_rtcp_report::rtp_timestamp, ast_rtp::rxjitter_samples, ast_rtcp::rxlsr, ast_rtp_rtcp_report::sender_information, ast_rtp_rtcp_report_block::source_ssrc, ast_rtp_rtcp_report::ssrc, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, ast_rtp::themssrc_valid, timersub(), timeval2ntp(), ast_rtp::txcount, ast_rtp::txoctetcount, ast_rtp_rtcp_report::type, and update_local_mes_stats().

Referenced by ast_rtcp_generate_compound_prefix().

◆ ast_rtcp_generate_sdes()

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

Definition at line 5025 of file res_rtp_asterisk.c.

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

References ast_rtp_instance_get_data(), ast_sockaddr_isnull(), AST_UUID_STR_LEN, ast_rtp::cname, len(), put_unaligned_uint32(), ast_rtp::rtcp, RTCP_PT_SDES, ast_rtp_rtcp_report::ssrc, and ast_rtcp::them.

Referenced by ast_rtcp_generate_compound_prefix().

◆ ast_rtcp_interpret()

static struct ast_frame * ast_rtcp_interpret ( struct ast_rtp_instance instance,
struct ast_srtp srtp,
const unsigned char *  rtcpdata,
size_t  size,
struct ast_sockaddr addr 
)
static

True if we have seen an acceptable SSRC to learn the remote RTCP address

True if the ssrc value we have is valid and not garbage because it doesn't exist.

Always use packet source SSRC to find the rtp instance unless explicitly told not to.

Definition at line 6781 of file res_rtp_asterisk.c.

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

References ao2_cleanup, ao2_lock, ao2_unlock, ast_calloc, AST_CONTROL_VIDUPDATE, ast_debug, ast_debug_rtcp, ast_debug_rtp_packet_is_allowed, AST_FRAME_CONTROL, AST_FRAME_RTCP, AST_FRIENDLY_OFFSET, ast_json_pack(), ast_json_unref(), ast_null_frame, ast_rtp_get_rate(), ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_NAT, AST_RTP_PROPERTY_REMB, ast_rtp_publish_rtcp_message(), AST_RTP_RTCP_FMT_FIR, AST_RTP_RTCP_FMT_NACK, AST_RTP_RTCP_FMT_PLI, AST_RTP_RTCP_FMT_REMB, ast_rtp_rtcp_handle_nack(), ast_rtp_rtcp_received_type(), ast_rtp_rtcp_report_alloc(), AST_RTP_RTCP_RTPFB, ast_samp2sec(), ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_verbose, ast_rtp_rtcp_feedback_remb::br_exp, ast_rtp_rtcp_feedback_remb::br_mantissa, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp_rtcp_report_block::dlsr, ast_rtp::f, ast_rtp_rtcp_feedback::fmt, ast_frame_subclass::format, ast_rtp_rtcp_report_block::fraction, ast_rtcp::frame_buf, ast_frame::frametype, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, ast_frame_subclass::integer, len(), ast_rtcp::local_addr_str, ast_rtp_rtcp_report_block::lost_count, ast_rtp_rtcp_report_block::lsr, ast_frame::mallocd, ntp2timeval(), NULL, ast_frame::offset, ast_rtp_rtcp_report_block::packets, ast_frame::ptr, RAII_VAR, ast_rtp_rtcp_feedback::remb, ast_rtp_rtcp_report::report_block, ast_rtcp::reported_mes, res_srtp, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_FB_NACK_BLOCK_WORD_LENGTH, RTCP_FB_REMB_BLOCK_WORD_LENGTH, RTCP_HEADER_SSRC_LENGTH, ast_rtcp::rtcp_info, RTCP_LENGTH_MASK, RTCP_LENGTH_SHIFT, rtcp_payload_subtype2str(), rtcp_payload_type2str(), RTCP_PAYLOAD_TYPE_MASK, RTCP_PAYLOAD_TYPE_SHIFT, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_PSFB, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, RTCP_REPORT_COUNT_MASK, RTCP_REPORT_COUNT_SHIFT, RTCP_RR_BLOCK_WORD_LENGTH, RTCP_SR_BLOCK_WORD_LENGTH, RTCP_VALID_MASK, RTCP_VALID_VALUE, RTCP_VERSION_MASK_SHIFTED, RTCP_VERSION_SHIFTED, rtp_find_instance_by_media_source_ssrc(), rtp_find_instance_by_packet_source_ssrc(), ast_rtcp::rtt, ast_rtcp::rxlsr, ast_frame::samples, ast_rtp::send_buffer, ast_rtcp::soc, ast_rtp_rtcp_report_block::source_ssrc, ast_rtcp::spc, ast_frame::src, srtp_replay_protection, ast_frame::stream_num, ast_rtp::stream_num, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, ast_rtp::themssrc_valid, timeval2ntp(), ast_srtp_res::unprotect, update_jitter_stats(), update_lost_stats(), update_reported_mes_stats(), and update_rtt_stats().

Referenced by ast_rtcp_read(), and ast_rtp_read().

◆ ast_rtcp_read()

static struct ast_frame * ast_rtcp_read ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 7287 of file res_rtp_asterisk.c.

7288{
7289 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7290 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 1);
7291 struct ast_sockaddr addr;
7292 unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
7293 unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
7294 size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
7295 int res;
7296
7297 /* Read in RTCP data from the socket */
7298 if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
7299 0, &addr)) < 0) {
7300 if (res == RTP_DTLS_ESTABLISHED) {
7303 return &rtp->f;
7304 }
7305
7306 ast_assert(errno != EBADF);
7307 if (errno != EAGAIN) {
7308 ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n",
7309 (errno) ? strerror(errno) : "Unspecified");
7310 return NULL;
7311 }
7312 return &ast_null_frame;
7313 }
7314
7315 /* If this was handled by the ICE session don't do anything further */
7316 if (!res) {
7317 return &ast_null_frame;
7318 }
7319
7320 if (!*read_area) {
7321 struct sockaddr_in addr_tmp;
7322 struct ast_sockaddr addr_v4;
7323
7324 if (ast_sockaddr_is_ipv4(&addr)) {
7325 ast_sockaddr_to_sin(&addr, &addr_tmp);
7326 } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
7327 ast_debug_stun(2, "(%p) STUN using IPv6 mapped address %s\n",
7328 instance, ast_sockaddr_stringify(&addr));
7329 ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
7330 } else {
7331 ast_debug_stun(2, "(%p) STUN cannot do for non IPv4 address %s\n",
7332 instance, ast_sockaddr_stringify(&addr));
7333 return &ast_null_frame;
7334 }
7335 if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
7336 ast_sockaddr_from_sin(&addr, &addr_tmp);
7337 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
7338 }
7339 return &ast_null_frame;
7340 }
7341
7342 return ast_rtcp_interpret(instance, srtp, read_area, res, &addr);
7343}
@ AST_CONTROL_SRCCHANGE
int errno
int ast_sockaddr_ipv4_mapped(const struct ast_sockaddr *addr, struct ast_sockaddr *ast_mapped)
Convert an IPv4-mapped IPv6 address into an IPv4 address.
Definition netsock2.c:37
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition netsock2.h:765
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition netsock2.h:778
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition netsock2.c:497
static struct ast_frame * ast_rtcp_interpret(struct ast_rtp_instance *instance, struct ast_srtp *srtp, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
handle an incoming STUN message.
Definition stun.c:293
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition stun.h:54
@ AST_STUN_ACCEPT
Definition stun.h:65
#define ast_assert(a)
Definition utils.h:779

References ast_assert, AST_CONTROL_SRCCHANGE, ast_debug_stun, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_log, ast_null_frame, ast_rtcp_interpret(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_ipv4_mapped(), ast_sockaddr_is_ipv4(), ast_sockaddr_stringify(), ast_sockaddr_to_sin, AST_STUN_ACCEPT, ast_stun_handle_packet(), errno, ast_rtp::f, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, ast_rtp::rtcp, rtcp_recvfrom(), RTP_DTLS_ESTABLISHED, ast_rtcp::s, ast_frame::subclass, and ast_rtcp::them.

Referenced by ast_rtp_read().

◆ ast_rtcp_write()

static int ast_rtcp_write ( const void *  data)
static

Write a RTCP packet to the far end.

Note
Decide if we are going to send an SR (with Reception Block) or RR RR is sent if we have not sent any rtp packets in the previous interval

Scheduler callback

Definition at line 5198 of file res_rtp_asterisk.c.

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

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_log, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_rtcp_report_alloc(), ast_sockaddr_copy(), ast_sockaddr_stringify(), AST_UUID_STR_LEN, ast_rtp::bundled, cleanup(), ast_rtp_instance::data, errno, LOG_ERROR, NULL, RAII_VAR, ast_rtp::rtcp, rtcp_sendto(), ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::themssrc_valid.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

◆ ast_rtp_bundle()

static int ast_rtp_bundle ( struct ast_rtp_instance child,
struct ast_rtp_instance parent 
)
static
Precondition
child is locked

Definition at line 9650 of file res_rtp_asterisk.c.

9651{
9652 struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child);
9653 struct ast_rtp *parent_rtp;
9654 struct rtp_ssrc_mapping mapping;
9655 struct ast_sockaddr them = { { 0, } };
9656
9657 if (child_rtp->bundled == parent) {
9658 return 0;
9659 }
9660
9661 /* If this instance was already bundled then remove the SSRC mapping */
9662 if (child_rtp->bundled) {
9663 struct ast_rtp *bundled_rtp;
9664
9665 ao2_unlock(child);
9666
9667 /* The child lock can't be held while accessing the parent */
9668 ao2_lock(child_rtp->bundled);
9669 bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled);
9671 ao2_unlock(child_rtp->bundled);
9672
9673 ao2_lock(child);
9674 ao2_ref(child_rtp->bundled, -1);
9675 child_rtp->bundled = NULL;
9676 }
9677
9678 if (!parent) {
9679 /* We transitioned away from bundle so we need our own transport resources once again */
9680 rtp_allocate_transport(child, child_rtp);
9681 return 0;
9682 }
9683
9684 parent_rtp = ast_rtp_instance_get_data(parent);
9685
9686 /* We no longer need any transport related resources as we will use our parent RTP instance instead */
9687 rtp_deallocate_transport(child, child_rtp);
9688
9689 /* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
9690 child_rtp->bundled = ao2_bump(parent);
9691
9692 mapping.ssrc = child_rtp->themssrc;
9693 mapping.ssrc_valid = child_rtp->themssrc_valid;
9694 mapping.instance = child;
9695
9696 ao2_unlock(child);
9697
9698 ao2_lock(parent);
9699
9700 AST_VECTOR_APPEND(&parent_rtp->ssrc_mapping, mapping);
9701
9702#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9703 /* If DTLS-SRTP is already in use then add the local SSRC to it, otherwise it will get added once DTLS
9704 * negotiation has been completed.
9705 */
9706 if (parent_rtp->dtls.connection == AST_RTP_DTLS_CONNECTION_EXISTING) {
9707 dtls_srtp_add_local_ssrc(parent_rtp, parent, 0, child_rtp->ssrc, 0);
9708 }
9709#endif
9710
9711 /* Bundle requires that RTCP-MUX be in use so only the main remote address needs to match */
9713
9714 ao2_unlock(parent);
9715
9716 ao2_lock(child);
9717
9719
9720 return 0;
9721}
#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 4735 of file res_rtp_asterisk.c.

4736{
4737 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4738 struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 0);
4739 struct ast_srtp *rtcp_srtp = ast_rtp_instance_get_srtp(instance, 1);
4740 unsigned int ssrc = ast_random();
4741
4742 if (rtp->lastts) {
4743 /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4745 }
4746
4747 ast_debug_rtp(3, "(%p) RTP changing ssrc from %u to %u due to a source change\n",
4748 instance, rtp->ssrc, ssrc);
4749
4750 if (srtp) {
4751 ast_debug_rtp(3, "(%p) RTP changing ssrc for SRTP from %u to %u\n",
4752 instance, rtp->ssrc, ssrc);
4753 res_srtp->change_source(srtp, rtp->ssrc, ssrc);
4754 if (rtcp_srtp != srtp) {
4755 res_srtp->change_source(rtcp_srtp, rtp->ssrc, ssrc);
4756 }
4757 }
4758
4759 rtp->ssrc = ssrc;
4760
4761 /* Since the source is changing, we don't know what sequence number to expect next */
4762 rtp->expectedrxseqno = -1;
4763
4764 return;
4765}
#define FLAG_NEED_MARKER_BIT
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
int(* change_source)(struct ast_srtp *srtp, unsigned int from_ssrc, unsigned int to_ssrc)
Definition res_srtp.h:44
struct ast_rtp_instance * rtp
Definition res_srtp.c:93
long int ast_random(void)
Definition utils.c:2346
#define ast_set_flag(p, flag)
Definition utils.h:71

References ast_debug_rtp, ast_random(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_set_flag, ast_srtp_res::change_source, FLAG_NEED_MARKER_BIT, res_srtp, and ast_srtp::rtp.

◆ ast_rtp_destroy()

static int ast_rtp_destroy ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4378 of file res_rtp_asterisk.c.

4379{
4380 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4381
4382 if (rtp->bundled) {
4383 struct ast_rtp *bundled_rtp;
4384
4385 /* We can't hold our instance lock while removing ourselves from the parent */
4386 ao2_unlock(instance);
4387
4388 ao2_lock(rtp->bundled);
4389 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
4391 ao2_unlock(rtp->bundled);
4392
4393 ao2_lock(instance);
4394 ao2_ref(rtp->bundled, -1);
4395 }
4396
4397 rtp_deallocate_transport(instance, rtp);
4398
4399 /* Destroy the smoother that was smoothing out audio if present */
4400 if (rtp->smoother) {
4402 }
4403
4404 /* Destroy RTCP if it was being used */
4405 if (rtp->rtcp) {
4406 /*
4407 * It is not possible for there to be an active RTCP scheduler
4408 * entry at this point since it holds a reference to the
4409 * RTP instance while it's active.
4410 */
4412 ast_free(rtp->rtcp);
4413 }
4414
4415 /* Destroy RED if it was being used */
4416 if (rtp->red) {
4417 ao2_unlock(instance);
4418 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
4419 ao2_lock(instance);
4420 ast_free(rtp->red);
4421 rtp->red = NULL;
4422 }
4423
4424 /* Destroy the send buffer if it was being used */
4425 if (rtp->send_buffer) {
4427 }
4428
4429 /* Destroy the recv buffer if it was being used */
4430 if (rtp->recv_buffer) {
4432 }
4433
4435
4441
4442 /* Finally destroy ourselves */
4443 rtp->owner = NULL;
4444 ast_free(rtp);
4445
4446 return 0;
4447}
#define ast_free(a)
Definition astmm.h:180
void ast_data_buffer_free(struct ast_data_buffer *buffer)
Free a data buffer (and all held data payloads)
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition sched.h:46
void ast_smoother_free(struct ast_smoother *s)
Definition smoother.c:220
struct ast_format * lasttxformat
struct rtp_transport_wide_cc_statistics transport_wide_cc
struct ast_smoother * smoother
struct ast_sched_context * sched
struct ast_data_buffer * recv_buffer
struct ast_rtp_instance * owner
The RTP instance owning us (used for debugging purposes) We don't hold a reference to the instance be...
struct rtp_red * red
struct ast_format * lastrxformat
struct rtp_transport_wide_cc_statistics::@511 packet_statistics
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185

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

◆ ast_rtp_dtmf_begin()

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

Definition at line 4465 of file res_rtp_asterisk.c.

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

References ao2_cleanup, ast_debug, ast_format_none, ast_log, ast_rtp_codecs_get_payload(), ast_rtp_codecs_get_preferred_dtmf_format_pt(), ast_rtp_codecs_get_preferred_dtmf_format_rate(), ast_rtp_codecs_get_preferred_format(), ast_rtp_codecs_payload_code_tx(), ast_rtp_codecs_payload_code_tx_sample_rate(), AST_RTP_DTMF, ast_rtp_get_rate(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_rtp_payload_mapping_tx_is_present(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_suite_event_notify, ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, calc_txstamp(), DEFAULT_DTMF_SAMPLE_RATE_MS, digit, ast_rtp::dtmf_samplerate_ms, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, ast_rtp::lasttxformat, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.

◆ ast_rtp_dtmf_compatible()

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

Definition at line 9433 of file res_rtp_asterisk.c.

9434{
9435 /* If both sides are not using the same method of DTMF transmission
9436 * (ie: one is RFC2833, other is INFO... then we can not do direct media.
9437 * --------------------------------------------------
9438 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
9439 * |-----------|------------|-----------------------|
9440 * | Inband | False | True |
9441 * | RFC2833 | True | True |
9442 * | SIP INFO | False | False |
9443 * --------------------------------------------------
9444 */
9446 (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
9447}
@ AST_RTP_PROPERTY_DTMF
Definition rtp_engine.h:120
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648

References ast_rtp_instance_get_prop(), and AST_RTP_PROPERTY_DTMF.

◆ ast_rtp_dtmf_continuation()

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4581 of file res_rtp_asterisk.c.

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

References ast_log, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, calc_txstamp(), ast_rtp::dtmf_samplerate_ms, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, NULL, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, and ast_rtp::ssrc.

Referenced by ast_rtp_interpret().

◆ ast_rtp_dtmf_end()

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

Definition at line 4717 of file res_rtp_asterisk.c.

4718{
4719 return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
4720}
static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)

References ast_rtp_dtmf_end_with_duration(), and digit.

◆ ast_rtp_dtmf_end_with_duration()

static int ast_rtp_dtmf_end_with_duration ( struct ast_rtp_instance instance,
char  digit,
unsigned int  duration 
)
static
Precondition
instance is locked

Definition at line 4627 of file res_rtp_asterisk.c.

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

References ast_debug_rtp, ast_log, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_smoother_free(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, calc_txstamp(), cleanup(), digit, ast_rtp::dtmf_samplerate_ms, ast_rtp::dtmfmute, errno, ast_rtp::expectedseqno, ast_rtp::f, ast_frame_subclass::format, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, NULL, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::smoother, ast_rtp::ssrc, and ast_frame::subclass.

Referenced by ast_rtp_dtmf_end().

◆ ast_rtp_dtmf_mode_get()

static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 4458 of file res_rtp_asterisk.c.

4459{
4460 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4461 return rtp->dtmfmode;
4462}
enum ast_rtp_dtmf_mode dtmfmode

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

◆ ast_rtp_dtmf_mode_set()

static int ast_rtp_dtmf_mode_set ( struct ast_rtp_instance instance,
enum ast_rtp_dtmf_mode  dtmf_mode 
)
static
Precondition
instance is locked

Definition at line 4450 of file res_rtp_asterisk.c.

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

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

◆ ast_rtp_extension_enable()

static int ast_rtp_extension_enable ( struct ast_rtp_instance instance,
enum ast_rtp_extension  extension 
)
static

Definition at line 9638 of file res_rtp_asterisk.c.

9639{
9640 switch (extension) {
9643 return 1;
9644 default:
9645 return 0;
9646 }
9647}
@ 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 9187 of file res_rtp_asterisk.c.

9188{
9189 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9190
9191 return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
9192}

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

9586{
9587 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9588
9589 return rtp->cname;
9590}

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

9578{
9579 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9580
9581 return rtp->ssrc;
9582}

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

9369{
9370 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9371
9372 if (!rtp->rtcp) {
9373 return -1;
9374 }
9375
9380
9392
9404
9411
9423
9424
9428
9429 return 0;
9430}
#define AST_RTP_STAT_TERMINATOR(combined)
Definition rtp_engine.h:500
@ AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS
Definition rtp_engine.h:207
@ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS
Definition rtp_engine.h:203
@ AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS
Definition rtp_engine.h:199
@ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVMES
Definition rtp_engine.h:270
@ AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER
Definition rtp_engine.h:223
@ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVMES
Definition rtp_engine.h:278
@ AST_RTP_INSTANCE_STAT_MIN_RTT
Definition rtp_engine.h:243
@ AST_RTP_INSTANCE_STAT_TXMES
Definition rtp_engine.h:262
@ AST_RTP_INSTANCE_STAT_CHANNEL_UNIQUEID
Definition rtp_engine.h:253
@ AST_RTP_INSTANCE_STAT_TXPLOSS
Definition rtp_engine.h:195
@ AST_RTP_INSTANCE_STAT_MAX_RTT
Definition rtp_engine.h:241
@ AST_RTP_INSTANCE_STAT_RXPLOSS
Definition rtp_engine.h:197
@ AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER
Definition rtp_engine.h:221
@ AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER
Definition rtp_engine.h:229
@ AST_RTP_INSTANCE_STAT_REMOTE_MINMES
Definition rtp_engine.h:268
@ AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER
Definition rtp_engine.h:227
@ AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS
Definition rtp_engine.h:201
@ AST_RTP_INSTANCE_STAT_LOCAL_MINMES
Definition rtp_engine.h:276
@ AST_RTP_INSTANCE_STAT_TXOCTETCOUNT
Definition rtp_engine.h:255
@ AST_RTP_INSTANCE_STAT_RXMES
Definition rtp_engine.h:264
@ AST_RTP_INSTANCE_STAT_REMOTE_STDEVMES
Definition rtp_engine.h:272
@ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS
Definition rtp_engine.h:211
@ AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS
Definition rtp_engine.h:205
@ AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS
Definition rtp_engine.h:213
@ AST_RTP_INSTANCE_STAT_REMOTE_MAXMES
Definition rtp_engine.h:266
@ AST_RTP_INSTANCE_STAT_TXCOUNT
Definition rtp_engine.h:189
@ AST_RTP_INSTANCE_STAT_STDEVRTT
Definition rtp_engine.h:247
@ AST_RTP_INSTANCE_STAT_COMBINED_MES
Definition rtp_engine.h:260
@ AST_RTP_INSTANCE_STAT_LOCAL_MAXMES
Definition rtp_engine.h:274
@ AST_RTP_INSTANCE_STAT_RXJITTER
Definition rtp_engine.h:219
@ AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS
Definition rtp_engine.h:209
@ AST_RTP_INSTANCE_STAT_LOCAL_SSRC
Definition rtp_engine.h:249
@ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER
Definition rtp_engine.h:225
@ AST_RTP_INSTANCE_STAT_COMBINED_JITTER
Definition rtp_engine.h:215
@ AST_RTP_INSTANCE_STAT_TXJITTER
Definition rtp_engine.h:217
@ AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER
Definition rtp_engine.h:231
@ AST_RTP_INSTANCE_STAT_COMBINED_LOSS
Definition rtp_engine.h:193
@ AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER
Definition rtp_engine.h:235
@ AST_RTP_INSTANCE_STAT_COMBINED_RTT
Definition rtp_engine.h:237
@ AST_RTP_INSTANCE_STAT_NORMDEVRTT
Definition rtp_engine.h:245
@ AST_RTP_INSTANCE_STAT_RTT
Definition rtp_engine.h:239
@ AST_RTP_INSTANCE_STAT_RXOCTETCOUNT
Definition rtp_engine.h:257
@ AST_RTP_INSTANCE_STAT_LOCAL_STDEVMES
Definition rtp_engine.h:280
@ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER
Definition rtp_engine.h:233
@ AST_RTP_INSTANCE_STAT_RXCOUNT
Definition rtp_engine.h:191
@ AST_RTP_INSTANCE_STAT_REMOTE_SSRC
Definition rtp_engine.h:251
#define AST_RTP_STAT_STRCPY(current_stat, combined, placement, value)
Definition rtp_engine.h:492
#define AST_RTP_STAT_SET(current_stat, combined, placement, value)
Definition rtp_engine.h:484
unsigned int received_prior
double reported_maxjitter
double reported_normdev_lost
double reported_minlost
double normdevrtt
double reported_normdev_mes
double minrxjitter
double reported_maxmes
unsigned int reported_lost
double reported_stdev_jitter
double normdev_rxjitter
double reported_stdev_lost
double normdev_rxlost
double reported_stdev_mes
double normdev_rxmes
double maxrxjitter
double reported_normdev_jitter
double reported_maxlost
double stdev_rxjitter
double reported_jitter
double stdev_rxmes
double reported_minjitter
unsigned int expected_prior
double reported_minmes
double stdev_rxlost
unsigned int remote_ssrc
Definition rtp_engine.h:454
unsigned int local_ssrc
Definition rtp_engine.h:452
unsigned int rxoctetcount
Definition rtp_engine.h:460
unsigned int txoctetcount
Definition rtp_engine.h:458
char channel_uniqueid[MAX_CHANNEL_ID]
Definition rtp_engine.h:456
unsigned int rxcount
unsigned int rxoctetcount
double rxjitter

References ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), AST_RTP_INSTANCE_STAT_CHANNEL_UNIQUEID, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, AST_RTP_INSTANCE_STAT_COMBINED_MES, AST_RTP_INSTANCE_STAT_COMBINED_RTT, AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MAXMES, AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MINMES, AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVMES, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_SSRC, AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_STDEVMES, AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MAXMES, AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MINMES, AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVMES, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_SSRC, AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_STDEVMES, AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_RXCOUNT, AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_RXMES, AST_RTP_INSTANCE_STAT_RXOCTETCOUNT, AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_TXCOUNT, AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_TXMES, AST_RTP_INSTANCE_STAT_TXOCTETCOUNT, AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_STAT_SET, AST_RTP_STAT_STRCPY, AST_RTP_STAT_TERMINATOR, ast_rtp_instance_stats::channel_uniqueid, ast_rtcp::expected_prior, ast_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxmes, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minmes, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevmes, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevmes, ast_rtp_instance_stats::local_stdevrxploss, ast_rtp_instance_stats::maxrtt, ast_rtcp::maxrtt, ast_rtcp::maxrxjitter, ast_rtcp::maxrxlost, ast_rtcp::maxrxmes, ast_rtp_instance_stats::minrtt, ast_rtcp::minrtt, ast_rtcp::minrxjitter, ast_rtcp::minrxlost, ast_rtcp::minrxmes, ast_rtcp::normdev_rxjitter, ast_rtcp::normdev_rxlost, ast_rtcp::normdev_rxmes, ast_rtp_instance_stats::normdevrtt, ast_rtcp::normdevrtt, ast_rtcp::received_prior, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxmes, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minmes, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevmes, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevmes, ast_rtp_instance_stats::remote_stdevrxploss, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_maxmes, ast_rtcp::reported_mes, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_minmes, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_normdev_mes, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtcp::reported_stdev_mes, ast_rtp::rtcp, ast_rtp_instance_stats::rtt, ast_rtcp::rtt, ast_rtp_instance_stats::rxcount, ast_rtp::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp::rxjitter, ast_rtp_instance_stats::rxmes, ast_rtp::rxmes, ast_rtp_instance_stats::rxoctetcount, ast_rtp::rxoctetcount, ast_rtp_instance_stats::rxploss, ast_rtp::ssrc, ast_rtcp::stdev_rxjitter, ast_rtcp::stdev_rxlost, ast_rtcp::stdev_rxmes, ast_rtp_instance_stats::stdevrtt, ast_rtcp::stdevrtt, ast_rtp::themssrc, ast_rtp_instance_stats::txcount, ast_rtp::txcount, ast_rtp_instance_stats::txjitter, ast_rtp_instance_stats::txmes, ast_rtp_instance_stats::txoctetcount, ast_rtp::txoctetcount, and ast_rtp_instance_stats::txploss.

◆ ast_rtp_interpret()

static struct ast_frame * ast_rtp_interpret ( struct ast_rtp_instance instance,
struct ast_srtp srtp,
const struct ast_sockaddr remote_address,
unsigned char *  read_area,
int  length,
int  prev_seqno,
unsigned int  bundled 
)
static

Definition at line 7897 of file res_rtp_asterisk.c.

7900{
7901 unsigned int *rtpheader = (unsigned int*)(read_area);
7902 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7903 struct ast_rtp_instance *instance1;
7904 int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc;
7905 unsigned int timestamp;
7906 RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
7907 struct frame_list frames;
7908
7909 /* If this payload is encrypted then decrypt it using the given SRTP instance */
7910 if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
7911 srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
7912 return &ast_null_frame;
7913 }
7914
7915 /* If we are currently sending DTMF to the remote party send a continuation packet */
7916 if (rtp->sending_digit) {
7917 ast_rtp_dtmf_continuation(instance);
7918 }
7919
7920 /* Pull out the various other fields we will need */
7921 ssrc = ntohl(rtpheader[2]);
7922 seqno = ntohl(rtpheader[0]);
7923 payloadtype = (seqno & 0x7f0000) >> 16;
7924 padding = seqno & (1 << 29);
7925 mark = seqno & (1 << 23);
7926 ext = seqno & (1 << 28);
7927 cc = (seqno & 0xF000000) >> 24;
7928 seqno &= 0xffff;
7929 timestamp = ntohl(rtpheader[1]);
7930
7932
7933 /* Remove any padding bytes that may be present */
7934 if (padding) {
7935 res -= read_area[res - 1];
7936 }
7937
7938 /* Skip over any CSRC fields */
7939 if (cc) {
7940 hdrlen += cc * 4;
7941 }
7942
7943 /* Look for any RTP extensions, currently we do not support any */
7944 if (ext) {
7945 int extensions_size = (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
7946 unsigned int profile;
7947 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
7948
7949 if (profile == 0xbede) {
7950 /* We skip over the first 4 bytes as they are just for the one byte extension header */
7951 rtp_instance_parse_extmap_extensions(instance, rtp, read_area + hdrlen + 4, extensions_size);
7952 } else if (DEBUG_ATLEAST(1)) {
7953 if (profile == 0x505a) {
7954 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
7955 } else {
7956 /* SDP negotiated RTP extensions can not currently be output in logging */
7957 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
7958 }
7959 }
7960
7961 hdrlen += extensions_size;
7962 hdrlen += 4;
7963 }
7964
7965 /* Make sure after we potentially mucked with the header length that it is once again valid */
7966 if (res < hdrlen) {
7967 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
7969 }
7970
7971 /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
7972 if (!bundled) {
7973 /* Force a marker bit and change SSRC if the SSRC changes */
7974 if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
7975 struct ast_frame *f, srcupdate = {
7978 };
7979
7980 if (!mark) {
7982 ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance);
7983 }
7984 mark = 1;
7985 }
7986
7987 f = ast_frisolate(&srcupdate);
7989
7990 rtp->seedrxseqno = 0;
7991 rtp->rxcount = 0;
7992 rtp->rxoctetcount = 0;
7993 rtp->cycles = 0;
7994 prev_seqno = 0;
7995 rtp->last_seqno = 0;
7996 rtp->last_end_timestamp.ts = 0;
7997 rtp->last_end_timestamp.is_set = 0;
7998 if (rtp->rtcp) {
7999 rtp->rtcp->expected_prior = 0;
8000 rtp->rtcp->received_prior = 0;
8001 }
8002 }
8003
8004 rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
8005 rtp->themssrc_valid = 1;
8006 }
8007
8008 rtp->rxcount++;
8009 rtp->rxoctetcount += (res - hdrlen);
8010 if (rtp->rxcount == 1) {
8011 rtp->seedrxseqno = seqno;
8012 }
8013
8014 /* Do not schedule RR if RTCP isn't run */
8015 if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 0) {
8016 /* Schedule transmission of Receiver Report */
8017 ao2_ref(instance, +1);
8019 if (rtp->rtcp->schedid < 0) {
8020 ao2_ref(instance, -1);
8021 ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
8022 }
8023 }
8024 if ((int)prev_seqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
8025 rtp->cycles += RTP_SEQ_MOD;
8026
8027 /* If we are directly bridged to another instance send the audio directly out,
8028 * but only after updating core information about the received traffic so that
8029 * outgoing RTCP reflects it.
8030 */
8031 instance1 = ast_rtp_instance_get_bridged(instance);
8032 if (instance1
8033 && !bridge_p2p_rtp_write(instance, instance1, rtpheader, res, hdrlen)) {
8034 struct timeval rxtime;
8035 struct ast_frame *f;
8036
8037 /* Update statistics for jitter so they are correct in RTCP */
8038 calc_rxstamp_and_jitter(&rxtime, rtp, timestamp, mark);
8039
8040
8041 /* When doing P2P we don't need to raise any frames about SSRC change to the core */
8042 while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list)) != NULL) {
8043 ast_frfree(f);
8044 }
8045
8046 return &ast_null_frame;
8047 }
8048
8049 payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
8050 if (!payload) {
8051 /* Unknown payload type. */
8053 }
8054
8055 /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
8056 if (!payload->asterisk_format) {
8057 struct ast_frame *f = NULL;
8058 if (payload->rtp_code == AST_RTP_DTMF) {
8059 /* process_dtmf_rfc2833 may need to return multiple frames. We do this
8060 * by passing the pointer to the frame list to it so that the method
8061 * can append frames to the list as needed.
8062 */
8063 process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames);
8064 } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
8065 f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
8066 } else if (payload->rtp_code == AST_RTP_CN) {
8067 f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
8068 } else {
8069 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
8070 payloadtype,
8071 ast_sockaddr_stringify(remote_address));
8072 }
8073
8074 if (f) {
8076 }
8077 /* Even if no frame was returned by one of the above methods,
8078 * we may have a frame to return in our frame list
8079 */
8081 }
8082
8083 ao2_replace(rtp->lastrxformat, payload->format);
8084 ao2_replace(rtp->f.subclass.format, payload->format);
8085 switch (ast_format_get_type(rtp->f.subclass.format)) {
8088 break;
8091 break;
8093 rtp->f.frametype = AST_FRAME_TEXT;
8094 break;
8096 /* Fall through */
8097 default:
8098 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8100 return &ast_null_frame;
8101 }
8102
8103 if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
8104 rtp->dtmf_timeout = 0;
8105
8106 if (rtp->resp) {
8107 struct ast_frame *f;
8108 f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
8110 rtp->resp = 0;
8111 rtp->dtmf_timeout = rtp->dtmf_duration = 0;
8113 return AST_LIST_FIRST(&frames);
8114 }
8115 }
8116
8117 rtp->f.src = "RTP";
8118 rtp->f.mallocd = 0;
8119 rtp->f.datalen = res - hdrlen;
8120 rtp->f.data.ptr = read_area + hdrlen;
8121 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
8123 rtp->f.seqno = seqno;
8124 rtp->f.stream_num = rtp->stream_num;
8125
8127 && ((int)seqno - (prev_seqno + 1) > 0)
8128 && ((int)seqno - (prev_seqno + 1) < 10)) {
8129 unsigned char *data = rtp->f.data.ptr;
8130
8131 memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
8132 rtp->f.datalen +=3;
8133 *data++ = 0xEF;
8134 *data++ = 0xBF;
8135 *data = 0xBD;
8136 }
8137
8139 unsigned char *data = rtp->f.data.ptr;
8140 unsigned char *header_end;
8141 int num_generations;
8142 int header_length;
8143 int len;
8144 int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
8145 int x;
8146
8148 header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
8149 if (header_end == NULL) {
8151 }
8152 header_end++;
8153
8154 header_length = header_end - data;
8155 num_generations = header_length / 4;
8156 len = header_length;
8157
8158 if (!diff) {
8159 for (x = 0; x < num_generations; x++)
8160 len += data[x * 4 + 3];
8161
8162 if (!(rtp->f.datalen - len))
8164
8165 rtp->f.data.ptr += len;
8166 rtp->f.datalen -= len;
8167 } else if (diff > num_generations && diff < 10) {
8168 len -= 3;
8169 rtp->f.data.ptr += len;
8170 rtp->f.datalen -= len;
8171
8172 data = rtp->f.data.ptr;
8173 *data++ = 0xEF;
8174 *data++ = 0xBF;
8175 *data = 0xBD;
8176 } else {
8177 for ( x = 0; x < num_generations - diff; x++)
8178 len += data[x * 4 + 3];
8179
8180 rtp->f.data.ptr += len;
8181 rtp->f.datalen -= len;
8182 }
8183 }
8184
8186 rtp->f.samples = ast_codec_samples_count(&rtp->f);
8188 ast_frame_byteswap_be(&rtp->f);
8189 }
8190 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8191 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
8193 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8194 rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
8196 /* Video -- samples is # of samples vs. 90000 */
8197 if (!rtp->lastividtimestamp)
8198 rtp->lastividtimestamp = timestamp;
8199 calc_rxstamp_and_jitter(&rtp->f.delivery, rtp, timestamp, mark);
8201 rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
8202 rtp->f.samples = timestamp - rtp->lastividtimestamp;
8203 rtp->lastividtimestamp = timestamp;
8204 rtp->f.delivery.tv_sec = 0;
8205 rtp->f.delivery.tv_usec = 0;
8206 /* Pass the RTP marker bit as bit */
8207 rtp->f.subclass.frame_ending = mark ? 1 : 0;
8209 /* TEXT -- samples is # of samples vs. 1000 */
8210 if (!rtp->lastitexttimestamp)
8211 rtp->lastitexttimestamp = timestamp;
8212 rtp->f.samples = timestamp - rtp->lastitexttimestamp;
8213 rtp->lastitexttimestamp = timestamp;
8214 rtp->f.delivery.tv_sec = 0;
8215 rtp->f.delivery.tv_usec = 0;
8216 } else {
8217 ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
8219 return &ast_null_frame;
8220 }
8221
8223 return AST_LIST_FIRST(&frames);
8224}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition codec.h:33
@ AST_MEDIA_TYPE_IMAGE
Definition codec.h:34
@ AST_MEDIA_TYPE_TEXT
Definition codec.h:35
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Definition codec.c:379
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition codec.c:348
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition format.c:354
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition format.c:379
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
struct ast_format * ast_format_t140_red
Built-in cached t140 red format.
struct ast_format * ast_format_t140
Built-in cached t140 format.
const char * ext
Definition http.c:151
#define ast_frame_byteswap_be(fr)
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
@ AST_FRFLAG_HAS_SEQUENCE_NUMBER
@ AST_FRFLAG_HAS_TIMING_INFO
@ AST_FRAME_DTMF_END
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define LOG_NOTICE
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
static int frames
Definition parser.c:51
static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, struct ast_rtp_instance *instance1, unsigned int *rtpheader, int len, int hdrlen)
static void calc_rxstamp_and_jitter(struct timeval *tv, struct ast_rtp *rtp, unsigned int rx_rtp_ts, int mark)
static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark, struct frame_list *frames)
static struct ast_frame * process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
static void rtp_instance_parse_extmap_extensions(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *extension, int len)
static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
static struct ast_frame * process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
#define RTP_SEQ_MOD
static struct ast_frame * create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
static int ast_rtcp_write(const void *data)
Write a RTCP packet to the far end.
struct ast_rtp_instance * ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
Get the other RTP instance that an instance is bridged to.
#define AST_RTP_CN
Definition rtp_engine.h:296
#define AST_RTP_CISCO_DTMF
Definition rtp_engine.h:298
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition sched.c:567
unsigned int lastividtimestamp
unsigned int dtmf_duration
unsigned short seedrxseqno
unsigned int last_seqno
unsigned int dtmf_timeout
optional_ts last_end_timestamp
unsigned int lastitexttimestamp
unsigned int ts
unsigned char is_set
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition time.h:282
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition time.h:107

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

Referenced by ast_rtp_read().

◆ ast_rtp_local_bridge()

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

Definition at line 9340 of file res_rtp_asterisk.c.

9341{
9342 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
9343
9344 ao2_lock(instance0);
9346 if (rtp->smoother) {
9348 rtp->smoother = NULL;
9349 }
9350
9351 /* We must use a new SSRC when local bridge ends */
9352 if (!instance1) {
9353 rtp->ssrc = rtp->ssrc_orig;
9354 rtp->ssrc_orig = 0;
9355 rtp->ssrc_saved = 0;
9356 } else if (!rtp->ssrc_saved) {
9357 /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
9358 rtp->ssrc_orig = rtp->ssrc;
9359 rtp->ssrc_saved = 1;
9360 }
9361
9362 ao2_unlock(instance0);
9363
9364 return 0;
9365}
#define FLAG_REQ_LOCAL_BRIDGE_BIT
unsigned int ssrc_orig
unsigned char ssrc_saved

References ao2_lock, ao2_unlock, ast_rtp_instance_get_data(), ast_set_flag, ast_smoother_free(), FLAG_NEED_MARKER_BIT, FLAG_REQ_LOCAL_BRIDGE_BIT, NULL, ast_rtp::smoother, ast_rtp::ssrc, ast_rtp::ssrc_orig, and ast_rtp::ssrc_saved.

◆ ast_rtp_new()

static int ast_rtp_new ( struct ast_rtp_instance instance,
struct ast_sched_context sched,
struct ast_sockaddr addr,
void *  data 
)
static
Precondition
instance is locked

Definition at line 4322 of file res_rtp_asterisk.c.

4325{
4326 struct ast_rtp *rtp = NULL;
4327
4328 /* Create a new RTP structure to hold all of our data */
4329 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
4330 return -1;
4331 }
4332 rtp->owner = instance;
4333 /* Set default parameters on the newly created RTP structure */
4334 rtp->ssrc = ast_random();
4335 ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname));
4336 rtp->seqno = ast_random() & 0xffff;
4337 rtp->expectedrxseqno = -1;
4338 rtp->expectedseqno = -1;
4339 rtp->rxstart = -1;
4340 rtp->sched = sched;
4341 ast_sockaddr_copy(&rtp->bind_address, addr);
4342 /* Transport creation operations can grab the RTP data from the instance, so set it */
4343 ast_rtp_instance_set_data(instance, rtp);
4344
4345 if (rtp_allocate_transport(instance, rtp)) {
4346 return -1;
4347 }
4348
4349 if (AST_VECTOR_INIT(&rtp->ssrc_mapping, 1)) {
4350 return -1;
4351 }
4352
4354 return -1;
4355 }
4356 rtp->transport_wide_cc.schedid = -1;
4357
4361 rtp->stream_num = -1;
4362
4363 return 0;
4364}
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition rtp_engine.c:609
struct ast_sockaddr bind_address
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition uuid.c:141
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

References ao2_bump, ast_calloc, ast_format_none, ast_random(), ast_rtp_instance_set_data(), ast_sockaddr_copy(), ast_uuid_generate_str(), AST_VECTOR_INIT, ast_rtp::bind_address, ast_rtp::cname, ast_rtp::expectedrxseqno, ast_rtp::expectedseqno, ast_rtp::f, ast_frame_subclass::format, ast_rtp::lastrxformat, ast_rtp::lasttxformat, NULL, ast_rtp::owner, rtp_transport_wide_cc_statistics::packet_statistics, rtp_allocate_transport(), ast_rtp::rxstart, ast_rtp::sched, rtp_transport_wide_cc_statistics::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::ssrc_mapping, ast_rtp::stream_num, ast_frame::subclass, and ast_rtp::transport_wide_cc.

◆ ast_rtp_prop_set()

static void ast_rtp_prop_set ( struct ast_rtp_instance instance,
enum ast_rtp_property  property,
int  value 
)
static
Precondition
instance is locked

Definition at line 9003 of file res_rtp_asterisk.c.

9004{
9005 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9006
9007 if (property == AST_RTP_PROPERTY_RTCP) {
9008 if (value) {
9009 struct ast_sockaddr local_addr;
9010
9011 if (rtp->rtcp && rtp->rtcp->type == value) {
9012 ast_debug_rtcp(1, "(%p) RTCP ignoring duplicate property\n", instance);
9013 return;
9014 }
9015
9016 if (!rtp->rtcp) {
9017 rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
9018 if (!rtp->rtcp) {
9019 return;
9020 }
9021 rtp->rtcp->s = -1;
9022#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9023 rtp->rtcp->dtls.timeout_timer = -1;
9024#endif
9025 rtp->rtcp->schedid = -1;
9026 }
9027
9028 rtp->rtcp->type = value;
9029
9030 /* Grab the IP address and port we are going to use */
9031 ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
9034 ast_sockaddr_port(&rtp->rtcp->us) + 1);
9035 }
9036
9037 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
9038 if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
9039 ast_sockaddr_set_port(&local_addr, ast_sockaddr_port(&rtp->rtcp->us));
9040 } else {
9041 /* Failed to get local address reset to use default. */
9042 ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
9043 }
9044
9047 if (!rtp->rtcp->local_addr_str) {
9048 ast_free(rtp->rtcp);
9049 rtp->rtcp = NULL;
9050 return;
9051 }
9052
9054 /* We're either setting up RTCP from scratch or
9055 * switching from MUX. Either way, we won't have
9056 * a socket set up, and we need to set it up
9057 */
9058 if ((rtp->rtcp->s = create_new_socket("RTCP", &rtp->rtcp->us)) < 0) {
9059 ast_debug_rtcp(1, "(%p) RTCP failed to create a new socket\n", instance);
9061 ast_free(rtp->rtcp);
9062 rtp->rtcp = NULL;
9063 return;
9064 }
9065
9066 /* 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 */
9067 if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
9068 ast_debug_rtcp(1, "(%p) RTCP failed to setup RTP instance\n", instance);
9069 close(rtp->rtcp->s);
9071 ast_free(rtp->rtcp);
9072 rtp->rtcp = NULL;
9073 return;
9074 }
9075#ifdef HAVE_PJPROJECT
9076 if (rtp->ice) {
9077 rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
9078 }
9079#endif
9080#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9081 dtls_setup_rtcp(instance);
9082#endif
9083 } else {
9084 struct ast_sockaddr addr;
9085 /* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
9086 * then close the socket we previously created.
9087 *
9088 * It may seem as though there is a possible race condition here where we might try
9089 * to close the RTCP socket while it is being used to send data. However, this is not
9090 * a problem in practice since setting and adjusting of RTCP properties happens prior
9091 * to activating RTP. It is not until RTP is activated that timers start for RTCP
9092 * transmission
9093 */
9094 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9095 close(rtp->rtcp->s);
9096 }
9097 rtp->rtcp->s = rtp->s;
9098 ast_rtp_instance_get_remote_address(instance, &addr);
9099 ast_sockaddr_copy(&rtp->rtcp->them, &addr);
9100#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9101 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9102 SSL_free(rtp->rtcp->dtls.ssl);
9103 }
9104 rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
9105#endif
9106 }
9107
9108 ast_debug_rtcp(1, "(%s) RTCP setup on RTP instance\n",
9110 } else {
9111 if (rtp->rtcp) {
9112 if (rtp->rtcp->schedid > -1) {
9113 ao2_unlock(instance);
9114 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9115 /* Successfully cancelled scheduler entry. */
9116 ao2_ref(instance, -1);
9117 } else {
9118 /* Unable to cancel scheduler entry */
9119 ast_debug_rtcp(1, "(%p) RTCP failed to tear down RTCP\n", instance);
9120 ao2_lock(instance);
9121 return;
9122 }
9123 ao2_lock(instance);
9124 rtp->rtcp->schedid = -1;
9125 }
9126 if (rtp->transport_wide_cc.schedid > -1) {
9127 ao2_unlock(instance);
9128 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9129 ao2_ref(instance, -1);
9130 } else {
9131 ast_debug_rtcp(1, "(%p) RTCP failed to tear down transport-cc feedback\n", instance);
9132 ao2_lock(instance);
9133 return;
9134 }
9135 ao2_lock(instance);
9136 rtp->transport_wide_cc.schedid = -1;
9137 }
9138 if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
9139 close(rtp->rtcp->s);
9140 }
9141#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9142 ao2_unlock(instance);
9143 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9144 ao2_lock(instance);
9145
9146 if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
9147 SSL_free(rtp->rtcp->dtls.ssl);
9148 }
9149#endif
9151 ast_free(rtp->rtcp);
9152 rtp->rtcp = NULL;
9153 ast_debug_rtcp(1, "(%s) RTCP torn down on RTP instance\n",
9155 }
9156 }
9157 } else if (property == AST_RTP_PROPERTY_ASYMMETRIC_CODEC) {
9158 rtp->asymmetric_codec = value;
9159 } else if (property == AST_RTP_PROPERTY_RETRANS_SEND) {
9160 if (value) {
9161 if (!rtp->send_buffer) {
9163 }
9164 } else {
9165 if (rtp->send_buffer) {
9167 rtp->send_buffer = NULL;
9168 }
9169 }
9170 } else if (property == AST_RTP_PROPERTY_RETRANS_RECV) {
9171 if (value) {
9172 if (!rtp->recv_buffer) {
9175 }
9176 } else {
9177 if (rtp->recv_buffer) {
9179 rtp->recv_buffer = NULL;
9181 }
9182 }
9183 }
9184}
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
Definition acl.c:1068
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
struct ast_data_buffer * ast_data_buffer_alloc(ast_data_buffer_free_callback free_fn, size_t size)
Allocate a data buffer.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition netsock2.h:517
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition netsock2.c:590
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition netsock2.h:532
#define DEFAULT_RTP_RECV_BUFFER_SIZE
static int create_new_socket(const char *type, struct ast_sockaddr *bind_addr)
#define DEFAULT_RTP_SEND_BUFFER_SIZE
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition rtp_engine.h:287
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition rtp_engine.c:694
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition rtp_engine.h:130
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition rtp_engine.h:132
@ AST_RTP_PROPERTY_RTCP
Definition rtp_engine.h:126
@ AST_RTP_PROPERTY_ASYMMETRIC_CODEC
Definition rtp_engine.h:128
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition sched.c:614
struct ast_sockaddr us
unsigned int asymmetric_codec
int value
Definition syslog.c:37

References ao2_lock, ao2_ref, ao2_unlock, ast_bind(), ast_calloc, ast_data_buffer_alloc(), ast_data_buffer_free(), ast_debug_rtcp, ast_find_ourip(), ast_free, ast_free_ptr(), AST_RTP_ICE_COMPONENT_RTCP, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, AST_RTP_INSTANCE_RTCP_STANDARD, AST_RTP_PROPERTY_ASYMMETRIC_CODEC, AST_RTP_PROPERTY_RETRANS_RECV, AST_RTP_PROPERTY_RETRANS_SEND, AST_RTP_PROPERTY_RTCP, ast_sched_del(), ast_sockaddr_copy(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdup, AST_VECTOR_FREE, AST_VECTOR_INIT, ast_rtp::asymmetric_codec, create_new_socket(), DEFAULT_RTP_RECV_BUFFER_SIZE, DEFAULT_RTP_SEND_BUFFER_SIZE, ast_rtcp::local_addr_str, ast_rtp::missing_seqno, NULL, ast_rtp::recv_buffer, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, ast_rtp::sched, rtp_transport_wide_cc_statistics::schedid, ast_rtcp::schedid, ast_rtp::send_buffer, ast_rtcp::them, TRANSPORT_SOCKET_RTCP, ast_rtp::transport_wide_cc, ast_rtcp::type, ast_rtcp::us, and value.

◆ ast_rtp_qos_set()

static int ast_rtp_qos_set ( struct ast_rtp_instance instance,
int  tos,
int  cos,
const char *  desc 
)
static
Precondition
instance is locked

Definition at line 9516 of file res_rtp_asterisk.c.

9517{
9518 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9519
9520 return ast_set_qos(rtp->s, tos, cos, desc);
9521}
static const char desc[]
Definition cdr_radius.c:84
unsigned int tos
Definition chan_iax2.c:392
unsigned int cos
Definition chan_iax2.c:393
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition netsock2.c:621

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

◆ ast_rtp_read()

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

Definition at line 8336 of file res_rtp_asterisk.c.

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

9196{
9197 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9198 struct ast_sockaddr local;
9199 int index;
9200
9201 ast_rtp_instance_get_local_address(instance, &local);
9202 if (!ast_sockaddr_isnull(addr)) {
9203 /* Update the local RTP address with what is being used */
9204 if (ast_ouraddrfor(addr, &local)) {
9205 /* Failed to update our address so reuse old local address */
9206 ast_rtp_instance_get_local_address(instance, &local);
9207 } else {
9208 ast_rtp_instance_set_local_address(instance, &local);
9209 }
9210 }
9211
9212 if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
9213 ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
9214 ast_sockaddr_copy(&rtp->rtcp->them, addr);
9215
9218
9219 /* Update the local RTCP address with what is being used */
9220 ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
9221 }
9222 ast_sockaddr_copy(&rtp->rtcp->us, &local);
9223
9226 }
9227
9228 /* Update any bundled RTP instances */
9229 for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
9230 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
9231
9233 }
9234
9235 /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
9236 rtp->last_seqno = 0;
9237 rtp->last_end_timestamp.ts = 0;
9238 rtp->last_end_timestamp.is_set = 0;
9239
9241 && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
9242 /* We only need to learn a new strict source address if we've been told the source is
9243 * changing to something different.
9244 */
9245 ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
9246 rtp, ast_sockaddr_stringify(addr));
9247 rtp_learning_start(rtp);
9248 }
9249}
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition acl.c:1021
static int strictrtp
static void rtp_learning_start(struct ast_rtp *rtp)
Start the strictrtp learning mode.
int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address that we are expecting to receive RTP on.
Definition rtp_engine.c:639

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

◆ ast_rtp_rtcp_handle_nack()

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

Definition at line 6644 of file res_rtp_asterisk.c.

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

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

Referenced by ast_rtcp_interpret().

◆ ast_rtp_sendcng()

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

generate comfort noice (CNG)

Precondition
instance is locked

Definition at line 9528 of file res_rtp_asterisk.c.

9529{
9530 unsigned int *rtpheader;
9531 int hdrlen = 12;
9532 int res, payload = 0;
9533 char data[256];
9534 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9535 struct ast_sockaddr remote_address = { {0,} };
9536 int ice;
9537
9538 ast_rtp_instance_get_remote_address(instance, &remote_address);
9539
9540 if (ast_sockaddr_isnull(&remote_address)) {
9541 return -1;
9542 }
9543
9545
9546 level = 127 - (level & 0x7f);
9547
9548 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
9549
9550 /* Get a pointer to the header */
9551 rtpheader = (unsigned int *)data;
9552 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
9553 rtpheader[1] = htonl(rtp->lastts);
9554 rtpheader[2] = htonl(rtp->ssrc);
9555 data[12] = level;
9556
9557 res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);
9558
9559 if (res < 0) {
9560 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
9561 return res;
9562 }
9563
9564 if (rtp_debug_test_addr(&remote_address)) {
9565 ast_verbose("Sent Comfort Noise RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
9566 ast_sockaddr_stringify(&remote_address),
9567 ice ? " (via ICE)" : "",
9568 AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
9569 }
9570
9571 rtp->seqno++;
9572
9573 return res;
9574}

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

9594{
9595 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9596
9597 if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
9598 return;
9599 }
9600
9601 rtp->themssrc = ssrc;
9602 rtp->themssrc_valid = 1;
9603
9604 /* If this is bundled we need to update the SSRC mapping */
9605 if (rtp->bundled) {
9606 struct ast_rtp *bundled_rtp;
9607 int index;
9608
9609 ao2_unlock(instance);
9610
9611 /* The child lock can't be held while accessing the parent */
9612 ao2_lock(rtp->bundled);
9613 bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
9614
9615 for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
9616 struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
9617
9618 if (mapping->instance == instance) {
9619 mapping->ssrc = ssrc;
9620 mapping->ssrc_valid = 1;
9621 break;
9622 }
9623 }
9624
9625 ao2_unlock(rtp->bundled);
9626
9628 }
9629}

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

9632{
9633 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9634
9635 rtp->stream_num = stream_num;
9636}

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

9466{
9467 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9468 struct ast_sockaddr addr = { {0,} };
9469
9470#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9471 ao2_unlock(instance);
9472 AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
9473
9474 dtls_srtp_stop_timeout_timer(instance, rtp, 0);
9475 if (rtp->rtcp) {
9476 dtls_srtp_stop_timeout_timer(instance, rtp, 1);
9477 }
9478 ao2_lock(instance);
9479#endif
9480 ast_debug_rtp(1, "(%s) RTP Stop\n",
9482
9483 if (rtp->rtcp && rtp->rtcp->schedid > -1) {
9484 ao2_unlock(instance);
9485 if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
9486 /* successfully cancelled scheduler entry. */
9487 ao2_ref(instance, -1);
9488 }
9489 ao2_lock(instance);
9490 rtp->rtcp->schedid = -1;
9491 }
9492
9493 if (rtp->transport_wide_cc.schedid > -1) {
9494 ao2_unlock(instance);
9495 if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
9496 ao2_ref(instance, -1);
9497 }
9498 ao2_lock(instance);
9499 rtp->transport_wide_cc.schedid = -1;
9500 }
9501
9502 if (rtp->red) {
9503 ao2_unlock(instance);
9504 AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
9505 ao2_lock(instance);
9506 ast_free(rtp->red);
9507 rtp->red = NULL;
9508 }
9509
9510 ast_rtp_instance_set_remote_address(instance, &addr);
9511
9513}
#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 9450 of file res_rtp_asterisk.c.

9451{
9452 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9453 struct sockaddr_in suggestion_tmp;
9454
9455 /*
9456 * The instance should not be locked because we can block
9457 * waiting for a STUN respone.
9458 */
9459 ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
9460 ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
9461 ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
9462}
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition stun.c:415

References ast_rtp_instance_get_data(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_stun_request(), NULL, and ast_rtp::s.

◆ ast_rtp_update_source()

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

Definition at line 4723 of file res_rtp_asterisk.c.

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

References ast_debug_rtp, ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

◆ ast_rtp_write()

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

Definition at line 5670 of file res_rtp_asterisk.c.

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

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

References ao2_cleanup, ao2_lock, ao2_replace, ao2_unlock, ast_clear_flag, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), ast_format_none, ast_log, ast_rtp_codecs_find_payload_code(), ast_rtp_codecs_get_payload(), ast_rtp_codecs_payload_code_tx_sample_rate(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_NAT, ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_verbose, ast_rtp::asymmetric_codec, DEBUG_ATLEAST, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, FLAG_REQ_LOCAL_BRIDGE_BIT, optional_ts::is_set, ast_rtp::last_end_timestamp, ast_rtp::lastrxformat, ast_rtp::lasttxformat, len(), LOG_WARNING, NULL, RAII_VAR, reconstruct(), rtp_debug_test_addr(), rtp_sendto(), ast_rtp::sending_digit, ast_rtp::ssrc, and optional_ts::ts.

Referenced by ast_rtp_interpret().

◆ calc_mean_and_standard_deviation()

static void calc_mean_and_standard_deviation ( double  new_sample,
double *  mean,
double *  std_dev,
unsigned int *  count 
)
static

Definition at line 3559 of file res_rtp_asterisk.c.

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

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

◆ calc_media_experience_score()

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

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

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

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

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

Definition at line 6420 of file res_rtp_asterisk.c.

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

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

References ast_debug_rtcp, ast_rtp_get_rate(), ast_rtp_instance_get_channel_id(), ast_samp2sec(), ast_samp2tv(), ast_sec2samp(), ast_tv2double(), ast_tvadd(), ast_tvsub(), calc_mean_and_standard_deviation(), d, ast_rtp::f, ast_frame_subclass::format, ast_rtp::last_transit_time_samples, ast_rtp::lastrxseqno, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, ast_rtcp::normdev_rxjitter, NULL, ast_rtp::owner, ast_rtp::prevrxseqno, ast_rtp::remote_seed_rx_rtp_ts, ast_rtp::remote_seed_rx_rtp_ts_stable, ast_rtp::rtcp, RTP_IGNORE_FIRST_PACKETS_COUNT, ast_rtp::rxcore, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxjitter_samples, ast_rtp::rxstart, ast_rtp::rxstart_stable, ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

Referenced by ast_rtp_interpret().

◆ calc_txstamp()

static unsigned int calc_txstamp ( struct ast_rtp rtp,
struct timeval *  delivery 
)
static

Definition at line 4029 of file res_rtp_asterisk.c.

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

References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.

Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), and rtp_raw_write().

◆ calculate_lost_packet_statistics()

static void calculate_lost_packet_statistics ( struct ast_rtp rtp,
unsigned int *  lost_packets,
int *  fraction_lost 
)
static

Definition at line 4803 of file res_rtp_asterisk.c.

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

References calc_mean_and_standard_deviation(), and ast_srtp::rtp.

Referenced by ast_rtcp_generate_report().

◆ compare_by_value()

static int compare_by_value ( int  elem,
int  value 
)
static

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

Definition at line 3191 of file res_rtp_asterisk.c.

3192{
3193 return elem - value;
3194}

References value.

Referenced by ast_rtp_read().

◆ create_dtmf_frame()

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

Definition at line 5990 of file res_rtp_asterisk.c.

5991{
5992 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5993 struct ast_sockaddr remote_address = { {0,} };
5994
5995 ast_rtp_instance_get_remote_address(instance, &remote_address);
5996
5997 if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
5998 ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
5999 instance, ast_sockaddr_stringify(&remote_address));
6000 rtp->resp = 0;
6001 rtp->dtmfsamples = 0;
6002 return &ast_null_frame;
6003 } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
6004 ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
6005 instance, ast_sockaddr_stringify(&remote_address));
6006 rtp->resp = 0;
6007 rtp->dtmfsamples = 0;
6008 return &ast_null_frame;
6009 }
6010
6011 if (rtp->resp == 'X') {
6012 ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
6013 instance, ast_sockaddr_stringify(&remote_address));
6016 } else {
6017 ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
6018 instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
6019 rtp->resp, rtp->resp,
6020 ast_sockaddr_stringify(&remote_address));
6021 rtp->f.frametype = type;
6022 rtp->f.subclass.integer = rtp->resp;
6023 }
6024 rtp->f.datalen = 0;
6025 rtp->f.samples = 0;
6026 rtp->f.mallocd = 0;
6027 rtp->f.src = "RTP";
6028 AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
6029
6030 return &rtp->f;
6031}
static const char type[]
@ AST_FRAME_DTMF_BEGIN
@ AST_CONTROL_FLASH
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
unsigned int dtmfsamples
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition time.h:137

References AST_CONTROL_FLASH, ast_debug_rtp, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_stringify(), ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, NULL, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and type.

Referenced by ast_rtp_interpret(), process_dtmf_cisco(), and process_dtmf_rfc2833().

◆ create_new_socket()

static int create_new_socket ( const char *  type,
struct ast_sockaddr bind_addr 
)
static

Definition at line 3587 of file res_rtp_asterisk.c.

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

References ast_log, ast_sockaddr_is_any(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_socket_nonblock, errno, LOG_WARNING, and type.

Referenced by ast_rtp_prop_set(), and rtp_allocate_transport().

◆ find_by_value()

static int find_by_value ( int  elem,
int  value 
)
static

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

Definition at line 3197 of file res_rtp_asterisk.c.

3198{
3199 return elem == value;
3200}

References value.

Referenced by ast_rtcp_generate_nack(), and ast_rtp_read().

◆ handle_cli_rtcp_set_debug()

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

Definition at line 9973 of file res_rtp_asterisk.c.

9974{
9975 switch (cmd) {
9976 case CLI_INIT:
9977 e->command = "rtcp set debug {on|off|ip}";
9978 e->usage =
9979 "Usage: rtcp set debug {on|off|ip host[:port]}\n"
9980 " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
9981 " specified, limit the dumped packets to those to and from\n"
9982 " the specified 'host' with optional port.\n";
9983 return NULL;
9984 case CLI_GENERATE:
9985 return NULL;
9986 }
9987
9988 if (a->argc == e->args) { /* set on or off */
9989 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9991 memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
9992 ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
9993 return CLI_SUCCESS;
9994 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9996 ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
9997 return CLI_SUCCESS;
9998 }
9999 } else if (a->argc == e->args +1) { /* ip */
10000 return rtcp_do_debug_ip(a);
10001 }
10002
10003 return CLI_SHOWUSAGE; /* default, failure */
10004}
#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 10006 of file res_rtp_asterisk.c.

10007{
10008 switch (cmd) {
10009 case CLI_INIT:
10010 e->command = "rtcp set stats {on|off}";
10011 e->usage =
10012 "Usage: rtcp set stats {on|off}\n"
10013 " Enable/Disable dumping of RTCP stats.\n";
10014 return NULL;
10015 case CLI_GENERATE:
10016 return NULL;
10017 }
10018
10019 if (a->argc != e->args)
10020 return CLI_SHOWUSAGE;
10021
10022 if (!strncasecmp(a->argv[e->args-1], "on", 2))
10023 rtcpstats = 1;
10024 else if (!strncasecmp(a->argv[e->args-1], "off", 3))
10025 rtcpstats = 0;
10026 else
10027 return CLI_SHOWUSAGE;
10028
10029 ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
10030 return CLI_SUCCESS;
10031}
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 9872 of file res_rtp_asterisk.c.

9873{
9874 switch (cmd) {
9875 case CLI_INIT:
9876 e->command = "rtp set debug {on|off|ip}";
9877 e->usage =
9878 "Usage: rtp set debug {on|off|ip host[:port]}\n"
9879 " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9880 " specified, limit the dumped packets to those to and from\n"
9881 " the specified 'host' with optional port.\n";
9882 return NULL;
9883 case CLI_GENERATE:
9884 return NULL;
9885 }
9886
9887 if (a->argc == e->args) { /* set on or off */
9888 if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9890 memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
9891 ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
9892 return CLI_SUCCESS;
9893 } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9895 ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
9896 return CLI_SUCCESS;
9897 }
9898 } else if (a->argc == e->args +1) { /* ip */
9899 return rtp_do_debug_ip(a);
9900 }
9901
9902 return CLI_SHOWUSAGE; /* default, failure */
9903}
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 9906 of file res_rtp_asterisk.c.

9907{
9908#ifdef HAVE_PJPROJECT
9909 struct sockaddr_in stunaddr_copy;
9910 const char *stun_hostname_copy = NULL;
9911 int stunaddr_ttl_copy = 0;
9912#endif
9913 switch (cmd) {
9914 case CLI_INIT:
9915 e->command = "rtp show settings";
9916 e->usage =
9917 "Usage: rtp show settings\n"
9918 " Display RTP configuration settings\n";
9919 return NULL;
9920 case CLI_GENERATE:
9921 return NULL;
9922 }
9923
9924 if (a->argc != 3) {
9925 return CLI_SHOWUSAGE;
9926 }
9927
9928 ast_cli(a->fd, "\n\nGeneral Settings:\n");
9929 ast_cli(a->fd, "----------------\n");
9930 ast_cli(a->fd, " Port start: %d\n", rtpstart);
9931 ast_cli(a->fd, " Port end: %d\n", rtpend);
9932#ifdef SO_NO_CHECK
9933 ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
9934#endif
9935 ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
9936 ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
9937
9938 if (strictrtp) {
9939 ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
9940 }
9941
9942 ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
9943#ifdef HAVE_PJPROJECT
9944 ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
9945
9946 ast_rwlock_rdlock(&stunaddr_lock);
9947 memcpy(&stunaddr_copy, &stunaddr, sizeof(stunaddr));
9948 stun_hostname_copy = ast_strdupa(S_OR(stun_hostname, ""));
9949 stunaddr_ttl_copy = stunaddr_ttl;
9950 ast_rwlock_unlock(&stunaddr_lock);
9951
9952 ast_cli(a->fd, " STUN: %s\n", stunaddr_copy.sin_addr.s_addr ? "enbabled" : "disabled");
9953 if (ast_strlen_zero(stun_hostname_copy)) {
9954 ast_cli(a->fd, " Address: %s:%d\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
9955 htons(stunaddr_copy.sin_port));
9956 } else {
9957 ast_cli(a->fd, " Hostname: %s:%d\n", stun_hostname_copy, htons(stunaddr_copy.sin_port));
9958 ast_cli(a->fd, " Resolved Addr: %s:%d%s\n", ast_inet_ntoa(stunaddr_copy.sin_addr),
9959 htons(stunaddr_copy.sin_port),
9960 stunaddr_copy.sin_addr.s_addr ? stunaddr_resolver ? "" : " (possibly stale)" : " (lookup failed)");
9961 ast_cli(a->fd, " Last TTL: %d (periodic resolution %s)\n", stunaddr_ttl_copy,
9962 stunaddr_resolver ? "enabled" : "disabled");
9963 ast_cli(a->fd, " Reresove TTL 0: %s\n", AST_CLI_YESNO(stunaddr_reresolve_ttl_0));
9964 }
9965 if (stun_acl) {
9966 ast_acl_output(a->fd, stun_acl, " ");
9967 }
9968#endif
9969 return CLI_SUCCESS;
9970}
void ast_acl_output(int fd, struct ast_acl_list *acl, const char *prefix)
output an ACL to the provided fd
Definition acl.c:1115
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition cli.h:71
#define ast_rwlock_rdlock(a)
Definition lock.h:242
#define ast_rwlock_unlock(a)
Definition lock.h:241
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition utils.c:962
static int rtpend
static int learning_min_sequential
static int rtpstart
static int dtmftimeout
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 10562 of file res_rtp_asterisk.c.

10563{
10564#ifdef HAVE_PJPROJECT
10565 pj_lock_t *lock;
10566
10568
10570 if (pj_init() != PJ_SUCCESS) {
10572 }
10573
10574 if (pjlib_util_init() != PJ_SUCCESS) {
10575 rtp_terminate_pjproject();
10577 }
10578
10579 if (pjnath_init() != PJ_SUCCESS) {
10580 rtp_terminate_pjproject();
10582 }
10583
10584 ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
10585
10586 pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
10587
10588 if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
10589 rtp_terminate_pjproject();
10591 }
10592
10593 if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
10594 rtp_terminate_pjproject();
10596 }
10597
10598 pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
10599
10600 if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
10601 rtp_terminate_pjproject();
10603 }
10604
10605#endif
10606
10607#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10608 dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
10609 if (!dtls_bio_methods) {
10610#ifdef HAVE_PJPROJECT
10611 rtp_terminate_pjproject();
10612#endif
10614 }
10615 BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
10616 BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
10617 BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
10618 BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
10619#endif
10620
10622#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10623 BIO_meth_free(dtls_bio_methods);
10624#endif
10625#ifdef HAVE_PJPROJECT
10626 rtp_terminate_pjproject();
10627#endif
10629 }
10630
10632#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10633 BIO_meth_free(dtls_bio_methods);
10634#endif
10635#ifdef HAVE_PJPROJECT
10637 rtp_terminate_pjproject();
10638#endif
10640 }
10641
10642 rtp_reload(0, 0);
10643
10645}
ast_mutex_t lock
Definition app_sla.c:337
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition netsock2.c:230
#define AST_PJPROJECT_INIT_LOG_LEVEL()
Get maximum log level pjproject was compiled with.
Definition options.h:177
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static int rtp_reload(int reload, int by_external_config)
static struct ast_rtp_engine asterisk_rtp_engine
static struct ast_cli_entry cli_rtp[]
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition rtp_engine.c:374
#define ast_rtp_engine_register(engine)
Definition rtp_engine.h:852
#define ARRAY_LEN(a)
Definition utils.h:706

References ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_pjproject_caching_pool_init(), AST_PJPROJECT_INIT_LOG_LEVEL, ast_rtp_engine_register, ast_rtp_engine_unregister(), ast_sockaddr_parse(), asterisk_rtp_engine, cachingpool, cli_rtp, lock, NULL, PARSE_PORT_IGNORE, and rtp_reload().

◆ ntp2timeval()

static void ntp2timeval ( unsigned int  msw,
unsigned int  lsw,
struct timeval *  tv 
)
static

Definition at line 4796 of file res_rtp_asterisk.c.

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

Referenced by ast_rtcp_interpret().

◆ process_cn_rfc3389()

static struct ast_frame * process_cn_rfc3389 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
int  payloadtype,
int  mark 
)
static

Definition at line 6251 of file res_rtp_asterisk.c.

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

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

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

References ast_debug, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup, AST_LIST_INSERT_TAIL, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), ast_verbose, create_dtmf_frame(), ast_frame::data, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, dtmftimeout, ast_frame_subclass::format, frames, optional_ts::is_set, ast_rtp::last_end_timestamp, ast_rtp::last_seqno, len(), ast_frame::len, NULL, ast_rtp::resp, rtp_debug_test_addr(), ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and optional_ts::ts.

Referenced by ast_rtp_interpret().

◆ put_unaligned_time24()

static void put_unaligned_time24 ( void *  p,
uint32_t  time_msw,
uint32_t  time_lsw 
)
static

Definition at line 5258 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_rtcp_handle_nack(), rtp_raw_write(), and rtp_transport_wide_cc_feedback_produce().

◆ red_t140_to_red()

static struct ast_frame * red_t140_to_red ( struct rtp_red red)
static

Definition at line 5503 of file res_rtp_asterisk.c.

5504{
5505 unsigned char *data = red->t140red.data.ptr;
5506 int len = 0;
5507 int i;
5508
5509 /* replace most aged generation */
5510 if (red->len[0]) {
5511 for (i = 1; i < red->num_gen+1; i++)
5512 len += red->len[i];
5513
5514 memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
5515 }
5516
5517 /* Store length of each generation and primary data length*/
5518 for (i = 0; i < red->num_gen; i++)
5519 red->len[i] = red->len[i+1];
5520 red->len[i] = red->t140.datalen;
5521
5522 /* write each generation length in red header */
5523 len = red->hdrlen;
5524 for (i = 0; i < red->num_gen; i++) {
5525 len += data[i*4+3] = red->len[i];
5526 }
5527
5528 /* add primary data to buffer */
5529 memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
5530 red->t140red.datalen = len + red->t140.datalen;
5531
5532 /* no primary data and no generations to send */
5533 if (len == red->hdrlen && !red->t140.datalen) {
5534 return NULL;
5535 }
5536
5537 /* reset t.140 buffer */
5538 red->t140.datalen = 0;
5539
5540 return &red->t140red;
5541}
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 9258 of file res_rtp_asterisk.c.

9259{
9260 struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
9261 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9262
9263 ao2_lock(instance);
9264 if (rtp->red->t140.datalen > 0) {
9265 ast_rtp_write(instance, &rtp->red->t140);
9266 }
9267 ao2_unlock(instance);
9268
9269 return 1;
9270}
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 10530 of file res_rtp_asterisk.c.

10531{
10532 rtp_reload(1, 0);
10533 return 0;
10534}

References rtp_reload().

◆ rtcp_debug_test_addr()

static int rtcp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2853 of file res_rtp_asterisk.c.

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

References ast_debug_rtcp_packet_is_allowed, ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), rtcpdebugaddr, and rtcpdebugport.

Referenced by ast_rtcp_calculate_sr_rr_statistics(), and ast_rtcp_interpret().

◆ rtcp_do_debug_ip()

static char * rtcp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9855 of file res_rtp_asterisk.c.

9856{
9857 char *arg = ast_strdupa(a->argv[4]);
9858 char *debughost = NULL;
9859 char *debugport = NULL;
9860
9861 if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9862 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9863 return CLI_FAILURE;
9864 }
9865 rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9866 ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9869 return CLI_SUCCESS;
9870}
#define CLI_FAILURE
Definition cli.h:46
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition netsock2.c:164

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

Referenced by handle_cli_rtcp_set_debug().

◆ rtcp_mux()

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

Definition at line 3202 of file res_rtp_asterisk.c.

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

References AST_RTP_INSTANCE_RTCP_MUX, ast_rtp::rtcp, ast_rtcp::type, and version.

Referenced by ast_rtp_read().

◆ rtcp_payload_subtype2str()

static const char * rtcp_payload_subtype2str ( unsigned int  pt,
unsigned int  subtype 
)
static

Definition at line 6623 of file res_rtp_asterisk.c.

6624{
6625 switch (pt) {
6626 case AST_RTP_RTCP_RTPFB:
6627 if (subtype == AST_RTP_RTCP_FMT_NACK) {
6628 return "NACK";
6629 }
6630 break;
6631 case RTCP_PT_PSFB:
6632 if (subtype == AST_RTP_RTCP_FMT_REMB) {
6633 return "REMB";
6634 }
6635 break;
6636 default:
6637 break;
6638 }
6639
6640 return NULL;
6641}

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

6592{
6593 const char *str;
6594
6595 switch (pt) {
6596 case RTCP_PT_SR:
6597 str = "Sender Report";
6598 break;
6599 case RTCP_PT_RR:
6600 str = "Receiver Report";
6601 break;
6602 case RTCP_PT_FUR:
6603 /* Full INTRA-frame Request / Fast Update Request */
6604 str = "H.261 FUR";
6605 break;
6606 case RTCP_PT_PSFB:
6607 /* Payload Specific Feed Back */
6608 str = "PSFB";
6609 break;
6610 case RTCP_PT_SDES:
6611 str = "Source Description";
6612 break;
6613 case RTCP_PT_BYE:
6614 str = "BYE";
6615 break;
6616 default:
6617 str = "Unknown";
6618 break;
6619 }
6620 return str;
6621}
const char * str
Definition app_jack.c:150

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

Referenced by ast_rtcp_interpret().

◆ rtcp_recvfrom()

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

Definition at line 3452 of file res_rtp_asterisk.c.

3453{
3454 return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
3455}
static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)

References __rtp_recvfrom(), and buf.

Referenced by ast_rtcp_read().

◆ rtcp_sendto()

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

Definition at line 3530 of file res_rtp_asterisk.c.

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

References __rtp_sendto(), and buf.

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

◆ rtp_allocate_transport()

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

Definition at line 4141 of file res_rtp_asterisk.c.

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

References ast_bind(), ast_cond_init, ast_debug_ice, ast_debug_rtp, ast_log, ast_random(), ast_rtp_instance_get_port_end(), ast_rtp_instance_get_port_start(), ast_rtp_instance_set_local_address(), ast_sockaddr_copy(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_test_suite_event_notify, ast_rtp::bind_address, create_new_socket(), errno, generate_random_string(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, rtpend, rtpstart, ast_rtp::s, STRICT_RTP_CLOSED, STRICT_RTP_OPEN, ast_rtp::strict_rtp_state, and strictrtp.

Referenced by ast_rtp_bundle(), and ast_rtp_new().

◆ rtp_deallocate_transport()

static void rtp_deallocate_transport ( struct ast_rtp_instance instance,
struct ast_rtp rtp 
)
static

Definition at line 4226 of file res_rtp_asterisk.c.

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

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

Referenced by ast_rtp_bundle(), and ast_rtp_destroy().

◆ rtp_debug_test_addr()

static int rtp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2837 of file res_rtp_asterisk.c.

2838{
2840 return 0;
2841 }
2843 if (rtpdebugport) {
2844 return (ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0); /* look for RTP packets from IP+Port */
2845 } else {
2846 return (ast_sockaddr_cmp_addr(&rtpdebugaddr, addr) == 0); /* only look for RTP packets from IP */
2847 }
2848 }
2849
2850 return 1;
2851}
static int rtpdebugport

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

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

◆ rtp_do_debug_ip()

static char * rtp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9838 of file res_rtp_asterisk.c.

9839{
9840 char *arg = ast_strdupa(a->argv[4]);
9841 char *debughost = NULL;
9842 char *debugport = NULL;
9843
9844 if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9845 ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9846 return CLI_FAILURE;
9847 }
9848 rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9849 ast_cli(a->fd, "RTP Packet Debugging Enabled for address: %s\n",
9852 return CLI_SUCCESS;
9853}

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

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

6580{
6581 return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
6582}

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

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

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

7515{
7516 if (instance) {
7517 ao2_unlock(instance);
7518 }
7519}

References ao2_unlock.

Referenced by ast_rtp_read().

◆ rtp_learning_rtp_seq_update()

static int rtp_learning_rtp_seq_update ( struct rtp_learning_info info,
uint16_t  seq 
)
static

Definition at line 3643 of file res_rtp_asterisk.c.

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

References AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_END, AST_MEDIA_TYPE_IMAGE, AST_MEDIA_TYPE_TEXT, AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), learning_min_duration, learning_min_sequential, seq, STRICT_RTP_YES, and strictrtp.

Referenced by ast_rtp_read().

◆ rtp_learning_seq_init()

static void rtp_learning_seq_init ( struct rtp_learning_info info,
uint16_t  seq 
)
static

Definition at line 3626 of file res_rtp_asterisk.c.

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

References learning_min_sequential, and seq.

Referenced by ast_rtp_read(), and rtp_learning_start().

◆ rtp_learning_start()

static void rtp_learning_start ( struct ast_rtp rtp)
static

Start the strictrtp learning mode.

Parameters
rtpRTP session description

Definition at line 3691 of file res_rtp_asterisk.c.

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

References ast_tvnow(), ast_rtp::lastrxseqno, rtp_learning_info::proposed_address, rtp_learning_seq_init(), ast_rtp::rtp_source_learn, rtp_learning_info::start, STRICT_RTP_LEARN, and ast_rtp::strict_rtp_state.

Referenced by ast_rtp_remote_address_set().

◆ rtp_raw_write()

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

Definition at line 5273 of file res_rtp_asterisk.c.

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

References abs, ao2_ref, ast_clear_flag, ast_data_buffer_put(), ast_debug, ast_debug_rtcp, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_g722, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_free, AST_FRFLAG_HAS_SEQUENCE_NUMBER, AST_FRFLAG_HAS_TIMING_INFO, ast_log, ast_malloc, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_EXTENSION_ABS_SEND_TIME, ast_rtp_get_rate(), ast_rtp_instance_extmap_get_id(), ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_NAT, ast_sched_add(), ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_tvnow(), ast_tvzero(), ast_verbose, ast_rtp_rtcp_nack_payload::buf, calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, ast_rtp::expectedseqno, ext, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_frame_subclass::format, ast_frame_subclass::frame_ending, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_WARNING, MAX_TIMESTAMP_SKEW, ast_frame::ptr, put_unaligned_time24(), put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_sendto(), ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::send_buffer, ast_rtp::sending_digit, ast_frame::seqno, ast_rtp::seqno, ast_rtp_rtcp_nack_payload::size, ast_rtp::ssrc, ast_frame::subclass, timeval2ntp(), and ast_frame::ts.

Referenced by ast_rtp_write().

◆ rtp_recvfrom()

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

Definition at line 3458 of file res_rtp_asterisk.c.

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

References __rtp_recvfrom(), and buf.

Referenced by ast_rtp_read().

◆ rtp_red_buffer()

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

Definition at line 9305 of file res_rtp_asterisk.c.

9306{
9307 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9308 struct rtp_red *red = rtp->red;
9309
9310 if (!red) {
9311 return 0;
9312 }
9313
9314 if (frame->datalen > 0) {
9315 if (red->t140.datalen > 0) {
9316 const unsigned char *primary = red->buf_data;
9317
9318 /* There is something already in the T.140 buffer */
9319 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9320 /* Flush the previous T.140 packet if it is a command */
9321 ast_rtp_write(instance, &rtp->red->t140);
9322 } else {
9323 primary = frame->data.ptr;
9324 if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
9325 /* Flush the previous T.140 packet if we are buffering a command now */
9326 ast_rtp_write(instance, &rtp->red->t140);
9327 }
9328 }
9329 }
9330
9331 memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
9332 red->t140.datalen += frame->datalen;
9333 red->t140.ts = frame->ts;
9334 }
9335
9336 return 0;
9337}
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 9273 of file res_rtp_asterisk.c.

9274{
9275 struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
9276 int x;
9277
9278 rtp->red = ast_calloc(1, sizeof(*rtp->red));
9279 if (!rtp->red) {
9280 return -1;
9281 }
9282
9285 rtp->red->t140.data.ptr = &rtp->red->buf_data;
9286
9287 rtp->red->t140red = rtp->red->t140;
9288 rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
9289
9290 rtp->red->num_gen = generations;
9291 rtp->red->hdrlen = generations * 4 + 1;
9292
9293 for (x = 0; x < generations; x++) {
9294 rtp->red->pt[x] = payloads[x];
9295 rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
9296 rtp->red->t140red_data[x*4] = rtp->red->pt[x];
9297 }
9298 rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
9299 rtp->red->schedid = ast_sched_add(rtp->sched, buffer_time, red_write, instance);
9300
9301 return 0;
9302}
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 10226 of file res_rtp_asterisk.c.

10227{
10228 struct ast_config *cfg;
10229 const char *s;
10230 struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
10231
10232#ifdef HAVE_PJPROJECT
10233 struct ast_variable *var;
10234 struct ast_ice_host_candidate *candidate;
10235 int acl_subscription_flag = 0;
10236#endif
10237
10238 cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
10239 if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
10240 return 0;
10241 }
10242
10243#ifdef SO_NO_CHECK
10244 nochecksums = 0;
10245#endif
10246
10255
10256 /** This resource is not "reloaded" so much as unloaded and loaded again.
10257 * In the case of the TURN related variables, the memory referenced by a
10258 * previously loaded instance *should* have been released when the
10259 * corresponding pool was destroyed. If at some point in the future this
10260 * resource were to support ACTUAL live reconfiguration and did NOT release
10261 * the pool this will cause a small memory leak.
10262 */
10263
10264#ifdef HAVE_PJPROJECT
10265 icesupport = DEFAULT_ICESUPPORT;
10266 stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE;
10267 turnport = DEFAULT_TURN_PORT;
10268 clean_stunaddr();
10269 turnaddr = pj_str(NULL);
10270 turnusername = pj_str(NULL);
10271 turnpassword = pj_str(NULL);
10272 host_candidate_overrides_clear();
10273#endif
10274
10275#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10276 dtls_mtu = DEFAULT_DTLS_MTU;
10277#endif
10278
10279 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
10280 rtpstart = atoi(s);
10285 }
10286 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
10287 rtpend = atoi(s);
10292 }
10293 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
10294 rtcpinterval = atoi(s);
10295 if (rtcpinterval == 0)
10296 rtcpinterval = 0; /* Just so we're clear... it's zero */
10298 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
10301 }
10302 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
10303#ifdef SO_NO_CHECK
10304 nochecksums = ast_false(s) ? 1 : 0;
10305#else
10306 if (ast_false(s))
10307 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10308#endif
10309 }
10310 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
10311 dtmftimeout = atoi(s);
10312 if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
10313 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
10316 };
10317 }
10318 if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
10319 if (ast_true(s)) {
10321 } else if (!strcasecmp(s, "seqno")) {
10323 } else {
10325 }
10326 }
10327 if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
10328 if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
10329 ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
10332 }
10334 }
10335 if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
10337 }
10338#ifdef HAVE_PJPROJECT
10339 if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
10340 icesupport = ast_true(s);
10341 }
10342 if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
10343 stun_software_attribute = ast_true(s);
10344 }
10345 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr_reresolve_ttl_0"))) {
10346 stunaddr_reresolve_ttl_0 = ast_true(s);
10347 }
10348 if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
10349 char *hostport, *host, *port;
10350 unsigned int port_parsed = STANDARD_STUN_PORT;
10351 struct ast_sockaddr stunaddr_parsed;
10352
10353 hostport = ast_strdupa(s);
10354
10355 if (!ast_parse_arg(hostport, PARSE_ADDR, &stunaddr_parsed)) {
10356 ast_debug_stun(3, "stunaddr = '%s' does not need name resolution\n",
10357 ast_sockaddr_stringify_host(&stunaddr_parsed));
10358 if (!ast_sockaddr_port(&stunaddr_parsed)) {
10359 ast_sockaddr_set_port(&stunaddr_parsed, STANDARD_STUN_PORT);
10360 }
10361 ast_rwlock_wrlock(&stunaddr_lock);
10362 ast_sockaddr_to_sin(&stunaddr_parsed, &stunaddr);
10363 /* Set stunaddr_ttl = -1 to indicate no resolution required in the future */
10364 stunaddr_ttl = -1;
10365 ast_rwlock_unlock(&stunaddr_lock);
10366 } else if (ast_sockaddr_split_hostport(hostport, &host, &port, 0)) {
10367 if (port) {
10368 ast_parse_arg(port, PARSE_UINT32|PARSE_IN_RANGE, &port_parsed, 1, 65535);
10369 }
10370
10371 ast_rwlock_wrlock(&stunaddr_lock);
10372
10373 stunaddr.sin_port = htons(port_parsed);
10374 ast_free(stun_hostname);
10375 stun_hostname = ast_strdup(host);
10376 if (!stun_hostname) {
10377 ast_log(LOG_ERROR, "Failed to set stun_hostname from '%s'", host);
10378 } else {
10379 stunaddr_resolver = ast_dns_resolve_recurring(host, T_A, C_IN,
10380 &stunaddr_resolve_callback, NULL);
10381 if (!stunaddr_resolver) {
10382 ast_log(LOG_ERROR, "Failed to setup recurring DNS resolution of stunaddr '%s'",
10383 host);
10384 } else {
10385 ast_debug_stun(2, "Attemping to start recurring stun hostname resolution for '%s'\n", stun_hostname);
10386 }
10387 /*
10388 * Set stunaddr_ttl = 0 to indicate resolution is required.
10389 * If a later query returns a positive ttl, great. We'll use the results
10390 * of the last query until it expires. If it returns 0, we'll resolve
10391 * every time we need it.
10392 */
10393 stunaddr_ttl = 0;
10394 }
10395 ast_rwlock_unlock(&stunaddr_lock);
10396
10397
10398 } else {
10399 ast_log(LOG_ERROR, "Failed to parse stunaddr '%s'", hostport);
10400 }
10401 }
10402 if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
10403 struct sockaddr_in addr;
10404 addr.sin_port = htons(DEFAULT_TURN_PORT);
10405 if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
10406 ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
10407 } else {
10408 pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
10409 /* ntohs() is not a bug here. The port number is used in host byte order with
10410 * a pjnat API. */
10411 turnport = ntohs(addr.sin_port);
10412 }
10413 }
10414 if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
10415 pj_strdup2_with_null(pool, &turnusername, s);
10416 }
10417 if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
10418 pj_strdup2_with_null(pool, &turnpassword, s);
10419 }
10420
10421 AST_RWLIST_WRLOCK(&host_candidates);
10422 for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
10423 struct ast_sockaddr local_addr, advertised_addr;
10424 unsigned int include_local_address = 0;
10425 char *sep;
10426
10427 ast_sockaddr_setnull(&local_addr);
10428 ast_sockaddr_setnull(&advertised_addr);
10429
10430 if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
10431 ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
10432 continue;
10433 }
10434
10435 sep = strchr((char *)var->value,',');
10436 if (sep) {
10437 *sep = '\0';
10438 sep++;
10439 sep = ast_skip_blanks(sep);
10440 include_local_address = strcmp(sep, "include_local_address") == 0;
10441 }
10442
10443 if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
10444 ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
10445 continue;
10446 }
10447
10448 if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
10449 ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
10450 break;
10451 }
10452
10453 candidate->include_local = include_local_address;
10454
10455 ast_sockaddr_copy(&candidate->local, &local_addr);
10456 ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
10457
10458 AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
10459 }
10460 AST_RWLIST_UNLOCK(&host_candidates);
10461
10462 ast_rwlock_wrlock(&ice_acl_lock);
10463 ast_rwlock_wrlock(&stun_acl_lock);
10464
10465 ice_acl = ast_free_acl_list(ice_acl);
10466 stun_acl = ast_free_acl_list(stun_acl);
10467
10468 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
10469 const char* sense = NULL;
10470 struct ast_acl_list **acl = NULL;
10471 if (strncasecmp(var->name, "ice_", 4) == 0) {
10472 sense = var->name + 4;
10473 acl = &ice_acl;
10474 } else if (strncasecmp(var->name, "stun_", 5) == 0) {
10475 sense = var->name + 5;
10476 acl = &stun_acl;
10477 } else {
10478 continue;
10479 }
10480
10481 if (strcasecmp(sense, "blacklist") == 0) {
10482 sense = "deny";
10483 }
10484
10485 if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
10486 continue;
10487 }
10488
10489 ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
10490 }
10491 ast_rwlock_unlock(&ice_acl_lock);
10492 ast_rwlock_unlock(&stun_acl_lock);
10493
10494 if (acl_subscription_flag && !acl_change_sub) {
10498 } else if (!acl_subscription_flag && acl_change_sub) {
10500 }
10501#endif
10502#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
10503 if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
10504 if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
10505 ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
10507 dtls_mtu = DEFAULT_DTLS_MTU;
10508 }
10509 }
10510#endif
10511
10512 ast_config_destroy(cfg);
10513
10514 /* Choosing an odd start port casues issues (like a potential infinite loop) and as odd parts are not
10515 chosen anyway, we are going to round up and issue a warning */
10516 if (rtpstart & 1) {
10517 rtpstart++;
10518 ast_log(LOG_WARNING, "Odd start value for RTP port in rtp.conf, rounding up to %d\n", rtpstart);
10519 }
10520
10521 if (rtpstart >= rtpend) {
10522 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
10525 }
10526 ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
10527 return 0;
10528}
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
Definition acl.c:429
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition acl.c:233
#define var
Definition ast_expr2f.c:605
static struct stasis_subscription * acl_change_sub
Definition chan_iax2.c:365
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition chan_iax2.c:1597
struct ast_dns_query_recurring * ast_dns_resolve_recurring(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query, and continue resolving it according to the lowest TTL available.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_INSERT_TAIL
#define ast_rwlock_wrlock(a)
Definition lock.h:243
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition netsock2.h:327
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition netsock2.h:138
static int reload(void)
#define DEFAULT_ICESUPPORT
#define DEFAULT_LEARNING_MIN_SEQUENTIAL
#define DEFAULT_RTP_END
#define RTCP_DEFAULT_INTERVALMS
#define DEFAULT_DTMF_TIMEOUT
#define RTCP_MAX_INTERVALMS
#define DEFAULT_SRTP_REPLAY_PROTECTION
#define DEFAULT_DTLS_MTU
#define DEFAULT_RTP_START
#define MINIMUM_RTP_PORT
#define RTCP_MIN_INTERVALMS
#define CALC_LEARNING_MIN_DURATION(count)
Calculate the min learning duration in ms.
#define MAXIMUM_RTP_PORT
#define DEFAULT_STRICT_RTP
#define DEFAULT_TURN_PORT
#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE
#define DEFAULT_LEARNING_MIN_DURATION
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition stasis.c:1090
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition stasis.c:1144
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1201
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2233
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition utils.c:2250
char *attribute_pure ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition strings.h:161
Wrapper for an ast_acl linked list.
Definition acl.h:76
Structure used to handle boolean flags.
Definition utils.h:220
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
static const int STANDARD_STUN_PORT
Definition stun.h:61

References acl_change_stasis_cb(), acl_change_sub, ast_append_acl(), ast_calloc, ast_config_destroy(), ast_config_load2(), ast_debug_stun, ast_dns_resolve_recurring(), ast_false(), ast_free, ast_free_acl_list(), ast_inet_ntoa(), ast_log, ast_named_acl_change_type(), ast_parse_arg(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rwlock_unlock, ast_rwlock_wrlock, ast_security_topic(), ast_skip_blanks(), ast_sockaddr_copy(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_setnull(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify_host(), ast_sockaddr_to_sin, ast_strdup, ast_strdupa, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CALC_LEARNING_MIN_DURATION, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTLS_MTU, DEFAULT_DTMF_TIMEOUT, DEFAULT_ICESUPPORT, DEFAULT_LEARNING_MIN_DURATION, DEFAULT_LEARNING_MIN_SEQUENTIAL, DEFAULT_RTP_END, DEFAULT_RTP_START, DEFAULT_SRTP_REPLAY_PROTECTION, DEFAULT_STRICT_RTP, DEFAULT_STUN_SOFTWARE_ATTRIBUTE, DEFAULT_TURN_PORT, dtmftimeout, learning_min_duration, learning_min_sequential, LOG_ERROR, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, ast_variable::next, NULL, PARSE_ADDR, PARSE_IN_RANGE, PARSE_INADDR, PARSE_PORT_IGNORE, PARSE_UINT32, reload(), RTCP_DEFAULT_INTERVALMS, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, srtp_replay_protection, STANDARD_STUN_PORT, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), stasis_unsubscribe_and_join(), STRICT_RTP_NO, STRICT_RTP_SEQNO, STRICT_RTP_YES, strictrtp, and var.

Referenced by load_module(), and reload_module().

◆ rtp_sendto()

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

Definition at line 3536 of file res_rtp_asterisk.c.

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

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

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

◆ rtp_transport_wide_cc_feedback_produce()

static int rtp_transport_wide_cc_feedback_produce ( const void *  data)
static

Definition at line 7597 of file res_rtp_asterisk.c.

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

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

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

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

7523{
7524 return a.seqno - b.seqno;
7525}
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 5543 of file res_rtp_asterisk.c.

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

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

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

References ao2_cleanup, ao2_lock, ao2_unlock, ast_debug_rtcp, ast_log, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_REMB, AST_RTP_RTCP_FMT_REMB, ast_rtp_rtcp_report_alloc(), ast_sockaddr_isnull(), ast_rtp_rtcp_feedback_remb::br_exp, ast_rtp_rtcp_feedback_remb::br_mantissa, ast_rtp::bundled, ast_frame::data, errno, ast_rtp_rtcp_feedback::fmt, LOG_ERROR, NULL, ast_frame::ptr, put_unaligned_uint32(), RAII_VAR, ast_rtp_rtcp_feedback::remb, ast_rtp::rtcp, RTCP_PT_PSFB, rtcp_sendto(), ast_rtcp::schedid, ast_rtp::ssrc, ast_rtcp::them, and ast_rtp::themssrc_valid.

Referenced by ast_rtp_write().

◆ timeval2ntp()

static void timeval2ntp ( struct timeval  tv,
unsigned int *  msw,
unsigned int *  lsw 
)
static

Definition at line 4767 of file res_rtp_asterisk.c.

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

Referenced by ast_rtcp_generate_report(), ast_rtcp_interpret(), ast_rtp_rtcp_handle_nack(), rtp_raw_write(), rtp_transport_wide_cc_feedback_produce(), and update_rtt_stats().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 10647 of file res_rtp_asterisk.c.

10648{
10651
10652#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
10653 if (dtls_bio_methods) {
10654 BIO_meth_free(dtls_bio_methods);
10655 }
10656#endif
10657
10658#ifdef HAVE_PJPROJECT
10659 host_candidate_overrides_clear();
10660 pj_thread_register_check();
10661 rtp_terminate_pjproject();
10662
10664 rtp_unload_acl(&ice_acl_lock, &ice_acl);
10665 rtp_unload_acl(&stun_acl_lock, &stun_acl);
10666 clean_stunaddr();
10667#endif
10668
10669 return 0;
10670}
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 6520 of file res_rtp_asterisk.c.

6521{
6523 rtp->rtcp->normdevrtt,
6524 rtp->rxjitter,
6525 rtp->rtcp->stdev_rxjitter,
6526 rtp->rtcp->normdev_rxlost);
6527
6528 if (rtp->rtcp->rxmes_count == 0) {
6529 rtp->rtcp->minrxmes = rtp->rxmes;
6530 }
6531 if (rtp->rxmes < rtp->rtcp->minrxmes) {
6532 rtp->rtcp->minrxmes = rtp->rxmes;
6533 }
6534 if (rtp->rxmes > rtp->rtcp->maxrxmes) {
6535 rtp->rtcp->maxrxmes = rtp->rxmes;
6536 }
6537
6539 &rtp->rtcp->stdev_rxmes, &rtp->rtcp->rxmes_count);
6540
6541 ast_debug_rtcp(2, " %s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6543 rtp->rtcp->normdevrtt,
6544 rtp->rxjitter,
6545 rtp->rtcp->stdev_rxjitter,
6546 rtp->rtcp->normdev_rxlost, rtp->rxmes);
6547}
static double calc_media_experience_score(struct ast_rtp_instance *instance, double normdevrtt, double normdev_rxjitter, double stdev_rxjitter, double normdev_rxlost)
Calculate a "media experience score" based on given data.
unsigned int rxmes_count

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

Referenced by ast_rtcp_generate_report().

◆ update_lost_stats()

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

Definition at line 6376 of file res_rtp_asterisk.c.

6377{
6378 double reported_lost;
6379
6380 rtp->rtcp->reported_lost = lost_packets;
6381 reported_lost = (double)rtp->rtcp->reported_lost;
6382 if (rtp->rtcp->reported_lost_count == 0) {
6383 rtp->rtcp->reported_minlost = reported_lost;
6384 }
6385 if (reported_lost < rtp->rtcp->reported_minlost) {
6386 rtp->rtcp->reported_minlost = reported_lost;
6387 }
6388 if (reported_lost > rtp->rtcp->reported_maxlost) {
6389 rtp->rtcp->reported_maxlost = reported_lost;
6390 }
6391
6394}
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 6485 of file res_rtp_asterisk.c.

6486{
6487 double mes = calc_media_experience_score(rtp->owner,
6488 rtp->rtcp->normdevrtt,
6489 rtp->rtcp->reported_jitter,
6492
6493 rtp->rtcp->reported_mes = mes;
6494 if (rtp->rtcp->reported_mes_count == 0) {
6495 rtp->rtcp->reported_minmes = mes;
6496 }
6497 if (mes < rtp->rtcp->reported_minmes) {
6498 rtp->rtcp->reported_minmes = mes;
6499 }
6500 if (mes > rtp->rtcp->reported_maxmes) {
6501 rtp->rtcp->reported_maxmes = mes;
6502 }
6503
6506
6507 ast_debug_rtcp(2, "%s: rtt: %.9f j: %.9f sjh: %.9f lost: %.9f mes: %4.1f\n",
6509 rtp->rtcp->normdevrtt,
6510 rtp->rtcp->reported_jitter,
6512 rtp->rtcp->reported_normdev_lost, mes);
6513}
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 6295 of file res_rtp_asterisk.c.

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 10681 of file res_rtp_asterisk.c.

◆ asterisk_rtp_engine

struct ast_rtp_engine asterisk_rtp_engine
static

Definition at line 2575 of file res_rtp_asterisk.c.

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

Referenced by load_module(), and unload_module().

◆ cli_rtp

struct ast_cli_entry cli_rtp[]
static

Definition at line 10213 of file res_rtp_asterisk.c.

10213 {
10214 AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
10215 AST_CLI_DEFINE(handle_cli_rtp_settings, "Display RTP settings"),
10216 AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
10217 AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
10218#ifdef AST_DEVMODE
10219 AST_CLI_DEFINE(handle_cli_rtp_drop_incoming_packets, "Drop RTP incoming packets"),
10220#endif
10221#ifdef HAVE_PJPROJECT
10222 AST_CLI_DEFINE(handle_cli_rtp_refresh_stun, "Force a resolution of the STUN hostname"),
10223#endif
10224};
#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().