[Freeswitch-svn] [commit] r12676 - freeswitch/trunk/src/mod/endpoints/mod_sofia

FreeSWITCH SVN anthm at freeswitch.org
Thu Mar 19 18:52:53 PDT 2009


Author: anthm
Date: Thu Mar 19 20:52:53 2009
New Revision: 12676

Log:
FSCORE-322

Modified:
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Thu Mar 19 20:52:53 2009
@@ -303,14 +303,14 @@
 		switch_core_session_rwunlock(a_session);
 	}
 
-
-
 	if (tech_pvt->nh && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
 		char reason[128] = "";
 		switch_stream_handle_t stream = { 0 };
 		switch_event_header_t *hi;
 		char *bye_headers = NULL;
 
+		sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
+
 		SWITCH_STANDARD_STREAM(stream);
 		if ((hi = switch_channel_variable_first(channel))) {
 			for (; hi; hi = hi->next) {
@@ -337,7 +337,7 @@
 			switch_snprintf(reason, sizeof(reason), "FreeSWITCH;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
 		}
 		
-		if (sofia_test_flag(tech_pvt, TFLAG_ANS)) {
+		if (switch_channel_test_flag(channel, CF_ANSWERED)) {
 			if (!tech_pvt->got_bye) {
 				switch_channel_set_variable(channel, "sip_hangup_disposition", "send_bye");
 			}
@@ -347,11 +347,12 @@
 					TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
 					TAG_END());
 		} else {
-			if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+			if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel));
 				if (!tech_pvt->got_bye) {
 					switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel");
 				}
+
 				nua_cancel(tech_pvt->nh, 
 						   SIPTAG_REASON_STR(reason), 
 						   TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
@@ -362,14 +363,16 @@
 				if (!tech_pvt->got_bye) {
 					switch_channel_set_variable(channel, "sip_hangup_disposition", "send_refuse");
 				}
-				nua_respond(tech_pvt->nh, sip_cause, sip_status_phrase(sip_cause), 
-							SIPTAG_REASON_STR(reason), 
-							TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
-							TAG_END());
+				if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+					nua_respond(tech_pvt->nh, sip_cause, sip_status_phrase(sip_cause), 
+								SIPTAG_REASON_STR(reason), 
+								TAG_IF(!switch_strlen_zero(bye_headers), SIPTAG_HEADER_STR(bye_headers)),
+								TAG_END());
+				}
 			}
 		}
 
-		sofia_set_flag(tech_pvt, TFLAG_BYE);
+
 		switch_safe_free(stream.data);
 	}
 
@@ -431,7 +434,7 @@
 	is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
 
 	if (b_sdp && is_proxy) {
-		tech_pvt->local_sdp_str = switch_core_session_strdup(session, b_sdp);
+		sofia_glue_tech_set_local_sdp(tech_pvt, b_sdp, SWITCH_TRUE);
 
 		if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
 			sofia_glue_tech_patch_sdp(tech_pvt);
@@ -443,13 +446,16 @@
 		/* This if statement check and handles the 3pcc proxy mode */
 		if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC)) {
 			/* Send the 200 OK */
-			nua_respond(tech_pvt->nh, SIP_200_OK,
-				SIPTAG_CONTACT_STR(tech_pvt->profile->url),
-				SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
-				SOATAG_REUSE_REJECTED(1),
-				SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "3PCC-PROXY, Sent a 200 OK, waiting for ACK\n");
-			
+			if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+				nua_respond(tech_pvt->nh, SIP_200_OK,
+							SIPTAG_CONTACT_STR(tech_pvt->profile->url),
+							SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+							SOATAG_REUSE_REJECTED(1),
+							SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
+
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "3PCC-PROXY, Sent a 200 OK, waiting for ACK\n");
+			}
+
 			/* Unlock the session signal to allow the ack to make it in */
 			// Maybe we should timeout?
 			switch_mutex_unlock(tech_pvt->sofia_mutex);
@@ -520,15 +526,16 @@
 		switch_channel_set_variable(channel, "sip_nat_detected", "true");
 	}
 
