diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 8fa0439b47..5481a20c0a 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -627,6 +627,9 @@ SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_ SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix); SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix); +SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel); +SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension); + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/switch_channel.c b/src/switch_channel.c index 8fd174372c..72bf651e29 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -146,6 +146,7 @@ struct switch_channel { int profile_index; opaque_channel_flag_t opaque_flags; switch_originator_type_t last_profile_type; + switch_caller_extension_t *queued_extension; }; @@ -2688,6 +2689,27 @@ SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_b } +SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel) +{ + switch_caller_extension_t *caller_extension; + + switch_mutex_lock(channel->profile_mutex); + caller_extension = channel->queued_extension; + channel->queued_extension = NULL; + switch_mutex_unlock(channel->profile_mutex); + + return caller_extension; +} + +SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension) +{ + switch_mutex_lock(channel->profile_mutex); + channel->queued_extension = caller_extension; + switch_mutex_unlock(channel->profile_mutex); + + switch_channel_set_flag(channel, CF_TRANSFER); + switch_channel_set_state(channel, CS_ROUTING); +} SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension) { diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 1bb97aa03d..4c191249df 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -93,6 +93,12 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) char *dp[25]; int argc, x, count = 0; + if ((extension = switch_channel_get_queued_extension(session->channel))) { + switch_channel_set_caller_extension(session->channel, extension); + switch_channel_set_state(session->channel, CS_EXECUTE); + goto end; + } + if (!zstr(caller_profile->dialplan)) { if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) { expanded = switch_channel_expand_variables(session->channel, dpstr); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 575dc47701..22731c1968 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -484,6 +484,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se unsigned long CMD_HANGUP = switch_hashfunc_default("hangup", &hlen); unsigned long CMD_NOMEDIA = switch_hashfunc_default("nomedia", &hlen); unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen); + unsigned long CMD_XFEREXT = switch_hashfunc_default("xferext", &hlen); char *lead_frames = switch_event_get_header(event, "lead-frames"); char *event_lock = switch_event_get_header(event, "event-lock"); char *event_lock_pri = switch_event_get_header(event, "event-lock-pri"); @@ -623,6 +624,33 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se switch_ivr_activate_unicast(session, local_ip, (switch_port_t) atoi(local_port), remote_ip, (switch_port_t) atoi(remote_port), transport, flags); + } else if (cmd_hash == CMD_XFEREXT) { + switch_event_header_t *hp; + switch_caller_extension_t *extension = NULL; + + + if ((extension = switch_caller_extension_new(session, "xferext", "xferext")) == 0) { + abort(); + } + + for (hp = event->headers; hp; hp = hp->next) { + char *app; + char *data; + + if (!strcasecmp(hp->name, "application")) { + app = strdup(hp->value); + data = strchr(app, ':'); + + if (data) { + *data++ = '\0'; + } + + switch_caller_extension_add_application(session, extension, app, data); + } + } + + switch_channel_transfer_to_extension(channel, extension); + } else if (cmd_hash == CMD_HANGUP) { char *cause_name = switch_event_get_header(event, "hangup-cause"); switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; @@ -1661,7 +1689,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_ switch_channel_set_caller_profile(channel, new_profile); switch_channel_set_flag(channel, CF_TRANSFER); - + switch_channel_set_state(channel, CS_ROUTING); msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSFER;