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
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_sockaddr address
Definition: rtp_engine.h:479
static pj_timer_heap_t * timer_heap
Global timer heap.
pj_ice_sess * real_ice
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ ast_rtp_ice_start_media()

static void ast_rtp_ice_start_media ( pj_ice_sess *  ice,
pj_status_t  status 
)
static

Definition at line 2581 of file res_rtp_asterisk.c.

References ao2_lock, ao2_unlock, ast_debug_category, AST_DEBUG_CATEGORY_DTLS, AST_DEBUG_CATEGORY_ICE, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), AST_RTP_INSTANCE_RTCP_STANDARD, ast_rtp_instance_set_prop(), ast_rtp_instance_set_remote_address, AST_RTP_PROPERTY_NAT, ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_verb, rtp_learning_start(), strictrtp, and update_address_with_ice_candidate().

Referenced by ast_rtp_on_ice_complete(), and ast_rtp_on_valid_pair().

2582 {
2583  struct ast_rtp_instance *instance = ice->user_data;
2584  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2585 
2586  ao2_lock(instance);
2587 
2588  if (status == PJ_SUCCESS) {
2589  struct ast_sockaddr remote_address;
2590 
2591  ast_sockaddr_setnull(&remote_address);
2593  if (!ast_sockaddr_isnull(&remote_address)) {
2594  /* Symmetric RTP must be disabled for the remote address to not get overwritten */
2596 
2597  ast_rtp_instance_set_remote_address(instance, &remote_address);
2598  }
2599 
2600  if (rtp->rtcp) {
2602  }
2603  }
2604 
2605 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
2606  /* If we've already started media, no need to do all of this again */
2607  if (rtp->ice_media_started) {
2608  ao2_unlock(instance);
2609  return;
2610  }
2611 
2613  "(%p) ICE starting media - perform DTLS - (%p)\n", instance, rtp);
2614 
2615  /*
2616  * Seemingly no reason to call dtls_perform_setup here. Currently we'll do a full
2617  * protocol level renegotiation if things do change. And if bundled is being used
2618  * then ICE is reused when a stream is added.
2619  *
2620  * Note, if for some reason in the future dtls_perform_setup does need to done here
2621  * be aware that creates a race condition between the call here (on ice completion)
2622  * and potential DTLS handshaking when receiving RTP. What happens is the ssl object
2623  * can get cleared (SSL_clear) during that handshaking process (DTLS init). If that
2624  * happens then Asterisk won't complete DTLS initialization. RTP packets are still
2625  * sent/received but won't be encrypted/decrypted.
2626  */
2627  dtls_perform_handshake(instance, &rtp->dtls, 0);
2628 
2629  if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
2630  dtls_perform_handshake(instance, &rtp->rtcp->dtls, 1);
2631  }
2632 #endif
2633 
2634  rtp->ice_media_started = 1;
2635 
2636  if (!strictrtp) {
2637  ao2_unlock(instance);
2638  return;
2639  }
2640 
2641  ast_verb(4, "%p -- Strict RTP learning after ICE completion\n", rtp);
2642  rtp_learning_start(rtp);
2643  ao2_unlock(instance);
2644 }
#define ast_debug_category(sublevel, ids,...)
Log for a debug category.
RTP session description.
static void rtp_learning_start(struct ast_rtp *rtp)
Start the strictrtp learning mode.
#define ao2_unlock(a)
Definition: astobj2.h:730
Socket address structure.
Definition: netsock2.h:97
#define ast_verb(level,...)
Definition: logger.h:463
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
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 ao2_lock(a)
Definition: astobj2.h:718
#define AST_DEBUG_CATEGORY_ICE
Definition: rtp_engine.h:2852
static int strictrtp
#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 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.
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_DEBUG_CATEGORY_DTLS
Definition: rtp_engine.h:2850
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:705
jack_status_t status
Definition: app_jack.c:146

◆ ast_rtp_ice_stop()

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

Definition at line 891 of file res_rtp_asterisk.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_debug_ice, ast_rtp_instance_get_data(), and NULL.

Referenced by ice_create(), and rtp_deallocate_transport().

892 {
893  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
894  struct ice_wrap *ice;
895 
896  ice = rtp->ice;
897  rtp->ice = NULL;
898  if (ice) {
899  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
900  ao2_unlock(instance);
901  ao2_ref(ice, -1);
902  ao2_lock(instance);
903  ast_debug_ice(2, "(%p) ICE stopped\n", instance);
904  }
905 }
RTP session description.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#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_turn_request()

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
Precondition
instance is locked

Definition at line 1577 of file res_rtp_asterisk.c.

References ao2_cleanup, ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, ast_assert, ast_cond_timedwait, ast_debug_ice, ast_log, ast_rtp_ice_add_cand(), AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), ast_rtp_turn_rtcp_sock_cb, ast_rtp_turn_rtp_sock_cb, ast_samp2tv(), ast_sockaddr_copy(), ast_sockaddr_is_ipv4(), ast_sockaddr_parse(), ast_sockaddr_port, ast_sockaddr_set_port, AST_TRANSPORT_TCP, AST_TRANSPORT_UDP, ast_tvadd(), ast_tvnow(), cachingpool, sip_to_pjsip::info(), LOG_WARNING, NULL, PARSE_PORT_FORBID, ice_wrap::real_ice, rtp_ioqueue_thread_get_or_create(), status, stun_software_attribute, TRANSPORT_TURN_RTCP, TRANSPORT_TURN_RTP, and TURN_STATE_WAIT_TIME.

Referenced by rtp_add_candidates_to_ice().

1579 {
1580  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1581  pj_turn_sock **turn_sock;
1582  const pj_turn_sock_cb *turn_cb;
1583  pj_turn_tp_type conn_type;
1584  int conn_transport;
1585  pj_stun_auth_cred cred = { 0, };
1586  pj_str_t turn_addr;
1587  struct ast_sockaddr addr = { { 0, } };
1588  pj_stun_config stun_config;
1589  struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
1590  struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
1591  pj_turn_session_info info;
1592  struct ast_sockaddr local, loop;
1593  pj_status_t status;
1594  pj_turn_sock_cfg turn_sock_cfg;
1595  struct ice_wrap *ice;
1596 
1597  ast_rtp_instance_get_local_address(instance, &local);
1598  if (ast_sockaddr_is_ipv4(&local)) {
1599  ast_sockaddr_parse(&loop, "127.0.0.1", PARSE_PORT_FORBID);
1600  } else {
1601  ast_sockaddr_parse(&loop, "::1", PARSE_PORT_FORBID);
1602  }
1603 
1604  /* Determine what component we are requesting a TURN session for */
1605  if (component == AST_RTP_ICE_COMPONENT_RTP) {
1606  turn_sock = &rtp->turn_rtp;
1607  turn_cb = &ast_rtp_turn_rtp_sock_cb;
1608  conn_transport = TRANSPORT_TURN_RTP;
1609  ast_sockaddr_set_port(&loop, ast_sockaddr_port(&local));
1610  } else if (component == AST_RTP_ICE_COMPONENT_RTCP) {
1611  turn_sock = &rtp->turn_rtcp;
1612  turn_cb = &ast_rtp_turn_rtcp_sock_cb;
1613  conn_transport = TRANSPORT_TURN_RTCP;
1614  ast_sockaddr_set_port(&loop, ast_sockaddr_port(&rtp->rtcp->us));
1615  } else {
1616  return;
1617  }
1618 
1619  if (transport == AST_TRANSPORT_UDP) {
1620  conn_type = PJ_TURN_TP_UDP;
1621  } else if (transport == AST_TRANSPORT_TCP) {
1622  conn_type = PJ_TURN_TP_TCP;
1623  } else {
1624  ast_assert(0);
1625  return;
1626  }
1627 
1628  ast_sockaddr_parse(&addr, server, PARSE_PORT_FORBID);
1629 
1630  if (*turn_sock) {
1631  rtp->turn_state = PJ_TURN_STATE_NULL;
1632 
1633  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
1634  ao2_unlock(instance);
1635  pj_turn_sock_destroy(*turn_sock);
1636  ao2_lock(instance);
1637  while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
1638  ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
1639  }
1640  }
1641 
1642  if (component == AST_RTP_ICE_COMPONENT_RTP && !rtp->ioqueue) {
1643  /*
1644  * We cannot hold the instance lock because we could wait
1645  * for the ioqueue thread to die and we might deadlock as
1646  * a result.
1647  */
1648  ao2_unlock(instance);
1649  rtp->ioqueue = rtp_ioqueue_thread_get_or_create();
1650  ao2_lock(instance);
1651  if (!rtp->ioqueue) {
1652  return;
1653  }
1654  }
1655 
1656  pj_stun_config_init(&stun_config, &cachingpool.factory, 0, rtp->ioqueue->ioqueue, rtp->ioqueue->timerheap);
1657  if (!stun_software_attribute) {
1658  stun_config.software_name = pj_str(NULL);
1659  }
1660 
1661  /* Use ICE session group lock for TURN session to avoid deadlock */
1662  pj_turn_sock_cfg_default(&turn_sock_cfg);
1663  ice = rtp->ice;
1664  if (ice) {
1665  turn_sock_cfg.grp_lock = ice->real_ice->grp_lock;
1666  ao2_ref(ice, +1);
1667  }
1668 
1669  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
1670  ao2_unlock(instance);
1671  status = pj_turn_sock_create(&stun_config,
1672  ast_sockaddr_is_ipv4(&addr) ? pj_AF_INET() : pj_AF_INET6(), conn_type,
1673  turn_cb, &turn_sock_cfg, instance, turn_sock);
1674  ao2_cleanup(ice);
1675  if (status != PJ_SUCCESS) {
1676  ast_log(LOG_WARNING, "(%p) Could not create a TURN client socket\n", instance);
1677  ao2_lock(instance);
1678  return;
1679  }
1680 
1681  cred.type = PJ_STUN_AUTH_CRED_STATIC;
1682  pj_strset2(&cred.data.static_cred.username, (char*)username);
1683  cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
1684  pj_strset2(&cred.data.static_cred.data, (char*)password);
1685 
1686  pj_turn_sock_alloc(*turn_sock, pj_cstr(&turn_addr, server), port, NULL, &cred, NULL);
1687 
1688  ast_debug_ice(2, "(%p) ICE request TURN %s %s candidate\n", instance,
1689  transport == AST_TRANSPORT_UDP ? "UDP" : "TCP",
1690  component == AST_RTP_ICE_COMPONENT_RTP ? "RTP" : "RTCP");
1691 
1692  ao2_lock(instance);
1693 
1694  /*
1695  * Because the TURN socket is asynchronous and we are synchronous we need to
1696  * wait until it is done
1697  */
1698  while (rtp->turn_state < PJ_TURN_STATE_READY) {
1699  ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
1700  }
1701 
1702  /* If a TURN session was allocated add it as a candidate */
1703  if (rtp->turn_state != PJ_TURN_STATE_READY) {
1704  return;
1705  }
1706 
1707  pj_turn_sock_get_info(*turn_sock, &info);
1708 
1709  ast_rtp_ice_add_cand(instance, rtp, component, conn_transport,
1710  PJ_ICE_CAND_TYPE_RELAYED, 65535, &info.relay_addr, &info.relay_addr,
1711  &info.mapped_addr, pj_sockaddr_get_len(&info.relay_addr));
1712 
1713  if (component == AST_RTP_ICE_COMPONENT_RTP) {
1714  ast_sockaddr_copy(&rtp->rtp_loop, &loop);
1715  } else if (component == AST_RTP_ICE_COMPONENT_RTCP) {
1716  ast_sockaddr_copy(&rtp->rtcp_loop, &loop);
1717  }
1718 }
RTP session description.
static pj_turn_sock_cb ast_rtp_turn_rtcp_sock_cb
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
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
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static pj_turn_sock_cb ast_rtp_turn_rtp_sock_cb
static int stun_software_attribute
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
#define TRANSPORT_TURN_RTP
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
static struct ast_str * password
Definition: cdr_mysql.c:77
#define TRANSPORT_TURN_RTCP
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
#define TURN_STATE_WAIT_TIME
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)
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
def info(msg)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
#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
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:643
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
static struct ast_rtp_ioqueue_thread * rtp_ioqueue_thread_get_or_create(void)
Finder and allocator for an ioqueue thread.
pj_ice_sess * real_ice
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
jack_status_t status
Definition: app_jack.c:146

◆ ast_rtp_interpret()

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

Definition at line 7200 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

7203 {
7204  unsigned int *rtpheader = (unsigned int*)(read_area);
7205  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7206  struct ast_rtp_instance *instance1;
7207  int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc;
7208  unsigned int timestamp;
7209  RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup);
7210  struct frame_list frames;
7211 
7212  /* If this payload is encrypted then decrypt it using the given SRTP instance */
7213  if ((*read_area & 0xC0) && res_srtp && srtp && res_srtp->unprotect(
7214  srtp, read_area, &res, 0 | (srtp_replay_protection << 1)) < 0) {
7215  return &ast_null_frame;
7216  }
7217 
7218  /* If we are currently sending DTMF to the remote party send a continuation packet */
7219  if (rtp->sending_digit) {
7220  ast_rtp_dtmf_continuation(instance);
7221  }
7222 
7223  /* Pull out the various other fields we will need */
7224  ssrc = ntohl(rtpheader[2]);
7225  seqno = ntohl(rtpheader[0]);
7226  payloadtype = (seqno & 0x7f0000) >> 16;
7227  padding = seqno & (1 << 29);
7228  mark = seqno & (1 << 23);
7229  ext = seqno & (1 << 28);
7230  cc = (seqno & 0xF000000) >> 24;
7231  seqno &= 0xffff;
7232  timestamp = ntohl(rtpheader[1]);
7233 
7235 
7236  /* Remove any padding bytes that may be present */
7237  if (padding) {
7238  res -= read_area[res - 1];
7239  }
7240 
7241  /* Skip over any CSRC fields */
7242  if (cc) {
7243  hdrlen += cc * 4;
7244  }
7245 
7246  /* Look for any RTP extensions, currently we do not support any */
7247  if (ext) {
7248  int extensions_size = (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
7249  unsigned int profile;
7250  profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
7251 
7252  if (profile == 0xbede) {
7253  /* We skip over the first 4 bytes as they are just for the one byte extension header */
7254  rtp_instance_parse_extmap_extensions(instance, rtp, read_area + hdrlen + 4, extensions_size);
7255  } else if (DEBUG_ATLEAST(1)) {
7256  if (profile == 0x505a) {
7257  ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
7258  } else {
7259  /* SDP negotiated RTP extensions can not currently be output in logging */
7260  ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
7261  }
7262  }
7263 
7264  hdrlen += extensions_size;
7265  hdrlen += 4;
7266  }
7267 
7268  /* Make sure after we potentially mucked with the header length that it is once again valid */
7269  if (res < hdrlen) {
7270  ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
7272  }
7273 
7274  /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */
7275  if (!bundled) {
7276  /* Force a marker bit and change SSRC if the SSRC changes */
7277  if (rtp->themssrc_valid && rtp->themssrc != ssrc) {
7278  struct ast_frame *f, srcupdate = {
7280  .subclass.integer = AST_CONTROL_SRCCHANGE,
7281  };
7282 
7283  if (!mark) {
7285  ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance);
7286  }
7287  mark = 1;
7288  }
7289 
7290  f = ast_frisolate(&srcupdate);
7292 
7293  rtp->seedrxseqno = 0;
7294  rtp->rxcount = 0;
7295  rtp->rxoctetcount = 0;
7296  rtp->cycles = 0;
7297  prev_seqno = 0;
7298  rtp->last_seqno = 0;
7299  rtp->last_end_timestamp.ts = 0;
7300  rtp->last_end_timestamp.is_set = 0;
7301  if (rtp->rtcp) {
7302  rtp->rtcp->expected_prior = 0;
7303  rtp->rtcp->received_prior = 0;
7304  }
7305  }
7306 
7307  rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */
7308  rtp->themssrc_valid = 1;
7309  }
7310 
7311  rtp->rxcount++;
7312  rtp->rxoctetcount += (res - hdrlen);
7313  if (rtp->rxcount == 1) {
7314  rtp->seedrxseqno = seqno;
7315  }
7316 
7317  /* Do not schedule RR if RTCP isn't run */
7318  if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 0) {
7319  /* Schedule transmission of Receiver Report */
7320  ao2_ref(instance, +1);
7321  rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
7322  if (rtp->rtcp->schedid < 0) {
7323  ao2_ref(instance, -1);
7324  ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
7325  }
7326  }
7327  if ((int)prev_seqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
7328  rtp->cycles += RTP_SEQ_MOD;
7329 
7330  /* If we are directly bridged to another instance send the audio directly out,
7331  * but only after updating core information about the received traffic so that
7332  * outgoing RTCP reflects it.
7333  */
7334  instance1 = ast_rtp_instance_get_bridged(instance);
7335  if (instance1
7336  && !bridge_p2p_rtp_write(instance, instance1, rtpheader, res, hdrlen)) {
7337  struct timeval rxtime;
7338  struct ast_frame *f;
7339 
7340  /* Update statistics for jitter so they are correct in RTCP */
7341  calc_rxstamp(&rxtime, rtp, timestamp, mark);
7342 
7343  /* When doing P2P we don't need to raise any frames about SSRC change to the core */
7344  while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list)) != NULL) {
7345  ast_frfree(f);
7346  }
7347 
7348  return &ast_null_frame;
7349  }
7350 
7351  payload = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payloadtype);
7352  if (!payload) {
7353  /* Unknown payload type. */
7355  }
7356 
7357  /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
7358  if (!payload->asterisk_format) {
7359  struct ast_frame *f = NULL;
7360  if (payload->rtp_code == AST_RTP_DTMF) {
7361  /* process_dtmf_rfc2833 may need to return multiple frames. We do this
7362  * by passing the pointer to the frame list to it so that the method
7363  * can append frames to the list as needed.
7364  */
7365  process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames);
7366  } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) {
7367  f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
7368  } else if (payload->rtp_code == AST_RTP_CN) {
7369  f = process_cn_rfc3389(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark);
7370  } else {
7371  ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
7372  payloadtype,
7373  ast_sockaddr_stringify(remote_address));
7374  }
7375 
7376  if (f) {
7378  }
7379  /* Even if no frame was returned by one of the above methods,
7380  * we may have a frame to return in our frame list
7381  */
7383  }
7384 
7385  ao2_replace(rtp->lastrxformat, payload->format);
7386  ao2_replace(rtp->f.subclass.format, payload->format);
7387  switch (ast_format_get_type(rtp->f.subclass.format)) {
7388  case AST_MEDIA_TYPE_AUDIO:
7389  rtp->f.frametype = AST_FRAME_VOICE;
7390  break;
7391  case AST_MEDIA_TYPE_VIDEO:
7392  rtp->f.frametype = AST_FRAME_VIDEO;
7393  break;
7394  case AST_MEDIA_TYPE_TEXT:
7395  rtp->f.frametype = AST_FRAME_TEXT;
7396  break;
7397  case AST_MEDIA_TYPE_IMAGE:
7398  /* Fall through */
7399  default:
7400  ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
7402  return &ast_null_frame;
7403  }
7404 
7405  if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
7406  rtp->dtmf_timeout = 0;
7407 
7408  if (rtp->resp) {
7409  struct ast_frame *f;
7410  f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
7411  f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, ast_rtp_get_rate(f->subclass.format)), ast_tv(0, 0));
7412  rtp->resp = 0;
7413  rtp->dtmf_timeout = rtp->dtmf_duration = 0;
7415  return AST_LIST_FIRST(&frames);
7416  }
7417  }
7418 
7419  rtp->f.src = "RTP";
7420  rtp->f.mallocd = 0;
7421  rtp->f.datalen = res - hdrlen;
7422  rtp->f.data.ptr = read_area + hdrlen;
7423  rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
7425  rtp->f.seqno = seqno;
7426  rtp->f.stream_num = rtp->stream_num;
7427 
7429  && ((int)seqno - (prev_seqno + 1) > 0)
7430  && ((int)seqno - (prev_seqno + 1) < 10)) {
7431  unsigned char *data = rtp->f.data.ptr;
7432 
7433  memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
7434  rtp->f.datalen +=3;
7435  *data++ = 0xEF;
7436  *data++ = 0xBF;
7437  *data = 0xBD;
7438  }
7439 
7441  unsigned char *data = rtp->f.data.ptr;
7442  unsigned char *header_end;
7443  int num_generations;
7444  int header_length;
7445  int len;
7446  int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
7447  int x;
7448 
7450  header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
7451  if (header_end == NULL) {
7453  }
7454  header_end++;
7455 
7456  header_length = header_end - data;
7457  num_generations = header_length / 4;
7458  len = header_length;
7459 
7460  if (!diff) {
7461  for (x = 0; x < num_generations; x++)
7462  len += data[x * 4 + 3];
7463 
7464  if (!(rtp->f.datalen - len))
7466 
7467  rtp->f.data.ptr += len;
7468  rtp->f.datalen -= len;
7469  } else if (diff > num_generations && diff < 10) {
7470  len -= 3;
7471  rtp->f.data.ptr += len;
7472  rtp->f.datalen -= len;
7473 
7474  data = rtp->f.data.ptr;
7475  *data++ = 0xEF;
7476  *data++ = 0xBF;
7477  *data = 0xBD;
7478  } else {
7479  for ( x = 0; x < num_generations - diff; x++)
7480  len += data[x * 4 + 3];
7481 
7482  rtp->f.data.ptr += len;
7483  rtp->f.datalen -= len;
7484  }
7485  }
7486 
7488  rtp->f.samples = ast_codec_samples_count(&rtp->f);
7490  ast_frame_byteswap_be(&rtp->f);
7491  }
7492  calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
7493  /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
7495  rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
7496  rtp->f.len = rtp->f.samples / ((ast_format_get_sample_rate(rtp->f.subclass.format) / 1000));
7498  /* Video -- samples is # of samples vs. 90000 */
7499  if (!rtp->lastividtimestamp)
7500  rtp->lastividtimestamp = timestamp;
7501  calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
7503  rtp->f.ts = timestamp / (ast_rtp_get_rate(rtp->f.subclass.format) / 1000);
7504  rtp->f.samples = timestamp - rtp->lastividtimestamp;
7505  rtp->lastividtimestamp = timestamp;
7506  rtp->f.delivery.tv_sec = 0;
7507  rtp->f.delivery.tv_usec = 0;
7508  /* Pass the RTP marker bit as bit */
7509  rtp->f.subclass.frame_ending = mark ? 1 : 0;
7511  /* TEXT -- samples is # of samples vs. 1000 */
7512  if (!rtp->lastitexttimestamp)
7513  rtp->lastitexttimestamp = timestamp;
7514  rtp->f.samples = timestamp - rtp->lastitexttimestamp;
7515  rtp->lastitexttimestamp = timestamp;
7516  rtp->f.delivery.tv_sec = 0;
7517  rtp->f.delivery.tv_usec = 0;
7518  } else {
7519  ast_log(LOG_WARNING, "Unknown or unsupported media type: %s\n",
7521  return &ast_null_frame;
7522  }
7523 
7525  return AST_LIST_FIRST(&frames);
7526 }
RTP session description.
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
struct ast_rtp_payload_type * ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
Retrieve rx payload mapped information by payload type.
Definition: rtp_engine.c:1479
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
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)
struct ast_format * ast_format_t140_red
Built-in cached t140 red format.
Definition: format_cache.c:241
static void rtp_instance_parse_extmap_extensions(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *extension, int len)
static int ast_rtcp_write(const void *data)
Write a RTCP packet to the far end.
#define ast_set_flag(p, flag)
Definition: utils.h:70
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
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
static struct ast_frame * create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
const char * ext
Definition: http.c:147
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
#define RTP_SEQ_MOD
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_srtp_res * res_srtp
Definition: rtp_engine.c:177
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
#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 frames
Definition: parser.c:51
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Definition: codec.c:378
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
unsigned int themssrc_valid
static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
Definition: format_cache.c:542
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
unsigned int themssrc
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
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 LOG_NOTICE
Definition: logger.h:263
#define AST_RTP_CISCO_DTMF
Definition: rtp_engine.h:270
static struct ast_frame * process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)
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(* unprotect)(struct ast_srtp *srtp, void *buf, int *size, int rtcp)
Definition: res_srtp.h:48
static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
struct ast_frame f
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
struct timeval delivery
struct ast_frame ast_null_frame
Definition: main/frame.c:79
static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, struct ast_rtp_instance *instance1, unsigned int *rtpheader, int len, int hdrlen)
unsigned int lastividtimestamp
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
struct ast_rtp_instance * ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
Get the other RTP instance that an instance is bridged to.
Definition: rtp_engine.c:2234
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
#define ast_frfree(fr)
static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
Data structure associated with a single frame of data.
#define ast_frame_byteswap_be(fr)
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format
#define AST_RTP_CN
Definition: rtp_engine.h:268
#define AST_RTP_DTMF
Definition: rtp_engine.h:266
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
struct ast_format * ast_format_t140
Built-in cached t140 format.
Definition: format_cache.c:236
unsigned int lastitexttimestamp
static struct ast_frame * process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark)

◆ ast_rtp_local_bridge()

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

Definition at line 8643 of file res_rtp_asterisk.c.

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

8644 {
8645  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
8646 
8647  ao2_lock(instance0);
8649  if (rtp->smoother) {
8650  ast_smoother_free(rtp->smoother);
8651  rtp->smoother = NULL;
8652  }
8653 
8654  /* We must use a new SSRC when local bridge ends */
8655  if (!instance1) {
8656  rtp->ssrc = rtp->ssrc_orig;
8657  rtp->ssrc_orig = 0;
8658  rtp->ssrc_saved = 0;
8659  } else if (!rtp->ssrc_saved) {
8660  /* In case ast_rtp_local_bridge is called multiple times, only save the ssrc from before local bridge began */
8661  rtp->ssrc_orig = rtp->ssrc;
8662  rtp->ssrc_saved = 1;
8663  }
8664 
8665  ao2_unlock(instance0);
8666 
8667  return 0;
8668 }
RTP session description.
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
unsigned int ssrc
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
#define ao2_lock(a)
Definition: astobj2.h:718
#define FLAG_NEED_MARKER_BIT
unsigned char ssrc_saved
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 FLAG_REQ_LOCAL_BRIDGE_BIT
unsigned int ssrc_orig

◆ ast_rtp_new()

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

Definition at line 3992 of file res_rtp_asterisk.c.

References ao2_bump, ast_calloc, ast_format_none, ast_random(), ast_rtp_instance_set_data(), ast_sockaddr_copy(), ast_uuid_generate_str(), AST_VECTOR_INIT, ast_rtp::cname, ast_rtp::expectedrxseqno, ast_rtp::f, ast_frame_subclass::format, NULL, rtp_allocate_transport(), sched, ast_rtp::ssrc, and ast_frame::subclass.

3995 {
3996  struct ast_rtp *rtp = NULL;
3997 
3998  /* Create a new RTP structure to hold all of our data */
3999  if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
4000  return -1;
4001  }
4002 
4003  /* Set default parameters on the newly created RTP structure */
4004  rtp->ssrc = ast_random();
4005  ast_uuid_generate_str(rtp->cname, sizeof(rtp->cname));
4006  rtp->seqno = ast_random() & 0x7fff;
4007  rtp->expectedrxseqno = -1;
4008  rtp->expectedseqno = -1;
4009  rtp->sched = sched;
4010  ast_sockaddr_copy(&rtp->bind_address, addr);
4011 
4012  /* Transport creation operations can grab the RTP data from the instance, so set it */
4013  ast_rtp_instance_set_data(instance, rtp);
4014 
4015  if (rtp_allocate_transport(instance, rtp)) {
4016  return -1;
4017  }
4018 
4019  if (AST_VECTOR_INIT(&rtp->ssrc_mapping, 1)) {
4020  return -1;
4021  }
4022 
4023  if (AST_VECTOR_INIT(&rtp->transport_wide_cc.packet_statistics, 0)) {
4024  return -1;
4025  }
4026  rtp->transport_wide_cc.schedid = -1;
4027 
4029  rtp->lastrxformat = ao2_bump(ast_format_none);
4030  rtp->lasttxformat = ao2_bump(ast_format_none);
4031  rtp->stream_num = -1;
4032 
4033  return 0;
4034 }
RTP session description.
static struct ast_sched_context * sched
Definition: chan_ooh323.c:400
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
static int rtp_allocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
#define NULL
Definition: resample.c:96
struct ast_format * ast_format_none
Built-in "null" format.
Definition: format_cache.c:251
struct ast_frame_subclass subclass
#define ao2_bump(obj)
Definition: astobj2.h:491
unsigned int ssrc
char cname[AST_UUID_STR_LEN]
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition: rtp_engine.c:558
long int ast_random(void)
Definition: main/utils.c:2064
int expectedrxseqno
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:143
struct ast_frame f
struct ast_format * format

◆ ast_rtp_on_ice_complete()

static void ast_rtp_on_ice_complete ( pj_ice_sess *  ice,
pj_status_t  status 
)
static

Definition at line 2656 of file res_rtp_asterisk.c.

References ast_debug_ice, and ast_rtp_ice_start_media().

2657 {
2658  ast_debug_ice(2, "(%p) ICE complete, start media\n", ice->user_data);
2660 }
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
static void ast_rtp_ice_start_media(pj_ice_sess *ice, pj_status_t status)
jack_status_t status
Definition: app_jack.c:146

◆ ast_rtp_on_ice_rx_data()

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

Definition at line 2663 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), TRANSPORT_SOCKET_RTCP, TRANSPORT_SOCKET_RTP, TRANSPORT_TURN_RTCP, and TRANSPORT_TURN_RTP.

2664 {
2665  struct ast_rtp_instance *instance = ice->user_data;
2666  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2667 
2668  /* Instead of handling the packet here (which really doesn't work with our architecture) we set a bit to indicate that it should be handled after pj_ice_sess_on_rx_pkt
2669  * returns */
2670  if (transport_id == TRANSPORT_SOCKET_RTP || transport_id == TRANSPORT_SOCKET_RTCP) {
2671  rtp->passthrough = 1;
2672  } else if (transport_id == TRANSPORT_TURN_RTP) {
2673  rtp->rtp_passthrough = 1;
2674  } else if (transport_id == TRANSPORT_TURN_RTCP) {
2675  rtp->rtcp_passthrough = 1;
2676  }
2677 }
RTP session description.
#define TRANSPORT_TURN_RTP
#define TRANSPORT_TURN_RTCP
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 TRANSPORT_SOCKET_RTCP
#define TRANSPORT_SOCKET_RTP

◆ ast_rtp_on_ice_tx_pkt()

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

Definition at line 2680 of file res_rtp_asterisk.c.

References ast_assert, ast_rtp_instance_get_data(), ast_rtp::s, status, TRANSPORT_SOCKET_RTCP, TRANSPORT_SOCKET_RTP, TRANSPORT_TURN_RTCP, and TRANSPORT_TURN_RTP.

2681 {
2682  struct ast_rtp_instance *instance = ice->user_data;
2683  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2684  pj_status_t status = PJ_EINVALIDOP;
2685  pj_ssize_t _size = (pj_ssize_t)size;
2686 
2687  if (transport_id == TRANSPORT_SOCKET_RTP) {
2688  /* Traffic is destined to go right out the RTP socket we already have */
2689  status = pj_sock_sendto(rtp->s, pkt, &_size, 0, dst_addr, dst_addr_len);
2690  /* sendto on a connectionless socket should send all the data, or none at all */
2691  ast_assert(_size == size || status != PJ_SUCCESS);
2692  } else if (transport_id == TRANSPORT_SOCKET_RTCP) {
2693  /* Traffic is destined to go right out the RTCP socket we already have */
2694  if (rtp->rtcp) {
2695  status = pj_sock_sendto(rtp->rtcp->s, pkt, &_size, 0, dst_addr, dst_addr_len);
2696  /* sendto on a connectionless socket should send all the data, or none at all */
2697  ast_assert(_size == size || status != PJ_SUCCESS);
2698  } else {
2699  status = PJ_SUCCESS;
2700  }
2701  } else if (transport_id == TRANSPORT_TURN_RTP) {
2702  /* Traffic is going through the RTP TURN relay */
2703  if (rtp->turn_rtp) {
2704  status = pj_turn_sock_sendto(rtp->turn_rtp, pkt, size, dst_addr, dst_addr_len);
2705  }
2706  } else if (transport_id == TRANSPORT_TURN_RTCP) {
2707  /* Traffic is going through the RTCP TURN relay */
2708  if (rtp->turn_rtcp) {
2709  status = pj_turn_sock_sendto(rtp->turn_rtcp, pkt, size, dst_addr, dst_addr_len);
2710  }
2711  }
2712 
2713  return status;
2714 }
RTP session description.
#define ast_assert(a)
Definition: utils.h:695
#define TRANSPORT_TURN_RTP
#define TRANSPORT_TURN_RTCP
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 TRANSPORT_SOCKET_RTCP
jack_status_t status
Definition: app_jack.c:146
#define TRANSPORT_SOCKET_RTP

◆ ast_rtp_on_turn_rtcp_state()

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

Definition at line 1421 of file res_rtp_asterisk.c.

References ao2_lock, ao2_unlock, ast_cond_signal, ast_rtp_instance_get_data(), and NULL.

1422 {
1423  struct ast_rtp_instance *instance = pj_turn_sock_get_user_data(turn_sock);
1424  struct ast_rtp *rtp;
1425 
1426  /* If this is a leftover from an already destroyed RTP instance just ignore the state change */
1427  if (!instance) {
1428  return;
1429  }
1430 
1431  rtp = ast_rtp_instance_get_data(instance);
1432 
1433  ao2_lock(instance);
1434 
1435  /* We store the new state so the other thread can actually handle it */
1436  rtp->turn_state = new_state;
1437  ast_cond_signal(&rtp->cond);
1438 
1439  if (new_state == PJ_TURN_STATE_DESTROYING) {
1440  pj_turn_sock_set_user_data(rtp->turn_rtcp, NULL);
1441  rtp->turn_rtcp = NULL;
1442  }
1443 
1444  ao2_unlock(instance);
1445 }
RTP session description.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
#define ao2_lock(a)
Definition: astobj2.h:718
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_on_turn_rtp_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

Definition at line 1355 of file res_rtp_asterisk.c.

References ao2_lock, ao2_unlock, ast_cond_signal, ast_rtp_instance_get_data(), and NULL.

1356 {
1357  struct ast_rtp_instance *instance = pj_turn_sock_get_user_data(turn_sock);
1358  struct ast_rtp *rtp;
1359 
1360  /* If this is a leftover from an already notified RTP instance just ignore the state change */
1361  if (!instance) {
1362  return;
1363  }
1364 
1365  rtp = ast_rtp_instance_get_data(instance);
1366 
1367  ao2_lock(instance);
1368 
1369  /* We store the new state so the other thread can actually handle it */
1370  rtp->turn_state = new_state;
1371  ast_cond_signal(&rtp->cond);
1372 
1373  if (new_state == PJ_TURN_STATE_DESTROYING) {
1374  pj_turn_sock_set_user_data(rtp->turn_rtp, NULL);
1375  rtp->turn_rtp = NULL;
1376  }
1377 
1378  ao2_unlock(instance);
1379 }
RTP session description.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
#define ao2_lock(a)
Definition: astobj2.h:718
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_on_turn_rx_rtcp_data()

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

Definition at line 1388 of file res_rtp_asterisk.c.

