improve dmachine stuff some more

This commit is contained in:
Anthony Minessale
2010-10-08 13:50:15 -05:00
parent 8a7f8cd22e
commit 1d921b1cfa
6 changed files with 233 additions and 63 deletions

View File

@@ -45,28 +45,41 @@ struct switch_ivr_dmachine_binding {
};
typedef struct switch_ivr_dmachine_binding switch_ivr_dmachine_binding_t;
#define DM_MAX_DIGIT_LEN 512
typedef struct {
switch_ivr_dmachine_binding_t *binding_list;
switch_ivr_dmachine_binding_t *tail;
} dm_binding_head_t;
struct switch_ivr_dmachine {
switch_memory_pool_t *pool;
switch_byte_t my_pool;
char *name;
uint32_t digit_timeout_ms;
uint32_t input_timeout_ms;
switch_ivr_dmachine_binding_t *binding_list;
switch_ivr_dmachine_binding_t *tail;
switch_ivr_dmachine_binding_t *last_matching_binding;
switch_hash_t *binding_hash;
switch_ivr_dmachine_match_t match;
char digits[DM_MAX_DIGIT_LEN];
char last_matching_digits[DM_MAX_DIGIT_LEN];
char digits[DMACHINE_MAX_DIGIT_LEN];
char last_matching_digits[DMACHINE_MAX_DIGIT_LEN];
char last_failed_digits[DMACHINE_MAX_DIGIT_LEN];
uint32_t cur_digit_len;
uint32_t max_digit_len;
switch_time_t last_digit_time;
switch_byte_t is_match;
switch_ivr_dmachine_callback_t match_callback;
switch_ivr_dmachine_callback_t nonmatch_callback;
dm_binding_head_t *realm;
switch_ivr_dmachine_binding_t *last_matching_binding;
void *user_data;
};
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p,
switch_memory_pool_t *pool,
uint32_t digit_timeout_ms, uint32_t input_timeout_ms)
const char *name,
switch_memory_pool_t *pool,
uint32_t digit_timeout_ms,
uint32_t input_timeout_ms,
switch_ivr_dmachine_callback_t match_callback,
switch_ivr_dmachine_callback_t nonmatch_callback,
void *user_data)
{
switch_byte_t my_pool = !!pool;
switch_ivr_dmachine_t *dmachine;
@@ -81,8 +94,22 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t
dmachine->digit_timeout_ms = digit_timeout_ms;
dmachine->input_timeout_ms = input_timeout_ms;
dmachine->match.dmachine = dmachine;
*dmachine_p = dmachine;
dmachine->name = switch_core_strdup(dmachine->pool, name);
switch_core_hash_init(&dmachine->binding_hash, dmachine->pool);
if (match_callback) {
dmachine->match_callback = match_callback;
}
if (nonmatch_callback) {
dmachine->nonmatch_callback = nonmatch_callback;
}
dmachine->user_data = user_data;
*dmachine_p = dmachine;
return SWITCH_STATUS_SUCCESS;
}
@@ -105,12 +132,42 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachin
pool = (*dmachine)->pool;
switch_core_hash_destroy(&(*dmachine)->binding_hash);
if ((*dmachine)->my_pool) {
switch_core_destroy_memory_pool(&pool);
}
}
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm)
{
dm_binding_head_t *headp = switch_core_hash_find(dmachine->binding_hash, realm);
if (headp) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Setting realm to %s\n", dmachine->name, realm);
dmachine->realm = headp;
return SWITCH_STATUS_SUCCESS;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Digit parser %s: Error Setting realm to %s\n", dmachine->name, realm);
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmachine_t *dmachine, const char *realm)
{
if (zstr(realm)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Digit parser %s: Error unknown realm: %s\n", dmachine->name, realm);
return SWITCH_STATUS_FALSE;
}
/* pool alloc'd just ditch it and it will give back the memory when we destroy ourselves */
switch_core_hash_delete(dmachine->binding_hash, realm);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine,
const char *realm,
const char *digits,
int32_t key,
switch_ivr_dmachine_callback_t callback,
@@ -118,43 +175,59 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *
{
switch_ivr_dmachine_binding_t *binding;
switch_size_t len;
dm_binding_head_t *headp;
if (strlen(digits) > DM_MAX_DIGIT_LEN -1) {
if (strlen(digits) > DMACHINE_MAX_DIGIT_LEN -1) {
return SWITCH_STATUS_FALSE;
}
if (zstr(realm)) {
realm = "default";
}
if (!(headp = switch_core_hash_find(dmachine->binding_hash, realm))) {
headp = switch_core_alloc(dmachine->pool, sizeof(*headp));
switch_core_hash_insert(dmachine->binding_hash, realm, headp);
}
binding = switch_core_alloc(dmachine->pool, sizeof(*binding));
if (*digits == '~') {
binding->is_regex = 1;
digits++;
}
binding->key = key;
binding->digits = switch_core_strdup(dmachine->pool, digits);
binding->callback = callback;
binding->user_data = user_data;
if (dmachine->tail) {
dmachine->tail->next = binding;
if (headp->tail) {
headp->tail->next = binding;
} else {
dmachine->binding_list = binding;
headp->binding_list = binding;
}
dmachine->tail = binding;
headp->tail = binding;
len = strlen(digits);
if (binding->is_regex && dmachine->max_digit_len != DM_MAX_DIGIT_LEN -1) {
dmachine->max_digit_len = DM_MAX_DIGIT_LEN -1;
if (dmachine->realm != headp) {
switch_ivr_dmachine_set_realm(dmachine, realm);
}
if (binding->is_regex && dmachine->max_digit_len != DMACHINE_MAX_DIGIT_LEN -1) {
dmachine->max_digit_len = DMACHINE_MAX_DIGIT_LEN -1;
} else if (len > dmachine->max_digit_len) {
dmachine->max_digit_len = (uint32_t) len;
}
if (binding->is_regex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "binding regex: %s key: %.4d callback: %p data: %p\n",
digits, key, (void *)(intptr_t) callback, user_data);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: binding realm: %s regex: %s key: %.4d callback: %p data: %p\n",
dmachine->name, realm, digits, key, (void *)(intptr_t) callback, user_data);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "binding digits: %4s key: %.4d callback: %p data: %p\n",
digits, key, (void *)(intptr_t) callback, user_data);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: binding realm %s digits: %4s key: %.4d callback: %p data: %p\n",
dmachine->name, realm, digits, key, (void *)(intptr_t) callback, user_data);
}
return SWITCH_STATUS_SUCCESS;
@@ -175,9 +248,9 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin
int exact_count = 0, partial_count = 0, both_count = 0;
if (!dmachine->cur_digit_len) goto end;
if (!dmachine->cur_digit_len || !dmachine->realm) goto end;
for(bp = dmachine->binding_list; bp; bp = bp->next) {
for(bp = dmachine->realm->binding_list; bp; bp = bp->next) {
if (bp->is_regex) {
switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits);
@@ -259,12 +332,17 @@ SWITCH_DECLARE(switch_ivr_dmachine_match_t *) switch_ivr_dmachine_get_match(swit
return NULL;
}
SWITCH_DECLARE(const char *) switch_ivr_dmachine_get_failed_digits(switch_ivr_dmachine_t *dmachine)
{
return dmachine->last_failed_digits;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p)
{
switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine);
dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout);
switch_status_t r;
int exec = 0;
if (zstr(dmachine->digits) && !is_timeout) {
r = SWITCH_STATUS_SUCCESS;
@@ -282,7 +360,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *
}
dmachine->is_match = 1;
exec = 1;
dmachine->match.type = DM_MATCH_POSITIVE;
if (dmachine->last_matching_binding->callback) {
dmachine->last_matching_binding->callback(&dmachine->match);
}
if (dmachine->match_callback) {
dmachine->match.user_data = dmachine->user_data;
dmachine->match_callback(&dmachine->match);
}
} else if (is_timeout) {
r = SWITCH_STATUS_TIMEOUT;
} else if (dmachine->cur_digit_len == dmachine->max_digit_len) {
@@ -291,14 +380,22 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *
r = SWITCH_STATUS_SUCCESS;
}
if (r != SWITCH_STATUS_FOUND && r != SWITCH_STATUS_SUCCESS) {
switch_set_string(dmachine->last_failed_digits, dmachine->digits);
dmachine->match.match_digits = dmachine->last_failed_digits;
dmachine->match.type = DM_MATCH_NEGATIVE;
if (dmachine->nonmatch_callback) {
dmachine->match.user_data = dmachine->user_data;
dmachine->nonmatch_callback(&dmachine->match);
}
}
if (r != SWITCH_STATUS_SUCCESS) {
switch_ivr_dmachine_clear(dmachine);
}
if (exec && dmachine->last_matching_binding->callback) {
dmachine->last_matching_binding->callback(&dmachine->match);
}
return r;
}