Asterisk - The Open Source Telephony Project  18.5.0
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 <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <openssl/opensslconf.h>
#include <openssl/opensslv.h>
#include <pjlib.h>
#include <pjlib-util.h>
#include <pjnath.h>
#include <ifaddrs.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 "asterisk/res_pjproject.h"
#include "asterisk/security_events.h"
Include dependency graph for res_rtp_asterisk.c:

Go to the source code of this file.

Data Structures

struct  ast_ice_host_candidate
 Structure which contains ICE host candidate mapping information. More...
 
struct  ast_rtcp
 Structure defining an RTCP session. More...
 
struct  ast_rtp
 RTP session description. More...
 
struct  ast_rtp_ioqueue_thread
 Structure which contains ioqueue thread information. More...
 
struct  ast_rtp_rtcp_nack_payload
 Structure for storing RTP packets for retransmission. More...
 
struct  frame_list
 
struct  host_candidates
 List of ICE host candidate mappings. More...
 
struct  ice_wrap
 
struct  ioqueues
 List of ioqueue threads. More...
 
struct  optional_ts
 
struct  rtp_drop_packets_data
 
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. More...
 
#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 DTMF_SAMPLE_RATE_MS   8
 
#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 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_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() More...
 
#define STRICT_RTP_LEARN_TIMEOUT   5000
 Strict RTP learning timeout time in milliseconds. More...
 
#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 __init_pj_thread_storage (void)
 
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)
 
static void acl_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void ast2pj_rtp_ice_role (enum ast_rtp_ice_role ast_role, enum pj_ice_sess_role *pj_role)
 
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. More...
 
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 void ast_rtp_ice_add_cand (struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned comp_id, unsigned transport_id, pj_ice_cand_type type, pj_uint16_t local_pref, const pj_sockaddr_t *addr, const pj_sockaddr_t *base_addr, const pj_sockaddr_t *rel_addr, int addr_len)
 
static void ast_rtp_ice_add_remote_candidate (struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
 
static void ast_rtp_ice_candidate_destroy (void *obj)
 Destructor for locally created ICE candidates. More...
 
static void ast_rtp_ice_change_components (struct ast_rtp_instance *instance, int num_components)
 
static struct ao2_containerast_rtp_ice_get_local_candidates (struct ast_rtp_instance *instance)
 
static const char * ast_rtp_ice_get_password (struct ast_rtp_instance *instance)
 
static const char * ast_rtp_ice_get_ufrag (struct ast_rtp_instance *instance)
 
static void ast_rtp_ice_lite (struct ast_rtp_instance *instance)
 
static void ast_rtp_ice_set_authentication (struct ast_rtp_instance *instance, const char *ufrag, const char *password)
 
static void ast_rtp_ice_set_role (struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
 
static void ast_rtp_ice_start (struct ast_rtp_instance *instance)
 
static void ast_rtp_ice_start_media (pj_ice_sess *ice, pj_status_t status)
 
static void ast_rtp_ice_stop (struct ast_rtp_instance *instance)
 
static void ast_rtp_ice_turn_request (struct ast_rtp_instance *instance, enum ast_rtp_ice_component_type component, enum ast_transport transport, const char *server, unsigned int port, const char *username, const char *password)
 
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_on_ice_complete (pj_ice_sess *ice, pj_status_t status)
 
static void ast_rtp_on_ice_rx_data (pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len)
 
static pj_status_t ast_rtp_on_ice_tx_pkt (pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, const void *pkt, pj_size_t size, const pj_sockaddr_t *dst_addr, unsigned dst_addr_len)
 
static void ast_rtp_on_turn_rtcp_state (pj_turn_sock *turn_sock, pj_turn_state_t old_state, pj_turn_state_t new_state)
 
static void ast_rtp_on_turn_rtp_state (pj_turn_sock *turn_sock, pj_turn_state_t old_state, pj_turn_state_t new_state)
 
static void ast_rtp_on_turn_rx_rtcp_data (pj_turn_sock *turn_sock, void *pkt, unsigned pkt_len, const pj_sockaddr_t *peer_addr, unsigned addr_len)
 
static void ast_rtp_on_turn_rx_rtp_data (pj_turn_sock *turn_sock, void *pkt, unsigned pkt_len, const pj_sockaddr_t *peer_addr, unsigned addr_len)
 
static void ast_rtp_on_valid_pair (pj_ice_sess *ice)
 
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) More...
 
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 void calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, 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. More...
 
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, int af)
 
static void drop_packets_data_update (struct timeval tv)
 
static int find_by_value (int elem, int value)
 Helper function to find an elem in a vector by value. More...
 
static char * generate_random_string (char *buf, size_t size)
 
static size_t get_recv_buffer_count (struct ast_rtp_instance *instance)
 
static size_t get_recv_buffer_max (struct ast_rtp_instance *instance)
 
static size_t get_send_buffer_count (struct ast_rtp_instance *instance)
 
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_drop_incoming_packets (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 void host_candidate_overrides_clear (void)
 Helper function which clears the ICE host candidate mapping. More...
 
static int ice_candidate_cmp (void *obj, void *arg, int flags)
 
static int ice_candidates_compare (struct ao2_container *left, struct ao2_container *right)
 
static int ice_create (struct ast_rtp_instance *instance, struct ast_sockaddr *addr, int port, int replace)
 
static int ice_reset_session (struct ast_rtp_instance *instance)
 
static void ice_wrap_dtor (void *vdoomed)
 ao2 ICE wrapper object destructor. More...
 
static int ioqueue_worker_thread (void *data)
 Worker thread for ioqueue and timerheap. More...
 
static int load_module (void)
 
static void ntp2timeval (unsigned int msw, unsigned int lsw, struct timeval *tv)
 
static void pj2ast_rtp_ice_role (enum pj_ice_sess_role pj_role, enum ast_rtp_ice_role *ast_role)
 
static void pj_thread_register_check (void)
 Function used to check if the calling thread is registered with pjlib. If it is not it will be registered. More...
 
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 redundacy frame. More...
 
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 void rtp_add_candidates_to_ice (struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *addr, int port, int component, int transport)
 
static int rtp_address_is_ice_blacklisted (const struct ast_sockaddr *address)
 
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 void rtp_ioqueue_thread_destroy (struct ast_rtp_ioqueue_thread *ioqueue)
 Destroyer for ioqueue thread. More...
 
static struct ast_rtp_ioqueue_threadrtp_ioqueue_thread_get_or_create (void)
 Finder and allocator for an ioqueue thread. More...
 
static void rtp_ioqueue_thread_remove (struct ast_rtp_ioqueue_thread *ioqueue)
 Removal function for ioqueue thread, determines if it should be terminated and destroyed. More...
 
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. More...
 
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 void rtp_terminate_pjproject (void)
 
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_unload_acl (ast_rwlock_t *lock, struct ast_acl_list **acl)
 
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 set_rtp_rtcp_schedid (struct ast_rtp_instance *instance, int id)
 
static int should_drop_packets (struct ast_sockaddr *addr)
 
static int stun_address_is_blacklisted (const struct ast_sockaddr *addr)
 
static int timer_worker_thread (void *data)
 Worker thread for timerheap. More...
 
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)
 
static int unload_module (void)
 
static void update_address_with_ice_candidate (pj_ice_sess *ice, enum ast_rtp_ice_component_type component, struct ast_sockaddr *cand_address)
 Helper function which updates an ast_sockaddr with the candidate used for the component. More...
 
static void update_jitter_stats (struct ast_rtp *rtp, unsigned int ia_jitter)
 
static void update_lost_stats (struct ast_rtp *rtp, unsigned int lost_packets)
 
static int update_rtt_stats (struct ast_rtp *rtp, unsigned int lsr, unsigned int dlsr)
 
static unsigned int use_random (struct ast_cli_args *a, int pos, unsigned int index)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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 1 .requires = "res_pjproject", #endif }
 
static struct stasis_subscriptionacl_change_sub = NULL
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_rtp_engine_ice ast_rtp_ice
 
static pj_ice_sess_cb ast_rtp_ice_sess_cb
 
static struct ast_rtp_engine_test ast_rtp_test
 
static pj_turn_sock_cb ast_rtp_turn_rtcp_sock_cb
 
static pj_turn_sock_cb ast_rtp_turn_rtp_sock_cb
 
static struct ast_rtp_engine asterisk_rtp_engine
 
static pj_caching_pool cachingpool
 Pool factory used by pjlib to allocate memory. More...
 
static struct ast_cli_entry cli_rtp []
 
static struct rtp_drop_packets_data drop_packets_data
 
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
 
static struct host_candidates host_candidates = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct ast_acl_listice_acl = NULL
 
static ast_rwlock_t ice_acl_lock = AST_RWLOCK_INIT_VALUE
 
static int icesupport = DEFAULT_ICESUPPORT
 
static struct ioqueues ioqueues = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION
 
static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL
 
static struct ast_sockaddr lo6 = { .len = 0 }
 
static struct ast_threadstorage pj_thread_storage = { .once = PTHREAD_ONCE_INIT , .key_init = __init_pj_thread_storage , .custom_init = NULL , }
 
static pj_pool_t * pool
 Global memory pool for configuration and timers. More...
 
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
 
static struct ast_acl_liststun_acl = NULL
 
static ast_rwlock_t stun_acl_lock = AST_RWLOCK_INIT_VALUE
 
static int stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE
 
static struct sockaddr_in stunaddr
 
static pj_timer_heap_t * timer_heap
 Global timer heap. More...
 
static int timer_terminate
 Used to tell the timer thread to terminate. More...
 
static pj_thread_t * timer_thread
 Thread executing the timer heap. More...
 
static pj_str_t turnaddr
 
static pj_str_t turnpassword
 
static int turnport = DEFAULT_TURN_PORT
 
static pj_str_t turnusername
 

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

Referenced by rtp_reload().

◆ DEFAULT_DTLS_MTU

#define DEFAULT_DTLS_MTU   1200

Definition at line 188 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_DTMF_TIMEOUT

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

samples

Definition at line 137 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_ICESUPPORT

#define DEFAULT_ICESUPPORT   1

Definition at line 186 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_LEARNING_MIN_DURATION

#define DEFAULT_LEARNING_MIN_DURATION   CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)

Definition at line 155 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_LEARNING_MIN_SEQUENTIAL

#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4

Definition at line 141 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_RTP_END

#define DEFAULT_RTP_END   31000

Default maximum port number to end allocating RTP ports at

Definition at line 100 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_RTP_RECV_BUFFER_SIZE

#define DEFAULT_RTP_RECV_BUFFER_SIZE   20

The initial size of the RTP receiver buffer

Definition at line 111 of file res_rtp_asterisk.c.

Referenced by ast_rtp_prop_set().

◆ DEFAULT_RTP_SEND_BUFFER_SIZE

#define DEFAULT_RTP_SEND_BUFFER_SIZE   250

The initial size of the RTP send buffer

Definition at line 109 of file res_rtp_asterisk.c.

Referenced by ast_rtp_prop_set().

◆ DEFAULT_RTP_START

#define DEFAULT_RTP_START   5000

Default port number to start allocating RTP ports from

Definition at line 99 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_SRTP_REPLAY_PROTECTION

#define DEFAULT_SRTP_REPLAY_PROTECTION   1

Definition at line 185 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_STRICT_RTP

#define DEFAULT_STRICT_RTP   STRICT_RTP_YES

Enabled by default

Definition at line 184 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_STUN_SOFTWARE_ATTRIBUTE

#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE   1

Definition at line 187 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DEFAULT_TURN_PORT

#define DEFAULT_TURN_PORT   3478

Definition at line 105 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ DTMF_SAMPLE_RATE_MS

#define DTMF_SAMPLE_RATE_MS   8

DTMF samples per millisecond

Definition at line 135 of file res_rtp_asterisk.c.

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

◆ FLAG_3389_WARNING

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 283 of file res_rtp_asterisk.c.

Referenced by process_cn_rfc3389().

◆ FLAG_DTMF_COMPENSATE

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 288 of file res_rtp_asterisk.c.

◆ FLAG_NAT_ACTIVE

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 284 of file res_rtp_asterisk.c.

Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and rtp_raw_write().

◆ FLAG_NAT_INACTIVE

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 285 of file res_rtp_asterisk.c.

Referenced by bridge_p2p_rtp_write(), and rtp_raw_write().

◆ FLAG_NAT_INACTIVE_NOWARN

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 286 of file res_rtp_asterisk.c.

Referenced by bridge_p2p_rtp_write(), and rtp_raw_write().

◆ FLAG_NEED_MARKER_BIT

#define FLAG_NEED_MARKER_BIT   (1 << 3)

◆ FLAG_REQ_LOCAL_BRIDGE_BIT

#define FLAG_REQ_LOCAL_BRIDGE_BIT   (1 << 5)

Definition at line 289 of file res_rtp_asterisk.c.

Referenced by ast_rtp_local_bridge(), and bridge_p2p_rtp_write().

◆ MAX_TIMESTAMP_SKEW

#define MAX_TIMESTAMP_SKEW   640

Definition at line 92 of file res_rtp_asterisk.c.

Referenced by rtp_raw_write().

◆ MAXIMUM_RTP_PORT

#define MAXIMUM_RTP_PORT   65535

Maximum port number to accept

Definition at line 103 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

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

Referenced by ast_rtp_read().

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

Referenced by ast_rtp_rtcp_handle_nack().

◆ MINIMUM_RTP_PORT

#define MINIMUM_RTP_PORT   1024

Minimum port number to accept

Definition at line 102 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

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

Referenced by ast_rtp_read().

◆ OLD_PACKET_COUNT

#define OLD_PACKET_COUNT   1000

The number of previous packets that are considered old

Definition at line 113 of file res_rtp_asterisk.c.

Referenced by ast_rtp_read().

◆ RTCP_DEFAULT_INTERVALMS

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 95 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ RTCP_FB_NACK_BLOCK_WORD_LENGTH

#define RTCP_FB_NACK_BLOCK_WORD_LENGTH   2

Definition at line 6098 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_FB_REMB_BLOCK_WORD_LENGTH

#define RTCP_FB_REMB_BLOCK_WORD_LENGTH   4

Definition at line 6097 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_HEADER_SSRC_LENGTH

#define RTCP_HEADER_SSRC_LENGTH   2

Definition at line 6096 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_LENGTH_MASK

#define RTCP_LENGTH_MASK   0xFFFF

Definition at line 6061 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_LENGTH_SHIFT

#define RTCP_LENGTH_SHIFT   0

Definition at line 6070 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_MAX_INTERVALMS

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 97 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ RTCP_MIN_INTERVALMS

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 96 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ RTCP_PADDING_MASK

#define RTCP_PADDING_MASK   0x01

Definition at line 6064 of file res_rtp_asterisk.c.

◆ RTCP_PADDING_SHIFT

#define RTCP_PADDING_SHIFT   29

Definition at line 6073 of file res_rtp_asterisk.c.

◆ RTCP_PAYLOAD_TYPE_MASK

#define RTCP_PAYLOAD_TYPE_MASK   0xFF

Definition at line 6062 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_PAYLOAD_TYPE_SHIFT

#define RTCP_PAYLOAD_TYPE_SHIFT   16

Definition at line 6071 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_PT_APP

#define RTCP_PT_APP   204

Application defined (From RFC3550)

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

Referenced by ast_rtcp_interpret(), and rtcp_payload_type2str().

◆ RTCP_PT_FUR

#define RTCP_PT_FUR   192

Full INTRA-frame Request / Fast Update Request (From RFC2032)

Definition at line 119 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret(), and rtcp_payload_type2str().

◆ RTCP_PT_PSFB

#define RTCP_PT_PSFB   AST_RTP_RTCP_PSFB

Payload Specific Feed Back (From RFC4585 also RFC5104)

