<!--all inbound reg will stored in the db using this domain -->
<param name="force-register-db-domain" value="$${domain}"/>
- <!-- enable rtcp on every channel also can be done per leg basis with rtcp_interval_msec variable -->
- <!--<param name="rtcp-interval-msec" value="10000"/>-->
+ <!-- enable rtcp on every channel also can be done per leg basis with rtcp_audio_interval_msec variable set to passthru to pass it across a call-->
+ <!--<param name="rtcp-audio-interval-msec" value="10000"/>-->
+ <!--<param name="rtcp-video-interval-msec" value="10000"/>-->
<!--force suscription expires to a lower value than requested-->
<!--<param name="force-subscription-expires" value="60"/>-->
\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);
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate, switch_port_t remote_port);
/*!
\brief Acvite a jitter buffer on an RTP session
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_ENABLE_RTCP = (1 << 30)
+ SWITCH_RTP_FLAG_ENABLE_RTCP = (1 << 30),
+ SWITCH_RTP_FLAG_RTCP_PASSTHRU = (1 << 31)
+ /* don't add any more 31 is the limit! gotta chnge to an array to add more */
} switch_rtp_flag_enum_t;
typedef uint32_t switch_rtp_flag_t;
char *record_path;
char *presence_hosts;
char *challenge_realm;
- char *rtcp_interval_msec;
+ char *rtcp_audio_interval_msec;
+ char *rtcp_video_interval_msec;
sofia_cid_type_t cid_type;
sofia_dtmf_t dtmf_type;
int auto_restart;
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, "rtcp-audio-interval-msec")) {
+ profile->rtcp_audio_interval_msec = switch_core_strdup(profile->pool, val);
+ } else if (!strcasecmp(var, "rtcp-video-interval-msec")) {
+ profile->rtcp_video_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) {
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, "rtcp-audio-interval-msec")) {
+ profile->rtcp_audio_interval_msec = switch_core_strdup(profile->pool, val);
+ } else if (!strcasecmp(var, "rtcp-video-interval-msec")) {
+ profile->rtcp_video_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) {
switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int force)
{
char *lookup_rtpip = tech_pvt->profile->rtpip; /* Pointer to externally looked up address */
- switch_port_t sdp_port; /* The external port to be sent in the SDP */
+ switch_port_t sdp_port, rtcp_port; /* The external port to be sent in the SDP */
const char *use_ip = NULL; /* The external IP to be sent in the SDP */
/* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
if (!zstr(tech_pvt->remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) {
/* Yes, map the port through switch_nat */
switch_nat_add_mapping(tech_pvt->local_sdp_audio_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE);
+ switch_nat_add_mapping(tech_pvt->local_sdp_audio_port + 1, SWITCH_NAT_UDP, &rtcp_port, SWITCH_FALSE);
} else {
/* No NAT detected */
use_ip = tech_pvt->profile->rtpip;
(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);
+ printf("WTF [%s][%s]\n", switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec"), tech_pvt->profile->rtcp_audio_interval_msec);
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec")) || (val = tech_pvt->profile->rtcp_audio_interval_msec)) {
+ const char *rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port");
+ switch_port_t remote_port = 0;
+ if (rport) {
+ remote_port = atoi(rport);
+ }
+ if (!strcasecmp(val, "passthru")) {
+ switch_rtp_activate_rtcp(tech_pvt->rtp_session, -1, remote_port);
} else {
- switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval);
+ 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, remote_port);
+ }
}
}
switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_pt", "%d", tech_pvt->video_agreed_pt);
tech_pvt->video_ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_video_ssrc", "%u", tech_pvt->ssrc);
+
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec")) || (val = tech_pvt->profile->rtcp_audio_interval_msec)) {
+ const char *rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port");
+ switch_port_t remote_port = 0;
+ if (rport) {
+ remote_port = atoi(rport);
+ }
+ if (!strcasecmp(val, "passthru")) {
+ switch_rtp_activate_rtcp(tech_pvt->rtp_session, -1, remote_port);
+ } else {
+ 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, remote_port);
+ }
+ }
+ }
+
+
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
} else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
sdp_rtpmap_t *map;
for (attr = m->m_attributes; attr; attr = attr->a_next) {
+
+ if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
+ switch_channel_set_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port", attr->a_value);
+ }
+
if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
ptime = atoi(attr->a_value);
} else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
framerate = atoi(attr->a_value);
}
+ if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
+ switch_channel_set_variable(tech_pvt->channel, "sip_remote_video_rtcp_port", attr->a_value);
+ }
}
if (!(rm_encoding = map->rm_encoding)) {
rm_encoding = "";
uint32_t ms_per_packet;
switch_port_t local_port;
switch_port_t remote_port;
+ switch_port_t remote_rtcp_port;
uint32_t stuncount;
uint32_t funny_stun;
uint32_t default_stuncount;
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) {
+ rtp_session->remote_rtcp_port, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !rtp_session->rtcp_remote_addr) {
*err = "RTCP Remote Address Error!";
return SWITCH_STATUS_FALSE;
}
{
switch_rtp_t *rtp_session = NULL;
switch_core_session_t *session = switch_core_memory_pool_get_data(pool, "__session");
+ switch_channel_t *channel = NULL;
+
+ if (session) channel = switch_core_session_get_channel(session);
*new_rtp_session = NULL;
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);
- }
+
+ 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;
switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
}
+ switch_channel_set_private(channel, "__rtcp_audio_rtp_session", rtp_session);
+
#ifdef ENABLE_ZRTP
if (zrtp_on) {
switch_rtp_t *master_rtp_session = NULL;
int initiator = 0;
- switch_channel_t *channel = switch_core_session_get_channel(session);
const char *zrtp_enabled = switch_channel_get_variable(channel, "zrtp_secure_media");
const char *srtp_enabled = switch_channel_get_variable(channel, "sip_secure_media");
return SWITCH_STATUS_SUCCESS;
}
-SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate)
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate, switch_port_t remote_port)
{
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);
+ if (!(rtp_session->remote_rtcp_port = remote_port)) {
+ rtp_session->remote_rtcp_port = rtp_session->remote_port + 1;
+ }
+
+ if (send_rate == -1) {
+ switch_set_flag(rtp_session, SWITCH_RTP_FLAG_RTCP_PASSTHRU);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "RTCP passthru enabled. Remote Port: %d\n", rtp_session->remote_rtcp_port);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "RTCP send rate is: %d and packet rate is: %d Remote Port: %d\n",
+ send_rate, rtp_session->ms_per_packet, rtp_session->remote_rtcp_port);
+ 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);
if (rtcp_poll_status == SWITCH_STATUS_SUCCESS) {
rtcp_status = read_rtcp_packet(rtp_session, &rtcp_bytes, flags);
+
+ if (rtcp_status == SWITCH_STATUS_SUCCESS && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_RTCP_PASSTHRU)) {
+ switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ const char *uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
+ if (uuid) {
+ switch_core_session_t *other_session;
+ switch_rtp_t *other_rtp_session = NULL;
+
+ if ((other_session = switch_core_session_locate(uuid))) {
+ switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
+ if ((other_rtp_session = switch_channel_get_private(other_channel, "__rtcp_audio_rtp_session")) &&
+ switch_test_flag(other_rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
+ *other_rtp_session->rtcp_send_msg.body = *rtp_session->rtcp_recv_msg.body;
+
+ if (switch_test_flag(other_rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
+ int sbytes = (int) rtcp_bytes;
+ int stat = srtp_protect_rtcp(other_rtp_session->send_ctx, &other_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(other_rtp_session->zrtp_stream, (void *) &other_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(other_rtp_session->rtcp_sock_output, other_rtp_session->rtcp_remote_addr, 0,
+ (const char*)&other_rtp_session->rtcp_send_msg, &rtcp_bytes ) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"RTCP packet not written\n");
+ }
+
+
+ }
+ }
+ }
+
+ }
}
}
rtp_session->last_write_ts = this_ts;
- if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) &&
+ if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_RTCP_PASSTHRU) &&
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;