diff --git a/src/include/switch_caller.h b/src/include/switch_caller.h index cfa05cf6c3..d06cf2f7b7 100644 --- a/src/include/switch_caller.h +++ b/src/include/switch_caller.h @@ -142,6 +142,9 @@ struct switch_caller_extension { SWITCH_DECLARE(switch_caller_extension_t *) switch_caller_extension_new(_In_ switch_core_session_t *session, _In_z_ const char *extension_name, _In_z_ const char *extension_number); +SWITCH_DECLARE(switch_status_t) switch_caller_extension_clone(switch_caller_extension_t **new_ext, switch_caller_extension_t *orig, + switch_memory_pool_t *pool); + /*! \brief Add an application (instruction) to the given extension \param session session associated with the extension (bound by scope) diff --git a/src/switch_caller.c b/src/switch_caller.c index e7c64f5189..1cb6ec517e 100644 --- a/src/switch_caller.c +++ b/src/switch_caller.c @@ -282,6 +282,56 @@ SWITCH_DECLARE(void) switch_caller_profile_event_set_data(switch_caller_profile_ switch_event_add_header(event, SWITCH_STACK_BOTTOM, header_name, switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER) ? "yes" : "no"); } +SWITCH_DECLARE(switch_status_t) switch_caller_extension_clone(switch_caller_extension_t **new_ext, switch_caller_extension_t *orig, + switch_memory_pool_t *pool) +{ + switch_caller_extension_t *caller_extension = NULL; + switch_caller_application_t *caller_application = NULL, *ap = NULL; + + *new_ext = NULL; + + if ((caller_extension = switch_core_alloc(pool, sizeof(switch_caller_extension_t))) != 0) { + int match = 0; + + caller_extension->extension_name = switch_core_strdup(pool, orig->extension_name); + caller_extension->extension_number = switch_core_strdup(pool, orig->extension_number); + + for(ap = orig->applications; ap; ap = ap->next) { + + if (!match) { + if (ap == orig->current_application) { + match++; + } else { + continue; + } + } + caller_application = switch_core_alloc(pool, sizeof(switch_caller_application_t)); + + caller_application->application_name = switch_core_strdup(pool, ap->application_name); + caller_application->application_data = switch_core_strdup(pool, ap->application_data); + + if (!caller_extension->applications) { + caller_extension->applications = caller_application; + } else if (caller_extension->last_application) { + caller_extension->last_application->next = caller_application; + } + + caller_extension->last_application = caller_application; + + if (ap == orig->current_application) { + caller_extension->current_application = caller_application; + } + } + + *new_ext = caller_extension; + + return SWITCH_STATUS_SUCCESS; + } + + + return SWITCH_STATUS_MEMERR; +} + SWITCH_DECLARE(switch_caller_extension_t *) switch_caller_extension_new(switch_core_session_t *session, const char *extension_name, const char *extension_number) { diff --git a/src/switch_channel.c b/src/switch_channel.c index 872e568bf9..1f6998f58a 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1147,6 +1147,9 @@ SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel caller_profile->times->progress_media = channel->caller_profile->times->progress_media; caller_profile->times->created = channel->caller_profile->times->created; caller_profile->times->hungup = channel->caller_profile->times->hungup; + if (channel->caller_profile->caller_extension) { + switch_caller_extension_clone(&caller_profile->caller_extension, channel->caller_profile->caller_extension, caller_profile->pool); + } } else { caller_profile->times->created = switch_timestamp_now(); } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 2dab092034..a75249bf31 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -814,13 +814,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses state = switch_channel_get_state(caller_channel); if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !inner_bridge) { - if ((state != CS_EXECUTE && state != CS_PARK && state != CS_ROUTING) || + 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 && switch_true(switch_channel_get_variable(caller_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE)))) { switch_channel_hangup(caller_channel, switch_channel_get_cause(peer_channel)); } } + state = switch_channel_get_state(caller_channel); + + if (state == CS_SOFT_EXECUTE || state == CS_PARK) { + switch_channel_set_state(caller_channel, CS_EXECUTE); + } + return status; }