diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 8d4a0cd122..f6e611b91f 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -718,6 +718,9 @@ SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *sessio SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session); +SWITCH_DECLARE(switch_digit_action_target_t) switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine); +SWITCH_DECLARE(void) switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target); + SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data); /*! diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 783b48e3b1..7eb27d2c45 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -221,6 +221,13 @@ typedef enum { SWITCH_DTMF_APP } switch_dtmf_source_t; +typedef enum { + DIGIT_TARGET_SELF, + DIGIT_TARGET_PEER +} switch_digit_action_target_t; + + + typedef enum { DTMF_FLAG_SKIP_PROCESS = (1 << 0) } dtmf_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 271421a9d3..02c64d8093 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -108,23 +108,33 @@ struct action_binding { static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t *match) { switch_core_session_t *session = (switch_core_session_t *) match->user_data; - switch_channel_t *channel = switch_core_session_get_channel(session); + switch_channel_t *channel; char str[DMACHINE_MAX_DIGIT_LEN + 2]; switch_event_t *event; switch_status_t status; + switch_core_session_t *use_session = session; + + if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER) { + if (switch_core_session_get_partner(session, &use_session) != SWITCH_STATUS_SUCCESS) { + use_session = session; + } + } + + channel = switch_core_session_get_channel(use_session); + switch_channel_set_variable(channel, "last_non_matching_digits", match->match_digits); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Digit NOT match binding [%s]\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_DEBUG, "%s Digit NOT match binding [%s]\n", switch_channel_get_name(channel), match->match_digits); if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "digits", match->match_digits); - if ((status = switch_core_session_queue_event(session, &event)) != SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_session_queue_event(use_session, &event)) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", - switch_core_session_get_name(session)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue failure.\n", + switch_core_session_get_name(use_session)); } } @@ -133,6 +143,11 @@ static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t switch_channel_queue_dtmf_string(channel, str); + if (use_session != session) { + switch_core_session_rwunlock(use_session); + } + + return SWITCH_STATUS_SUCCESS; } @@ -143,9 +158,19 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) switch_status_t status; int exec = 0; char *string = act->string; - switch_channel_t *channel = switch_core_session_get_channel(act->session); + switch_channel_t *channel; + switch_core_session_t *use_session = act->session; + + if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER) { + if (switch_core_session_get_partner(act->session, &use_session) != SWITCH_STATUS_SUCCESS) { + use_session = act->session; + } + } + + channel = switch_core_session_get_channel(use_session); switch_channel_set_variable(channel, "last_matching_digits", match->match_digits); + if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n", @@ -163,18 +188,24 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 2 ? "non-blocking" : "blocking"); } - if ((status = switch_core_session_queue_event(act->session, &event)) != SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_session_queue_event(use_session, &event)) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", - switch_core_session_get_name(act->session)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", + switch_core_session_get_name(use_session)); } } if (exec) { - char *cmd = switch_core_session_sprintf(act->session, "%s::%s", string, act->value); - switch_ivr_broadcast_in_thread(act->session, cmd, SMF_ECHO_ALEG|SMF_HOLD_BLEG); + char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value); + switch_ivr_broadcast_in_thread(use_session, cmd, SMF_ECHO_ALEG|SMF_HOLD_BLEG); } + + if (use_session != act->session) { + switch_core_session_rwunlock(use_session); + } + + return SWITCH_STATUS_SUCCESS; } @@ -212,6 +243,30 @@ SWITCH_STANDARD_APP(digit_action_set_realm_function) } + +#define DIGIT_ACTION_SET_TARGET_USAGE "" +SWITCH_STANDARD_APP(digit_action_set_target_function) +{ + switch_ivr_dmachine_t *dmachine; + char *target_str = (char *) data; + + if (zstr(data)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_TARGET_USAGE); + return; + } + + if ((dmachine = switch_core_session_get_dmachine(session))) { + switch_digit_action_target_t target = DIGIT_TARGET_SELF; + + if (!strcasecmp(target_str, "peer")) { + target = DIGIT_TARGET_PEER; + } + + switch_ivr_dmachine_set_target(dmachine, target); + } + +} + #define BIND_DIGIT_ACTION_USAGE ",,," SWITCH_STANDARD_APP(bind_digit_action_function) { @@ -219,7 +274,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function) switch_ivr_dmachine_t *dmachine; char *mydata; int argc = 0; - char *argv[4] = { 0 }; + char *argv[5] = { 0 }; struct action_binding *act; if (zstr(data)) { @@ -266,7 +321,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function) act->string = argv[2]; act->value = argv[3]; act->session = session; - + switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act); } @@ -3788,6 +3843,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "digit_action_set_realm", "change binding realm", "", digit_action_set_realm_function, DIGIT_ACTION_SET_REALM_USAGE, SAF_SUPPORT_NOMEDIA); + + SWITCH_ADD_APP(app_interface, "digit_action_set_target", "change binding target", "", + digit_action_set_target_function, DIGIT_ACTION_SET_TARGET_USAGE, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "privacy", "Set privacy on calls", "Set caller privacy on calls.", privacy_function, "off|on|name|full|number", diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 100d8bf9f6..3a30cdaf74 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -1293,9 +1293,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio } else if (!new_dtmf.duration) { new_dtmf.duration = switch_core_default_dtmf_duration(0); } - + if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { - if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + if (session->dmachine && switch_ivr_dmachine_get_target(session->dmachine) == DIGIT_TARGET_SELF && + !switch_channel_test_flag(session->channel, CF_BROADCAST)) { char str[2] = { dtmf->digit, '\0' }; switch_ivr_dmachine_feed(session->dmachine, str, NULL); fed = 1; @@ -1337,13 +1338,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio new_dtmf.duration = switch_core_default_dtmf_duration(0); } - + for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) { if ((status = ptr->send_dtmf(session, dtmf, SWITCH_DTMF_SEND)) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_SUCCESS; } } + if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { + if (session->dmachine && switch_ivr_dmachine_get_target(session->dmachine) == DIGIT_TARGET_PEER && + !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + char str[2] = { new_dtmf.digit, '\0' }; + switch_ivr_dmachine_feed(session->dmachine, str, NULL); + return SWITCH_STATUS_SUCCESS; + } + } + + if (session->endpoint_interface->io_routines->send_dtmf) { int send = 0; status = SWITCH_STATUS_SUCCESS; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 7eeb1404e5..fe8d9ddb1b 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -59,6 +59,7 @@ struct switch_ivr_dmachine { uint32_t input_timeout_ms; switch_hash_t *binding_hash; switch_ivr_dmachine_match_t match; + switch_digit_action_target_t target; char digits[DMACHINE_MAX_DIGIT_LEN]; char last_matching_digits[DMACHINE_MAX_DIGIT_LEN]; char last_failed_digits[DMACHINE_MAX_DIGIT_LEN]; @@ -74,6 +75,17 @@ struct switch_ivr_dmachine { }; +SWITCH_DECLARE(switch_digit_action_target_t) switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine) +{ + return dmachine->target; +} + +SWITCH_DECLARE(void) switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target) +{ + dmachine->target = target; +} + + SWITCH_DECLARE(void) switch_ivr_dmachine_set_match_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t match_callback) {