References ao2_bump, ao2_lock, ao2_ref, ao2_unlock, ast_log, AST_RTP_ICE_COMPONENT_RTCP, ast_rtp_instance_get_data(), ast_sendto(), LOG_WARNING, ice_wrap::real_ice, ast_rtp::s, status, and TRANSPORT_TURN_RTCP.

1389 {
1390  struct ast_rtp_instance *instance = pj_turn_sock_get_user_data(turn_sock);
1391  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1392  struct ice_wrap *ice;
1393  pj_status_t status;
1394 
1395  ao2_lock(instance);
1396  ice = ao2_bump(rtp->ice);
1397  ao2_unlock(instance);
1398 
1399  if (ice) {
1400  status = pj_ice_sess_on_rx_pkt(ice->real_ice, AST_RTP_ICE_COMPONENT_RTCP,
1401  TRANSPORT_TURN_RTCP, pkt, pkt_len, peer_addr, addr_len);
1402  ao2_ref(ice, -1);
1403  if (status != PJ_SUCCESS) {
1404  char buf[100];
1405 
1406  pj_strerror(status, buf, sizeof(buf));
1407  ast_log(LOG_WARNING, "PJ ICE Rx error status code: %d '%s'.\n",
1408  (int)status, buf);
1409  return;
1410  }
1411  if (!rtp->rtcp_passthrough) {
1412  return;
1413  }
1414  rtp->rtcp_passthrough = 0;
1415  }
1416 
1417  ast_sendto(rtp->rtcp->s, pkt, pkt_len, 0, &rtp->rtcp_loop);
1418 }
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
#define LOG_WARNING
Definition: logger.h:274
#define ao2_unlock(a)
Definition: astobj2.h:730
#define TRANSPORT_TURN_RTCP
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
pj_ice_sess * real_ice
jack_status_t status
Definition: app_jack.c:146

◆ ast_rtp_on_turn_rx_rtp_data()

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

Definition at line 1322 of file res_rtp_asterisk.c.

References ao2_bump, ao2_lock, ao2_ref, ao2_unlock, ast_log, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_instance_get_data(), ast_sendto(), LOG_WARNING, ice_wrap::real_ice, ast_rtp::s, status, and TRANSPORT_TURN_RTP.

1323 {
1324  struct ast_rtp_instance *instance = pj_turn_sock_get_user_data(turn_sock);
1325  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
1326  struct ice_wrap *ice;
1327  pj_status_t status;
1328 
1329  ao2_lock(instance);
1330  ice = ao2_bump(rtp->ice);
1331  ao2_unlock(instance);
1332 
1333  if (ice) {
1334  status = pj_ice_sess_on_rx_pkt(ice->real_ice, AST_RTP_ICE_COMPONENT_RTP,
1335  TRANSPORT_TURN_RTP, pkt, pkt_len, peer_addr, addr_len);
1336  ao2_ref(ice, -1);
1337  if (status != PJ_SUCCESS) {
1338  char buf[100];
1339 
1340  pj_strerror(status, buf, sizeof(buf));
1341  ast_log(LOG_WARNING, "(%p) ICE PJ Rx error status code: %d '%s'.\n",
1342  instance, (int)status, buf);
1343  return;
1344  }
1345  if (!rtp->rtp_passthrough) {
1346  return;
1347  }
1348  rtp->rtp_passthrough = 0;
1349  }
1350 
1351  ast_sendto(rtp->s, pkt, pkt_len, 0, &rtp->rtp_loop);
1352 }
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
#define LOG_WARNING
Definition: logger.h:274
#define ao2_unlock(a)
Definition: astobj2.h:730
#define TRANSPORT_TURN_RTP
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
pj_ice_sess * real_ice
jack_status_t status
Definition: app_jack.c:146

◆ ast_rtp_on_valid_pair()

static void ast_rtp_on_valid_pair ( pj_ice_sess *  ice)
static

Definition at line 2648 of file res_rtp_asterisk.c.

References ast_debug_ice, and ast_rtp_ice_start_media().

2649 {
2650  ast_debug_ice(2, "(%p) ICE valid pair, start media\n", ice->user_data);
2651  ast_rtp_ice_start_media(ice, PJ_SUCCESS);
2652 }
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
static void ast_rtp_ice_start_media(pj_ice_sess *ice, pj_status_t status)

◆ ast_rtp_prop_set()

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

Definition at line 8303 of file res_rtp_asterisk.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_bind(), ast_calloc, ast_data_buffer_alloc(), ast_data_buffer_free(), ast_debug_rtcp, ast_find_ourip(), ast_free, ast_free_ptr(), AST_RTP_ICE_COMPONENT_RTCP, ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, AST_RTP_INSTANCE_RTCP_STANDARD, AST_RTP_PROPERTY_ASYMMETRIC_CODEC, AST_RTP_PROPERTY_RETRANS_RECV, AST_RTP_PROPERTY_RETRANS_SEND, AST_RTP_PROPERTY_RTCP, ast_sched_del(), ast_sockaddr_copy(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdup, AST_VECTOR_FREE, AST_VECTOR_INIT, create_new_socket(), DEFAULT_RTP_RECV_BUFFER_SIZE, DEFAULT_RTP_SEND_BUFFER_SIZE, NULL, rtp_add_candidates_to_ice(), ast_rtp::s, TRANSPORT_SOCKET_RTCP, and value.

8304 {
8305  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8306 
8307  if (property == AST_RTP_PROPERTY_RTCP) {
8308  if (value) {
8309  struct ast_sockaddr local_addr;
8310 
8311  if (rtp->rtcp && rtp->rtcp->type == value) {
8312  ast_debug_rtcp(1, "(%p) RTCP ignoring duplicate property\n", instance);
8313  return;
8314  }
8315 
8316  if (!rtp->rtcp) {
8317  rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp));
8318  if (!rtp->rtcp) {
8319  return;
8320  }
8321  rtp->rtcp->s = -1;
8322 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8323  rtp->rtcp->dtls.timeout_timer = -1;
8324 #endif
8325  rtp->rtcp->schedid = -1;
8326  }
8327 
8328  rtp->rtcp->type = value;
8329 
8330  /* Grab the IP address and port we are going to use */
8331  ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
8333  ast_sockaddr_set_port(&rtp->rtcp->us,
8334  ast_sockaddr_port(&rtp->rtcp->us) + 1);
8335  }
8336 
8337  ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
8338  if (!ast_find_ourip(&local_addr, &rtp->rtcp->us, 0)) {
8339  ast_sockaddr_set_port(&local_addr, ast_sockaddr_port(&rtp->rtcp->us));
8340  } else {
8341  /* Failed to get local address reset to use default. */
8342  ast_sockaddr_copy(&local_addr, &rtp->rtcp->us);
8343  }
8344 
8345  ast_free(rtp->rtcp->local_addr_str);
8346  rtp->rtcp->local_addr_str = ast_strdup(ast_sockaddr_stringify(&local_addr));
8347  if (!rtp->rtcp->local_addr_str) {
8348  ast_free(rtp->rtcp);
8349  rtp->rtcp = NULL;
8350  return;
8351  }
8352 
8354  /* We're either setting up RTCP from scratch or
8355  * switching from MUX. Either way, we won't have
8356  * a socket set up, and we need to set it up
8357  */
8358  if ((rtp->rtcp->s =
8359  create_new_socket("RTCP",
8360  ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
8361  AF_INET :
8362  ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
8363  AF_INET6 : -1)) < 0) {
8364  ast_debug_rtcp(1, "(%p) RTCP failed to create a new socket\n", instance);
8365  ast_free(rtp->rtcp->local_addr_str);
8366  ast_free(rtp->rtcp);
8367  rtp->rtcp = NULL;
8368  return;
8369  }
8370 
8371  /* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
8372  if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
8373  ast_debug_rtcp(1, "(%p) RTCP failed to setup RTP instance\n", instance);
8374  close(rtp->rtcp->s);
8375  ast_free(rtp->rtcp->local_addr_str);
8376  ast_free(rtp->rtcp);
8377  rtp->rtcp = NULL;
8378  return;
8379  }
8380 #ifdef HAVE_PJPROJECT
8381  if (rtp->ice) {
8382  rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us, ast_sockaddr_port(&rtp->rtcp->us), AST_RTP_ICE_COMPONENT_RTCP, TRANSPORT_SOCKET_RTCP);
8383  }
8384 #endif
8385 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8386  dtls_setup_rtcp(instance);
8387 #endif
8388  } else {
8389  struct ast_sockaddr addr;
8390  /* RTCPMUX uses the same socket as RTP. If we were previously using standard RTCP
8391  * then close the socket we previously created.
8392  *
8393  * It may seem as though there is a possible race condition here where we might try
8394  * to close the RTCP socket while it is being used to send data. However, this is not
8395  * a problem in practice since setting and adjusting of RTCP properties happens prior
8396  * to activating RTP. It is not until RTP is activated that timers start for RTCP
8397  * transmission
8398  */
8399  if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
8400  close(rtp->rtcp->s);
8401  }
8402  rtp->rtcp->s = rtp->s;
8403  ast_rtp_instance_get_remote_address(instance, &addr);
8404  ast_sockaddr_copy(&rtp->rtcp->them, &addr);
8405 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8406  if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
8407  SSL_free(rtp->rtcp->dtls.ssl);
8408  }
8409  rtp->rtcp->dtls.ssl = rtp->dtls.ssl;
8410 #endif
8411  }
8412 
8413  ast_debug_rtcp(1, "(%p) RTCP setup on RTP instance\n", instance);
8414  } else {
8415  if (rtp->rtcp) {
8416  if (rtp->rtcp->schedid > -1) {
8417  ao2_unlock(instance);
8418  if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
8419  /* Successfully cancelled scheduler entry. */
8420  ao2_ref(instance, -1);
8421  } else {
8422  /* Unable to cancel scheduler entry */
8423  ast_debug_rtcp(1, "(%p) RTCP failed to tear down RTCP\n", instance);
8424  ao2_lock(instance);
8425  return;
8426  }
8427  ao2_lock(instance);
8428  rtp->rtcp->schedid = -1;
8429  }
8430  if (rtp->transport_wide_cc.schedid > -1) {
8431  ao2_unlock(instance);
8432  if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
8433  ao2_ref(instance, -1);
8434  } else {
8435  ast_debug_rtcp(1, "(%p) RTCP failed to tear down transport-cc feedback\n", instance);
8436  ao2_lock(instance);
8437  return;
8438  }
8439  ao2_lock(instance);
8440  rtp->transport_wide_cc.schedid = -1;
8441  }
8442  if (rtp->rtcp->s > -1 && rtp->rtcp->s != rtp->s) {
8443  close(rtp->rtcp->s);
8444  }
8445 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8446  ao2_unlock(instance);
8447  dtls_srtp_stop_timeout_timer(instance, rtp, 1);
8448  ao2_lock(instance);
8449 
8450  if (rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
8451  SSL_free(rtp->rtcp->dtls.ssl);
8452  }
8453 #endif
8454  ast_free(rtp->rtcp->local_addr_str);
8455  ast_free(rtp->rtcp);
8456  rtp->rtcp = NULL;
8457  }
8458  }
8459  } else if (property == AST_RTP_PROPERTY_ASYMMETRIC_CODEC) {
8460  rtp->asymmetric_codec = value;
8461  } else if (property == AST_RTP_PROPERTY_RETRANS_SEND) {
8462  if (value) {
8463  if (!rtp->send_buffer) {
8465  }
8466  } else {
8467  if (rtp->send_buffer) {
8468  ast_data_buffer_free(rtp->send_buffer);
8469  rtp->send_buffer = NULL;
8470  }
8471  }
8472  } else if (property == AST_RTP_PROPERTY_RETRANS_RECV) {
8473  if (value) {
8474  if (!rtp->recv_buffer) {
8476  AST_VECTOR_INIT(&rtp->missing_seqno, 0);
8477  }
8478  } else {
8479  if (rtp->recv_buffer) {
8480  ast_data_buffer_free(rtp->recv_buffer);
8481  rtp->recv_buffer = NULL;
8482  AST_VECTOR_FREE(&rtp->missing_seqno);
8483  }
8484  }
8485  }
8486 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
RTP session description.
struct ast_data_buffer * ast_data_buffer_alloc(ast_data_buffer_free_callback free_fn, size_t size)
Allocate a data buffer.
Definition: data_buffer.c:145
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
Definition: acl.c:1052
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
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
Socket address structure.
Definition: netsock2.h:97
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
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)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#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_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
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_free(a)
Definition: astmm.h:182
#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 DEFAULT_RTP_RECV_BUFFER_SIZE
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:610
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:643
#define DEFAULT_RTP_SEND_BUFFER_SIZE
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
#define TRANSPORT_SOCKET_RTCP
static int create_new_socket(const char *type, int af)
#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
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
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_qos_set()

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

Definition at line 8804 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_qos(), and ast_rtp::s.

8805 {
8806  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8807 
8808  return ast_set_qos(rtp->s, tos, cos, desc);
8809 }
RTP session description.
unsigned int cos
Definition: chan_iax2.c:352
static const char desc[]
Definition: cdr_mysql.c:73
unsigned int tos
Definition: chan_iax2.c:351
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621
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_read()

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

Definition at line 7638 of file res_rtp_asterisk.c.

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

7639 {
7640  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
7641  struct ast_srtp *srtp;
7643  struct ast_sockaddr addr;
7644  int res, hdrlen = 12, version, payloadtype;
7645  unsigned char *read_area = rtp->rawdata + AST_FRIENDLY_OFFSET;
7646  size_t read_area_size = sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET;
7647  unsigned int *rtpheader = (unsigned int*)(read_area), seqno, ssrc, timestamp, prev_seqno;
7648  struct ast_sockaddr remote_address = { {0,} };
7649  struct frame_list frames;
7650  struct ast_frame *frame;
7651  unsigned int bundled;
7652 
7653  /* If this is actually RTCP let's hop on over and handle it */
7654  if (rtcp) {
7655  if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
7656  return ast_rtcp_read(instance);
7657  }
7658  return &ast_null_frame;
7659  }
7660 
7661  /* Actually read in the data from the socket */
7662  if ((res = rtp_recvfrom(instance, read_area, read_area_size, 0,
7663  &addr)) < 0) {
7664  if (res == RTP_DTLS_ESTABLISHED) {
7665  rtp->f.frametype = AST_FRAME_CONTROL;
7667  return &rtp->f;
7668  }
7669 
7670  ast_assert(errno != EBADF);
7671  if (errno != EAGAIN) {
7672  ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n",
7673  (errno) ? strerror(errno) : "Unspecified");
7674  return NULL;
7675  }
7676  return &ast_null_frame;
7677  }
7678 
7679  /* If this was handled by the ICE session don't do anything */
7680  if (!res) {
7681  return &ast_null_frame;
7682  }
7683 
7684  /* This could be a multiplexed RTCP packet. If so, be sure to interpret it correctly */
7685  if (rtcp_mux(rtp, read_area)) {
7686  return ast_rtcp_interpret(instance, ast_rtp_instance_get_srtp(instance, 1), read_area, res, &addr);
7687  }
7688 
7689  /* Make sure the data that was read in is actually enough to make up an RTP packet */
7690  if (res < hdrlen) {
7691  /* If this is a keepalive containing only nulls, don't bother with a warning */
7692  int i;
7693  for (i = 0; i < res; ++i) {
7694  if (read_area[i] != '\0') {
7695  ast_log(LOG_WARNING, "RTP Read too short\n");
7696  return &ast_null_frame;
7697  }
7698  }
7699  return &ast_null_frame;
7700  }
7701 
7702  /* Get fields and verify this is an RTP packet */
7703  seqno = ntohl(rtpheader[0]);
7704 
7705  ast_rtp_instance_get_remote_address(instance, &remote_address);
7706 
7707  if (!(version = (seqno & 0xC0000000) >> 30)) {
7708  struct sockaddr_in addr_tmp;
7709  struct ast_sockaddr addr_v4;
7710  if (ast_sockaddr_is_ipv4(&addr)) {
7711  ast_sockaddr_to_sin(&addr, &addr_tmp);
7712  } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
7713  ast_debug_stun(1, "(%p) STUN using IPv6 mapped address %s\n",
7714  instance, ast_sockaddr_stringify(&addr));
7715  ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
7716  } else {
7717  ast_debug_stun(1, "(%p) STUN cannot do for non IPv4 address %s\n",
7718  instance, ast_sockaddr_stringify(&addr));
7719  return &ast_null_frame;
7720  }
7721  if ((ast_stun_handle_packet(rtp->s, &addr_tmp, read_area, res, NULL, NULL) == AST_STUN_ACCEPT) &&
7722  ast_sockaddr_isnull(&remote_address)) {
7723  ast_sockaddr_from_sin(&addr, &addr_tmp);
7724  ast_rtp_instance_set_remote_address(instance, &addr);
7725  }
7726  return &ast_null_frame;
7727  }
7728 
7729  /* If the version is not what we expected by this point then just drop the packet */
7730  if (version != 2) {
7731  return &ast_null_frame;
7732  }
7733 
7734  /* We use the SSRC to determine what RTP instance this packet is actually for */
7735  ssrc = ntohl(rtpheader[2]);
7736 
7737  /* We use the SRTP data from the provided instance that it came in on, not the child */
7738  srtp = ast_rtp_instance_get_srtp(instance, 0);
7739 
7740  /* Determine the appropriate instance for this */
7741  child = rtp_find_instance_by_packet_source_ssrc(instance, rtp, ssrc);
7742  if (!child) {
7743  /* Neither the bundled parent nor any child has this SSRC */
7744  return &ast_null_frame;
7745  }
7746  if (child != instance) {
7747  /* It is safe to hold the child lock while holding the parent lock, we guarantee that the locking order
7748  * is always parent->child or that the child lock is not held when acquiring the parent lock.
7749  */
7750  ao2_lock(child);
7751  instance = child;
7752  rtp = ast_rtp_instance_get_data(instance);
7753  } else {
7754  /* The child is the parent! We don't need to unlock it. */
7755  child = NULL;
7756  }
7757 
7758  /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
7759  switch (rtp->strict_rtp_state) {
7760  case STRICT_RTP_LEARN:
7761  /*
7762  * Scenario setup:
7763  * PartyA -- Ast1 -- Ast2 -- PartyB
7764  *
7765  * The learning timeout is necessary for Ast1 to handle the above
7766  * setup where PartyA calls PartyB and Ast2 initiates direct media
7767  * between Ast1 and PartyB. Ast1 may lock onto the Ast2 stream and
7768  * never learn the PartyB stream when it starts. The timeout makes
7769  * Ast1 stay in the learning state long enough to see and learn the
7770  * RTP stream from PartyB.
7771  *
7772  * To mitigate against attack, the learning state cannot switch
7773  * streams while there are competing streams. The competing streams
7774  * interfere with each other's qualification. Once we accept a
7775  * stream and reach the timeout, an attacker cannot interfere
7776  * anymore.
7777  *
7778  * Here are a few scenarios and each one assumes that the streams
7779  * are continuous:
7780  *
7781  * 1) We already have a known stream source address and the known
7782  * stream wants to change to a new source address. An attacking
7783  * stream will block learning the new stream source. After the
7784  * timeout we re-lock onto the original stream source address which
7785  * likely went away. The result is one way audio.
7786  *
7787  * 2) We already have a known stream source address and the known
7788  * stream doesn't want to change source addresses. An attacking
7789  * stream will not be able to replace the known stream. After the
7790  * timeout we re-lock onto the known stream. The call is not
7791  * affected.
7792  *
7793  * 3) We don't have a known stream source address. This presumably
7794  * is the start of a call. Competing streams will result in staying
7795  * in learning mode until a stream becomes the victor and we reach
7796  * the timeout. We cannot exit learning if we have no known stream
7797  * to lock onto. The result is one way audio until there is a victor.
7798  *
7799  * If we learn a stream source address before the timeout we will be
7800  * in scenario 1) or 2) when a competing stream starts.
7801  */
7802  if (!ast_sockaddr_isnull(&rtp->strict_rtp_address)
7803  && STRICT_RTP_LEARN_TIMEOUT < ast_tvdiff_ms(ast_tvnow(), rtp->rtp_source_learn.start)) {
7804  ast_verb(4, "%p -- Strict RTP learning complete - Locking on source address %s\n",
7805  rtp, ast_sockaddr_stringify(&rtp->strict_rtp_address));
7806  ast_test_suite_event_notify("STRICT_RTP_LEARN", "Source: %s",
7807  ast_sockaddr_stringify(&rtp->strict_rtp_address));
7808  rtp->strict_rtp_state = STRICT_RTP_CLOSED;
7809  } else {
7810  struct ast_sockaddr target_address;
7811 
7812  if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
7813  /*
7814  * We are open to learning a new address but have received
7815  * traffic from the current address, accept it and reset
7816  * the learning counts for a new source. When no more
7817  * current source packets arrive a new source can take over
7818  * once sufficient traffic is received.
7819  */
7820  rtp_learning_seq_init(&rtp->rtp_source_learn, seqno);
7821  break;
7822  }
7823 
7824  /*
7825  * We give preferential treatment to the requested target address
7826  * (negotiated SDP address) where we are to send our RTP. However,
7827  * the other end has no obligation to send from that address even
7828  * though it is practically a requirement when NAT is involved.
7829  */
7830  ast_rtp_instance_get_requested_target_address(instance, &target_address);
7831  if (!ast_sockaddr_cmp(&target_address, &addr)) {
7832  /* Accept the negotiated target RTP stream as the source */
7833  ast_verb(4, "%p -- Strict RTP switching to RTP target address %s as source\n",
7834  rtp, ast_sockaddr_stringify(&addr));
7835  ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
7836  rtp_learning_seq_init(&rtp->rtp_source_learn, seqno);
7837  break;
7838  }
7839 
7840  /*
7841  * Trying to learn a new address. If we pass a probationary period
7842  * with it, that means we've stopped getting RTP from the original
7843  * source and we should switch to it.
7844  */
7845  if (!ast_sockaddr_cmp(&rtp->rtp_source_learn.proposed_address, &addr)) {
7846  if (rtp->rtp_source_learn.stream_type == AST_MEDIA_TYPE_UNKNOWN) {
7847  struct ast_rtp_codecs *codecs;
7848 
7849  codecs = ast_rtp_instance_get_codecs(instance);
7850  rtp->rtp_source_learn.stream_type =
7852  ast_verb(4, "%p -- Strict RTP qualifying stream type: %s\n",
7853  rtp, ast_codec_media_type2str(rtp->rtp_source_learn.stream_type));
7854  }
7855  if (!rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
7856  /* Accept the new RTP stream */
7857  ast_verb(4, "%p -- Strict RTP switching source address to %s\n",
7858  rtp, ast_sockaddr_stringify(&addr));
7859  ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
7860  rtp_learning_seq_init(&rtp->rtp_source_learn, seqno);
7861  break;
7862  }
7863  /* Not ready to accept the RTP stream candidate */
7864  ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection. Will switch to it in %d packets.\n",
7865  instance, rtp, ast_sockaddr_stringify(&addr), rtp->rtp_source_learn.packets);
7866  } else {
7867  /*
7868  * This is either an attacking stream or
7869  * the start of the expected new stream.
7870  */
7871  ast_sockaddr_copy(&rtp->rtp_source_learn.proposed_address, &addr);
7872  rtp_learning_seq_init(&rtp->rtp_source_learn, seqno);
7873  ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection. Qualifying new stream.\n",
7874  instance, rtp, ast_sockaddr_stringify(&addr));
7875  }
7876  return &ast_null_frame;
7877  }
7878  /* Fall through */
7879  case STRICT_RTP_CLOSED:
7880  /*
7881  * We should not allow a stream address change if the SSRC matches
7882  * once strictrtp learning is closed. Any kind of address change
7883  * like this should have happened while we were in the learning
7884  * state. We do not want to allow the possibility of an attacker
7885  * interfering with the RTP stream after the learning period.
7886  * An attacker could manage to get an RTCP packet redirected to
7887  * them which can contain the SSRC value.
7888  */
7889  if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
7890  break;
7891  }
7892  ast_debug_rtp(1, "(%p) RTP %p -- Received packet from %s, dropping due to strict RTP protection.\n",
7893  instance, rtp, ast_sockaddr_stringify(&addr));
7894 #ifdef TEST_FRAMEWORK
7895  {
7896  static int strict_rtp_test_event = 1;
7897  if (strict_rtp_test_event) {
7898  ast_test_suite_event_notify("STRICT_RTP_CLOSED", "Source: %s",
7899  ast_sockaddr_stringify(&addr));
7900  strict_rtp_test_event = 0; /* Only run this event once to prevent possible spam */
7901  }
7902  }
7903 #endif
7904  return &ast_null_frame;
7905  case STRICT_RTP_OPEN:
7906  break;
7907  }
7908 
7909  /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
7911  if (ast_sockaddr_cmp(&remote_address, &addr)) {
7912  /* do not update the originally given address, but only the remote */
7914  ast_sockaddr_copy(&remote_address, &addr);
7915  if (rtp->rtcp && rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
7916  ast_sockaddr_copy(&rtp->rtcp->them, &addr);
7917  ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1);
7918  }
7921  ast_debug(0, "(%p) RTP NAT: Got audio from other end. Now sending to address %s\n",
7922  instance, ast_sockaddr_stringify(&remote_address));
7923  }
7924  }
7925 
7926  /* Pull out the various other fields we will need */
7927  payloadtype = (seqno & 0x7f0000) >> 16;
7928  seqno &= 0xffff;
7929  timestamp = ntohl(rtpheader[1]);
7930 
7931 #ifdef AST_DEVMODE
7932  if (should_drop_packets(&addr)) {
7933  ast_debug(0, "(%p) RTP: drop received packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
7934  instance, ast_sockaddr_stringify(&addr), payloadtype, seqno, timestamp, res - hdrlen);
7935  return &ast_null_frame;
7936  }
7937 #endif
7938 
7939  if (rtp_debug_test_addr(&addr)) {
7940  ast_verbose("Got RTP packet from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d)\n",
7941  ast_sockaddr_stringify(&addr),
7942  payloadtype, seqno, timestamp, res - hdrlen);
7943  }
7944 
7946 
7947  bundled = (child || AST_VECTOR_SIZE(&rtp->ssrc_mapping)) ? 1 : 0;
7948 
7949  prev_seqno = rtp->lastrxseqno;
7950  rtp->lastrxseqno = seqno;
7951 
7952  if (!rtp->recv_buffer) {
7953  /* If there is no receive buffer then we can pass back the frame directly */
7954  frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
7956  return AST_LIST_FIRST(&frames);
7957  } else if (rtp->expectedrxseqno == -1 || seqno == rtp->expectedrxseqno) {
7958  rtp->expectedrxseqno = seqno + 1;
7959 
7960  /* We've cycled over, so go back to 0 */
7961  if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
7962  rtp->expectedrxseqno = 0;
7963  }
7964 
7965  /* If there are no buffered packets that will be placed after this frame then we can
7966  * return it directly without duplicating it.
7967  */
7968  if (!ast_data_buffer_count(rtp->recv_buffer)) {
7969  frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
7971  return AST_LIST_FIRST(&frames);
7972  }
7973 
7974  if (!AST_VECTOR_REMOVE_CMP_ORDERED(&rtp->missing_seqno, seqno, find_by_value,
7976  ast_debug_rtp(2, "(%p) RTP Packet with sequence number '%d' on instance is no longer missing\n",
7977  instance, seqno);
7978  }
7979 
7980  /* If we don't have the next packet after this we can directly return the frame, as there is no
7981  * chance it will be overwritten.
7982  */
7983  if (!ast_data_buffer_get(rtp->recv_buffer, rtp->expectedrxseqno)) {
7984  frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
7986  return AST_LIST_FIRST(&frames);
7987  }
7988 
7989  /* Otherwise we need to dupe the frame so that the potential processing of frames placed after
7990  * it do not overwrite the data. You may be thinking that we could just add the current packet
7991  * to the head of the frames list and avoid having to duplicate it but this would result in out
7992  * of order packet processing by libsrtp which we are trying to avoid.
7993  */
7994  frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled));
7995  if (frame) {
7997  prev_seqno = seqno;
7998  }
7999 
8000  /* Add any additional packets that we have buffered and that are available */
8001  while (ast_data_buffer_count(rtp->recv_buffer)) {
8002  struct ast_rtp_rtcp_nack_payload *payload;
8003 
8004  payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_remove(rtp->recv_buffer, rtp->expectedrxseqno);
8005  if (!payload) {
8006  break;
8007  }
8008 
8009  frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled));
8010  ast_free(payload);
8011 
8012  if (!frame) {
8013  /* If this packet can't be interpeted due to being out of memory we return what we have and assume
8014  * that we will determine it is a missing packet later and NACK for it.
8015  */
8016  return AST_LIST_FIRST(&frames);
8017  }
8018 
8019  ast_debug_rtp(2, "(%p) RTP pulled buffered packet with sequence number '%d' to additionally return\n",
8020  instance, frame->seqno);
8022  prev_seqno = rtp->expectedrxseqno;
8023  rtp->expectedrxseqno++;
8024  if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8025  rtp->expectedrxseqno = 0;
8026  }
8027  }
8028 
8029  return AST_LIST_FIRST(&frames);
8030  } else if ((((seqno - rtp->expectedrxseqno) > 100) && timestamp > rtp->lastividtimestamp) ||
8031  ast_data_buffer_count(rtp->recv_buffer) == ast_data_buffer_max(rtp->recv_buffer)) {
8032  int inserted = 0;
8033 
8034  /* We have a large number of outstanding buffered packets or we've jumped far ahead in time.
8035  * To compensate we dump what we have in the buffer and place the current packet in a logical
8036  * spot. In the case of video we also require a full frame to give the decoding side a fighting
8037  * chance.
8038  */
8039 
8040  if (rtp->rtp_source_learn.stream_type == AST_MEDIA_TYPE_VIDEO) {
8041  ast_debug_rtp(2, "(%p) RTP source has wild gap or packet loss, sending FIR\n",
8042  instance);
8043  rtp_write_rtcp_fir(instance, rtp, &remote_address);
8044  }
8045 
8046  /* This works by going through the progression of the sequence number retrieving buffered packets
8047  * or inserting the current received packet until we've run out of packets. This ensures that the
8048  * packets are in the correct sequence number order.
8049  */
8050  while (ast_data_buffer_count(rtp->recv_buffer)) {
8051  struct ast_rtp_rtcp_nack_payload *payload;
8052 
8053  /* If the packet we received is the one we are expecting at this point then add it in */
8054  if (rtp->expectedrxseqno == seqno) {
8055  frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled));
8056  if (frame) {
8058  prev_seqno = seqno;
8059  ast_debug_rtp(2, "(%p) RTP inserted just received packet with sequence number '%d' in correct order\n",
8060  instance, seqno);
8061  }
8062  /* It is possible due to packet retransmission for this packet to also exist in the receive
8063  * buffer so we explicitly remove it in case this occurs, otherwise the receive buffer will
8064  * never be empty.
8065  */
8066  payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_remove(rtp->recv_buffer, seqno);
8067  if (payload) {
8068  ast_free(payload);
8069  }
8070  rtp->expectedrxseqno++;
8071  if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8072  rtp->expectedrxseqno = 0;
8073  }
8074  inserted = 1;
8075  continue;
8076  }
8077 
8078  payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_remove(rtp->recv_buffer, rtp->expectedrxseqno);
8079  if (payload) {
8080  frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled));
8081  if (frame) {
8083  prev_seqno = rtp->expectedrxseqno;
8084  ast_debug_rtp(2, "(%p) RTP emptying queue and returning packet with sequence number '%d'\n",
8085  instance, frame->seqno);
8086  }
8087  ast_free(payload);
8088  }
8089 
8090  rtp->expectedrxseqno++;
8091  if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8092  rtp->expectedrxseqno = 0;
8093  }
8094  }
8095 
8096  if (!inserted) {
8097  /* This current packet goes after them, and we assume that packets going forward will follow
8098  * that new sequence number increment. It is okay for this to not be duplicated as it is guaranteed
8099  * to be the last packet processed right now and it is also guaranteed that it will always return
8100  * non-NULL.
8101  */
8102  frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled);
8104  rtp->expectedrxseqno = seqno + 1;
8105  if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {
8106  rtp->expectedrxseqno = 0;
8107  }
8108 
8109  ast_debug_rtp(2, "(%p) RTP adding just received packet with sequence number '%d' to end of dumped queue\n",
8110  instance, seqno);
8111  }
8112 
8113  /* When we flush increase our chance for next time by growing the receive buffer when possible
8114  * by how many packets we missed, to give ourselves a bit more breathing room.
8115  */
8117  ast_data_buffer_max(rtp->recv_buffer) + AST_VECTOR_SIZE(&rtp->missing_seqno)));
8118  ast_debug_rtp(2, "(%p) RTP receive buffer is now at maximum of %zu\n", instance, ast_data_buffer_max(rtp->recv_buffer));
8119 
8120  /* As there is such a large gap we don't want to flood the order side with missing packets, so we
8121  * give up and start anew.
8122  */
8123  AST_VECTOR_RESET(&rtp->missing_seqno, AST_VECTOR_ELEM_CLEANUP_NOOP);
8124 
8125  return AST_LIST_FIRST(&frames);
8126  }
8127 
8128  /* We're finished with the frames list */
8130 
8131  /* Determine if the received packet is from the last OLD_PACKET_COUNT (1000 by default) packets or not.
8132  * For the case where the received sequence number exceeds that of the expected sequence number we calculate
8133  * the past sequence number that would be 1000 sequence numbers ago. If the received sequence number
8134  * exceeds or meets that then it is within OLD_PACKET_COUNT packets ago. For example if the expected
8135  * sequence number is 100 and we receive 65530, then it would be considered old. This is because
8136  * 65535 - 1000 + 100 = 64635 which gives us the sequence number at which we would consider the packets
8137  * old. Since 65530 is above that, it would be considered old.
8138  * For the case where the received sequence number is less than the expected sequence number we can do
8139  * a simple subtraction to see if it is 1000 packets ago or not.
8140  */
8141  if ((seqno < rtp->expectedrxseqno && ((rtp->expectedrxseqno - seqno) <= OLD_PACKET_COUNT)) ||
8142  (seqno > rtp->expectedrxseqno && (seqno >= (65535 - OLD_PACKET_COUNT + rtp->expectedrxseqno)))) {
8143  /* If this is a packet from the past then we have received a duplicate packet, so just drop it */
8144  ast_debug_rtp(2, "(%p) RTP received an old packet with sequence number '%d', dropping it\n",
8145  instance, seqno);
8146  return &ast_null_frame;
8147  } else if (ast_data_buffer_get(rtp->recv_buffer, seqno)) {
8148  /* If this is a packet we already have buffered then it is a duplicate, so just drop it */
8149  ast_debug_rtp(2, "(%p) RTP received a duplicate transmission of packet with sequence number '%d', dropping it\n",
8150  instance, seqno);
8151  return &ast_null_frame;
8152  } else {
8153  /* This is an out of order packet from the future */
8154  struct ast_rtp_rtcp_nack_payload *payload;
8155  int missing_seqno;
8156  int remove_failed;
8157  unsigned int missing_seqnos_added = 0;
8158 
8159  ast_debug_rtp(2, "(%p) RTP received an out of order packet with sequence number '%d' while expecting '%d' from the future\n",
8160  instance, seqno, rtp->expectedrxseqno);
8161 
8162  payload = ast_malloc(sizeof(*payload) + res);
8163  if (!payload) {
8164  /* If the payload can't be allocated then we can't defer this packet right now.
8165  * Instead of dumping what we have we pretend we lost this packet. It will then
8166  * get NACKed later or the existing buffer will be returned entirely. Well, we may
8167  * try since we're seemingly out of memory. It's a bad situation all around and
8168  * packets are likely to get lost anyway.
8169  */
8170  return &ast_null_frame;
8171  }
8172 
8173  payload->size = res;
8174  memcpy(payload->buf, rtpheader, res);
8175  if (ast_data_buffer_put(rtp->recv_buffer, seqno, payload) == -1) {
8176  ast_free(payload);
8177  }
8178 
8179  /* If this sequence number is removed that means we had a gap and this packet has filled it in
8180  * some. Since it was part of the gap we will have already added any other missing sequence numbers
8181  * before it (and possibly after it) to the vector so we don't need to do that again. Note that
8182  * remove_failed will be set to -1 if the sequence number isn't removed, and 0 if it is.
8183  */
8184  remove_failed = AST_VECTOR_REMOVE_CMP_ORDERED(&rtp->missing_seqno, seqno, find_by_value,
8186  if (!remove_failed) {
8187  ast_debug_rtp(2, "(%p) RTP packet with sequence number '%d' is no longer missing\n",
8188  instance, seqno);
8189  }
8190 
8191  /* The missing sequence number code works by taking the sequence number of the
8192  * packet we've just received and going backwards until we hit the sequence number
8193  * of the last packet we've received. While doing so we check to make sure that the
8194  * sequence number is not already missing and that it is not already buffered.
8195  */
8196  missing_seqno = seqno;
8197  while (remove_failed) {
8198  missing_seqno -= 1;
8199 
8200  /* If we've cycled backwards then start back at the top */
8201  if (missing_seqno < 0) {
8202  missing_seqno = 65535;
8203  }
8204 
8205  /* We've gone backwards enough such that we've hit the previous sequence number */
8206  if (missing_seqno == prev_seqno) {
8207  break;
8208  }
8209 
8210  /* We don't want missing sequence number duplicates. If, for some reason,
8211  * packets are really out of order, we could end up in this scenario:
8212  *
8213  * We are expecting sequence number 100
8214  * We receive sequence number 105
8215  * Sequence numbers 100 through 104 get added to the vector
8216  * We receive sequence number 101 (this section is skipped)
8217  * We receive sequence number 103
8218  * Sequence number 102 is added to the vector
8219  *
8220  * This will prevent the duplicate from being added.
8221  */
8222  if (AST_VECTOR_GET_CMP(&rtp->missing_seqno, missing_seqno,
8223  find_by_value)) {
8224  continue;
8225  }
8226 
8227  /* If this packet has been buffered already then don't count it amongst the
8228  * missing.
8229  */
8230  if (ast_data_buffer_get(rtp->recv_buffer, missing_seqno)) {
8231  continue;
8232  }
8233 
8234  ast_debug_rtp(2, "(%p) RTP added missing sequence number '%d'\n",
8235  instance, missing_seqno);
8236  AST_VECTOR_ADD_SORTED(&rtp->missing_seqno, missing_seqno,
8238  missing_seqnos_added++;
8239  }
8240 
8241  /* When we add a large number of missing sequence numbers we assume there was a substantial
8242  * gap in reception so we trigger an immediate NACK. When our data buffer is 1/4 full we
8243  * assume that the packets aren't just out of order but have actually been lost. At 1/2
8244  * full we get more aggressive and ask for retransmission when we get a new packet.
8245  * To get them back we construct and send a NACK causing the sender to retransmit them.
8246  */
8247  if (missing_seqnos_added >= MISSING_SEQNOS_ADDED_TRIGGER ||
8248  ast_data_buffer_count(rtp->recv_buffer) == ast_data_buffer_max(rtp->recv_buffer) / 4 ||
8249  ast_data_buffer_count(rtp->recv_buffer) >= ast_data_buffer_max(rtp->recv_buffer) / 2) {
8250  int packet_len = 0;
8251  int res = 0;
8252  int ice;
8253  int sr;
8254  size_t data_size = AST_UUID_STR_LEN + 128 + (AST_VECTOR_SIZE(&rtp->missing_seqno) * 4);
8255  RAII_VAR(unsigned char *, rtcpheader, NULL, ast_free_ptr);
8256  RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
8258  ao2_cleanup);
8259 
8260  /* Sufficient space for RTCP headers and report, SDES with CNAME, NACK header,
8261  * and worst case 4 bytes per missing sequence number.
8262  */
8263  rtcpheader = ast_malloc(sizeof(*rtcpheader) + data_size);
8264  if (!rtcpheader) {
8265  ast_debug_rtcp(1, "(%p) RTCP failed to allocate memory for NACK\n", instance);
8266  return &ast_null_frame;
8267  }
8268 
8269  memset(rtcpheader, 0, data_size);
8270 
8271  res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
8272 
8273  if (res == 0 || res == 1) {
8274  return &ast_null_frame;
8275  }
8276 
8277  packet_len += res;
8278 
8279  res = ast_rtcp_generate_nack(instance, rtcpheader + packet_len);
8280 
8281  if (res == 0) {
8282  ast_debug_rtcp(1, "(%p) RTCP failed to construct NACK, stopping here\n", instance);
8283  return &ast_null_frame;
8284  }
8285 
8286  packet_len += res;
8287 
8288  res = rtcp_sendto(instance, rtcpheader, packet_len, 0, &remote_address, &ice);
8289  if (res < 0) {
8290  ast_debug_rtcp(1, "(%p) RTCP failed to send NACK request out\n", instance);
8291  } else {
8292  ast_debug_rtcp(2, "(%p) RTCP sending a NACK request to get missing packets\n", instance);
8293  /* Update RTCP SR/RR statistics */
8294  ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, remote_address, ice, sr);
8295  }
8296  }
8297  }
8298 
8299  return &ast_null_frame;
8300 }
static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq)
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:331
RTP session description.
#define ast_frdup(fr)
Copies a frame.
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
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)
void * ast_data_buffer_remove(struct ast_data_buffer *buffer, size_t pos)
Remove a data payload from the data buffer.
Definition: data_buffer.c:299
#define SEQNO_CYCLE_OVER
static void rtp_write_rtcp_fir(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)
#define AST_UUID_STR_LEN
Definition: uuid.h:27
Structure for storing RTP packets for retransmission.
static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq)
#define OLD_PACKET_COUNT
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
static int compare_by_value(int elem, int value)
Helper function to compare an elem in a vector by value.
#define MISSING_SEQNOS_ADDED_TRIGGER
#define ast_set_flag(p, flag)
Definition: utils.h:70
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
#define RTP_DTLS_ESTABLISHED
static void rtp_instance_unlock(struct ast_rtp_instance *instance)
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
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
static struct ast_rtp_instance * rtp_find_instance_by_packet_source_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc)
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
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static struct ast_frame * ast_rtp_interpret(struct ast_rtp_instance *instance, struct ast_srtp *srtp, const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno, unsigned int bundled)
#define ast_assert(a)
Definition: utils.h:695
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
void ast_frame_free(struct ast_frame *fr, int cache)
Requests a frame to be allocated.
Definition: main/frame.c:176
#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
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
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
Socket address structure.
Definition: netsock2.h:97
#define ast_verb(level,...)
Definition: logger.h:463
struct ast_frame_subclass subclass
int ast_data_buffer_put(struct ast_data_buffer *buffer, size_t pos, void *payload)
Place a data payload at a position in the data buffer.
Definition: data_buffer.c:203
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_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
#define MIN(a, b)
Definition: utils.h:226
#define FLAG_NAT_ACTIVE
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#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
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:573
#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 frames
Definition: parser.c:51
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
#define MAXIMUM_RTP_RECV_BUFFER_SIZE
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
unsigned int themssrc_valid
void * ast_data_buffer_get(const struct ast_data_buffer *buffer, size_t pos)
Retrieve a data payload from the data buffer.
Definition: data_buffer.c:269
#define STRICT_RTP_LEARN_TIMEOUT
Strict RTP learning timeout time in milliseconds.
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
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_test_suite_event_notify(s, f,...)
Definition: test.h:196
#define ast_debug_stun(sublevel,...)
Log debug level STUN information.
Definition: stun.h:53
static int rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
int expectedrxseqno
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
#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 struct ast_frame * ast_rtcp_read(struct ast_rtp_instance *instance)
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
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:2864
static int should_drop_packets(struct ast_sockaddr *addr)
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
#define ast_free(a)
Definition: astmm.h:182
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
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 AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:733
#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison while maintaining order...
Definition: vector.h:540
struct ast_frame ast_null_frame
Definition: main/frame.c:79
unsigned int lastividtimestamp
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
#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)
size_t ast_data_buffer_count(const struct ast_data_buffer *buffer)
Return the number of payloads in a data buffer.
Definition: data_buffer.c:356
void ast_rtp_instance_get_requested_target_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the requested target address of the remote endpoint.
Definition: rtp_engine.c:673
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
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
Data structure associated with a single frame of data.
static int rtcp_mux(struct ast_rtp *rtp, const unsigned char *packet)
#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
static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
void ast_data_buffer_resize(struct ast_data_buffer *buffer, size_t size)
Resize a data buffer.
Definition: data_buffer.c:168
enum ast_media_type ast_rtp_codecs_get_stream_type(struct ast_rtp_codecs *codecs)
Determine the type of RTP stream media from the codecs mapped.
Definition: rtp_engine.c:1460
static int find_by_value(int elem, int value)
Helper function to find an elem in a vector by value.
#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
size_t ast_data_buffer_max(const struct ast_data_buffer *buffer)
Return the maximum number of payloads a data buffer can hold.
Definition: data_buffer.c:363
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
int ast_rtp_instance_set_incoming_source_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the incoming source address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:606