-
-	nua_respond(tech_pvt->nh, SIP_200_OK,
-				NUTAG_AUTOANSWER(0),
-				TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
-				NUTAG_SESSION_TIMER(session_timeout),
-				SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
-				SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
-				SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
-	sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
+	if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+		nua_respond(tech_pvt->nh, SIP_200_OK,
+					NUTAG_AUTOANSWER(0),
+					TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
+					NUTAG_SESSION_TIMER(session_timeout),
+					SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+					SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+					SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
+		sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
+	}
 
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -976,7 +983,7 @@
 	private_object_t *tech_pvt = switch_core_session_get_private(session);
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
-	if (switch_channel_down(channel) || !tech_pvt) {
+	if (switch_channel_down(channel) || !tech_pvt || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
 		status = SWITCH_STATUS_FALSE;
 		goto end;
 	}
@@ -1010,11 +1017,11 @@
 	default:
 		break;
 	}
-	
+
 	/* ones that do need to lock sofia mutex */
 	switch_mutex_lock(tech_pvt->sofia_mutex);
 
-	if (switch_channel_down(channel) || !tech_pvt) {
+	if (switch_channel_down(channel) || !tech_pvt || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
 		status = SWITCH_STATUS_FALSE;
 		goto end_lock;
 	}
@@ -1046,11 +1053,13 @@
 				sofia_glue_set_local_sdp(tech_pvt, ip, atoi(port), msg->string_arg, 1);
 			}
 
-			nua_respond(tech_pvt->nh, SIP_200_OK,
-						SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
-						SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
-						SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
-			switch_channel_mark_answered(channel);
+			if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+				nua_respond(tech_pvt->nh, SIP_200_OK,
+							SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+							SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+							SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
+				switch_channel_mark_answered(channel);
+			}
 		}
 		break;
 	case SWITCH_MESSAGE_INDICATE_NOMEDIA:
@@ -1061,7 +1070,8 @@
 			const char *ip = NULL, *port = NULL;
 
 			switch_channel_set_flag(channel, CF_PROXY_MODE);
-			tech_pvt->local_sdp_str = NULL;
+			sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
+
 			if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
 				&& (other_session = switch_core_session_locate(uuid))) {
 				other_channel = switch_core_session_get_channel(other_session);
@@ -1085,7 +1095,8 @@
 		{
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Sending media re-direct:\n%s\n", 
 							  switch_channel_get_name(channel), msg->string_arg);
-			tech_pvt->local_sdp_str = switch_core_session_strdup(session, msg->string_arg);
+			sofia_glue_tech_set_local_sdp(tech_pvt, msg->string_arg, SWITCH_TRUE);
+
 			sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
 			sofia_glue_do_invite(session);
 		}
@@ -1112,7 +1123,7 @@
 			uint32_t send_invite = 1;
 
 			switch_channel_clear_flag(channel, CF_PROXY_MODE);
