[commit] r3520 - freeswitch/branches/knhor/trunk/src
Author: knhor Date: Sun Dec 3 17:07:21 2006 New Revision: 3520 Modified: freeswitch/branches/knhor/trunk/src/switch_ivr.c Log: switch_ivr_collect_digits_count should not always return SUCCESS if there was a failure to collect digits switch_ivr_collect_digits_count should not assume that a terminator set was supplied add digit timeout support to switch_ivr_digit_stream_parser Modified: freeswitch/branches/knhor/trunk/src/switch_ivr.c ============================================================================== --- freeswitch/branches/knhor/trunk/src/switch_ivr.c (original) +++ freeswitch/branches/knhor/trunk/src/switch_ivr.c Sun Dec 3 17:07:21 2006 @@ -27,7 +27,7 @@ * Paul D. Tinsley <pdt at jackhammer.org> * Neal Horman <neal at wanlink dot com> * - * switch_ivr_api.c -- IVR Library + * switch_ivr.c -- IVR Library * */ #include <switch.h> @@ -253,18 +253,19 @@ { uint32_t i = 0, x = (uint32_t) strlen(buf); switch_channel_t *channel; - switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_status_t status = SWITCH_STATUS_FALSE; switch_time_t started = 0; uint32_t elapsed; channel = switch_core_session_get_channel(session); - assert(channel != NULL); + assert(channel != NULL); - *terminator = '\0'; + if (terminator != NULL) + *terminator = '\0'; - if (terminators) { + if (!switch_strlen_zero(terminators)) { for (i = 0 ; i < x; i++) { - if (strchr(terminators, buf[i])) { + if (strchr(terminators, buf[i]) && terminator != NULL) { *terminator = buf[i]; return SWITCH_STATUS_SUCCESS; } @@ -293,10 +294,11 @@ if (switch_channel_has_dtmf(channel)) { char dtmf[128]; + switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf)); for(i =0 ; i < (uint32_t) strlen(dtmf); i++) { - if (strchr(terminators, dtmf[i])) { + if (!switch_strlen_zero(terminators) && strchr(terminators, dtmf[i]) && terminator != NULL) { *terminator = dtmf[i]; return SWITCH_STATUS_SUCCESS; } @@ -3413,6 +3415,8 @@ return SWITCH_STATUS_SUCCESS; } +/******************************************************************************************************/ + struct switch_ivr_digit_stream_parser { int pool_auto_created; switch_memory_pool_t *pool; @@ -3420,6 +3424,9 @@ char *digits; char terminator; switch_size_t maxlen; + switch_size_t minlen; + unsigned int digit_timeout_ms; + switch_time_t last_digit_time; }; SWITCH_DECLARE(switch_status_t) switch_ivr_digit_stream_parser_new(switch_memory_pool_t *pool, switch_ivr_digit_stream_parser_t **parser) @@ -3431,6 +3438,7 @@ // if the caller didn't provide a pool, make one if (pool == NULL) { switch_core_new_memory_pool(&pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "created a memory pool\n"); if (pool != NULL) { pool_auto_created = 1; } @@ -3446,12 +3454,13 @@ memset(*parser,0,sizeof(switch_ivr_digit_stream_parser_t)); (*parser)->pool_auto_created = pool_auto_created; (*parser)->pool = pool; + (*parser)->digit_timeout_ms = 1000; switch_core_hash_init(&(*parser)->hash,(*parser)->pool); status = SWITCH_STATUS_SUCCESS; } else { status = SWITCH_STATUS_MEMERR; - // clean up the pool if we created it + // if we can't create a parser object,clean up the pool if we created it if (pool != NULL && pool_auto_created) { switch_core_destroy_memory_pool(&pool); } @@ -3484,11 +3493,29 @@ { switch_status_t status = SWITCH_STATUS_FALSE; if (parser != NULL && digits != NULL && *digits && parser->hash != NULL) { - switch_size_t len; status = switch_core_hash_insert_dup(parser->hash,digits,data); - if (status == SWITCH_STATUS_SUCCESS && parser->terminator == '\0' && (len = strlen(digits)) > parser->maxlen) { - parser->maxlen = len; + if (status == SWITCH_STATUS_SUCCESS) { + switch_size_t len = strlen(digits); + + // if we don't have a terminator, then we have to try and + // figure out when a digit set is completed, therefore we + // keep track of the min and max digit lengths + if (parser->terminator == '\0') { + if (len > parser->maxlen) { + parser->maxlen = len; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "max len %u\n",parser->maxlen); + } + if (parser->minlen == 0 || len < parser->minlen) { + parser->minlen = len; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "min len %u\n",parser->minlen); + } + } else { + // since we have a terminator, reset min and max + parser->minlen = 0; + parser->maxlen = 0; + } + } } if (status != SWITCH_STATUS_SUCCESS) { @@ -3515,28 +3542,40 @@ SWITCH_DECLARE(void *) switch_ivr_digit_stream_parser_feed(switch_ivr_digit_stream_parser_t *parser, char digit) { void *result = NULL; - if (parser != NULL && digit != '\0') { + if (parser != NULL) { switch_size_t len = (parser->digits != NULL ? strlen(parser->digits) : 0); - // if it's not a terminator digit, add it to the collected digits - if (digit != parser->terminator) { - // if collected digits length >= the max length of the keys - // in the hash table, then left shift the digit string - if ( len > 0 && parser->maxlen != 0 && len >= parser->maxlen) { - char *src = parser->digits + 1; - char *dst = parser->digits; + // handle new digit arrivals + if(digit != '\0') { - while (*src) { - *(dst++) = *(src++); + // if it's not a terminator digit, add it to the collected digits + if (digit != parser->terminator) { + // if collected digits length >= the max length of the keys + // in the hash table, then left shift the digit string + if (len > 0 && parser->maxlen != 0 && len >= parser->maxlen) { + char *src = parser->digits + 1; + char *dst = parser->digits; + + while (*src) { + *(dst++) = *(src++); + } + *dst = digit; + } else { + parser->digits = realloc(parser->digits,len+2); + *(parser->digits+(len++)) = digit; + *(parser->digits+len) = '\0'; + parser->last_digit_time = switch_time_now() / 1000; } - *dst = digit; - } else { - parser->digits = realloc(parser->digits,len+2); - *(parser->digits+(len++)) = digit; - *(parser->digits+len) = '\0'; } } + // don't allow collected digit string testing if there are varying sized keys until timeout + if ( parser->maxlen - parser->minlen > 0 + && (switch_time_now() / 1000) - parser->last_digit_time < parser->digit_timeout_ms + ) { + len = 0; + } + // if we have digits to test if (len) { result = switch_core_hash_find(parser->hash,parser->digits); @@ -3547,7 +3586,7 @@ parser->digits = NULL; } } - } +} return result; } @@ -3569,6 +3608,8 @@ if (parser != NULL) { parser->terminator = digit; + // since we have a terminator, reset min and max + parser->minlen = 0; parser->maxlen = 0; status = SWITCH_STATUS_SUCCESS; } @@ -3576,6 +3617,8 @@ return status; } +/******************************************************************************************************/ + struct switch_ivr_menu_action; struct switch_ivr_menu { @@ -3721,7 +3764,6 @@ return SWITCH_STATUS_SUCCESS; } - SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_action(switch_ivr_menu_t *menu, switch_ivr_action_t ivr_action, char *arg, char *bind) { switch_ivr_menu_action_t *action; @@ -3743,7 +3785,6 @@ return SWITCH_STATUS_MEMERR; } - SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_function(switch_ivr_menu_t *menu, switch_ivr_menu_action_function_t *function, char *arg, char *bind) { switch_ivr_menu_action_t *action; @@ -3809,9 +3850,9 @@ } if (need) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "waiting for %u digits\n",need); menu->ptr += strlen(menu->buf); if (strlen(menu->buf) < need) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "waiting for %u digits\n",need); status = switch_ivr_collect_digits_count(session, menu->ptr, menu->inlen - strlen(menu->buf), need, "#", &terminator, menu->timeout); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "digits '%s'\n",menu->buf); @@ -3824,7 +3865,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj) { int reps = 0, errs = 0, match = 0, running = 1; - char *greeting_sound = NULL, *aptr; + char *greeting_sound = NULL, *aptr = NULL; char arg[512]; switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; switch_ivr_menu_action_t *ap; @@ -3851,8 +3892,6 @@ } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "stack timer name '%s'\n",stack->timer_name); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "menu timer name '%s'\n",menu->timer_name); for (reps = 0 ; (running && status == SWITCH_STATUS_SUCCESS && errs < menu->max_failures) ; reps++) { if (!switch_channel_ready(channel)) { @@ -3870,8 +3909,8 @@ memset(arg, 0, sizeof(arg)); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "want %d digits\n",menu->inlen); - play_or_say(session, menu, greeting_sound, menu->inlen, stack->timer_name); + memset(menu->buf, 0, menu->inlen); + status = play_or_say(session, menu, greeting_sound, menu->inlen, stack->timer_name); if (!switch_strlen_zero(menu->buf)) { for(ap = menu->actions; ap ; ap = ap->next) { @@ -3898,9 +3937,7 @@ status = switch_ivr_play_file(session, NULL, aptr, stack->timer_name, NULL, NULL, 0); break; case SWITCH_IVR_ACTION_SAYTEXT: - if (menu->tts_engine && menu->tts_voice) { - switch_ivr_speak_text(session, menu->tts_engine, menu->tts_voice, NULL, 0, NULL, aptr, NULL, 0); - } + status = switch_ivr_speak_text(session, menu->tts_engine, menu->tts_voice, NULL, 0, NULL, aptr, NULL, 0); break; case SWITCH_IVR_ACTION_TRANSFER: switch_ivr_session_transfer(session, aptr, NULL, NULL); @@ -3960,7 +3997,7 @@ } } } - if (!match) { + if (*menu->buf && !match) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, menu->buf); if (menu->invalid_sound) { @@ -3975,14 +4012,17 @@ } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "exit-sound '%s'\n",menu->exit_sound); - if (!switch_strlen_zero(menu->exit_sound)) + if (!switch_strlen_zero(menu->exit_sound)) { status = switch_ivr_play_file(session, NULL, menu->exit_sound, stack->timer_name, NULL, NULL, 0); + } switch_safe_free(menu->buf); return status; } +/******************************************************************************************************/ + typedef struct switch_ivr_menu_xml_map { char *name; switch_ivr_action_t action; @@ -4016,8 +4056,7 @@ if (xml_ctx != NULL && name != NULL && xml_ctx->pool != NULL && switch_ivr_menu_stack_xml_find(xml_ctx,name) == NULL) { switch_ivr_menu_xml_map_t *map = switch_core_alloc(xml_ctx->pool,sizeof(switch_ivr_menu_xml_map_t)); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "switch_ivr_menu_stack_xml_add bindng '%s'\n",name); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "switch_ivr_menu_stack_xml_add bindng '%s'\n",name); // and we have memory if (map != NULL) { map->name = switch_core_strdup(xml_ctx->pool,name); @@ -4191,17 +4230,3 @@ return status; } -/* -SWITCH_DECLARE(switch_status_t) switch_ivr_menu_stack_xml_free(switch_ivr_menu_xml_ctx_t **xml_menu_ctx, - switch_ivr_menu_t **menu_stack) -{ - switch_status_t status = SWITCH_STATUS_FALSE; - - if (xml_menu_ctx != NULL && *xml_menu_ctx != NULL ) { - } - - status = switch_ivr_menu_stack_free(menu_stack); - - return status -} -*/
participants (1)
-
Freeswitch SVN