Definition at line 132 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret(), rtcp_payload_subtype2str(), rtcp_payload_type2str(), rtp_write_rtcp_fir(), and rtp_write_rtcp_psfb().

◆ RTCP_PT_RR

#define RTCP_PT_RR   AST_RTP_RTCP_RR

Receiver Report (From RFC3550)

Definition at line 123 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_generate_report(), ast_rtcp_interpret(), and rtcp_payload_type2str().

◆ RTCP_PT_SDES

#define RTCP_PT_SDES   202

Source Description (From RFC3550)

Definition at line 125 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_generate_sdes(), ast_rtcp_interpret(), and rtcp_payload_type2str().

◆ RTCP_PT_SR

#define RTCP_PT_SR   AST_RTP_RTCP_SR

Sender Report (From RFC3550)

Definition at line 121 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_generate_report(), ast_rtcp_interpret(), and rtcp_payload_type2str().

◆ RTCP_REPORT_COUNT_MASK

#define RTCP_REPORT_COUNT_MASK   0x1F

Definition at line 6063 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_REPORT_COUNT_SHIFT

#define RTCP_REPORT_COUNT_SHIFT   24

Definition at line 6072 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_RR_BLOCK_WORD_LENGTH

#define RTCP_RR_BLOCK_WORD_LENGTH   6

Definition at line 6095 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_SR_BLOCK_WORD_LENGTH

#define RTCP_SR_BLOCK_WORD_LENGTH   5

Definition at line 6094 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_VALID_MASK

#define RTCP_VALID_MASK   (RTCP_VERSION_MASK_SHIFTED | (((RTCP_PAYLOAD_TYPE_MASK & ~0x1)) << RTCP_PAYLOAD_TYPE_SHIFT))

Definition at line 6091 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_VALID_VALUE

#define RTCP_VALID_VALUE   (RTCP_VERSION_SHIFTED | (RTCP_PT_SR << RTCP_PAYLOAD_TYPE_SHIFT))

Definition at line 6092 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_VERSION

#define RTCP_VERSION   2U

Definition at line 6076 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK

#define RTCP_VERSION_MASK   0x03

Definition at line 6065 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_MASK_SHIFTED

#define RTCP_VERSION_MASK_SHIFTED   (RTCP_VERSION_MASK << RTCP_VERSION_SHIFT)

Definition at line 6078 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTCP_VERSION_SHIFT

#define RTCP_VERSION_SHIFT   30

Definition at line 6074 of file res_rtp_asterisk.c.

◆ RTCP_VERSION_SHIFTED

#define RTCP_VERSION_SHIFTED   (RTCP_VERSION << RTCP_VERSION_SHIFT)

Definition at line 6077 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

◆ RTP_DTLS_ESTABLISHED

#define RTP_DTLS_ESTABLISHED   -37

Definition at line 161 of file res_rtp_asterisk.c.

Referenced by __rtp_recvfrom(), ast_rtcp_read(), and ast_rtp_read().

◆ RTP_MTU

#define RTP_MTU   1200

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

Referenced by ast_rtp_interpret(), and rtp_instance_parse_transport_wide_cc().

◆ SEQNO_CYCLE_OVER

#define SEQNO_CYCLE_OVER   65536

The number after the maximum allowed sequence number

Definition at line 116 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_generate_nack(), and ast_rtp_read().

◆ SRTP_MASTER_KEY_LEN

#define SRTP_MASTER_KEY_LEN   16

Definition at line 157 of file res_rtp_asterisk.c.

Referenced by res_sdp_crypto_alloc(), and rtcp_debug_test_addr().

◆ SRTP_MASTER_LEN

#define SRTP_MASTER_LEN   (SRTP_MASTER_KEY_LEN + SRTP_MASTER_SALT_LEN)

Definition at line 159 of file res_rtp_asterisk.c.

Referenced by rtcp_debug_test_addr().

◆ SRTP_MASTER_SALT_LEN

#define SRTP_MASTER_SALT_LEN   14

Definition at line 158 of file res_rtp_asterisk.c.

Referenced by rtcp_debug_test_addr().

◆ 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.
Returns
0 if element does not match.
Non-zero if element matches.

Definition at line 4045 of file res_rtp_asterisk.c.

Referenced by ast_rtp_bundle(), and ast_rtp_destroy().

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

Referenced by ast_rtp_read().

◆ TRANSPORT_SOCKET_RTCP

#define TRANSPORT_SOCKET_RTCP   1

◆ TRANSPORT_SOCKET_RTP

#define TRANSPORT_SOCKET_RTP   0

◆ TRANSPORT_TURN_RTCP

#define TRANSPORT_TURN_RTCP   3

◆ TRANSPORT_TURN_RTP

#define TRANSPORT_TURN_RTP   2

◆ TURN_STATE_WAIT_TIME

#define TURN_STATE_WAIT_TIME   2000

◆ ZFONE_PROFILE_ID

#define ZFONE_PROFILE_ID   0x505a

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

169  {
170  STRICT_RTP_NO = 0, /*! Don't adhere to any strict RTP rules */
171  STRICT_RTP_YES, /*! Strict RTP that restricts packets based on time and sequence number */
172  STRICT_RTP_SEQNO, /*! Strict RTP that restricts packets based on sequence number */
173 };

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

163  {
164  STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
165  STRICT_RTP_LEARN, /*! Accept next packet as source */
166  STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
167 };

Function Documentation

◆ __init_pj_thread_storage()

static void __init_pj_thread_storage ( void  )
static

Definition at line 862 of file res_rtp_asterisk.c.

866 {

◆ __reg_module()

static void __reg_module ( void  )
static

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

References ast_rtp_get_ssrc(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, rtp_ssrc_mapping::instance, NULL, rtp_ssrc_mapping::ssrc, 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().

5871 {
5872  int index;
5873 
5874  if (!AST_VECTOR_SIZE(&rtp->ssrc_mapping)) {
5875  /* This instance is not bundled */
5876  return instance;
5877  }
5878 
5879  /* Find the bundled child instance */
5880  for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
5881  struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
5882  unsigned int mapping_ssrc = source ? ast_rtp_get_ssrc(mapping->instance) : mapping->ssrc;
5883 
5884  if (mapping->ssrc_valid && mapping_ssrc == ssrc) {
5885  return mapping->instance;
5886  }
5887  }
5888 
5889  /* Does the SSRC match the bundled parent? */
5890  if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
5891  return instance;
5892  }
5893  return NULL;
5894 }
struct ast_rtp_instance * instance
The RTP instance this SSRC belongs to.
Structure used for mapping an incoming SSRC to an RTP instance.
#define NULL
Definition: resample.c:96
unsigned int ssrc_valid
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:670
unsigned int themssrc_valid
unsigned int themssrc
static unsigned int ast_rtp_get_ssrc(struct ast_rtp_instance *instance)
unsigned int ssrc
The received SSRC.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ __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 3084 of file res_rtp_asterisk.c.

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_data(), ast_rtp_instance_get_remote_address, ast_rtp_instance_get_test(), ast_rtp_instance_set_remote_address, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), buf, error(), in, len(), LOG_ERROR, LOG_WARNING, ast_rtp_engine_test::packets_to_drop, pj_thread_register_check(), ice_wrap::real_ice, RTP_DTLS_ESTABLISHED, ast_rtp::s, status, TRANSPORT_SOCKET_RTCP, and TRANSPORT_SOCKET_RTP.

Referenced by rtcp_recvfrom(), and rtp_recvfrom().

3085 {
3086  int len;
3087  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3088 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3089  char *in = buf;
3090 #endif
3091 #ifdef HAVE_PJPROJECT
3092  struct ast_sockaddr *loop = rtcp ? &rtp->rtcp_loop : &rtp->rtp_loop;
3093 #endif
3094 #ifdef TEST_FRAMEWORK
3096 #endif
3097 
3098  if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
3099  return len;
3100  }
3101 
3102 #ifdef TEST_FRAMEWORK
3103  if (test && test->packets_to_drop > 0) {
3104  test->packets_to_drop--;
3105  return 0;
3106  }
3107 #endif
3108 
3109 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3110  /* If this is an SSL packet pass it to OpenSSL for processing. RFC section for first byte value:
3111  * https://tools.ietf.org/html/rfc5764#section-5.1.2 */
3112  if ((*in >= 20) && (*in <= 63)) {
3113  struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
3114  int res = 0;
3115 
3116  /* If no SSL session actually exists terminate things */
3117  if (!dtls->ssl) {
3118  ast_log(LOG_ERROR, "Received SSL traffic on RTP instance '%p' without an SSL session\n",
3119  instance);
3120  return -1;
3121  }
3122 
3123  ast_debug_dtls(3, "(%p) DTLS - __rtp_recvfrom rtp=%p - Got SSL packet '%d'\n", instance, rtp, *in);
3124 
3125  /*
3126  * A race condition is prevented between dtls_perform_handshake()
3127  * and this function because both functions have to get the
3128  * instance lock before they can do anything. The
3129  * dtls_perform_handshake() function needs to start the timer
3130  * before we stop it below.
3131  */
3132 
3133  /* Before we feed data into OpenSSL ensure that the timeout timer is either stopped or completed */
3134  ao2_unlock(instance);
3135  dtls_srtp_stop_timeout_timer(instance, rtp, rtcp);
3136  ao2_lock(instance);
3137 
3138  /* If we don't yet know if we are active or passive and we receive a packet... we are obviously passive */
3139  if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
3140  dtls->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
3141  SSL_set_accept_state(dtls->ssl);
3142  }
3143 
3144  BIO_write(dtls->read_bio, buf, len);
3145 
3146  len = SSL_read(dtls->ssl, buf, len);
3147 
3148  if ((len < 0) && (SSL_get_error(dtls->ssl, len) == SSL_ERROR_SSL)) {
3149  unsigned long error = ERR_get_error();
3150  ast_log(LOG_ERROR, "DTLS failure occurred on RTP instance '%p' due to reason '%s', terminating\n",
3151  instance, ERR_reason_error_string(error));
3152  return -1;
3153  }
3154 
3155  if (SSL_is_init_finished(dtls->ssl)) {
3156  /* Any further connections will be existing since this is now established */
3157  dtls->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
3158  /* Use the keying material to set up key/salt information */
3159  if ((res = dtls_srtp_setup(rtp, instance, rtcp))) {
3160  return res;
3161  }
3162  /* Notify that dtls has been established */
3163  res = RTP_DTLS_ESTABLISHED;
3164 
3165  ast_debug_dtls(3, "(%p) DTLS - __rtp_recvfrom rtp=%p - established'\n", instance, rtp);
3166  } else {
3167  /* Since we've sent additional traffic start the timeout timer for retransmission */
3168  dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
3169  }
3170 
3171  return res;
3172  }
3173 #endif
3174 
3175 #ifdef HAVE_PJPROJECT
3176  if (!ast_sockaddr_isnull(loop) && !ast_sockaddr_cmp(loop, sa)) {
3177  /* ICE traffic will have been handled in the TURN callback, so skip it but update the address
3178  * so it reflects the actual source and not the loopback
3179  */
3180  if (rtcp) {
3181  ast_sockaddr_copy(sa, &rtp->rtcp->them);
3182  } else {
3184  }
3185  } else if (rtp->ice) {
3186  pj_str_t combined = pj_str(ast_sockaddr_stringify(sa));
3187  pj_sockaddr address;
3188  pj_status_t status;
3189  struct ice_wrap *ice;
3190 
3192 
3193  pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &combined, &address);
3194 
3195  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3196  ice = rtp->ice;
3197  ao2_ref(ice, +1);
3198  ao2_unlock(instance);
3199  status = pj_ice_sess_on_rx_pkt(ice->real_ice,
3201  rtcp ? TRANSPORT_SOCKET_RTCP : TRANSPORT_SOCKET_RTP, buf, len, &address,
3202  pj_sockaddr_get_len(&address));
3203  ao2_ref(ice, -1);
3204  ao2_lock(instance);
3205  if (status != PJ_SUCCESS) {
3206  char err_buf[100];
3207 
3208  pj_strerror(status, err_buf, sizeof(err_buf));
3209  ast_log(LOG_WARNING, "PJ ICE Rx error status code: %d '%s'.\n",
3210  (int)status, err_buf);
3211  return -1;
3212  }
3213  if (!rtp->passthrough) {
3214  /* If a unidirectional ICE negotiation occurs then lock on to the source of the
3215  * ICE traffic and use it as the target. This will occur if the remote side only
3216  * wants to receive media but never send to us.
3217  */
3218  if (!rtp->ice_active_remote_candidates && !rtp->ice_proposed_remote_candidates) {
3219  if (rtcp) {
3220  ast_sockaddr_copy(&rtp->rtcp->them, sa);
3221  } else {
3223  }
3224  }
3225  return 0;
3226  }
3227  rtp->passthrough = 0;
3228  }
3229 #endif
3230 
3231  return len;
3232 }
RTP session description.
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:171
char * address
Definition: f2c.h:59
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
struct ast_rtp_engine_test * ast_rtp_instance_get_test(struct ast_rtp_instance *instance)
Obtain a pointer to the test callbacks on an RTP instance.
Definition: rtp_engine.c:2901
#define RTP_DTLS_ESTABLISHED
#define ao2_unlock(a)
Definition: astobj2.h:730
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
Socket address structure.
Definition: netsock2.h:97
static void pj_thread_register_check(void)
Function used to check if the calling thread is registered with pjlib. If it is not it will be regist...
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define ast_log
Definition: astobj2.c:42
FILE * in
Definition: utils/frame.c:33
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define LOG_ERROR
Definition: logger.h:285
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1080
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
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
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
Structure that represents the test functionality for res_rtp_asterisk unit tests. ...
Definition: rtp_engine.h:595
#define ast_debug_dtls(sublevel,...)
Log debug level DTLS information.
Definition: rtp_engine.h:2886
#define TRANSPORT_SOCKET_RTCP
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192
pj_ice_sess * real_ice
jack_status_t status
Definition: app_jack.c:146
#define TRANSPORT_SOCKET_RTP

◆ __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 3247 of file res_rtp_asterisk.c.

References ao2_lock, ao2_ref, ao2_unlock, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_rtp_instance_set_last_tx(), ast_sendto(), buf, len(), NULL, pj_thread_register_check(), ast_srtp_res::protect, ice_wrap::real_ice, ast_rtp::s, and status.

Referenced by rtcp_sendto(), and rtp_sendto().

3248 {
3249  int len = size;
3250  void *temp = buf;
3251  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3252  struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
3253  struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
3254  struct ast_srtp *srtp = ast_rtp_instance_get_srtp(transport, rtcp);
3255  int res;
3256 
3257  *via_ice = 0;
3258 
3259  if (use_srtp && res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
3260  return -1;
3261  }
3262 
3263 #ifdef HAVE_PJPROJECT
3264  if (transport_rtp->ice) {
3266  pj_status_t status;
3267  struct ice_wrap *ice;
3268 
3269  /* If RTCP is sharing the same socket then use the same component */
3270  if (rtcp && rtp->rtcp->s == rtp->s) {
3271  component = AST_RTP_ICE_COMPONENT_RTP;
3272  }
3273 
3275 
3276  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3277  ice = transport_rtp->ice;
3278  ao2_ref(ice, +1);
3279  if (instance == transport) {
3280  ao2_unlock(instance);
3281  }
3282  status = pj_ice_sess_send_data(ice->real_ice, component, temp, len);
3283  ao2_ref(ice, -1);
3284  if (instance == transport) {
3285  ao2_lock(instance);
3286  }
3287  if (status == PJ_SUCCESS) {
3288  *via_ice = 1;
3289  return len;
3290  }
3291  }
3292 #endif
3293 
3294  res = ast_sendto(rtcp ? transport_rtp->rtcp->s : transport_rtp->s, temp, len, flags, sa);
3295  if (res > 0) {
3296  ast_rtp_instance_set_last_tx(instance, time(NULL));
3297  }
3298 
3299  return res;
3300 }
RTP session description.
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
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
Definition: rtp_engine.c:2763
#define ao2_unlock(a)
Definition: astobj2.h:730
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP transmission time.
Definition: rtp_engine.c:3763
#define NULL
Definition: resample.c:96
static void pj_thread_register_check(void)
Function used to check if the calling thread is registered with pjlib. If it is not it will be regist...
struct ast_srtp_res * res_srtp
Definition: rtp_engine.c:177
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
ast_rtp_ice_component_type
ICE component types.
Definition: rtp_engine.h:462
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
int(* protect)(struct ast_srtp *srtp, void **buf, int *size, int rtcp)
Definition: res_srtp.h:50
pj_ice_sess * real_ice
jack_status_t status
Definition: app_jack.c:146

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 9742 of file res_rtp_asterisk.c.