-			tech_pvt->local_sdp_str = NULL;
+			sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
 
 			if (!switch_channel_media_ready(channel)) {
 				if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
@@ -1175,7 +1186,7 @@
 		break;
 	case SWITCH_MESSAGE_INDICATE_REDIRECT:
 		if (!switch_strlen_zero(msg->string_arg)) {
-			if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
+			if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Redirecting to %s\n", msg->string_arg);
 				nua_respond(tech_pvt->nh, SIP_302_MOVED_TEMPORARILY, SIPTAG_CONTACT_STR(msg->string_arg), TAG_END());
 				sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
@@ -1212,7 +1223,7 @@
 		if (msg->numeric_arg || msg->string_arg) {
 			int code = msg->numeric_arg;
 			const char *reason = NULL;
-
+			
 			if (code) {
 				reason = msg->string_arg;
 			} else {
@@ -1229,6 +1240,12 @@
 				code = 488;
 			}
 
+			if (!switch_channel_test_flag(channel, CF_ANSWERED) && code >= 300) {
+				if (sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+					goto end_lock;
+				}
+			}
+			
 			if (switch_strlen_zero(reason) && code != 407 && code != 302) {
 				reason = sip_status_phrase(code);
 				if (switch_strlen_zero(reason)) {
@@ -1260,11 +1277,12 @@
 					}
 				}
 
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", code, reason);
-				nua_respond(tech_pvt->nh, code, su_strdup(tech_pvt->nh->nh_home, reason), TAG_IF(to_uri, SIPTAG_CONTACT_STR(to_uri)),
-							SIPTAG_SUPPORTED_STR(NULL), SIPTAG_ACCEPT_STR(NULL),
-							TAG_IF(!switch_strlen_zero(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)), TAG_END());
-				if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
+				if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", code, reason);
+					nua_respond(tech_pvt->nh, code, su_strdup(tech_pvt->nh->nh_home, reason), TAG_IF(to_uri, SIPTAG_CONTACT_STR(to_uri)),
+								SIPTAG_SUPPORTED_STR(NULL), SIPTAG_ACCEPT_STR(NULL),
+								TAG_IF(!switch_strlen_zero(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)), TAG_END());
+					
 					sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
 				}
 			} else if (code == 302 && !switch_strlen_zero(msg->string_arg)) {
@@ -1274,31 +1292,30 @@
 				msg->string_arg = p;
 				switch_core_session_receive_message(session, msg);
 				goto end_lock;
-			} else {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Responding with %d [%s]\n", code, reason);
-
-				if (!switch_strlen_zero(((char *) msg->pointer_arg))) {
-					tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, (char *) msg->pointer_arg);
-					if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
-						sofia_glue_tech_patch_sdp(tech_pvt);
-						sofia_glue_tech_proxy_remote_addr(tech_pvt);
+			} else if (!switch_channel_test_flag(channel, CF_ANSWERED)) {				
+				if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Responding with %d [%s]\n", code, reason);
+					if (!switch_strlen_zero(((char *) msg->pointer_arg))) {
+						sofia_glue_tech_set_local_sdp(tech_pvt, (char *) msg->pointer_arg, SWITCH_TRUE);
+						
+						if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
+							sofia_glue_tech_patch_sdp(tech_pvt);
+							sofia_glue_tech_proxy_remote_addr(tech_pvt);
+						}
+						nua_respond(tech_pvt->nh, code, su_strdup(tech_pvt->nh->nh_home, reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+									SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
+									SOATAG_REUSE_REJECTED(1),
+									SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
+					} else {
+						nua_respond(tech_pvt->nh, code, su_strdup(tech_pvt->nh->nh_home, reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), TAG_END());
 					}
-					nua_respond(tech_pvt->nh, code, su_strdup(tech_pvt->nh->nh_home, reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
-								SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
-								SOATAG_REUSE_REJECTED(1),
-								SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
-				} else {
-					nua_respond(tech_pvt->nh, code, su_strdup(tech_pvt->nh->nh_home, reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), TAG_END());
-				}
-				if (!switch_channel_test_flag(channel, CF_ANSWERED) && code >= 300) {
-					sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
 				}
 			}
 
 		}
 		break;
 	case SWITCH_MESSAGE_INDICATE_RINGING:
-		if (!switch_channel_test_flag(channel, CF_RING_READY) &&
+		if (!switch_channel_test_flag(channel, CF_RING_READY) && !sofia_test_flag(tech_pvt, TFLAG_BYE) &&
 			!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
 			nua_respond(tech_pvt->nh, SIP_180_RINGING, SIPTAG_CONTACT_STR(tech_pvt->reply_contact), TAG_END());
 			switch_channel_mark_ring_ready(channel);
@@ -1321,10 +1338,12 @@
 				if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
 					const char *sdp = NULL;
 					if ((sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE))) {
-						tech_pvt->local_sdp_str = switch_core_session_strdup(session, sdp);
+						sofia_glue_tech_set_local_sdp(tech_pvt, sdp, SWITCH_TRUE);
 					}
 					if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
+						
 						sofia_glue_tech_patch_sdp(tech_pvt);
+						
 						if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
 							status = SWITCH_STATUS_FALSE;
 							goto end_lock;
@@ -1369,16 +1388,17 @@
 					switch_channel_set_variable(channel, "sip_nat_detected", "true");
 				}
 
-
-				nua_respond(tech_pvt->nh,
-							SIP_183_SESSION_PROGRESS,
-							NUTAG_AUTOANSWER(0),
-							TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
-							SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
-							SOATAG_REUSE_REJECTED(1),
-							SOATAG_ORDERED_USER(1),
-							SOATAG_ADDRESS(tech_pvt->adv_sdp_audio_ip),
-							SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_AUDIO_AUX("cn telephone-event"), TAG_END());
+				if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+					nua_respond(tech_pvt->nh,
+								SIP_183_SESSION_PROGRESS,
+								NUTAG_AUTOANSWER(0),
+								TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
+								SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
+								SOATAG_REUSE_REJECTED(1),
+								SOATAG_ORDERED_USER(1),
+								SOATAG_ADDRESS(tech_pvt->adv_sdp_audio_ip),
+								SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_AUDIO_AUX("cn telephone-event"), TAG_END());
+				}
 			}
 		}
 		break;
