[Freeswitch-svn] [commit] r7260 - in freeswitch/trunk/src: . include mod/endpoints/mod_sofia

Freeswitch SVN anthm at freeswitch.org
Wed Jan 16 23:16:04 EST 2008


Author: anthm
Date: Wed Jan 16 23:16:04 2008
New Revision: 7260

Modified:
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/switch_rtp.c

Log:
spec followers finish last

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Wed Jan 16 23:16:04 2008
@@ -370,17 +370,20 @@
 	SWITCH_RTP_FLAG_IO = (1 << 1),
 	SWITCH_RTP_FLAG_USE_TIMER = (1 << 2),
 	SWITCH_RTP_FLAG_TIMER_RECLOCK = (1 << 3),
-	SWITCH_RTP_FLAG_SECURE = (1 << 4),
-	SWITCH_RTP_FLAG_AUTOADJ = (1 << 5),
-	SWITCH_RTP_FLAG_RAW_WRITE = (1 << 6),
-	SWITCH_RTP_FLAG_GOOGLEHACK = (1 << 7),
-	SWITCH_RTP_FLAG_VAD = (1 << 8),
-	SWITCH_RTP_FLAG_BREAK = (1 << 9),
-	SWITCH_RTP_FLAG_MINI = (1 << 10),
-	SWITCH_RTP_FLAG_DATAWAIT = (1 << 11),
-	SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 12),
-	SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 13),
-	SWITCH_RTP_FLAG_AUTO_CNG = (1 << 14)
+	SWITCH_RTP_FLAG_SECURE_SEND = (1 << 4),
+	SWITCH_RTP_FLAG_SECURE_RECV = (1 << 5),
+	SWITCH_RTP_FLAG_AUTOADJ = (1 << 6),
+	SWITCH_RTP_FLAG_RAW_WRITE = (1 << 7),
+	SWITCH_RTP_FLAG_GOOGLEHACK = (1 << 8),
+	SWITCH_RTP_FLAG_VAD = (1 << 9),
+	SWITCH_RTP_FLAG_BREAK = (1 << 10),
+	SWITCH_RTP_FLAG_MINI = (1 << 11),
+	SWITCH_RTP_FLAG_DATAWAIT = (1 << 12),
+	SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 13),
+	SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14),
+	SWITCH_RTP_FLAG_AUTO_CNG = (1 << 15),
+	SWITCH_RTP_FLAG_SECURE_SEND_RESET = (1 << 16),
+	SWITCH_RTP_FLAG_SECURE_RECV_RESET = (1 << 17)
 } switch_rtp_flag_t;
 
 /*!

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Wed Jan 16 23:16:04 2008
@@ -82,15 +82,16 @@
 	tech_pvt->session_id++;
 	
 	switch_snprintf(buf, sizeof(buf),
-			 "v=0\n"
-			 "o=FreeSWITCH %010u %010u IN IP4 %s\n"
-			 "s=FreeSWITCH\n" 
-			 "c=IN IP4 %s\n" "t=0 0\n" 
-			 "a=%s\n" 
-			 "m=audio %d RTP/AVP", tech_pvt->owner_id, tech_pvt->session_id, ip, ip, sr, port);
+					"v=0\n"
+					"o=FreeSWITCH %010u %010u IN IP4 %s\n"
+					"s=FreeSWITCH\n" 
+					"c=IN IP4 %s\n" "t=0 0\n" 
+					"a=%s\n" 
+					"m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, ip, ip, sr, port,
+					(!switch_strlen_zero(tech_pvt->local_crypto_key) && switch_test_flag(tech_pvt, TFLAG_SECURE)) ? "S" : ""
+					);
 	
 
-
 	if (tech_pvt->rm_encoding) {
 		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->pt);
 	} else if (tech_pvt->num_codecs) {
@@ -184,9 +185,38 @@
 		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime);
 	}
 
+
 	if (!switch_strlen_zero(tech_pvt->local_crypto_key) && switch_test_flag(tech_pvt, TFLAG_SECURE)) {
 		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=crypto:%s\n", tech_pvt->local_crypto_key);
-		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+		//switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "m=audio %d RTP/AVP", port);
+		
+		if (tech_pvt->rm_encoding) {
+			switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", tech_pvt->pt);
+		} else if (tech_pvt->num_codecs) {
+			int i;
+			int already_did[128] = { 0 };
+			for (i = 0; i < tech_pvt->num_codecs; i++) {
+				const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+				
+				if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+					continue;
+				}
+				
+				if (imp->ianacode < 128) {
+					if (already_did[imp->ianacode]) {
+						continue;
+					}
+					
+					already_did[imp->ianacode] = 1;
+				}
+
+				switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %d", imp->ianacode);
+			}
+		}
+
+		switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "\na=crypto:%s\n", tech_pvt->local_crypto_key);
+		
 	}
 
 	if (switch_test_flag(tech_pvt, TFLAG_VIDEO) && tech_pvt->video_rm_encoding) {
@@ -1455,6 +1485,7 @@
 	switch_channel_t *channel = NULL;
 	const char *val;
 	const char *crypto = NULL;
+	int got_crypto = 0;
 
 	tech_pvt = switch_core_session_get_private(session);
 	switch_assert(tech_pvt != NULL);
@@ -1542,30 +1573,40 @@
 
 		if (m->m_type == sdp_media_audio) {
 			sdp_rtpmap_t *map;
-
+			
 			for (a = m->m_attributes; a; a = a->a_next) {
 				if (!strcasecmp(a->a_name, "ptime") && a->a_value) {
 					ptime = atoi(a->a_value);
-				} else if (!strcasecmp(a->a_name, "crypto") && a->a_value) {
+				} else if (!got_crypto && !strcasecmp(a->a_name, "crypto") && !switch_strlen_zero(a->a_value)) {
 					crypto = a->a_value;
 					int crypto_tag = atoi(crypto);
 					
+
 					if (tech_pvt->remote_crypto_key) {
 						if (crypto_tag && crypto_tag == tech_pvt->crypto_tag) {
 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
 						} else {
-							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
-							tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
-							tech_pvt->crypto_tag = crypto_tag;
-							sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
-							switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag, 
-													  tech_pvt->crypto_type, tech_pvt->remote_raw_key, SWITCH_RTP_KEY_LEN);
+							const char *a = switch_stristr("AES", tech_pvt->remote_crypto_key);
+							const char *b = switch_stristr("AES", crypto);
+							
+							if (a && b && strncasecmp(a, b, 23)) {
+								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
+								tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
+								tech_pvt->crypto_tag = crypto_tag;
+								sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
+								switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag, 
+														  tech_pvt->crypto_type, tech_pvt->remote_raw_key, SWITCH_RTP_KEY_LEN);
+								got_crypto++;
+							} else {
+								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
+							}
 						}
 					} else {
 						tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", tech_pvt->remote_crypto_key);
 						tech_pvt->crypto_tag = crypto_tag;
-
+						got_crypto++;
+						
 						if (switch_strlen_zero(tech_pvt->local_crypto_key)) {
 							if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
 								switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
@@ -1577,6 +1618,16 @@
 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
 							}
 						}
+
+						if (switch_rtp_ready(tech_pvt->rtp_session) &&
+							!switch_strlen_zero(tech_pvt->local_crypto_key) && !switch_strlen_zero(tech_pvt->remote_crypto_key)) {
+							switch_set_flag_locked(tech_pvt, TFLAG_SECURE);
+							sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
+							switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag,
+                                                      tech_pvt->crypto_type, tech_pvt->remote_raw_key, SWITCH_RTP_KEY_LEN);
+							switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, tech_pvt->crypto_tag,
+                                                      tech_pvt->crypto_type, tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
+						}
 					}
 				}
 			}

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Wed Jan 16 23:16:04 2008
@@ -495,10 +495,15 @@
 	switch_rtp_crypto_key_t *crypto_key;
 	srtp_policy_t *policy;
 	err_status_t stat;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	crypto_key = switch_core_alloc(rtp_session->pool, sizeof(*crypto_key));
 	
-	policy = direction == SWITCH_RTP_CRYPTO_RECV ? &rtp_session->recv_policy : &rtp_session->send_policy;
+	if (direction == SWITCH_RTP_CRYPTO_RECV) {
+		policy = &rtp_session->recv_policy;
+	} else {
+		policy = &rtp_session->send_policy;
+	}
 	
 
 	crypto_key->type = type;
@@ -509,7 +514,7 @@
 
 
 	memset(policy, 0, sizeof(*policy));
-	switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE);
+	
 
 	switch(crypto_key->type) {
 	case AES_CM_128_HMAC_SHA1_80:
@@ -532,21 +537,43 @@
 	switch(direction) {
 	case SWITCH_RTP_CRYPTO_RECV:
 		policy->ssrc.type = ssrc_any_inbound;
-		if ((stat = srtp_create(&rtp_session->recv_ctx, policy))) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
-			return SWITCH_STATUS_FALSE;
+
+		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV)) {
+			switch_set_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET);
+		} else {
+			if ((stat = srtp_create(&rtp_session->recv_ctx, policy))) {
+				status = SWITCH_STATUS_FALSE;
+			}
+
+			if (status == SWITCH_STATUS_SUCCESS) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP RECV\n");
+				switch_set_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV);
+			} else {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
+				return status;
+			}
 		}
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP RECV\n");
 		break;
 	case SWITCH_RTP_CRYPTO_SEND:
 		policy->ssrc.type = ssrc_specific;
 		policy->ssrc.value = rtp_session->ssrc;
 
-		if ((stat = srtp_create(&rtp_session->send_ctx, policy))) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
-			return SWITCH_STATUS_FALSE;
+		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
+			switch_set_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET);
+		} else {
+			if ((stat = srtp_create(&rtp_session->send_ctx, policy))) {
+				status = SWITCH_STATUS_FALSE;
+			}
+
+			if (status == SWITCH_STATUS_SUCCESS) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP SEND\n");
+				switch_set_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND);
+			} else {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
+				return status;
+			}
 		}
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Activating Secure RTP SEND\n");
+
 		break;
 	default:
 		abort();
@@ -774,9 +801,20 @@
 		switch_rtp_disable_vad(*rtp_session);
 	}
 
-	if (switch_test_flag((*rtp_session), SWITCH_RTP_FLAG_SECURE)) {
-		srtp_dealloc((*rtp_session)->recv_ctx);
+	if (switch_test_flag((*rtp_session), SWITCH_RTP_FLAG_SECURE_SEND)) {
+		switch_mutex_lock((*rtp_session)->flag_mutex);
 		srtp_dealloc((*rtp_session)->send_ctx);
+		(*rtp_session)->send_ctx = NULL;
+		switch_clear_flag((*rtp_session), SWITCH_RTP_FLAG_SECURE_SEND);
+		switch_mutex_unlock((*rtp_session)->flag_mutex);
+	}
+
+	if (switch_test_flag((*rtp_session), SWITCH_RTP_FLAG_SECURE_RECV)) {
+		switch_mutex_lock((*rtp_session)->flag_mutex);
+		srtp_dealloc((*rtp_session)->recv_ctx);
+		(*rtp_session)->recv_ctx = NULL;
+		switch_clear_flag((*rtp_session), SWITCH_RTP_FLAG_SECURE_RECV);
+		switch_mutex_unlock((*rtp_session)->flag_mutex);
 	}
 
 	if ((*rtp_session)->timer.timer_interface) {
@@ -970,12 +1008,26 @@
 			return -1;
 		}
 
-		if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
+		if (bytes && switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV)) {
 			int sbytes = (int) bytes;
-			err_status_t stat;
+			err_status_t stat = 0;
 
+			if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET)) {
+				switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE_RECV_RESET);
+				srtp_dealloc(rtp_session->recv_ctx);
+				rtp_session->recv_ctx = NULL;
+				if ((stat = srtp_create(&rtp_session->recv_ctx, &rtp_session->recv_policy))) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP RECV\n");
+					return -1;
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RE-Activating Secure RTP RECV\n");
+					rtp_session->srtp_errs = 0;
+				}
+			}
 
 			stat = srtp_unprotect(rtp_session->recv_ctx, &rtp_session->recv_msg.header, &sbytes);
+
+
 			if (stat && rtp_session->recv_msg.header.pt != rtp_session->te && rtp_session->recv_msg.header.pt != rtp_session->cng_pt) {
 				if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) {
 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
@@ -1558,10 +1610,24 @@
 		send_msg->header.seq = htons(++rtp_session->seq);
 		
 
-		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
+		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
 			int sbytes = (int) bytes;
 			err_status_t stat;
 			
+
+			if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET)) {
+				switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET);
+				srtp_dealloc(rtp_session->send_ctx);
+				rtp_session->send_ctx = NULL;
+				if ((stat = srtp_create(&rtp_session->send_ctx, &rtp_session->send_policy))) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP SEND\n");
+					return -1;
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RE-Activating Secure RTP SEND\n");
+				}
+			}
+			
+
 			stat = srtp_protect(rtp_session->send_ctx, &send_msg->header, &sbytes);
 			if (stat) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error: srtp protection failed with code %d\n", stat);
@@ -1723,10 +1789,22 @@
 
 	bytes = rtp_header_len + datalen;
 
-	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE)) {
+	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
 		int sbytes = (int) bytes;
 		err_status_t stat;
 
+		if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET)) {
+			switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND_RESET);
+			srtp_dealloc(rtp_session->send_ctx);
+			rtp_session->send_ctx = NULL;
+			if ((stat = srtp_create(&rtp_session->send_ctx, &rtp_session->send_policy))) {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! RE-Activating Secure RTP SEND\n");
+				return -1;
+			} else {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RE-Activating Secure RTP SEND\n");
+			}
+		}
+
 		stat = srtp_protect(rtp_session->send_ctx, &rtp_session->write_msg.header, &sbytes);
 		if (stat) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error: srtp protection failed with code %d\n", stat);



More information about the Freeswitch-svn mailing list