◆ acl_change_stasis_cb()

static void acl_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 9613 of file res_rtp_asterisk.c.

References ast_named_acl_change_type(), rtp_reload(), and stasis_message_type().

Referenced by rtp_learning_start().

9614 {
9615  if (stasis_message_type(message) != ast_named_acl_change_type()) {
9616  return;
9617  }
9618 
9619  /* There is no simple way to just reload the ACLs, so just execute a forced reload. */
9620  rtp_reload(1, 1);
9621 }
static int rtp_reload(int reload, int by_external_config)
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
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 ...

◆ ast2pj_rtp_ice_role()

static void ast2pj_rtp_ice_role ( enum ast_rtp_ice_role  ast_role,
enum pj_ice_sess_role *  pj_role 
)
static

Definition at line 927 of file res_rtp_asterisk.c.

References AST_RTP_ICE_ROLE_CONTROLLED, and AST_RTP_ICE_ROLE_CONTROLLING.

Referenced by ice_reset_session().

928 {
929  switch (ast_role) {
931  *pj_role = PJ_ICE_SESS_ROLE_CONTROLLED;
932  break;
934  *pj_role = PJ_ICE_SESS_ROLE_CONTROLLING;
935  break;
936  }
937 }

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

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

References rtcpinterval.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

3324 {
3325  unsigned int interval;
3326  /*! \todo XXX Do a more reasonable calculation on this one
3327  * Look in RFC 3550 Section A.7 for an example*/
3328  interval = rtcpinterval;
3329  return interval;
3330 }
static int rtcpinterval

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

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_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_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, rtcp_debug_test_addr(), ast_rtp_rtcp_report::rtp_timestamp, ast_rtp_rtcp_report::sender_information, ast_rtp_rtcp_report_block::source_ssrc, ast_rtp_rtcp_report::ssrc, and ast_frame::subclass.

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

4581 {
4582  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4583  struct ast_rtp_rtcp_report_block *report_block = NULL;
4584  RAII_VAR(struct ast_json *, message_blob, NULL, ast_json_unref);
4585 
4586  if (!rtp || !rtp->rtcp) {
4587  return 0;
4588  }
4589 
4590  if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4591  return 0;
4592  }
4593 
4594  if (!rtcp_report) {
4595  return -1;
4596  }
4597 
4598  report_block = rtcp_report->report_block[0];
4599 
4600  if (sr) {
4601  rtp->rtcp->txlsr = rtcp_report->sender_information.ntp_timestamp;
4602  rtp->rtcp->sr_count++;
4603  rtp->rtcp->lastsrtxcount = rtp->txcount;
4604  } else {
4605  rtp->rtcp->rr_count++;
4606  }
4607 
4608  if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
4609  ast_verbose("* Sent RTCP %s to %s%s\n", sr ? "SR" : "RR",
4610  ast_sockaddr_stringify(&remote_address), ice ? " (via ICE)" : "");
4611  ast_verbose(" Our SSRC: %u\n", rtcp_report->ssrc);
4612  if (sr) {
4613  ast_verbose(" Sent(NTP): %u.%06u\n",
4614  (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
4615  (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
4616  ast_verbose(" Sent(RTP): %u\n", rtcp_report->sender_information.rtp_timestamp);
4617  ast_verbose(" Sent packets: %u\n", rtcp_report->sender_information.packet_count);
4618  ast_verbose(" Sent octets: %u\n", rtcp_report->sender_information.octet_count);
4619  }
4620  if (report_block) {
4621  ast_verbose(" Report block:\n");
4622  ast_verbose(" Their SSRC: %u\n", report_block->source_ssrc);
4623  ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
4624  ast_verbose(" Cumulative loss: %u\n", report_block->lost_count.packets);
4625  ast_verbose(" Highest seq no: %u\n", report_block->highest_seq_no);
4626  ast_verbose(" IA jitter: %.4f\n", (double)report_block->ia_jitter / ast_rtp_get_rate(rtp->f.subclass.format));
4627  ast_verbose(" Their last SR: %u\n", report_block->lsr);
4628  ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(report_block->dlsr / 65536.0));
4629  }
4630  }
4631 
4632  message_blob = ast_json_pack("{s: s, s: s}",
4633  "to", ast_sockaddr_stringify(&remote_address),
4634  "from", rtp->rtcp->local_addr_str);
4636  rtcp_report, message_blob);
4637 
4638  return 1;
4639 }
struct stasis_message_type * ast_rtp_rtcp_sent_type(void)
Message type for an RTCP message sent from this Asterisk instance.
RTP session description.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
unsigned int highest_seq_no
Definition: rtp_engine.h:322
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_rtp_rtcp_report_block * report_block[0]
Definition: rtp_engine.h:344
A report block within a SR/RR report.
Definition: rtp_engine.h:316
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
unsigned int rtp_timestamp
Definition: rtp_engine.h:337
struct ast_rtp_rtcp_report::@315 sender_information
struct ast_frame_subclass subclass
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
unsigned short fraction
Definition: rtp_engine.h:319
#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:911
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.
Definition: rtp_engine.c:3485
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
Definition: rtp_engine.c:4030
static int rtcp_debug_test_addr(struct ast_sockaddr *addr)
unsigned int packet_count
Definition: rtp_engine.h:338
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
unsigned int ssrc
Definition: rtp_engine.h:333
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
struct ast_frame f
Abstract JSON element (object, array, string, int, ...).
unsigned int octet_count
Definition: rtp_engine.h:339
struct ast_format * format
struct timeval ntp_timestamp
Definition: rtp_engine.h:336
unsigned int source_ssrc
Definition: rtp_engine.h:317
struct ast_rtp_rtcp_report_block::@314 lost_count

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

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().

4701 {
4702  int packet_len = 0;
4703  int res;
4704 
4705  /* Every RTCP packet needs to be sent out with a SR/RR and SDES prefixing it.
4706  * At the end of this function, rtcpheader should contain both of those packets,
4707  * and will return the length of the overall packet. This can be used to determine
4708  * where further packets can be inserted in the compound packet.
4709  */
4710  res = ast_rtcp_generate_report(instance, rtcpheader, report, sr);
4711 
4712  if (res == 0 || res == 1) {
4713  ast_debug_rtcp(1, "(%p) RTCP failed to generate %s report!\n", instance, sr ? "SR" : "RR");
4714  return 0;
4715  }
4716 
4717  packet_len += res;
4718 
4719  res = ast_rtcp_generate_sdes(instance, rtcpheader + packet_len, report);
4720 
4721  if (res == 0 || res == 1) {
4722  ast_debug_rtcp(1, "(%p) RTCP failed to generate SDES!\n", instance);
4723  return 0;
4724  }
4725 
4726  return packet_len + res;
4727 }
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
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)

◆ ast_rtcp_generate_nack()

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

Definition at line 4729 of file res_rtp_asterisk.c.

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(), put_unaligned_uint32(), SEQNO_CYCLE_OVER, ast_rtp::ssrc, and ast_rtp::themssrc.

Referenced by ast_rtp_read().

4730 {
4731  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4732  int packet_len;
4733  int blp_index = -1;
4734  int current_seqno;
4735  unsigned int fci = 0;
4736  size_t remaining_missing_seqno;
4737 
4738  if (!rtp || !rtp->rtcp) {
4739  return 0;
4740  }
4741 
4742  if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4743  return 0;
4744  }
4745 
4746  current_seqno = rtp->expectedrxseqno;
4747  remaining_missing_seqno = AST_VECTOR_SIZE(&rtp->missing_seqno);
4748  packet_len = 12; /* The header length is 12 (version line, packet source SSRC, media source SSRC) */
4749 
4750  /* If there are no missing sequence numbers then don't bother sending a NACK needlessly */
4751  if (!remaining_missing_seqno) {
4752  return 0;
4753  }
4754 
4755  /* This iterates through the possible forward sequence numbers seeing which ones we
4756  * have no packet for, adding it to the NACK until we are out of missing packets.
4757  */
4758  while (remaining_missing_seqno) {
4759  int *missing_seqno;
4760 
4761  /* On the first entry to this loop blp_index will be -1, so this will become 0
4762  * and the sequence number will be placed into the packet as the PID.
4763  */
4764  blp_index++;
4765 
4766  missing_seqno = AST_VECTOR_GET_CMP(&rtp->missing_seqno, current_seqno,
4767  find_by_value);
4768  if (missing_seqno) {
4769  /* We hit the max blp size, reset */
4770  if (blp_index >= 17) {
4771  put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
4772  fci = 0;
4773  blp_index = 0;
4774  packet_len += 4;
4775  }
4776 
4777  if (blp_index == 0) {
4778  fci |= (current_seqno << 16);
4779  } else {
4780  fci |= (1 << (blp_index - 1));
4781  }
4782 
4783  /* Since we've used a missing sequence number, we're down one */
4784  remaining_missing_seqno--;
4785  }
4786 
4787  /* Handle cycling of the sequence number */
4788  current_seqno++;
4789  if (current_seqno == SEQNO_CYCLE_OVER) {
4790  current_seqno = 0;
4791  }
4792  }
4793 
4794  put_unaligned_uint32(rtcpheader + packet_len, htonl(fci));
4795  packet_len += 4;
4796 
4797  /* Length MUST be 2+n, where n is the number of NACKs. Same as length in words minus 1 */
4798  put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_NACK << 24)
4799  | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
4800  put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
4801  put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
4802 
4803  return packet_len;
4804 }
RTP session description.
#define SEQNO_CYCLE_OVER
#define AST_RTP_RTCP_FMT_NACK
Definition: rtp_engine.h:303
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
unsigned int ssrc
#define AST_RTP_RTCP_RTPFB
Definition: rtp_engine.h:297
unsigned int themssrc
int expectedrxseqno
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:733
static int find_by_value(int elem, int value)
Helper function to find an elem in a vector by value.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

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

References ast_calloc, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_sockaddr_isnull(), ast_tvzero(), calculate_lost_packet_statistics(), 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_rtp::lastrxseqno, 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, RTCP_PT_RR, RTCP_PT_SR, ast_rtp_rtcp_report::rtp_timestamp, ast_rtp_rtcp_report::sender_information, ast_rtp_rtcp_report_block::source_ssrc, ast_rtp_rtcp_report::ssrc, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::themssrc, ast_rtp::themssrc_valid, timersub(), timeval2ntp(), and ast_rtp_rtcp_report::type.

Referenced by ast_rtcp_generate_compound_prefix().

4493 {
4494  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4495  int len = 0;
4496  struct timeval now;
4497  unsigned int now_lsw;
4498  unsigned int now_msw;
4499  unsigned int lost_packets;
4500  int fraction_lost;
4501  struct timeval dlsr = { 0, };
4502  struct ast_rtp_rtcp_report_block *report_block = NULL;
4503 
4504  if (!rtp || !rtp->rtcp) {
4505  return 0;
4506  }
4507 
4508  if (ast_sockaddr_isnull(&rtp->rtcp->them)) { /* This'll stop rtcp for this rtp session */
4509  /* RTCP was stopped. */
4510  return 0;
4511  }
4512 
4513  if (!rtcp_report) {
4514  return 1;
4515  }
4516 
4517  *sr = rtp->txcount > rtp->rtcp->lastsrtxcount ? 1 : 0;
4518 
4519  /* Compute statistics */
4520  calculate_lost_packet_statistics(rtp, &lost_packets, &fraction_lost);
4521 
4522  gettimeofday(&now, NULL);
4523  rtcp_report->reception_report_count = rtp->themssrc_valid ? 1 : 0;
4524  rtcp_report->ssrc = rtp->ssrc;
4525  rtcp_report->type = *sr ? RTCP_PT_SR : RTCP_PT_RR;
4526  if (*sr) {
4527  rtcp_report->sender_information.ntp_timestamp = now;
4528  rtcp_report->sender_information.rtp_timestamp = rtp->lastts;
4529  rtcp_report->sender_information.packet_count = rtp->txcount;
4530  rtcp_report->sender_information.octet_count = rtp->txoctetcount;
4531  }
4532 
4533  if (rtp->themssrc_valid) {
4534  report_block = ast_calloc(1, sizeof(*report_block));
4535  if (!report_block) {
4536  return 1;
4537  }
4538 
4539  rtcp_report->report_block[0] = report_block;
4540  report_block->source_ssrc = rtp->themssrc;
4541  report_block->lost_count.fraction = (fraction_lost & 0xff);
4542  report_block->lost_count.packets = (lost_packets & 0xffffff);
4543  report_block->highest_seq_no = (rtp->cycles | (rtp->lastrxseqno & 0xffff));
4544  report_block->ia_jitter = (unsigned int)(rtp->rxjitter * ast_rtp_get_rate(rtp->f.subclass.format));
4545  report_block->lsr = rtp->rtcp->themrxlsr;
4546  /* If we haven't received an SR report, DLSR should be 0 */
4547  if (!ast_tvzero(rtp->rtcp->rxlsr)) {
4548  timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
4549  report_block->dlsr = (((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000;
4550  }
4551  }
4552  timeval2ntp(rtcp_report->sender_information.ntp_timestamp, &now_msw, &now_lsw);
4553  put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc)); /* Our SSRC */
4554  len += 8;
4555  if (*sr) {
4556  put_unaligned_uint32(rtcpheader + len, htonl(now_msw)); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970 */
4557  put_unaligned_uint32(rtcpheader + len + 4, htonl(now_lsw)); /* now, LSW */
4558  put_unaligned_uint32(rtcpheader + len + 8, htonl(rtcp_report->sender_information.rtp_timestamp));
4559  put_unaligned_uint32(rtcpheader + len + 12, htonl(rtcp_report->sender_information.packet_count));
4560  put_unaligned_uint32(rtcpheader + len + 16, htonl(rtcp_report->sender_information.octet_count));
4561  len += 20;
4562  }
4563  if (report_block) {
4564  put_unaligned_uint32(rtcpheader + len, htonl(report_block->source_ssrc)); /* Their SSRC */
4565  put_unaligned_uint32(rtcpheader + len + 4, htonl((report_block->lost_count.fraction << 24) | report_block->lost_count.packets));
4566  put_unaligned_uint32(rtcpheader + len + 8, htonl(report_block->highest_seq_no));
4567  put_unaligned_uint32(rtcpheader + len + 12, htonl(report_block->ia_jitter));
4568  put_unaligned_uint32(rtcpheader + len + 16, htonl(report_block->lsr));
4569  put_unaligned_uint32(rtcpheader + len + 20, htonl(report_block->dlsr));
4570  len += 24;
4571  }
4572 
4573  put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (rtcp_report->reception_report_count << 24)
4574  | ((*sr ? RTCP_PT_SR : RTCP_PT_RR) << 16) | ((len/4)-1)));
4575 
4576  return len;
4577 }
RTP session description.
#define RTCP_PT_SR
unsigned int highest_seq_no
Definition: rtp_engine.h:322
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
unsigned short reception_report_count
Definition: rtp_engine.h:332
struct ast_rtp_rtcp_report_block * report_block[0]
Definition: rtp_engine.h:344
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
A report block within a SR/RR report.
Definition: rtp_engine.h:316
#define NULL
Definition: resample.c:96
unsigned int rtp_timestamp
Definition: rtp_engine.h:337
struct ast_rtp_rtcp_report::@315 sender_information
struct ast_frame_subclass subclass
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
unsigned int ssrc
void timersub(struct timeval *tvend, struct timeval *tvstart, struct timeval *tvdiff)
unsigned short fraction
Definition: rtp_engine.h:319
unsigned int themssrc_valid
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
Definition: rtp_engine.c:4030
#define RTCP_PT_RR
static void calculate_lost_packet_statistics(struct ast_rtp *rtp, unsigned int *lost_packets, int *fraction_lost)
unsigned int themssrc
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
unsigned int packet_count
Definition: rtp_engine.h:338
unsigned int ssrc
Definition: rtp_engine.h:333
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
struct ast_frame f
unsigned int type
Definition: rtp_engine.h:334
unsigned int lastts
unsigned int octet_count
Definition: rtp_engine.h:339
struct ast_format * format
struct timeval ntp_timestamp
Definition: rtp_engine.h:336
unsigned int source_ssrc
Definition: rtp_engine.h:317
struct ast_rtp_rtcp_report_block::@314 lost_count

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

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

