diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index a3d54e660f..758e8c9570 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4167,6 +4167,41 @@ SWITCH_STANDARD_API(uuid_send_info_function) return SWITCH_STATUS_SUCCESS; } +#define XFER_ZOMBIE_SYNTAX "" +SWITCH_STANDARD_API(uuid_xfer_zombie) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + char *mycmd = NULL, *argv[2] = { 0 }; + int argc = 0; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (argc < 1) { + stream->write_function(stream, "-USAGE: %s\n", XFER_ZOMBIE_SYNTAX); + } else { + switch_core_session_t *lsession = NULL; + + if ((lsession = switch_core_session_locate(argv[0]))) { + switch_channel_t *channel = switch_core_session_get_channel(lsession); + + switch_channel_set_flag(channel, CF_XFER_ZOMBIE); + status = SWITCH_STATUS_SUCCESS; + switch_core_session_rwunlock(lsession); + } + } + + if (status == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "+OK Success\n"); + } else { + stream->write_function(stream, "-ERR Operation Failed\n"); + } + + switch_safe_free(mycmd); + + return SWITCH_STATUS_SUCCESS; +} #define VIDEO_REFRESH_SYNTAX "" SWITCH_STANDARD_API(uuid_video_refresh_function) @@ -4185,6 +4220,7 @@ SWITCH_STANDARD_API(uuid_video_refresh_function) switch_core_session_t *lsession = NULL; if ((lsession = switch_core_session_locate(argv[0]))) { + switch_channel_set_flag(switch_core_session_get_channel(lsession), CF_XFER_ZOMBIE); switch_core_session_request_video_refresh(lsession); switch_core_media_gen_key_frame(lsession); status = SWITCH_STATUS_SUCCESS; @@ -7333,6 +7369,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_jitterbuffer", "uuid_jitterbuffer", uuid_jitterbuffer_function, JITTERBUFFER_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_zombie_exec", "Set zombie_exec flag on the specified uuid", uuid_zombie_exec_function, ""); + SWITCH_ADD_API(commands_api_interface, "uuid_xfer_zombie", "Allow A leg to hangup and continue originating", uuid_xfer_zombie, XFER_ZOMBIE_SYNTAX); SWITCH_ADD_API(commands_api_interface, "xml_flush_cache", "Clear xml cache", xml_flush_function, " "); SWITCH_ADD_API(commands_api_interface, "xml_locate", "Find some xml", xml_locate_function, "[root |
]"); SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, " "); @@ -7525,6 +7562,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_dual_transfer ::console::list_uuid"); switch_console_set_complete("add uuid_video_refresh ::console::list_uuid"); switch_console_set_complete("add uuid_video_bitrate ::console::list_uuid"); + switch_console_set_complete("add uuid_xfer_zombie ::console::list_uuid"); switch_console_set_complete("add version"); switch_console_set_complete("add uuid_warning ::console::list_uuid"); switch_console_set_complete("add ..."); diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 596721b69a..95ec9a4b2e 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1016,7 +1016,20 @@ static switch_status_t audio_bridge_on_exchange_media(switch_core_session_t *ses switch_channel_hangup(channel, SWITCH_CAUSE_PICKED_OFF); } else { if (!switch_channel_test_flag(channel, CF_ANSWERED)) { - switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL); + int x = 0; + + if (switch_channel_execute_on(channel, "execute_on_orphaned_bleg") == SWITCH_STATUS_SUCCESS) { + x++; + } + + if (switch_channel_api_on(channel, "api_on_orphaned_bleg") == SWITCH_STATUS_SUCCESS) { + x++; + } + + if (!x) { + switch_channel_hangup(channel, SWITCH_CAUSE_ORIGINATOR_CANCEL); + } + } else { switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); } diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 6016809fd2..2379d31867 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2184,6 +2184,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess const char *cdr_var; const char *json_cdr_var; + if (switch_channel_var_true(caller_channel, "originate_xfer_zombie")) { + switch_channel_set_flag(caller_channel, CF_XFER_ZOMBIE); + oglobals.early_ok = 0; + oglobals.ignore_early_media = 1; + } + if ((cdr_var = switch_channel_get_variable(caller_channel, "failed_xml_cdr_prefix"))) { char buf[128] = ""; switch_snprintf(buf, sizeof(buf), "%s_total", cdr_var); @@ -3629,7 +3635,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } if (caller_channel) { - if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) { + + if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE) && !switch_channel_up(caller_channel)) { + if (switch_channel_media_up(peer_channel)) { + oglobals.idx = IDX_XFER; + reason = force_reason = SWITCH_CAUSE_ATTENDED_TRANSFER; + switch_channel_execute_on(peer_channel, "execute_on_orphaned_bleg"); + switch_channel_api_on(peer_channel, "api_on_orphaned_bleg"); + } + } else if (switch_channel_test_flag(peer_channel, CF_ANSWERED)) { switch_channel_pass_callee_id(peer_channel, caller_channel); if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) { status = SWITCH_STATUS_SUCCESS;