diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index f7ace52676..219663b0e0 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -658,7 +658,7 @@ SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_cha SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel); SWITCH_DECLARE(switch_status_t) switch_channel_state_thread_trylock(switch_channel_t *channel); - +SWITCH_DECLARE(void) switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause); SWITCH_END_EXTERN_C #endif diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 5818bd0752..52c94633bf 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2933,11 +2933,6 @@ SWITCH_STANDARD_APP(audio_bridge_function) { switch_channel_t *caller_channel = switch_core_session_get_channel(session); switch_core_session_t *peer_session = NULL; - - const char *transfer_on_fail = NULL; - char *tof_data = NULL; - char *tof_array[4] = { 0 }; - //int tof_arrayc = 0; const char *v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL; switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; int campon_retries = 100, campon_timeout = 10, campon_sleep = 10, tmp, camping = 0, fail = 0, thread_started = 0; @@ -2953,11 +2948,6 @@ SWITCH_STANDARD_APP(audio_bridge_function) return; } - transfer_on_fail = switch_channel_get_variable(caller_channel, "transfer_on_fail"); - tof_data = switch_core_session_strdup(session, transfer_on_fail); - switch_split(tof_data, ' ', tof_array); - transfer_on_fail = tof_array[0]; - if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) { const char *cid_name = NULL; const char *cid_number = NULL; @@ -3105,126 +3095,7 @@ SWITCH_STANDARD_APP(audio_bridge_function) if (fail) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause)); - /* - if the variable continue_on_fail is set it can be: - 'true' to continue on all failures. - 'false' to not continue. - A list of codes either names or numbers eg "user_busy,normal_temporary_failure,603" - failure_causes acts as the opposite version - EXCEPTION... ATTENDED_TRANSFER never is a reason to continue....... - */ - if (cause != SWITCH_CAUSE_ATTENDED_TRANSFER) { - const char *continue_on_fail = NULL, *failure_causes = NULL; - - continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail"); - failure_causes = switch_channel_get_variable(caller_channel, "failure_causes"); - - if (continue_on_fail || failure_causes) { - const char *cause_str; - char cause_num[35] = ""; - - cause_str = switch_channel_cause2str(cause); - switch_snprintf(cause_num, sizeof(cause_num), "%u", cause); - - if (failure_causes) { - char *lbuf = switch_core_session_strdup(session, failure_causes); - char *argv[256] = { 0 }; - int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); - int i, x = 0; - - for (i = 0; i < argc; i++) { - if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { - x++; - break; - } - } - if (!x) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str); - return; - } - } - - if (continue_on_fail) { - if (switch_true(continue_on_fail)) { - return; - } else { - char *lbuf = switch_core_session_strdup(session, continue_on_fail); - char *argv[256] = { 0 }; - int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); - int i; - - for (i = 0; i < argc; i++) { - if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "Continue on fail [%s]: Cause: %s\n", continue_on_fail, cause_str); - return; - } - } - } - } - } else { - /* no answer is *always* a reason to continue */ - if (cause == SWITCH_CAUSE_NO_ANSWER || cause == SWITCH_CAUSE_NO_USER_RESPONSE || cause == SWITCH_CAUSE_ORIGINATOR_CANCEL) { - return; - } - } - - if (transfer_on_fail || failure_causes) { - const char *cause_str; - char cause_num[35] = ""; - - cause_str = switch_channel_cause2str(cause); - switch_snprintf(cause_num, sizeof(cause_num), "%u", cause); - - if ((tof_array[1] == NULL ) || (!strcasecmp(tof_array[1], "auto_cause"))){ - tof_array[1] = (char *) cause_str; - } - - if (failure_causes) { - char *lbuf = switch_core_session_strdup(session, failure_causes); - char *argv[256] = { 0 }; - int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); - int i, x = 0; - - for (i = 0; i < argc; i++) { - if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { - x++; - break; - } - } - if (!x) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str); - - switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]); - } - } - - if (transfer_on_fail) { - if (switch_true(transfer_on_fail)) { - return; - } else { - char *lbuf = switch_core_session_strdup(session, transfer_on_fail); - char *argv[256] = { 0 }; - int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); - int i; - - for (i = 0; i < argc; i++) { - if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, - "Transfer on fail [%s]: Cause: %s\n", transfer_on_fail, cause_str); - switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]); - } - } - } - } - } - } - if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !switch_channel_test_flag(caller_channel, CF_CONFIRM_BLIND_TRANSFER) && - switch_channel_get_state(caller_channel) != CS_ROUTING) { - switch_channel_hangup(caller_channel, cause); - } + switch_channel_handle_cause(caller_channel, cause); return; } else { diff --git a/src/switch_channel.c b/src/switch_channel.c index 9f83d84177..e477bffa57 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -4386,6 +4386,148 @@ SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *c return uuid; } +SWITCH_DECLARE(void) switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause) +{ + switch_core_session_t *session = channel->session; + const char *transfer_on_fail = NULL; + char *tof_data = NULL; + char *tof_array[4] = { 0 }; + //int tof_arrayc = 0; + + if (!switch_channel_up_nosig(channel)) { + return; + } + + transfer_on_fail = switch_channel_get_variable(channel, "transfer_on_fail"); + tof_data = switch_core_session_strdup(session, transfer_on_fail); + switch_split(tof_data, ' ', tof_array); + transfer_on_fail = tof_array[0]; + + /* + if the variable continue_on_fail is set it can be: + 'true' to continue on all failures. + 'false' to not continue. + A list of codes either names or numbers eg "user_busy,normal_temporary_failure,603" + failure_causes acts as the opposite version + EXCEPTION... ATTENDED_TRANSFER never is a reason to continue....... + */ + if (cause != SWITCH_CAUSE_ATTENDED_TRANSFER) { + const char *continue_on_fail = NULL, *failure_causes = NULL; + + continue_on_fail = switch_channel_get_variable(channel, "continue_on_fail"); + failure_causes = switch_channel_get_variable(channel, "failure_causes"); + + if (continue_on_fail || failure_causes) { + const char *cause_str; + char cause_num[35] = ""; + + cause_str = switch_channel_cause2str(cause); + switch_snprintf(cause_num, sizeof(cause_num), "%u", cause); + + if (failure_causes) { + char *lbuf = switch_core_session_strdup(session, failure_causes); + char *argv[256] = { 0 }; + int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + int i, x = 0; + + for (i = 0; i < argc; i++) { + if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { + x++; + break; + } + } + if (!x) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str); + return; + } + } + + if (continue_on_fail) { + if (switch_true(continue_on_fail)) { + return; + } else { + char *lbuf = switch_core_session_strdup(session, continue_on_fail); + char *argv[256] = { 0 }; + int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + int i; + + for (i = 0; i < argc; i++) { + if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "Continue on fail [%s]: Cause: %s\n", continue_on_fail, cause_str); + return; + } + } + } + } + } else { + /* no answer is *always* a reason to continue */ + if (cause == SWITCH_CAUSE_NO_ANSWER || cause == SWITCH_CAUSE_NO_USER_RESPONSE || cause == SWITCH_CAUSE_ORIGINATOR_CANCEL) { + return; + } + } + + if (transfer_on_fail || failure_causes) { + const char *cause_str; + char cause_num[35] = ""; + + cause_str = switch_channel_cause2str(cause); + switch_snprintf(cause_num, sizeof(cause_num), "%u", cause); + + if ((tof_array[1] == NULL ) || (!strcasecmp(tof_array[1], "auto_cause"))){ + tof_array[1] = (char *) cause_str; + } + + if (failure_causes) { + char *lbuf = switch_core_session_strdup(session, failure_causes); + char *argv[256] = { 0 }; + int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + int i, x = 0; + + for (i = 0; i < argc; i++) { + if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { + x++; + break; + } + } + if (!x) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str); + + switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]); + } + } + + if (transfer_on_fail) { + if (switch_true(transfer_on_fail)) { + return; + } else { + char *lbuf = switch_core_session_strdup(session, transfer_on_fail); + char *argv[256] = { 0 }; + int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + int i; + + for (i = 0; i < argc; i++) { + if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "Transfer on fail [%s]: Cause: %s\n", transfer_on_fail, cause_str); + switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]); + } + } + } + } + } + } + + + if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_CONFIRM_BLIND_TRANSFER) && + switch_channel_get_state(channel) != CS_ROUTING) { + switch_channel_hangup(channel, cause); + } +} + + /* For Emacs: * Local Variables: * mode:c diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 13896f7b13..d1b5874795 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1644,6 +1644,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess } for (i = 0; i < x_argc; i++) { + + if (channel) { + switch_channel_handle_cause(channel, handles[i].cause); + } + if (hp == &handles[i]) { continue; } @@ -1861,6 +1866,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess const char *ringback_data = NULL; switch_event_t *var_event = NULL; int8_t fail_on_single_reject = 0; + int8_t hangup_on_single_reject = 0; char *fail_on_single_reject_var = NULL; char *loop_data = NULL; uint32_t progress_timelimit_sec = 0; @@ -2119,6 +2125,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess ok = 1; } else if (!strcasecmp((char *) hi->name, "fail_on_single_reject")) { ok = 1; + } else if (!strcasecmp((char *) hi->name, "hangup_on_single_reject")) { + ok = 1; } else if (!strcasecmp((char *) hi->name, "ignore_early_media")) { ok = 1; } else if (!strcasecmp((char *) hi->name, "bridge_early_media")) { @@ -2216,7 +2224,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess If the value is set to 'true' any fail cause will end the attempt otherwise it can contain a comma (,) separated list of cause names which should be considered fatal */ - if ((var = switch_event_get_header(var_event, "fail_on_single_reject"))) { + if ((var = switch_event_get_header(var_event, "hangup_on_single_reject"))) { + hangup_on_single_reject = 1; + } + + if (hangup_on_single_reject || (var = switch_event_get_header(var_event, "fail_on_single_reject"))) { fail_on_single_reject_var = strdup(var); if (switch_true(var)) { fail_on_single_reject = 1; @@ -3807,6 +3819,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_safe_free(write_frame.data); switch_safe_free(fail_on_single_reject_var); + if (force_reason != SWITCH_CAUSE_NONE) { + *cause = force_reason; + } + if (caller_channel) { switch_channel_execute_on(caller_channel, SWITCH_CHANNEL_EXECUTE_ON_POST_ORIGINATE_VARIABLE); @@ -3814,11 +3830,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_clear_flag(caller_channel, CF_ORIGINATOR); switch_channel_clear_flag(caller_channel, CF_XFER_ZOMBIE); + + if (hangup_on_single_reject) { + switch_channel_hangup(caller_channel, *cause); + } } - if (force_reason != SWITCH_CAUSE_NONE) { - *cause = force_reason; - } switch_core_destroy_memory_pool(&oglobals.pool);