Referenced by ast_rtcp_generate_compound_prefix().

4643 {
4644  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4645  int len = 0;
4646  uint16_t sdes_packet_len_bytes;
4647  uint16_t sdes_packet_len_rounded;
4648 
4649  if (!rtp || !rtp->rtcp) {
4650  return 0;
4651  }
4652 
4653  if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
4654  return 0;
4655  }
4656 
4657  if (!rtcp_report) {
4658  return -1;
4659  }
4660 
4661  sdes_packet_len_bytes =
4662  4 + /* RTCP Header */
4663  4 + /* SSRC */
4664  1 + /* Type (CNAME) */
4665  1 + /* Text Length */
4666  AST_UUID_STR_LEN /* Text and NULL terminator */
4667  ;
4668 
4669  /* Round to 32 bit boundary */
4670  sdes_packet_len_rounded = (sdes_packet_len_bytes + 3) & ~0x3;
4671 
4672  put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | ((sdes_packet_len_rounded / 4) - 1)));
4673  put_unaligned_uint32(rtcpheader + 4, htonl(rtcp_report->ssrc));
4674  rtcpheader[8] = 0x01; /* CNAME */
4675  rtcpheader[9] = AST_UUID_STR_LEN - 1; /* Number of bytes of text */
4676  memcpy(rtcpheader + 10, rtp->cname, AST_UUID_STR_LEN);
4677  len += 10 + AST_UUID_STR_LEN;
4678 
4679  /* Padding - Note that we don't set the padded bit on the packet. From
4680  * RFC 3550 Section 6.5:
4681  *
4682  * No length octet follows the null item type octet, but additional null
4683  * octets MUST be included if needd to pad until the next 32-bit
4684  * boundary. Note that this padding is separate from that indicated by
4685  * the P bit in the RTCP header.
4686  *
4687  * These bytes will already be zeroed out during array initialization.
4688  */
4689  len += (sdes_packet_len_rounded - sdes_packet_len_bytes);
4690 
4691  return len;
4692 }
RTP session description.
#define AST_UUID_STR_LEN
Definition: uuid.h:27
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
char cname[AST_UUID_STR_LEN]
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
unsigned int ssrc
Definition: rtp_engine.h:333
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define RTCP_PT_SDES

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

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_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_test(), 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_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_rtp_rtcp_report_block::fraction, ast_frame::frametype, ast_rtp_rtcp_report_block::highest_seq_no, ast_rtp_rtcp_report_block::ia_jitter, ast_frame_subclass::integer, 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, rtcp_debug_test_addr(), RTCP_FB_NACK_BLOCK_WORD_LENGTH, RTCP_FB_REMB_BLOCK_WORD_LENGTH, RTCP_HEADER_SSRC_LENGTH, 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_frame::samples, ast_rtp_engine_test::sdes_received, ast_rtp_rtcp_report_block::source_ssrc, ast_frame::src, srtp_replay_protection, ast_frame::stream_num, STRICT_RTP_OPEN, ast_frame::subclass, ast_rtp::themssrc, ast_rtp::themssrc_valid, timeval2ntp(), ast_srtp_res::unprotect, update_jitter_stats(), update_lost_stats(), and update_rtt_stats().

Referenced by ast_rtcp_read(), and ast_rtp_read().