◆ ast_rtp_remote_address_set()

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

Definition at line 8497 of file res_rtp_asterisk.c.

References ast_debug_rtcp, ast_free, ast_ouraddrfor(), ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), AST_RTP_INSTANCE_RTCP_STANDARD, ast_rtp_instance_set_local_address(), ast_rtp_instance_set_remote_address, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdup, AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_verb, rtp_ssrc_mapping::instance, rtp_learning_start(), STRICT_RTP_OPEN, and strictrtp.

8498 {
8499  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8500  struct ast_sockaddr local;
8501  int index;
8502 
8503  ast_rtp_instance_get_local_address(instance, &local);
8504  if (!ast_sockaddr_isnull(addr)) {
8505  /* Update the local RTP address with what is being used */
8506  if (ast_ouraddrfor(addr, &local)) {
8507  /* Failed to update our address so reuse old local address */
8508  ast_rtp_instance_get_local_address(instance, &local);
8509  } else {
8510  ast_rtp_instance_set_local_address(instance, &local);
8511  }
8512  }
8513 
8514  if (rtp->rtcp && !ast_sockaddr_isnull(addr)) {
8515  ast_debug_rtcp(1, "(%p) RTCP setting address on RTP instance\n", instance);
8516  ast_sockaddr_copy(&rtp->rtcp->them, addr);
8517 
8518  if (rtp->rtcp->type == AST_RTP_INSTANCE_RTCP_STANDARD) {
8519  ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(addr) + 1);
8520 
8521  /* Update the local RTCP address with what is being used */
8522  ast_sockaddr_set_port(&local, ast_sockaddr_port(&local) + 1);
8523  }
8524  ast_sockaddr_copy(&rtp->rtcp->us, &local);
8525 
8526  ast_free(rtp->rtcp->local_addr_str);
8527  rtp->rtcp->local_addr_str = ast_strdup(ast_sockaddr_stringify(&local));
8528  }
8529 
8530  /* Update any bundled RTP instances */
8531  for (index = 0; index < AST_VECTOR_SIZE(&rtp->ssrc_mapping); ++index) {
8532  struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&rtp->ssrc_mapping, index);
8533 
8535  }
8536 
8537  /* Need to reset the DTMF last sequence number and the timestamp of the last END packet */
8538  rtp->last_seqno = 0;
8539  rtp->last_end_timestamp.ts = 0;
8540  rtp->last_end_timestamp.is_set = 0;
8541 
8542  if (strictrtp && rtp->strict_rtp_state != STRICT_RTP_OPEN
8543  && !ast_sockaddr_isnull(addr) && ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
8544  /* We only need to learn a new strict source address if we've been told the source is
8545  * changing to something different.
8546  */
8547  ast_verb(4, "%p -- Strict RTP learning after remote address set to: %s\n",
8548  rtp, ast_sockaddr_stringify(addr));
8549  rtp_learning_start(rtp);
8550  }
8551 }
struct ast_rtp_instance * instance
The RTP instance this SSRC belongs to.
RTP session description.
Structure used for mapping an incoming SSRC to an RTP instance.
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
static void rtp_learning_start(struct ast_rtp *rtp)
Start the strictrtp learning mode.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
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
#define ast_verb(level,...)
Definition: logger.h:463
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_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
Definition: acl.c:1005
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:670
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address that we are expecting to receive RTP on.
Definition: rtp_engine.c:588
static int strictrtp
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
#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 char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#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
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:643
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ ast_rtp_rtcp_handle_nack()

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

Definition at line 5963 of file res_rtp_asterisk.c.

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

Referenced by ast_rtcp_interpret().

5965 {
5966  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5967  int res = 0;
5968  int blp_index;
5969  int packet_index;
5970  int ice;
5971  struct ast_rtp_rtcp_nack_payload *payload;
5972  unsigned int current_word;
5973  unsigned int pid; /* Packet ID which refers to seqno of lost packet */
5974  unsigned int blp; /* Bitmask of following lost packets */
5975  struct ast_sockaddr remote_address = { {0,} };
5976  int abs_send_time_id;
5977  unsigned int now_msw = 0;
5978  unsigned int now_lsw = 0;
5979  unsigned int packets_not_found = 0;
5980 
5981  if (!rtp->send_buffer) {
5982  ast_debug_rtcp(1, "(%p) RTCP tried to handle NACK request, "
5983  "but we don't have a RTP packet storage!\n", instance);
5984  return res;
5985  }
5986 
5988  if (abs_send_time_id != -1) {
5989  timeval2ntp(ast_tvnow(), &now_msw, &now_lsw);
5990  }
5991 
5992  ast_rtp_instance_get_remote_address(instance, &remote_address);
5993 
5994  /*
5995  * We use index 3 because with feedback messages, the FCI (Feedback Control Information)
5996  * does not begin until after the version, packet SSRC, and media SSRC words.
5997  */
5998  for (packet_index = 3; packet_index < length; packet_index++) {
5999  current_word = ntohl(nackdata[position + packet_index]);
6000  pid = current_word >> 16;
6001  /* We know the remote end is missing this packet. Go ahead and send it if we still have it. */
6002  payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_get(rtp->send_buffer, pid);
6003  if (payload) {
6004  if (abs_send_time_id != -1) {
6005  /* On retransmission we need to update the timestamp within the packet, as it
6006  * is supposed to contain when the packet was actually sent.
6007  */
6008  put_unaligned_time24(payload->buf + 17, now_msw, now_lsw);
6009  }
6010  res += rtp_sendto(instance, payload->buf, payload->size, 0, &remote_address, &ice);
6011  } else {
6012  ast_debug_rtcp(1, "(%p) RTCP received NACK request for RTP packet with seqno %d, "
6013  "but we don't have it\n", instance, pid);
6014  packets_not_found++;
6015  }
6016  /*
6017  * The bitmask. Denoting the least significant bit as 1 and its most significant bit
6018  * as 16, then bit i of the bitmask is set to 1 if the receiver has not received RTP
6019  * packet (pid+i)(modulo 2^16). Otherwise, it is set to 0. We cannot assume bits set
6020  * to 0 after a bit set to 1 have actually been received.
6021  */
6022  blp = current_word & 0xffff;
6023  blp_index = 1;
6024  while (blp) {
6025  if (blp & 1) {
6026  /* Packet (pid + i)(modulo 2^16) is missing too. */
6027  unsigned int seqno = (pid + blp_index) % 65536;
6028  payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_get(rtp->send_buffer, seqno);
6029  if (payload) {
6030  if (abs_send_time_id != -1) {
6031  put_unaligned_time24(payload->buf + 17, now_msw, now_lsw);
6032  }
6033  res += rtp_sendto(instance, payload->buf, payload->size, 0, &remote_address, &ice);
6034  } else {
6035  ast_debug_rtcp(1, "(%p) RTCP remote end also requested RTP packet with seqno %d, "
6036  "but we don't have it\n", instance, seqno);
6037  packets_not_found++;
6038  }
6039  }
6040  blp >>= 1;
6041  blp_index++;
6042  }
6043  }
6044 
6045  if (packets_not_found) {
6046  /* Grow the send buffer based on how many packets were not found in the buffer, but
6047  * enforce a maximum.
6048  */
6050  ast_data_buffer_max(rtp->send_buffer) + packets_not_found));
6051  ast_debug_rtcp(2, "(%p) RTCP send buffer on RTP instance is now at maximum of %zu\n",
6052  instance, ast_data_buffer_max(rtp->send_buffer));
6053  }
6054 
6055  return res;
6056 }
RTP session description.
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:886
Structure for storing RTP packets for retransmission.
static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
#define MAXIMUM_RTP_SEND_BUFFER_SIZE
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
Socket address structure.
Definition: netsock2.h:97
#define MIN(a, b)
Definition: utils.h:226
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
void * ast_data_buffer_get(const struct ast_data_buffer *buffer, size_t pos)
Retrieve a data payload from the data buffer.
Definition: data_buffer.c:269
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 rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
static void put_unaligned_time24(void *p, uint32_t time_msw, uint32_t time_lsw)
void ast_data_buffer_resize(struct ast_data_buffer *buffer, size_t size)
Resize a data buffer.
Definition: data_buffer.c:168
#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
size_t ast_data_buffer_max(const struct ast_data_buffer *buffer)
Return the maximum number of payloads a data buffer can hold.
Definition: data_buffer.c:363

◆ ast_rtp_sendcng()

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

generate comfort noice (CNG)

Precondition
instance is locked

Definition at line 8816 of file res_rtp_asterisk.c.

References ast_log, AST_RTP_CN, ast_rtp_codecs_payload_code_tx(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose(), errno, ast_rtp::lastts, LOG_ERROR, NULL, rtp_debug_test_addr(), rtp_sendto(), and ast_rtp::ssrc.

8817 {
8818  unsigned int *rtpheader;
8819  int hdrlen = 12;
8820  int res, payload = 0;
8821  char data[256];
8822  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8823  struct ast_sockaddr remote_address = { {0,} };
8824  int ice;
8825 
8826  ast_rtp_instance_get_remote_address(instance, &remote_address);
8827 
8828  if (ast_sockaddr_isnull(&remote_address)) {
8829  return -1;
8830  }
8831 
8833 
8834  level = 127 - (level & 0x7f);
8835 
8836  rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
8837 
8838  /* Get a pointer to the header */
8839  rtpheader = (unsigned int *)data;
8840  rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
8841  rtpheader[1] = htonl(rtp->lastts);
8842  rtpheader[2] = htonl(rtp->ssrc);
8843  data[12] = level;
8844 
8845  res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address, &ice);
8846 
8847  if (res < 0) {
8848  ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
8849  return res;
8850  }
8851 
8852  if (rtp_debug_test_addr(&remote_address)) {
8853  ast_verbose("Sent Comfort Noise RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
8854  ast_sockaddr_stringify(&remote_address),
8855  ice ? " (via ICE)" : "",
8856  AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
8857  }
8858 
8859  rtp->seqno++;
8860 
8861  return res;
8862 }
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
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
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
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_CN
Definition: rtp_engine.h:268
#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_set_remote_ssrc()

static void ast_rtp_set_remote_ssrc ( struct ast_rtp_instance instance,
unsigned int  ssrc 
)
static
Precondition
instance is locked

Definition at line 8881 of file res_rtp_asterisk.c.

References ao2_lock, ao2_unlock, ast_rtp_instance_get_data(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, rtp_ssrc_mapping::instance, rtp_ssrc_mapping::ssrc, ast_rtp::ssrc, rtp_ssrc_mapping::ssrc_valid, ast_rtp::themssrc, and ast_rtp::themssrc_valid.

8882 {
8883  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8884 
8885  if (rtp->themssrc_valid && rtp->themssrc == ssrc) {
8886  return;
8887  }
8888 
8889  rtp->themssrc = ssrc;
8890  rtp->themssrc_valid = 1;
8891 
8892  /* If this is bundled we need to update the SSRC mapping */
8893  if (rtp->bundled) {
8894  struct ast_rtp *bundled_rtp;
8895  int index;
8896 
8897  ao2_unlock(instance);
8898 
8899  /* The child lock can't be held while accessing the parent */
8900  ao2_lock(rtp->bundled);
8901  bundled_rtp = ast_rtp_instance_get_data(rtp->bundled);
8902 
8903  for (index = 0; index < AST_VECTOR_SIZE(&bundled_rtp->ssrc_mapping); ++index) {
8904  struct rtp_ssrc_mapping *mapping = AST_VECTOR_GET_ADDR(&bundled_rtp->ssrc_mapping, index);
8905 
8906  if (mapping->instance == instance) {
8907  mapping->ssrc = ssrc;
8908  mapping->ssrc_valid = 1;
8909  break;
8910  }
8911  }
8912 
8913  ao2_unlock(rtp->bundled);
8914 
8915  ao2_lock(instance);
8916  }
8917 }
struct ast_rtp_instance * instance
The RTP instance this SSRC belongs to.
RTP session description.
Structure used for mapping an incoming SSRC to an RTP instance.
#define ao2_unlock(a)
Definition: astobj2.h:730
unsigned int ssrc_valid
unsigned int ssrc
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:670
#define ao2_lock(a)
Definition: astobj2.h:718
unsigned int themssrc_valid
unsigned int themssrc
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 ssrc
The received SSRC.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ ast_rtp_set_stream_num()

static void ast_rtp_set_stream_num ( struct ast_rtp_instance instance,
int  stream_num 
)
static

Definition at line 8919 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data().

8920 {
8921  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8922 
8923  rtp->stream_num = stream_num;
8924 }
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_stop()

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

Definition at line 8755 of file res_rtp_asterisk.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_free, ast_rtp_instance_get_data(), ast_rtp_instance_set_remote_address, AST_SCHED_DEL, ast_sched_del(), AST_SCHED_DEL_UNREF, ast_set_flag, FLAG_NEED_MARKER_BIT, and NULL.

8756 {
8757  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8758  struct ast_sockaddr addr = { {0,} };
8759 
8760 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
8761  ao2_unlock(instance);
8762  AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
8763 
8764  dtls_srtp_stop_timeout_timer(instance, rtp, 0);
8765  if (rtp->rtcp) {
8766  dtls_srtp_stop_timeout_timer(instance, rtp, 1);
8767  }
8768  ao2_lock(instance);
8769 #endif
8770 
8771  if (rtp->rtcp && rtp->rtcp->schedid > -1) {
8772  ao2_unlock(instance);
8773  if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
8774  /* successfully cancelled scheduler entry. */
8775  ao2_ref(instance, -1);
8776  }
8777  ao2_lock(instance);
8778  rtp->rtcp->schedid = -1;
8779  }
8780 
8781  if (rtp->transport_wide_cc.schedid > -1) {
8782  ao2_unlock(instance);
8783  if (!ast_sched_del(rtp->sched, rtp->transport_wide_cc.schedid)) {
8784  ao2_ref(instance, -1);
8785  }
8786  ao2_lock(instance);
8787  rtp->transport_wide_cc.schedid = -1;
8788  }
8789 
8790  if (rtp->red) {
8791  ao2_unlock(instance);
8792  AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
8793  ao2_lock(instance);
8794  ast_free(rtp->red);
8795  rtp->red = NULL;
8796  }
8797 
8798  ast_rtp_instance_set_remote_address(instance, &addr);
8799 
8801 }
RTP session description.
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_SCHED_DEL_UNREF(sched, id, refcall)
schedule task to get deleted and call unref function
Definition: sched.h:80
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define FLAG_NEED_MARKER_BIT
#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
#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
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:610

◆ ast_rtp_stun_request()

static void ast_rtp_stun_request ( struct ast_rtp_instance instance,
struct ast_sockaddr suggestion,
const char *  username 
)
static
Precondition
instance is NOT locked

Definition at line 8740 of file res_rtp_asterisk.c.

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

8741 {
8742  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8743  struct sockaddr_in suggestion_tmp;
8744 
8745  /*
8746  * The instance should not be locked because we can block
8747  * waiting for a STUN respone.
8748  */
8749  ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
8750  ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
8751  ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
8752 }
RTP session description.
#define NULL
Definition: resample.c:96
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:782
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition: stun.c:384
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_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:769

◆ ast_rtp_update_source()

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

Definition at line 4348 of file res_rtp_asterisk.c.

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

4349 {
4350  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4351 
4352  /* We simply set this bit so that the next packet sent will have the marker bit turned on */
4354  ast_debug_rtp(3, "(%p) RTP setting the marker bit due to a source update\n", instance);
4355 
4356  return;
4357 }
RTP session description.
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
#define FLAG_NEED_MARKER_BIT
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_write()

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

Definition at line 5289 of file res_rtp_asterisk.c.

References ao2_replace, AST_CONTROL_VIDUPDATE, ast_debug_rtp, ast_format_can_be_smoothed(), ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_default_ms(), ast_format_get_minimum_bytes(), ast_format_get_minimum_ms(), ast_format_get_name(), ast_format_get_smoother_flags(), AST_FRAME_CONTROL, AST_FRAME_RTCP, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup, ast_frfree, ast_log, ast_rtp_codecs_get_framing(), ast_rtp_codecs_payload_code_tx(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, AST_RTP_RTCP_PSFB, ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, AST_SMOOTHER_FLAG_FORCED, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_sockaddr_isnull(), ast_format::codec, ast_frame::data, ast_frame::datalen, format, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, ast_frame::offset, ast_frame::ptr, red_t140_to_red(), rtp_raw_write(), rtp_write_rtcp_fir(), rtp_write_rtcp_psfb(), and ast_frame::subclass.

Referenced by red_write(), and rtp_red_buffer().

5290 {
5291  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5292  struct ast_sockaddr remote_address = { {0,} };
5293  struct ast_format *format;
5294  int codec;
5295 
5296  ast_rtp_instance_get_remote_address(instance, &remote_address);
5297 
5298  /* If we don't actually know the remote address don't even bother doing anything */
5299  if (ast_sockaddr_isnull(&remote_address)) {
5300  ast_debug_rtp(1, "(%p) RTP no remote address on instance, so dropping frame\n", instance);
5301  return 0;
5302  }
5303 
5304  /* VP8: is this a request to send a RTCP FIR? */
5305  if (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_VIDUPDATE) {
5306  rtp_write_rtcp_fir(instance, rtp, &remote_address);
5307  return 0;
5308  } else if (frame->frametype == AST_FRAME_RTCP) {
5309  if (frame->subclass.integer == AST_RTP_RTCP_PSFB) {
5310  rtp_write_rtcp_psfb(instance, rtp, frame, &remote_address);
5311  }
5312  return 0;
5313  }
5314 
5315  /* If there is no data length we can't very well send the packet */
5316  if (!frame->datalen) {
5317  ast_debug_rtp(1, "(%p) RTP received frame with no data for instance, so dropping frame\n", instance);
5318  return 0;
5319  }
5320 
5321  /* If the packet is not one our RTP stack supports bail out */
5322  if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
5323  ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
5324  return -1;
5325  }
5326 
5327  if (rtp->red) {
5328  /* return 0; */
5329  /* no primary data or generations to send */
5330  if ((frame = red_t140_to_red(rtp->red)) == NULL)
5331  return 0;
5332  }
5333 
5334  /* Grab the subclass and look up the payload we are going to use */
5336  1, frame->subclass.format, 0);
5337  if (codec < 0) {
5338  ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n",
5340  return -1;
5341  }
5342 
5343  /* Note that we do not increase the ref count here as this pointer
5344  * will not be held by any thing explicitly. The format variable is
5345  * merely a convenience reference to frame->subclass.format */
5346  format = frame->subclass.format;
5347  if (ast_format_cmp(rtp->lasttxformat, format) == AST_FORMAT_CMP_NOT_EQUAL) {
5348  /* Oh dear, if the format changed we will have to set up a new smoother */
5349  ast_debug_rtp(1, "(%p) RTP ooh, format changed from %s to %s\n",
5350  instance, ast_format_get_name(rtp->lasttxformat),
5352  ao2_replace(rtp->lasttxformat, format);
5353  if (rtp->smoother) {
5354  ast_smoother_free(rtp->smoother);
5355  rtp->smoother = NULL;
5356  }
5357  }
5358 
5359  /* If no smoother is present see if we have to set one up */
5360  if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
5361  unsigned int smoother_flags = ast_format_get_smoother_flags(format);
5362  unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
5363 
5364  if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
5365  framing_ms = ast_format_get_default_ms(format);
5366  }
5367 
5368  if (framing_ms) {
5369  rtp->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
5370  if (!rtp->smoother) {
5371  ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len: %u\n",
5372  ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
5373  return -1;
5374  }
5375  ast_smoother_set_flags(rtp->smoother, smoother_flags);
5376  }
5377  }
5378 
5379  /* Feed audio frames into the actual function that will create a frame and send it */
5380  if (rtp->smoother) {
5381  struct ast_frame *f;
5382 
5383  if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
5384  ast_smoother_feed_be(rtp->smoother, frame);
5385  } else {
5386  ast_smoother_feed(rtp->smoother, frame);
5387  }
5388 
5389  while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
5390  rtp_raw_write(instance, f, codec);
5391  }
5392  } else {
5393  int hdrlen = 12;
5394  struct ast_frame *f = NULL;
5395 
5396  if (frame->offset < hdrlen) {
5397  f = ast_frdup(frame);
5398  } else {
5399  f = frame;
5400  }
5401  if (f->data.ptr) {
5402  rtp_raw_write(instance, f, codec);
5403  }
5404  if (f != frame) {
5405  ast_frfree(f);
5406  }
5407 
5408  }
5409 
5410  return 0;
5411 }
RTP session description.
#define ast_frdup(fr)
Copies a frame.
#define ast_smoother_feed(s, f)
Definition: smoother.h:76
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
static void rtp_write_rtcp_fir(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *remote_address)
static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
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
Definition of a media format.
Definition: format.c:43
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
static void rtp_write_rtcp_psfb(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_frame *frame, struct ast_sockaddr *remote_address)
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
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1569
struct ast_frame_subclass subclass
int ast_format_get_smoother_flags(const struct ast_format *format)
Get smoother flags for this format.
Definition: format.c:349
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
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
#define ast_log
Definition: astobj2.c:42
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
#define AST_SMOOTHER_FLAG_FORCED
Definition: smoother.h:36
unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
Get the minimum number of bytes expected in a frame for this format.
Definition: format.c:374
int ast_format_can_be_smoothed(const struct ast_format *format)
Get whether or not the format can be smoothed.
Definition: format.c:344
#define ast_smoother_feed_be(s, f)
Definition: smoother.h:81
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
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 ast_format_get_default_ms(const struct ast_format *format)
Get the default framing size (in milliseconds) for a format.
Definition: format.c:359
int ast_smoother_test_flag(struct ast_smoother *s, int flag)
Definition: smoother.c:128
#define AST_SMOOTHER_FLAG_BE
Definition: smoother.h:35
void ast_smoother_set_flags(struct ast_smoother *smoother, int flags)
Definition: smoother.c:123
#define ao2_replace(dst, src)
Definition: astobj2.h:517
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
#define ast_frfree(fr)
Data structure associated with a single frame of data.
#define AST_RTP_RTCP_PSFB
Definition: rtp_engine.h:299
union ast_frame::@263 data
enum ast_frame_type frametype
static struct ast_frame * red_t140_to_red(struct rtp_red *red)
struct ast_format * format
unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
Get the minimum amount of media carried in this format.
Definition: format.c:364
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#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

◆ bridge_p2p_rtp_write()

static int bridge_p2p_rtp_write ( struct ast_rtp_instance instance,
struct ast_rtp_instance instance1,
unsigned int *  rtpheader,
int  len,
int  hdrlen 
)
static
Precondition
instance is locked

Definition at line 6649 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_interpret().

