fix recursion error

This commit is contained in:
Anthony Minessale 2012-12-10 10:56:07 -06:00
parent 779564de50
commit 8be9d429fb
6 changed files with 112 additions and 14 deletions

View File

@ -358,7 +358,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_stop_inband_dtmf_generate_session(swi
\brief - NEEDDESC -
\param session the session to act on
*/
SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session, switch_input_args_t *args);
SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *session, switch_input_args_t *args);
/*!
\brief Stop looking for TONES

View File

@ -1972,6 +1972,19 @@ struct switch_ivr_dmachine_match {
typedef struct switch_ivr_dmachine_match switch_ivr_dmachine_match_t;
typedef switch_status_t (*switch_ivr_dmachine_callback_t) (switch_ivr_dmachine_match_t *match);
#define MAX_ARG_RECURSION 25
#define arg_recursion_check_start(_args) if (_args) { \
if (_args->loops >= MAX_ARG_RECURSION) { \
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, \
"RECURSION ERROR! It's not the best idea to call things that collect input recursively from an input callback.\n"); \
return SWITCH_STATUS_GENERR; \
} else {_args->loops++;} \
}
#define arg_recursion_check_stop(_args) if (_args) _args->loops--
typedef struct {
switch_input_callback_function_t input_callback;
void *buf;
@ -1979,6 +1992,7 @@ typedef struct {
switch_read_frame_callback_function_t read_frame_callback;
void *user_data;
switch_ivr_dmachine_t *dmachine;
int loops;
} switch_input_args_t;

View File

@ -141,6 +141,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
int sval = 0;
const char *var;
arg_recursion_check_start(args);
/*
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
!switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) {
@ -156,12 +158,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
for (elapsed=0; switch_channel_up(channel) && elapsed<(ms/20); elapsed++) {
if (switch_channel_test_flag(channel, CF_BREAK)) {
switch_channel_clear_flag(channel, CF_BREAK);
return SWITCH_STATUS_BREAK;
switch_goto_status(SWITCH_STATUS_BREAK, end);
}
switch_yield(20 * 1000);
}
return SWITCH_STATUS_SUCCESS;
switch_goto_status(SWITCH_STATUS_SUCCESS, end);
}
var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE);
@ -183,7 +185,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
@ -213,7 +215,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
}
if (!ms) {
return SWITCH_STATUS_SUCCESS;
switch_goto_status(SWITCH_STATUS_SUCCESS, end);
}
for (;;) {
@ -303,6 +305,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
}
}
end:
arg_recursion_check_stop(args);
if (write_frame.codec) {
switch_core_codec_destroy(&codec);
}
@ -874,6 +881,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
unsigned char *abuf = NULL;
switch_codec_implementation_t imp = { 0 };
if (switch_channel_test_flag(channel, CF_RECOVERED) && switch_channel_test_flag(channel, CF_CONTROLLED)) {
switch_channel_clear_flag(channel, CF_CONTROLLED);
}
@ -887,6 +896,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
if ((to = switch_channel_get_variable(channel, "park_timeout"))) {
char *cause_str;
@ -931,7 +942,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
@ -982,7 +993,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
if (switch_channel_test_flag(channel, CF_UNICAST)) {
if (!switch_channel_media_ready(channel)) {
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
}
@ -1100,6 +1111,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
}
end:
arg_recursion_check_stop(args);
if (write_frame.codec) {
switch_core_codec_destroy(&codec);
}
@ -1133,12 +1148,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
return SWITCH_STATUS_GENERR;
}
arg_recursion_check_start(args);
if (abs_timeout) {
abs_started = switch_micro_time_now();
}
if (digit_timeout) {
digit_started = switch_micro_time_now();
}
while (switch_channel_ready(channel)) {
switch_frame_t *read_frame = NULL;
switch_event_t *event;
@ -1224,6 +1242,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
}
}
arg_recursion_check_stop(args);
return status;
}
@ -2890,6 +2910,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
channel = switch_core_session_get_channel(session);
switch_assert(channel);
arg_recursion_check_start(args);
if (zstr(module_name)) {
module_name = "en";
}
@ -2971,6 +2994,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say(switch_core_session_t *session,
done:
arg_recursion_check_stop(args);
if (hint_data) {
switch_event_destroy(&hint_data);
}

View File

@ -616,7 +616,7 @@ static void *SWITCH_THREAD_FUNC echo_video_thread(switch_thread_t *thread, void
}
#endif
SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session, switch_input_args_t *args)
SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *session, switch_input_args_t *args)
{
switch_status_t status;
switch_frame_t *read_frame;
@ -630,9 +630,11 @@ SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session, swi
#endif
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return;
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
restart:
#ifdef SWITCH_VIDEO_IN_THREADS
@ -725,6 +727,7 @@ SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session, swi
}
#endif
return SWITCH_STATUS_SUCCESS;
}
typedef struct {
@ -3413,6 +3416,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_and_detect_speech(switch_core_se
play_and_detect_speech_state_t state = { 0, "" };
switch_channel_t *channel = switch_core_session_get_channel(session);
arg_recursion_check_start(args);
if (result == NULL) {
goto done;
}
@ -3474,6 +3479,8 @@ done:
status = SWITCH_STATUS_FALSE;
}
arg_recursion_check_stop(args);
return status;;
}

View File

@ -54,11 +54,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
switch_bool_t sound_prefix_enforced = switch_true(switch_channel_get_variable(channel, "sound_prefix_enforced"));
switch_bool_t local_sound_prefix_enforced = SWITCH_FALSE;
if (!macro_name) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No phrase macro specified.\n");
return status;
}
arg_recursion_check_start(args);
if (!lang) {
chan_lang = switch_channel_get_variable(channel, "default_language");
if (!chan_lang) {
@ -331,6 +334,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_phrase_macro_event(switch_core_sessio
done:
arg_recursion_check_stop(args);
if (hint_data) {
switch_event_destroy(&hint_data);
}
@ -379,6 +384,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
int restart_limit_on_dtmf = 0;
const char *prefix, *var;
prefix = switch_channel_get_variable(channel, "sound_prefix");
if (!prefix) {
@ -404,6 +410,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
if (!fh) {
fh = &lfh;
}
@ -467,6 +475,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
write_frame.samples = write_frame.datalen / 2;
write_frame.codec = &write_codec;
} else {
arg_recursion_check_stop(args);
return SWITCH_STATUS_FALSE;
}
}
@ -519,6 +528,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
if (switch_core_file_open(fh, file, fh->channels, read_impl.actual_samples_per_second, file_flags, NULL) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
arg_recursion_check_stop(args);
return SWITCH_STATUS_GENERR;
}
@ -590,6 +600,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
fh->channels, read_impl.microseconds_per_packet / 1000);
switch_core_file_close(fh);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
arg_recursion_check_stop(args);
return SWITCH_STATUS_GENERR;
}
}
@ -796,6 +807,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
}
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
arg_recursion_check_stop(args);
return status;
}
@ -841,6 +854,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
memset(&ts, 0, sizeof(ts));
write_frame.codec = &write_codec;
write_frame.data = data;
@ -946,6 +962,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi
switch_buffer_destroy(&audio_buffer);
teletone_destroy_session(&ts);
arg_recursion_check_stop(args);
return SWITCH_STATUS_SUCCESS;
}
@ -1084,6 +1102,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
if (!strcasecmp(read_impl.iananame, "l16")) {
l16++;
}
@ -1136,6 +1156,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
*arg++ = '\0';
}
if ((status = switch_ivr_phrase_macro(session, dup, arg, lang, args)) != SWITCH_STATUS_SUCCESS) {
arg_recursion_check_stop(args);
return status;
}
continue;
@ -1160,6 +1181,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
if (!zstr(engine) && !zstr(voice) && !zstr(text)) {
if ((status = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
arg_recursion_check_stop(args);
return status;
}
} else {
@ -1168,6 +1190,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
voice = (char *) switch_channel_get_variable(channel, "tts_voice");
if (engine && text) {
if ((status = switch_ivr_speak_text(session, engine, voice, text, args)) != SWITCH_STATUS_SUCCESS) {
arg_recursion_check_stop(args);
return status;
}
} else {
@ -1727,6 +1750,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
switch_safe_free(abuf);
switch_core_session_reset(session, SWITCH_FALSE, SWITCH_FALSE);
arg_recursion_check_stop(args);
return status;
}
@ -2119,6 +2145,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
write_frame.data = abuf;
write_frame.buflen = sizeof(abuf);
@ -2149,6 +2177,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
switch_size_t mylen = strlen(text) + extra + 1;
tmp = malloc(mylen);
if (!tmp) {
arg_recursion_check_stop(args);
return SWITCH_STATUS_MEMERR;
}
memset(tmp, 0, mylen);
@ -2369,6 +2398,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n");
flags = 0;
switch_core_speech_flush_tts(sh);
arg_recursion_check_stop(args);
return status;
}
@ -2426,6 +2457,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
return SWITCH_STATUS_FALSE;
}
arg_recursion_check_start(args);
sh = &lsh;
codec = &lcodec;
timer = &ltimer;
@ -2466,6 +2499,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid TTS module!\n");
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
switch_ivr_clear_speech_cache(session);
arg_recursion_check_stop(args);
return status;
}
} else if (cache_obj && strcasecmp(cache_obj->voice_name, voice_name)) {
@ -2476,6 +2510,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
flags = 0;
switch_core_speech_close(sh, &flags);
arg_recursion_check_stop(args);
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
@ -2495,6 +2530,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
switch_core_speech_close(sh, &flags);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
switch_ivr_clear_speech_cache(session);
arg_recursion_check_stop(args);
return SWITCH_STATUS_GENERR;
}
}
@ -2510,6 +2546,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
switch_core_speech_close(sh, &flags);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
switch_ivr_clear_speech_cache(session);
arg_recursion_check_stop(args);
return SWITCH_STATUS_GENERR;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", sh->samples * 2,
@ -2539,6 +2576,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
}
switch_core_session_reset(session, SWITCH_FALSE, SWITCH_TRUE);
arg_recursion_check_stop(args);
return status;
}

View File

@ -133,6 +133,8 @@ SWITCH_DECLARE(switch_say_type_t) switch_ivr_get_say_type_by_name(const char *na
SWITCH_DECLARE(switch_status_t) switch_ivr_say_spell(switch_core_session_t *session, char *tosay, switch_say_args_t *say_args, switch_input_args_t *args)
{
char *p;
arg_recursion_check_start(args);
for (p = tosay; p && *p; p++) {
int a = tolower((int) *p);
@ -147,6 +149,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_spell(switch_core_session_t *sess
}
}
arg_recursion_check_stop(args);
return SWITCH_STATUS_SUCCESS;
}
@ -172,24 +176,28 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_ip(switch_core_session_t *session
switch_input_args_t *args)
{
char *a, *b, *c, *d;
switch_status_t status = SWITCH_STATUS_SUCCESS;
arg_recursion_check_start(args);
if (!(a = switch_core_session_strdup(session, tosay))) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
if (!(b = strchr(a, '.'))) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
*b++ = '\0';
if (!(c = strchr(b, '.'))) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
*c++ = '\0';
if (!(d = strchr(c, '.'))) {
return SWITCH_STATUS_FALSE;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
*d++ = '\0';
@ -202,7 +210,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_ip(switch_core_session_t *session
say_file("digits/dot.wav");
say_num(atoi(d), say_args->method);
return SWITCH_STATUS_SUCCESS;
end:
arg_recursion_check_stop(args);
return status;
}