6102 {
6103  struct ast_rtp_instance *transport = instance;
6104  struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(instance);
6105  int len = size;
6106  unsigned int *rtcpheader = (unsigned int *)(rtcpdata);
6107  unsigned int packetwords;
6108  unsigned int position;
6109  unsigned int first_word;
6110  /*! True if we have seen an acceptable SSRC to learn the remote RTCP address */
6111  unsigned int ssrc_seen;
6112  struct ast_rtp_rtcp_report_block *report_block;
6113  struct ast_frame *f = &ast_null_frame;
6114 #ifdef TEST_FRAMEWORK
6115  struct ast_rtp_engine_test *test_engine;
6116 #endif
6117 
6118  /* If this is encrypted then decrypt the payload */
6119  if ((*rtcpheader & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
6120  srtp, rtcpheader, &len, 1 | (srtp_replay_protection << 1)) < 0) {
6121  return &ast_null_frame;
6122  }
6123 
6124  packetwords = len / 4;
6125 
6126  ast_debug_rtcp(1, "(%p) RTCP got report of %d bytes from %s\n",
6127  instance, len, ast_sockaddr_stringify(addr));
6128 
6129  /*
6130  * Validate the RTCP packet according to an adapted and slightly
6131  * modified RFC3550 validation algorithm.
6132  */
6133  if (packetwords < RTCP_HEADER_SSRC_LENGTH) {
6134  ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: Frame size (%u words) is too short\n",
6135  instance, transport_rtp, ast_sockaddr_stringify(addr), packetwords);
6136  return &ast_null_frame;
6137  }
6138  position = 0;
6139  first_word = ntohl(rtcpheader[position]);
6140  if ((first_word & RTCP_VALID_MASK) != RTCP_VALID_VALUE) {
6141  ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: Failed first packet validity check\n",
6142  instance, transport_rtp, ast_sockaddr_stringify(addr));
6143  return &ast_null_frame;
6144  }
6145  do {
6146  position += ((first_word >> RTCP_LENGTH_SHIFT) & RTCP_LENGTH_MASK) + 1;
6147  if (packetwords <= position) {
6148  break;
6149  }
6150  first_word = ntohl(rtcpheader[position]);
6151  } while ((first_word & RTCP_VERSION_MASK_SHIFTED) == RTCP_VERSION_SHIFTED);
6152  if (position != packetwords) {
6153  ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: Failed packet version or length check\n",
6154  instance, transport_rtp, ast_sockaddr_stringify(addr));
6155  return &ast_null_frame;
6156  }
6157 
6158  /*
6159  * Note: RFC3605 points out that true NAT (vs NAPT) can cause RTCP
6160  * to have a different IP address and port than RTP. Otherwise, when
6161  * strictrtp is enabled we could reject RTCP packets not coming from
6162  * the learned RTP IP address if it is available.
6163  */
6164 
6165  /*
6166  * strictrtp safety needs SSRC to match before we use the
6167  * sender's address for symmetrical RTP to send our RTCP
6168  * reports.
6169  *
6170  * If strictrtp is not enabled then claim to have already seen
6171  * a matching SSRC so we'll accept this packet's address for
6172  * symmetrical RTP.
6173  */
6174  ssrc_seen = transport_rtp->strict_rtp_state == STRICT_RTP_OPEN;
6175 
6176  position = 0;
6177  while (position < packetwords) {
6178  unsigned int i;
6179  unsigned int pt;
6180  unsigned int rc;
6181  unsigned int ssrc;
6182  /*! True if the ssrc value we have is valid and not garbage because it doesn't exist. */
6183  unsigned int ssrc_valid;
6184  unsigned int length;
6185  unsigned int min_length;
6186  /*! Always use packet source SSRC to find the rtp instance unless explicitly told not to. */
6187  unsigned int use_packet_source = 1;
6188 
6189  struct ast_json *message_blob;
6190  RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
6191  struct ast_rtp_instance *child;
6192  struct ast_rtp *rtp;
6193  struct ast_rtp_rtcp_feedback *feedback;
6194 
6195  i = position;
6196  first_word = ntohl(rtcpheader[i]);
6197  pt = (first_word >> RTCP_PAYLOAD_TYPE_SHIFT) & RTCP_PAYLOAD_TYPE_MASK;
6198  rc = (first_word >> RTCP_REPORT_COUNT_SHIFT) & RTCP_REPORT_COUNT_MASK;
6199  /* RFC3550 says 'length' is the number of words in the packet - 1 */
6200  length = ((first_word >> RTCP_LENGTH_SHIFT) & RTCP_LENGTH_MASK) + 1;
6201 
6202  /* Check expected RTCP packet record length */
6203  min_length = RTCP_HEADER_SSRC_LENGTH;
6204  switch (pt) {
6205  case RTCP_PT_SR:
6206  min_length += RTCP_SR_BLOCK_WORD_LENGTH;
6207  /* fall through */
6208  case RTCP_PT_RR:
6209  min_length += (rc * RTCP_RR_BLOCK_WORD_LENGTH);
6210  use_packet_source = 0;
6211  break;
6212  case RTCP_PT_FUR:
6213  break;
6214  case AST_RTP_RTCP_RTPFB:
6215  switch (rc) {
6216  case AST_RTP_RTCP_FMT_NACK:
6217  min_length += RTCP_FB_NACK_BLOCK_WORD_LENGTH;
6218  break;
6219  default:
6220  break;
6221  }
6222  use_packet_source = 0;
6223  break;
6224  case RTCP_PT_PSFB:
6225  switch (rc) {
6226  case AST_RTP_RTCP_FMT_REMB:
6227  min_length += RTCP_FB_REMB_BLOCK_WORD_LENGTH;
6228  break;
6229  default:
6230  break;
6231  }
6232  break;
6233  case RTCP_PT_SDES:
6234  case RTCP_PT_BYE:
6235  /*
6236  * There may not be a SSRC/CSRC present. The packet is
6237  * useless but still valid if it isn't present.
6238  *
6239  * We don't know what min_length should be so disable the check
6240  */
6241  min_length = length;
6242  break;
6243  default:
6244  ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: %u(%s) skipping record\n",
6245  instance, transport_rtp, ast_sockaddr_stringify(addr), pt, rtcp_payload_type2str(pt));
6246  if (rtcp_debug_test_addr(addr)) {
6247  ast_verbose("\n");
6248  ast_verbose("RTCP from %s: %u(%s) skipping record\n",
6250  }
6251  position += length;
6252  continue;
6253  }
6254  if (length < min_length) {
6255  ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: %u(%s) length field less than expected minimum. Min:%u Got:%u\n",
6256  instance, transport_rtp, ast_sockaddr_stringify(addr), pt, rtcp_payload_type2str(pt),
6257  min_length - 1, length - 1);
6258  return &ast_null_frame;
6259  }
6260 
6261  /* Get the RTCP record SSRC if defined for the record */
6262  ssrc_valid = 1;
6263  switch (pt) {
6264  case RTCP_PT_SR:
6265  case RTCP_PT_RR:
6266  rtcp_report = ast_rtp_rtcp_report_alloc(rc);
6267  if (!rtcp_report) {
6268  return &ast_null_frame;
6269  }
6270  rtcp_report->reception_report_count = rc;
6271 
6272  ssrc = ntohl(rtcpheader[i + 2]);
6273  rtcp_report->ssrc = ssrc;
6274  break;
6275  case RTCP_PT_FUR:
6276  case RTCP_PT_PSFB:
6277  ssrc = ntohl(rtcpheader[i + 1]);
6278  break;
6279  case AST_RTP_RTCP_RTPFB:
6280  ssrc = ntohl(rtcpheader[i + 2]);
6281  break;
6282  case RTCP_PT_SDES:
6283  case RTCP_PT_BYE:
6284  default:
6285  ssrc = 0;
6286  ssrc_valid = 0;
6287  break;
6288  }
6289 
6290  if (rtcp_debug_test_addr(addr)) {
6291  const char *subtype = rtcp_payload_subtype2str(pt, rc);
6292 
6293  ast_verbose("\n");
6294  ast_verbose("RTCP from %s\n", ast_sockaddr_stringify(addr));
6295  ast_verbose("PT: %u (%s)\n", pt, rtcp_payload_type2str(pt));
6296  if (subtype) {
6297  ast_verbose("Packet Subtype: %u (%s)\n", rc, subtype);
6298  } else {
6299  ast_verbose("Reception reports: %u\n", rc);
6300  }
6301  ast_verbose("SSRC of sender: %u\n", ssrc);
6302  }
6303 
6304  /* Determine the appropriate instance for this */
6305  if (ssrc_valid) {
6306  /*
6307  * Depending on the payload type, either the packet source or media source
6308  * SSRC is used.
6309  */
6310  if (use_packet_source) {
6311  child = rtp_find_instance_by_packet_source_ssrc(transport, transport_rtp, ssrc);
6312  } else {
6313  child = rtp_find_instance_by_media_source_ssrc(transport, transport_rtp, ssrc);
6314  }
6315  if (child && child != transport) {
6316  /*
6317  * It is safe to hold the child lock while holding the parent lock.
6318  * We guarantee that the locking order is always parent->child or
6319  * that the child lock is not held when acquiring the parent lock.
6320  */
6321  ao2_lock(child);
6322  instance = child;
6323  rtp = ast_rtp_instance_get_data(instance);
6324  } else {
6325  /* The child is the parent! We don't need to unlock it. */
6326  child = NULL;
6327  rtp = transport_rtp;
6328  }
6329  } else {
6330  child = NULL;
6331  rtp = transport_rtp;
6332  }
6333 
6334  if (ssrc_valid && rtp->themssrc_valid) {
6335  /*
6336  * If the SSRC is 1, we still need to handle RTCP since this could be a
6337  * special case. For example, if we have a unidirectional video stream, the
6338  * SSRC may be set to 1 by the browser (in the case of chromium), and requests
6339  * will still need to be processed so that video can flow as expected. This
6340  * should only be done for PLI and FUR, since there is not a way to get the
6341  * appropriate rtp instance when the SSRC is 1.
6342  */
6343  int exception = (ssrc == 1 && !((pt == RTCP_PT_PSFB && rc == AST_RTP_RTCP_FMT_PLI) || pt == RTCP_PT_FUR));
6344  if ((ssrc != rtp->themssrc && use_packet_source && ssrc != 1)
6345  || exception) {
6346  /*
6347  * Skip over this RTCP record as it does not contain the
6348  * correct SSRC. We should not act upon RTCP records
6349  * for a different stream.
6350  */
6351  position += length;
6352  ast_debug_rtcp(1, "(%p) RTCP %p -- from %s: Skipping record, received SSRC '%u' != expected '%u'\n",
6353  instance, rtp, ast_sockaddr_stringify(addr), ssrc, rtp->themssrc);
6354  if (child) {
6355  ao2_unlock(child);
6356  }
6357  continue;
6358  }
6359  ssrc_seen = 1;
6360  }
6361 
6362  if (ssrc_seen && ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
6363  /* Send to whoever sent to us */
6364  if (ast_sockaddr_cmp(&rtp->rtcp->them, addr)) {
6365  ast_sockaddr_copy(&rtp->rtcp->them, addr);
6367  ast_debug(0, "(%p) RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
6368  instance, ast_sockaddr_stringify(addr));
6369  }
6370  }
6371  }
6372 
6373  i += RTCP_HEADER_SSRC_LENGTH; /* Advance past header and ssrc */
6374  switch (pt) {
6375  case RTCP_PT_SR:
6376  gettimeofday(&rtp->rtcp->rxlsr, NULL);
6377  rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16);
6378  rtp->rtcp->spc = ntohl(rtcpheader[i + 3]);
6379  rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
6380 
6381  rtcp_report->type = RTCP_PT_SR;
6382  rtcp_report->sender_information.packet_count = rtp->rtcp->spc;
6383  rtcp_report->sender_information.octet_count = rtp->rtcp->soc;
6384  ntp2timeval((unsigned int)ntohl(rtcpheader[i]),
6385  (unsigned int)ntohl(rtcpheader[i + 1]),
6386  &rtcp_report->sender_information.ntp_timestamp);
6387  rtcp_report->sender_information.rtp_timestamp = ntohl(rtcpheader[i + 2]);
6388  if (rtcp_debug_test_addr(addr)) {
6389  ast_verbose("NTP timestamp: %u.%06u\n",
6390  (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_sec,
6391  (unsigned int)rtcp_report->sender_information.ntp_timestamp.tv_usec);
6392  ast_verbose("RTP timestamp: %u\n", rtcp_report->sender_information.rtp_timestamp);
6393  ast_verbose("SPC: %u\tSOC: %u\n",
6394  rtcp_report->sender_information.packet_count,
6395  rtcp_report->sender_information.octet_count);
6396  }
6398  /* Intentional fall through */
6399  case RTCP_PT_RR:
6400  if (rtcp_report->type != RTCP_PT_SR) {
6401  rtcp_report->type = RTCP_PT_RR;
6402  }
6403 
6404  if (rc > 0) {
6405  /* Don't handle multiple reception reports (rc > 1) yet */
6406  report_block = ast_calloc(1, sizeof(*report_block));
6407  if (!report_block) {
6408  if (child) {
6409  ao2_unlock(child);
6410  }
6411  return &ast_null_frame;
6412  }
6413  rtcp_report->report_block[0] = report_block;
6414  report_block->source_ssrc = ntohl(rtcpheader[i]);
6415  report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
6416  report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
6417  report_block->highest_seq_no = ntohl(rtcpheader[i + 2]);
6418  report_block->ia_jitter = ntohl(rtcpheader[i + 3]);
6419  report_block->lsr = ntohl(rtcpheader[i + 4]);
6420  report_block->dlsr = ntohl(rtcpheader[i + 5]);
6421  if (report_block->lsr
6422  && update_rtt_stats(rtp, report_block->lsr, report_block->dlsr)
6423  && rtcp_debug_test_addr(addr)) {
6424  struct timeval now;
6425  unsigned int lsr_now, lsw, msw;
6426  gettimeofday(&now, NULL);
6427  timeval2ntp(now, &msw, &lsw);
6428  lsr_now = (((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16));
6429  ast_verbose("Internal RTCP NTP clock skew detected: "
6430  "lsr=%u, now=%u, dlsr=%u (%u:%03ums), "
6431  "diff=%u\n",
6432  report_block->lsr, lsr_now, report_block->dlsr, report_block->dlsr / 65536,
6433  (report_block->dlsr % 65536) * 1000 / 65536,
6434  report_block->dlsr - (lsr_now - report_block->lsr));
6435  }
6436  update_jitter_stats(rtp, report_block->ia_jitter);
6437  update_lost_stats(rtp, report_block->lost_count.packets);
6438 
6439  if (rtcp_debug_test_addr(addr)) {
6440  ast_verbose(" Fraction lost: %d\n", report_block->lost_count.fraction);
6441  ast_verbose(" Packets lost so far: %u\n", report_block->lost_count.packets);
6442  ast_verbose(" Highest sequence number: %u\n", report_block->highest_seq_no & 0x0000ffff);
6443  ast_verbose(" Sequence number cycles: %u\n", report_block->highest_seq_no >> 16);
6444  ast_verbose(" Interarrival jitter: %u\n", report_block->ia_jitter);
6445  ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long)(report_block->lsr) >> 16,((unsigned long)(report_block->lsr) << 16) * 4096);
6446  ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
6447  ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
6448  }
6449  }
6450  /* If and when we handle more than one report block, this should occur outside
6451  * this loop.
6452  */
6453 
6454  message_blob = ast_json_pack("{s: s, s: s, s: f}",
6455  "from", ast_sockaddr_stringify(addr),
6456  "to", transport_rtp->rtcp->local_addr_str,
6457  "rtt", rtp->rtcp->rtt);
6459  rtcp_report,
6460  message_blob);
6461  ast_json_unref(message_blob);
6462 
6463  /* Return an AST_FRAME_RTCP frame with the ast_rtp_rtcp_report
6464  * object as a its data */
6465  transport_rtp->f.frametype = AST_FRAME_RTCP;
6466  transport_rtp->f.subclass.integer = pt;
6467  transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
6468  memcpy(transport_rtp->f.data.ptr, rtcp_report, sizeof(struct ast_rtp_rtcp_report));
6469  transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_report);
6470  if (rc > 0) {
6471  /* There's always a single report block stored, here */
6472  struct ast_rtp_rtcp_report *rtcp_report2;
6473  report_block = transport_rtp->f.data.ptr + transport_rtp->f.datalen + sizeof(struct ast_rtp_rtcp_report_block *);
6474  memcpy(report_block, rtcp_report->report_block[0], sizeof(struct ast_rtp_rtcp_report_block));
6475  rtcp_report2 = (struct ast_rtp_rtcp_report *)transport_rtp->f.data.ptr;
6476  rtcp_report2->report_block[0] = report_block;
6477  transport_rtp->f.datalen += sizeof(struct ast_rtp_rtcp_report_block);
6478  }
6479  transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
6480  transport_rtp->f.samples = 0;
6481  transport_rtp->f.mallocd = 0;
6482  transport_rtp->f.delivery.tv_sec = 0;
6483  transport_rtp->f.delivery.tv_usec = 0;
6484  transport_rtp->f.src = "RTP";
6485  transport_rtp->f.stream_num = rtp->stream_num;
6486  f = &transport_rtp->f;
6487  break;
6488  case AST_RTP_RTCP_RTPFB:
6489  switch (rc) {
6490  case AST_RTP_RTCP_FMT_NACK:
6491  /* If retransmissions are not enabled ignore this message */
6492  if (!rtp->send_buffer) {
6493  break;
6494  }
6495 
6496  if (rtcp_debug_test_addr(addr)) {
6497  ast_verbose("Received generic RTCP NACK message\n");
6498  }
6499 
6500  ast_rtp_rtcp_handle_nack(instance, rtcpheader, position, length);
6501  break;
6502  default:
6503  break;
6504  }
6505  break;
6506  case RTCP_PT_FUR:
6507  /* Handle RTCP FUR as FIR by setting the format to 4 */
6508  rc = AST_RTP_RTCP_FMT_FIR;
6509  case RTCP_PT_PSFB:
6510  switch (rc) {
6511  case AST_RTP_RTCP_FMT_PLI:
6512  case AST_RTP_RTCP_FMT_FIR:
6513  if (rtcp_debug_test_addr(addr)) {
6514  ast_verbose("Received an RTCP Fast Update Request\n");
6515  }
6516  transport_rtp->f.frametype = AST_FRAME_CONTROL;
6517  transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
6518  transport_rtp->f.datalen = 0;
6519  transport_rtp->f.samples = 0;
6520  transport_rtp->f.mallocd = 0;
6521  transport_rtp->f.src = "RTP";
6522  f = &transport_rtp->f;
6523  break;
6524  case AST_RTP_RTCP_FMT_REMB:
6525  /* If REMB support is not enabled ignore this message */
6527  break;
6528  }
6529 
6530  if (rtcp_debug_test_addr(addr)) {
6531  ast_verbose("Received REMB report\n");
6532  }
6533  transport_rtp->f.frametype = AST_FRAME_RTCP;
6534  transport_rtp->f.subclass.integer = pt;
6535  transport_rtp->f.stream_num = rtp->stream_num;
6536  transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
6537  feedback = transport_rtp->f.data.ptr;
6538  feedback->fmt = rc;
6539 
6540  /* We don't actually care about the SSRC information in the feedback message */
6541  first_word = ntohl(rtcpheader[i + 2]);
6542  feedback->remb.br_exp = (first_word >> 18) & ((1 << 6) - 1);
6543  feedback->remb.br_mantissa = first_word & ((1 << 18) - 1);
6544 
6545  transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_feedback);
6546  transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
6547  transport_rtp->f.samples = 0;
6548  transport_rtp->f.mallocd = 0;
6549  transport_rtp->f.delivery.tv_sec = 0;
6550  transport_rtp->f.delivery.tv_usec = 0;
6551  transport_rtp->f.src = "RTP";
6552  f = &transport_rtp->f;
6553  break;
6554  default:
6555  break;
6556  }
6557  break;
6558  case RTCP_PT_SDES:
6559  if (rtcp_debug_test_addr(addr)) {
6560  ast_verbose("Received an SDES from %s\n",
6561  ast_sockaddr_stringify(addr));
6562  }
6563 #ifdef TEST_FRAMEWORK
6564  if ((test_engine = ast_rtp_instance_get_test(instance))) {
6565  test_engine->sdes_received = 1;
6566  }
6567 #endif
6568  break;
6569  case RTCP_PT_BYE:
6570  if (rtcp_debug_test_addr(addr)) {
6571  ast_verbose("Received a BYE from %s\n",
6572  ast_sockaddr_stringify(addr));
6573  }
6574  break;
6575  default:
6576  break;
6577  }
6578  position += length;
6579  rtp->rtcp->rtcp_info = 1;
6580 
6581  if (child) {
6582  ao2_unlock(child);
6583  }
6584  }
6585 
6586  return f;
6587 }
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_FB_REMB_BLOCK_WORD_LENGTH
#define RTCP_VALID_VALUE
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:331
RTP session description.
#define RTCP_PT_SR
#define RTCP_HEADER_SSRC_LENGTH
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
static const char * rtcp_payload_type2str(unsigned int pt)
#define RTCP_VALID_MASK
unsigned int highest_seq_no
Definition: rtp_engine.h:322
#define RTCP_REPORT_COUNT_SHIFT
#define AST_RTP_RTCP_FMT_NACK
Definition: rtp_engine.h:303
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:171
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define AST_RTP_RTCP_FMT_PLI
Definition: rtp_engine.h:305
#define RTCP_LENGTH_MASK
struct ast_rtp_engine_test * ast_rtp_instance_get_test(struct ast_rtp_instance *instance)
Obtain a pointer to the test callbacks on an RTP instance.
Definition: rtp_engine.c:2901
#define RTCP_SR_BLOCK_WORD_LENGTH
An object that represents data received in a feedback report.
Definition: rtp_engine.h:358
struct ast_rtp_rtcp_report_block * report_block[0]
Definition: rtp_engine.h:344
#define RTCP_PAYLOAD_TYPE_MASK
static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
static struct ast_rtp_instance * rtp_find_instance_by_packet_source_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
A report block within a SR/RR report.
Definition: rtp_engine.h:316
#define ao2_unlock(a)
Definition: astobj2.h:730
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
unsigned int fmt
Definition: rtp_engine.h:359
struct ast_rtp_rtcp_feedback_remb remb
Definition: rtp_engine.h:361
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
struct stasis_message_type * ast_rtp_rtcp_received_type(void)
Message type for an RTCP message received from some external source.
struct ast_frame_subclass subclass
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define RTCP_LENGTH_SHIFT
struct ast_srtp_res * res_srtp
Definition: rtp_engine.c:177
static void update_lost_stats(struct ast_rtp *rtp, unsigned int lost_packets)
unsigned short fraction
Definition: rtp_engine.h:319
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
#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:911
static int update_rtt_stats(struct ast_rtp *rtp, unsigned int lsr, unsigned int dlsr)
#define RTCP_PAYLOAD_TYPE_SHIFT
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
#define ao2_lock(a)
Definition: astobj2.h:718
#define AST_RTP_RTCP_RTPFB
Definition: rtp_engine.h:297
unsigned int themssrc_valid
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.
Definition: rtp_engine.c:3485
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.
Definition: rtp_engine.c:3474
#define RTCP_VERSION_SHIFTED
#define RTCP_PT_RR
static int rtcp_debug_test_addr(struct ast_sockaddr *addr)
unsigned int themssrc
#define RTCP_RR_BLOCK_WORD_LENGTH
static int srtp_replay_protection
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:2864
#define RTCP_FB_NACK_BLOCK_WORD_LENGTH
#define RTCP_REPORT_COUNT_MASK
static int ast_rtp_rtcp_handle_nack(struct ast_rtp_instance *instance, unsigned int *nackdata, unsigned int position, unsigned int length)
#define AST_RTP_RTCP_FMT_FIR
Definition: rtp_engine.h:307
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define RTCP_PT_FUR
int(* unprotect)(struct ast_srtp *srtp, void *buf, int *size, int rtcp)
Definition: res_srtp.h:48
static const char * rtcp_payload_subtype2str(unsigned int pt, unsigned int subtype)
struct ast_frame f
Structure that represents the test functionality for res_rtp_asterisk unit tests. ...
Definition: rtp_engine.h:595
struct timeval delivery
struct ast_frame ast_null_frame
Definition: main/frame.c:79
static void ntp2timeval(unsigned int msw, unsigned int lsw, struct timeval *tv)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define RTCP_VERSION_MASK_SHIFTED
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:716
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
static void update_jitter_stats(struct ast_rtp *rtp, unsigned int ia_jitter)
union ast_frame::@263 data
#define RTCP_PT_SDES
enum ast_frame_type frametype
#define RTCP_PT_BYE
unsigned int source_ssrc
Definition: rtp_engine.h:317
#define RTCP_PT_PSFB
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:309
struct ast_rtp_rtcp_report_block::@314 lost_count

◆ ast_rtcp_read()

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

Definition at line 6590 of file res_rtp_asterisk.c.

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, rtcp_recvfrom(), RTP_DTLS_ESTABLISHED, ast_rtp::s, and ast_frame::subclass.

Referenced by ast_rtp_read().

6591 {
6592  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6593  struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 1);
6594  struct ast_sockaddr addr;
6595  unsigned char rtcpdata[8192 + AST_FRIENDLY_OFFSET];
6596  unsigned char *read_area = rtcpdata + AST_FRIENDLY_OFFSET;
6597  size_t read_area_size = sizeof(rtcpdata) - AST_FRIENDLY_OFFSET;
6598  int res;
6599 
6600  /* Read in RTCP data from the socket */
6601  if ((res = rtcp_recvfrom(instance, read_area, read_area_size,
6602  0, &addr)) < 0) {
6603  if (res == RTP_DTLS_ESTABLISHED) {
6604  rtp->f.frametype = AST_FRAME_CONTROL;
6606  return &rtp->f;
6607  }
6608 
6609  ast_assert(errno != EBADF);
6610  if (errno != EAGAIN) {
6611  ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n",
6612  (errno) ? strerror(errno) : "Unspecified");
6613  return NULL;
6614  }
6615  return &ast_null_frame;
6616  }
6617 
6618  /* If this was handled by the ICE session don't do anything further */
6619  if (!res) {
6620  return &ast_null_frame;
6621  }
6622 
6623  if (!*read_area) {
6624  struct sockaddr_in addr_tmp;
6625  struct ast_sockaddr addr_v4;
6626 
6627  if (ast_sockaddr_is_ipv4(&addr)) {
6628  ast_sockaddr_to_sin(&addr, &addr_tmp);
6629  } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
6630  ast_debug_stun(2, "(%p) STUN using IPv6 mapped address %s\n",
6631  instance, ast_sockaddr_stringify(&addr));
6632  ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
6633  } else {
6634  ast_debug_stun(2, "(%p) STUN cannot do for non IPv4 address %s\n",
6635  instance, ast_sockaddr_stringify(&addr));
6636  return &ast_null_frame;
6637  }
6638  if ((ast_stun_handle_packet(rtp->rtcp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT)) {
6639  ast_sockaddr_from_sin(&addr, &addr_tmp);
6640  ast_sockaddr_copy(&rtp->rtcp->them, &addr);
6641  }
6642  return &ast_null_frame;
6643  }
6644 
6645  return ast_rtcp_interpret(instance, srtp, read_area, res, &addr);
6646 }
RTP session description.
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:171
#define LOG_WARNING
Definition: logger.h:274
#define RTP_DTLS_ESTABLISHED
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
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
Definition: rtp_engine.c:2763
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
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:268
Socket address structure.
Definition: netsock2.h:97
static int rtcp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
struct ast_frame_subclass subclass
#define ast_log
Definition: astobj2.c:42
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:782
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)
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:53
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
struct ast_frame f
struct ast_frame ast_null_frame
Definition: main/frame.c:79
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:769
enum ast_frame_type frametype

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

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, cleanup(), errno, LOG_ERROR, RAII_VAR, rtcp_sendto(), and ast_rtp::themssrc_valid.

