[Freeswitch-svn] [commit] r13734 - in freeswitch/trunk: conf/sip_profiles src/mod/endpoints/mod_sofia

FreeSWITCH SVN brian at freeswitch.org
Tue Jun 9 12:05:12 PDT 2009


Author: brian
Date: Tue Jun  9 14:05:11 2009
New Revision: 13734

Log:
 improve handling of 302 redirect and add option to handle them in the dialplan if needed.  Also all redirects back to ourself will be transfered to the dialplan automatically now bypassing the loop.

Modified:
   freeswitch/trunk/conf/sip_profiles/internal.xml
   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/conf/sip_profiles/internal.xml
==============================================================================
--- freeswitch/trunk/conf/sip_profiles/internal.xml	(original)
+++ freeswitch/trunk/conf/sip_profiles/internal.xml	Tue Jun  9 14:05:11 2009
@@ -134,7 +134,9 @@
     <!--Uncomment if you want to force the outbound leg of a bridge to only offer the codec 
 	that the originator is using-->
     <!--<param name="disable-transcoding" value="true"/>-->
-    <!-- Disable Refer -->
+    <!-- Handle 302 Redirect in the dialplan -->
+    <!--<param name="manual-redirect" value="true"/> -->
+    <!-- Disable Register -->
     <!--<param name="disable-transfer" value="true"/> -->
     <!-- Disable Register -->
     <!--<param name="disable-register" value="true"/> -->

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	Tue Jun  9 14:05:11 2009
@@ -191,7 +191,7 @@
 	PFLAG_AUTOFIX_TIMING,
 	PFLAG_MESSAGE_QUERY_ON_REGISTER,
 	PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE,
-	PFLAG_PROXY_FOLLOW_REDIRECT,
+	PFLAG_MANUAL_REDIRECT,
 	PFLAG_AUTO_NAT,
 	/* No new flags below this line */
 	PFLAG_MAX
@@ -621,6 +621,7 @@
 	switch_codec_implementation_t read_impl;
 	switch_codec_implementation_t write_impl;
 	char *user_via;
+	char *redirected;
 };
 
 struct callback_t {

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	Tue Jun  9 14:05:11 2009
@@ -1591,11 +1591,11 @@
 						} else {
 							sofia_clear_pflag(profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
 						}
-					} else if (!strcasecmp(var, "proxy-follow-redirect")) {
+					} else if (!strcasecmp(var, "manual-redirect")) {
 						if (switch_true(val)) {
-							sofia_set_pflag(profile, PFLAG_PROXY_FOLLOW_REDIRECT);
+							sofia_set_pflag(profile, PFLAG_MANUAL_REDIRECT);
 						} else {
-							sofia_clear_pflag(profile, PFLAG_PROXY_FOLLOW_REDIRECT);
+							sofia_clear_pflag(profile, PFLAG_MANUAL_REDIRECT);
 						}
 					} else if (!strcasecmp(var, "outbound-use-uuid-as-callid")) {
 						if (switch_true(val)) {
@@ -2109,11 +2109,11 @@
 						} else {
 							sofia_clear_pflag(profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
 						}
-					} else if (!strcasecmp(var, "proxy-follow-redirect")) {
+					} else if (!strcasecmp(var, "manual-redirect")) {
 						if (switch_true(val)) {
-							sofia_set_pflag(profile, PFLAG_PROXY_FOLLOW_REDIRECT);
+							sofia_set_pflag(profile, PFLAG_MANUAL_REDIRECT);
 						} else {
-							sofia_clear_pflag(profile, PFLAG_PROXY_FOLLOW_REDIRECT);
+							sofia_clear_pflag(profile, PFLAG_MANUAL_REDIRECT);
 						}
 					} else if (!strcasecmp(var, "inbound-proxy-media") && switch_true(val)) {
 						sofia_set_flag(profile, TFLAG_PROXY_MEDIA);
@@ -2968,42 +2968,134 @@
 			}
 		}
 