@@ -1392,6 +1412,10 @@
 
   end:
 
+	if (switch_channel_down(channel) || !tech_pvt || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+		status = SWITCH_STATUS_FALSE;
+	}
+
 	return status;
 
 }

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	Thu Mar 19 20:52:53 2009
@@ -510,8 +510,13 @@
 	char *rm_fmtp;
 	char *fmtp_out;
 	char *remote_sdp_str;
+	int crypto_tag;
+	unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
+	unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
+	switch_rtp_crypto_key_type_t crypto_send_type;
+	switch_rtp_crypto_key_type_t crypto_recv_type;
+	switch_rtp_crypto_key_type_t crypto_type;
 	char *local_sdp_str;
-	char *orig_local_sdp_str;
 	char *dest;
 	char *dest_to;
 	char *key;
@@ -533,12 +538,6 @@
 	char *stun_ip;
 	switch_port_t stun_port;
 	uint32_t stun_flags;
-	int crypto_tag;
-	unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
-	unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
-	switch_rtp_crypto_key_type_t crypto_send_type;
-	switch_rtp_crypto_key_type_t crypto_recv_type;
-	switch_rtp_crypto_key_type_t crypto_type;
 	unsigned long rm_rate;
 	switch_payload_t pt;
 	switch_mutex_t *flag_mutex;
@@ -837,3 +836,4 @@
  */
 int sofia_get_loglevel(const char *name);
 sofia_cid_type_t sofia_cid_name2type(const char *name);
+void sofia_glue_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Thu Mar 19 20:52:53 2009
@@ -342,8 +342,21 @@
 		} else if (!switch_strlen_zero(sofia_private->uuid)) {
 			if ((session = switch_core_session_locate(sofia_private->uuid))) {
 				tech_pvt = switch_core_session_get_private(session);
-				switch_assert(tech_pvt);
-				channel = switch_core_session_get_channel(tech_pvt->session);
+				channel = switch_core_session_get_channel(session);
+				if (tech_pvt) {
+
+					if (status >= 300) {
+						sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
+					}
+
+					switch_mutex_lock(tech_pvt->sofia_mutex);
+					locked = 1;										
+				} else {
+					switch_core_session_rwunlock(session);
+					return;
+				}
+				
+				
 				if (status >= 180 && !*sofia_private->auth_gateway_name) {
 					const char *gwname = switch_channel_get_variable(channel, "sip_use_gateway");
 					if (!switch_strlen_zero(gwname)) {
@@ -369,11 +382,6 @@
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel is already hungup.\n");
 			goto done;
 		}
-
-		if (tech_pvt) {
-			switch_mutex_lock(tech_pvt->sofia_mutex);
-			locked = 1;
-		}
 	} else if (sofia_private && sofia_private->is_call) {
 		sofia_private->destroy_me = 22;
 	}
@@ -542,13 +550,13 @@
 		sofia_reg_release_gateway(gateway);
 	}
 
+	if (locked && tech_pvt) {
+		switch_mutex_unlock(tech_pvt->sofia_mutex);
+	}
+	
 	if (session) {
 		switch_core_session_rwunlock(session);
 	}
-
-	if (tech_pvt && locked) {
-		switch_mutex_unlock(tech_pvt->sofia_mutex);
-	}
 }
 
 void event_handler(switch_event_t *event)
