*/
SWITCH_DECLARE(void) switch_channel_variable_last(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);
+
/*!
\brief Assign a caller extension to a given channel
\param channel channel to assign extension to
switch_channel_set_variable(channel_b, SWITCH_HOLDING_UUID_VARIABLE, br_a);
switch_channel_set_flag(channel_b, CF_XFER_ZOMBIE);
switch_channel_set_flag(channel_b, CF_TRANSFER);
-
- //switch_channel_set_variable(channel_b, "park_timeout", "2");
- //switch_channel_set_state(channel_b, CS_PARK);
+
if ((a_session = switch_core_session_locate(br_a))) {
const char *moh = profile->hold_music;
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 (0 && b_tech_pvt) {
+
+ if (1 && 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\""),
switch_mutex_unlock(channel->state_mutex);
}
+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;
+ switch_caller_extension_t *extension = NULL, *orig_extension = NULL;
+ switch_caller_application_t *ap;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_event_header_t *hi = NULL;
+ const char *no_copy = switch_channel_get_variable(orig_channel, "attended_transfer_no_copy");
+ char *dup;
+ int i, argc = 0;
+ char *argv[128];
+
+ if (no_copy) {
+ dup = switch_core_session_strdup(new_channel->session, no_copy);
+ argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
+ }
+
+
+ switch_mutex_lock(orig_channel->profile_mutex);
+ switch_mutex_lock(new_channel->profile_mutex);
+
+
+ caller_profile = switch_caller_profile_clone(new_channel->session, new_channel->caller_profile);
+ switch_assert(caller_profile);
+ extension = switch_caller_extension_new(new_channel->session, caller_profile->destination_number, caller_profile->destination_number);
+ orig_extension = switch_channel_get_caller_extension(orig_channel);
+
+
+ if (extension && orig_extension) {
+ for(ap = orig_extension->current_application; ap && offset > 0; offset--) {
+ ap = ap->next;
+ }
+
+ for (; ap; ap = ap->next) {
+ switch_caller_extension_add_application(new_channel->session, extension, ap->application_name, ap->application_data);
+ }
+
+ caller_profile->destination_number = switch_core_strdup(caller_profile->pool, orig_channel->caller_profile->destination_number);
+ switch_channel_set_caller_profile(new_channel, caller_profile);
+ switch_channel_set_caller_extension(new_channel, extension);
+
+ for (hi = orig_channel->variables->headers; hi; hi = hi->next) {
+ int ok = 1;
+ for (i = 0; i < argc; i++) {
+ if (!strcasecmp(argv[i], hi->name)) {
+ ok = 0;
+ break;
+ }
+ }
+
+ if (!ok) continue;
+
+ switch_channel_set_variable(new_channel, hi->name, hi->value);
+ }
+
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+
+ switch_mutex_unlock(new_channel->profile_mutex);
+ switch_mutex_unlock(orig_channel->profile_mutex);
+
+
+ return status;
+}
+
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
{
switch_assert(channel != NULL);
} else if (state < CS_HANGUP && (var = switch_channel_get_variable(channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE))) {
transfer_after_bridge(session, var);
} else {
- if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_REDIRECT) && bd && !bd->clean_exit
+ if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_REDIRECT) &&
+ !switch_channel_test_flag(channel, CF_XFER_ZOMBIE) && bd && !bd->clean_exit
&& state != CS_PARK && state != CS_ROUTING && !switch_channel_test_flag(channel, CF_INNER_BRIDGE)) {
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
state = switch_channel_get_state(caller_channel);
- if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !switch_channel_test_flag(caller_channel, CF_REDIRECT)
- && !a_leg->clean_exit && !inner_bridge) {
+ if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !switch_channel_test_flag(caller_channel, CF_REDIRECT) &&
+ !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) && !a_leg->clean_exit && !inner_bridge) {
if ((state != CS_EXECUTE && state != CS_SOFT_EXECUTE && state != CS_PARK && state != CS_ROUTING) ||
(switch_channel_test_flag(peer_channel, CF_ANSWERED) && state < CS_HANGUP)) {
if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE))) {
if (switch_channel_media_ready(caller_channel)) {
tstatus = switch_core_session_read_frame(oglobals.session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(tstatus)) {
+ if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
+ continue;
+ }
break;
}
} else {
}
if (switch_core_session_write_frame(oglobals.session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
+ if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
+ continue;
+ }
break;
}
}
}
}
- if (caller_channel && !switch_channel_ready(caller_channel)) {
+ if (caller_channel && !switch_channel_ready(caller_channel) && !switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) {
oglobals.idx = IDX_CANCEL;
}
const char *context = switch_channel_get_variable(peer_channel, "context");
const char *dialplan = switch_channel_get_variable(peer_channel, "dialplan");
switch_core_session_t *holding_session;
-
+
if (caller_channel) {
if (switch_strlen_zero(context)) {
context = switch_channel_get_variable(caller_channel, "context");
}
if ((holding_session = switch_core_session_locate(holding))) {
- switch_ivr_session_transfer(holding_session, dest, dialplan, context);
+ switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
+ switch_status_t mstatus = SWITCH_STATUS_FALSE;
+
+ 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);
+ }
+ }
+
+ if (mstatus != SWITCH_STATUS_SUCCESS) {
+ switch_ivr_session_transfer(holding_session, dest, dialplan, context);
+ }
+
switch_core_session_rwunlock(holding_session);
holding = NULL;
holding_session = NULL;
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)) {
force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER;
if (i != oglobals.idx) {
holding = NULL;
- if (force_reason != SWITCH_CAUSE_NONE) {
- reason = force_reason;
- } else if (oglobals.idx == IDX_TIMEOUT || to) {
+ if (oglobals.idx == IDX_TIMEOUT || to) {
reason = SWITCH_CAUSE_NO_ANSWER;
} else {
if (oglobals.idx == IDX_CANCEL) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG,
"Originate Cancelled by originator termination Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
+ } else if (oglobals.idx == IDX_TIMEOUT) {
+ *cause = SWITCH_CAUSE_NO_ANSWER;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals.session), SWITCH_LOG_DEBUG,
"Originate Resulted in Error Cause: %d [%s]\n", *cause, switch_channel_cause2str(*cause));
switch_channel_clear_flag(caller_channel, CF_XFER_ZOMBIE);
}
+ if (force_reason != SWITCH_CAUSE_NONE) {
+ *cause = force_reason;
+ }
+
return status;
}