[Freeswitch-branches] [commit] r3520 - freeswitch/branches/knhor/trunk/src

Freeswitch SVN knhor at freeswitch.org
Sun Dec 3 17:07:22 EST 2006


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
-}
-*/



More information about the Freeswitch-branches mailing list