[Freeswitch-trunk] [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-trunk
mailing list