]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
cleanup more on att-xfer
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 9 Oct 2009 22:28:31 +0000 (22:28 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 9 Oct 2009 22:28:31 +0000 (22:28 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15134 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_channel.h
src/mod/endpoints/mod_sofia/sofia.c
src/switch_channel.c
src/switch_ivr_originate.c

index 8a7a80e908245edf16be330caa021e1dbc9624d6..d9d0406a69fc541f7bb1f4f01781582204cb1e9c 100644 (file)
@@ -263,6 +263,8 @@ SWITCH_DECLARE(switch_event_header_t *) switch_channel_variable_first(switch_cha
 SWITCH_DECLARE(void) switch_channel_variable_last(switch_channel_t *channel);
 
 
+SWITCH_DECLARE(void) switch_channel_restart(switch_channel_t *channel);
+
 SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switch_channel_t *orig_channel, switch_channel_t *new_channel, uint32_t offset);
 
 /*!
index 0c281cfd48a6a12bcfb82ad65d05fba9c64e7c72..bc6f4f62eaa34cc41b32898d6e504b374b81825c 100644 (file)
@@ -4146,6 +4146,34 @@ static void launch_nightmare_xfer(nightmare_xfer_helper_t *nhelper)
 
 /*---------------------------------------*/
 
+static switch_status_t xfer_hanguphook(switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_channel_state_t state = switch_channel_get_state(channel);
+
+       if (state == CS_HANGUP) {
+               switch_core_session_t *ksession;
+               const char *uuid = switch_channel_get_variable(channel, "att_xfer_kill_uuid");
+               
+               if (uuid && (ksession = switch_core_session_force_locate(uuid))) {
+                       switch_channel_t *kchannel = switch_core_session_get_channel(ksession);
+                       
+                       switch_channel_clear_flag(kchannel, CF_XFER_ZOMBIE);
+                       switch_channel_clear_flag(kchannel, CF_TRANSFER);
+                       if (switch_channel_up(kchannel)) {
+                               switch_channel_hangup(kchannel, SWITCH_CAUSE_NORMAL_CLEARING);
+                       }
+
+                       switch_core_session_rwunlock(ksession);
+               }
+
+               switch_core_event_hook_remove_state_change(session, xfer_hanguphook);
+
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[])
 {
        /* Incoming refer */
@@ -4279,34 +4307,31 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
                                                                switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
                                                                const char *tmp;
 
+                                                               switch_core_event_hook_add_state_change(a_session, xfer_hanguphook);
+                                                               switch_channel_set_variable(a_channel, "att_xfer_kill_uuid", switch_core_session_get_uuid(b_session));
+
                                                                if ((tmp = switch_channel_get_variable(a_channel, SWITCH_HOLD_MUSIC_VARIABLE))) {
                                                                        moh = tmp;
                                                                }
-
+                                                               
                                                                if (!strcasecmp(moh, "silence")) {
                                                                        moh = NULL;
                                                                }
                                                                
-                                                               //switch_channel_set_variable(a_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, "true");
-                                                               
                                                                if (moh) {
                                                                        char *xdest;
-                                                                       //switch_channel_set_variable_printf(a_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, 
-                                                                       //                                                         "'endless_playback:%s,park':inline", moh);
                                                                        xdest = switch_core_session_sprintf(a_session, "endless_playback:%s,park", moh);
                                                                        switch_ivr_session_transfer(a_session, xdest, "inline", NULL);
                                                                } else {
-                                                                       //switch_channel_set_variable(a_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, "park:inline");
                                                                        switch_ivr_session_transfer(a_session, "park", "inline", NULL);
                                                                }
-                                                               //switch_channel_set_variable_printf(a_channel, "park_command", "moh");
+                                                               
                                                                switch_core_session_rwunlock(a_session);
 
                                                                nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
                                                                                   NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"), SIPTAG_EVENT_STR(etmp), TAG_END());
 
-                                                               
-                                                               if (1 && b_tech_pvt) {
+                                                               if (b_tech_pvt) {
                                                                        sofia_set_flag_locked(b_tech_pvt, TFLAG_BYE);
                                                                        nua_bye(b_tech_pvt->nh, 
                                                                                        SIPTAG_REASON_STR("Q.850;cause=16;text=\"normal_clearing\""),
@@ -4319,11 +4344,6 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
                                                                                   SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), TAG_END());
                                                        }
 
-                                                       
-                                                       //switch_channel_set_variable(channel_b, "park_timeout", "2");
-                                                       //switch_channel_set_state(channel_b, CS_PARK);
-                                                       
-                                                                                         
                                                } else if (br_a && br_b) {
                                                        switch_core_session_t *tmp = NULL;
                                                        
index acefb6ed815c90dacac0a5f473c80a086bc4ebcf..85cead7c5ef59464e801d923532abff2be5c0bb8 100644 (file)
@@ -1664,6 +1664,22 @@ SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channe
        switch_mutex_unlock(channel->state_mutex);
 }
 
+SWITCH_DECLARE(void) switch_channel_restart(switch_channel_t *channel)
+{
+       switch_channel_set_state(channel, CS_RESET);
+       switch_channel_wait_for_state_timeout(channel, CS_RESET, 5000);
+       switch_channel_set_state(channel, CS_EXECUTE);
+}
+
+/* XXX This is a somewhat simple operation.  Were essentially taking the extension that one channel 
+   was executing and generating a new extension for another channel that starts out where the 
+   original one left off with an optional forward offset.  Since all we are really doing is 
+   copying a few basic pool-allocated structures from one channel to another there really is 
+   not much to worry about here in terms of threading since we use read-write locks. 
+   While the features are nice, they only really are needed in one specific crazy attended 
+   transfer scenario where one channel was in the middle of calling a particular extension
+   when it was rudely cut off by a transfer key press. XXX */
+
 SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switch_channel_t *orig_channel, switch_channel_t *new_channel, uint32_t offset)
 {
        switch_caller_profile_t *caller_profile;
index 218098e510b3167fd9743ca2f7c6bcf838fdc6b9..ae78c300489e07bc8a7a86a43cad1b5059e6b919 100644 (file)
@@ -2204,13 +2204,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                                }
                                        }
                                }