@@ -697,6 +705,8 @@
 	switch_thread_t *worker_thread;
 	switch_status_t st;
 
+	
+
 	switch_mutex_lock(mod_sofia_globals.mutex);
 	mod_sofia_globals.threads++;
 	switch_mutex_unlock(mod_sofia_globals.mutex);
@@ -2798,13 +2808,13 @@
 	if (session) {
 		channel = switch_core_session_get_channel(session);
 		tech_pvt = switch_core_session_get_private(session);
-		switch_assert(tech_pvt != NULL);
-		if (!tech_pvt->nh) {
+
+		if (!tech_pvt || !tech_pvt->nh) {
 			goto done;
 		}
 
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel %s entering state [%s]\n",
-						  switch_channel_get_name(channel), nua_callstate_name(ss_state));
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Channel %s entering state [%s][%d]\n",
+						  switch_channel_get_name(channel), nua_callstate_name(ss_state), status);
 		
 		if (r_sdp) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp);
@@ -2894,7 +2904,6 @@
 					if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
 						switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
 					}
-
 					switch_channel_pre_answer(other_channel);
 					switch_core_session_rwunlock(other_session);
 				}
@@ -3071,13 +3080,13 @@
 					if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
 						&& (other_session = switch_core_session_locate(uuid))) {
 						switch_core_session_message_t msg = { 0 };
-
+						
 						if (profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) {
 							tech_pvt->hold_laps = 1;
 							switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
 							switch_channel_clear_flag(channel, CF_PROXY_MODE);
-							tech_pvt->local_sdp_str = NULL;
-
+							sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
+							
 							if (!switch_channel_media_ready(channel)) {
 								if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
 									//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
@@ -3329,44 +3338,44 @@
 			tech_pvt->q850_cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
 		}
 	case nua_callstate_terminated:
-		if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
-			sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
-			if (sofia_test_flag(tech_pvt, TFLAG_NOHUP)) {
-				sofia_clear_flag_locked(tech_pvt, TFLAG_NOHUP);
+		if (sofia_test_flag(tech_pvt, TFLAG_NOHUP)) {
+			sofia_clear_flag_locked(tech_pvt, TFLAG_NOHUP);
+		} else if (switch_channel_up(channel)) {
+			int cause;
+			if (tech_pvt->q850_cause) {
+				cause = tech_pvt->q850_cause;
 			} else {
-				int cause;
-				if (tech_pvt->q850_cause) {
-					cause = tech_pvt->q850_cause;
-				} else {
-					cause = sofia_glue_sip_cause_to_freeswitch(status);
-				}
-				if (status) {
-					switch_snprintf(st, sizeof(st), "%d", status);
-					switch_channel_set_variable(channel, "sip_term_status", st);
-					switch_snprintf(st, sizeof(st), "sip:%d", status);
-					switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
-					switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
-					if (phrase) {
-						switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase);
-					}
+				cause = sofia_glue_sip_cause_to_freeswitch(status);
+			}
+			if (status) {
+				switch_snprintf(st, sizeof(st), "%d", status);
+				switch_channel_set_variable(channel, "sip_term_status", st);
+				switch_snprintf(st, sizeof(st), "sip:%d", status);
+				switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
+				switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
+				if (phrase) {
+					switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase);
 				}
-				switch_snprintf(st, sizeof(st), "%d", cause);
-				switch_channel_set_variable(channel, "sip_term_cause", st);
-				switch_channel_hangup(channel, cause);
 			}
+			switch_snprintf(st, sizeof(st), "%d", cause);
+			switch_channel_set_variable(channel, "sip_term_cause", st);
+			switch_channel_hangup(channel, cause);
 		}
+		
+
 		if (ss_state == nua_callstate_terminated) {
 			if (tech_pvt->sofia_private) {
 				tech_pvt->sofia_private = NULL;
 			}
 			
 			tech_pvt->nh = NULL;
-			
+	
 			if (nh) {
 				nua_handle_bind(nh, NULL);
 				nua_handle_destroy(nh);
 			}
 		}
+		
 		break;
 	}
 
@@ -4616,7 +4625,7 @@
 		
 		switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
 	}