6651 {
6652  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6653  struct ast_rtp *bridged;
6654  int res = 0, payload = 0, bridged_payload = 0, mark;
6655  RAII_VAR(struct ast_rtp_payload_type *, payload_type, NULL, ao2_cleanup);
6656  int reconstruct = ntohl(rtpheader[0]);
6657  struct ast_sockaddr remote_address = { {0,} };
6658  int ice;
6659  unsigned int timestamp = ntohl(rtpheader[1]);
6660 
6661  /* Get fields from packet */
6662  payload = (reconstruct & 0x7f0000) >> 16;
6663  mark = (reconstruct & 0x800000) >> 23;
6664 
6665  /* Check what the payload value should be */
6666  payload_type = ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload);
6667  if (!payload_type) {
6668  return -1;
6669  }
6670 
6671  /* Otherwise adjust bridged payload to match */
6672  bridged_payload = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance1),
6673  payload_type->asterisk_format, payload_type->format, payload_type->rtp_code);
6674 
6675  /* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged. Bail. */
6676  if (bridged_payload < 0) {
6677  return -1;
6678  }
6679 
6680  /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
6681  if (ast_rtp_codecs_find_payload_code(ast_rtp_instance_get_codecs(instance1), bridged_payload) == -1) {
6682  ast_debug_rtp(1, "(%p, %p) RTP unsupported payload type received\n", instance, instance1);
6683  return -1;
6684  }
6685 
6686  /*
6687  * Even if we are no longer in dtmf, we could still be receiving
6688  * re-transmissions of the last dtmf end still. Feed those to the
6689  * core so they can be filtered accordingly.
6690  */
6691  if (rtp->last_end_timestamp.is_set && rtp->last_end_timestamp.ts == timestamp) {
6692  ast_debug_rtp(1, "(%p, %p) RTP feeding packet with duplicate timestamp to core\n", instance, instance1);
6693  return -1;
6694  }
6695 
6696  if (payload_type->asterisk_format) {
6697  ao2_replace(rtp->lastrxformat, payload_type->format);
6698  }
6699 
6700  /*
6701  * We have now determined that we need to send the RTP packet
6702  * out the bridged instance to do local bridging so we must unlock
6703  * the receiving instance to prevent deadlock with the bridged
6704  * instance.
6705  *
6706  * Technically we should grab a ref to instance1 so it won't go
6707  * away on us. However, we should be safe because the bridged
6708  * instance won't change without both channels involved being
6709  * locked and we currently have the channel lock for the receiving
6710  * instance.
6711  */
6712  ao2_unlock(instance);
6713  ao2_lock(instance1);
6714 
6715  /*
6716  * Get the peer rtp pointer now to emphasize that using it
6717  * must happen while instance1 is locked.
6718  */
6719  bridged = ast_rtp_instance_get_data(instance1);
6720 
6721 
6722  /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */
6723  if (bridged->sending_digit) {
6724  ast_debug_rtp(1, "(%p, %p) RTP Feeding packet to core until DTMF finishes\n", instance, instance1);
6725  ao2_unlock(instance1);
6726  ao2_lock(instance);
6727  return -1;
6728  }
6729 
6730  if (payload_type->asterisk_format) {
6731  /*
6732  * If bridged peer has already received rtp, perform the asymmetric codec check
6733  * if that feature has been activated
6734  */
6735  if (!bridged->asymmetric_codec
6736  && bridged->lastrxformat != ast_format_none
6737  && ast_format_cmp(payload_type->format, bridged->lastrxformat) == AST_FORMAT_CMP_NOT_EQUAL) {
6738  ast_debug_rtp(1, "(%p, %p) RTP asymmetric RTP codecs detected (TX: %s, RX: %s) sending frame to core\n",
6739  instance, instance1, ast_format_get_name(payload_type->format),
6740  ast_format_get_name(bridged->lastrxformat));
6741  ao2_unlock(instance1);
6742  ao2_lock(instance);
6743  return -1;
6744  }
6745 
6746  ao2_replace(bridged->lasttxformat, payload_type->format);
6747  }
6748 
6749  ast_rtp_instance_get_remote_address(instance1, &remote_address);
6750 
6751  if (ast_sockaddr_isnull(&remote_address)) {
6752  ast_debug_rtp(5, "(%p, %p) RTP remote address is null, most likely RTP has been stopped\n",
6753  instance, instance1);
6754  ao2_unlock(instance1);
6755  ao2_lock(instance);
6756  return 0;
6757  }
6758 
6759  /* If the marker bit has been explicitly set turn it on */
6760  if (ast_test_flag(bridged, FLAG_NEED_MARKER_BIT)) {
6761  mark = 1;
6763  }
6764 
6765  /* Set the marker bit for the first local bridged packet which has the first bridged peer's SSRC. */
6766  if (ast_test_flag(bridged, FLAG_REQ_LOCAL_BRIDGE_BIT)) {
6767  mark = 1;
6769  }
6770 
6771  /* Reconstruct part of the packet */
6772  reconstruct &= 0xFF80FFFF;
6773  reconstruct |= (bridged_payload << 16);
6774  reconstruct |= (mark << 23);
6775  rtpheader[0] = htonl(reconstruct);
6776 
6777  if (mark) {
6778  /* make this rtp instance aware of the new ssrc it is sending */
6779  bridged->ssrc = ntohl(rtpheader[2]);
6780  }
6781 
6782  /* Send the packet back out */
6783  res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address, &ice);
6784  if (res < 0) {
6787  "RTP Transmission error of packet to %s: %s\n",
6788  ast_sockaddr_stringify(&remote_address),
6789  strerror(errno));
6793  "RTP NAT: Can't write RTP to private "
6794  "address %s, waiting for other end to "
6795  "send audio...\n",
6796  ast_sockaddr_stringify(&remote_address));
6797  }
6799  }
6800  ao2_unlock(instance1);
6801  ao2_lock(instance);
6802  return 0;
6803  }
6804 
6805  if (rtp_debug_test_addr(&remote_address)) {
6806  ast_verbose("Sent RTP P2P packet to %s%s (type %-2.2d, len %-6.6d)\n",
6807  ast_sockaddr_stringify(&remote_address),
6808  ice ? " (via ICE)" : "",
6809  bridged_payload, len - hdrlen);
6810  }
6811 
6812  ao2_unlock(instance1);
6813  ao2_lock(instance);
6814  return 0;
6815 }
RTP session description.
struct ast_rtp_payload_type * ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
Retrieve rx payload mapped information by payload type.
Definition: rtp_engine.c:1479
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
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
#define ao2_unlock(a)
Definition: astobj2.h:730
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
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_format * ast_format_none
Built-in "null" format.
Definition: format_cache.c:251
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
#define FLAG_NAT_ACTIVE
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_log
Definition: astobj2.c:42
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
#define FLAG_NAT_INACTIVE_NOWARN
#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 ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
#define ao2_lock(a)
Definition: astobj2.h:718
#define FLAG_NEED_MARKER_BIT
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:2864
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_clear_flag(p, flag)
Definition: utils.h:77
static int reconstruct(int sign, int dqln, int y)
Definition: codec_g726.c:331
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
#define FLAG_REQ_LOCAL_BRIDGE_BIT
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
int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int payload)
Search for the tx payload type in the ast_rtp_codecs structure.
Definition: rtp_engine.c:1975
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
#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
#define FLAG_NAT_INACTIVE

◆ calc_mean_and_standard_deviation()

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

Definition at line 3332 of file res_rtp_asterisk.c.

References ast_rtp_ioqueue_thread::count.

Referenced by calc_rxstamp(), calculate_lost_packet_statistics(), update_jitter_stats(), update_lost_stats(), and update_rtt_stats().

3333 {
3334  double delta1;
3335  double delta2;
3336 
3337  /* First convert the standard deviation back into a sum of squares. */
3338  double last_sum_of_squares = (*std_dev) * (*std_dev) * (*count ?: 1);
3339 
3340  if (++(*count) == 0) {
3341  /* Avoid potential divide by zero on an overflow */
3342  *count = 1;
3343  }
3344 
3345  /*
3346  * Below is an implementation of Welford's online algorithm [1] for calculating
3347  * mean and variance in a single pass.
3348  *
3349  * [1] https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
3350  */
3351 
3352  delta1 = new_sample - *mean;
3353  *mean += (delta1 / *count);
3354  delta2 = new_sample - *mean;
3355 
3356  /* Now calculate the new variance, and subsequent standard deviation */
3357  *std_dev = sqrt((last_sum_of_squares + (delta1 * delta2)) / *count);
3358 }

◆ calc_rxstamp()

static void calc_rxstamp ( struct timeval *  tv,
struct ast_rtp rtp,
unsigned int  timestamp,
int  mark 
)
static

Definition at line 5413 of file res_rtp_asterisk.c.

References ast_rtp_get_rate(), ast_samp2tv(), ast_tvadd(), ast_tvsub(), calc_mean_and_standard_deviation(), d, ast_rtp::f, ast_frame_subclass::format, NULL, and ast_frame::subclass.

Referenced by ast_rtp_interpret().

5414 {
5415  struct timeval now;
5416  struct timeval tmp;
5417  double transit;
5418  double current_time;
5419  double d;
5420  double dtv;
5421  double prog;
5422  int rate = ast_rtp_get_rate(rtp->f.subclass.format);
5423 
5424  if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
5425  gettimeofday(&rtp->rxcore, NULL);
5426  rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
5427  /* map timestamp to a real time */
5428  rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
5429  tmp = ast_samp2tv(timestamp, rate);
5430  rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
5431  /* Round to 0.1ms for nice, pretty timestamps */
5432  rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
5433  }
5434 
5435  gettimeofday(&now,NULL);
5436  /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
5437  tmp = ast_samp2tv(timestamp, rate);
5438  *tv = ast_tvadd(rtp->rxcore, tmp);
5439 
5440  prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
5441  dtv = (double)rtp->drxcore + (double)(prog);
5442  current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
5443  transit = current_time - dtv;
5444  d = transit - rtp->rxtransit;
5445  rtp->rxtransit = transit;
5446  if (d<0) {
5447  d=-d;
5448  }
5449  rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
5450  if (rtp->rtcp) {
5451  if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
5452  rtp->rtcp->maxrxjitter = rtp->rxjitter;
5453  if (rtp->rtcp->rxjitter_count == 1)
5454  rtp->rtcp->minrxjitter = rtp->rxjitter;
5455  if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
5456  rtp->rtcp->minrxjitter = rtp->rxjitter;
5457 
5458  calc_mean_and_standard_deviation(rtp->rxjitter, &rtp->rtcp->normdev_rxjitter,
5459  &rtp->rtcp->stdev_rxjitter, &rtp->rtcp->rxjitter_count);
5460  }
5461 }
static struct test_val d
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
static void calc_mean_and_standard_deviation(double new_sample, double *mean, double *std_dev, unsigned int *count)
struct ast_frame_subclass subclass
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
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
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
struct ast_frame f
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2298
struct ast_format * format

◆ calc_txstamp()

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

Definition at line 3716 of file res_rtp_asterisk.c.

References ast_tvdiff_ms(), ast_tvnow(), and ast_tvzero().

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

3717 {
3718  struct timeval t;
3719  long ms;
3720 
3721  if (ast_tvzero(rtp->txcore)) {
3722  rtp->txcore = ast_tvnow();
3723  rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
3724  }
3725 
3726  t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
3727  if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
3728  ms = 0;
3729  }
3730  rtp->txcore = t;
3731 
3732  return (unsigned int) ms;
3733 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98

◆ calculate_lost_packet_statistics()

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

Definition at line 4428 of file res_rtp_asterisk.c.

References calc_mean_and_standard_deviation(), and ast_rtp::lastrxseqno.

Referenced by ast_rtcp_generate_report().

4431 {
4432  unsigned int extended_seq_no;
4433  unsigned int expected_packets;
4434  unsigned int expected_interval;
4435  unsigned int received_interval;
4436  int lost_interval;
4437 
4438  /* Compute statistics */
4439  extended_seq_no = rtp->cycles + rtp->lastrxseqno;
4440  expected_packets = extended_seq_no - rtp->seedrxseqno + 1;
4441  if (rtp->rxcount > expected_packets) {
4442  expected_packets += rtp->rxcount - expected_packets;
4443  }
4444  *lost_packets = expected_packets - rtp->rxcount;
4445  expected_interval = expected_packets - rtp->rtcp->expected_prior;
4446  received_interval = rtp->rxcount - rtp->rtcp->received_prior;
4447  if (received_interval > expected_interval) {
4448  /* If we receive some late packets it is possible for the packets
4449  * we received in this interval to exceed the number we expected.
4450  * We update the expected so that the packet loss calculations
4451  * show that no packets are lost.
4452  */
4453  expected_interval = received_interval;
4454  }
4455  lost_interval = expected_interval - received_interval;
4456  if (expected_interval == 0 || lost_interval <= 0) {
4457  *fraction_lost = 0;
4458  } else {
4459  *fraction_lost = (lost_interval << 8) / expected_interval;
4460  }
4461 
4462  /* Update RTCP statistics */
4463  rtp->rtcp->received_prior = rtp->rxcount;
4464  rtp->rtcp->expected_prior = expected_packets;
4465 
4466  /*
4467  * While rxlost represents the number of packets lost since the last report was sent, for
4468  * the calculations below it should be thought of as a single sample. Thus min/max are the
4469  * lowest/highest sample value seen, and the mean is the average number of packets lost
4470  * between each report. As such rxlost_count only needs to be incremented per report.
4471  */
4472  if (lost_interval <= 0) {
4473  rtp->rtcp->rxlost = 0;
4474  } else {
4475  rtp->rtcp->rxlost = lost_interval;
4476  }
4477  if (rtp->rtcp->rxlost_count == 0) {
4478  rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4479  }
4480  if (lost_interval && lost_interval < rtp->rtcp->minrxlost) {
4481  rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
4482  }
4483  if (lost_interval > rtp->rtcp->maxrxlost) {
4484  rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
4485  }
4486 
4487  calc_mean_and_standard_deviation(rtp->rtcp->rxlost, &rtp->rtcp->normdev_rxlost,
4488  &rtp->rtcp->stdev_rxlost, &rtp->rtcp->rxlost_count);
4489 }
static void calc_mean_and_standard_deviation(double new_sample, double *mean, double *std_dev, unsigned int *count)

◆ compare_by_value()

static int compare_by_value ( int  elem,
int  value 
)
static

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

Definition at line 3039 of file res_rtp_asterisk.c.

References value.

Referenced by ast_rtp_read().

3040 {
3041  return elem - value;
3042 }
int value
Definition: syslog.c:37

◆ create_dtmf_frame()

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

Definition at line 5463 of file res_rtp_asterisk.c.

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

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

5464 {
5465  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5466  struct ast_sockaddr remote_address = { {0,} };
5467 
5468  ast_rtp_instance_get_remote_address(instance, &remote_address);
5469 
5470  if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
5471  ast_debug_rtp(1, "(%p) RTP ignore potential DTMF echo from '%s'\n",
5472  instance, ast_sockaddr_stringify(&remote_address));
5473  rtp->resp = 0;
5474  rtp->dtmfsamples = 0;
5475  return &ast_null_frame;
5476  } else if (type == AST_FRAME_DTMF_BEGIN && rtp->resp == 'X') {
5477  ast_debug_rtp(1, "(%p) RTP ignore flash begin from '%s'\n",
5478  instance, ast_sockaddr_stringify(&remote_address));
5479  rtp->resp = 0;
5480  rtp->dtmfsamples = 0;
5481  return &ast_null_frame;
5482  }
5483 
5484  if (rtp->resp == 'X') {
5485  ast_debug_rtp(1, "(%p) RTP creating flash Frame at %s\n",
5486  instance, ast_sockaddr_stringify(&remote_address));
5487  rtp->f.frametype = AST_FRAME_CONTROL;
5489  } else {
5490  ast_debug_rtp(1, "(%p) RTP creating %s DTMF Frame: %d (%c), at %s\n",
5491  instance, type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
5492  rtp->resp, rtp->resp,
5493  ast_sockaddr_stringify(&remote_address));
5494  rtp->f.frametype = type;
5495  rtp->f.subclass.integer = rtp->resp;
5496  }
5497  rtp->f.datalen = 0;
5498  rtp->f.samples = 0;
5499  rtp->f.mallocd = 0;
5500  rtp->f.src = "RTP";
5501  AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
5502 
5503  return &rtp->f;
5504 }
static const char type[]
Definition: chan_ooh323.c:109
RTP session description.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
struct ast_frame_subclass subclass
const char * src
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
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
enum ast_frame_type frametype
#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

◆ create_new_socket()

static int create_new_socket ( const char *  type,
int  af 
)
static

Definition at line 3360 of file res_rtp_asterisk.c.

References ast_log, ast_socket_nonblock, errno, and LOG_WARNING.

Referenced by ast_rtp_prop_set(), and rtp_allocate_transport().

3361 {
3362  int sock = ast_socket_nonblock(af, SOCK_DGRAM, 0);
3363 
3364  if (sock < 0) {
3365  ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
3366  return sock;
3367  }
3368 
3369 #ifdef SO_NO_CHECK
3370  if (nochecksums) {
3371  setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
3372  }
3373 #endif
3374 
3375  return sock;
3376 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1043
#define ast_log
Definition: astobj2.c:42
int errno

◆ drop_packets_data_update()

static void drop_packets_data_update ( struct timeval  tv)
static

Definition at line 7553 of file res_rtp_asterisk.c.

References ast_random(), ast_time_create_by_unit(), ast_time_tv_to_usec(), ast_tvadd(), drop_packets_data, rtp_drop_packets_data::interval, rtp_drop_packets_data::next, rtp_drop_packets_data::num_dropped, rtp_drop_packets_data::num_to_drop, TIME_UNIT_MICROSECOND, rtp_drop_packets_data::use_random_interval, and rtp_drop_packets_data::use_random_num.

Referenced by handle_cli_rtp_drop_incoming_packets(), and should_drop_packets().

7554 {
7555  /*
7556  * num_dropped keeps up with the number of packets that have been dropped for a
7557  * given interval. Once the specified number of packets have been dropped and
7558  * the next time interval is ready to trigger then set this number to zero (drop
7559  * the next 'n' packets up to 'num_to_drop'), or if 'use_random_num' is set to
7560  * true then set to a random number between zero and 'num_to_drop'.
7561  */
7564 
7565  /*
7566  * A specified number of packets can be dropped at a given interval (e.g every
7567  * 30 seconds). If 'use_random_interval' is false simply add the interval to
7568  * the given time to get the next trigger point. If set to true, then get a
7569  * random time between the given time and up to the specified interval.
7570  */
7572  /* Calculate as a percentage of the specified drop packets interval */
7573  struct timeval interval = ast_time_create_by_unit(ast_time_tv_to_usec(
7574  &drop_packets_data.interval) * ((double)(ast_random() % 100 + 1) / 100),
7576 
7577  drop_packets_data.next = ast_tvadd(tv, interval);
7578  } else {
7580  }
7581 }
ast_suseconds_t ast_time_tv_to_usec(const struct timeval *tv)
Convert a timeval structure to microseconds.
Definition: time.c:89
unsigned int use_random_interval
long int ast_random(void)
Definition: main/utils.c:2064
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
struct timeval ast_time_create_by_unit(unsigned long val, enum TIME_UNIT unit)
Convert the given unit value, and create a timeval object from it.
Definition: time.c:112
static struct rtp_drop_packets_data drop_packets_data

◆ find_by_value()

static int find_by_value ( int  elem,
int  value 
)
static

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

Definition at line 3045 of file res_rtp_asterisk.c.

References value.

Referenced by ast_rtcp_generate_nack(), and ast_rtp_read().

3046 {
3047  return elem == value;
3048 }
int value
Definition: syslog.c:37

◆ generate_random_string()

static char * generate_random_string ( char *  buf,
size_t  size 
)
static

Definition at line 1720 of file res_rtp_asterisk.c.

References ast_random(), and buf.

Referenced by ast_rtp_ice_set_authentication(), and rtp_allocate_transport().

1721 {
1722  long val[4];
1723  int x;
1724 
1725  for (x=0; x<4; x++) {
1726  val[x] = ast_random();
1727  }
1728  snprintf(buf, size, "%08lx%08lx%08lx%08lx", (long unsigned)val[0], (long unsigned)val[1], (long unsigned)val[2], (long unsigned)val[3]);
1729 
1730  return buf;
1731 }
Definition: ast_expr2.c:325
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
long int ast_random(void)
Definition: main/utils.c:2064

◆ get_recv_buffer_count()

static size_t get_recv_buffer_count ( struct ast_rtp_instance instance)
static

Definition at line 2430 of file res_rtp_asterisk.c.

References ast_data_buffer_count(), and ast_rtp_instance_get_data().

2431 {
2432  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2433 
2434  if (rtp && rtp->recv_buffer) {
2435  return ast_data_buffer_count(rtp->recv_buffer);
2436  }
2437 
2438  return 0;
2439 }
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
size_t ast_data_buffer_count(const struct ast_data_buffer *buffer)
Return the number of payloads in a data buffer.
Definition: data_buffer.c:356

◆ get_recv_buffer_max()

static size_t get_recv_buffer_max ( struct ast_rtp_instance instance)
static

Definition at line 2441 of file res_rtp_asterisk.c.

References ast_data_buffer_max(), and ast_rtp_instance_get_data().

2442 {
2443  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2444 
2445  if (rtp && rtp->recv_buffer) {
2446  return ast_data_buffer_max(rtp->recv_buffer);
2447  }
2448 
2449  return 0;
2450 }
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
size_t ast_data_buffer_max(const struct ast_data_buffer *buffer)
Return the maximum number of payloads a data buffer can hold.
Definition: data_buffer.c:363

◆ get_send_buffer_count()

static size_t get_send_buffer_count ( struct ast_rtp_instance instance)
static

Definition at line 2452 of file res_rtp_asterisk.c.

References ast_data_buffer_count(), and ast_rtp_instance_get_data().

2453 {
2454  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2455 
2456  if (rtp && rtp->send_buffer) {
2457  return ast_data_buffer_count(rtp->send_buffer);
2458  }
2459 
2460  return 0;
2461 }
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
size_t ast_data_buffer_count(const struct ast_data_buffer *buffer)
Return the number of payloads in a data buffer.
Definition: data_buffer.c:356

◆ handle_cli_rtcp_set_debug()

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

Definition at line 9145 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_DISABLED, AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTCP_PACKET, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, rtcp_do_debug_ip(), rtcpdebugaddr, and ast_cli_entry::usage.

9146 {
9147  switch (cmd) {
9148  case CLI_INIT:
9149  e->command = "rtcp set debug {on|off|ip}";
9150  e->usage =
9151  "Usage: rtcp set debug {on|off|ip host[:port]}\n"
9152  " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
9153  " specified, limit the dumped packets to those to and from\n"
9154  " the specified 'host' with optional port.\n";
9155  return NULL;
9156  case CLI_GENERATE:
9157  return NULL;
9158  }
9159 
9160  if (a->argc == e->args) { /* set on or off */
9161  if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9163  memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
9164  ast_cli(a->fd, "RTCP Packet Debugging Enabled\n");
9165  return CLI_SUCCESS;
9166  } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9168  ast_cli(a->fd, "RTCP Packet Debugging Disabled\n");
9169  return CLI_SUCCESS;
9170  }
9171  } else if (a->argc == e->args +1) { /* ip */
9172  return rtcp_do_debug_ip(a);
9173  }
9174 
9175  return CLI_SHOWUSAGE; /* default, failure */
9176 }
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category&#39;s sublevel.
const int argc
Definition: cli.h:160
Definition: cli.h:152
static char * rtcp_do_debug_ip(struct ast_cli_args *a)
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
static struct ast_sockaddr rtcpdebugaddr
const char *const * argv
Definition: cli.h:161
#define AST_LOG_CATEGORY_RTCP_PACKET
Definition: rtp_engine.h:2830
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_LOG_CATEGORY_DISABLED
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_LOG_CATEGORY_ENABLED

◆ handle_cli_rtcp_set_stats()

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

Definition at line 9178 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, rtcpstats, and ast_cli_entry::usage.

9179 {
9180  switch (cmd) {
9181  case CLI_INIT:
9182  e->command = "rtcp set stats {on|off}";
9183  e->usage =
9184  "Usage: rtcp set stats {on|off}\n"
9185  " Enable/Disable dumping of RTCP stats.\n";
9186  return NULL;
9187  case CLI_GENERATE:
9188  return NULL;
9189  }
9190 
9191  if (a->argc != e->args)
9192  return CLI_SHOWUSAGE;
9193 
9194  if (!strncasecmp(a->argv[e->args-1], "on", 2))
9195  rtcpstats = 1;
9196  else if (!strncasecmp(a->argv[e->args-1], "off", 3))
9197  rtcpstats = 0;
9198  else
9199  return CLI_SHOWUSAGE;
9200 
9201  ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
9202  return CLI_SUCCESS;
9203 }
static int rtcpstats
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ handle_cli_rtp_drop_incoming_packets()

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

Definition at line 9213 of file res_rtp_asterisk.c.

References rtp_drop_packets_data::addr, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), ast_cli_completion_add(), ast_sockaddr_copy(), ast_sockaddr_parse(), ast_sockaddr_port, ast_str_to_uint(), ast_strdup, ast_time_create_by_unit_str(), ast_tvnow(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, drop_packets_data, drop_packets_data_update(), ast_cli_args::fd, rtp_drop_packets_data::interval, ast_cli_args::n, NULL, rtp_drop_packets_data::num_to_drop, rtp_drop_packets_data::port, ast_cli_args::pos, ast_cli_entry::usage, use_random(), rtp_drop_packets_data::use_random_interval, rtp_drop_packets_data::use_random_num, and ast_cli_args::word.

9214 {
9215  static const char * const completions_2[] = { "stop", "<N>", NULL };
9216  static const char * const completions_3[] = { "random", "incoming packets", NULL };
9217  static const char * const completions_5[] = { "on", "every", NULL };
9218  static const char * const completions_units[] = { "random", "usec", "msec", "sec", "min", NULL };
9219 
9220  unsigned int use_random_num = 0;
9221  unsigned int use_random_interval = 0;
9222  unsigned int num_to_drop = 0;
9223  unsigned int interval = 0;
9224  const char *interval_s = NULL;
9225  const char *unit_s = NULL;
9226  struct ast_sockaddr addr;
9227  const char *addr_s = NULL;
9228 
9229  switch (cmd) {
9230  case CLI_INIT:
9231  e->command = "rtp drop";
9232  e->usage =
9233  "Usage: rtp drop [stop|[<N> [random] incoming packets[ every <N> [random] {usec|msec|sec|min}][ on <ip[:port]>]]\n"
9234  " Drop RTP incoming packets.\n";
9235  return NULL;
9236  case CLI_GENERATE:
9237  use_random_num = use_random(a, a->pos, 4);
9238  use_random_interval = use_random(a, a->pos, 8 + use_random_num) ||
9239  use_random(a, a->pos, 10 + use_random_num);
9240 
9241  switch (a->pos - use_random_num - use_random_interval) {
9242  case 2:
9243  return ast_cli_complete(a->word, completions_2, a->n);
9244  case 3:
9245  return ast_cli_complete(a->word, completions_3 + use_random_num, a->n);
9246  case 5:
9247  return ast_cli_complete(a->word, completions_5, a->n);
9248  case 7:
9249  if (!strcasecmp(a->argv[a->pos - 2], "on")) {
9251  break;
9252  }
9253  /* Fall through */
9254  case 9:
9255  if (!strcasecmp(a->argv[a->pos - 2 - use_random_interval], "every")) {
9256  return ast_cli_complete(a->word, completions_units + use_random_interval, a->n);
9257  }
9258  break;
9259  case 8:
9260  if (!strcasecmp(a->argv[a->pos - 3 - use_random_interval], "every")) {
9262  }
9263  break;
9264  }
9265 
9266  return NULL;
9267  }
9268 
9269  if (a->argc < 3) {
9270  return CLI_SHOWUSAGE;
9271  }
9272 
9273  use_random_num = use_random(a, a->argc, 4);
9274  use_random_interval = use_random(a, a->argc, 8 + use_random_num) ||
9275  use_random(a, a->argc, 10 + use_random_num);
9276 
9277  if (!strcasecmp(a->argv[2], "stop")) {
9278  /* rtp drop stop */
9279  } else if (a->argc < 5) {
9280  return CLI_SHOWUSAGE;
9281  } else if (ast_str_to_uint(a->argv[2], &num_to_drop)) {
9282  ast_cli(a->fd, "%s is not a valid number of packets to drop\n", a->argv[2]);
9283  return CLI_FAILURE;
9284  } else if (a->argc - use_random_num == 5) {
9285  /* rtp drop <N> [random] incoming packets */
9286  } else if (a->argc - use_random_num >= 7 && !strcasecmp(a->argv[5 + use_random_num], "on")) {
9287  /* rtp drop <N> [random] incoming packets on <ip[:port]> */
9288  addr_s = a->argv[6 + use_random_num];
9289  if (a->argc - use_random_num - use_random_interval == 10 &&
9290  !strcasecmp(a->argv[7 + use_random_num], "every")) {
9291  /* rtp drop <N> [random] incoming packets on <ip[:port]> every <N> [random] {usec|msec|sec|min} */
9292  interval_s = a->argv[8 + use_random_num];
9293  unit_s = a->argv[9 + use_random_num + use_random_interval];
9294  }
9295  } else if (a->argc - use_random_num >= 8 && !strcasecmp(a->argv[5 + use_random_num], "every")) {
9296  /* rtp drop <N> [random] incoming packets every <N> [random] {usec|msec|sec|min} */
9297  interval_s = a->argv[6 + use_random_num];
9298  unit_s = a->argv[7 + use_random_num + use_random_interval];
9299  if (a->argc == 10 + use_random_num + use_random_interval &&
9300  !strcasecmp(a->argv[8 + use_random_num + use_random_interval], "on")) {
9301  /* rtp drop <N> [random] incoming packets every <N> [random] {usec|msec|sec|min} on <ip[:port]> */
9302  addr_s = a->argv[9 + use_random_num + use_random_interval];
9303  }
9304  } else {
9305  return CLI_SHOWUSAGE;
9306  }
9307 
9308  if (a->argc - use_random_num >= 8 && !interval_s && !addr_s) {
9309  return CLI_SHOWUSAGE;
9310  }
9311 
9312  if (interval_s && ast_str_to_uint(interval_s, &interval)) {
9313  ast_cli(a->fd, "%s is not a valid interval number\n", interval_s);
9314  return CLI_FAILURE;
9315  }
9316 
9317  memset(&addr, 0, sizeof(addr));
9318  if (addr_s && !ast_sockaddr_parse(&addr, addr_s, 0)) {
9319  ast_cli(a->fd, "%s is not a valid hostname[:port]\n", addr_s);
9320  return CLI_FAILURE;
9321  }
9322 
9323  drop_packets_data.use_random_num = use_random_num;
9324  drop_packets_data.use_random_interval = use_random_interval;
9325  drop_packets_data.num_to_drop = num_to_drop;
9329 
9331 
9332  return CLI_SUCCESS;
9333 }
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
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
const int argc
Definition: cli.h:160
struct timeval ast_time_create_by_unit_str(unsigned long val, const char *unit)
Convert the given unit value, and create a timeval object from it.
Definition: time.c:142
Definition: cli.h:152
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
Socket address structure.
Definition: netsock2.h:97
struct ast_sockaddr addr
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1811
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
unsigned int use_random_interval
static void drop_packets_data_update(struct timeval tv)
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Definition: conversions.c:56
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
static struct rtp_drop_packets_data drop_packets_data
static unsigned int use_random(struct ast_cli_args *a, int pos, unsigned int index)

◆ handle_cli_rtp_set_debug()

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

Definition at line 9072 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_DISABLED, AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTP_PACKET, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, rtp_do_debug_ip(), rtpdebugaddr, and ast_cli_entry::usage.

9073 {
9074  switch (cmd) {
9075  case CLI_INIT:
9076  e->command = "rtp set debug {on|off|ip}";
9077  e->usage =
9078  "Usage: rtp set debug {on|off|ip host[:port]}\n"
9079  " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
9080  " specified, limit the dumped packets to those to and from\n"
9081  " the specified 'host' with optional port.\n";
9082  return NULL;
9083  case CLI_GENERATE:
9084  return NULL;
9085  }
9086 
9087  if (a->argc == e->args) { /* set on or off */
9088  if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
9090  memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
9091  ast_cli(a->fd, "RTP Packet Debugging Enabled\n");
9092  return CLI_SUCCESS;
9093  } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
9095  ast_cli(a->fd, "RTP Packet Debugging Disabled\n");
9096  return CLI_SUCCESS;
9097  }
9098  } else if (a->argc == e->args +1) { /* ip */
9099  return rtp_do_debug_ip(a);
9100  }
9101 
9102  return CLI_SHOWUSAGE; /* default, failure */
9103 }
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category&#39;s sublevel.
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
static struct ast_sockaddr rtpdebugaddr
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_LOG_CATEGORY_DISABLED
char * command
Definition: cli.h:186
static char * rtp_do_debug_ip(struct ast_cli_args *a)
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_LOG_CATEGORY_RTP_PACKET
Definition: rtp_engine.h:2826
#define AST_LOG_CATEGORY_ENABLED

◆ handle_cli_rtp_settings()

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

Definition at line 9106 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dtmftimeout, ast_cli_args::fd, icesupport, learning_min_sequential, NULL, rtpend, rtpstart, srtp_replay_protection, strictrtp, and ast_cli_entry::usage.

9107 {
9108  switch (cmd) {
9109  case CLI_INIT:
9110  e->command = "rtp show settings";
9111  e->usage =
9112  "Usage: rtp show settings\n"
9113  " Display RTP configuration settings\n";
9114  return NULL;
9115  case CLI_GENERATE:
9116  return NULL;
9117  }
9118 
9119  if (a->argc != 3) {
9120  return CLI_SHOWUSAGE;
9121  }
9122 
9123  ast_cli(a->fd, "\n\nGeneral Settings:\n");
9124  ast_cli(a->fd, "----------------\n");
9125  ast_cli(a->fd, " Port start: %d\n", rtpstart);
9126  ast_cli(a->fd, " Port end: %d\n", rtpend);
9127 #ifdef SO_NO_CHECK
9128  ast_cli(a->fd, " Checksums: %s\n", AST_CLI_YESNO(nochecksums == 0));
9129 #endif
9130  ast_cli(a->fd, " DTMF Timeout: %d\n", dtmftimeout);
9131  ast_cli(a->fd, " Strict RTP: %s\n", AST_CLI_YESNO(strictrtp));
9132 
9133  if (strictrtp) {
9134  ast_cli(a->fd, " Probation: %d frames\n", learning_min_sequential);
9135  }
9136 
9137  ast_cli(a->fd, " Replay Protect: %s\n", AST_CLI_YESNO(srtp_replay_protection));
9138 #ifdef HAVE_PJPROJECT
9139  ast_cli(a->fd, " ICE support: %s\n", AST_CLI_YESNO(icesupport));
9140 #endif
9141  return CLI_SUCCESS;
9142 }
static int icesupport
static int rtpstart
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static int dtmftimeout
const int fd
Definition: cli.h:159
static int srtp_replay_protection
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int strictrtp
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static int learning_min_sequential
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
static int rtpend

◆ host_candidate_overrides_clear()

static void host_candidate_overrides_clear ( void  )
static

Helper function which clears the ICE host candidate mapping.

Definition at line 735 of file res_rtp_asterisk.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and ast_rtp_ioqueue_thread::next.

Referenced by rtp_reload(), and unload_module().

736 {
737  struct ast_ice_host_candidate *candidate;
738 
742  ast_free(candidate);
743  }
746 }
List of ICE host candidate mappings.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
Structure which contains ICE host candidate mapping information.
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ice_candidate_cmp()

static int ice_candidate_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 806 of file res_rtp_asterisk.c.

References ast_rtp_engine_ice_candidate::address, ast_sockaddr_cmp(), CMP_MATCH, CMP_STOP, ast_rtp_engine_ice_candidate::foundation, ast_rtp_engine_ice_candidate::id, and ast_rtp_engine_ice_candidate::type.

Referenced by ast_rtp_ice_add_cand(), and ast_rtp_ice_add_remote_candidate().

807 {
808  struct ast_rtp_engine_ice_candidate *candidate1 = obj, *candidate2 = arg;
809 
810  if (strcmp(candidate1->foundation, candidate2->foundation) ||
811  candidate1->id != candidate2->id ||
812  candidate1->type != candidate2->type ||
813  ast_sockaddr_cmp(&candidate1->address, &candidate2->address)) {
814  return 0;
815  }
816 
817  return CMP_MATCH | CMP_STOP;
818 }
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
Structure for an ICE candidate.
Definition: rtp_engine.h:474
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:481
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:476
struct ast_sockaddr address
Definition: rtp_engine.h:479

◆ ice_candidates_compare()

static int ice_candidates_compare ( struct ao2_container left,
struct ao2_container right 
)
static

Definition at line 1003 of file res_rtp_asterisk.c.

References ao2_container_count(), ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, and OBJ_POINTER.

Referenced by ast_rtp_ice_start().