-
+                               
                        end_search:
 
-                               if (peer_channel && (oglobals.idx == IDX_TIMEOUT || to || oglobals.idx == IDX_KEY_CANCEL || oglobals.idx == IDX_CANCEL)) {
-                                       const char *dest = switch_channel_get_variable(peer_channel, "destination_number");
-                                       const char *context = switch_channel_get_variable(peer_channel, "context");
-                                       const char *dialplan = switch_channel_get_variable(peer_channel, "dialplan");
+                               if (peer_channel && switch_channel_down(peer_channel)) {
+                                       switch_core_session_rwunlock(peer_session);
+                                       peer_session = NULL;
+                                       peer_channel = NULL;
+
+                               }
+                               
+                               if (oglobals.idx == IDX_TIMEOUT || to || oglobals.idx == IDX_KEY_CANCEL || oglobals.idx == IDX_CANCEL || 
+                                       (!peer_session && oglobals.idx == IDX_NADA)) {
+                                       const char *dest = NULL;
+                                       const char *context = NULL;
+                                       const char *dialplan = NULL;
                                        switch_core_session_t *holding_session;
                                        
                                        if (caller_channel) {
@@ -2236,14 +2244,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                                
                                                if (caller_channel) {
                                                        if ((mstatus = switch_channel_caller_extension_masquerade(caller_channel, holding_channel, 1)) == SWITCH_STATUS_SUCCESS) {
-                                                               switch_channel_set_state(holding_channel, CS_RESET);
-                                                               switch_channel_wait_for_state_timeout(holding_channel, CS_RESET, 5000);
-                                                               switch_channel_set_state(holding_channel, CS_EXECUTE);
+                                                               switch_channel_restart(holding_channel);
                                                        }
                                                }
 
                                                if (mstatus != SWITCH_STATUS_SUCCESS) {
-                                                       switch_ivr_session_transfer(holding_session, dest, dialplan, context);
+                                                       if (peer_channel) {
+                                                               dest = switch_channel_get_variable(peer_channel, "destination_number");
+                                                               context = switch_channel_get_variable(peer_channel, "context");
+                                                               dialplan = switch_channel_get_variable(peer_channel, "dialplan");
+                                                       } else if (caller_channel) {
+                                                               dest = switch_channel_get_variable(caller_channel, "destination_number");
+                                                       }
+                                                       if (dest) {
+                                                               switch_ivr_session_transfer(holding_session, dest, dialplan, context);
+                                                       }
                                                }
 
                                                switch_core_session_rwunlock(holding_session);
@@ -2251,8 +2266,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
                                                holding_session = NULL;
                                        }
 
-                                       switch_channel_hangup(peer_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
-                                       switch_core_session_rwunlock(peer_session);
+                                       if (peer_channel) {
+                                               switch_channel_hangup(peer_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
+                                               switch_core_session_rwunlock(peer_session);
+                                       }
                                        force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
                                } else {
                                        if (peer_channel && switch_channel_ready(peer_channel)) {