-
+	
 	if (!(sofia_private = malloc(sizeof(*sofia_private)))) {
 		abort();
 	}

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	Thu Mar 19 20:52:53 2009
@@ -103,8 +103,7 @@
 					t38_options->T38VendorInfo
 					);
 	
-	
-	tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, buf);
+	sofia_glue_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE);
 }
 
 void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32_t port, const char *sr, int force)
@@ -392,8 +391,7 @@
 			}
 		}
 	}
-
-	tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, buf);
+	sofia_glue_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE);
 }
 
 void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt)
@@ -862,16 +860,17 @@
 	return new_uri;
 }
 
+#define RA_PTR_LEN 512
 switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
 {
 	const char *err;
-	char rip[128] = "";
-	char rp[128] = "";
-	char rvp[128] = "";
-	char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL;
+	char rip[RA_PTR_LEN] = "";
+	char rp[RA_PTR_LEN] = "";
+	char rvp[RA_PTR_LEN] = "";
+	char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe;
 	int x;
 	const char *val;
-
+	
 	if (switch_strlen_zero(tech_pvt->remote_sdp_str)) {
 		return SWITCH_STATUS_FALSE;
 	}
@@ -898,24 +897,34 @@
 	}
 
 	p = ip_ptr;
+	pe = p + strlen(p);
 	x = 0;