1004 {
1005  struct ao2_iterator i;
1006  struct ast_rtp_engine_ice_candidate *right_candidate;
1007 
1008  if (ao2_container_count(left) != ao2_container_count(right)) {
1009  return -1;
1010  }
1011 
1012  i = ao2_iterator_init(right, 0);
1013  while ((right_candidate = ao2_iterator_next(&i))) {
1014  struct ast_rtp_engine_ice_candidate *left_candidate = ao2_find(left, right_candidate, OBJ_POINTER);
1015 
1016  if (!left_candidate) {
1017  ao2_ref(right_candidate, -1);
1019  return -1;
1020  }
1021 
1022  ao2_ref(left_candidate, -1);
1023  ao2_ref(right_candidate, -1);
1024  }
1026 
1027  return 0;
1028 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define OBJ_POINTER
Definition: astobj2.h:1154
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Structure for an ICE candidate.
Definition: rtp_engine.h:474
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ ice_create()

static int ice_create ( struct ast_rtp_instance instance,
struct ast_sockaddr addr,
int  port,
int  replace 
)
static

Definition at line 3750 of file res_rtp_asterisk.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_debug_ice, AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_ice_stop(), ast_rtp_instance_get_data(), ast_sockaddr_port, cachingpool, ice_wrap_dtor(), NULL, pj_thread_register_check(), ice_wrap::real_ice, rtp_add_candidates_to_ice(), status, stun_software_attribute, timer_heap, TRANSPORT_SOCKET_RTCP, and TRANSPORT_SOCKET_RTP.

Referenced by ice_reset_session(), pj_thread_register_check(), and rtp_allocate_transport().

3752 {
3753  pj_stun_config stun_config;
3754  pj_str_t ufrag, passwd;
3755  pj_status_t status;
3756  struct ice_wrap *ice_old;
3757  struct ice_wrap *ice;
3758  pj_ice_sess *real_ice = NULL;
3759  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3760 
3761  ao2_cleanup(rtp->ice_local_candidates);
3762  rtp->ice_local_candidates = NULL;
3763 
3764  ast_debug_ice(2, "(%p) ICE create%s\n", instance, replace ? " and replace" : "");
3765 
3767  if (!ice) {
3768  ast_rtp_ice_stop(instance);
3769  return -1;
3770  }
3771 
3773 
3774  pj_stun_config_init(&stun_config, &cachingpool.factory, 0, NULL, timer_heap);
3775  if (!stun_software_attribute) {
3776  stun_config.software_name = pj_str(NULL);
3777  }
3778 
3779  ufrag = pj_str(rtp->local_ufrag);
3780  passwd = pj_str(rtp->local_passwd);
3781 
3782  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3783  ao2_unlock(instance);
3784  /* Create an ICE session for ICE negotiation */
3785  status = pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN,
3786  rtp->ice_num_components, &ast_rtp_ice_sess_cb, &ufrag, &passwd, NULL, &real_ice);
3787  ao2_lock(instance);
3788  if (status == PJ_SUCCESS) {
3789  /* Safely complete linking the ICE session into the instance */
3790  real_ice->user_data = instance;
3791  ice->real_ice = real_ice;
3792  ice_old = rtp->ice;
3793  rtp->ice = ice;
3794  if (ice_old) {
3795  ao2_unlock(instance);
3796  ao2_ref(ice_old, -1);
3797  ao2_lock(instance);
3798  }
3799 
3800  /* Add all of the available candidates to the ICE session */
3801  rtp_add_candidates_to_ice(instance, rtp, addr, port, AST_RTP_ICE_COMPONENT_RTP,
3803 
3804  /* Only add the RTCP candidates to ICE when replacing the session and if
3805  * the ICE session contains more than just an RTP component. New sessions
3806  * handle this in a separate part of the setup phase */
3807  if (replace && rtp->rtcp && rtp->ice_num_components > 1) {
3808  rtp_add_candidates_to_ice(instance, rtp, &rtp->rtcp->us,
3811  }
3812 
3813  return 0;
3814  }
3815 
3816  /*
3817  * It is safe to unref this while instance is locked here.
3818  * It was not initialized with a real_ice pointer.
3819  */
3820  ao2_ref(ice, -1);
3821 
3822  ast_rtp_ice_stop(instance);
3823  return -1;
3824 
3825 }
RTP session description.
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static void ice_wrap_dtor(void *vdoomed)
ao2 ICE wrapper object destructor.
static int stun_software_attribute
static pj_ice_sess_cb ast_rtp_ice_sess_cb
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static void ast_rtp_ice_stop(struct ast_rtp_instance *instance)
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_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
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)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#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 replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:790
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define TRANSPORT_SOCKET_RTCP
static pj_timer_heap_t * timer_heap
Global timer heap.
pj_ice_sess * real_ice
jack_status_t status
Definition: app_jack.c:146
#define TRANSPORT_SOCKET_RTP

◆ ice_reset_session()

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

Definition at line 959 of file res_rtp_asterisk.c.

References ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, ast2pj_rtp_ice_role(), ast_cond_timedwait, ast_debug_ice, ast_rtp_instance_get_data(), ast_samp2tv(), ast_sockaddr_stringify(), ast_tvadd(), ast_tvnow(), ice_create(), and TURN_STATE_WAIT_TIME.

Referenced by ast_rtp_ice_change_components(), and ast_rtp_ice_start().

960 {
961  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
962  int res;
963 
964  ast_debug_ice(3, "(%p) ICE resetting\n", instance);
965  if (!rtp->ice->real_ice->is_nominating && !rtp->ice->real_ice->is_complete) {
966  ast_debug_ice(3, " (%p) ICE nevermind, not ready for a reset\n", instance);
967  return 0;
968  }
969 
970  ast_debug_ice(3, "(%p) ICE recreating ICE session %s (%d)\n",
971  instance, ast_sockaddr_stringify(&rtp->ice_original_rtp_addr), rtp->ice_port);
972  res = ice_create(instance, &rtp->ice_original_rtp_addr, rtp->ice_port, 1);
973  if (!res) {
974  /* Use the current expected role for the ICE session */
975  enum pj_ice_sess_role role = PJ_ICE_SESS_ROLE_UNKNOWN;
976  ast2pj_rtp_ice_role(rtp->role, &role);
977  pj_ice_sess_change_role(rtp->ice->real_ice, role);
978  }
979 
980  /* If we only have one component now, and we previously set up TURN for RTCP,
981  * we need to destroy that TURN socket.
982  */
983  if (rtp->ice_num_components == 1 && rtp->turn_rtcp) {
984  struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
985  struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
986 
987  rtp->turn_state = PJ_TURN_STATE_NULL;
988 
989  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
990  ao2_unlock(instance);
991  pj_turn_sock_destroy(rtp->turn_rtcp);
992  ao2_lock(instance);
993  while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
994  ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
995  }
996  }
997 
998  rtp->ice_media_started = 0;
999 
1000  return res;
1001 }
RTP session description.
static void ast2pj_rtp_ice_role(enum ast_rtp_ice_role ast_role, enum pj_ice_sess_role *pj_role)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ao2_lock(a)
Definition: astobj2.h:718
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
#define TURN_STATE_WAIT_TIME
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
#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_create(struct ast_rtp_instance *instance, struct ast_sockaddr *addr, int port, int replace)
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204

◆ ice_wrap_dtor()

static void ice_wrap_dtor ( void *  vdoomed)
static

ao2 ICE wrapper object destructor.

Parameters
vdoomedObject being destroyed.
Note
The associated struct ast_rtp_instance object must not be locked when unreffing the object. Otherwise we could deadlock trying to destroy the PJPROJECT ICE structure.

Definition at line 916 of file res_rtp_asterisk.c.

References pj_thread_register_check(), and ice_wrap::real_ice.

Referenced by ice_create().

917 {
918  struct ice_wrap *ice = vdoomed;
919 
920  if (ice->real_ice) {
922 
923  pj_ice_sess_destroy(ice->real_ice);
924  }
925 }
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...
pj_ice_sess * real_ice

◆ ioqueue_worker_thread()

static int ioqueue_worker_thread ( void *  data)
static

Worker thread for ioqueue and timerheap.

Definition at line 1454 of file res_rtp_asterisk.c.

References ast_rtp_ioqueue_thread::ioqueue, NULL, ast_rtp_ioqueue_thread::terminate, and ast_rtp_ioqueue_thread::timerheap.

Referenced by rtp_ioqueue_thread_get_or_create().

1455 {
1456  struct ast_rtp_ioqueue_thread *ioqueue = data;
1457 
1458  while (!ioqueue->terminate) {
1459  const pj_time_val delay = {0, 10};
1460 
1461  pj_ioqueue_poll(ioqueue->ioqueue, &delay);
1462 
1463  pj_timer_heap_poll(ioqueue->timerheap, NULL);
1464  }
1465 
1466  return 0;
1467 }
Structure which contains ioqueue thread information.
int terminate
Termination request.
#define NULL
Definition: resample.c:96
pj_ioqueue_t * ioqueue
Ioqueue which polls on sockets.
pj_timer_heap_t * timerheap
Timer heap for scheduled items.

◆ load_module()

static int load_module ( void  )
static

Definition at line 9624 of file res_rtp_asterisk.c.

References ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_pjproject_caching_pool_init(), AST_PJPROJECT_INIT_LOG_LEVEL, ast_rtp_engine_register, ast_rtp_engine_unregister(), ast_sockaddr_parse(), cachingpool, lock, NULL, PARSE_PORT_IGNORE, ast_rtp_ioqueue_thread::pool, rtp_reload(), rtp_terminate_pjproject(), timer_heap, timer_thread, and timer_worker_thread().

Referenced by unload_module().

9625 {
9626 #ifdef HAVE_PJPROJECT
9627  pj_lock_t *lock;
9628 
9630 
9632  if (pj_init() != PJ_SUCCESS) {
9633  return AST_MODULE_LOAD_DECLINE;
9634  }
9635 
9636  if (pjlib_util_init() != PJ_SUCCESS) {
9638  return AST_MODULE_LOAD_DECLINE;
9639  }
9640 
9641  if (pjnath_init() != PJ_SUCCESS) {
9643  return AST_MODULE_LOAD_DECLINE;
9644  }
9645 
9646  ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
9647 
9648  pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
9649 
9650  if (pj_timer_heap_create(pool, 100, &timer_heap) != PJ_SUCCESS) {
9652  return AST_MODULE_LOAD_DECLINE;
9653  }
9654 
9655  if (pj_lock_create_recursive_mutex(pool, "rtp%p", &lock) != PJ_SUCCESS) {
9657  return AST_MODULE_LOAD_DECLINE;
9658  }
9659 
9660  pj_timer_heap_set_lock(timer_heap, lock, PJ_TRUE);
9661 
9662  if (pj_thread_create(pool, "timer", &timer_worker_thread, NULL, 0, 0, &timer_thread) != PJ_SUCCESS) {
9664  return AST_MODULE_LOAD_DECLINE;
9665  }
9666 
9667 #endif
9668 
9669 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
9670  dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
9671  if (!dtls_bio_methods) {
9672 #ifdef HAVE_PJPROJECT
9674 #endif
9675  return AST_MODULE_LOAD_DECLINE;
9676  }
9677  BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
9678  BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
9679  BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
9680  BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
9681 #endif
9682 
9684 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
9685  BIO_meth_free(dtls_bio_methods);
9686 #endif
9687 #ifdef HAVE_PJPROJECT
9689 #endif
9690  return AST_MODULE_LOAD_DECLINE;
9691  }
9692 
9694 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
9695  BIO_meth_free(dtls_bio_methods);
9696 #endif
9697 #ifdef HAVE_PJPROJECT
9700 #endif
9701  return AST_MODULE_LOAD_DECLINE;
9702  }
9703 
9704  rtp_reload(0, 0);
9705 
9706  return AST_MODULE_LOAD_SUCCESS;
9707 }
static int rtp_reload(int reload, int by_external_config)
#define ast_rtp_engine_register(engine)
Definition: rtp_engine.h:794
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int timer_worker_thread(void *data)
Worker thread for timerheap.
#define NULL
Definition: resample.c:96
static struct ast_sockaddr lo6
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:364
ast_mutex_t lock
Definition: app_meetme.c:1091
static void rtp_terminate_pjproject(void)
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
static pj_thread_t * timer_thread
Thread executing the timer heap.
#define AST_PJPROJECT_INIT_LOG_LEVEL()
Get maximum log level pjproject was compiled with.
Definition: options.h:166
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_cli_entry cli_rtp[]
static struct ast_rtp_engine asterisk_rtp_engine
static pj_timer_heap_t * timer_heap
Global timer heap.

◆ ntp2timeval()

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

Definition at line 4421 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_interpret().

4422 {
4423  tv->tv_sec = msw - 2208988800u;
4424  /* Reverse the sequence in timeval2ntp() */
4425  tv->tv_usec = ((((lsw >> 7) * 125) >> 7) * 125) >> 12;
4426 }

◆ pj2ast_rtp_ice_role()

static void pj2ast_rtp_ice_role ( enum pj_ice_sess_role  pj_role,
enum ast_rtp_ice_role ast_role 
)
static

Definition at line 939 of file res_rtp_asterisk.c.

References ast_assert, AST_RTP_ICE_ROLE_CONTROLLED, and AST_RTP_ICE_ROLE_CONTROLLING.

Referenced by ast_rtp_ice_start().

940 {
941  switch (pj_role) {
942  case PJ_ICE_SESS_ROLE_CONTROLLED:
943  *ast_role = AST_RTP_ICE_ROLE_CONTROLLED;
944  return;
945  case PJ_ICE_SESS_ROLE_CONTROLLING:
946  *ast_role = AST_RTP_ICE_ROLE_CONTROLLING;
947  return;
948  case PJ_ICE_SESS_ROLE_UNKNOWN:
949  /* Don't change anything */
950  return;
951  default:
952  /* If we aren't explicitly handling something, it's a bug */
953  ast_assert(0);
954  return;
955  }
956 }
#define ast_assert(a)
Definition: utils.h:695

◆ pj_thread_register_check()

static void pj_thread_register_check ( void  )
static

Function used to check if the calling thread is registered with pjlib. If it is not it will be registered.

Definition at line 865 of file res_rtp_asterisk.c.

References ast_log, ast_threadstorage_get(), desc, ice_create(), LOG_ERROR, pj_thread_storage, replace(), and ast_rtp_ioqueue_thread::thread.

Referenced by __rtp_recvfrom(), __rtp_sendto(), ast_rtp_ice_add_cand(), ast_rtp_ice_lite(), ast_rtp_ice_set_role(), ast_rtp_ice_start(), ice_create(), ice_wrap_dtor(), rtp_deallocate_transport(), rtp_terminate_pjproject(), and unload_module().

866 {
867  pj_thread_desc *desc;
868  pj_thread_t *thread;
869 
870  if (pj_thread_is_registered() == PJ_TRUE) {
871  return;
872  }
873 
874  desc = ast_threadstorage_get(&pj_thread_storage, sizeof(pj_thread_desc));
875  if (!desc) {
876  ast_log(LOG_ERROR, "Could not get thread desc from thread-local storage. Expect awful things to occur\n");
877  return;
878  }
879  pj_bzero(*desc, sizeof(*desc));
880 
881  if (pj_thread_register("Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
882  ast_log(LOG_ERROR, "Coudln't register thread with PJLIB.\n");
883  }
884  return;
885 }
pthread_t thread
Definition: app_meetme.c:1089
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
static const char desc[]
Definition: cdr_mysql.c:73
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static struct ast_threadstorage pj_thread_storage

◆ process_cn_rfc3389()

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

Definition at line 5724 of file res_rtp_asterisk.c.

References ast_debug, ast_debug_rtp_packet_is_allowed, ast_format_get_name(), AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_log, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_set_flag, ast_sockaddr_stringify(), ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_3389_WARNING, ast_frame::frametype, ast_frame_subclass::integer, LOG_NOTICE, NULL, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, ast_frame::samples, and ast_frame::subclass.

Referenced by ast_rtp_interpret().

5725 {
5726  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5727 
5728  /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
5729  totally help us out becuase we don't have an engine to keep it going and we are not
5730  guaranteed to have it every 20ms or anything */
5732  ast_debug(0, "- RTP 3389 Comfort noise event: Format %s (len = %d)\n",
5733  ast_format_get_name(rtp->lastrxformat), len);
5734  }
5735 
5736  if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
5737  struct ast_sockaddr remote_address = { {0,} };
5738 
5739  ast_rtp_instance_get_remote_address(instance, &remote_address);
5740 
5741  ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
5742  ast_sockaddr_stringify(&remote_address));
5744  }
5745 
5746  /* Must have at least one byte */
5747  if (!len) {
5748  return NULL;
5749  }
5750  if (len < 24) {
5751  rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
5752  rtp->f.datalen = len - 1;
5753  rtp->f.offset = AST_FRIENDLY_OFFSET;
5754  memcpy(rtp->f.data.ptr, data + 1, len - 1);
5755  } else {
5756  rtp->f.data.ptr = NULL;
5757  rtp->f.offset = 0;
5758  rtp->f.datalen = 0;
5759  }
5760  rtp->f.frametype = AST_FRAME_CNG;
5761  rtp->f.subclass.integer = data[0] & 0x7f;
5762  rtp->f.samples = 0;
5763  rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
5764 
5765  return &rtp->f;
5766 }
RTP session description.
#define FLAG_3389_WARNING
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
struct ast_frame_subclass subclass
unsigned char rawdata[8192+AST_FRIENDLY_OFFSET]
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
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 LOG_NOTICE
Definition: logger.h:263
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 timeval delivery
union ast_frame::@263 data
enum ast_frame_type frametype
#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

◆ process_dtmf_cisco()

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

Definition at line 5644 of file res_rtp_asterisk.c.

References ast_debug, ast_debug_rtp_packet_is_allowed, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_DTMF_COMPENSATE, create_dtmf_frame(), NULL, ast_frame::samples, and seq.

Referenced by ast_rtp_interpret().

5645 {
5646  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5647  unsigned int event, flags, power;
5648  char resp = 0;
5649  unsigned char seq;
5650  struct ast_frame *f = NULL;
5651 
5652  if (len < 4) {
5653  return NULL;
5654  }
5655 
5656  /* The format of Cisco RTP DTMF packet looks like next:
5657  +0 - sequence number of DTMF RTP packet (begins from 1,
5658  wrapped to 0)
5659  +1 - set of flags
5660  +1 (bit 0) - flaps by different DTMF digits delimited by audio
5661  or repeated digit without audio???
5662  +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
5663  then falls to 0 at its end)
5664  +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
5665  Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
5666  by each new packet and thus provides some redudancy.
5667 
5668  Sample of Cisco RTP DTMF packet is (all data in hex):
5669  19 07 00 02 12 02 20 02
5670  showing end of DTMF digit '2'.
5671 
5672  The packets
5673  27 07 00 02 0A 02 20 02
5674  28 06 20 02 00 02 0A 02
5675  shows begin of new digit '2' with very short pause (20 ms) after
5676  previous digit '2'. Bit +1.0 flips at begin of new digit.
5677 
5678  Cisco RTP DTMF packets comes as replacement of audio RTP packets
5679  so its uses the same sequencing and timestamping rules as replaced
5680  audio packets. Repeat interval of DTMF packets is 20 ms and not rely
5681  on audio framing parameters. Marker bit isn't used within stream of
5682  DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
5683  are not sequential at borders between DTMF and audio streams,
5684  */
5685 
5686  seq = data[0];
5687  flags = data[1];
5688  power = data[2];
5689  event = data[3] & 0x1f;
5690 
5692  ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%u, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
5693  if (event < 10) {
5694  resp = '0' + event;
5695  } else if (event < 11) {
5696  resp = '*';
5697  } else if (event < 12) {
5698  resp = '#';
5699  } else if (event < 16) {
5700  resp = 'A' + (event - 12);
5701  } else if (event < 17) {
5702  resp = 'X';
5703  }
5704  if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
5705  rtp->resp = resp;
5706  /* Why we should care on DTMF compensation at reception? */
5708  f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
5709  rtp->dtmfsamples = 0;
5710  }
5711  } else if ((rtp->resp == resp) && !power) {
5713  f->samples = rtp->dtmfsamples * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
5714  rtp->resp = 0;
5715  } else if (rtp->resp == resp) {
5716  rtp->dtmfsamples += 20 * (ast_rtp_get_rate(rtp->lastrxformat) / 1000);
5717  }
5718 
5719  rtp->dtmf_timeout = 0;
5720 
5721  return f;
5722 }
RTP session description.
Definition: astman.c:222
static struct ast_frame * create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
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 len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:2864
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 volatile unsigned int seq
Definition: app_sms.c:120
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.
union ast_frame::@263 data

◆ process_dtmf_rfc2833()

static void process_dtmf_rfc2833 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
int  payloadtype,
int  mark,
struct frame_list frames 
)
static

Definition at line 5506 of file res_rtp_asterisk.c.

References ast_debug, ast_debug_rtp, ast_debug_rtp_packet_is_allowed, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup, AST_LIST_INSERT_TAIL, ast_rtp_get_rate(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), ast_verbose(), create_dtmf_frame(), dtmftimeout, ast_frame_subclass::format, ast_frame::len, NULL, rtp_debug_test_addr(), ast_frame::samples, ast_frame::seqno, and ast_frame::subclass.

Referenced by ast_rtp_interpret().

5507 {
5508  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
5509  struct ast_sockaddr remote_address = { {0,} };
5510  unsigned int event, event_end, samples;
5511  char resp = 0;
5512  struct ast_frame *f = NULL;
5513 
5514  ast_rtp_instance_get_remote_address(instance, &remote_address);
5515 
5516  /* Figure out event, event end, and samples */
5517  event = ntohl(*((unsigned int *)(data)));
5518  event >>= 24;
5519  event_end = ntohl(*((unsigned int *)(data)));
5520  event_end <<= 8;
5521  event_end >>= 24;
5522  samples = ntohl(*((unsigned int *)(data)));
5523  samples &= 0xFFFF;
5524 
5525  if (rtp_debug_test_addr(&remote_address)) {
5526  ast_verbose("Got RTP RFC2833 from %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6d, mark %d, event %08x, end %d, duration %-5.5u) \n",
5527  ast_sockaddr_stringify(&remote_address),
5528  payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
5529  }
5530 
5531  /* Print out debug if turned on */
5533  ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
5534 
5535  /* Figure out what digit was pressed */
5536  if (event < 10) {
5537  resp = '0' + event;
5538  } else if (event < 11) {
5539  resp = '*';
5540  } else if (event < 12) {
5541  resp = '#';
5542  } else if (event < 16) {
5543  resp = 'A' + (event - 12);
5544  } else if (event < 17) { /* Event 16: Hook flash */
5545  resp = 'X';
5546  } else {
5547  /* Not a supported event */
5548  ast_debug_rtp(1, "(%p) RTP ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", instance, event);
5549  return;
5550  }
5551 
5553  if (!rtp->last_end_timestamp.is_set || rtp->last_end_timestamp.ts != timestamp || (rtp->resp && rtp->resp != resp)) {
5554  rtp->resp = resp;
5555  rtp->dtmf_timeout = 0;
5557  f->len = 0;
5558  rtp->last_end_timestamp.ts = timestamp;
5559  rtp->last_end_timestamp.is_set = 1;
5560  AST_LIST_INSERT_TAIL(frames, f, frame_list);
5561  }
5562  } else {
5563  /* The duration parameter measures the complete
5564  duration of the event (from the beginning) - RFC2833.
5565  Account for the fact that duration is only 16 bits long
5566  (about 8 seconds at 8000 Hz) and can wrap is digit
5567  is hold for too long. */
5568  unsigned int new_duration = rtp->dtmf_duration;
5569  unsigned int last_duration = new_duration & 0xFFFF;
5570 
5571  if (last_duration > 64000 && samples < last_duration) {
5572  new_duration += 0xFFFF + 1;
5573  }
5574  new_duration = (new_duration & ~0xFFFF) | samples;
5575 
5576  if (event_end & 0x80) {
5577  /* End event */
5578  if (rtp->last_seqno != seqno && (!rtp->last_end_timestamp.is_set || timestamp > rtp->last_end_timestamp.ts)) {
5579  rtp->last_end_timestamp.ts = timestamp;
5580  rtp->last_end_timestamp.is_set = 1;
5581  rtp->dtmf_duration = new_duration;
5582  rtp->resp = resp;
5583  f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
5584  f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, ast_rtp_get_rate(f->subclass.format)), ast_tv(0, 0));
5585  rtp->resp = 0;
5586  rtp->dtmf_duration = rtp->dtmf_timeout = 0;
5587  AST_LIST_INSERT_TAIL(frames, f, frame_list);
5588  } else if (ast_debug_rtp_packet_is_allowed) {
5589  ast_debug_rtp(1, "(%p) RTP dropping duplicate or out of order DTMF END frame (seqno: %u, ts %u, digit %c)\n",
5590  instance, seqno, timestamp, resp);
5591  }
5592  } else {
5593  /* Begin/continuation */
5594 
5595  /* The second portion of the seqno check is to not mistakenly
5596  * stop accepting DTMF if the seqno rolls over beyond
5597  * 65535.
5598  */
5599  if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
5600  || (rtp->last_end_timestamp.is_set
5601  && timestamp <= rtp->last_end_timestamp.ts)) {
5602  /* Out of order frame. Processing this can cause us to
5603  * improperly duplicate incoming DTMF, so just drop
5604  * this.
5605  */
5607  ast_debug(0, "Dropping out of order DTMF frame (seqno %u, ts %u, digit %c)\n",
5608  seqno, timestamp, resp);
5609  }
5610  return;
5611  }
5612 
5613  if (rtp->resp && rtp->resp != resp) {
5614  /* Another digit already began. End it */
5615  f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
5616  f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, ast_rtp_get_rate(f->subclass.format)), ast_tv(0, 0));
5617  rtp->resp = 0;
5618  rtp->dtmf_duration = rtp->dtmf_timeout = 0;
5619  AST_LIST_INSERT_TAIL(frames, f, frame_list);
5620  }
5621 
5622  if (rtp->resp) {
5623  /* Digit continues */
5624  rtp->dtmf_duration = new_duration;
5625  } else {
5626  /* New digit began */
5627  rtp->resp = resp;
5629  rtp->dtmf_duration = samples;
5630  AST_LIST_INSERT_TAIL(frames, f, frame_list);
5631  }
5632 
5633  rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
5634  }
5635 
5636  rtp->last_seqno = seqno;
5637  }
5638 
5639  rtp->dtmfsamples = samples;
5640 
5641  return;
5642 }
RTP session description.
#define ast_frdup(fr)
Copies a frame.
Definition: astman.c:222
static struct ast_frame * create_dtmf_frame(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
#define NULL
Definition: resample.c:96
static int dtmftimeout
Socket address structure.
Definition: netsock2.h:97
struct ast_frame_subclass subclass
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
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 AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
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
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 timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
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.
union ast_frame::@263 data
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

◆ put_unaligned_time24()

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

Definition at line 4876 of file res_rtp_asterisk.c.

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

4877 {
4878  unsigned char *cp = p;
4879  uint32_t datum;
4880 
4881  /* Convert the time to 6.18 format */
4882  datum = (time_msw << 18) & 0x00fc0000;
4883  datum |= (time_lsw >> 14) & 0x0003ffff;
4884 
4885  cp[0] = datum >> 16;
4886  cp[1] = datum >> 8;
4887  cp[2] = datum;
4888 }
Definition: ndbm.h:57

◆ red_t140_to_red()

static struct ast_frame* red_t140_to_red ( struct rtp_red red)
static

Definition at line 5120 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_write().

5121 {
5122  unsigned char *data = red->t140red.data.ptr;
5123  int len = 0;
5124  int i;
5125 
5126  /* replace most aged generation */
5127  if (red->len[0]) {
5128  for (i = 1; i < red->num_gen+1; i++)
5129  len += red->len[i];
5130 
5131  memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
5132  }
5133 
5134  /* Store length of each generation and primary data length*/
5135  for (i = 0; i < red->num_gen; i++)
5136  red->len[i] = red->len[i+1];
5137  red->len[i] = red->t140.datalen;
5138 
5139  /* write each generation length in red header */
5140  len = red->hdrlen;
5141  for (i = 0; i < red->num_gen; i++) {
5142  len += data[i*4+3] = red->len[i];
5143  }
5144 
5145  /* add primary data to buffer */
5146  memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
5147  red->t140red.datalen = len + red->t140.datalen;
5148 
5149  /* no primary data and no generations to send */
5150  if (len == red->hdrlen && !red->t140.datalen) {
5151  return NULL;
5152  }
5153 
5154  /* reset t.140 buffer */
5155  red->t140.datalen = 0;
5156 
5157  return &red->t140red;
5158 }
#define NULL
Definition: resample.c:96
struct ast_frame t140red
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_frame t140
unsigned char len[AST_RED_MAX_GENERATION]
union ast_frame::@263 data

◆ red_write()

static int red_write ( const void *  data)
static

Write t140 redundacy frame.

Parameters
dataprimary data to be buffered

Scheduler callback

Definition at line 8560 of file res_rtp_asterisk.c.

References ao2_lock, ao2_unlock, ast_rtp_instance_get_data(), and ast_rtp_write().

Referenced by rtp_red_init().

8561 {
8562  struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
8563  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8564 
8565  ao2_lock(instance);
8566  if (rtp->red->t140.datalen > 0) {
8567  ast_rtp_write(instance, &rtp->red->t140);
8568  }
8569  ao2_unlock(instance);
8570 
8571  return 1;
8572 }
RTP session description.
#define ao2_unlock(a)
Definition: astobj2.h:730
static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
#define ao2_lock(a)
Definition: astobj2.h:718
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 9592 of file res_rtp_asterisk.c.

References rtp_reload().

Referenced by unload_module().

9593 {
9594  rtp_reload(1, 0);
9595  return 0;
9596 }
static int rtp_reload(int reload, int by_external_config)

◆ rtcp_debug_test_addr()

static int rtcp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2762 of file res_rtp_asterisk.c.

References ast_srtp_policy_res::alloc, ao2_lock, ao2_ref, ao2_unlock, ast_assert, ast_debug_dtls, ast_debug_rtcp_packet_is_allowed, ast_log, AST_RTP_DTLS_HASH_SHA1, AST_RTP_DTLS_HASH_SHA256, AST_RTP_DTLS_SETUP_ACTIVE, AST_RTP_DTLS_VERIFY_FINGERPRINT, ast_rtp_instance_add_srtp_policy(), ast_rtp_instance_get_data(), ast_rtp_instance_get_ssrc(), ast_sched_add(), AST_SCHED_DEL_UNREF, ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_srtp_policy_res::destroy, error(), rtp_ssrc_mapping::instance, LOG_ERROR, LOG_WARNING, NULL, rtcpdebugaddr, rtcpdebugport, ast_srtp_policy_res::set_master_key, ast_srtp_policy_res::set_ssrc, ast_srtp_policy_res::set_suite, SRTP_MASTER_KEY_LEN, SRTP_MASTER_LEN, SRTP_MASTER_SALT_LEN, ast_rtp::ssrc, timeout, and type.

Referenced by ast_rtcp_calculate_sr_rr_statistics(), and ast_rtcp_interpret().

2763 {
2765  return 0;
2766  }
2768  if (rtcpdebugport) {
2769  return (ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0); /* look for RTCP packets from IP+Port */
2770  } else {
2771  return (ast_sockaddr_cmp_addr(&rtcpdebugaddr, addr) == 0); /* only look for RTCP packets from IP */
2772  }
2773  }
2774 
2775  return 1;
2776 }
static int rtcpdebugport
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413
static int 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
static struct ast_sockaddr rtcpdebugaddr
#define ast_debug_rtcp_packet_is_allowed
Definition: rtp_engine.h:2877

◆ rtcp_do_debug_ip()

static char* rtcp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9055 of file res_rtp_asterisk.c.

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

Referenced by handle_cli_rtcp_set_debug().

9056 {
9057  char *arg = ast_strdupa(a->argv[4]);
9058  char *debughost = NULL;
9059  char *debugport = NULL;
9060 
9061  if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9062  ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9063  return CLI_FAILURE;
9064  }
9065  rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9066  ast_cli(a->fd, "RTCP Packet Debugging Enabled for address: %s\n",
9069  return CLI_SUCCESS;
9070 }
static int rtcpdebugport
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category&#39;s sublevel.
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition: netsock2.c:164
const int fd
Definition: cli.h:159
static struct ast_sockaddr rtcpdebugaddr
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char *const * argv
Definition: cli.h:161
#define AST_LOG_CATEGORY_RTCP_PACKET
Definition: rtp_engine.h:2830
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define CLI_FAILURE
Definition: cli.h:46
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_LOG_CATEGORY_ENABLED

◆ rtcp_mux()

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

Definition at line 3050 of file res_rtp_asterisk.c.

References AST_RTP_INSTANCE_RTCP_MUX, and version.

Referenced by ast_rtp_read().

3051 {
3052  uint8_t version;
3053  uint8_t pt;
3054  uint8_t m;
3055 
3056  if (!rtp->rtcp || rtp->rtcp->type != AST_RTP_INSTANCE_RTCP_MUX) {
3057  return 0;
3058  }
3059 
3060  version = (packet[0] & 0XC0) >> 6;
3061  if (version == 0) {
3062  /* version 0 indicates this is a STUN packet and shouldn't
3063  * be interpreted as a possible RTCP packet
3064  */
3065  return 0;
3066  }
3067 
3068  /* The second octet of a packet will be one of the following:
3069  * For RTP: The marker bit (1 bit) and the RTP payload type (7 bits)
3070  * For RTCP: The payload type (8)
3071  *
3072  * RTP has a forbidden range of payload types (64-95) since these
3073  * will conflict with RTCP payload numbers if the marker bit is set.
3074  */
3075  m = packet[1] & 0x80;
3076  pt = packet[1] & 0x7F;
3077  if (m && pt >= 64 && pt <= 95) {
3078  return 1;
3079  }
3080  return 0;
3081 }
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391

◆ rtcp_payload_subtype2str()

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

Definition at line 5942 of file res_rtp_asterisk.c.

References AST_RTP_RTCP_FMT_NACK, AST_RTP_RTCP_FMT_REMB, AST_RTP_RTCP_RTPFB, NULL, and RTCP_PT_PSFB.

Referenced by ast_rtcp_interpret().

5943 {
5944  switch (pt) {
5945  case AST_RTP_RTCP_RTPFB:
5946  if (subtype == AST_RTP_RTCP_FMT_NACK) {
5947  return "NACK";
5948  }
5949  break;
5950  case RTCP_PT_PSFB:
5951  if (subtype == AST_RTP_RTCP_FMT_REMB) {
5952  return "REMB";
5953  }
5954  break;
5955  default:
5956  break;
5957  }
5958 
5959  return NULL;
5960 }
#define AST_RTP_RTCP_FMT_NACK
Definition: rtp_engine.h:303
#define NULL
Definition: resample.c:96
#define AST_RTP_RTCP_RTPFB
Definition: rtp_engine.h:297
#define RTCP_PT_PSFB
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:309

◆ rtcp_payload_type2str()

static const char* rtcp_payload_type2str ( unsigned int  pt)
static

Definition at line 5910 of file res_rtp_asterisk.c.

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

Referenced by ast_rtcp_interpret().

5911 {
5912  const char *str;
5913 
5914  switch (pt) {
5915  case RTCP_PT_SR:
5916  str = "Sender Report";
5917  break;
5918  case RTCP_PT_RR:
5919  str = "Receiver Report";
5920  break;
5921  case RTCP_PT_FUR:
5922  /* Full INTRA-frame Request / Fast Update Request */
5923  str = "H.261 FUR";
5924  break;
5925  case RTCP_PT_PSFB:
5926  /* Payload Specific Feed Back */
5927  str = "PSFB";
5928  break;
5929  case RTCP_PT_SDES:
5930  str = "Source Description";
5931  break;
5932  case RTCP_PT_BYE:
5933  str = "BYE";
5934  break;
5935  default:
5936  str = "Unknown";
5937  break;
5938  }
5939  return str;
5940 }
#define RTCP_PT_SR
const char * str
Definition: app_jack.c:147
#define RTCP_PT_RR
#define RTCP_PT_FUR
#define RTCP_PT_SDES
#define RTCP_PT_BYE
#define RTCP_PT_PSFB

◆ rtcp_recvfrom()

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

Definition at line 3235 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtcp_read().

3236 {
3237  return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
3238 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)

◆ rtcp_sendto()

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

Definition at line 3303 of file res_rtp_asterisk.c.

References __rtp_sendto().

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

3304 {
3305  return __rtp_sendto(instance, buf, size, flags, sa, 1, ice, 1);
3306 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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)

◆ rtp_add_candidates_to_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
Precondition
instance is locked

Definition at line 3522 of file res_rtp_asterisk.c.