Referenced by ast_rtp_interpret(), and rtp_raw_write().

4815 {
4816  struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
4817  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4818  int res;
4819  int sr = 0;
4820  int packet_len = 0;
4821  int ice;
4822  struct ast_sockaddr remote_address = { { 0, } };
4823  unsigned char *rtcpheader;
4824  unsigned char bdata[AST_UUID_STR_LEN + 128] = ""; /* More than enough */
4825  RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
4827  ao2_cleanup);
4828 
4829  if (!rtp || !rtp->rtcp || rtp->rtcp->schedid == -1) {
4830  ao2_ref(instance, -1);
4831  return 0;
4832  }
4833 
4834  ao2_lock(instance);
4835  rtcpheader = bdata;
4836 
4837  res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
4838 
4839  if (res == 0 || res == 1) {
4840  goto cleanup;
4841  }
4842 
4843  packet_len += res;
4844 
4845  if (rtp->bundled) {
4846  ast_rtp_instance_get_remote_address(instance, &remote_address);
4847  } else {
4848  ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
4849  }
4850 
4851  res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
4852  if (res < 0) {
4853  ast_log(LOG_ERROR, "RTCP %s transmission error to %s, rtcp halted %s\n",
4854  sr ? "SR" : "RR",
4855  ast_sockaddr_stringify(&rtp->rtcp->them),
4856  strerror(errno));
4857  res = 0;
4858  } else {
4859  ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
4860  }
4861 
4862 cleanup:
4863  ao2_unlock(instance);
4864 
4865  if (!res) {
4866  /*
4867  * Not being rescheduled.
4868  */
4869  rtp->rtcp->schedid = -1;
4870  ao2_ref(instance, -1);
4871  }
4872 
4873  return res;
4874 }
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:331
RTP session description.
static int ast_rtcp_generate_compound_prefix(struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
#define AST_UUID_STR_LEN
Definition: uuid.h:27
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:171
#define ao2_unlock(a)
Definition: astobj2.h:730
Socket address structure.
Definition: netsock2.h:97
#define ast_log
Definition: astobj2.c:42
#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:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
unsigned int themssrc_valid
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.
Definition: rtp_engine.c:3474
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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 rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192

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

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

8939 {
8940  struct ast_rtp *child_rtp = ast_rtp_instance_get_data(child);
8941  struct ast_rtp *parent_rtp;
8942  struct rtp_ssrc_mapping mapping;
8943  struct ast_sockaddr them = { { 0, } };
8944 
8945  if (child_rtp->bundled == parent) {
8946  return 0;
8947  }
8948 
8949  /* If this instance was already bundled then remove the SSRC mapping */
8950  if (child_rtp->bundled) {
8951  struct ast_rtp *bundled_rtp;
8952 
8953  ao2_unlock(child);
8954 
8955  /* The child lock can't be held while accessing the parent */
8956  ao2_lock(child_rtp->bundled);
8957  bundled_rtp = ast_rtp_instance_get_data(child_rtp->bundled);
8959  ao2_unlock(child_rtp->bundled);
8960 
8961  ao2_lock(child);
8962  ao2_ref(child_rtp->bundled, -1);
8963  child_rtp->bundled = NULL;
8964  }
8965 
8966  if (!parent) {
8967  /* We transitioned away from bundle so we need our own transport resources once again */
8968  rtp_allocate_transport(child, child_rtp);
8969  return 0;
8970  }
8971 
8972  parent_rtp = ast_rtp_instance_get_data(parent);
8973 
8974  /* We no longer need any transport related resources as we will use our parent RTP instance instead */
8975  rtp_deallocate_transport(child, child_rtp);
8976 
8977  /* Children maintain a reference to the parent to guarantee that the transport doesn't go away on them */
8978  child_rtp->bundled = ao2_bump(parent);
8979 
8980  mapping.ssrc = child_rtp->themssrc;
8981  mapping.ssrc_valid = child_rtp->themssrc_valid;
8982  mapping.instance = child;
8983 
8984  ao2_unlock(child);
8985 
8986  ao2_lock(parent);
8987 
8988  AST_VECTOR_APPEND(&parent_rtp->ssrc_mapping, mapping);
8989 
8990 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8991  /* If DTLS-SRTP is already in use then add the local SSRC to it, otherwise it will get added once DTLS
8992  * negotiation has been completed.
8993  */
8994  if (parent_rtp->dtls.connection == AST_RTP_DTLS_CONNECTION_EXISTING) {
8995  dtls_srtp_add_local_ssrc(parent_rtp, parent, 0, child_rtp->ssrc, 0);
8996  }
8997 #endif
8998 
8999  /* Bundle requires that RTCP-MUX be in use so only the main remote address needs to match */
9000  ast_rtp_instance_get_remote_address(parent, &them);
9001 
9002  ao2_unlock(parent);
9003 
9004  ao2_lock(child);
9005 
9007 
9008  return 0;
9009 }
RTP session description.
Structure used for mapping an incoming SSRC to an RTP instance.
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition: vector.h:488
static int rtp_allocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define SSRC_MAPPING_ELEM_CMP(elem, value)
SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()
#define ao2_unlock(a)
Definition: astobj2.h:730
static void rtp_deallocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define ao2_bump(obj)
Definition: astobj2.h:491
unsigned int ssrc
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:573
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
unsigned int themssrc_valid
unsigned int themssrc
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1080
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192

◆ ast_rtp_change_source()

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

Definition at line 4360 of file res_rtp_asterisk.c.

References ast_debug_rtp, ast_random(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_set_flag, ast_srtp_res::change_source, ast_rtp::expectedrxseqno, FLAG_NEED_MARKER_BIT, ast_rtp::lastts, and ast_rtp::ssrc.

4361 {
4362  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4363  struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance, 0);
4364  struct ast_srtp *rtcp_srtp = ast_rtp_instance_get_srtp(instance, 1);
4365  unsigned int ssrc = ast_random();
4366 
4367  if (rtp->lastts) {
4368  /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4370  }
4371 
4372  ast_debug_rtp(3, "(%p) RTP changing ssrc from %u to %u due to a source change\n",
4373  instance, rtp->ssrc, ssrc);
4374 
4375  if (srtp) {
4376  ast_debug_rtp(3, "(%p) RTP changing ssrc for SRTP from %u to %u\n",
4377  instance, rtp->ssrc, ssrc);
4378  res_srtp->change_source(srtp, rtp->ssrc, ssrc);
4379  if (rtcp_srtp != srtp) {
4380  res_srtp->change_source(rtcp_srtp, rtp->ssrc, ssrc);
4381  }
4382  }
4383 
4384  rtp->ssrc = ssrc;
4385 
4386  /* Since the source is changing, we don't know what sequence number to expect next */
4387  rtp->expectedrxseqno = -1;
4388 
4389  return;
4390 }
RTP session description.
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct ast_srtp * ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance, int rtcp)
Obtain the SRTP instance associated with an RTP instance.
Definition: rtp_engine.c:2763
int(* change_source)(struct ast_srtp *srtp, unsigned int from_ssrc, unsigned int to_ssrc)
Definition: res_srtp.h:44
unsigned int ssrc
struct ast_srtp_res * res_srtp
Definition: rtp_engine.c:177
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
long int ast_random(void)
Definition: main/utils.c:2064
#define FLAG_NEED_MARKER_BIT
int expectedrxseqno
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
unsigned int lastts

◆ ast_rtp_destroy()

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

Definition at line 4048 of file res_rtp_asterisk.c.

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::f, ast_frame_subclass::format, NULL, rtp_deallocate_transport(), SSRC_MAPPING_ELEM_CMP, and ast_frame::subclass.

4049 {
4050  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4051 
4052  if (rtp->bundled) {
4053  struct ast_rtp *bundled_rtp;
4054 
4055  /* We can't hold our instance lock while removing ourselves from the parent */
4056  ao2_unlock(instance);
4057 
4058  ao2_lock(rtp->bundled);
4059  bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
4061  ao2_unlock(rtp->bundled);
4062 
4063  ao2_lock(instance);
4064  ao2_ref(rtp->bundled, -1);
4065  }
4066 
4067  rtp_deallocate_transport(instance, rtp);
4068 
4069  /* Destroy the smoother that was smoothing out audio if present */
4070  if (rtp->smoother) {
4071  ast_smoother_free(rtp->smoother);
4072  }
4073 
4074  /* Destroy RTCP if it was being used */
4075  if (rtp->rtcp) {
4076  /*
4077  * It is not possible for there to be an active RTCP scheduler
4078  * entry at this point since it holds a reference to the
4079  * RTP instance while it's active.
4080  */
4081  ast_free(rtp->rtcp->local_addr_str);
4082  ast_free(rtp->rtcp);
4083  }
4084 
4085  /* Destroy RED if it was being used */
4086  if (rtp->red) {
4087  ao2_unlock(instance);
4088  AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
4089  ao2_lock(instance);
4090  ast_free(rtp->red);
4091  rtp->red = NULL;
4092  }
4093 
4094  /* Destroy the send buffer if it was being used */
4095  if (rtp->send_buffer) {
4096  ast_data_buffer_free(rtp->send_buffer);
4097  }
4098 
4099  /* Destroy the recv buffer if it was being used */
4100  if (rtp->recv_buffer) {
4101  ast_data_buffer_free(rtp->recv_buffer);
4102  }
4103 
4104  AST_VECTOR_FREE(&rtp->transport_wide_cc.packet_statistics);
4105 
4106  ao2_cleanup(rtp->lasttxformat);
4107  ao2_cleanup(rtp->lastrxformat);
4108  ao2_cleanup(rtp->f.subclass.format);
4109  AST_VECTOR_FREE(&rtp->ssrc_mapping);
4110  AST_VECTOR_FREE(&rtp->missing_seqno);
4111 
4112  /* Finally destroy ourselves */
4113  ast_free(rtp);
4114 
4115  return 0;
4116 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
RTP session description.
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition: vector.h:488
#define SSRC_MAPPING_ELEM_CMP(elem, value)
SSRC mapping comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()
#define ao2_unlock(a)
Definition: astobj2.h:730
static void rtp_deallocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:573
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_free(a)
Definition: astmm.h:182
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
struct ast_frame f
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_format * format
void ast_data_buffer_free(struct ast_data_buffer *buffer)
Free a data buffer (and all held data payloads)
Definition: data_buffer.c:338

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

References ast_log, ast_rtp_codecs_payload_code_tx(), AST_RTP_DTMF, 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(), calc_txstamp(), digit, DTMF_SAMPLE_RATE_MS, errno, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, NULL, rtp_debug_test_addr(), rtp_sendto(), and ast_rtp::ssrc.

4135 {
4136  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4137  struct ast_sockaddr remote_address = { {0,} };
4138  int hdrlen = 12, res = 0, i = 0, payload = 101;
4139  char data[256];
4140  unsigned int *rtpheader = (unsigned int*)data;
4141 
4142  ast_rtp_instance_get_remote_address(instance, &remote_address);
4143 
4144  /* If we have no remote address information bail out now */
4145  if (ast_sockaddr_isnull(&remote_address)) {
4146  return -1;
4147  }
4148 
4149  /* Convert given digit into what we want to transmit */
4150  if ((digit <= '9') && (digit >= '0')) {
4151  digit -= '0';
4152  } else if (digit == '*') {
4153  digit = 10;
4154  } else if (digit == '#') {
4155  digit = 11;
4156  } else if ((digit >= 'A') && (digit <= 'D')) {
4157  digit = digit - 'A' + 12;
4158  } else if ((digit >= 'a') && (digit <= 'd')) {
4159  digit = digit - 'a' + 12;
4160  } else {
4161  ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4162  return -1;
4163  }
4164 
4165  /* Grab the payload that they expect the RFC2833 packet to be received in */
4167 
4168  rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4169  rtp->send_duration = 160;
4170  rtp->lastts += calc_txstamp(rtp, NULL) * DTMF_SAMPLE_RATE_MS;
4171  rtp->lastdigitts = rtp->lastts + rtp->send_duration;
4172 
4173  /* Create the actual packet that we will be sending */
4174  rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
4175  rtpheader[1] = htonl(rtp->lastdigitts);
4176  rtpheader[2] = htonl(rtp->ssrc);
4177 
4178  /* Actually send the packet */
4179  for (i = 0; i < 2; i++) {
4180  int ice;
4181 
4182  rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4183  res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4184  if (res < 0) {
4185  ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4186  ast_sockaddr_stringify(&remote_address),
4187  strerror(errno));
4188  }
4189  if (rtp_debug_test_addr(&remote_address)) {
4190  ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4191  ast_sockaddr_stringify(&remote_address),
4192  ice ? " (via ICE)" : "",
4193  payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4194  }
4195  rtp->seqno++;
4196  rtp->send_duration += 160;
4197  rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
4198  }
4199 
4200  /* Record that we are in the process of sending a digit and information needed to continue doing so */
4201  rtp->sending_digit = 1;
4202  rtp->send_digit = digit;
4203  rtp->send_payload = payload;
4204 
4205  return 0;
4206 }
char digit
RTP session description.
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:727
#define LOG_WARNING
Definition: logger.h:274
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
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...
Definition: rtp_engine.c:1928
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
unsigned int ssrc
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int errno
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define DTMF_SAMPLE_RATE_MS
unsigned int lastts
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
#define AST_RTP_DTMF
Definition: rtp_engine.h:266
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192

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

References ast_channel_tech(), ast_rtp_instance_get_prop(), and AST_RTP_PROPERTY_DTMF.

8724 {
8725  /* If both sides are not using the same method of DTMF transmission
8726  * (ie: one is RFC2833, other is INFO... then we can not do direct media.
8727  * --------------------------------------------------
8728  * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
8729  * |-----------|------------|-----------------------|
8730  * | Inband | False | True |
8731  * | RFC2833 | True | True |
8732  * | SIP INFO | False | False |
8733  * --------------------------------------------------
8734  */
8736  (!ast_channel_tech(chan0)->send_digit_begin != !ast_channel_tech(chan1)->send_digit_begin)) ? 0 : 1);
8737 }
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:716
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)

◆ ast_rtp_dtmf_continuation()

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

Definition at line 4209 of file res_rtp_asterisk.c.

References ast_log, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose(), calc_txstamp(), DTMF_SAMPLE_RATE_MS, errno, ast_rtp::lastts, LOG_ERROR, NULL, rtp_debug_test_addr(), rtp_sendto(), and ast_rtp::ssrc.

Referenced by ast_rtp_interpret().