-	while (x < sizeof(rip) && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) {
+	while (x < sizeof(rip) - 1 && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) {
 		rip[x++] = *p;
 		p++;
+		if (p >= pe) {
+			return SWITCH_STATUS_FALSE;
+		}
 	}
 
 	p = port_ptr;
 	x = 0;
-	while (x < sizeof(rp) && p && *p && (*p >= '0' && *p <= '9')) {
+	while (x < sizeof(rp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
 		rp[x++] = *p;
 		p++;
+		if (p >= pe) {
+			return SWITCH_STATUS_FALSE;
+		}
 	}
 
 	p = vid_port_ptr;
 	x = 0;
-	while (x < sizeof(rvp) && p && *p && (*p >= '0' && *p <= '9')) {
+	while (x < sizeof(rvp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
 		rvp[x++] = *p;
 		p++;
+		if (p >= pe) {
+			return SWITCH_STATUS_FALSE;
+		}
 	}
 
 	if (!(*rip && *rp)) {
@@ -965,12 +974,9 @@
 							  tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
 			return SWITCH_STATUS_SUCCESS;
 		}
-
-	}
-	
-	if (switch_rtp_ready(tech_pvt->rtp_session)) {
-		if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port, SWITCH_TRUE, &err) !=
-			SWITCH_STATUS_SUCCESS) {
+		
+		if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, 
+										  tech_pvt->remote_sdp_audio_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
 		} else {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
@@ -990,17 +996,19 @@
 void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt)
 {
 	switch_size_t len;
-	char *p, *q;
+	char *p, *q, *pe , *qe;
 	int has_video=0,has_audio=0,has_ip=0;
 	char port_buf[25] = "";
 	char vport_buf[25] = "";
+	char *new_sdp;
+	int bad = 0;
 
 	if (switch_strlen_zero(tech_pvt->local_sdp_str)) {
 		return;
 	}
 
-	len = strlen(tech_pvt->local_sdp_str) + 384;
-
+	len = strlen(tech_pvt->local_sdp_str) * 2;
+	
 	if (switch_stristr("sendonly", tech_pvt->local_sdp_str) || switch_stristr("0.0.0.0", tech_pvt->local_sdp_str)) {
 	    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Skip patch on hold SDP\n");
 	    return;
@@ -1016,14 +1024,26 @@
 		tech_pvt->codec_ms = 20;
 	}
 	
+	new_sdp = switch_core_session_alloc(tech_pvt->session, len);
 	switch_snprintf(port_buf, sizeof(port_buf), "%u", tech_pvt->adv_sdp_audio_port);
-	tech_pvt->orig_local_sdp_str = tech_pvt->local_sdp_str;
-	tech_pvt->local_sdp_str = switch_core_session_alloc(tech_pvt->session, len);
+	
 
-	p = tech_pvt->orig_local_sdp_str;
-	q = tech_pvt->local_sdp_str;
+	p = tech_pvt->local_sdp_str;
+	q = new_sdp;
+	pe = p + strlen(p);
+	qe = q + len - 1;
 
 	while(p && *p) {
+		if (p >= pe) {
+			bad = 1;
+			goto end;
+		}
+		
+		if (q >= qe) {
+			bad = 2;
+			goto end;
+		}
+
 	    if (tech_pvt->adv_sdp_audio_ip && !strncmp("c=IN IP", p, 7)) {
 			strncpy(q, p, 9);
 			p += 9;
@@ -1032,19 +1052,46 @@
 			q += strlen(tech_pvt->adv_sdp_audio_ip);
 
 			while(p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
+				if (p >= pe) {
+					bad = 3;
+					goto end;
+				}
 				p++;
 			}
 
 	    	has_ip++;
 
 		} else if (!strncmp("m=audio ", p, 8) || (!strncmp("m=image ", p, 8))) {
-			strncpy(q,p,8);
+			strncpy(q, p, 8);
 			p += 8;
+
+			if (p >= pe) {
+				bad = 4;
+				goto end;
+			}
+
+
 			q += 8;
+			
+			if (q >= qe) {
+				bad = 5;
+				goto end;
+			}
+
+
 			strncpy(q, port_buf, strlen(port_buf));
 			q += strlen(port_buf);
 
+			if (q >= qe) {
+				bad = 6;
+				goto end;
+			}
+
 			while (p && *p && (*p >= '0' && *p <= '9')) {
+				if (p >= pe) {
+					bad = 7;
+					goto end;
+				}
 				p++;
 			}
 
@@ -1061,33 +1108,102 @@
 
 			strncpy(q, p, 8);
 			p += 8;
+
+			if (p >= pe) {
+				bad = 8;
+				goto end;
+			}
+
 			q += 8;
+
+			if (q >= qe) {
+				bad = 9;
+				goto end;
+			}
+
 			strncpy(q, vport_buf, strlen(vport_buf));
 			q += strlen(vport_buf);
 
+			if (q >= qe) {
+				bad = 10;
+				goto end;
+			}
+
 			while (p && *p && (*p >= '0' && *p <= '9')) {
+
+				if (p >= pe) {
+					bad = 11;
+					goto end;
+				}
+
 				p++;
 			}
-
+			
 			has_video++;
 	    }
 	    
 	    while (p && *p && *p != '\n') {
+
+			if (p >= pe) {
+				bad = 12;
+				goto end;
+			}
+
+			if (q >= qe) {
+				bad = 13;
+				goto end;
+			}
+
 			*q++ = *p++;
 	    }
+		
+		if (p >= pe) {
+            bad = 14;
+            goto end;
+        }
+		
+		if (q >= qe) {
+			bad = 15;
+			goto end;
+		}
 
 	    *q++ = *p++;
+
 	}
 
+ end:
+
+	if (bad) {
+		return;
+	}
+
+
+	if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s too late.\n", switch_channel_get_name(tech_pvt->channel));
+		return;
+	}
+
+
 	if (!has_ip && !has_audio) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s SDP has no audio in it.\n%s\n",
 						  switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str);
-		tech_pvt->local_sdp_str = tech_pvt->orig_local_sdp_str;
 		return;
 	}
 	
+
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Patched SDP\n---\n%s\n+++\n%s\n",
-					  switch_channel_get_name(tech_pvt->channel), tech_pvt->orig_local_sdp_str, tech_pvt->local_sdp_str);
+					  switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str, new_sdp);
+
+	sofia_glue_tech_set_local_sdp(tech_pvt, new_sdp, SWITCH_FALSE);
+
+}
+
+
+void sofia_glue_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup)
+{
+	switch_mutex_lock(tech_pvt->sofia_mutex);
+	tech_pvt->local_sdp_str = dup ? switch_core_session_strdup(tech_pvt->session, sdp_str) : (char *)sdp_str;
+	switch_mutex_unlock(tech_pvt->sofia_mutex);	
 }
 
 