References ast_rtp_engine_ice_candidate::address, ast_ice_host_candidate::advertised, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_debug_category, AST_DEBUG_CATEGORY_ICE, AST_DEBUG_CATEGORY_STUN, ast_debug_ice, ast_inet_ntoa(), AST_LIST_TRAVERSE, ast_log, ast_rtp_ice_add_cand(), AST_RTP_ICE_COMPONENT_RTCP, AST_RTP_ICE_COMPONENT_RTP, ast_rtp_ice_turn_request(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_from_sockaddr, ast_sockaddr_is_any(), ast_sockaddr_is_ipv4(), ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_sockaddr_to_pj_sockaddr(), ast_strdupa, ast_stun_request(), AST_TRANSPORT_TCP, AST_TRANSPORT_UDP, ast_rtp_ioqueue_thread::count, errno, ext, if(), ast_ice_host_candidate::include_local, ast_ice_host_candidate::local, LOG_ERROR, ast_rtp_ioqueue_thread::next, NULL, rtp_address_is_ice_blacklisted(), ast_rtp::s, stun_address_is_blacklisted(), stunaddr, turnaddr, turnpassword, turnport, and turnusername.

Referenced by ast_rtp_prop_set(), and ice_create().

3524 {
3525  unsigned int count = 0;
3526  struct ifaddrs *ifa, *ia;
3527  struct ast_sockaddr tmp;
3528  pj_sockaddr pjtmp;
3529  struct ast_ice_host_candidate *candidate;
3530  int af_inet_ok = 0, af_inet6_ok = 0;
3531 
3532  if (ast_sockaddr_is_ipv4(addr)) {
3533  af_inet_ok = 1;
3534  } else if (ast_sockaddr_is_any(addr)) {
3535  af_inet_ok = af_inet6_ok = 1;
3536  } else {
3537  af_inet6_ok = 1;
3538  }
3539 
3540  if (getifaddrs(&ifa) < 0) {
3541  /* If we can't get addresses, we can't load ICE candidates */
3542  ast_log(LOG_ERROR, "(%p) ICE Error obtaining list of local addresses: %s\n",
3543  instance, strerror(errno));
3544  } else {
3545  ast_debug_ice(2, "(%p) ICE add system candidates\n", instance);
3546  /* Iterate through the list of addresses obtained from the system,
3547  * until we've iterated through all of them, or accepted
3548  * PJ_ICE_MAX_CAND candidates */
3549  for (ia = ifa; ia && count < PJ_ICE_MAX_CAND; ia = ia->ifa_next) {
3550  /* Interface is either not UP or doesn't have an address assigned,
3551  * eg, a ppp that just completed LCP but no IPCP yet */
3552  if (!ia->ifa_addr || (ia->ifa_flags & IFF_UP) == 0) {
3553  continue;
3554  }
3555 
3556  /* Filter out non-IPvX addresses, eg, link-layer */
3557  if (ia->ifa_addr->sa_family != AF_INET && ia->ifa_addr->sa_family != AF_INET6) {
3558  continue;
3559  }
3560 
3561  ast_sockaddr_from_sockaddr(&tmp, ia->ifa_addr);
3562 
3563  if (ia->ifa_addr->sa_family == AF_INET) {
3564  const struct sockaddr_in *sa_in = (struct sockaddr_in*)ia->ifa_addr;
3565  if (!af_inet_ok) {
3566  continue;
3567  }
3568 
3569  /* Skip 127.0.0.0/8 (loopback) */
3570  /* Don't use IFF_LOOPBACK check since one could assign usable
3571  * publics to the loopback */
3572  if ((sa_in->sin_addr.s_addr & htonl(0xFF000000)) == htonl(0x7F000000)) {
3573  continue;
3574  }
3575 
3576  /* Skip 0.0.0.0/8 based on RFC1122, and from pjproject */
3577  if ((sa_in->sin_addr.s_addr & htonl(0xFF000000)) == 0) {
3578  continue;
3579  }
3580  } else { /* ia->ifa_addr->sa_family == AF_INET6 */
3581  if (!af_inet6_ok) {
3582  continue;
3583  }
3584 
3585  /* Filter ::1 */
3586  if (!ast_sockaddr_cmp_addr(&lo6, &tmp)) {
3587  continue;
3588  }
3589  }
3590 
3591  /* Pull in the host candidates from [ice_host_candidates] */
3593  AST_LIST_TRAVERSE(&host_candidates, candidate, next) {
3594  if (!ast_sockaddr_cmp(&candidate->local, &tmp)) {
3595  /* candidate->local matches actual assigned, so check if
3596  * advertised is blacklisted, if not, add it to the
3597  * advertised list. Not that it would make sense to remap
3598  * a local address to a blacklisted address, but honour it
3599  * anyway. */
3600  if (!rtp_address_is_ice_blacklisted(&candidate->advertised)) {
3601  ast_sockaddr_to_pj_sockaddr(&candidate->advertised, &pjtmp);
3602  pj_sockaddr_set_port(&pjtmp, port);
3603  ast_rtp_ice_add_cand(instance, rtp, component, transport,
3604  PJ_ICE_CAND_TYPE_HOST, 65535, &pjtmp, &pjtmp, NULL,
3605  pj_sockaddr_get_len(&pjtmp));
3606  ++count;
3607  }
3608 
3609  if (!candidate->include_local) {
3610  /* We don't want to advertise the actual address */
3612  }
3613 
3614  break;
3615  }
3616  }
3618 
3619  /* we had an entry in [ice_host_candidates] that matched, and
3620  * didn't have include_local_address set. Alternatively, adding
3621  * that match resulted in us going to PJ_ICE_MAX_CAND */
3622  if (ast_sockaddr_isnull(&tmp) || count == PJ_ICE_MAX_CAND) {
3623  continue;
3624  }
3625 
3627  continue;
3628  }
3629 
3630  ast_sockaddr_to_pj_sockaddr(&tmp, &pjtmp);
3631  pj_sockaddr_set_port(&pjtmp, port);
3632  ast_rtp_ice_add_cand(instance, rtp, component, transport,
3633  PJ_ICE_CAND_TYPE_HOST, 65535, &pjtmp, &pjtmp, NULL,
3634  pj_sockaddr_get_len(&pjtmp));
3635  ++count;
3636  }
3637  freeifaddrs(ifa);
3638  }
3639 
3640  /* If configured to use a STUN server to get our external mapped address do so */
3641  if (stunaddr.sin_addr.s_addr && !stun_address_is_blacklisted(addr) &&
3642  (ast_sockaddr_is_ipv4(addr) || ast_sockaddr_is_any(addr)) &&
3643  count < PJ_ICE_MAX_CAND) {
3644  struct sockaddr_in answer;
3645  int rsp;
3646 
3648  "(%p) ICE request STUN %s %s candidate\n", instance,
3649  transport == AST_TRANSPORT_UDP ? "UDP" : "TCP",
3650  component == AST_RTP_ICE_COMPONENT_RTP ? "RTP" : "RTCP");
3651 
3652  /*
3653  * The instance should not be locked because we can block
3654  * waiting for a STUN respone.
3655  */
3656  ao2_unlock(instance);
3657  rsp = ast_stun_request(component == AST_RTP_ICE_COMPONENT_RTCP
3658  ? rtp->rtcp->s : rtp->s, &stunaddr, NULL, &answer);
3659  ao2_lock(instance);
3660  if (!rsp) {
3661  struct ast_rtp_engine_ice_candidate *candidate;
3662  pj_sockaddr ext, base;
3663  pj_str_t mapped = pj_str(ast_strdupa(ast_inet_ntoa(answer.sin_addr)));
3664  int srflx = 1, baseset = 0;
3665  struct ao2_iterator i;
3666 
3667  pj_sockaddr_init(pj_AF_INET(), &ext, &mapped, ntohs(answer.sin_port));
3668 
3669  /*
3670  * If the returned address is the same as one of our host
3671  * candidates, don't send the srflx. At the same time,
3672  * we need to set the base address (raddr).
3673  */
3674  i = ao2_iterator_init(rtp->ice_local_candidates, 0);
3675  while (srflx && (candidate = ao2_iterator_next(&i))) {
3676  if (!baseset && ast_sockaddr_is_ipv4(&candidate->address)) {
3677  baseset = 1;
3678  ast_sockaddr_to_pj_sockaddr(&candidate->address, &base);
3679  }
3680 
3681  if (!pj_sockaddr_cmp(&candidate->address, &ext)) {
3682  srflx = 0;
3683  }
3684 
3685  ao2_ref(candidate, -1);
3686  }
3688 
3689  if (srflx && baseset) {
3690  pj_sockaddr_set_port(&base, port);
3691  ast_rtp_ice_add_cand(instance, rtp, component, transport,
3692  PJ_ICE_CAND_TYPE_SRFLX, 65535, &ext, &base, &base,
3693  pj_sockaddr_get_len(&ext));
3694  }
3695  }
3696  }
3697 
3698  /* If configured to use a TURN relay create a session and allocate */
3699  if (pj_strlen(&turnaddr)) {
3700  ast_rtp_ice_turn_request(instance, component, AST_TRANSPORT_TCP, pj_strbuf(&turnaddr), turnport,
3701  pj_strbuf(&turnusername), pj_strbuf(&turnpassword));
3702  }
3703 }
struct ast_sockaddr local
#define ast_debug_category(sublevel, ids,...)
Log for a debug category.
List of ICE host candidate mappings.
#define AST_DEBUG_CATEGORY_STUN
Definition: stun.h:44
static int tmp()
Definition: bt_open.c:389
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
int ast_sockaddr_to_pj_sockaddr(const struct ast_sockaddr *addr, pj_sockaddr *pjaddr)
Fill a pj_sockaddr from an ast_sockaddr.
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
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
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
const char * ext
Definition: http.c:147
Structure for an ICE candidate.
Definition: rtp_engine.h:474
Socket address structure.
Definition: netsock2.h:97
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413
static struct ast_sockaddr lo6
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
static int turnport
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_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_log
Definition: astobj2.c:42
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition: netsock2.c:534
static struct sockaddr_in stunaddr
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
Definition: stun.c:384
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int answer(void *data)
Definition: chan_pjsip.c:682
#define AST_DEBUG_CATEGORY_ICE
Definition: rtp_engine.h:2852
#define LOG_ERROR
Definition: logger.h:285
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)
#define ast_sockaddr_from_sockaddr(addr, sa)
Converts a struct sockaddr to a struct ast_sockaddr.
Definition: netsock2.h:824
static int stun_address_is_blacklisted(const struct ast_sockaddr *addr)
int errno
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
static int rtp_address_is_ice_blacklisted(const struct ast_sockaddr *address)
struct ast_sockaddr advertised
static pj_str_t turnaddr
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
static pj_str_t turnpassword
Structure which contains ICE host candidate mapping information.
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
struct ast_sockaddr address
Definition: rtp_engine.h:479
static pj_str_t turnusername
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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)

◆ rtp_address_is_ice_blacklisted()

static int rtp_address_is_ice_blacklisted ( const struct ast_sockaddr address)
static

Definition at line 3487 of file res_rtp_asterisk.c.

References ast_apply_acl_nolog(), ast_rwlock_rdlock, ast_rwlock_unlock, AST_SENSE_DENY, and result.

Referenced by rtp_add_candidates_to_ice().

3488 {
3489  int result = 0;
3490 
3492  result |= ast_apply_acl_nolog(ice_acl, address) == AST_SENSE_DENY;
3494 
3495  return result;
3496 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
enum ast_acl_sense ast_apply_acl_nolog(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address, don&#39;t log failure.
Definition: acl.c:804
#define ast_rwlock_unlock(a)
Definition: lock.h:232
static struct ast_acl_list * ice_acl
static ast_rwlock_t ice_acl_lock
static PGresult * result
Definition: cel_pgsql.c:88

◆ rtp_allocate_transport()

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

Definition at line 3828 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_bundle(), and ast_rtp_new().

3829 {
3830  int x, startplace;
3831 
3832  rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_CLOSED : STRICT_RTP_OPEN);
3833 
3834  /* Create a new socket for us to listen on and use */
3835  if ((rtp->s =
3836  create_new_socket("RTP",
3837  ast_sockaddr_is_ipv4(&rtp->bind_address) ? AF_INET :
3838  ast_sockaddr_is_ipv6(&rtp->bind_address) ? AF_INET6 : -1)) < 0) {
3839  ast_log(LOG_WARNING, "Failed to create a new socket for RTP instance '%p'\n", instance);
3840  return -1;
3841  }
3842 
3843  /* Now actually find a free RTP port to use */
3844  x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
3845  x = x & ~1;
3846  startplace = x;
3847 
3848  for (;;) {
3849  ast_sockaddr_set_port(&rtp->bind_address, x);
3850  /* Try to bind, this will tell us whether the port is available or not */
3851  if (!ast_bind(rtp->s, &rtp->bind_address)) {
3852  ast_debug_rtp(1, "(%p) RTP allocated port %d\n", instance, x);
3853  ast_rtp_instance_set_local_address(instance, &rtp->bind_address);
3854  ast_test_suite_event_notify("RTP_PORT_ALLOCATED", "Port: %d", x);
3855  break;
3856  }
3857 
3858  x += 2;
3859  if (x > rtpend) {
3860  x = (rtpstart + 1) & ~1;
3861  }
3862 
3863  /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
3864  if (x == startplace || (errno != EADDRINUSE && errno != EACCES)) {
3865  ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
3866  close(rtp->s);
3867  rtp->s = -1;
3868  return -1;
3869  }
3870  }
3871 
3872 #ifdef HAVE_PJPROJECT
3873  /* Initialize synchronization aspects */
3874  ast_cond_init(&rtp->cond, NULL);
3875 
3876  generate_random_string(rtp->local_ufrag, sizeof(rtp->local_ufrag));
3877  generate_random_string(rtp->local_passwd, sizeof(rtp->local_passwd));
3878 
3879  /* Create an ICE session for ICE negotiation */
3880  if (icesupport) {
3881  rtp->ice_num_components = 2;
3882  ast_debug_ice(2, "(%p) ICE creating session %s (%d)\n", instance,
3883  ast_sockaddr_stringify(&rtp->bind_address), x);
3884  if (ice_create(instance, &rtp->bind_address, x, 0)) {
3885  ast_log(LOG_NOTICE, "(%p) ICE failed to create session\n", instance);
3886  } else {
3887  rtp->ice_port = x;
3888  ast_sockaddr_copy(&rtp->ice_original_rtp_addr, &rtp->bind_address);
3889  }
3890  }
3891 #endif
3892 
3893 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3894  rtp->rekeyid = -1;
3895  rtp->dtls.timeout_timer = -1;
3896 #endif
3897 
3898  return 0;
3899 }
static int icesupport
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
static int rtpstart
#define LOG_WARNING
Definition: logger.h:274
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
#define ast_log
Definition: astobj2.c:42
#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
int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address that we are expecting to receive RTP on.
Definition: rtp_engine.c:588
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
#define LOG_ERROR
Definition: logger.h:285
static int strictrtp
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
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
#define LOG_NOTICE
Definition: logger.h:263
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
static char * generate_random_string(char *buf, size_t size)
static int ice_create(struct ast_rtp_instance *instance, struct ast_sockaddr *addr, int port, int replace)
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
static int create_new_socket(const char *type, int af)
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524
static int rtpend

◆ rtp_deallocate_transport()

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

Definition at line 3901 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_bundle(), and ast_rtp_destroy().

3902 {
3903  int saved_rtp_s = rtp->s;
3904 #ifdef HAVE_PJPROJECT
3905  struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
3906  struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
3907 #endif
3908 
3909 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
3910  ast_rtp_dtls_stop(instance);
3911 #endif
3912 
3913  /* Close our own socket so we no longer get packets */
3914  if (rtp->s > -1) {
3915  close(rtp->s);
3916  rtp->s = -1;
3917  }
3918 
3919  /* Destroy RTCP if it was being used */
3920  if (rtp->rtcp && rtp->rtcp->s > -1) {
3921  if (saved_rtp_s != rtp->rtcp->s) {
3922  close(rtp->rtcp->s);
3923  }
3924  rtp->rtcp->s = -1;
3925  }
3926 
3927 #ifdef HAVE_PJPROJECT
3929 
3930  /*
3931  * The instance lock is already held.
3932  *
3933  * Destroy the RTP TURN relay if being used
3934  */
3935  if (rtp->turn_rtp) {
3936  rtp->turn_state = PJ_TURN_STATE_NULL;
3937 
3938  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3939  ao2_unlock(instance);
3940  pj_turn_sock_destroy(rtp->turn_rtp);
3941  ao2_lock(instance);
3942  while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
3943  ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
3944  }
3945  rtp->turn_rtp = NULL;
3946  }
3947 
3948  /* Destroy the RTCP TURN relay if being used */
3949  if (rtp->turn_rtcp) {
3950  rtp->turn_state = PJ_TURN_STATE_NULL;
3951 
3952  /* Release the instance lock to avoid deadlock with PJPROJECT group lock */
3953  ao2_unlock(instance);
3954  pj_turn_sock_destroy(rtp->turn_rtcp);
3955  ao2_lock(instance);
3956  while (rtp->turn_state != PJ_TURN_STATE_DESTROYING) {
3957  ast_cond_timedwait(&rtp->cond, ao2_object_get_lockaddr(instance), &ts);
3958  }
3959  rtp->turn_rtcp = NULL;
3960  }
3961 
3962  ast_debug_ice(2, "(%p) ICE RTP transport deallocating\n", instance);
3963  /* Destroy any ICE session */
3964  ast_rtp_ice_stop(instance);
3965 
3966  /* Destroy any candidates */
3967  if (rtp->ice_local_candidates) {
3968  ao2_ref(rtp->ice_local_candidates, -1);
3969  rtp->ice_local_candidates = NULL;
3970  }
3971 
3972  if (rtp->ice_active_remote_candidates) {
3973  ao2_ref(rtp->ice_active_remote_candidates, -1);
3974  rtp->ice_active_remote_candidates = NULL;
3975  }
3976 
3977  if (rtp->ioqueue) {
3978  /*
3979  * We cannot hold the instance lock because we could wait
3980  * for the ioqueue thread to die and we might deadlock as
3981  * a result.
3982  */
3983  ao2_unlock(instance);
3984  rtp_ioqueue_thread_remove(rtp->ioqueue);
3985  ao2_lock(instance);
3986  rtp->ioqueue = NULL;
3987  }
3988 #endif
3989 }
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static void ast_rtp_ice_stop(struct ast_rtp_instance *instance)
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 * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
#define TURN_STATE_WAIT_TIME
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2898
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.
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204

◆ rtp_debug_test_addr()

static int rtp_debug_test_addr ( struct ast_sockaddr addr)
inlinestatic

Definition at line 2746 of file res_rtp_asterisk.c.

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

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

2747 {
2749  return 0;
2750  }
2752  if (rtpdebugport) {
2753  return (ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0); /* look for RTP packets from IP+Port */
2754  } else {
2755  return (ast_sockaddr_cmp_addr(&rtpdebugaddr, addr) == 0); /* only look for RTP packets from IP */
2756  }
2757  }
2758 
2759  return 1;
2760 }
static int rtpdebugport
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413
static int 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
static struct ast_sockaddr rtpdebugaddr
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:2864

◆ rtp_do_debug_ip()

static char* rtp_do_debug_ip ( struct ast_cli_args a)
static

Definition at line 9038 of file res_rtp_asterisk.c.

References ast_cli_args::argv, ast_cli(), ast_debug_category_set_sublevel(), AST_LOG_CATEGORY_ENABLED, AST_LOG_CATEGORY_RTP_PACKET, ast_sockaddr_parse(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify(), ast_strdupa, ast_strlen_zero, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, NULL, rtpdebugaddr, and rtpdebugport.

Referenced by handle_cli_rtp_set_debug().

9039 {
9040  char *arg = ast_strdupa(a->argv[4]);
9041  char *debughost = NULL;
9042  char *debugport = NULL;
9043 
9044  if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
9045  ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
9046  return CLI_FAILURE;
9047  }
9048  rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
9049  ast_cli(a->fd, "RTP Packet Debugging Enabled for address: %s\n",
9052  return CLI_SUCCESS;
9053 }
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
int ast_debug_category_set_sublevel(const char *name, int sublevel)
Set the debug category&#39;s sublevel.
static int rtpdebugport
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition: netsock2.c:164
const int fd
Definition: cli.h:159
static struct ast_sockaddr rtpdebugaddr
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char *const * argv
Definition: cli.h:161
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define CLI_FAILURE
Definition: cli.h:46
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_LOG_CATEGORY_RTP_PACKET
Definition: rtp_engine.h:2826
#define AST_LOG_CATEGORY_ENABLED

◆ rtp_find_instance_by_media_source_ssrc()

static struct ast_rtp_instance* rtp_find_instance_by_media_source_ssrc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned int  ssrc 
)
static
Precondition
instance is locked

Definition at line 5904 of file res_rtp_asterisk.c.

References __rtp_find_instance_by_ssrc().

Referenced by ast_rtcp_interpret().

5906 {
5907  return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 1);
5908 }
static struct ast_rtp_instance * __rtp_find_instance_by_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc, int source)

◆ rtp_find_instance_by_packet_source_ssrc()

static struct ast_rtp_instance* rtp_find_instance_by_packet_source_ssrc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned int  ssrc 
)
static
Precondition
instance is locked

Definition at line 5897 of file res_rtp_asterisk.c.

References __rtp_find_instance_by_ssrc().

Referenced by ast_rtcp_interpret(), and ast_rtp_read().

5899 {
5900  return __rtp_find_instance_by_ssrc(instance, rtp, ssrc, 0);
5901 }
static struct ast_rtp_instance * __rtp_find_instance_by_ssrc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned int ssrc, int source)

◆ rtp_instance_parse_extmap_extensions()

static void rtp_instance_parse_extmap_extensions ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned char *  extension,
int  len 
)
static

Definition at line 7142 of file res_rtp_asterisk.c.

References AST_RTP_EXTENSION_TRANSPORT_WIDE_CC, ast_rtp_instance_extmap_get_id(), len(), and rtp_instance_parse_transport_wide_cc().

Referenced by ast_rtp_interpret().

7144 {
7145  int transport_wide_cc_id = ast_rtp_instance_extmap_get_id(instance, AST_RTP_EXTENSION_TRANSPORT_WIDE_CC);
7146  int pos = 0;
7147 
7148  /* We currently only care about the transport-cc extension, so if that's not negotiated then do nothing */
7149  if (transport_wide_cc_id == -1) {
7150  return;
7151  }
7152 
7153  /* Only while we do not exceed available extension data do we continue */
7154  while (pos < len) {
7155  int id = extension[pos] >> 4;
7156  int extension_len = (extension[pos] & 0xF) + 1;
7157 
7158  /* We've handled the first byte as it contains the extension id and length, so always
7159  * skip ahead now
7160  */
7161  pos += 1;
7162 
7163  if (id == 0) {
7164  /* From the RFC:
7165  * In both forms, padding bytes have the value of 0 (zero). They may be
7166  * placed between extension elements, if desired for alignment, or after
7167  * the last extension element, if needed for padding. A padding byte
7168  * does not supply the ID of an element, nor the length field. When a
7169  * padding byte is found, it is ignored and the parser moves on to
7170  * interpreting the next byte.
7171  */
7172  continue;
7173  } else if (id == 15) {
7174  /* From the RFC:
7175  * The local identifier value 15 is reserved for future extension and
7176  * MUST NOT be used as an identifier. If the ID value 15 is
7177  * encountered, its length field should be ignored, processing of the
7178  * entire extension should terminate at that point, and only the
7179  * extension elements present prior to the element with ID 15
7180  * considered.
7181  */
7182  break;
7183  } else if ((pos + extension_len) > len) {
7184  /* The extension is corrupted and is stating that it contains more data than is
7185  * available in the extensions data.
7186  */
7187  break;
7188  }
7189 
7190  /* If this is transport-cc then we need to parse it further */
7191  if (id == transport_wide_cc_id) {
7192  rtp_instance_parse_transport_wide_cc(instance, rtp, extension + pos, extension_len);
7193  }
7194 
7195  /* Skip ahead to the next extension */
7196  pos += extension_len;
7197  }
7198 }
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:886
structure to hold extensions
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static void rtp_instance_parse_transport_wide_cc(struct ast_rtp_instance *instance, struct ast_rtp *rtp, unsigned char *data, int len)

◆ rtp_instance_parse_transport_wide_cc()

static void rtp_instance_parse_transport_wide_cc ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
unsigned char *  data,
int  len 
)
static

Definition at line 7087 of file res_rtp_asterisk.c.

References ao2_ref, ast_debug_rtcp, ast_log, ast_rtp_instance_get_data(), ast_sched_add(), ast_tvnow(), AST_VECTOR_ADD_SORTED, AST_VECTOR_APPEND, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_RESET, AST_VECTOR_SIZE, LOG_WARNING, rtp_transport_wide_cc_packet_statistics::received, RTP_SEQ_MOD, rtp_transport_wide_cc_feedback_produce(), rtp_transport_wide_cc_packet_statistics_cmp(), and rtp_transport_wide_cc_packet_statistics::seqno.

Referenced by rtp_instance_parse_extmap_extensions().

7089 {
7090  uint16_t *seqno = (uint16_t *)data;
7092  struct ast_rtp_instance *transport = rtp->bundled ? rtp->bundled : instance;
7093  struct ast_rtp *transport_rtp = ast_rtp_instance_get_data(transport);
7094 
7095  /* If the sequence number has cycled over then record it as such */
7096  if (((int)transport_rtp->transport_wide_cc.last_seqno - (int)ntohs(*seqno)) > 100) {
7097  transport_rtp->transport_wide_cc.cycles += RTP_SEQ_MOD;
7098  }
7099 
7100  /* Populate the statistics information for this packet */
7101  statistics.seqno = transport_rtp->transport_wide_cc.cycles + ntohs(*seqno);
7102  statistics.received = ast_tvnow();
7103 
7104  /* We allow at a maximum 1000 packet statistics in play at a time, if we hit the
7105  * limit we give up and start fresh.
7106  */
7107  if (AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) > 1000) {
7108  AST_VECTOR_RESET(&rtp->transport_wide_cc.packet_statistics, AST_VECTOR_ELEM_CLEANUP_NOOP);
7109  }
7110 
7111  if (!AST_VECTOR_SIZE(&transport_rtp->transport_wide_cc.packet_statistics) ||
7112  statistics.seqno > transport_rtp->transport_wide_cc.last_extended_seqno) {
7113  /* This is the expected path */
7114  if (AST_VECTOR_APPEND(&transport_rtp->transport_wide_cc.packet_statistics, statistics)) {
7115  return;
7116  }
7117 
7118  transport_rtp->transport_wide_cc.last_extended_seqno = statistics.seqno;
7119  transport_rtp->transport_wide_cc.last_seqno = ntohs(*seqno);
7120  } else {
7121  /* This packet was out of order, so reorder it within the vector accordingly */
7122  if (AST_VECTOR_ADD_SORTED(&transport_rtp->transport_wide_cc.packet_statistics, statistics,
7124  return;
7125  }
7126  }
7127 
7128  /* If we have not yet scheduled the periodic sending of feedback for this transport then do so */
7129  if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
7130  ast_debug_rtcp(1, "(%p) RTCP starting transport-cc feedback transmission on RTP instance '%p'\n", instance, transport);
7131  ao2_ref(transport, +1);
7132  transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
7134  if (transport_rtp->transport_wide_cc.schedid < 0) {
7135  ao2_ref(transport, -1);
7136  ast_log(LOG_WARNING, "Scheduling RTCP transport-cc feedback transmission failed on RTP instance '%p'\n",
7137  transport);
7138  }
7139  }
7140 }
RTP session description.
static void statistics(void)
Definition: utils/frame.c:287
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371
static int rtp_transport_wide_cc_feedback_produce(const void *data)
#define LOG_WARNING
Definition: logger.h:274
Packet statistics (used for transport-cc)
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
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)
#define RTP_SEQ_MOD
#define ast_log
Definition: astobj2.c:42
#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 ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
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 ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ rtp_instance_unlock()

static void rtp_instance_unlock ( struct ast_rtp_instance instance)
static

Definition at line 6817 of file res_rtp_asterisk.c.

References ao2_unlock.

Referenced by ast_rtp_read().

6818 {
6819  if (instance) {
6820  ao2_unlock(instance);
6821  }
6822 }
#define ao2_unlock(a)
Definition: astobj2.h:730

◆ rtp_ioqueue_thread_destroy()

static void rtp_ioqueue_thread_destroy ( struct ast_rtp_ioqueue_thread ioqueue)
static

Destroyer for ioqueue thread.

Definition at line 1470 of file res_rtp_asterisk.c.

References ast_free, NULL, ast_rtp_ioqueue_thread::pool, ast_rtp_ioqueue_thread::terminate, and ast_rtp_ioqueue_thread::thread.

Referenced by rtp_ioqueue_thread_get_or_create(), and rtp_ioqueue_thread_remove().

1471 {
1472  if (ioqueue->thread) {
1473  ioqueue->terminate = 1;
1474  pj_thread_join(ioqueue->thread);
1475  pj_thread_destroy(ioqueue->thread);
1476  }
1477 
1478  if (ioqueue->pool) {
1479  /* This mimics the behavior of pj_pool_safe_release
1480  * which was introduced in pjproject 2.6.
1481  */
1482  pj_pool_t *temp_pool = ioqueue->pool;
1483 
1484  ioqueue->pool = NULL;
1485  pj_pool_release(temp_pool);
1486  }
1487 
1488  ast_free(ioqueue);
1489 }
int terminate
Termination request.
#define NULL
Definition: resample.c:96
pj_thread_t * thread
The thread handling the queue and timer heap.
#define ast_free(a)
Definition: astmm.h:182
pj_pool_t * pool
Pool used by the thread.

◆ rtp_ioqueue_thread_get_or_create()

static struct ast_rtp_ioqueue_thread* rtp_ioqueue_thread_get_or_create ( void  )
static

Finder and allocator for an ioqueue thread.

Definition at line 1512 of file res_rtp_asterisk.c.

References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cachingpool, ast_rtp_ioqueue_thread::count, end, ast_rtp_ioqueue_thread::ioqueue, ioqueue_worker_thread(), lock, ast_rtp_ioqueue_thread::next, NULL, ast_rtp_ioqueue_thread::pool, rtp_ioqueue_thread_destroy(), ast_rtp_ioqueue_thread::thread, and ast_rtp_ioqueue_thread::timerheap.

Referenced by ast_rtp_ice_turn_request().

1513 {
1515  pj_lock_t *lock;
1516 
1518 
1519  /* See if an ioqueue thread exists that can handle more */
1520  AST_LIST_TRAVERSE(&ioqueues, ioqueue, next) {
1521  if ((ioqueue->count + 2) < PJ_IOQUEUE_MAX_HANDLES) {
1522  break;
1523  }
1524  }
1525 
1526  /* If we found one bump it up and return it */
1527  if (ioqueue) {
1528  ioqueue->count += 2;
1529  goto end;
1530  }
1531 
1532  ioqueue = ast_calloc(1, sizeof(*ioqueue));
1533  if (!ioqueue) {
1534  goto end;
1535  }
1536 
1537  ioqueue->pool = pj_pool_create(&cachingpool.factory, "rtp", 512, 512, NULL);
1538 
1539  /* We use a timer on the ioqueue thread for TURN so that two threads aren't operating
1540  * on a session at the same time
1541  */
1542  if (pj_timer_heap_create(ioqueue->pool, 4, &ioqueue->timerheap) != PJ_SUCCESS) {
1543  goto fatal;
1544  }
1545 
1546  if (pj_lock_create_recursive_mutex(ioqueue->pool, "rtp%p", &lock) != PJ_SUCCESS) {
1547  goto fatal;
1548  }
1549 
1550  pj_timer_heap_set_lock(ioqueue->timerheap, lock, PJ_TRUE);
1551 
1552  if (pj_ioqueue_create(ioqueue->pool, PJ_IOQUEUE_MAX_HANDLES, &ioqueue->ioqueue) != PJ_SUCCESS) {
1553  goto fatal;
1554  }
1555 
1556  if (pj_thread_create(ioqueue->pool, "ice", &ioqueue_worker_thread, ioqueue, 0, 0, &ioqueue->thread) != PJ_SUCCESS) {
1557  goto fatal;
1558  }
1559 
1560  AST_LIST_INSERT_HEAD(&ioqueues, ioqueue, next);
1561 
1562  /* Since this is being returned to an active session the count always starts at 2 */
1563  ioqueue->count = 2;
1564 
1565  goto end;
1566 
1567 fatal:
1568  rtp_ioqueue_thread_destroy(ioqueue);
1569  ioqueue = NULL;
1570 
1571 end:
1573  return ioqueue;
1574 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
Structure which contains ioqueue thread information.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
static int ioqueue_worker_thread(void *data)
Worker thread for ioqueue and timerheap.
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
pj_thread_t * thread
The thread handling the queue and timer heap.
ast_mutex_t lock
Definition: app_meetme.c:1091
pj_ioqueue_t * ioqueue
Ioqueue which polls on sockets.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_rtp_ioqueue_thread * next
pj_pool_t * pool
Pool used by the thread.
static void rtp_ioqueue_thread_destroy(struct ast_rtp_ioqueue_thread *ioqueue)
Destroyer for ioqueue thread.
List of ioqueue threads.
unsigned int count
Current number of descriptors being waited on.
pj_timer_heap_t * timerheap
Timer heap for scheduled items.

◆ rtp_ioqueue_thread_remove()

static void rtp_ioqueue_thread_remove ( struct ast_rtp_ioqueue_thread ioqueue)
static

Removal function for ioqueue thread, determines if it should be terminated and destroyed.

Definition at line 1492 of file res_rtp_asterisk.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_rtp_ioqueue_thread::count, destroy(), ast_rtp_ioqueue_thread::next, and rtp_ioqueue_thread_destroy().

Referenced by rtp_deallocate_transport().

1493 {
1494  int destroy = 0;
1495 
1496  /* If nothing is using this ioqueue thread destroy it */
1498  if ((ioqueue->count - 2) == 0) {
1499  destroy = 1;
1500  AST_LIST_REMOVE(&ioqueues, ioqueue, next);
1501  }
1503 
1504  if (!destroy) {
1505  return;
1506  }
1507 
1508  rtp_ioqueue_thread_destroy(ioqueue);
1509 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:855
static void destroy(struct ast_trans_pvt *pvt)
Definition: translate.c:291
struct ast_rtp_ioqueue_thread * next
static void rtp_ioqueue_thread_destroy(struct ast_rtp_ioqueue_thread *ioqueue)
Destroyer for ioqueue thread.
List of ioqueue threads.
unsigned int count
Current number of descriptors being waited on.

◆ rtp_learning_rtp_seq_update()

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

Definition at line 3403 of file res_rtp_asterisk.c.

References AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_END, AST_MEDIA_TYPE_IMAGE, AST_MEDIA_TYPE_TEXT, AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), learning_min_duration, learning_min_sequential, rtp_learning_info::max_seq, rtp_learning_info::packets, rtp_learning_info::received, seq, rtp_learning_info::stream_type, STRICT_RTP_YES, and strictrtp.

Referenced by ast_rtp_read().

3404 {
3405  if (seq == (uint16_t) (info->max_seq + 1)) {
3406  /* packet is in sequence */
3407  info->packets--;
3408  } else {
3409  /* Sequence discontinuity; reset */
3410  info->packets = learning_min_sequential - 1;
3411  info->received = ast_tvnow();
3412  }
3413 
3414  /* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */
3415  if (strictrtp == STRICT_RTP_YES) {
3416  switch (info->stream_type) {
3418  case AST_MEDIA_TYPE_AUDIO:
3419  /*
3420  * Protect against packet floods by checking that we
3421  * received the packet sequence in at least the minimum
3422  * allowed time.
3423  */
3424  if (ast_tvzero(info->received)) {
3425  info->received = ast_tvnow();
3426  } else if (!info->packets
3428  /* Packet flood; reset */
3429  info->packets = learning_min_sequential - 1;
3430  info->received = ast_tvnow();
3431  }
3432  break;
3433  case AST_MEDIA_TYPE_VIDEO:
3434  case AST_MEDIA_TYPE_IMAGE:
3435  case AST_MEDIA_TYPE_TEXT:
3436  case AST_MEDIA_TYPE_END:
3437  break;
3438  }
3439  }
3440 
3441  info->max_seq = seq;
3442 
3443  return info->packets;
3444 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
static int strictrtp
enum ast_media_type stream_type
static int learning_min_duration
static volatile unsigned int seq
Definition: app_sms.c:120
static int learning_min_sequential
struct timeval received

◆ rtp_learning_seq_init()

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

Definition at line 3386 of file res_rtp_asterisk.c.

References learning_min_sequential, rtp_learning_info::max_seq, rtp_learning_info::packets, rtp_learning_info::received, and seq.

Referenced by ast_rtp_read(), and rtp_learning_start().

3387 {
3388  info->max_seq = seq;
3390  memset(&info->received, 0, sizeof(info->received));
3391 }
static volatile unsigned int seq
Definition: app_sms.c:120
static int learning_min_sequential
struct timeval received

◆ rtp_learning_start()

static void rtp_learning_start ( struct ast_rtp rtp)
static

Start the strictrtp learning mode.

Parameters
rtpRTP session description
Returns
Nothing

Definition at line 3453 of file res_rtp_asterisk.c.

References acl_change_stasis_cb(), ast_tvnow(), ast_rtp::lastrxseqno, rtp_learning_seq_init(), STRICT_RTP_LEARN, and sub.

Referenced by ast_rtp_ice_start_media(), and ast_rtp_remote_address_set().

3454 {
3455  rtp->strict_rtp_state = STRICT_RTP_LEARN;
3456  memset(&rtp->rtp_source_learn.proposed_address, 0,
3457  sizeof(rtp->rtp_source_learn.proposed_address));
3458  rtp->rtp_source_learn.start = ast_tvnow();
3459  rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t) rtp->lastrxseqno);
3460 }
static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150

