mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-13 15:50:59 +00:00
FSRTP-14
This commit is contained in:
parent
9a74958b22
commit
70d73cafb7
@ -116,6 +116,7 @@
|
||||
#include "switch_utils.h"
|
||||
#include "switch_caller.h"
|
||||
#include "switch_frame.h"
|
||||
#include "switch_rtcp_frame.h"
|
||||
#include "switch_module_interfaces.h"
|
||||
#include "switch_channel.h"
|
||||
#include "switch_buffer.h"
|
||||
|
74
src/include/switch_rtcp_frame.h
Normal file
74
src/include/switch_rtcp_frame.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Sherwin Sim
|
||||
*
|
||||
*
|
||||
* switch_rtcp_frame.h -- RTCP Frame Structure
|
||||
*
|
||||
*/
|
||||
/*! \file switch_rtcp_frame.h
|
||||
\brief RTCP Frame Structure
|
||||
*/
|
||||
|
||||
#ifndef SWITCH_RTCP_FRAME_H
|
||||
#define SWITCH_RTCP_FRAME_H
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
/*! \brief An abstraction of a rtcp frame */
|
||||
struct switch_rtcp_frame {
|
||||
|
||||
uint16_t report_count;
|
||||
|
||||
uint16_t packet_type;
|
||||
|
||||
uint32_t ssrc;
|
||||
|
||||
uint32_t ntp_msw;
|
||||
|
||||
uint32_t ntp_lsw;
|
||||
|
||||
uint32_t timestamp;
|
||||
|
||||
uint32_t packet_count;
|
||||
|
||||
uint32_t octect_count;
|
||||
|
||||
};
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
@ -41,6 +41,7 @@
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
#define SWITCH_RTP_MAX_BUF_LEN 16384
|
||||
#define SWITCH_RTCP_MAX_BUF_LEN 16384
|
||||
#define SWITCH_RTP_MAX_CRYPTO_LEN 64
|
||||
#define SWITCH_RTP_KEY_LEN 30
|
||||
#define SWITCH_RTP_CRYPTO_KEY_32 "AES_CM_128_HMAC_SHA1_32"
|
||||
@ -213,6 +214,13 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session);
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin);
|
||||
|
||||
/*!
|
||||
\brief Activate sending RTCP Sender Reports (SR's)
|
||||
\param send_rate interval in milliseconds to send at
|
||||
\return SWITCH_STATUS_SUCCESS
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate);
|
||||
|
||||
/*!
|
||||
\brief Acvite a jitter buffer on an RTP session
|
||||
\param rtp_session the rtp session
|
||||
@ -347,6 +355,15 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_sessi
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_frame_t *frame, switch_io_flag_t io_flags);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Read RTCP data from a given RTP session without copying
|
||||
\param rtp_session the RTP session to read from
|
||||
\param frame an RTCP frame to populate with information
|
||||
\return the number of bytes read
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtcp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_rtcp_frame_t *frame);
|
||||
|
||||
SWITCH_DECLARE(void) rtp_flush_read_buffer(switch_rtp_t *rtp_session, switch_rtp_flush_t flush);
|
||||
|
||||
/*!
|
||||
|
@ -534,7 +534,8 @@ typedef enum {
|
||||
SWITCH_ZRTP_FLAG_SECURE_MITM_RECV = (1 << 26),
|
||||
SWITCH_RTP_FLAG_DEBUG_RTP_READ = (1 << 27),
|
||||
SWITCH_RTP_FLAG_DEBUG_RTP_WRITE = (1 << 28),
|
||||
SWITCH_RTP_FLAG_VIDEO = (1 << 29)
|
||||
SWITCH_RTP_FLAG_VIDEO = (1 << 29),
|
||||
SWITCH_RTP_FLAG_ENABLE_RTCP = (1 << 30)
|
||||
} switch_rtp_flag_enum_t;
|
||||
typedef uint32_t switch_rtp_flag_t;
|
||||
|
||||
@ -607,6 +608,35 @@ typedef struct {
|
||||
#pragma pack(pop, r1)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, r1, 1)
|
||||
#endif
|
||||
|
||||
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
|
||||
typedef struct {
|
||||
unsigned version:2; /* protocol version */
|
||||
unsigned p:1; /* padding flag */
|
||||
unsigned count:5; /* number of reception report blocks */
|
||||
unsigned type:8; /* packet type */
|
||||
unsigned length:16; /* length in 32-bit words - 1 */
|
||||
} switch_rtcp_hdr_t;
|
||||
|
||||
#else /* BIG_ENDIAN */
|
||||
|
||||
typedef struct {
|
||||
unsigned count:5; /* number of reception report blocks */
|
||||
unsigned p:1; /* padding flag */
|
||||
unsigned version:2; /* protocol version */
|
||||
unsigned type:8; /* packet type */
|
||||
unsigned length:16; /* length in 32-bit words - 1 */
|
||||
} switch_rtcp_hdr_t;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop, r1)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\enum switch_priority_t
|
||||
\brief Priority Indication
|
||||
@ -1352,6 +1382,7 @@ typedef enum {
|
||||
SWITCH_EVENT_SERVER_DISCONNECTED,
|
||||
SWITCH_EVENT_SEND_INFO,
|
||||
SWITCH_EVENT_RECV_INFO,
|
||||
SWITCH_EVENT_RECV_RTCP_MESSAGE,
|
||||
SWITCH_EVENT_CALL_SECURE,
|
||||
SWITCH_EVENT_NAT,
|
||||
SWITCH_EVENT_RECORD_START,
|
||||
@ -1472,6 +1503,7 @@ typedef uint16_t switch_port_t;
|
||||
typedef uint8_t switch_payload_t;
|
||||
typedef struct switch_app_log switch_app_log_t;
|
||||
typedef struct switch_rtp switch_rtp_t;
|
||||
typedef struct switch_rtcp switch_rtcp_t;
|
||||
typedef struct switch_core_session_message switch_core_session_message_t;
|
||||
typedef struct switch_event_header switch_event_header_t;
|
||||
typedef struct switch_event switch_event_t;
|
||||
@ -1479,6 +1511,7 @@ typedef struct switch_event_subclass switch_event_subclass_t;
|
||||
typedef struct switch_event_node switch_event_node_t;
|
||||
typedef struct switch_loadable_module switch_loadable_module_t;
|
||||
typedef struct switch_frame switch_frame_t;
|
||||
typedef struct switch_rtcp_frame switch_rtcp_frame_t;
|
||||
typedef struct switch_channel switch_channel_t;
|
||||
typedef struct switch_file_handle switch_file_handle_t;
|
||||
typedef struct switch_core_session switch_core_session_t;
|
||||
|
@ -802,6 +802,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
int payload = 0;
|
||||
uint32_t sanity = 1000;
|
||||
switch_rtcp_frame_t rtcp_frame;
|
||||
|
||||
switch_assert(tech_pvt != NULL);
|
||||
|
||||
@ -859,6 +860,50 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Try to read an RTCP frame, if successful raise an event */
|
||||
if (switch_rtcp_zerocopy_read_frame(tech_pvt->rtp_session, &rtcp_frame) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_t *event;
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_RECV_RTCP_MESSAGE) == SWITCH_STATUS_SUCCESS) {
|
||||
char buf[30];
|
||||
|
||||
char* uuid = switch_core_session_get_uuid(session);
|
||||
if (uuid) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%.8x", rtcp_frame.ssrc);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_msw);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_lsw);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", rtcp_frame.timestamp);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", rtcp_frame.packet_count);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", rtcp_frame.octect_count);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%lu", tech_pvt->read_frame.timestamp);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", tech_pvt->read_frame.rate);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%lu", switch_time_now());
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", buf);
|
||||
|
||||
switch_event_fire(&event);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Dispatched RTCP event\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Fast PASS! */
|
||||
if (switch_test_flag((&tech_pvt->read_frame), SFF_PROXY_PACKET)) {
|
||||
|
@ -466,6 +466,7 @@ struct sofia_profile {
|
||||
char *record_path;
|
||||
char *presence_hosts;
|
||||
char *challenge_realm;
|
||||
char *rtcp_interval_msec;
|
||||
sofia_cid_type_t cid_type;
|
||||
sofia_dtmf_t dtmf_type;
|
||||
int auto_restart;
|
||||
|
@ -2459,6 +2459,8 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
profile->hold_music = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "outbound-proxy")) {
|
||||
profile->outbound_proxy = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "rtcp-interval-msec")) {
|
||||
profile->rtcp_interval_msec = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "session-timeout")) {
|
||||
int v_session_timeout = atoi(val);
|
||||
if (v_session_timeout >= 0) {
|
||||
@ -2996,6 +2998,8 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
profile->hold_music = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "outbound-proxy")) {
|
||||
profile->outbound_proxy = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "rtcp-interval-msec")) {
|
||||
profile->rtcp_interval_msec = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "session-timeout")) {
|
||||
int v_session_timeout = atoi(val);
|
||||
if (v_session_timeout >= 0) {
|
||||
|
@ -2725,6 +2725,15 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
switch_rtp_activate_stun_ping(tech_pvt->rtp_session, tech_pvt->stun_ip, tech_pvt->stun_port, stun_ping,
|
||||
(tech_pvt->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0);
|
||||
}
|
||||
|
||||
if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_interval_msec")) || (val = tech_pvt->profile->rtcp_interval_msec)) {
|
||||
int interval = atoi(val);
|
||||
if (interval < 100 || interval > 5000) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
|
||||
} else {
|
||||
switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval);
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec"))) {
|
||||
int len = atoi(val);
|
||||
|
@ -180,6 +180,7 @@ static char *EVENT_NAMES[] = {
|
||||
"SERVER_DISCONNECTED",
|
||||
"SEND_INFO",
|
||||
"RECV_INFO",
|
||||
"RECV_RTCP_MESSAGE",
|
||||
"CALL_SECURE",
|
||||
"NAT",
|
||||
"RECORD_START",
|
||||
|
454
src/switch_rtp.c
454
src/switch_rtp.c
@ -89,6 +89,11 @@ typedef struct {
|
||||
char body[SWITCH_RTP_MAX_BUF_LEN];
|
||||
} rtp_msg_t;
|
||||
|
||||
typedef struct {
|
||||
switch_rtcp_hdr_t header;
|
||||
char body[SWITCH_RTCP_MAX_BUF_LEN];
|
||||
} rtcp_msg_t;
|
||||
|
||||
struct switch_rtp_vad_data {
|
||||
switch_core_session_t *session;
|
||||
switch_codec_t vad_codec;
|
||||
@ -137,16 +142,17 @@ struct switch_rtp {
|
||||
* families are equal, sock_input == sock_output and only one socket is
|
||||
* used.
|
||||
*/
|
||||
switch_socket_t *sock_input, *sock_output;
|
||||
switch_pollfd_t *read_pollfd;
|
||||
switch_socket_t *sock_input, *sock_output, *rtcp_sock_input, *rtcp_sock_output;
|
||||
switch_pollfd_t *read_pollfd, *rtcp_read_pollfd;
|
||||
switch_pollfd_t *jb_pollfd;
|
||||
|
||||
switch_sockaddr_t *local_addr;
|
||||
switch_sockaddr_t *local_addr, *rtcp_local_addr;
|
||||
rtp_msg_t send_msg;
|
||||
rtcp_msg_t rtcp_send_msg;
|
||||
|
||||
switch_sockaddr_t *remote_addr;
|
||||
switch_sockaddr_t *remote_addr, *rtcp_remote_addr;
|
||||
rtp_msg_t recv_msg;
|
||||
|
||||
rtcp_msg_t rtcp_recv_msg;
|
||||
|
||||
switch_sockaddr_t *remote_stun_addr;
|
||||
|
||||
@ -173,12 +179,13 @@ struct switch_rtp {
|
||||
switch_time_t last_write_timestamp;
|
||||
uint32_t flags;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_sockaddr_t *from_addr;
|
||||
switch_sockaddr_t *from_addr, *rtcp_from_addr;
|
||||
char *rx_host;
|
||||
switch_port_t rx_port;
|
||||
char *ice_user;
|
||||
char *user_ice;
|
||||
char *timer_name;
|
||||
char *local_host_str;
|
||||
char *remote_host_str;
|
||||
switch_time_t last_stun;
|
||||
uint32_t samples_per_interval;
|
||||
@ -186,6 +193,7 @@ struct switch_rtp {
|
||||
uint32_t conf_samples_per_interval;
|
||||
uint32_t rsamples_per_interval;
|
||||
uint32_t ms_per_packet;
|
||||
switch_port_t local_port;
|
||||
switch_port_t remote_port;
|
||||
uint32_t stuncount;
|
||||
uint32_t funny_stun;
|
||||
@ -216,6 +224,8 @@ struct switch_rtp {
|
||||
switch_rtp_stats_t stats;
|
||||
uint32_t hot_hits;
|
||||
uint32_t sync_packets;
|
||||
int rtcp_interval;
|
||||
switch_bool_t rtcp_fresh_frame;
|
||||
|
||||
#ifdef ENABLE_ZRTP
|
||||
zrtp_session_t *zrtp_session;
|
||||
@ -225,10 +235,16 @@ struct switch_rtp {
|
||||
int zinit;
|
||||
#endif
|
||||
|
||||
#ifdef RTP_DEBUG_WRITE_DELTA
|
||||
switch_time_t send_time;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct switch_rtcp_senderinfo {
|
||||
unsigned ssrc:32;
|
||||
unsigned ntp_msw:32;
|
||||
unsigned ntp_lsw:32;
|
||||
unsigned ts:32;
|
||||
unsigned pc:32;
|
||||
unsigned oc:32;
|
||||
};
|
||||
|
||||
static int global_init = 0;
|
||||
@ -284,7 +300,7 @@ static switch_status_t do_stun_ping(switch_rtp_t *rtp_session)
|
||||
switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_stun_addr, 0, (void *) packet, &bytes);
|
||||
rtp_session->stuncount = rtp_session->default_stuncount;
|
||||
|
||||
end:
|
||||
end:
|
||||
WRITE_DEC(rtp_session);
|
||||
|
||||
return status;
|
||||
@ -324,7 +340,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session)
|
||||
switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) packet, &bytes);
|
||||
rtp_session->stuncount = rtp_session->default_stuncount;
|
||||
|
||||
end:
|
||||
end:
|
||||
WRITE_DEC(rtp_session);
|
||||
|
||||
return status;
|
||||
@ -410,7 +426,7 @@ static void handle_ice(switch_rtp_t *rtp_session, void *data, switch_size_t len)
|
||||
switch_socket_sendto(rtp_session->sock_output, rtp_session->from_addr, 0, (void *) rpacket, &bytes);
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
|
||||
READ_DEC(rtp_session);
|
||||
WRITE_DEC(rtp_session);
|
||||
@ -750,6 +766,104 @@ SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, swit
|
||||
rtp_session->rtp_bugs = bugs;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t enable_remote_rtcp_socket(switch_rtp_t *rtp_session, const char **err) {
|
||||
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
|
||||
rtp_session->rtcp_remote_addr = rtp_session->remote_addr;
|
||||
|
||||
if (switch_sockaddr_info_get(&rtp_session->rtcp_remote_addr, rtp_session->remote_host_str, SWITCH_UNSPEC,
|
||||
rtp_session->remote_port + 1, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !rtp_session->rtcp_remote_addr) {
|
||||
*err = "RTCP Remote Address Error!";
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (rtp_session->rtcp_sock_input && switch_sockaddr_get_family(rtp_session->rtcp_remote_addr) ==
|
||||
switch_sockaddr_get_family(rtp_session->rtcp_local_addr)) {
|
||||
rtp_session->rtcp_sock_output = rtp_session->rtcp_sock_input;
|
||||
} else {
|
||||
if (rtp_session->rtcp_sock_output && rtp_session->rtcp_sock_output != rtp_session->rtcp_sock_input) {
|
||||
switch_socket_close(rtp_session->rtcp_sock_output);
|
||||
}
|
||||
if ((status = switch_socket_create(&rtp_session->rtcp_sock_output,
|
||||
switch_sockaddr_get_family(rtp_session->rtcp_remote_addr),
|
||||
SOCK_DGRAM, 0, rtp_session->pool)) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Socket Error!";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*err = "RTCP NOT ACTIVE!";
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static switch_status_t enable_local_rtcp_socket(switch_rtp_t *rtp_session, const char **err) {
|
||||
|
||||
const char *host = rtp_session->local_host_str;
|
||||
switch_port_t port = rtp_session->local_port;
|
||||
switch_socket_t *rtcp_new_sock = NULL, *rtcp_old_sock = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
char bufa[30];
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
if (switch_sockaddr_info_get(&rtp_session->rtcp_local_addr, host, SWITCH_UNSPEC, port+1, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Local Address Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_socket_create(&rtcp_new_sock, switch_sockaddr_get_family(rtp_session->rtcp_local_addr), SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Socket Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_socket_opt_set(rtcp_new_sock, SWITCH_SO_REUSEADDR, 1) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Socket Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_socket_bind(rtcp_new_sock, rtp_session->rtcp_local_addr) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP Bind Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_sockaddr_info_get(&rtp_session->rtcp_from_addr, switch_get_addr(bufa, sizeof(bufa), rtp_session->from_addr),
|
||||
SWITCH_UNSPEC, switch_sockaddr_get_port(rtp_session->from_addr) + 1, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "RTCP From Address Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
rtcp_old_sock = rtp_session->rtcp_sock_input;
|
||||
rtp_session->rtcp_sock_input = rtcp_new_sock;
|
||||
rtcp_new_sock = NULL;
|
||||
|
||||
switch_socket_create_pollset(&rtp_session->rtcp_read_pollfd, rtp_session->rtcp_sock_input, SWITCH_POLLIN | SWITCH_POLLERR, rtp_session->pool);
|
||||
|
||||
done:
|
||||
|
||||
if (*err) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating rtcp [%s]\n", *err);
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (rtcp_new_sock) {
|
||||
switch_socket_close(rtcp_new_sock);
|
||||
}
|
||||
|
||||
if (rtcp_old_sock) {
|
||||
switch_socket_close(rtcp_old_sock);
|
||||
}
|
||||
} else {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err)
|
||||
{
|
||||
switch_socket_t *new_sock = NULL, *old_sock = NULL;
|
||||
@ -781,11 +895,17 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
rtp_session->local_host_str = switch_core_strdup(rtp_session->pool, host);
|
||||
rtp_session->local_port = port;
|
||||
|
||||
|
||||
if (switch_sockaddr_info_get(&rtp_session->local_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "Local Address Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (rtp_session->sock_input) {
|
||||
switch_rtp_kill_socket(rtp_session);
|
||||
}
|
||||
@ -799,11 +919,12 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
|
||||
*err = "Socket Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (switch_socket_bind(new_sock, rtp_session->local_addr) != SWITCH_STATUS_SUCCESS) {
|
||||
*err = "Bind Error!";
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
len = sizeof(i);
|
||||
switch_socket_opt_set(new_sock, SWITCH_SO_NONBLOCK, TRUE);
|
||||
@ -827,12 +948,15 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
|
||||
}
|
||||
switch_socket_opt_set(new_sock, SWITCH_SO_NONBLOCK, FALSE);
|
||||
|
||||
#endif
|
||||
|
||||
old_sock = rtp_session->sock_input;
|
||||
rtp_session->sock_input = new_sock;
|
||||
new_sock = NULL;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) {
|
||||
switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE);
|
||||
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
@ -840,11 +964,18 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
|
||||
|
||||
switch_socket_create_pollset(&rtp_session->read_pollfd, rtp_session->sock_input, SWITCH_POLLIN | SWITCH_POLLERR, rtp_session->pool);
|
||||
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
*err = "Success";
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
if ((status = enable_local_rtcp_socket(rtp_session, err)) == SWITCH_STATUS_SUCCESS) {
|
||||
*err = "Success";
|
||||
}
|
||||
} else {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
*err = "Success";
|
||||
}
|
||||
|
||||
switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_IO);
|
||||
|
||||
done:
|
||||
done:
|
||||
|
||||
if (new_sock) {
|
||||
switch_socket_close(new_sock);
|
||||
@ -854,6 +985,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
|
||||
switch_socket_close(old_sock);
|
||||
}
|
||||
|
||||
|
||||
if (rtp_session->ready != 1) {
|
||||
WRITE_DEC(rtp_session);
|
||||
READ_DEC(rtp_session);
|
||||
@ -901,6 +1033,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
switch_mutex_lock(rtp_session->write_mutex);
|
||||
|
||||
rtp_session->remote_addr = remote_addr;
|
||||
@ -923,6 +1056,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
status = enable_remote_rtcp_socket(rtp_session, err);
|
||||
}
|
||||
|
||||
switch_mutex_unlock(rtp_session->write_mutex);
|
||||
|
||||
return status;
|
||||
@ -985,8 +1122,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
|
||||
|
||||
policy->next = NULL;
|
||||
policy->key = (uint8_t *) crypto_key->key;
|
||||
crypto_policy_set_rtcp_default(&policy->rtcp);
|
||||
policy->rtcp.sec_serv = sec_serv_none;
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
crypto_policy_set_rtcp_default(&policy->rtcp);
|
||||
policy->rtcp.sec_serv = sec_serv_none;
|
||||
}
|
||||
|
||||
policy->rtp.sec_serv = sec_serv_conf_and_auth;
|
||||
switch (direction) {
|
||||
@ -1136,8 +1276,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||
|
||||
/* for from address on recvfrom calls */
|
||||
switch_sockaddr_info_get(&rtp_session->from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
|
||||
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
switch_sockaddr_info_get(&rtp_session->rtcp_from_addr, NULL, SWITCH_UNSPEC, 0, 0, pool);
|
||||
}
|
||||
rtp_session->seq = (uint16_t) rand();
|
||||
rtp_session->ssrc = (uint32_t) ((intptr_t) rtp_session + (uint32_t) switch_epoch_time_now(NULL));
|
||||
|
||||
@ -1162,6 +1303,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||
|
||||
rtp_session->payload = payload;
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
rtp_session->rtcp_send_msg.header.version = 2;
|
||||
rtp_session->rtcp_send_msg.header.p = 0;
|
||||
rtp_session->rtcp_send_msg.header.type = 200;
|
||||
rtp_session->rtcp_send_msg.header.count = 0;
|
||||
rtp_session->rtcp_send_msg.header.length = htons(6);
|
||||
}
|
||||
|
||||
switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval);
|
||||
rtp_session->conf_samples_per_interval = samples_per_interval;
|
||||
|
||||
@ -1257,7 +1406,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
|
||||
#endif
|
||||
|
||||
@ -1316,7 +1465,7 @@ SWITCH_DECLARE(switch_rtp_t *) switch_rtp_new(const char *rx_host,
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
|
||||
if (rtp_session) {
|
||||
switch_mutex_unlock(rtp_session->flag_mutex);
|
||||
@ -1382,6 +1531,19 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate)
|
||||
{
|
||||
const char *err = NULL;
|
||||
|
||||
switch_set_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTCP send rate is: %d and packet rate is: %d\n", send_rate, rtp_session->ms_per_packet);
|
||||
rtp_session->rtcp_interval = send_rate/(rtp_session->ms_per_packet/1000);
|
||||
|
||||
return enable_local_rtcp_socket(rtp_session, &err) || enable_remote_rtcp_socket(rtp_session, &err);
|
||||
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin)
|
||||
{
|
||||
char ice_user[80];
|
||||
@ -1407,6 +1569,10 @@ static void ping_socket(switch_rtp_t *rtp_session)
|
||||
uint32_t o = UINT_MAX;
|
||||
switch_size_t len = sizeof(o);
|
||||
switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) &o, &len);
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) && rtp_session->rtcp_sock_input) {
|
||||
switch_socket_sendto(rtp_session->rtcp_sock_input, rtp_session->rtcp_local_addr, 0, (void *) &o, &len);
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
|
||||
@ -1443,6 +1609,16 @@ SWITCH_DECLARE(void) switch_rtp_kill_socket(switch_rtp_t *rtp_session)
|
||||
if (rtp_session->sock_output && rtp_session->sock_output != rtp_session->sock_input) {
|
||||
switch_socket_shutdown(rtp_session->sock_output, SWITCH_SHUTDOWN_READWRITE);
|
||||
}
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
if (rtp_session->rtcp_sock_input) {
|
||||
ping_socket(rtp_session);
|
||||
switch_socket_shutdown(rtp_session->rtcp_sock_input, SWITCH_SHUTDOWN_READWRITE);
|
||||
}
|
||||
if (rtp_session->rtcp_sock_output && rtp_session->rtcp_sock_output != rtp_session->rtcp_sock_input) {
|
||||
switch_socket_shutdown(rtp_session->rtcp_sock_output, SWITCH_SHUTDOWN_READWRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(rtp_session->flag_mutex);
|
||||
}
|
||||
@ -1746,7 +1922,7 @@ static void do_flush(switch_rtp_t *rtp_session)
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
|
||||
SWITCH_LOG_CONSOLE, "%s FLUSH\n", switch_channel_get_name(switch_core_session_get_channel(session))
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1841,18 +2017,126 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes, switch_frame_flag_t *flags)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_assert(bytes);
|
||||
|
||||
*bytes = sizeof(rtcp_msg_t);
|
||||
if ((status = switch_socket_recvfrom(rtp_session->rtcp_from_addr, rtp_session->rtcp_sock_input, 0, (void *) &rtp_session->rtcp_recv_msg, bytes))
|
||||
!= SWITCH_STATUS_SUCCESS) {
|
||||
*bytes = 0;
|
||||
}
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV)) {
|
||||
int sbytes = (int) *bytes;
|
||||
err_status_t stat = 0;
|
||||
|
||||
stat = srtp_unprotect_rtcp(rtp_session->recv_ctx, &rtp_session->rtcp_recv_msg.header, &sbytes);
|
||||
|
||||
if (stat) {
|
||||
if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Error: SRTP RTCP unprotect failed with code %d%s\n", stat,
|
||||
stat == err_status_replay_fail ? " (replay check failed)" : stat ==
|
||||
err_status_auth_fail ? " (auth check failed)" : "");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
sbytes = 0;
|
||||
}
|
||||
} else {
|
||||
rtp_session->srtp_errs = 0;
|
||||
}
|
||||
|
||||
*bytes = sbytes;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_ZRTP
|
||||
/* ZRTP Recv */
|
||||
if (bytes) {
|
||||
unsigned int sbytes = (int) bytes;
|
||||
zrtp_status_t stat = 0;
|
||||
|
||||
stat = zrtp_process_srtcp(rtp_session->zrtp_stream, (void *) &rtp_session->rtcp_recv_msg, &sbytes);
|
||||
|
||||
switch (stat) {
|
||||
case zrtp_status_ok:
|
||||
bytes = sbytes;
|
||||
break;
|
||||
case zrtp_status_drop:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
|
||||
bytes = 0;
|
||||
goto do_continue;
|
||||
case zrtp_status_fail:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
|
||||
ret = -1;
|
||||
goto end;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (*bytes) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10,"Received an RTCP packet of length %lu bytes\n", *bytes);
|
||||
if (rtp_session->rtcp_recv_msg.header.version == 2) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10,"RTCP packet type is %d\n", rtp_session->rtcp_recv_msg.header.type);
|
||||
if (rtp_session->rtcp_recv_msg.header.type == 200) {
|
||||
struct switch_rtcp_senderinfo* sr = (struct switch_rtcp_senderinfo*)rtp_session->rtcp_recv_msg.body;
|
||||
|
||||
rtp_session->rtcp_fresh_frame = 1;
|
||||
|
||||
/* sender report */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10,"Received a SR with %d report blocks, " \
|
||||
"length in words = %d, " \
|
||||
"SSRC = 0x%X, " \
|
||||
"NTP MSW = %u, " \
|
||||
"NTP LSW = %u, " \
|
||||
"RTP timestamp = %u, " \
|
||||
"Sender Packet Count = %u, " \
|
||||
"Sender Octet Count = %u\n",
|
||||
rtp_session->rtcp_recv_msg.header.count,
|
||||
ntohs(rtp_session->rtcp_recv_msg.header.length),
|
||||
ntohl(sr->ssrc),
|
||||
ntohl(sr->ntp_msw),
|
||||
ntohl(sr->ntp_lsw),
|
||||
ntohl(sr->ts),
|
||||
ntohl(sr->pc),
|
||||
ntohl(sr->oc));
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received an unsupported RTCP packet version %d\nn", rtp_session->rtcp_recv_msg.header.version);
|
||||
}
|
||||
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_type, switch_frame_flag_t *flags, switch_io_flag_t io_flags)
|
||||
{
|
||||
switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
|
||||
switch_channel_t *channel = NULL;
|
||||
switch_size_t bytes = 0;
|
||||
switch_size_t rtcp_bytes = 0;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS, poll_status = SWITCH_STATUS_SUCCESS;
|
||||
switch_status_t rtcp_status = SWITCH_STATUS_SUCCESS, rtcp_poll_status = SWITCH_STATUS_SUCCESS;
|
||||
int check = 0;
|
||||
int ret = -1;
|
||||
int sleep_mss = 1000;
|
||||
int poll_sec = 5;
|
||||
int poll_loop = 0;
|
||||
int fdr = 0;
|
||||
int rtcp_fdr = 0;
|
||||
int hot_socket = 0;
|
||||
|
||||
if (session) {
|
||||
@ -1904,7 +2188,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
}
|
||||
}
|
||||
|
||||
recvfrom:
|
||||
recvfrom:
|
||||
bytes = 0;
|
||||
|
||||
if (!switch_rtp_ready(rtp_session)) {
|
||||
@ -1946,6 +2230,14 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
return_cng_frame();
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) && rtp_session->rtcp_read_pollfd) {
|
||||
rtcp_poll_status = switch_poll(rtp_session->rtcp_read_pollfd, 1, &rtcp_fdr, 0);
|
||||
|
||||
if (rtcp_poll_status == SWITCH_STATUS_SUCCESS) {
|
||||
rtcp_status = read_rtcp_packet(rtp_session, &rtcp_bytes, flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes < 0) {
|
||||
ret = (int) bytes;
|
||||
@ -2210,7 +2502,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
We know the real rules here, but if we enforce them, it's an interop nightmare so,
|
||||
we put up with as much as we can so we don't have to deal with being punished for
|
||||
doing it right. Nice guys finish last!
|
||||
*/
|
||||
*/
|
||||
if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) &&
|
||||
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
|
||||
switch_size_t len = bytes - rtp_header_len;
|
||||
@ -2324,7 +2616,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
return_cng_frame();
|
||||
}
|
||||
|
||||
timer_check:
|
||||
timer_check:
|
||||
|
||||
if (do_cng) {
|
||||
uint8_t *data = (uint8_t *) rtp_session->recv_msg.body;
|
||||
@ -2371,7 +2663,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
|
||||
break;
|
||||
|
||||
do_continue:
|
||||
do_continue:
|
||||
|
||||
if (!bytes && !rtp_session->timer.interval) {
|
||||
switch_yield(sleep_mss);
|
||||
@ -2391,7 +2683,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
|
||||
READ_DEC(rtp_session);
|
||||
|
||||
@ -2513,6 +2805,33 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtcp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_rtcp_frame_t *frame)
|
||||
{
|
||||
|
||||
if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* A fresh frame has been found! */
|
||||
if (rtp_session->rtcp_fresh_frame) {
|
||||
struct switch_rtcp_senderinfo* sr = (struct switch_rtcp_senderinfo*)rtp_session->rtcp_recv_msg.body;
|
||||
/* turn the flag off! */
|
||||
rtp_session->rtcp_fresh_frame = 0;
|
||||
|
||||
frame->ssrc = ntohl(sr->ssrc);
|
||||
frame->packet_type = rtp_session->rtcp_recv_msg.header.type;
|
||||
frame->ntp_msw = ntohl(sr->ntp_msw);
|
||||
frame->ntp_lsw = ntohl(sr->ntp_lsw);
|
||||
frame->timestamp = ntohl(sr->ts);
|
||||
frame->packet_count = ntohl(sr->pc);
|
||||
frame->octect_count = ntohl(sr->oc);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_frame_t *frame, switch_io_flag_t io_flags)
|
||||
{
|
||||
int bytes = 0;
|
||||
@ -2625,10 +2944,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_sessi
|
||||
static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags)
|
||||
{
|
||||
switch_size_t bytes;
|
||||
switch_size_t bytes, rtcp_bytes;
|
||||
uint8_t send = 1;
|
||||
uint32_t this_ts = 0;
|
||||
int ret;
|
||||
switch_time_t now;
|
||||
|
||||
if (!switch_rtp_ready(rtp_session)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
@ -2860,15 +3180,14 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
}
|
||||
#endif
|
||||
|
||||
now = switch_time_now();
|
||||
#ifdef RTP_DEBUG_WRITE_DELTA
|
||||
{
|
||||
switch_time_t now = switch_time_now();
|
||||
int delta = (int) (now - rtp_session->send_time) / 1000;
|
||||
printf("WRITE %d delta %d\n", (int) bytes, delta);
|
||||
rtp_session->send_time = now;
|
||||
}
|
||||
#endif
|
||||
|
||||
rtp_session->send_time = now;
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DEBUG_RTP_WRITE)) {
|
||||
switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
|
||||
@ -2924,6 +3243,61 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
}
|
||||
|
||||
rtp_session->last_write_ts = this_ts;
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) &&
|
||||
rtp_session->rtcp_interval && (rtp_session->stats.outbound.packet_count % rtp_session->rtcp_interval) == 0) {
|
||||
struct switch_rtcp_senderinfo* sr = (struct switch_rtcp_senderinfo*)rtp_session->rtcp_send_msg.body;
|
||||
|
||||
sr->ssrc = send_msg->header.ssrc;
|
||||
sr->ntp_msw = htonl(rtp_session->send_time / 1000000 + 2208988800UL);
|
||||
sr->ntp_lsw = htonl(rtp_session->send_time % 1000000 * ((UINT_MAX * 1.0)/ 1000000.0));
|
||||
sr->ts = send_msg->header.ts;
|
||||
sr->pc = htonl(rtp_session->stats.outbound.packet_count);
|
||||
sr->oc = htonl((rtp_session->stats.outbound.raw_bytes - rtp_session->stats.outbound.packet_count * sizeof(srtp_hdr_t)));
|
||||
|
||||
rtcp_bytes = sizeof(switch_rtcp_hdr_t) + sizeof(struct switch_rtcp_senderinfo);
|
||||
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
|
||||
int sbytes = (int) rtcp_bytes;
|
||||
int stat = srtp_protect_rtcp(rtp_session->send_ctx, &rtp_session->rtcp_send_msg.header, &sbytes);
|
||||
if (stat) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
|
||||
}
|
||||
rtcp_bytes = sbytes;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ZRTP
|
||||
/* ZRTP Send */
|
||||
if (1) {
|
||||
unsigned int sbytes = (int) bytes;
|
||||
zrtp_status_t stat = zrtp_status_fail;
|
||||
|
||||
stat = zrtp_process_rtcp(rtp_session->zrtp_stream, (void *) &rtp_session->rtcp_send_msg, &sbytes);
|
||||
|
||||
switch (stat) {
|
||||
case zrtp_status_ok:
|
||||
break;
|
||||
case zrtp_status_drop:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
|
||||
ret = (int) bytes;
|
||||
goto end;
|
||||
break;
|
||||
case zrtp_status_fail:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bytes = sbytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (switch_socket_sendto(rtp_session->rtcp_sock_output, rtp_session->rtcp_remote_addr, 0,
|
||||
(const char*)&rtp_session->rtcp_send_msg, &rtcp_bytes ) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"RTCP packet not written\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rtp_session->remote_stun_addr) {
|
||||
@ -2939,7 +3313,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
|
||||
ret = (int) bytes;
|
||||
|
||||
end:
|
||||
end:
|
||||
|
||||
WRITE_DEC(rtp_session);
|
||||
|
||||
@ -3031,9 +3405,9 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
|
||||
send_msg = frame->packet;
|
||||
|
||||
/*
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
|
||||
send_msg->header.pt = rtp_session->payload;
|
||||
}
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
|
||||
send_msg->header.pt = rtp_session->payload;
|
||||
}
|
||||
*/
|
||||
|
||||
if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
|
||||
@ -3131,9 +3505,9 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
|
||||
}
|
||||
|
||||
/*
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
|
||||
send_msg->header.pt = rtp_session->payload;
|
||||
}
|
||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
|
||||
send_msg->header.pt = rtp_session->payload;
|
||||
}
|
||||
*/
|
||||
|
||||
return rtp_common_write(rtp_session, send_msg, data, len, payload, ts, &frame->flags);
|
||||
@ -3234,7 +3608,7 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session,
|
||||
|
||||
ret = (int) bytes;
|
||||
|
||||
end:
|
||||
end:
|
||||
|
||||
WRITE_DEC(rtp_session);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user