@@ -1298,7 +1414,6 @@
 								  SIPTAG_FROM_STR(from_str),
 								  SIPTAG_CONTACT_STR(invite_contact),
 								  TAG_END());
-		
 
 		if (tech_pvt->dest && (strstr(tech_pvt->dest, ";fs_nat") || strstr(tech_pvt->dest, ";received") 
 							   || ((val = switch_channel_get_variable(channel, "sip_sticky_contact")) && switch_true(val)))) {
@@ -1570,7 +1685,7 @@
 			}
 			sdp_parser_free(parser);
 		}
-		tech_pvt->local_sdp_str = switch_core_session_strdup(tech_pvt->session, sdp_str);
+		sofia_glue_tech_set_local_sdp(tech_pvt, sdp_str, SWITCH_TRUE);
 	}
 }
 
@@ -1883,6 +1998,11 @@
 	const char *var;
 
 	switch_assert(tech_pvt != NULL);
+
+	if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+		return SWITCH_STATUS_FALSE;
+	}
+
 	switch_mutex_lock(tech_pvt->sofia_mutex);
 
 	if (switch_rtp_ready(tech_pvt->rtp_session)) {
@@ -1893,7 +2013,6 @@
 		sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
 	}
 
-
 	if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
 		status = SWITCH_STATUS_SUCCESS;
 		goto end;
@@ -1997,6 +2116,7 @@
 		if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) {
 			goto end;
 		}
+
 		if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
 			!((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
 			flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
@@ -2005,7 +2125,8 @@
 		}
 		timer_name = NULL;
 
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
+						  "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
 						  switch_channel_get_name(tech_pvt->channel),
 						  tech_pvt->local_sdp_audio_ip,
 						  tech_pvt->local_sdp_audio_port,
@@ -2014,20 +2135,23 @@
 
 	} else {
 		timer_name = tech_pvt->profile->timer_name;
-	}
 
-	if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
-		timer_name = (char *) var;
+		if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
+			timer_name = (char *) var;
+		}
 	}
 
-	tech_pvt->rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
-										   tech_pvt->local_sdp_audio_port,
-										   tech_pvt->remote_sdp_audio_ip,
-										   tech_pvt->remote_sdp_audio_port,
-										   tech_pvt->agreed_pt,
-										   tech_pvt->read_impl.samples_per_packet,
-										   tech_pvt->codec_ms * 1000,
-										   (switch_rtp_flag_t) flags, timer_name, &err, switch_core_session_get_pool(tech_pvt->session));
+	if (switch_channel_up(tech_pvt->channel) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+		tech_pvt->rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
+											   tech_pvt->local_sdp_audio_port,
+											   tech_pvt->remote_sdp_audio_ip,
+											   tech_pvt->remote_sdp_audio_port,
+											   tech_pvt->agreed_pt,
+											   tech_pvt->read_impl.samples_per_packet,
+											   tech_pvt->codec_ms * 1000,
+											   (switch_rtp_flag_t) flags, timer_name, &err,
+											   switch_core_session_get_pool(tech_pvt->session));
+	}
 
 	if (switch_rtp_ready(tech_pvt->rtp_session)) {
 		uint8_t vad_in = sofia_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
@@ -2223,19 +2347,18 @@
 	switch_assert(tech_pvt != NULL);
 	switch_assert(r_sdp != NULL);
 
-	parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0);
-
 	if (switch_strlen_zero(r_sdp)) {
 		return SWITCH_STATUS_FALSE;
 	}
 
-	if (tech_pvt->num_codecs) {
-		if ((sdp = sdp_session(parser))) {
-			match = sofia_glue_negotiate_sdp(tech_pvt->session, sdp);
+	if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
+		
+		if (tech_pvt->num_codecs) {
+			if ((sdp = sdp_session(parser))) {
+				match = sofia_glue_negotiate_sdp(tech_pvt->session, sdp);
+			}
 		}
-	}
-
-	if (parser) {
+		
 		sdp_parser_free(parser);
 	}
 



More information about the Freeswitch-svn mailing list