-		if (channel && sip && status == 100 && switch_channel_test_flag(channel, CF_OUTBOUND)) {
+		if (channel && sip && (status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
 			sip_contact_t * p_contact = sip->sip_contact;
 			int i = 0;
 			char var_name[80];	
+			const char *diversion_header;
+			char *full_contact = NULL;
+			char *invite_contact;
+			const char *br;
 			
-			if (sofia_test_pflag(profile, PFLAG_PROXY_FOLLOW_REDIRECT) && tech_pvt->route_uri && p_contact && p_contact->m_url) {
-				if (p_contact->m_url->url_port) {
-					tech_pvt->route_uri = switch_core_session_sprintf(tech_pvt->session, "sip:%s@%s:%s", 
-																	  p_contact->m_url->url_user, p_contact->m_url->url_host, p_contact->m_url->url_port);
-				} else {
-					tech_pvt->route_uri = switch_core_session_sprintf(tech_pvt->session, "sip:%s@%s", 
-																	  p_contact->m_url->url_user, p_contact->m_url->url_host);
-				}
+			if ((br = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
+				switch_xml_t root = NULL, domain = NULL;
+				switch_core_session_t *a_session;
+				switch_channel_t *a_channel;
 
-				nua_set_hparams(tech_pvt->nh, NUTAG_PROXY(tech_pvt->route_uri), TAG_END());
-			}
+				const char *sip_redirect_profile, *sip_redirect_context, *sip_redirect_dialplan, *sip_redirect_fork;
 
-			while (p_contact) {
-				if (p_contact->m_url) {
-					if (p_contact->m_url->url_user) {
-						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_user_%d", i);
-						switch_channel_set_variable_partner(channel, var_name, p_contact->m_url->url_user);
-						switch_channel_set_variable(channel, var_name, p_contact->m_url->url_user);
+				if ((a_session = switch_core_session_locate(br)) && (a_channel = switch_core_session_get_channel(a_session))) { 
+					switch_stream_handle_t stream = { 0 };
+					char separator[2] = "|";
+					char *redirect_dialstring;
+					su_home_t *home = su_home_new(sizeof(*home));
+					switch_assert(home != NULL);
+
+					SWITCH_STANDARD_STREAM(stream);
+
+					if (!(sip_redirect_profile = switch_channel_get_variable(channel, "sip_redirect_profile"))) {
+						sip_redirect_profile = profile->name;
+					}
+					if (!(sip_redirect_context = switch_channel_get_variable(channel, "sip_redirect_context"))) {
+						sip_redirect_context = "redirected";
+					}
+					if (!(sip_redirect_dialplan = switch_channel_get_variable(channel, "sip_redirect_dialplan"))) {
+						sip_redirect_dialplan = "XML";
+					}
+
+					sip_redirect_fork = switch_channel_get_variable(channel, "sip_redirect_fork");
+					
+					if (switch_true(sip_redirect_fork)) {
+						*separator = ',';
+					}
+
+					for (p_contact = sip->sip_contact; p_contact; p_contact = p_contact->m_next) {
+						if (p_contact->m_url) {
+							full_contact = sip_header_as_string(home, (void *) sip->sip_contact);
+							invite_contact = sofia_glue_strip_uri(full_contact);
+							
+							switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_%d", i);
+							switch_channel_set_variable(a_channel, var_name, full_contact);
+							
+							if (i == 0) {
+								switch_channel_set_variable(channel, "sip_redirected_to", full_contact);
+								switch_channel_set_variable(a_channel, "sip_redirected_to", full_contact);
+							}
+							
+							if (p_contact->m_url->url_user) {
+								switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_user_%d", i);
+								switch_channel_set_variable(channel, var_name, p_contact->m_url->url_user);
+								switch_channel_set_variable(a_channel, var_name, p_contact->m_url->url_user);
+							}
+							if (p_contact->m_url->url_host) {
+								switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_host_%d", i);
+								switch_channel_set_variable(channel, var_name, p_contact->m_url->url_host);
+								switch_channel_set_variable(a_channel, var_name, p_contact->m_url->url_host);
+							}
+							if (p_contact->m_url->url_params) {
+								switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_params_%d", i);
+								switch_channel_set_variable(channel, var_name, p_contact->m_url->url_params);
+								switch_channel_set_variable(a_channel, var_name, p_contact->m_url->url_params);
+							}
+							
+							switch_snprintf(var_name, sizeof(var_name), "sip_redirect_dialstring_%d", i);
+							switch_channel_set_variable_printf(channel, var_name, "sofia/%s/%s", sip_redirect_profile, invite_contact);
+							switch_channel_set_variable_printf(a_channel, var_name, "sofia/%s/%s", sip_redirect_profile, invite_contact);
+							stream.write_function(&stream, "%ssofia/%s/%s", i ? separator : "", sip_redirect_profile, invite_contact);
+							free(invite_contact);
+							i++;
+						}
+					}
+					
+					redirect_dialstring = stream.data;
+					
+					switch_channel_set_variable(channel, "sip_redirect_dialstring", redirect_dialstring);
+					switch_channel_set_variable(a_channel, "sip_redirect_dialstring", redirect_dialstring);
+					
+					p_contact = sip->sip_contact;
+					full_contact = sip_header_as_string(home, (void *) sip->sip_contact);
+					
+					if ((diversion_header = sofia_glue_get_unknown_header(sip, "diversion"))) {
+						switch_channel_set_variable(channel, "sip_redirected_by", diversion_header);
+						switch_channel_set_variable(a_channel, "sip_redirected_by", diversion_header);
 					}
-					if (p_contact->m_url->url_host) {
-						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_host_%d", i);
-						switch_channel_set_variable_partner(channel, var_name, p_contact->m_url->url_host);
-						switch_channel_set_variable(channel, var_name, p_contact->m_url->url_host);
+					
+					if (sofia_test_pflag(profile, PFLAG_MANUAL_REDIRECT)) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Redirect: Transfering to %s %s %s\n", 
+										  p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
+						switch_ivr_session_transfer(a_session, p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);					
+					} else if ((!strcmp(profile->sipip, p_contact->m_url->url_host))
+							   || (!strcmp(profile->extsipip, p_contact->m_url->url_host))
+							   || (switch_xml_locate_domain(p_contact->m_url->url_host, NULL, &root, &domain) == SWITCH_STATUS_SUCCESS)) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Redirect: Transfering to %s\n", p_contact->m_url->url_user);
+						switch_ivr_session_transfer(a_session, p_contact->m_url->url_user, NULL, NULL);
+					} else {
+						invite_contact = sofia_glue_strip_uri(full_contact);
+						tech_pvt->redirected = switch_core_session_strdup(session, invite_contact);
+						free(invite_contact);
 					}
-					if (p_contact->m_url->url_params) {
-						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_params_%d", i);
-						switch_channel_set_variable_partner(channel, var_name, p_contact->m_url->url_params);
-						switch_channel_set_variable(channel, var_name, p_contact->m_url->url_params);
+					
+					if (home) {
+						su_home_unref(home);
+						home = NULL;
 					}
-					p_contact = p_contact->m_next;
-					i++;
+
+					free(stream.data);
+					switch_core_session_rwunlock(a_session);
+				}
+			} else {
+				su_home_t *home = su_home_new(sizeof(*home));
+				switch_assert(home != NULL);
+				full_contact = sip_header_as_string(home, (void *) sip->sip_contact);
+				invite_contact = sofia_glue_strip_uri(full_contact);
+
+				tech_pvt->redirected = switch_core_session_strdup(session, invite_contact);
+
+				free(invite_contact);
+
+				if (home) {
+					su_home_unref(home);
+					home = NULL;
 				}
 			}
 		}
@@ -3084,6 +3176,22 @@
 			SIPTAG_REPLACES_STR_REF(replaces_str), SOATAG_LOCAL_SDP_STR_REF(l_sdp), SOATAG_REMOTE_SDP_STR_REF(r_sdp), TAG_END());
 	
 	if (ss_state == nua_callstate_terminated) {
+
+		if ((status == 302 || status == 305) && session) {
+			channel = switch_core_session_get_channel(session);
+			tech_pvt = switch_core_session_get_private(session);
+			
+			if (!tech_pvt || !tech_pvt->nh) {
+				goto done;
+			}
+			
+
+			if (tech_pvt->redirected) {
+				sofia_glue_do_invite(session);
+				goto done;
+			}
+		}
+
 		if (sofia_private) {
 			sofia_private->destroy_me = 1;
 		}
@@ -3493,7 +3601,7 @@
 			sdp_session_t *sdp;
 			uint8_t match = 0;
 			int is_ok = 1;
-			
+
 			sofia_clear_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
 
 			if (tech_pvt->num_codecs) {

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	Tue Jun  9 14:05:11 2009
@@ -1705,6 +1705,7 @@
 	nua_invite(tech_pvt->nh,
 			   NUTAG_AUTOANSWER(0),
 			   NUTAG_SESSION_TIMER(session_timeout),
+			   TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
 			   TAG_IF(!switch_strlen_zero(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
 			   TAG_IF(!switch_strlen_zero(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
 			   TAG_IF(!switch_strlen_zero(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
@@ -1724,6 +1725,7 @@
 			   SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL), TAG_IF(rep, SIPTAG_REPLACES_STR(rep)), SOATAG_HOLD(holdstr), TAG_END());
 
 	switch_safe_free(stream.data);
+	tech_pvt->redirected = NULL;
 
 	return SWITCH_STATUS_SUCCESS;
 }



More information about the Freeswitch-svn mailing list