◆ rtp_raw_write()

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

Definition at line 4891 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_write().

4892 {
4893  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
4894  int pred, mark = 0;
4895  unsigned int ms = calc_txstamp(rtp, &frame->delivery);
4896  struct ast_sockaddr remote_address = { {0,} };
4897  int rate = ast_rtp_get_rate(frame->subclass.format) / 1000;
4898  unsigned int seqno;
4899 #ifdef TEST_FRAMEWORK
4901 #endif
4902 
4904  frame->samples /= 2;
4905  }
4906 
4907  if (rtp->sending_digit) {
4908  return 0;
4909  }
4910 
4911 #ifdef TEST_FRAMEWORK
4912  if (test && test->send_report) {
4913  test->send_report = 0;
4914  ast_rtcp_write(instance);
4915  return 0;
4916  }
4917 #endif
4918 
4919  if (frame->frametype == AST_FRAME_VOICE) {
4920  pred = rtp->lastts + frame->samples;
4921 
4922  /* Re-calculate last TS */
4923  rtp->lastts = rtp->lastts + ms * rate;
4924  if (ast_tvzero(frame->delivery)) {
4925  /* If this isn't an absolute delivery time, Check if it is close to our prediction,
4926  and if so, go with our prediction */
4927  if (abs((int)rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
4928  rtp->lastts = pred;
4929  } else {
4930  ast_debug_rtp(3, "(%p) RTP audio difference is %d, ms is %u\n",
4931  instance, abs((int)rtp->lastts - pred), ms);
4932  mark = 1;
4933  }
4934  }
4935  } else if (frame->frametype == AST_FRAME_VIDEO) {
4936  mark = frame->subclass.frame_ending;
4937  pred = rtp->lastovidtimestamp + frame->samples;
4938  /* Re-calculate last TS */
4939  rtp->lastts = rtp->lastts + ms * 90;
4940  /* If it's close to our prediction, go for it */
4941  if (ast_tvzero(frame->delivery)) {
4942  if (abs((int)rtp->lastts - pred) < 7200) {
4943  rtp->lastts = pred;
4944  rtp->lastovidtimestamp += frame->samples;
4945  } else {
4946  ast_debug_rtp(3, "(%p) RTP video difference is %d, ms is %u (%u), pred/ts/samples %u/%d/%d\n",
4947  instance, abs((int)rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
4948  rtp->lastovidtimestamp = rtp->lastts;
4949  }
4950  }
4951  } else {
4952  pred = rtp->lastotexttimestamp + frame->samples;
4953  /* Re-calculate last TS */
4954  rtp->lastts = rtp->lastts + ms;
4955  /* If it's close to our prediction, go for it */
4956  if (ast_tvzero(frame->delivery)) {
4957  if (abs((int)rtp->lastts - pred) < 7200) {
4958  rtp->lastts = pred;
4959  rtp->lastotexttimestamp += frame->samples;
4960  } else {
4961  ast_debug_rtp(3, "(%p) RTP other difference is %d, ms is %u, pred/ts/samples %u/%d/%d\n",
4962  instance, abs((int)rtp->lastts - pred), ms, rtp->lastts, pred, frame->samples);
4963  rtp->lastotexttimestamp = rtp->lastts;
4964  }
4965  }
4966  }
4967 
4968  /* If we have been explicitly told to set the marker bit then do so */
4969  if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
4970  mark = 1;
4972  }
4973 
4974  /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
4975  if (rtp->lastts > rtp->lastdigitts) {
4976  rtp->lastdigitts = rtp->lastts;
4977  }
4978 
4979  /* Assume that the sequence number we expect to use is what will be used until proven otherwise */
4980  seqno = rtp->seqno;
4981 
4982  /* If the frame contains sequence number information use it to influence our sequence number */
4984  if (rtp->expectedseqno != -1) {
4985  /* Determine where the frame from the core is in relation to where we expected */
4986  int difference = frame->seqno - rtp->expectedseqno;
4987 
4988  /* If there is a substantial difference then we've either got packets really out
4989  * of order, or the source is RTP and it has cycled. If this happens we resync
4990  * the sequence number adjustments to this frame. If we also have packet loss
4991  * things won't be reflected correctly but it will sort itself out after a bit.
4992  */
4993  if (abs(difference) > 100) {
4994  difference = 0;
4995  }
4996 
4997  /* Adjust the sequence number being used for this packet accordingly */
4998  seqno += difference;
4999 
5000  if (difference >= 0) {
5001  /* This frame is on time or in the future */
5002  rtp->expectedseqno = frame->seqno + 1;
5003  rtp->seqno += difference;
5004  }
5005  } else {
5006  /* This is the first frame with sequence number we've seen, so start keeping track */
5007  rtp->expectedseqno = frame->seqno + 1;
5008  }
5009  } else {
5010  rtp->expectedseqno = -1;
5011  }
5012 
5014  rtp->lastts = frame->ts * rate;
5015  }
5016 
5017  ast_rtp_instance_get_remote_address(instance, &remote_address);
5018 
5019  /* If we know the remote address construct a packet and send it out */
5020  if (!ast_sockaddr_isnull(&remote_address)) {
5021  int hdrlen = 12;
5022  int res;
5023  int ice;
5024  int ext = 0;
5025  int abs_send_time_id;
5026  int packet_len;
5027  unsigned char *rtpheader;
5028 
5029  /* If the abs-send-time extension has been negotiated determine how much space we need */
5031  if (abs_send_time_id != -1) {
5032  /* 4 bytes for the shared information, 1 byte for identifier, 3 bytes for abs-send-time */
5033  hdrlen += 8;
5034  ext = 1;
5035  }
5036 
5037  packet_len = frame->datalen + hdrlen;
5038  rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
5039 
5040  put_unaligned_uint32(rtpheader, htonl((2 << 30) | (ext << 28) | (codec << 16) | (seqno) | (mark << 23)));
5041  put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
5042  put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
5043 
5044  /* We assume right now that we will only ever have the abs-send-time extension in the packet
5045  * which simplifies things a bit.
5046  */
5047  if (abs_send_time_id != -1) {
5048  unsigned int now_msw;
5049  unsigned int now_lsw;
5050 
5051  /* This happens before being placed into the retransmission buffer so that when we
5052  * retransmit we only have to update the timestamp, not everything else.
5053  */
5054  put_unaligned_uint32(rtpheader + 12, htonl((0xBEDE << 16) | 1));
5055  rtpheader[16] = (abs_send_time_id << 4) | 2;
5056 
5057  timeval2ntp(ast_tvnow(), &now_msw, &now_lsw);
5058  put_unaligned_time24(rtpheader + 17, now_msw, now_lsw);
5059  }
5060 
5061  /* If retransmissions are enabled, we need to store this packet for future use */
5062  if (rtp->send_buffer) {
5063  struct ast_rtp_rtcp_nack_payload *payload;
5064 
5065  payload = ast_malloc(sizeof(*payload) + packet_len);
5066  if (payload) {
5067  payload->size = packet_len;
5068  memcpy(payload->buf, rtpheader, packet_len);
5069  if (ast_data_buffer_put(rtp->send_buffer, rtp->seqno, payload) == -1) {
5070  ast_free(payload);
5071  }
5072  }
5073  }
5074 
5075  res = rtp_sendto(instance, (void *)rtpheader, packet_len, 0, &remote_address, &ice);
5076  if (res < 0) {
5078  ast_debug_rtp(1, "(%p) RTP transmission error of packet %d to %s: %s\n",
5079  instance, rtp->seqno,
5080  ast_sockaddr_stringify(&remote_address),
5081  strerror(errno));
5083  /* Only give this error message once if we are not RTP debugging */
5085  ast_debug(0, "(%p) RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
5086  instance, ast_sockaddr_stringify(&remote_address));
5088  }
5089  } else {
5090  if (rtp->rtcp && rtp->rtcp->schedid < 0) {
5091  ast_debug_rtcp(1, "(%p) RTCP starting transmission\n", instance);
5092  ao2_ref(instance, +1);
5093  rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
5094  if (rtp->rtcp->schedid < 0) {
5095  ao2_ref(instance, -1);
5096  ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
5097  }
5098  }
5099  }
5100 
5101  if (rtp_debug_test_addr(&remote_address)) {
5102  ast_verbose("Sent RTP packet to %s%s (type %-2.2d, seq %-6.6d, ts %-6.6u, len %-6.6d)\n",
5103  ast_sockaddr_stringify(&remote_address),
5104  ice ? " (via ICE)" : "",
5105  codec, rtp->seqno, rtp->lastts, res - hdrlen);
5106  }
5107  }
5108 
5109  /* If the sequence number that has been used doesn't match what we expected then this is an out of
5110  * order late packet, so we don't need to increment as we haven't yet gotten the expected frame from
5111  * the core.
5112  */
5113  if (seqno == rtp->seqno) {
5114  rtp->seqno++;
5115  }
5116 
5117  return 0;
5118 }
RTP session description.
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:886
unsigned int lastovidtimestamp
unsigned int lastotexttimestamp
Structure for storing RTP packets for retransmission.
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int ast_rtcp_write(const void *data)
Write a RTCP packet to the far end.
#define ast_set_flag(p, flag)
Definition: utils.h:70
#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
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
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)
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
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:111
const char * ext
Definition: http.c:147
Socket address structure.
Definition: netsock2.h:97
struct ast_frame_subclass subclass
int ast_data_buffer_put(struct ast_data_buffer *buffer, size_t pos, void *payload)
Place a data payload at a position in the data buffer.
Definition: data_buffer.c:203
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 FLAG_NAT_ACTIVE
static int rtp_debug_test_addr(struct ast_sockaddr *addr)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
#define FLAG_NAT_INACTIVE_NOWARN
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2860
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define FLAG_NEED_MARKER_BIT
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
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
#define ast_debug_rtp_packet_is_allowed
Definition: rtp_engine.h:2864
static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
#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
Structure that represents the test functionality for res_rtp_asterisk unit tests. ...
Definition: rtp_engine.h:595
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct timeval delivery
unsigned int lastts
#define abs(x)
Definition: f2c.h:195
static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
static void put_unaligned_time24(void *p, uint32_t time_msw, uint32_t time_lsw)
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
static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format
#define MAX_TIMESTAMP_SKEW
#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
#define FLAG_NAT_INACTIVE

◆ rtp_recvfrom()

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

Definition at line 3241 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtp_read().

3242 {
3243  return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
3244 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)

◆ rtp_red_buffer()

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

Definition at line 8608 of file res_rtp_asterisk.c.

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

8609 {
8610  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8611  struct rtp_red *red = rtp->red;
8612 
8613  if (!red) {
8614  return 0;
8615  }
8616 
8617  if (frame->datalen > 0) {
8618  if (red->t140.datalen > 0) {
8619  const unsigned char *primary = red->buf_data;
8620 
8621  /* There is something already in the T.140 buffer */
8622  if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
8623  /* Flush the previous T.140 packet if it is a command */
8624  ast_rtp_write(instance, &rtp->red->t140);
8625  } else {
8626  primary = frame->data.ptr;
8627  if (primary[0] == 0x08 || primary[0] == 0x0a || primary[0] == 0x0d) {
8628  /* Flush the previous T.140 packet if we are buffering a command now */
8629  ast_rtp_write(instance, &rtp->red->t140);
8630  }
8631  }
8632  }
8633 
8634  memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
8635  red->t140.datalen += frame->datalen;
8636  red->t140.ts = frame->ts;
8637  }
8638 
8639  return 0;
8640 }
RTP session description.
static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
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 t140
unsigned char buf_data[64000]
union ast_frame::@263 data

◆ rtp_red_init()

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

Definition at line 8575 of file res_rtp_asterisk.c.

References ast_calloc, ast_format_t140_red, AST_FRAME_TEXT, ast_rtp_instance_get_data(), ast_sched_add(), and red_write().

8576 {
8577  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
8578  int x;
8579 
8580  rtp->red = ast_calloc(1, sizeof(*rtp->red));
8581  if (!rtp->red) {
8582  return -1;
8583  }
8584 
8585  rtp->red->t140.frametype = AST_FRAME_TEXT;
8586  rtp->red->t140.subclass.format = ast_format_t140_red;
8587  rtp->red->t140.data.ptr = &rtp->red->buf_data;
8588 
8589  rtp->red->t140red = rtp->red->t140;
8590  rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
8591 
8592  rtp->red->ti = buffer_time;
8593  rtp->red->num_gen = generations;
8594  rtp->red->hdrlen = generations * 4 + 1;
8595 
8596  for (x = 0; x < generations; x++) {
8597  rtp->red->pt[x] = payloads[x];
8598  rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
8599  rtp->red->t140red_data[x*4] = rtp->red->pt[x];
8600  }
8601  rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
8602  rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
8603 
8604  return 0;
8605 }
RTP session description.
struct ast_format * ast_format_t140_red
Built-in cached t140 red format.
Definition: format_cache.c:241
#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
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
static int red_write(const void *data)
Write t140 redundacy frame.

◆ rtp_reload()

static int rtp_reload ( int  reload,
int  by_external_config 
)
static

This resource is not "reloaded" so much as unloaded and loaded again. In the case of the TURN related variables, the memory referenced by a previously loaded instance should have been released when the corresponding pool was destroyed. If at some point in the future this resource were to support ACTUAL live reconfiguration and did NOT release the pool this will cause a small memory leak.

Definition at line 9346 of file res_rtp_asterisk.c.

References ast_ice_host_candidate::advertised, ast_append_acl(), ast_calloc, ast_config_destroy(), ast_config_load2(), ast_false(), ast_free_acl_list(), ast_inet_ntoa(), ast_log, ast_named_acl_change_type(), ast_parse_arg(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rwlock_unlock, ast_rwlock_wrlock, ast_security_topic(), ast_skip_blanks(), ast_sockaddr_copy(), ast_sockaddr_setnull(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CALC_LEARNING_MIN_DURATION, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTLS_MTU, DEFAULT_DTMF_TIMEOUT, DEFAULT_ICESUPPORT, DEFAULT_LEARNING_MIN_DURATION, DEFAULT_LEARNING_MIN_SEQUENTIAL, DEFAULT_RTP_END, DEFAULT_RTP_START, DEFAULT_SRTP_REPLAY_PROTECTION, DEFAULT_STRICT_RTP, DEFAULT_STUN_SOFTWARE_ATTRIBUTE, DEFAULT_TURN_PORT, dtmftimeout, host_candidate_overrides_clear(), ice_acl, icesupport, ast_ice_host_candidate::include_local, learning_min_duration, learning_min_sequential, ast_ice_host_candidate::local, LOG_ERROR, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, ast_variable::name, ast_variable::next, ast_rtp_ioqueue_thread::next, NULL, PARSE_ADDR, PARSE_INADDR, PARSE_PORT_IGNORE, ast_rtp_ioqueue_thread::pool, RTCP_DEFAULT_INTERVALMS, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, srtp_replay_protection, STANDARD_STUN_PORT, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), stasis_unsubscribe_and_join(), STRICT_RTP_NO, STRICT_RTP_SEQNO, STRICT_RTP_YES, strictrtp, stun_acl, stun_software_attribute, stunaddr, turnaddr, turnpassword, turnport, turnusername, ast_variable::value, and var.

Referenced by acl_change_stasis_cb(), load_module(), and reload_module().

9347 {
9348  struct ast_config *cfg;
9349  const char *s;
9350  struct ast_flags config_flags = { (reload && !by_external_config) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
9351 
9352 #ifdef HAVE_PJPROJECT
9353  struct ast_variable *var;
9354  struct ast_ice_host_candidate *candidate;
9355  int acl_subscription_flag = 0;
9356 #endif
9357 
9358  cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
9359  if (!cfg || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
9360  return 0;
9361  }
9362 
9363 #ifdef SO_NO_CHECK
9364  nochecksums = 0;
9365 #endif
9366 
9375 
9376  /** This resource is not "reloaded" so much as unloaded and loaded again.
9377  * In the case of the TURN related variables, the memory referenced by a
9378  * previously loaded instance *should* have been released when the
9379  * corresponding pool was destroyed. If at some point in the future this
9380  * resource were to support ACTUAL live reconfiguration and did NOT release
9381  * the pool this will cause a small memory leak.
9382  */
9383 
9384 #ifdef HAVE_PJPROJECT
9388  memset(&stunaddr, 0, sizeof(stunaddr));
9389  turnaddr = pj_str(NULL);
9390  turnusername = pj_str(NULL);
9391  turnpassword = pj_str(NULL);
9393 #endif
9394 
9395 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9396  dtls_mtu = DEFAULT_DTLS_MTU;
9397 #endif
9398 
9399  if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
9400  rtpstart = atoi(s);
9401  if (rtpstart < MINIMUM_RTP_PORT)
9403  if (rtpstart > MAXIMUM_RTP_PORT)
9405  }
9406  if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
9407  rtpend = atoi(s);
9408  if (rtpend < MINIMUM_RTP_PORT)
9410  if (rtpend > MAXIMUM_RTP_PORT)
9412  }
9413  if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
9414  rtcpinterval = atoi(s);
9415  if (rtcpinterval == 0)
9416  rtcpinterval = 0; /* Just so we're clear... it's zero */
9418  rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
9421  }
9422  if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
9423 #ifdef SO_NO_CHECK
9424  nochecksums = ast_false(s) ? 1 : 0;
9425 #else
9426  if (ast_false(s))
9427  ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
9428 #endif
9429  }
9430  if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
9431  dtmftimeout = atoi(s);
9432  if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
9433  ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
9436  };
9437  }
9438  if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
9439  if (ast_true(s)) {
9441  } else if (!strcasecmp(s, "seqno")) {
9443  } else {
9445  }
9446  }
9447  if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
9448  if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {
9449  ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
9452  }
9454  }
9455  if ((s = ast_variable_retrieve(cfg, "general", "srtpreplayprotection"))) {
9457  }
9458 #ifdef HAVE_PJPROJECT
9459  if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {
9460  icesupport = ast_true(s);
9461  }
9462  if ((s = ast_variable_retrieve(cfg, "general", "stun_software_attribute"))) {
9464  }
9465  if ((s = ast_variable_retrieve(cfg, "general", "stunaddr"))) {
9466  stunaddr.sin_port = htons(STANDARD_STUN_PORT);
9467  if (ast_parse_arg(s, PARSE_INADDR, &stunaddr)) {
9468  ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", s);
9469  }
9470  }
9471  if ((s = ast_variable_retrieve(cfg, "general", "turnaddr"))) {
9472  struct sockaddr_in addr;
9473  addr.sin_port = htons(DEFAULT_TURN_PORT);
9474  if (ast_parse_arg(s, PARSE_INADDR, &addr)) {
9475  ast_log(LOG_WARNING, "Invalid TURN server address: %s\n", s);
9476  } else {
9477  pj_strdup2_with_null(pool, &turnaddr, ast_inet_ntoa(addr.sin_addr));
9478  /* ntohs() is not a bug here. The port number is used in host byte order with
9479  * a pjnat API. */
9480  turnport = ntohs(addr.sin_port);
9481  }
9482  }
9483  if ((s = ast_variable_retrieve(cfg, "general", "turnusername"))) {
9484  pj_strdup2_with_null(pool, &turnusername, s);
9485  }
9486  if ((s = ast_variable_retrieve(cfg, "general", "turnpassword"))) {
9487  pj_strdup2_with_null(pool, &turnpassword, s);
9488  }
9489 
9491  for (var = ast_variable_browse(cfg, "ice_host_candidates"); var; var = var->next) {
9492  struct ast_sockaddr local_addr, advertised_addr;
9493  unsigned int include_local_address = 0;
9494  char *sep;
9495 
9496  ast_sockaddr_setnull(&local_addr);
9497  ast_sockaddr_setnull(&advertised_addr);
9498 
9499  if (ast_parse_arg(var->name, PARSE_ADDR | PARSE_PORT_IGNORE, &local_addr)) {
9500  ast_log(LOG_WARNING, "Invalid local ICE host address: %s\n", var->name);
9501  continue;
9502  }
9503 
9504  sep = strchr(var->value,',');
9505  if (sep) {
9506  *sep = '\0';
9507  sep++;
9508  sep = ast_skip_blanks(sep);
9509  include_local_address = strcmp(sep, "include_local_address") == 0;
9510  }
9511 
9512  if (ast_parse_arg(var->value, PARSE_ADDR | PARSE_PORT_IGNORE, &advertised_addr)) {
9513  ast_log(LOG_WARNING, "Invalid advertised ICE host address: %s\n", var->value);
9514  continue;
9515  }
9516 
9517  if (!(candidate = ast_calloc(1, sizeof(*candidate)))) {
9518  ast_log(LOG_ERROR, "Failed to allocate ICE host candidate mapping.\n");
9519  break;
9520  }
9521 
9522  candidate->include_local = include_local_address;
9523 
9524  ast_sockaddr_copy(&candidate->local, &local_addr);
9525  ast_sockaddr_copy(&candidate->advertised, &advertised_addr);
9526 
9527  AST_RWLIST_INSERT_TAIL(&host_candidates, candidate, next);
9528  }
9530 
9533 
9536 
9537  for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
9538  const char* sense = NULL;
9539  struct ast_acl_list **acl = NULL;
9540  if (strncasecmp(var->name, "ice_", 4) == 0) {
9541  sense = var->name + 4;
9542  acl = &ice_acl;
9543  } else if (strncasecmp(var->name, "stun_", 5) == 0) {
9544  sense = var->name + 5;
9545  acl = &stun_acl;
9546  } else {
9547  continue;
9548  }
9549 
9550  if (strcasecmp(sense, "blacklist") == 0) {
9551  sense = "deny";
9552  }
9553 
9554  if (strcasecmp(sense, "acl") && strcasecmp(sense, "permit") && strcasecmp(sense, "deny")) {
9555  continue;
9556  }
9557 
9558  ast_append_acl(sense, var->value, acl, NULL, &acl_subscription_flag);
9559  }
9562 
9563  if (acl_subscription_flag && !acl_change_sub) {
9567  } else if (!acl_subscription_flag && acl_change_sub) {
9569  }
9570 #endif
9571 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
9572  if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
9573  if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
9574  ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
9576  dtls_mtu = DEFAULT_DTLS_MTU;
9577  }
9578  }
9579 #endif
9580 
9581  ast_config_destroy(cfg);
9582 
9583  if (rtpstart >= rtpend) {
9584  ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
9587  }
9588  ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
9589  return 0;
9590 }
struct ast_sockaddr local
struct ast_variable * next
#define DEFAULT_STRICT_RTP
List of ICE host candidate mappings.
#define DEFAULT_SRTP_REPLAY_PROTECTION
static int icesupport
#define DEFAULT_TURN_PORT
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
#define DEFAULT_DTMF_TIMEOUT
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 AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
static int rtpstart
#define LOG_WARNING
Definition: logger.h:274
#define MINIMUM_RTP_PORT
#define CONFIG_STATUS_FILEINVALID
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3154
Structure for variables, used for configurations and for channel variables.
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define RTCP_MIN_INTERVALMS
#define var
Definition: ast_expr2f.c:614
static int stun_software_attribute
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
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 ...
Wrapper for an ast_acl linked list.
Definition: acl.h:76
#define NULL
Definition: resample.c:96
#define DEFAULT_RTP_END
static int dtmftimeout
#define ast_rwlock_unlock(a)
Definition: lock.h:232
Socket address structure.
Definition: netsock2.h:97
#define ast_verb(level,...)
Definition: logger.h:463
#define RTCP_MAX_INTERVALMS
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
static int turnport
#define ast_log
Definition: astobj2.c:42
static struct sockaddr_in stunaddr
static const int STANDARD_STUN_PORT
Definition: stun.h:60
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define MAXIMUM_RTP_PORT
static struct ast_acl_list * stun_acl
static struct ast_acl_list * ice_acl
#define DEFAULT_LEARNING_MIN_DURATION
#define CONFIG_STATUS_FILEUNCHANGED
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
#define DEFAULT_LEARNING_MIN_SEQUENTIAL
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define DEFAULT_RTP_START
static int srtp_replay_protection
static void host_candidate_overrides_clear(void)
Helper function which clears the ICE host candidate mapping.
static int strictrtp
static struct stasis_subscription * acl_change_sub
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition: acl.c:233
static ast_rwlock_t ice_acl_lock
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
Definition: test_acl.c:111
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
#define RTCP_DEFAULT_INTERVALMS
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int reload(void)
Definition: cdr_mysql.c:741
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *result,...)
The argument parsing routine.
Definition: main/config.c:3657
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
Structure used to handle boolean flags.
Definition: utils.h:199
#define DEFAULT_ICESUPPORT
struct ast_sockaddr advertised
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
static int learning_min_duration
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
static pj_str_t turnaddr
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
static pj_str_t turnpassword
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
Definition: acl.c:430
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968
Structure which contains ICE host candidate mapping information.
static int learning_min_sequential
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1025
#define DEFAULT_DTLS_MTU
static int rtcpinterval
#define CALC_LEARNING_MIN_DURATION(count)
Calculate the min learning duration in ms.
static ast_rwlock_t stun_acl_lock
#define DEFAULT_STUN_SOFTWARE_ATTRIBUTE
static pj_str_t turnusername
static int rtpend

◆ rtp_sendto()

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

Definition at line 3309 of file res_rtp_asterisk.c.

References __rtp_sendto(), and ast_rtp_instance_get_data().

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

3310 {
3311  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
3312  int hdrlen = 12;
3313  int res;
3314 
3315  if ((res = __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1)) > 0) {
3316  rtp->txcount++;
3317  rtp->txoctetcount += (res - hdrlen);
3318  }
3319 
3320  return res;
3321 }
RTP session description.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ rtp_terminate_pjproject()

static void rtp_terminate_pjproject ( void  )
static

Definition at line 9599 of file res_rtp_asterisk.c.

References ast_pjproject_caching_pool_destroy(), cachingpool, pj_thread_register_check(), timer_terminate, and timer_thread.

Referenced by load_module(), and unload_module().

9600 {
9602 
9603  if (timer_thread) {
9604  timer_terminate = 1;
9605  pj_thread_join(timer_thread);
9606  pj_thread_destroy(timer_thread);
9607  }
9608 
9610  pj_shutdown();
9611 }
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
static pj_caching_pool cachingpool
Pool factory used by pjlib to allocate memory.
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 timer_terminate
Used to tell the timer thread to terminate.
static pj_thread_t * timer_thread
Thread executing the timer heap.

◆ rtp_transport_wide_cc_feedback_produce()

static int rtp_transport_wide_cc_feedback_produce ( const void *  data)
static

Definition at line 6900 of file res_rtp_asterisk.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_debug_rtcp, ast_log, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_data(), AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC, AST_RTP_RTCP_RTPFB, ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_tvdiff_us(), AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_GET_ADDR, AST_VECTOR_RESET, AST_VECTOR_SIZE, rtp_transport_wide_cc_packet_statistics::delta, errno, LOG_ERROR, put_unaligned_time24(), put_unaligned_uint16(), put_unaligned_uint32(), rtp_transport_wide_cc_packet_statistics::received, rtcp_sendto(), rtp_transport_wide_cc_feedback_status_append(), rtp_transport_wide_cc_packet_statistics::seqno, ast_rtp::ssrc, statistics(), ast_rtp::themssrc, and timeval2ntp().

Referenced by rtp_instance_parse_transport_wide_cc().

6901 {
6902  struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
6903  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
6904  unsigned char *rtcpheader;
6905  char bdata[1024];
6906  struct rtp_transport_wide_cc_packet_statistics *first_packet;
6907  struct rtp_transport_wide_cc_packet_statistics *previous_packet;
6908  int i;
6909  int status_vector_chunk_bits = 14;
6910  uint16_t status_vector_chunk = (1 << 15) | (1 << 14);
6911  int run_length_chunk_count = 0;
6912  int run_length_chunk_status = -1;
6913  int packet_len = 20;
6914  int delta_len = 0;
6915  int packet_count = 0;
6916  unsigned int received_msw;
6917  unsigned int received_lsw;
6918  struct ast_sockaddr remote_address = { { 0, } };
6919  int res;
6920  int ice;
6921  unsigned int large_delta_count = 0;
6922  unsigned int small_delta_count = 0;
6923  unsigned int lost_count = 0;
6924 
6925  if (!rtp || !rtp->rtcp || rtp->transport_wide_cc.schedid == -1) {
6926  ao2_ref(instance, -1);
6927  return 0;
6928  }
6929 
6930  ao2_lock(instance);
6931 
6932  /* If no packets have been received then do nothing */
6933  if (!AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics)) {
6934  ao2_unlock(instance);
6935  return 1000;
6936  }
6937 
6938  rtcpheader = (unsigned char *)bdata;
6939 
6940  /* The first packet in the vector acts as our base sequence number and reference time */
6941  first_packet = AST_VECTOR_GET_ADDR(&rtp->transport_wide_cc.packet_statistics, 0);
6942  previous_packet = first_packet;
6943 
6944  /* We go through each packet that we have statistics for, adding it either to a status
6945  * vector chunk or a run length chunk. The code tries to be as efficient as possible to
6946  * reduce packet size and will favor run length chunks when it makes sense.
6947  */
6948  for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
6950  int lost = 0;
6951  int res = 0;
6952 
6953  statistics = AST_VECTOR_GET_ADDR(&rtp->transport_wide_cc.packet_statistics, i);
6954 
6955  packet_count++;
6956 
6957  if (first_packet != statistics) {
6958  /* The vector stores statistics in a sorted fashion based on the sequence
6959  * number. This ensures we can detect any packets that have been lost/not
6960  * received by comparing the sequence numbers.
6961  */
6962  lost = statistics->seqno - (previous_packet->seqno + 1);
6963  lost_count += lost;
6964  }
6965 
6966  while (lost) {
6967  /* We append a not received status until all the lost packets have been accounted for */
6968  rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
6969  &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 0);
6970  packet_count++;
6971 
6972  /* If there is no more room left for storing packets stop now, we leave 20
6973  * extra bits at the end just in case.
6974  */
6975  if (packet_len + delta_len + 20 > sizeof(bdata)) {
6976  res = -1;
6977  break;
6978  }
6979 
6980  lost--;
6981  }
6982 
6983  /* If the lost packet appending bailed out because we have no more space, then exit here too */
6984  if (res) {
6985  break;
6986  }
6987 
6988  /* Per the spec the delta is in increments of 250 */
6989  statistics->delta = ast_tvdiff_us(statistics->received, previous_packet->received) / 250;
6990 
6991  /* Based on the delta determine the status of this packet */
6992  if (statistics->delta < 0 || statistics->delta > 127) {
6993  /* Large or negative delta */
6994  rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
6995  &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 2);
6996  delta_len += 2;
6997  large_delta_count++;
6998  } else {
6999  /* Small delta */
7000  rtp_transport_wide_cc_feedback_status_append(rtcpheader, &packet_len, &status_vector_chunk_bits,
7001  &status_vector_chunk, &run_length_chunk_count, &run_length_chunk_status, 1);
7002  delta_len += 1;
7003  small_delta_count++;
7004  }
7005 
7006  previous_packet = statistics;
7007 
7008  /* If there is no more room left in the packet stop handling of any subsequent packets */
7009  if (packet_len + delta_len + 20 > sizeof(bdata)) {
7010  break;
7011  }
7012  }
7013 
7014  if (status_vector_chunk_bits != 14) {
7015  /* If the status vector chunk has packets in it then place it in the RTCP packet */
7016  put_unaligned_uint16(rtcpheader + packet_len, htons(status_vector_chunk));
7017  packet_len += 2;
7018  } else if (run_length_chunk_count) {
7019  /* If there is a run length chunk in progress then place it in the RTCP packet */
7020  put_unaligned_uint16(rtcpheader + packet_len, htons((0 << 15) | (run_length_chunk_status << 13) | run_length_chunk_count));
7021  packet_len += 2;
7022  }
7023 
7024  /* We iterate again to build delta chunks */
7025  for (i = 0; i < AST_VECTOR_SIZE(&rtp->transport_wide_cc.packet_statistics); ++i) {
7027 
7028  statistics = AST_VECTOR_GET_ADDR(&rtp->transport_wide_cc.packet_statistics, i);
7029 
7030  if (statistics->delta < 0 || statistics->delta > 127) {
7031  /* We need 2 bytes to store this delta */
7032  put_unaligned_uint16(rtcpheader + packet_len, htons(statistics->delta));
7033  packet_len += 2;
7034  } else {
7035  /* We can store this delta in 1 byte */
7036  rtcpheader[packet_len] = statistics->delta;
7037  packet_len += 1;
7038  }
7039 
7040  /* If this is the last packet handled by the run length chunk or status vector chunk code
7041  * then we can go no further.
7042  */
7043  if (statistics == previous_packet) {
7044  break;
7045  }
7046  }
7047 
7048  /* Zero pad the end of the packet */
7049  while (packet_len % 4) {
7050  rtcpheader[packet_len++] = 0;
7051  }
7052 
7053  /* Add the general RTCP header information */
7054  put_unaligned_uint32(rtcpheader, htonl((2 << 30) | (AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC << 24)
7055  | (AST_RTP_RTCP_RTPFB << 16) | ((packet_len / 4) - 1)));
7056  put_unaligned_uint32(rtcpheader + 4, htonl(rtp->ssrc));
7057  put_unaligned_uint32(rtcpheader + 8, htonl(rtp->themssrc));
7058 
7059  /* Add the transport-cc specific header information */
7060  put_unaligned_uint32(rtcpheader + 12, htonl((first_packet->seqno << 16) | packet_count));
7061 
7062  timeval2ntp(first_packet->received, &received_msw, &received_lsw);
7063  put_unaligned_time24(rtcpheader + 16, received_msw, received_lsw);
7064  rtcpheader[19] = rtp->transport_wide_cc.feedback_count;
7065 
7066  /* The packet is now fully constructed so send it out */
7067  ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
7068 
7069  ast_debug_rtcp(2, "(%p) RTCP sending transport-cc feedback packet of size '%d' on '%s' with packet count of %d (small = %d, large = %d, lost = %d)\n",
7070  instance, packet_len, ast_rtp_instance_get_channel_id(instance), packet_count, small_delta_count, large_delta_count, lost_count);
7071 
7072  res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len, 0, &remote_address, &ice);
7073  if (res < 0) {
7074  ast_log(LOG_ERROR, "RTCP transport-cc feedback error to %s due to %s\n",
7075  ast_sockaddr_stringify(&remote_address), strerror(errno));
7076  }
7077 
7078  AST_VECTOR_RESET(&rtp->transport_wide_cc.packet_statistics, AST_VECTOR_ELEM_CLEANUP_NOOP);
7079 
7080  rtp->transport_wide_cc.feedback_count++;
7081 
7082  ao2_unlock(instance);
7083 
7084  return 1000;
7085 }
RTP session description.
static void statistics(void)
Definition: utils/frame.c:287
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
Packet statistics (used for transport-cc)
static void put_unaligned_uint16(void *p, unsigned short datum)
Definition: unaligned.h:65
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)
#define ao2_unlock(a)
Definition: astobj2.h:730
Socket address structure.
Definition: netsock2.h:97
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)
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
#define ast_log
Definition: astobj2.c:42
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:670
#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 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
#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
#define AST_RTP_RTCP_FMT_TRANSPORT_WIDE_CC
Definition: rtp_engine.h:311
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
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 put_unaligned_time24(void *p, uint32_t time_msw, uint32_t time_lsw)
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ rtp_transport_wide_cc_feedback_status_append()

