Revision
16563
Author
brian
Date
2010-02-03 13:19:10 -0600 (Wed, 03 Feb 2010)

Log Message

 ZRTP Video works with ZFone (but you have to set your endpoint to use 99 for the payload for video or 125 in mod_h26x.c for H264 becuase the payloads MUST match or it can't figure it out

Modified Paths

Diff

Modified: freeswitch/trunk/src/include/switch_channel.h (16562 => 16563)


--- freeswitch/trunk/src/include/switch_channel.h	2010-02-03 19:14:12 UTC (rev 16562)
+++ freeswitch/trunk/src/include/switch_channel.h	2010-02-03 19:19:10 UTC (rev 16563)
@@ -434,6 +434,7 @@
   \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

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (16562 => 16563)


--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2010-02-03 19:14:12 UTC (rev 16562)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	2010-02-03 19:19:10 UTC (rev 16563)
@@ -2032,6 +2032,18 @@
 		}
 	}
 
+	if (tech_pvt->video_rtp_session) {
+		switch_rtp_destroy(&tech_pvt->video_rtp_session);
+	} else if (tech_pvt->local_sdp_video_port) {
+		switch_rtp_release_port(tech_pvt->profile->rtpip, tech_pvt->local_sdp_video_port);
+	}
+
+		
+	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) {
@@ -2042,16 +2054,6 @@
 		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) {
-		switch_rtp_release_port(tech_pvt->profile->rtpip, tech_pvt->local_sdp_video_port);
-	}
-
-		
-	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);
-	}
 }
 
 switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force)
@@ -2749,7 +2751,7 @@
 			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,

Modified: freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx (16562 => 16563)


--- freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx	2010-02-03 19:14:12 UTC (rev 16562)
+++ freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx	2010-02-03 19:19:10 UTC (rev 16563)
@@ -21111,6 +21111,23 @@
 }
 
 
+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_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_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;
 }

Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs (16562 => 16563)


--- freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs	2010-02-03 19:14:12 UTC (rev 16562)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs	2010-02-03 19:19:10 UTC (rev 16563)
@@ -2851,6 +2851,11 @@
     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 @@
     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 @@
     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 @@
   [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 @@
   [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 @@
   [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);

Modified: freeswitch/trunk/src/switch_channel.c (16562 => 16563)


--- freeswitch/trunk/src/switch_channel.c	2010-02-03 19:14:12 UTC (rev 16562)
+++ freeswitch/trunk/src/switch_channel.c	2010-02-03 19:19:10 UTC (rev 16563)
@@ -623,6 +623,24 @@
 	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;

Modified: freeswitch/trunk/src/switch_rtp.c (16562 => 16563)


--- freeswitch/trunk/src/switch_rtp.c	2010-02-03 19:14:12 UTC (rev 16562)
+++ freeswitch/trunk/src/switch_rtp.c	2010-02-03 19:19:10 UTC (rev 16563)
@@ -219,9 +219,9 @@
 #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 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;
 	
-	zrtp_session_info_t zrtp_session_info;
-
+	type = switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) ? "video" : "audio";
+	
 	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_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);
+			}
 		}
-		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);
-		}
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 {
 	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 @@
 
 
 	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 @@
 
 #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 @@
 			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);
 			
-			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();
+				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_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 @@
 	/* 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 @@
 		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 @@
 			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
+				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);
 				}
-#endif
 			}
-
+			
 			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 @@
 			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 @@
 #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 @@
 
 					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_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 @@
 					}
 				}
 			}
+		} 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 @@
 		}
 #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 @@
 		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 @@
 
 					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_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 @@
 	}
 #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);