diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 8c59ffac44..7e86f71599 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -434,6 +434,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_private(switch_channel_t *cha \return void pointer to channel's private data */ SWITCH_DECLARE(void *) switch_channel_get_private(switch_channel_t *channel, const char *key); +SWITCH_DECLARE(void *) switch_channel_get_private_partner(switch_channel_t *channel, const char *key); /*! \brief Assign a name to a given channel diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 1a7cb8ae24..1db3056f2c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2032,16 +2032,6 @@ void sofia_glue_deactivate_rtp(private_object_t *tech_pvt) } } - if (tech_pvt->rtp_session) { - switch_rtp_destroy(&tech_pvt->rtp_session); - } else if (tech_pvt->local_sdp_audio_port) { - switch_rtp_release_port(tech_pvt->profile->rtpip, tech_pvt->local_sdp_audio_port); - } - - if (tech_pvt->local_sdp_audio_port > 0 && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) { - switch_nat_del_mapping((switch_port_t)tech_pvt->local_sdp_audio_port, SWITCH_NAT_UDP); - } - if (tech_pvt->video_rtp_session) { switch_rtp_destroy(&tech_pvt->video_rtp_session); } else if (tech_pvt->local_sdp_video_port) { @@ -2052,6 +2042,18 @@ void sofia_glue_deactivate_rtp(private_object_t *tech_pvt) if (tech_pvt->local_sdp_video_port > 0 && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) { switch_nat_del_mapping((switch_port_t)tech_pvt->local_sdp_video_port, SWITCH_NAT_UDP); } + + + if (tech_pvt->rtp_session) { + switch_rtp_destroy(&tech_pvt->rtp_session); + } else if (tech_pvt->local_sdp_audio_port) { + switch_rtp_release_port(tech_pvt->profile->rtpip, tech_pvt->local_sdp_audio_port); + } + + if (tech_pvt->local_sdp_audio_port > 0 && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) { + switch_nat_del_mapping((switch_port_t)tech_pvt->local_sdp_audio_port, SWITCH_NAT_UDP); + } + } switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force) @@ -2749,7 +2751,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f sofia_glue_tech_set_video_codec(tech_pvt, 0); flags &= ~(SWITCH_RTP_FLAG_USE_TIMER | SWITCH_RTP_FLAG_NOBLOCK); - flags |= SWITCH_RTP_FLAG_VIDEO | SWITCH_RTP_FLAG_PROXY_MEDIA; + flags |= SWITCH_RTP_FLAG_VIDEO; tech_pvt->video_rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_video_port, diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index 09ee75944a..7ae0a6a6a9 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -21111,6 +21111,23 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_variable_printf(void * jarg } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_variable_name_printf(void * jarg1, char * jarg2, char * jarg3) { + int jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + void *arg4 = 0 ; + switch_status_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + result = (switch_status_t)switch_channel_set_variable_name_printf(arg1,(char const *)arg2,(char const *)arg3,arg4); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_variable_partner_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -21567,6 +21584,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_channel_get_private(void * jarg1, ch } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_channel_get_private_partner(void * jarg1, char * jarg2) { + void * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *arg2 = (char *) 0 ; + void *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (char *)jarg2; + result = (void *)switch_channel_get_private_partner(arg1,(char const *)arg2); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_name(void * jarg1, char * jarg2) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -22746,15 +22777,17 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_add_header_string(void * jarg1, i } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_del_header(void * jarg1, char * jarg2) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_del_header_val(void * jarg1, char * jarg2, char * jarg3) { int jresult ; switch_event_t *arg1 = (switch_event_t *) 0 ; char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; switch_status_t result; arg1 = (switch_event_t *)jarg1; arg2 = (char *)jarg2; - result = (switch_status_t)switch_event_del_header(arg1,(char const *)arg2); + arg3 = (char *)jarg3; + result = (switch_status_t)switch_event_del_header_val(arg1,(char const *)arg2,(char const *)arg3); jresult = result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 73adfb6c2a..10254c4783 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -2851,6 +2851,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_channel_set_variable_name_printf(SWIGTYPE_p_switch_channel channel, string val, string fmt) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_set_variable_name_printf(SWIGTYPE_p_switch_channel.getCPtr(channel), val, fmt); + return ret; + } + public static switch_status_t switch_channel_set_variable_partner_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_set_variable_partner_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check); return ret; @@ -3014,6 +3019,12 @@ public class freeswitch { return ret; } + public static SWIGTYPE_p_void switch_channel_get_private_partner(SWIGTYPE_p_switch_channel channel, string key) { + IntPtr cPtr = freeswitchPINVOKE.switch_channel_get_private_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), key); + SWIGTYPE_p_void ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_void(cPtr, false); + return ret; + } + public static switch_status_t switch_channel_set_name(SWIGTYPE_p_switch_channel channel, string name) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_set_name(SWIGTYPE_p_switch_channel.getCPtr(channel), name); return ret; @@ -3273,8 +3284,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_event_del_header(switch_event arg0, string header_name) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_del_header(switch_event.getCPtr(arg0), header_name); + public static switch_status_t switch_event_del_header_val(switch_event arg0, string header_name, string val) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_del_header_val(switch_event.getCPtr(arg0), header_name, val); return ret; } @@ -10035,6 +10046,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_variable_printf")] public static extern int switch_channel_set_variable_printf(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_variable_name_printf")] + public static extern int switch_channel_set_variable_name_printf(HandleRef jarg1, string jarg2, string jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_variable_partner_var_check")] public static extern int switch_channel_set_variable_partner_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4); @@ -10137,6 +10151,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_private")] public static extern IntPtr switch_channel_get_private(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_private_partner")] + public static extern IntPtr switch_channel_get_private_partner(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_name")] public static extern int switch_channel_set_name(HandleRef jarg1, string jarg2); @@ -10404,8 +10421,8 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_event_add_header_string")] public static extern int switch_event_add_header_string(HandleRef jarg1, int jarg2, string jarg3, string jarg4); - [DllImport("mod_managed", EntryPoint="CSharp_switch_event_del_header")] - public static extern int switch_event_del_header(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_del_header_val")] + public static extern int switch_event_del_header_val(HandleRef jarg1, string jarg2, string jarg3); [DllImport("mod_managed", EntryPoint="CSharp_switch_event_destroy")] public static extern void switch_event_destroy(HandleRef jarg1); diff --git a/src/switch_channel.c b/src/switch_channel.c index 7cbe7f6837..d4ed3ec140 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -623,6 +623,24 @@ SWITCH_DECLARE(void *) switch_channel_get_private(switch_channel_t *channel, con return val; } +SWITCH_DECLARE(void *) switch_channel_get_private_partner(switch_channel_t *channel, const char *key) +{ + const char *uuid; + void *val = NULL; + + switch_assert(channel != NULL); + + if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) { + switch_core_session_t *session; + if ((session = switch_core_session_locate(uuid))) { + val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex); + switch_core_session_rwunlock(session); + } + } + + return val; +} + SWITCH_DECLARE(switch_status_t) switch_channel_set_name(switch_channel_t *channel, const char *name) { const char *old = NULL; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 7ecc2f74d8..f964dfa9f4 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -219,9 +219,9 @@ struct switch_rtp { #ifdef ENABLE_ZRTP zrtp_session_t *zrtp_session; zrtp_profile_t *zrtp_profile; - zrtp_stream_t *zrtp_audio_ctx; - zrtp_stream_t *zrtp_video_ctx; + zrtp_stream_t *zrtp_stream; int zrtp_mitm_tries; + int zinit; #endif #ifdef RTP_DEBUG_WRITE_DELTA @@ -439,44 +439,74 @@ static int zrtp_send_rtp_callback(const zrtp_stream_t* stream, char* rtp_packet, static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) { switch_rtp_t *rtp_session = zrtp_stream_get_userdata(stream); + zrtp_session_info_t zrtp_session_info; 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); switch_event_t *fsevent = NULL; + const char *type; + + type = switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) ? "video" : "audio"; - zrtp_session_info_t zrtp_session_info; - switch (event) { case ZRTP_EVENT_IS_SECURE: { switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND); switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_RECV); - switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); - switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); - if (zrtp_status_ok == zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info)) { + if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { + switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); + switch_set_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); + } + if (zrtp_status_ok == zrtp_session_get(stream->session, &zrtp_session_info)) { if (zrtp_session_info.sas_is_ready) { - switch_channel_set_variable(channel, "zrtp_secure_media_confirmed", "true"); - switch_channel_set_variable(channel, "zrtp_sas1_string", rtp_session->zrtp_session->sas1.buffer); - switch_channel_set_variable(channel, "zrtp_sas2_string", rtp_session->zrtp_session->sas2.buffer); + switch_channel_set_variable_name_printf(channel, "true", "zrtp_secure_media_confirmed_%s", type); + switch_channel_set_variable_name_printf(channel, stream->session->sas1.buffer, "zrtp_sas1_string_%s", type); + switch_channel_set_variable_name_printf(channel, stream->session->sas2.buffer, "zrtp_sas2_string", type); - zrtp_verified_set(zrtp_global, &rtp_session->zrtp_session->zid, - &rtp_session->zrtp_session->peer_zid, zrtp_session_info.sas_is_verified^1); + zrtp_verified_set(zrtp_global, &stream->session->zid, + &stream->session->peer_zid, zrtp_session_info.sas_is_verified^1); } } - } - if (switch_event_create(&fsevent, SWITCH_EVENT_CALL_SECURE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(fsevent, SWITCH_STACK_BOTTOM, "secure_type", "zrtp:%s:%s", - rtp_session->zrtp_session->sas1.buffer, rtp_session->zrtp_session->sas2.buffer); - switch_event_add_header_string(fsevent, SWITCH_STACK_BOTTOM, "caller-unique-id", switch_channel_get_uuid(channel)); - switch_event_fire(&fsevent); + + if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { + switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session"); + + if (session) { + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_rtp_t *video_rtp_session = switch_channel_get_private(channel, "__zrtp_video_rtp_session"); + + if (!video_rtp_session) { + video_rtp_session = switch_channel_get_private_partner(channel, "__zrtp_video_rtp_session"); + } + + if (video_rtp_session) { + if (zrtp_status_ok != zrtp_stream_attach(stream->session, &video_rtp_session->zrtp_stream)) { + abort(); + } + zrtp_stream_set_userdata(video_rtp_session->zrtp_stream, video_rtp_session); + if (switch_true(switch_channel_get_variable(channel, "zrtp_enrollment"))) { + zrtp_stream_registration_start(video_rtp_session->zrtp_stream, video_rtp_session->ssrc); + } else { + zrtp_stream_start(video_rtp_session->zrtp_stream, video_rtp_session->ssrc); + } + } + } + } + + if (switch_event_create(&fsevent, SWITCH_EVENT_CALL_SECURE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(fsevent, SWITCH_STACK_BOTTOM, "secure_media_type", "%s", type); + switch_event_add_header(fsevent, SWITCH_STACK_BOTTOM, "secure_type", "zrtp:%s:%s", stream->session->sas1.buffer, stream->session->sas2.buffer); + switch_event_add_header_string(fsevent, SWITCH_STACK_BOTTOM, "caller-unique-id", switch_channel_get_uuid(channel)); + switch_event_fire(&fsevent); + } } break; #if 0 case ZRTP_EVENT_NO_ZRTP_QUICK: { - if (rtp_session->zrtp_audio_ctx != NULL) { - zrtp_stream_stop(rtp_session->zrtp_audio_ctx); + if (stream != NULL) { + zrtp_stream_stop(stream); } } break; @@ -484,19 +514,19 @@ static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) case ZRTP_EVENT_IS_CLIENT_ENROLLMENT: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Enrolled complete!\n"); - switch_channel_set_variable(channel, "zrtp_enroll_complete", "true"); + switch_channel_set_variable_name_printf(channel, "true", "zrtp_enroll_complete_%s", type); } break; case ZRTP_EVENT_USER_ALREADY_ENROLLED: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "User already enrolled!\n"); - switch_channel_set_variable(channel, "zrtp_already_enrolled", "true"); + switch_channel_set_variable_name_printf(channel, "true", "zrtp_already_enrolled_%s", type); - if (zrtp_status_ok == zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info)) { + if (zrtp_status_ok == zrtp_session_get(stream->session, &zrtp_session_info)) { if (zrtp_session_info.sas_is_ready) { - zrtp_verified_set(zrtp_global, &rtp_session->zrtp_session->zid, - &rtp_session->zrtp_session->peer_zid, zrtp_session_info.sas_is_verified^1); + zrtp_verified_set(zrtp_global, &stream->session->zid, + &stream->session->peer_zid, zrtp_session_info.sas_is_verified^1); } } } @@ -505,12 +535,12 @@ static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) case ZRTP_EVENT_NEW_USER_ENROLLED: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New user enrolled!\n"); - switch_channel_set_variable(channel, "zrtp_new_user_enrolled", "true"); + switch_channel_set_variable_name_printf(channel, "true", "zrtp_new_user_enrolled_%s", type); - if (zrtp_status_ok == zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info)) { + if (zrtp_status_ok == zrtp_session_get(stream->session, &zrtp_session_info)) { if (zrtp_session_info.sas_is_ready) { - zrtp_verified_set(zrtp_global, &rtp_session->zrtp_session->zid, - &rtp_session->zrtp_session->peer_zid, zrtp_session_info.sas_is_verified^1); + zrtp_verified_set(zrtp_global, &stream->session->zid, + &stream->session->peer_zid, zrtp_session_info.sas_is_verified^1); } } } @@ -519,12 +549,12 @@ static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) case ZRTP_EVENT_USER_UNENROLLED: { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "User unenrolled!\n"); - switch_channel_set_variable(channel, "zrtp_user_unenrolled", "true"); + switch_channel_set_variable_name_printf(channel, "true", "zrtp_user_unenrolled_%s", type); - if (zrtp_status_ok == zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info)) { + if (zrtp_status_ok == zrtp_session_get(stream->session, &zrtp_session_info)) { if (zrtp_session_info.sas_is_ready) { - zrtp_verified_set(zrtp_global, &rtp_session->zrtp_session->zid, - &rtp_session->zrtp_session->peer_zid, zrtp_session_info.sas_is_verified^1); + zrtp_verified_set(zrtp_global, &stream->session->zid, + &stream->session->peer_zid, zrtp_session_info.sas_is_verified^1); } } } @@ -532,7 +562,7 @@ static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) case ZRTP_EVENT_IS_PENDINGCLEAR: { - switch_channel_set_variable(channel, "zrtp_secure_media_confirmed", "false"); + switch_channel_set_variable_name_printf(channel, "false", "zrtp_secure_media_confirmed_%s", type); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_RECV); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); @@ -543,7 +573,7 @@ static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) case ZRTP_EVENT_NO_ZRTP: { - switch_channel_set_variable(channel, "zrtp_secure_media_confirmed", "false"); + switch_channel_set_variable_name_printf(channel, "false", "zrtp_secure_media_confirmed_%s", type); } break; @@ -556,24 +586,6 @@ static void zrtp_logger(int level, const char *data, int len, int offset) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s", data); } - -static void zrtp_handler(switch_rtp_t *rtp_session, switch_socket_t *sock, void *data, switch_size_t datalen, switch_sockaddr_t *from_addr) -{ - zrtp_status_t status = zrtp_status_fail; - unsigned int len = datalen; - - status = zrtp_process_srtp(rtp_session->zrtp_audio_ctx, (char*)data, &len); - switch(status) { - case zrtp_status_ok: - break; - case zrtp_status_drop: - break; - case zrtp_status_fail: - break; - default: - break; - } -} #endif SWITCH_DECLARE(void) switch_rtp_init(switch_memory_pool_t *pool) @@ -1126,7 +1138,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session rtp_session->seq = (uint16_t) rand(); - rtp_session->ssrc = (uint32_t) ((intptr_t) &rtp_session + (uint32_t) switch_epoch_time_now(NULL)); + rtp_session->ssrc = (uint32_t) ((intptr_t) rtp_session + (uint32_t) switch_epoch_time_now(NULL)); + rtp_session->send_msg.header.ssrc = htonl(rtp_session->ssrc); rtp_session->send_msg.header.ts = 0; rtp_session->send_msg.header.m = 0; @@ -1180,6 +1193,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_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"); @@ -1191,40 +1206,57 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session zrtp_enabled = NULL; } - switch_channel_set_private(channel, "__zrtp_rtp_session", rtp_session); if (switch_true(zrtp_enabled)) { + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)){ + switch_channel_set_private(channel, "__zrtp_video_rtp_session", rtp_session); + master_rtp_session = switch_channel_get_private(channel, "__zrtp_audio_rtp_session"); + } else { + switch_channel_set_private(channel, "__zrtp_audio_rtp_session", rtp_session); + master_rtp_session = rtp_session; + } + + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { initiator = 1; } + + if (rtp_session == master_rtp_session) { + rtp_session->zrtp_profile = switch_core_alloc(rtp_session->pool, sizeof(*rtp_session->zrtp_profile)); + zrtp_profile_defaults(rtp_session->zrtp_profile, zrtp_global); - rtp_session->zrtp_profile = switch_core_alloc(rtp_session->pool, sizeof(*rtp_session->zrtp_profile)); - zrtp_profile_defaults(rtp_session->zrtp_profile, zrtp_global); + rtp_session->zrtp_profile->allowclear = 0; + rtp_session->zrtp_profile->disclose_bit = 0; + rtp_session->zrtp_profile->cache_ttl = -1; - rtp_session->zrtp_profile->allowclear = 0; - rtp_session->zrtp_profile->disclose_bit = 0; - rtp_session->zrtp_profile->cache_ttl = -1; + if (zrtp_status_ok != zrtp_session_init(zrtp_global, rtp_session->zrtp_profile, zid, initiator, &rtp_session->zrtp_session)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! zRTP INIT Failed\n"); + zrtp_session_down(rtp_session->zrtp_session); + rtp_session->zrtp_session = NULL; + goto end; + } - if (zrtp_status_ok != zrtp_session_init(zrtp_global, rtp_session->zrtp_profile, zid, initiator, &rtp_session->zrtp_session)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! zRTP INIT Failed\n"); - zrtp_session_down(rtp_session->zrtp_session); - rtp_session->zrtp_session = NULL; + zrtp_session_set_userdata(rtp_session->zrtp_session, session); + + + if (zrtp_status_ok != zrtp_stream_attach(master_rtp_session->zrtp_session, &rtp_session->zrtp_stream)) { + abort(); + } + + zrtp_stream_set_userdata(rtp_session->zrtp_stream, rtp_session); + + if (switch_true(switch_channel_get_variable(channel, "zrtp_enrollment"))) { + zrtp_stream_registration_start(rtp_session->zrtp_stream, rtp_session->ssrc); + } else { + zrtp_stream_start(rtp_session->zrtp_stream, rtp_session->ssrc); + } } - zrtp_session_set_userdata(rtp_session->zrtp_session, rtp_session); - - if (zrtp_status_ok != zrtp_stream_attach(rtp_session->zrtp_session, &rtp_session->zrtp_audio_ctx)) { - abort(); - } - zrtp_stream_set_userdata(rtp_session->zrtp_audio_ctx, rtp_session); - - if (switch_true(switch_channel_get_variable(channel, "zrtp_enrollment"))) { - zrtp_stream_registration_start(rtp_session->zrtp_audio_ctx, rtp_session->ssrc); - } else { - zrtp_stream_start(rtp_session->zrtp_audio_ctx, rtp_session->ssrc); - } } } + + end: + #endif rtp_session->ready = 1; @@ -1484,8 +1516,8 @@ SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session) /* ZRTP */ if (zrtp_on) { - if ((*rtp_session)->zrtp_audio_ctx != NULL) { - zrtp_stream_stop((*rtp_session)->zrtp_audio_ctx); + if ((*rtp_session)->zrtp_stream != NULL) { + zrtp_stream_stop((*rtp_session)->zrtp_stream); } if (switch_test_flag((*rtp_session), SWITCH_ZRTP_FLAG_SECURE_SEND)) { @@ -1940,7 +1972,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (!bytes && poll_loop) { goto recvfrom; } - + if (bytes && rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->te) { rtp_flush_read_buffer(rtp_session, SWITCH_RTP_FLUSH_ONCE); } @@ -2063,24 +2095,43 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ do_2833(rtp_session); } +#ifdef ENABLE_ZRTP + /* ZRTP Recv */ + if (bytes) { + unsigned int sbytes = (int) bytes; + zrtp_status_t stat = 0; + + stat = zrtp_process_srtp(rtp_session->zrtp_stream, (void *)&rtp_session->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 && rtp_session->recv_msg.header.version != 2) { uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; - if (rtp_session->recv_msg.header.version == 0) { -#ifdef ENABLE_ZRTP - if (zrtp_on && ZRTP_PACKETS_MAGIC == zrtp_ntoh32(rtp_session->recv_msg.header.ts)) { - zrtp_handler(rtp_session, rtp_session->sock_input, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr); - } else { -#endif - if (rtp_session->ice_user) { - handle_ice(rtp_session, (void *) &rtp_session->recv_msg, bytes); - } else if (rtp_session->remote_stun_addr) { - handle_stun_ping_reply(rtp_session, (void *) &rtp_session->recv_msg, bytes); - } -#ifdef ENABLE_ZRTP - } -#endif - } + if (rtp_session->recv_msg.header.version == 0) { + if (rtp_session->ice_user) { + handle_ice(rtp_session, (void *) &rtp_session->recv_msg, bytes); + } else if (rtp_session->remote_stun_addr) { + handle_stun_ping_reply(rtp_session, (void *) &rtp_session->recv_msg, bytes); + } + } + if (rtp_session->invalid_handler) { rtp_session->invalid_handler(rtp_session, rtp_session->sock_input, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr); } @@ -2133,31 +2184,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ bytes = sbytes; } -#ifdef ENABLE_ZRTP - /* ZRTP Recv */ - if (bytes && switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_RECV)) { - unsigned int sbytes = (int) bytes; - zrtp_status_t stat = 0; - - stat = zrtp_process_srtp(rtp_session->zrtp_audio_ctx, (void *)&rtp_session->recv_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); - break; - 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; - } - bytes = sbytes; - } -#endif - #ifdef DEBUG_2833 if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) { printf("sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); @@ -2504,8 +2530,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp #ifdef ENABLE_ZRTP if (zrtp_on && switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV)) { zrtp_session_info_t zrtp_session_info; - - if (zrtp_status_ok == zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info)) { + + if (rtp_session->zrtp_session && (zrtp_status_ok == zrtp_session_get(rtp_session->zrtp_session, &zrtp_session_info))) { if (zrtp_session_info.sas_is_ready) { 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); @@ -2516,7 +2542,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp if ((other_session = switch_core_session_locate(uuid))) { switch_channel_t *other_channel = switch_core_session_get_channel(other_session); - switch_rtp_t *other_rtp_session = switch_channel_get_private(other_channel, "__zrtp_rtp_session"); + switch_rtp_t *other_rtp_session = switch_channel_get_private(other_channel, "__zrtp_audio_rtp_session"); if (other_rtp_session) { if (zrtp_status_ok == zrtp_session_get(other_rtp_session->zrtp_session, &zrtp_session_info)) { @@ -2525,7 +2551,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp switch_clear_flag(other_rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); - } else if (zrtp_status_ok == zrtp_resolve_mitm_call(other_rtp_session->zrtp_audio_ctx, rtp_session->zrtp_audio_ctx)) { + } else if (zrtp_status_ok == zrtp_resolve_mitm_call(other_rtp_session->zrtp_stream, rtp_session->zrtp_stream)) { switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); switch_clear_flag(other_rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); @@ -2541,8 +2567,12 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp } } } + } else { + switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); + switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); } } + #endif if (bytes < 0) { @@ -2798,17 +2828,19 @@ static int rtp_common_write(switch_rtp_t *rtp_session, } #ifdef ENABLE_ZRTP /* ZRTP Send */ - if (switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND)) { + if (1) { unsigned int sbytes = (int) bytes; zrtp_status_t stat = zrtp_status_fail; - stat = zrtp_process_rtp(rtp_session->zrtp_audio_ctx, (void*)send_msg, &sbytes); + stat = zrtp_process_rtp(rtp_session->zrtp_stream, (void*)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); @@ -3004,7 +3036,6 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra rtp_session->stats.outbound.media_bytes += bytes; rtp_session->stats.outbound.media_packet_count++; rtp_session->stats.outbound.packet_count++; - return (int) bytes; } @@ -3023,7 +3054,9 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra if ((other_session = switch_core_session_locate(uuid))) { switch_channel_t *other_channel = switch_core_session_get_channel(other_session); - switch_rtp_t *other_rtp_session = switch_channel_get_private(other_channel, "__zrtp_rtp_session"); + switch_rtp_t *other_rtp_session = switch_channel_get_private(other_channel, "__zrtp_audio_rtp_session"); + + if (other_rtp_session) { if (zrtp_status_ok == zrtp_session_get(other_rtp_session->zrtp_session, &zrtp_session_info)) { if (rtp_session->zrtp_mitm_tries > ZRTP_MITM_TRIES) { @@ -3031,7 +3064,7 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); switch_clear_flag(other_rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); switch_clear_flag(other_rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); - } else if (zrtp_status_ok == zrtp_resolve_mitm_call(other_rtp_session->zrtp_audio_ctx, rtp_session->zrtp_audio_ctx)) { + } else if (zrtp_status_ok == zrtp_resolve_mitm_call(other_rtp_session->zrtp_stream, rtp_session->zrtp_stream)) { switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); switch_clear_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_SEND); switch_clear_flag(other_rtp_session, SWITCH_ZRTP_FLAG_SECURE_MITM_RECV); @@ -3152,17 +3185,19 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session, } #ifdef ENABLE_ZRTP /* ZRTP Send */ - if (switch_test_flag(rtp_session, SWITCH_ZRTP_FLAG_SECURE_SEND)) { + if (1) { unsigned int sbytes = (int) bytes; zrtp_status_t stat = zrtp_status_fail; - stat = zrtp_process_rtp(rtp_session->zrtp_audio_ctx, (void*)&rtp_session->write_msg, &sbytes); + stat = zrtp_process_rtp(rtp_session->zrtp_stream, (void*)&rtp_session->write_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);