static void rtp_transport_wide_cc_feedback_status_append ( unsigned char *  rtcpheader,
int *  packet_len,
int *  status_vector_chunk_bits,
uint16_t *  status_vector_chunk,
int *  run_length_chunk_count,
int *  run_length_chunk_status,
int  status 
)
static

Definition at line 6859 of file res_rtp_asterisk.c.

References put_unaligned_uint16(), rtp_transport_wide_cc_feedback_status_vector_append(), and status.

Referenced by rtp_transport_wide_cc_feedback_produce().

6861 {
6862  if (*run_length_chunk_status != status) {
6863  while (*run_length_chunk_count > 0 && *run_length_chunk_count < 8) {
6864  /* Realistically it only makes sense to use a run length chunk if there were 8 or more
6865  * consecutive packets of the same type, otherwise we could end up making the packet larger
6866  * if we have lots of small blocks of the same type. To help with this we backfill the status
6867  * vector (since it always represents 7 packets). Best case we end up with only that single
6868  * status vector and the rest are run length chunks.
6869  */
6870  rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
6871  status_vector_chunk, *run_length_chunk_status);
6872  *run_length_chunk_count -= 1;
6873  }
6874 
6875  if (*run_length_chunk_count) {
6876  /* There is a run length chunk which needs to be written out */
6877  put_unaligned_uint16(rtcpheader + *packet_len, htons((0 << 15) | (*run_length_chunk_status << 13) | *run_length_chunk_count));
6878  *packet_len += 2;
6879  }
6880 
6881  /* In all cases the run length chunk has to be reset */
6882  *run_length_chunk_count = 0;
6883  *run_length_chunk_status = -1;
6884 
6885  if (*status_vector_chunk_bits == 14) {
6886  /* We aren't in the middle of a status vector so we can try for a run length chunk */
6887  *run_length_chunk_status = status;
6888  *run_length_chunk_count = 1;
6889  } else {
6890  /* We're doing a status vector so populate it accordingly */
6891  rtp_transport_wide_cc_feedback_status_vector_append(rtcpheader, packet_len, status_vector_chunk_bits,
6892  status_vector_chunk, status);
6893  }
6894  } else {
6895  /* This is easy, the run length chunk count can just get bumped up */
6896  *run_length_chunk_count += 1;
6897  }
6898 }
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 void put_unaligned_uint16(void *p, unsigned short datum)
Definition: unaligned.h:65
jack_status_t status
Definition: app_jack.c:146

◆ rtp_transport_wide_cc_feedback_status_vector_append()

static void rtp_transport_wide_cc_feedback_status_vector_append ( unsigned char *  rtcpheader,
int *  packet_len,
int *  status_vector_chunk_bits,
uint16_t *  status_vector_chunk,
int  status 
)
static

Definition at line 6830 of file res_rtp_asterisk.c.

References put_unaligned_uint16().

Referenced by rtp_transport_wide_cc_feedback_status_append().

6832 {
6833  /* Appending this status will use up 2 bits */
6834  *status_vector_chunk_bits -= 2;
6835 
6836  /* We calculate which bits we want to update the status of. Since a status vector
6837  * is 16 bits we take away 2 (for the header), and then we take away any that have
6838  * already been used.
6839  */
6840  *status_vector_chunk |= (status << (16 - 2 - (14 - *status_vector_chunk_bits)));
6841 
6842  /* If there are still bits available we can return early */
6843  if (*status_vector_chunk_bits) {
6844  return;
6845  }
6846 
6847  /* Otherwise we have to place this chunk into the packet */
6848  put_unaligned_uint16(rtcpheader + *packet_len, htons(*status_vector_chunk));
6849  *status_vector_chunk_bits = 14;
6850 
6851  /* The first bit being 1 indicates that this is a status vector chunk and the second
6852  * bit being 1 indicates that we are using 2 bits to represent each status for a
6853  * packet.
6854  */
6855  *status_vector_chunk = (1 << 15) | (1 << 14);
6856  *packet_len += 2;
6857 }
static void put_unaligned_uint16(void *p, unsigned short datum)
Definition: unaligned.h:65
jack_status_t status
Definition: app_jack.c:146

◆ rtp_transport_wide_cc_packet_statistics_cmp()

static int rtp_transport_wide_cc_packet_statistics_cmp ( struct rtp_transport_wide_cc_packet_statistics  a,
struct rtp_transport_wide_cc_packet_statistics  b 
)
static

Definition at line 6824 of file res_rtp_asterisk.c.

References rtp_transport_wide_cc_packet_statistics::seqno.

Referenced by rtp_instance_parse_transport_wide_cc().

6826 {
6827  return a.seqno - b.seqno;
6828 }

◆ rtp_unload_acl()

static void rtp_unload_acl ( ast_rwlock_t lock,
struct ast_acl_list **  acl 
)
static

Definition at line 3471 of file res_rtp_asterisk.c.

References ast_free_acl_list(), ast_rwlock_unlock, and ast_rwlock_wrlock.

Referenced by unload_module().

3472 {
3473  ast_rwlock_wrlock(lock);
3474  *acl = ast_free_acl_list(*acl);
3475  ast_rwlock_unlock(lock);
3476 }
#define ast_rwlock_unlock(a)
Definition: lock.h:232
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
Definition: acl.c:233
#define ast_rwlock_wrlock(a)
Definition: lock.h:234

◆ rtp_write_rtcp_fir()

static void rtp_write_rtcp_fir ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
struct ast_sockaddr remote_address 
)
static

Definition at line 5160 of file res_rtp_asterisk.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_log, ast_rtcp_calculate_sr_rr_statistics(), ast_rtcp_generate_compound_prefix(), ast_rtp_rtcp_report_alloc(), ast_sockaddr_isnull(), errno, LOG_ERROR, put_unaligned_uint32(), RAII_VAR, RTCP_PT_PSFB, rtcp_sendto(), ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::themssrc_valid.

Referenced by ast_rtp_read(), and ast_rtp_write().

5161 {
5162  unsigned char *rtcpheader;
5163  unsigned char bdata[1024];
5164  int packet_len = 0;
5165  int fir_len = 20;
5166  int ice;
5167  int res;
5168  int sr;
5169  RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
5171  ao2_cleanup);
5172 
5173  if (!rtp || !rtp->rtcp) {
5174  return;
5175  }
5176 
5177  if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5178  /*
5179  * RTCP was stopped.
5180  */
5181  return;
5182  }
5183 
5184  if (!rtp->themssrc_valid) {
5185  /* We don't know their SSRC value so we don't know who to update. */
5186  return;
5187  }
5188 
5189  /* Prepare RTCP FIR (PT=206, FMT=4) */
5190  rtp->rtcp->firseq++;
5191  if(rtp->rtcp->firseq == 256) {
5192  rtp->rtcp->firseq = 0;
5193  }
5194 
5195  rtcpheader = bdata;
5196 
5197  ao2_lock(instance);
5198  res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5199 
5200  if (res == 0 || res == 1) {
5201  ao2_unlock(instance);
5202  return;
5203  }
5204 
5205  packet_len += res;
5206 
5207  put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (4 << 24) | (RTCP_PT_PSFB << 16) | ((fir_len/4)-1)));
5208  put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5209  put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(rtp->themssrc));
5210  put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(rtp->themssrc)); /* FCI: SSRC */
5211  put_unaligned_uint32(rtcpheader + packet_len + 16, htonl(rtp->rtcp->firseq << 24)); /* FCI: Sequence number */
5212  res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + fir_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5213  if (res < 0) {
5214  ast_log(LOG_ERROR, "RTCP FIR transmission error: %s\n", strerror(errno));
5215  } else {
5216  ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5217  }
5218 
5219  ao2_unlock(instance);
5220 }
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:331
static int ast_rtcp_generate_compound_prefix(struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
#define ao2_unlock(a)
Definition: astobj2.h:730
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_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_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
unsigned int themssrc
#define LOG_ERROR
Definition: logger.h:285
int errno
#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 RTCP_PT_PSFB

◆ rtp_write_rtcp_psfb()

static void rtp_write_rtcp_psfb ( struct ast_rtp_instance instance,
struct ast_rtp rtp,
struct ast_frame frame,
struct ast_sockaddr remote_address 
)
static

Definition at line 5222 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_write().

5223 {
5224  struct ast_rtp_rtcp_feedback *feedback = frame->data.ptr;
5225  unsigned char *rtcpheader;
5226  unsigned char bdata[1024];
5227  int remb_len = 24;
5228  int ice;
5229  int res;
5230  int sr = 0;
5231  int packet_len = 0;
5232  RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report,
5234  ao2_cleanup);
5235 
5236  if (feedback->fmt != AST_RTP_RTCP_FMT_REMB) {
5237  ast_debug_rtcp(1, "(%p) RTCP provided feedback frame of format %d to write, but only REMB is supported\n",
5238  instance, feedback->fmt);
5239  return;
5240  }
5241 
5242  if (!rtp || !rtp->rtcp) {
5243  return;
5244  }
5245 
5246  /* If REMB support is not enabled don't send this RTCP packet */
5248  ast_debug_rtcp(1, "(%p) RTCP provided feedback REMB report to write, but REMB support not enabled\n",
5249  instance);
5250  return;
5251  }
5252 
5253  if (ast_sockaddr_isnull(&rtp->rtcp->them) || rtp->rtcp->schedid < 0) {
5254  /*
5255  * RTCP was stopped.
5256  */
5257  return;
5258  }
5259 
5260  rtcpheader = bdata;
5261 
5262  ao2_lock(instance);
5263  res = ast_rtcp_generate_compound_prefix(instance, rtcpheader, rtcp_report, &sr);
5264 
5265  if (res == 0 || res == 1) {
5266  ao2_unlock(instance);
5267  return;
5268  }
5269 
5270  packet_len += res;
5271 
5272  put_unaligned_uint32(rtcpheader + packet_len + 0, htonl((2 << 30) | (AST_RTP_RTCP_FMT_REMB << 24) | (RTCP_PT_PSFB << 16) | ((remb_len/4)-1)));
5273  put_unaligned_uint32(rtcpheader + packet_len + 4, htonl(rtp->ssrc));
5274  put_unaligned_uint32(rtcpheader + packet_len + 8, htonl(0)); /* Per the draft, this should always be 0 */
5275  put_unaligned_uint32(rtcpheader + packet_len + 12, htonl(('R' << 24) | ('E' << 16) | ('M' << 8) | ('B'))); /* Unique identifier 'R' 'E' 'M' 'B' */
5276  put_unaligned_uint32(rtcpheader + packet_len + 16, htonl((1 << 24) | (feedback->remb.br_exp << 18) | (feedback->remb.br_mantissa))); /* Number of SSRCs / BR Exp / BR Mantissa */
5277  put_unaligned_uint32(rtcpheader + packet_len + 20, htonl(rtp->ssrc)); /* The SSRC this feedback message applies to */
5278  res = rtcp_sendto(instance, (unsigned int *)rtcpheader, packet_len + remb_len, 0, rtp->bundled ? remote_address : &rtp->rtcp->them, &ice);
5279  if (res < 0) {
5280  ast_log(LOG_ERROR, "RTCP PSFB transmission error: %s\n", strerror(errno));
5281  } else {
5282  ast_rtcp_calculate_sr_rr_statistics(instance, rtcp_report, rtp->bundled ? *remote_address : rtp->rtcp->them, ice, sr);
5283  }
5284 
5285  ao2_unlock(instance);
5286 }
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:331
static int ast_rtcp_generate_compound_prefix(struct ast_rtp_instance *instance, unsigned char *rtcpheader, struct ast_rtp_rtcp_report *report, int *sr)
An object that represents data received in a feedback report.
Definition: rtp_engine.h:358
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
#define ao2_unlock(a)
Definition: astobj2.h:730
unsigned int fmt
Definition: rtp_engine.h:359
struct ast_rtp_rtcp_feedback_remb remb
Definition: rtp_engine.h:361
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_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 ast_debug_rtcp(sublevel,...)
Log debug level RTCP information.
Definition: rtp_engine.h:2873
#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
#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)
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
union ast_frame::@263 data
static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
#define RTCP_PT_PSFB
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:309

◆ set_rtp_rtcp_schedid()

static void set_rtp_rtcp_schedid ( struct ast_rtp_instance instance,
int  id 
)
static

Definition at line 2463 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and id.

2464 {
2465  struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
2466 
2467  if (rtp && rtp->rtcp) {
2468  rtp->rtcp->schedid = id;
2469  }
2470 }
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
enum queue_result id
Definition: app_queue.c:1507

◆ should_drop_packets()

static int should_drop_packets ( struct ast_sockaddr addr)
static

Definition at line 7583 of file res_rtp_asterisk.c.

References rtp_drop_packets_data::addr, ast_sockaddr_cmp(), ast_sockaddr_cmp_addr(), ast_sockaddr_isnull(), ast_tvcmp(), ast_tvnow(), ast_tvzero(), drop_packets_data, drop_packets_data_update(), rtp_drop_packets_data::interval, rtp_drop_packets_data::next, rtp_drop_packets_data::num_dropped, rtp_drop_packets_data::num_to_drop, and rtp_drop_packets_data::port.

Referenced by ast_rtp_read().

7584 {
7585  struct timeval tv;
7586 
7588  return 0;
7589  }
7590 
7591  /*
7592  * If an address has been specified then filter on it, and also the port if
7593  * it too was included.
7594  */
7599  /* Address and/or port does not match */
7600  return 0;
7601  }
7602 
7603  /* Keep dropping packets until we've reached the total to drop */
7606  return 1;
7607  }
7608 
7609  /*
7610  * Once the set number of packets has been dropped check to see if it's
7611  * time to drop more.
7612  */
7613 
7615  /* If no interval then drop specified number of packets and be done */
7617  return 0;
7618  }
7619 
7620  tv = ast_tvnow();
7621  if (ast_tvcmp(tv, drop_packets_data.next) == -1) {
7622  /* Still waiting for the next time interval to elapse */
7623  return 0;
7624  }
7625 
7626  /*
7627  * The next time interval has elapsed so update the tracking structure
7628  * in order to start dropping more packets, and figure out when the next
7629  * time interval is.
7630  */
7632  return 1;
7633 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares the addresses of two ast_sockaddr structures.
Definition: netsock2.c:413
struct ast_sockaddr addr
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
static void drop_packets_data_update(struct timeval tv)
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
Definition: time.h:128
static struct rtp_drop_packets_data drop_packets_data

◆ stun_address_is_blacklisted()

static int stun_address_is_blacklisted ( const struct ast_sockaddr addr)
static

Definition at line 3510 of file res_rtp_asterisk.c.

References ast_apply_acl_nolog(), ast_rwlock_rdlock, ast_rwlock_unlock, AST_SENSE_DENY, and result.

Referenced by rtp_add_candidates_to_ice().

3511 {
3512  int result = 0;
3513 
3515  result |= ast_apply_acl_nolog(stun_acl, addr) == AST_SENSE_DENY;
3517 
3518  return result;
3519 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
enum ast_acl_sense ast_apply_acl_nolog(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address, don&#39;t log failure.
Definition: acl.c:804
#define ast_rwlock_unlock(a)
Definition: lock.h:232
static struct ast_acl_list * stun_acl
static PGresult * result
Definition: cel_pgsql.c:88
static ast_rwlock_t stun_acl_lock

◆ timer_worker_thread()

static int timer_worker_thread ( void *  data)
static

Worker thread for timerheap.

Definition at line 2727 of file res_rtp_asterisk.c.

References ast_rtp_ioqueue_thread::ioqueue, NULL, ast_rtp_ioqueue_thread::pool, timer_heap, and timer_terminate.

Referenced by load_module().

2728 {
2729  pj_ioqueue_t *ioqueue;
2730 
2731  if (pj_ioqueue_create(pool, 1, &ioqueue) != PJ_SUCCESS) {
2732  return -1;
2733  }
2734 
2735  while (!timer_terminate) {
2736  const pj_time_val delay = {0, 10};
2737 
2738  pj_timer_heap_poll(timer_heap, NULL);
2739  pj_ioqueue_poll(ioqueue, &delay);
2740  }
2741 
2742  return 0;
2743 }
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define NULL
Definition: resample.c:96
static int timer_terminate
Used to tell the timer thread to terminate.
static pj_timer_heap_t * timer_heap
Global timer heap.

◆ timeval2ntp()

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

Definition at line 4392 of file res_rtp_asterisk.c.

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

4393 {
4394  unsigned int sec, usec, frac;
4395  sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
4396  usec = tv.tv_usec;
4397  /*
4398  * Convert usec to 0.32 bit fixed point without overflow.
4399  *
4400  * = usec * 2^32 / 10^6
4401  * = usec * 2^32 / (2^6 * 5^6)
4402  * = usec * 2^26 / 5^6
4403  *
4404  * The usec value needs 20 bits to represent 999999 usec. So
4405  * splitting the 2^26 to get the most precision using 32 bit
4406  * values gives:
4407  *
4408  * = ((usec * 2^12) / 5^6) * 2^14
4409  *
4410  * Splitting the division into two stages preserves all the
4411  * available significant bits of usec over doing the division
4412  * all at once.
4413  *
4414  * = ((((usec * 2^12) / 5^3) * 2^7) / 5^3) * 2^7
4415  */
4416  frac = ((((usec << 12) / 125) << 7) / 125) << 7;
4417  *msw = sec;
4418  *lsw = frac;
4419 }

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 9709 of file res_rtp_asterisk.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_rtp_engine_unregister(), ASTERISK_GPL_KEY, HAVE_PJPROJECT, host_candidate_overrides_clear(), load_module(), pj_thread_register_check(), reload(), reload_module(), rtp_terminate_pjproject(), rtp_unload_acl(), and stasis_unsubscribe_and_join().

9710 {
9713 
9714 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
9715  if (dtls_bio_methods) {
9716  BIO_meth_free(dtls_bio_methods);
9717  }
9718 #endif
9719 
9720 #ifdef HAVE_PJPROJECT
9724 
9728 #endif
9729 
9730  return 0;
9731 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
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...
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:364
static struct ast_acl_list * stun_acl
static struct ast_acl_list * ice_acl
static void rtp_terminate_pjproject(void)
static void host_candidate_overrides_clear(void)
Helper function which clears the ICE host candidate mapping.
static struct stasis_subscription * acl_change_sub
static ast_rwlock_t ice_acl_lock
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
static struct ast_cli_entry cli_rtp[]
static struct ast_rtp_engine asterisk_rtp_engine
static ast_rwlock_t stun_acl_lock
static void rtp_unload_acl(ast_rwlock_t *lock, struct ast_acl_list **acl)

◆ update_address_with_ice_candidate()

static void update_address_with_ice_candidate ( pj_ice_sess *  ice,
enum ast_rtp_ice_component_type  component,
struct ast_sockaddr cand_address 
)
static

Helper function which updates an ast_sockaddr with the candidate used for the component.

Definition at line 749 of file res_rtp_asterisk.c.

References ast_sockaddr_parse(), and ast_sockaddr_set_port.

Referenced by ast_rtp_ice_start_media().

751 {
752  char address[PJ_INET6_ADDRSTRLEN];
753 
754  if (component < 1 || !ice->comp[component - 1].valid_check) {
755  return;
756  }
757 
758  ast_sockaddr_parse(cand_address,
759  pj_sockaddr_print(&ice->comp[component - 1].valid_check->rcand->addr, address,
760  sizeof(address), 0), 0);
761  ast_sockaddr_set_port(cand_address,
762  pj_sockaddr_get_port(&ice->comp[component - 1].valid_check->rcand->addr));
763 }
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 ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537

◆ update_jitter_stats()

static void update_jitter_stats ( struct ast_rtp rtp,
unsigned int  ia_jitter 
)
static

Definition at line 5824 of file res_rtp_asterisk.c.

References calc_mean_and_standard_deviation(), and if().

Referenced by ast_rtcp_interpret().

5825 {
5826  double reported_jitter;
5827 
5828  rtp->rtcp->reported_jitter = ia_jitter;
5829  reported_jitter = (double) rtp->rtcp->reported_jitter;
5830  if (rtp->rtcp->reported_jitter_count == 0) {
5831  rtp->rtcp->reported_minjitter = reported_jitter;
5832  }
5833  if (reported_jitter < rtp->rtcp->reported_minjitter) {
5834  rtp->rtcp->reported_minjitter = reported_jitter;
5835  }
5836  if (reported_jitter > rtp->rtcp->reported_maxjitter) {
5837  rtp->rtcp->reported_maxjitter = reported_jitter;
5838  }
5839 
5840  calc_mean_and_standard_deviation(reported_jitter, &rtp->rtcp->reported_normdev_jitter,
5841  &rtp->rtcp->reported_stdev_jitter, &rtp->rtcp->reported_jitter_count);
5842 }
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
static void calc_mean_and_standard_deviation(double new_sample, double *mean, double *std_dev, unsigned int *count)

◆ update_lost_stats()

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

Definition at line 5848 of file res_rtp_asterisk.c.

References calc_mean_and_standard_deviation(), and if().

Referenced by ast_rtcp_interpret().

5849 {
5850  double reported_lost;
5851 
5852  rtp->rtcp->reported_lost = lost_packets;
5853  reported_lost = (double)rtp->rtcp->reported_lost;
5854  if (rtp->rtcp->reported_lost_count == 0) {
5855  rtp->rtcp->reported_minlost = reported_lost;
5856  }
5857  if (reported_lost < rtp->rtcp->reported_minlost) {
5858  rtp->rtcp->reported_minlost = reported_lost;
5859  }
5860  if (reported_lost > rtp->rtcp->reported_maxlost) {
5861  rtp->rtcp->reported_maxlost = reported_lost;
5862  }
5863 
5864  calc_mean_and_standard_deviation(reported_lost, &rtp->rtcp->reported_normdev_lost,
5865  &rtp->rtcp->reported_stdev_lost, &rtp->rtcp->reported_lost_count);
5866 }
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
static void calc_mean_and_standard_deviation(double new_sample, double *mean, double *std_dev, unsigned int *count)

◆ update_rtt_stats()

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

Definition at line 5768 of file res_rtp_asterisk.c.

References calc_mean_and_standard_deviation(), NULL, and timeval2ntp().

Referenced by ast_rtcp_interpret().

5769 {
5770  struct timeval now;
5771  struct timeval rtt_tv;
5772  unsigned int msw;
5773  unsigned int lsw;
5774  unsigned int rtt_msw;
5775  unsigned int rtt_lsw;
5776  unsigned int lsr_a;
5777  unsigned int rtt;
5778 
5779  gettimeofday(&now, NULL);
5780  timeval2ntp(now, &msw, &lsw);
5781 
5782  lsr_a = ((msw & 0x0000ffff) << 16) | ((lsw & 0xffff0000) >> 16);
5783  rtt = lsr_a - lsr - dlsr;
5784  rtt_msw = (rtt & 0xffff0000) >> 16;
5785  rtt_lsw = (rtt & 0x0000ffff);
5786  rtt_tv.tv_sec = rtt_msw;
5787  /*
5788  * Convert 16.16 fixed point rtt_lsw to usec without
5789  * overflow.
5790  *
5791  * = rtt_lsw * 10^6 / 2^16
5792  * = rtt_lsw * (2^6 * 5^6) / 2^16
5793  * = rtt_lsw * 5^6 / 2^10
5794  *
5795  * The rtt_lsw value is in 16.16 fixed point format and 5^6
5796  * requires 14 bits to represent. We have enough space to
5797  * directly do the conversion because there is no integer
5798  * component in rtt_lsw.
5799  */
5800  rtt_tv.tv_usec = (rtt_lsw * 15625) >> 10;
5801  rtp->rtcp->rtt = (double)rtt_tv.tv_sec + ((double)rtt_tv.tv_usec / 1000000);
5802  if (lsr_a - dlsr < lsr) {
5803  return 1;
5804  }
5805 
5806  rtp->rtcp->accumulated_transit += rtp->rtcp->rtt;
5807  if (rtp->rtcp->rtt_count == 0 || rtp->rtcp->minrtt > rtp->rtcp->rtt) {
5808  rtp->rtcp->minrtt = rtp->rtcp->rtt;
5809  }
5810  if (rtp->rtcp->maxrtt < rtp->rtcp->rtt) {
5811  rtp->rtcp->maxrtt = rtp->rtcp->rtt;
5812  }
5813 
5814  calc_mean_and_standard_deviation(rtp->rtcp->rtt, &rtp->rtcp->normdevrtt,
5815  &rtp->rtcp->stdevrtt, &rtp->rtcp->rtt_count);
5816 
5817  return 0;
5818 }
static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
#define NULL
Definition: resample.c:96
static void calc_mean_and_standard_deviation(double new_sample, double *mean, double *std_dev, unsigned int *count)

◆ use_random()

static unsigned int use_random ( struct ast_cli_args a,
int  pos,
unsigned int  index 
)
static

Definition at line 9207 of file res_rtp_asterisk.c.

References ast_cli_args::argv, and ast_strlen_zero.

Referenced by handle_cli_rtp_drop_incoming_packets().

9208 {
9209  return pos >= index && !ast_strlen_zero(a->argv[index - 1]) &&
9210  !strcasecmp(a->argv[index - 1], "random");
9211 }
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char *const * argv
Definition: cli.h:161

Variable Documentation

◆ __mod_info

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

Definition at line 9742 of file res_rtp_asterisk.c.

◆ acl_change_sub

struct stasis_subscription* acl_change_sub = NULL
static

Definition at line 221 of file res_rtp_asterisk.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 9742 of file res_rtp_asterisk.c.

◆ ast_rtp_ice

struct ast_rtp_engine_ice ast_rtp_ice
static

Definition at line 1753 of file res_rtp_asterisk.c.

◆ ast_rtp_ice_sess_cb

pj_ice_sess_cb ast_rtp_ice_sess_cb
static

Definition at line 2717 of file res_rtp_asterisk.c.

◆ ast_rtp_test

struct ast_rtp_engine_test ast_rtp_test
static

Definition at line 2472 of file res_rtp_asterisk.c.

◆ ast_rtp_turn_rtcp_sock_cb

pj_turn_sock_cb ast_rtp_turn_rtcp_sock_cb
static
Initial value:
= {
}
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_rtcp_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, pj_turn_state_t new_state)

Definition at line 1448 of file res_rtp_asterisk.c.

Referenced by ast_rtp_ice_turn_request().

◆ ast_rtp_turn_rtp_sock_cb

pj_turn_sock_cb ast_rtp_turn_rtp_sock_cb
static
Initial value:
= {
}
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_rtp_data(pj_turn_sock *turn_sock, void *pkt, unsigned pkt_len, const pj_sockaddr_t *peer_addr, unsigned addr_len)

Definition at line 1382 of file res_rtp_asterisk.c.

Referenced by ast_rtp_ice_turn_request().

◆ asterisk_rtp_engine

struct ast_rtp_engine asterisk_rtp_engine
static

Definition at line 2484 of file res_rtp_asterisk.c.

◆ cachingpool

pj_caching_pool cachingpool
static

Pool factory used by pjlib to allocate memory.

Definition at line 233 of file res_rtp_asterisk.c.

Referenced by ast_rtp_ice_turn_request(), ice_create(), load_module(), rtp_ioqueue_thread_get_or_create(), and rtp_terminate_pjproject().

◆ cli_rtp

struct ast_cli_entry cli_rtp[]
static

Definition at line 9336 of file res_rtp_asterisk.c.

◆ drop_packets_data

struct rtp_drop_packets_data drop_packets_data
static

◆ dtmftimeout

int dtmftimeout = DEFAULT_DTMF_TIMEOUT
static

Definition at line 193 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), process_dtmf_rfc2833(), and rtp_reload().

◆ host_candidates

struct host_candidates host_candidates = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ ice_acl

struct ast_acl_list* ice_acl = NULL
static

ACL for ICE addresses

Definition at line 225 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ ice_acl_lock

ast_rwlock_t ice_acl_lock = AST_RWLOCK_INIT_VALUE
static

Definition at line 226 of file res_rtp_asterisk.c.

◆ icesupport

int icesupport = DEFAULT_ICESUPPORT
static

◆ ioqueues

struct ioqueues ioqueues = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ learning_min_duration

int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION
static

Lowest acceptable timeout between the first and the last sequential RTP frame.

Definition at line 208 of file res_rtp_asterisk.c.

Referenced by rtp_learning_rtp_seq_update(), and rtp_reload().

◆ learning_min_sequential

int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL
static

Number of sequential RTP frames needed from a single source during learning mode to accept new source.

Definition at line 207 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), rtp_learning_rtp_seq_update(), rtp_learning_seq_init(), and rtp_reload().

◆ lo6

struct ast_sockaddr lo6 = { .len = 0 }
static

Definition at line 222 of file res_rtp_asterisk.c.

◆ pj_thread_storage

struct ast_threadstorage pj_thread_storage = { .once = PTHREAD_ONCE_INIT , .key_init = __init_pj_thread_storage , .custom_init = NULL , }
static

Definition at line 862 of file res_rtp_asterisk.c.

Referenced by pj_thread_register_check().

◆ pool

pj_pool_t* pool
static

◆ res_srtp

struct ast_srtp_res* res_srtp

Definition at line 177 of file rtp_engine.c.

◆ res_srtp_policy

struct ast_srtp_policy_res* res_srtp_policy

Definition at line 178 of file rtp_engine.c.

Referenced by ast_rtp_engine_srtp_is_registered().

◆ rtcpdebugaddr

struct ast_sockaddr rtcpdebugaddr
static

Debug RTCP packets to/from this host

Definition at line 200 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_debug(), rtcp_debug_test_addr(), and rtcp_do_debug_ip().

◆ rtcpdebugport

int rtcpdebugport
static

Debug only RTCP packets from IP or IP+Port if port is > 0

Definition at line 202 of file res_rtp_asterisk.c.

Referenced by rtcp_debug_test_addr(), and rtcp_do_debug_ip().

◆ rtcpinterval

int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static

Time between rtcp reports in millisecs

Definition at line 198 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_calc_interval(), and rtp_reload().

◆ rtcpstats

int rtcpstats
static

Are we debugging RTCP?

Definition at line 197 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_stats().

◆ rtpdebugaddr

struct ast_sockaddr rtpdebugaddr
static

Debug packets to/from this host

Definition at line 199 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_set_debug(), rtp_debug_test_addr(), and rtp_do_debug_ip().

◆ rtpdebugport

int rtpdebugport
static

Debug only RTP packets from IP or IP+Port if port is > 0

Definition at line 201 of file res_rtp_asterisk.c.

Referenced by rtp_debug_test_addr(), and rtp_do_debug_ip().

◆ rtpend

int rtpend = DEFAULT_RTP_END
static

Last port for RTP sessions (set in rtp.conf)

Definition at line 196 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), rtp_allocate_transport(), and rtp_reload().

◆ rtpstart

int rtpstart = DEFAULT_RTP_START
static

First port for RTP sessions (set in rtp.conf)

Definition at line 195 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_settings(), rtp_allocate_transport(), and rtp_reload().

◆ srtp_replay_protection

int srtp_replay_protection = DEFAULT_SRTP_REPLAY_PROTECTION
static

◆ strictrtp

int strictrtp = DEFAULT_STRICT_RTP
static

Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode.

Definition at line 206 of file res_rtp_asterisk.c.

Referenced by ast_rtp_ice_start_media(), ast_rtp_remote_address_set(), handle_cli_rtp_settings(), rtp_allocate_transport(), rtp_learning_rtp_seq_update(), and rtp_reload().

◆ stun_acl

struct ast_acl_list* stun_acl = NULL
static

ACL for STUN requests

Definition at line 229 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

◆ stun_acl_lock

ast_rwlock_t stun_acl_lock = AST_RWLOCK_INIT_VALUE
static

Definition at line 230 of file res_rtp_asterisk.c.

◆ stun_software_attribute

int stun_software_attribute = DEFAULT_STUN_SOFTWARE_ATTRIBUTE
static

Definition at line 215 of file res_rtp_asterisk.c.

Referenced by ast_rtp_ice_turn_request(), ice_create(), and rtp_reload().

◆ stunaddr

struct sockaddr_in stunaddr
static

Definition at line 216 of file res_rtp_asterisk.c.

Referenced by rtp_add_candidates_to_ice(), and rtp_reload().

◆ timer_heap

pj_timer_heap_t* timer_heap
static

Global timer heap.

Definition at line 239 of file res_rtp_asterisk.c.

Referenced by ast_rtp_ice_start(), ice_create(), load_module(), and timer_worker_thread().

◆ timer_terminate

int timer_terminate
static

Used to tell the timer thread to terminate.

Definition at line 245 of file res_rtp_asterisk.c.

Referenced by rtp_terminate_pjproject(), and timer_worker_thread().

◆ timer_thread

pj_thread_t* timer_thread
static

Thread executing the timer heap.

Definition at line 242 of file res_rtp_asterisk.c.

Referenced by load_module(), and rtp_terminate_pjproject().

◆ turnaddr

pj_str_t turnaddr
static

Definition at line 217 of file res_rtp_asterisk.c.

Referenced by rtp_add_candidates_to_ice(), and rtp_reload().

◆ turnpassword

pj_str_t turnpassword
static

Definition at line 220 of file res_rtp_asterisk.c.

Referenced by rtp_add_candidates_to_ice(), and rtp_reload().

◆ turnport

int turnport = DEFAULT_TURN_PORT
static

Definition at line 218 of file res_rtp_asterisk.c.

Referenced by rtp_add_candidates_to_ice(), and rtp_reload().

◆ turnusername

pj_str_t turnusername
static

Definition at line 219 of file res_rtp_asterisk.c.

Referenced by rtp_add_candidates_to_ice(), and rtp_reload().