4210 {
4211  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4212  struct ast_sockaddr remote_address = { {0,} };
4213  int hdrlen = 12, res = 0;
4214  char data[256];
4215  unsigned int *rtpheader = (unsigned int*)data;
4216  int ice;
4217 
4218  ast_rtp_instance_get_remote_address(instance, &remote_address);
4219 
4220  /* Make sure we know where the other side is so we can send them the packet */
4221  if (ast_sockaddr_isnull(&remote_address)) {
4222  return -1;
4223  }
4224 
4225  /* Actually create the packet we will be sending */
4226  rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4227  rtpheader[1] = htonl(rtp->lastdigitts);
4228  rtpheader[2] = htonl(rtp->ssrc);
4229  rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
4230 
4231  /* Boom, send it on out */
4232  res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4233  if (res < 0) {
4234  ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4235  ast_sockaddr_stringify(&remote_address),
4236  strerror(errno));
4237  }
4238 
4239  if (rtp_debug_test_addr(&remote_address)) {
4240  ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4241  ast_sockaddr_stringify(&remote_address),
4242  ice ? " (via ICE)" : "",
4243  rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4244  }
4245 
4246  /* And now we increment some values for the next time we swing by */
4247  rtp->seqno++;
4248  rtp->send_duration += 160;
4249  rtp->lastts += calc_txstamp(rtp, NULL) * DTMF_SAMPLE_RATE_MS;
4250 
4251  return 0;
4252 }
RTP session description.
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
unsigned int ssrc
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define DTMF_SAMPLE_RATE_MS
unsigned int lastts
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192

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

References ast_rtp_dtmf_end_with_duration().

4343 {
4344  return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
4345 }
char digit
static int ast_rtp_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)

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

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(), DTMF_SAMPLE_RATE_MS, errno, ast_rtp::f, ast_frame_subclass::format, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, NULL, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::ssrc, and ast_frame::subclass.

Referenced by ast_rtp_dtmf_end().

4256 {
4257  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4258  struct ast_sockaddr remote_address = { {0,} };
4259  int hdrlen = 12, res = -1, i = 0;
4260  char data[256];
4261  unsigned int *rtpheader = (unsigned int*)data;
4262  unsigned int measured_samples;
4263 
4264  ast_rtp_instance_get_remote_address(instance, &remote_address);
4265 
4266  /* Make sure we know where the remote side is so we can send them the packet we construct */
4267  if (ast_sockaddr_isnull(&remote_address)) {
4268  goto cleanup;
4269  }
4270 
4271  /* Convert the given digit to the one we are going to send */
4272  if ((digit <= '9') && (digit >= '0')) {
4273  digit -= '0';
4274  } else if (digit == '*') {
4275  digit = 10;
4276  } else if (digit == '#') {
4277  digit = 11;
4278  } else if ((digit >= 'A') && (digit <= 'D')) {
4279  digit = digit - 'A' + 12;
4280  } else if ((digit >= 'a') && (digit <= 'd')) {
4281  digit = digit - 'a' + 12;
4282  } else {
4283  ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
4284  goto cleanup;
4285  }
4286 
4287  rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
4288 
4289  if (duration > 0 && (measured_samples = duration * ast_rtp_get_rate(rtp->f.subclass.format) / 1000) > rtp->send_duration) {
4290  ast_debug_rtp(2, "(%p) RTP adjusting final end duration from %d to %u\n",
4291  instance, rtp->send_duration, measured_samples);
4292  rtp->send_duration = measured_samples;
4293  }
4294 
4295  /* Construct the packet we are going to send */
4296  rtpheader[1] = htonl(rtp->lastdigitts);
4297  rtpheader[2] = htonl(rtp->ssrc);
4298  rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
4299  rtpheader[3] |= htonl((1 << 23));
4300 
4301  /* Send it 3 times, that's the magical number */
4302  for (i = 0; i < 3; i++) {
4303  int ice;
4304 
4305  rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
4306 
4307  res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address, &ice);
4308 
4309  if (res < 0) {
4310  ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
4311  ast_sockaddr_stringify(&remote_address),
4312  strerror(errno));
4313  }
4314 
4315  if (rtp_debug_test_addr(&remote_address)) {
4316  ast_verbose("Sent RTP DTMF packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
4317  ast_sockaddr_stringify(&remote_address),
4318  ice ? " (via ICE)" : "",
4319  rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
4320  }
4321 
4322  rtp->seqno++;
4323  }
4324  res = 0;
4325 
4326  /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
4327  rtp->lastts += calc_txstamp(rtp, NULL) * DTMF_SAMPLE_RATE_MS;
4328 
4329  /* Reset the smoother as the delivery time stored in it is now out of date */
4330  if (rtp->smoother) {
4331  ast_smoother_free(rtp->smoother);
4332  rtp->smoother = NULL;
4333  }
4334 cleanup:
4335  rtp->sending_digit = 0;
4336  rtp->send_digit = 0;
4337 
4338  return res;
4339 }
char digit
RTP session description.
#define LOG_WARNING
Definition: logger.h:274
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
struct ast_frame_subclass subclass
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
unsigned int ssrc
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_log
Definition: astobj2.c:42
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
int ast_rtp_get_rate(const struct ast_format *format)
Retrieve the sample rate of a format according to RTP specifications.
Definition: rtp_engine.c:4030
#define LOG_ERROR
Definition: logger.h:285
int errno
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define DTMF_SAMPLE_RATE_MS
struct ast_frame f
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
unsigned int lastts
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
struct ast_format * format
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192

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

References ast_rtp_instance_get_data().

4128 {
4129  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4130  return rtp->dtmfmode;
4131 }
RTP session description.
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

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

References ast_rtp_instance_get_data().

4120 {
4121  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4122  rtp->dtmfmode = dtmf_mode;
4123  return 0;
4124 }
RTP session description.
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_extension_enable()

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

Definition at line 8926 of file res_rtp_asterisk.c.

References AST_RTP_EXTENSION_ABS_SEND_TIME, and AST_RTP_EXTENSION_TRANSPORT_WIDE_CC.

8927 {
8928  switch (extension) {
8931  return 1;
8932  default:
8933  return 0;
8934  }
8935 }
structure to hold extensions

◆ ast_rtp_fd()

static int ast_rtp_fd ( struct ast_rtp_instance instance,
int  rtcp 
)
static
Precondition
instance is locked

Definition at line 8489 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::s.

8490 {
8491  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8492 
8493  return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
8494 }
RTP session description.
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_get_cname()

static const char * ast_rtp_get_cname ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 8873 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::cname.

8874 {
8875  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8876 
8877  return rtp->cname;
8878 }
RTP session description.
char cname[AST_UUID_STR_LEN]
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_get_ssrc()

static unsigned int ast_rtp_get_ssrc ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 8865 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::ssrc.

Referenced by __rtp_find_instance_by_ssrc().

8866 {
8867  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8868 
8869  return rtp->ssrc;
8870 }
RTP session description.
unsigned int ssrc
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

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

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_RTT, AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_SSRC, AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, 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_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_SSRC, AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, 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_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_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_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevrxploss, ast_rtp_instance_stats::maxrtt, ast_rtp_instance_stats::minrtt, ast_rtp_instance_stats::normdevrtt, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevrxploss, ast_rtp_instance_stats::rtt, ast_rtp_instance_stats::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp_instance_stats::rxoctetcount, ast_rtp_instance_stats::rxploss, ast_rtp::ssrc, ast_rtp_instance_stats::stdevrtt, ast_rtp::themssrc, ast_rtp_instance_stats::txcount, ast_rtp_instance_stats::txjitter, ast_rtp_instance_stats::txoctetcount, and ast_rtp_instance_stats::txploss.

8672 {
8673  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8674 
8675  if (!rtp->rtcp) {
8676  return -1;
8677  }
8678 
8679  AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
8680  AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
8681  AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXOCTETCOUNT, -1, stats->txoctetcount, rtp->txoctetcount);
8682  AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXOCTETCOUNT, -1, stats->rxoctetcount, rtp->rxoctetcount);
8683 
8685  AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->rxploss, rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
8695 
8697  AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->rxjitter, rtp->rtcp->reported_jitter / (unsigned int) 65536.0);
8707 
8714 
8718 
8719  return 0;
8720 }
RTP session description.
#define AST_RTP_STAT_STRCPY(current_stat, combined, placement, value)
Definition: rtp_engine.h:441
unsigned int txcount
Definition: rtp_engine.h:368
unsigned int rxploss
Definition: rtp_engine.h:394
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:548
unsigned int ssrc
char channel_uniqueid[MAX_CHANNEL_ID]
Definition: rtp_engine.h:426
unsigned int txoctetcount
Definition: rtp_engine.h:428
unsigned int rxcount
Definition: rtp_engine.h:370
unsigned int themssrc
unsigned int rxoctetcount
Definition: rtp_engine.h:430
unsigned int local_ssrc
Definition: rtp_engine.h:422
unsigned int txploss
Definition: rtp_engine.h:392
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
#define AST_RTP_STAT_SET(current_stat, combined, placement, value)
Definition: rtp_engine.h:433
#define AST_RTP_STAT_TERMINATOR(combined)
Definition: rtp_engine.h:449
unsigned int remote_ssrc
Definition: rtp_engine.h:424

◆ ast_rtp_ice_add_cand()

static void ast_rtp_ice_add_cand ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned  comp_id,
unsigned  transport_id,
pj_ice_cand_type  type,
pj_uint16_t  local_pref,
const pj_sockaddr_t *  addr,
const pj_sockaddr_t *  base_addr,
const pj_sockaddr_t *  rel_addr,
int  addr_len 
)
static
Precondition
instance is locked

Definition at line 1239 of file res_rtp_asterisk.c.

References ast_rtp_engine_ice_candidate::address, ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug_ice, ast_rtp_ice_candidate_destroy(), AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, ast_sockaddr_parse(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdup, ast_strndup, ast_rtp_engine_ice_candidate::foundation, ice_candidate_cmp(), ast_rtp_engine_ice_candidate::id, NULL, OBJ_POINTER, pj_thread_register_check(), ast_rtp_engine_ice_candidate::priority, ice_wrap::real_ice, ast_rtp_engine_ice_candidate::relay_address, status, ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

Referenced by ast_rtp_ice_turn_request(), and rtp_add_candidates_to_ice().

1243 {
1244  pj_str_t foundation;
1245  struct ast_rtp_engine_ice_candidate *candidate, *existing;
1246  struct ice_wrap *ice;
1247  char address[PJ_INET6_ADDRSTRLEN];
1248  pj_status_t status;
1249 
1250  if (!rtp->ice) {
1251  return;
1252  }
1253 
1255 
1256  pj_ice_calc_foundation(rtp->ice->real_ice->pool, &foundation, type, addr);
1257 
1258  if (!rtp->ice_local_candidates) {
1259  rtp->ice_local_candidates = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
1261  if (!rtp->ice_local_candidates) {
1262  return;
1263  }
1264  }
1265 
1266  if (!(candidate = ao2_alloc(sizeof(*candidate), ast_rtp_ice_candidate_destroy))) {
1267  return;
1268  }
1269 
1270  candidate->foundation = ast_strndup(pj_strbuf(&foundation), pj_strlen(&foundation));
1271  candidate->id = comp_id;
1272  candidate->transport = ast_strdup("UDP");
1273 
1274  ast_sockaddr_parse(&candidate->address, pj_sockaddr_print(addr, address, sizeof(address), 0), 0);
1275  ast_sockaddr_set_port(&candidate->address, pj_sockaddr_get_port(addr));
1276 
1277  if (rel_addr) {
1278  ast_sockaddr_parse(&candidate->relay_address, pj_sockaddr_print(rel_addr, address, sizeof(address), 0), 0);
1279  ast_sockaddr_set_port(&candidate->relay_address, pj_sockaddr_get_port(rel_addr));
1280  }
1281 
1282  if (type == PJ_ICE_CAND_TYPE_HOST) {
1284  } else if (type == PJ_ICE_CAND_TYPE_SRFLX) {
1286  } else if (type == PJ_ICE_CAND_TYPE_RELAYED) {
1288  }
1289 
1290  if ((existing = ao2_find(rtp->ice_local_candidates, candidate, OBJ_POINTER))) {
1291  ao2_ref(existing, -1);
1292  ao2_ref(candidate, -1);
1293  return;
1294  }
1295 
1296  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
1297  ice = rtp->ice;
1298  ao2_ref(ice, +1);
1299  ao2_unlock(instance);
1300  status = pj_ice_sess_add_cand(ice->real_ice, comp_id, transport_id, type, local_pref,
1301  &foundation, addr, base_addr, rel_addr, addr_len, NULL);
1302  ao2_ref(ice, -1);
1303  ao2_lock(instance);
1304  if (!rtp->ice || status != PJ_SUCCESS) {
1305  ast_debug_ice(2, "(%p) ICE unable to add candidate: %s, %d\n", instance, ast_sockaddr_stringify(
1306  &candidate->address), candidate->priority);
1307  ao2_ref(candidate, -1);
1308  return;
1309  }
1310 
1311  /* By placing the candidate into the ICE session it will have produced the priority, so update the local candidate with it */
1312  candidate->priority = rtp->ice->real_ice->lcand[rtp->ice->real_ice->lcand_cnt - 1].prio;
1313 
1314  ast_debug_ice(2, "(%p) ICE add candidate: %s, %d\n", instance, ast_sockaddr_stringify(
1315  &candidate->address), candidate->priority);
1316 
1317  ao2_link(rtp->ice_local_candidates, candidate);
1318  ao2_ref(candidate, -1);
1319 }
static const char type[]
Definition: chan_ooh323.c:109
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
char * address
Definition: f2c.h:59
#define OBJ_POINTER
Definition: astobj2.h:1154
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
Structure for an ICE candidate.
Definition: rtp_engine.h:474
static void pj_thread_register_check(void)
Function used to check if the calling thread is registered with pjlib. If it is not it will be regist...
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:481
static void ast_rtp_ice_candidate_destroy(void *obj)
Destructor for locally created ICE candidates.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_sockaddr relay_address
Definition: rtp_engine.h:480
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:476
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:258
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int ice_candidate_cmp(void *obj, void *arg, int flags)
struct ast_sockaddr address
Definition: rtp_engine.h:479
pj_ice_sess * real_ice
jack_status_t status
Definition: app_jack.c:146
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_rtp_ice_add_remote_candidate()

static void ast_rtp_ice_add_remote_candidate ( struct ast_rtp_instance instance,
const struct ast_rtp_engine_ice_candidate candidate 
)
static
Precondition
instance is locked

Definition at line 821 of file res_rtp_asterisk.c.

References ast_rtp_engine_ice_candidate::address, ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, ao2_container_count(), ao2_link, ao2_ref, ast_debug_ice, ast_rtp_ice_candidate_destroy(), ast_rtp_instance_get_data(), ast_sockaddr_copy(), ast_strdup, ast_rtp_engine_ice_candidate::foundation, ice_candidate_cmp(), ast_rtp_engine_ice_candidate::id, NULL, ast_rtp_engine_ice_candidate::priority, ast_rtp_engine_ice_candidate::relay_address, ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

822 {
823  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
824  struct ast_rtp_engine_ice_candidate *remote_candidate;
825 
826  /* ICE sessions only support UDP candidates */
827  if (strcasecmp(candidate->transport, "udp")) {
828  return;
829  }
830 
831  if (!rtp->ice_proposed_remote_candidates) {
832  rtp->ice_proposed_remote_candidates = ao2_container_alloc_list(
834  if (!rtp->ice_proposed_remote_candidates) {
835  return;
836  }
837  }
838 
839  /* If this is going to exceed the maximum number of ICE candidates don't even add it */
840  if (ao2_container_count(rtp->ice_proposed_remote_candidates) == PJ_ICE_MAX_CAND) {
841  return;
842  }
843 
844  if (!(remote_candidate = ao2_alloc(sizeof(*remote_candidate), ast_rtp_ice_candidate_destroy))) {
845  return;
846  }
847 
848  remote_candidate->foundation = ast_strdup(candidate->foundation);
849  remote_candidate->id = candidate->id;
850  remote_candidate->transport = ast_strdup(candidate->transport);
851  remote_candidate->priority = candidate->priority;
852  ast_sockaddr_copy(&remote_candidate->address, &candidate->address);
853  ast_sockaddr_copy(&remote_candidate->relay_address, &candidate->relay_address);
854  remote_candidate->type = candidate->type;
855 
856  ast_debug_ice(2, "(%p) ICE add remote candidate\n", instance);
857 
858  ao2_link(rtp->ice_proposed_remote_candidates, remote_candidate);
859  ao2_ref(remote_candidate, -1);
860 }
RTP session description.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
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:171
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
Structure for an ICE candidate.
Definition: rtp_engine.h:474
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:481
static void ast_rtp_ice_candidate_destroy(void *obj)
Destructor for locally created ICE candidates.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_sockaddr relay_address
Definition: rtp_engine.h:480
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:476
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
static int ice_candidate_cmp(void *obj, void *arg, int flags)
struct ast_sockaddr address
Definition: rtp_engine.h:479
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_rtp_ice_candidate_destroy()

static void ast_rtp_ice_candidate_destroy ( void *  obj)
static

Destructor for locally created ICE candidates.

Definition at line 766 of file res_rtp_asterisk.c.

References ast_free, ast_rtp_engine_ice_candidate::foundation, and ast_rtp_engine_ice_candidate::transport.

Referenced by ast_rtp_ice_add_cand(), and ast_rtp_ice_add_remote_candidate().

767 {
768  struct ast_rtp_engine_ice_candidate *candidate = obj;
769 
770  if (candidate->foundation) {
771  ast_free(candidate->foundation);
772  }
773 
774  if (candidate->transport) {
775  ast_free(candidate->transport);
776  }
777 }
Structure for an ICE candidate.
Definition: rtp_engine.h:474
#define ast_free(a)
Definition: astmm.h:182

◆ ast_rtp_ice_change_components()

static void ast_rtp_ice_change_components ( struct ast_rtp_instance instance,
int  num_components 
)
static
Precondition
instance is locked

Definition at line 1734 of file res_rtp_asterisk.c.

References ast_debug_ice, ast_rtp_instance_get_data(), ice_reset_session(), and icesupport.

1735 {
1736  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1737 
1738  /* Don't do anything if ICE is unsupported or if we're not changing the
1739  * number of components
1740  */
1741  if (!icesupport || !rtp->ice || rtp->ice_num_components == num_components) {
1742  return;
1743  }
1744 
1745  ast_debug_ice(2, "(%p) ICE change number of components %u -> %u\n", instance,
1746  rtp->ice_num_components, num_components);
1747 
1748  rtp->ice_num_components = num_components;
1749  ice_reset_session(instance);
1750 }
RTP session description.
static int icesupport
static int ice_reset_session(struct ast_rtp_instance *instance)
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_ice_get_local_candidates()

static struct ao2_container* ast_rtp_ice_get_local_candidates ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 1189 of file res_rtp_asterisk.c.

References ao2_ref, and ast_rtp_instance_get_data().

1190 {
1191  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1192 
1193  if (rtp->ice_local_candidates) {
1194  ao2_ref(rtp->ice_local_candidates, +1);
1195  }
1196 
1197  return rtp->ice_local_candidates;
1198 }
RTP session description.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_ice_get_password()

static const char* ast_rtp_ice_get_password ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 1181 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data().

1182 {
1183  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1184 
1185  return rtp->local_passwd;
1186 }
RTP session description.
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_ice_get_ufrag()

static const char* ast_rtp_ice_get_ufrag ( struct ast_rtp_instance instance)
static
Precondition
instance is locked

Definition at line 1173 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data().

1174 {
1175  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1176 
1177  return rtp->local_ufrag;
1178 }
RTP session description.
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_ice_lite()

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

Definition at line 1201 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and pj_thread_register_check().

1202 {
1203  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1204 
1205  if (!rtp->ice) {
1206  return;
1207  }
1208 
1210 
1211  pj_ice_sess_change_role(rtp->ice->real_ice, PJ_ICE_SESS_ROLE_CONTROLLING);
1212 }
RTP session description.
static void pj_thread_register_check(void)
Function used to check if the calling thread is registered with pjlib. If it is not it will be regist...
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_ice_set_authentication()

static void ast_rtp_ice_set_authentication ( struct ast_rtp_instance instance,
const char *  ufrag,
const char *  password 
)
static
Precondition
instance is locked

Definition at line 780 of file res_rtp_asterisk.c.

References ast_copy_string(), ast_rtp_instance_get_data(), ast_strlen_zero, and generate_random_string().

781 {
782  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
783  int ice_attrb_reset = 0;
784 
785  if (!ast_strlen_zero(ufrag)) {
786  if (!ast_strlen_zero(rtp->remote_ufrag) && strcmp(ufrag, rtp->remote_ufrag)) {
787  ice_attrb_reset = 1;
788  }
789  ast_copy_string(rtp->remote_ufrag, ufrag, sizeof(rtp->remote_ufrag));
790  }
791 
792  if (!ast_strlen_zero(password)) {
793  if (!ast_strlen_zero(rtp->remote_passwd) && strcmp(password, rtp->remote_passwd)) {
794  ice_attrb_reset = 1;
795  }
796  ast_copy_string(rtp->remote_passwd, password, sizeof(rtp->remote_passwd));
797  }
798 
799  /* If the remote ufrag or passwd changed, local ufrag and passwd need to regenerate */
800  if (ice_attrb_reset) {
801  generate_random_string(rtp->local_ufrag, sizeof(rtp->local_ufrag));
802  generate_random_string(rtp->local_passwd, sizeof(rtp->local_passwd));
803  }
804 }
RTP session description.
static struct ast_str * password
Definition: cdr_mysql.c:77
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char * generate_random_string(char *buf, size_t size)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_rtp_ice_set_role()

static void ast_rtp_ice_set_role ( struct ast_rtp_instance instance,
enum ast_rtp_ice_role  role 
)
static
Precondition
instance is locked

Definition at line 1215 of file res_rtp_asterisk.c.

References ast_debug_ice, AST_RTP_ICE_ROLE_CONTROLLED, ast_rtp_instance_get_data(), and pj_thread_register_check().

1216 {
1217  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1218 
1219  if (!rtp->ice) {
1220  ast_debug_ice(3, "(%p) ICE set role failed; no ice instance\n", instance);
1221  return;
1222  }
1223 
1224  rtp->role = role;
1225 
1226  if (!rtp->ice->real_ice->is_nominating && !rtp->ice->real_ice->is_complete) {
1228  ast_debug_ice(2, "(%p) ICE set role to %s\n",
1229  instance, role == AST_RTP_ICE_ROLE_CONTROLLED ? "CONTROLLED" : "CONTROLLING");
1230  pj_ice_sess_change_role(rtp->ice->real_ice, role == AST_RTP_ICE_ROLE_CONTROLLED ?
1231  PJ_ICE_SESS_ROLE_CONTROLLED : PJ_ICE_SESS_ROLE_CONTROLLING);
1232  } else {
1233  ast_debug_ice(2, "(%p) ICE not setting role because state is %s\n",
1234  instance, rtp->ice->real_ice->is_nominating ? "nominating" : "complete");
1235  }
1236 }
RTP session description.
static void pj_thread_register_check(void)
Function used to check if the calling thread is registered with pjlib. If it is not it will be regist...
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ ast_rtp_ice_start()

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

Definition at line 1031 of file res_rtp_asterisk.c.

References ast_rtp_engine_ice_candidate::address, ao2_cleanup, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_debug_ice, ast_log, AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_suite_event_notify, ast_rtp_engine_ice_candidate::foundation, ice_candidates_compare(), ice_reset_session(), ast_rtp_engine_ice_candidate::id, LOG_NOTICE, LOG_WARNING, NULL, pj2ast_rtp_ice_role(), pj_thread_register_check(), ast_rtp_engine_ice_candidate::priority, ice_wrap::real_ice, ast_rtp_engine_ice_candidate::relay_address, STRICT_RTP_OPEN, timer_heap, and ast_rtp_engine_ice_candidate::type.

1032 {
1033  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1034  pj_str_t ufrag = pj_str(rtp->remote_ufrag), passwd = pj_str(rtp->remote_passwd);
1035  pj_ice_sess_cand candidates[PJ_ICE_MAX_CAND];
1036  struct ao2_iterator i;
1037  struct ast_rtp_engine_ice_candidate *candidate;
1038  int cand_cnt = 0, has_rtp = 0, has_rtcp = 0;
1039 
1040  if (!rtp->ice || !rtp->ice_proposed_remote_candidates) {
1041  return;
1042  }
1043 
1044  /* Check for equivalence in the lists */
1045  if (rtp->ice_active_remote_candidates &&
1046  !ice_candidates_compare(rtp->ice_proposed_remote_candidates, rtp->ice_active_remote_candidates)) {
1047  ast_debug_ice(2, "(%p) ICE proposed equals active candidates\n", instance);
1048  ao2_cleanup(rtp->ice_proposed_remote_candidates);
1049  rtp->ice_proposed_remote_candidates = NULL;
1050  /* If this ICE session is being preserved then go back to the role it currently is */
1051  pj2ast_rtp_ice_role(rtp->ice->real_ice->role, &rtp->role);
1052  return;
1053  }
1054 
1055  /* Out with the old, in with the new */
1056  ao2_cleanup(rtp->ice_active_remote_candidates);
1057  rtp->ice_active_remote_candidates = rtp->ice_proposed_remote_candidates;
1058  rtp->ice_proposed_remote_candidates = NULL;
1059 
1060  ast_debug_ice(2, "(%p) ICE start\n", instance);
1061 
1062  /* Reset the ICE session. Is this going to work? */
1063  if (ice_reset_session(instance)) {
1064  ast_log(LOG_NOTICE, "(%p) ICE failed to create replacement session\n", instance);
1065  return;
1066  }
1067 
1069 
1070  i = ao2_iterator_init(rtp->ice_active_remote_candidates, 0);
1071 
1072  while ((candidate = ao2_iterator_next(&i)) && (cand_cnt < PJ_ICE_MAX_CAND)) {
1073  pj_str_t address;
1074 
1075  /* there needs to be at least one rtp and rtcp candidate in the list */
1076  has_rtp |= candidate->id == AST_RTP_ICE_COMPONENT_RTP;
1077  has_rtcp |= candidate->id == AST_RTP_ICE_COMPONENT_RTCP;
1078 
1079  pj_strdup2(rtp->ice->real_ice->pool, &candidates[cand_cnt].foundation,
1080  candidate->foundation);
1081  candidates[cand_cnt].comp_id = candidate->id;
1082  candidates[cand_cnt].prio = candidate->priority;
1083 
1084  pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&address, ast_sockaddr_stringify(&candidate->address)), &candidates[cand_cnt].addr);
1085 
1086  if (!ast_sockaddr_isnull(&candidate->relay_address)) {
1087  pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&address, ast_sockaddr_stringify(&candidate->relay_address)), &candidates[cand_cnt].rel_addr);
1088  }
1089 
1090  if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
1091  candidates[cand_cnt].type = PJ_ICE_CAND_TYPE_HOST;
1092  } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
1093  candidates[cand_cnt].type = PJ_ICE_CAND_TYPE_SRFLX;
1094  } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_RELAYED) {
1095  candidates[cand_cnt].type = PJ_ICE_CAND_TYPE_RELAYED;
1096  }
1097 
1098  if (candidate->id == AST_RTP_ICE_COMPONENT_RTP && rtp->turn_rtp) {
1099  ast_debug_ice(2, "(%p) ICE RTP candidate %s\n", instance, ast_sockaddr_stringify(&candidate->address));
1100  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
1101  ao2_unlock(instance);
1102  pj_turn_sock_set_perm(rtp->turn_rtp, 1, &candidates[cand_cnt].addr, 1);
1103  ao2_lock(instance);
1104  } else if (candidate->id == AST_RTP_ICE_COMPONENT_RTCP && rtp->turn_rtcp) {
1105  ast_debug_ice(2, "(%p) ICE RTCP candidate %s\n", instance, ast_sockaddr_stringify(&candidate->address));
1106  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
1107  ao2_unlock(instance);
1108  pj_turn_sock_set_perm(rtp->turn_rtcp, 1, &candidates[cand_cnt].addr, 1);
1109  ao2_lock(instance);
1110  }
1111 
1112  cand_cnt++;
1113  ao2_ref(candidate, -1);
1114  }
1115 
1117 
1118  if (cand_cnt < ao2_container_count(rtp->ice_active_remote_candidates)) {
1119  ast_log(LOG_WARNING, "(%p) ICE lost %d candidates. Consider increasing PJ_ICE_MAX_CAND in PJSIP\n",
1120  instance, ao2_container_count(rtp->ice_active_remote_candidates) - cand_cnt);
1121  }
1122 
1123  if (!has_rtp) {
1124  ast_log(LOG_WARNING, "(%p) ICE no RTP candidates; skipping checklist\n", instance);
1125  }
1126 
1127  /* If we're only dealing with one ICE component, then we don't care about the lack of RTCP candidates */
1128  if (!has_rtcp && rtp->ice_num_components > 1) {
1129  ast_log(LOG_WARNING, "(%p) ICE no RTCP candidates; skipping checklist\n", instance);
1130  }
1131 
1132  if (rtp->ice && has_rtp && (has_rtcp || rtp->ice_num_components == 1)) {
1133  pj_status_t res;
1134  char reason[80];
1135  struct ice_wrap *ice;
1136 
1137  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
1138  ice = rtp->ice;
1139  ao2_ref(ice, +1);
1140  ao2_unlock(instance);
1141  res = pj_ice_sess_create_check_list(ice->real_ice, &ufrag, &passwd, cand_cnt, &candidates[0]);
1142  if (res == PJ_SUCCESS) {
1143  ast_debug_ice(2, "(%p) ICE successfully created checklist\n", instance);
1144  ast_test_suite_event_notify("ICECHECKLISTCREATE", "Result: SUCCESS");
1145  pj_ice_sess_start_check(ice->real_ice);
1146  pj_timer_heap_poll(timer_heap, NULL);
1147  ao2_ref(ice, -1);
1148  ao2_lock(instance);
1149  rtp->strict_rtp_state = STRICT_RTP_OPEN;
1150  return;
1151  }
1152  ao2_ref(ice, -1);
1153  ao2_lock(instance);
1154 
1155  pj_strerror(res, reason, sizeof(reason));
1156  ast_log(LOG_WARNING, "(%p) ICE failed to create session check list: %s\n", instance, reason);
1157  }
1158 
1159  ast_test_suite_event_notify("ICECHECKLISTCREATE", "Result: FAILURE");
1160 
1161  /* even though create check list failed don't stop ice as
1162  it might still work */
1163  /* however we do need to reset remote candidates since
1164  this function may be re-entered */
1165  ao2_ref(rtp->ice_active_remote_candidates, -1);
1166  rtp->ice_active_remote_candidates = NULL;
1167  if (rtp->ice) {
1168  rtp->ice->real_ice->rcand_cnt = rtp->ice->real_ice->clist.count = 0;
1169  }
1170 }
RTP session description.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char * address
Definition: f2c.h:59
#define LOG_WARNING
Definition: logger.h:274
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
Structure for an ICE candidate.
Definition: rtp_engine.h:474
static void pj_thread_register_check(void)
Function used to check if the calling thread is registered with pjlib. If it is not it will be regist...
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:481
#define ast_log
Definition: astobj2.c:42
static int ice_reset_session(struct ast_rtp_instance *instance)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_sockaddr relay_address
Definition: rtp_engine.h:480
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:476
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define LOG_NOTICE
Definition: logger.h:263
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
static int ice_candidates_compare(struct ao2_container *left, struct ao2_container *right)
static void pj2ast_rtp_ice_role(enum pj_ice_sess_role pj_role, enum ast_rtp_ice_role *ast_role)
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841