From 5800db655679ada2b0199c9de95e43b8871083ca Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Fri, 7 Jan 2000 10:54:40 +0000 Subject: Version 0.1.2 from FTP git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@198 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- pbx.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 14 deletions(-) (limited to 'pbx.c') diff --git a/pbx.c b/pbx.c index 23dd88a84..3c8c17c6b 100755 --- a/pbx.c +++ b/pbx.c @@ -82,6 +82,8 @@ struct ast_app { struct ast_app *next; }; +static int pbx_builtin_prefix(struct ast_channel *, void *); +static int pbx_builtin_stripmsd(struct ast_channel *, void *); static int pbx_builtin_answer(struct ast_channel *, void *); static int pbx_builtin_goto(struct ast_channel *, void *); static int pbx_builtin_hangup(struct ast_channel *, void *); @@ -104,6 +106,8 @@ static struct pbx_builtin { { "ResponseTimeout", pbx_builtin_rtimeout }, { "BackGround", pbx_builtin_background }, { "Wait", pbx_builtin_wait }, + { "StripMSD", pbx_builtin_stripmsd }, + { "Prefix", pbx_builtin_prefix }, }; /* Lock for the application list */ @@ -155,6 +159,7 @@ static int pbx_exec(struct ast_channel *c, /* Channel */ #define HELPER_EXISTS 0 #define HELPER_SPAWN 1 #define HELPER_EXEC 2 +#define HELPER_CANMATCH 3 static struct ast_app *pbx_findapp(char *app) { @@ -213,6 +218,42 @@ static int extension_match(char *pattern, char *data) return match; } +static int extension_close(char *pattern, char *data) +{ + int match; + /* If "data" is longer, it can'be a subset of pattern */ + if (strlen(pattern) < strlen(data)) + return 0; + + if (!strncasecmp(pattern, data, strlen(data))) { + return 1; + } + /* All patterns begin with _ */ + if (pattern[0] != '_') + return 0; + /* Start optimistic */ + match=1; + pattern++; + while(match && *data && *pattern) { + switch(toupper(*pattern)) { + case 'N': + if ((*data < '2') || (*data > '9')) + match=0; + break; + case 'X': + if ((*data < '0') || (*data > '9')) + match = 0; + break; + default: + if (*data != *pattern) + match =0; + } + data++; + pattern++; + } + return match; +} + static int pbx_extension_helper(struct ast_channel *c, char *context, char *exten, int priority, int action) { struct ast_context *tmp; @@ -222,7 +263,7 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte int res; if (pthread_mutex_lock(&conlock)) { ast_log(LOG_WARNING, "Unable to obtain lock\n"); - if (action == HELPER_EXISTS) + if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH)) return 0; else return -1; @@ -230,27 +271,32 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte tmp = contexts; while(tmp) { if (!strcasecmp(tmp->name, context)) { +#if 0 /* By locking tmp, not only can the state of its entries not change, but it cannot be destroyed either. */ pthread_mutex_lock(&tmp->lock); - /* But we can relieve the conlock, as tmp will not change */ - pthread_mutex_unlock(&conlock); +#endif e = tmp->root; while(e) { - if (extension_match(e->exten, exten)) { + if (extension_match(e->exten, exten) || + ((action == HELPER_CANMATCH) && extension_close(e->exten, exten))) { while(e) { if (e->priority == priority) { - pthread_mutex_unlock(&tmp->lock); /* We have a winner! Maybe there are some races in here though. XXX */ switch(action) { + case HELPER_CANMATCH: + pthread_mutex_unlock(&conlock); + return -1; case HELPER_EXISTS: + pthread_mutex_unlock(&conlock); return -1; case HELPER_SPAWN: newstack++; /* Fall through */ case HELPER_EXEC: app = pbx_findapp(e->app); + pthread_mutex_unlock(&conlock); if (app) { strncpy(c->context, context, sizeof(c->context)); strncpy(c->exten, exten, sizeof(c->exten)); @@ -265,6 +311,7 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte res = pbx_exec(c, app->execute, e->data, newstack); c->appl = NULL; c->data = NULL; + pthread_mutex_unlock(&conlock); return res; } else { ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority); @@ -277,20 +324,25 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte e = e->peer; } pthread_mutex_unlock(&tmp->lock); - if (action != HELPER_EXISTS) { + if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH)) { ast_log(LOG_WARNING, "No such priority '%d' in '%s' in '%s'\n", priority, exten, context); + pthread_mutex_unlock(&conlock); return -1; - } else + } else { + pthread_mutex_unlock(&conlock); return 0; + } } e = e->next; } - pthread_mutex_unlock(&tmp->lock); - if (action != HELPER_EXISTS) { + if ((action != HELPER_EXISTS) && (action != HELPER_CANMATCH)) { + pthread_mutex_unlock(&conlock); ast_log(LOG_WARNING, "No such extension '%s' in '%s'\n", exten, context); return -1; - } else + } else { + pthread_mutex_unlock(&conlock); return 0; + } } tmp = tmp->next; } @@ -338,6 +390,11 @@ int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int return pbx_extension_helper(c, context, exten, priority, HELPER_EXISTS); } +int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority) +{ + return pbx_extension_helper(c, context, exten, priority, HELPER_CANMATCH); +} + int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority) { return pbx_extension_helper(c, context, exten, priority, HELPER_SPAWN); @@ -382,14 +439,13 @@ static void *pbx_thread(void *data) goto out; } /* If we're playing something in the background, wait for it to finish or for a digit */ - if (c->stream) { + if (c->stream || (c->trans && c->trans->stream)) { digit = ast_waitstream(c, AST_DIGIT_ANY); ast_stopstream(c); /* Hang up if something goes wrong */ if (digit < 0) goto out; else if (digit) { - ast_stopstream(c); exten[pos++] = digit; break; } @@ -402,8 +458,8 @@ static void *pbx_thread(void *data) waittime = c->pbx->dtimeout; else waittime = c->pbx->rtimeout; - while(!ast_exists_extension(c, c->context, exten, 1) && ( - strlen(exten) < ast_pbx_longest_extension(c->context))) { + while(!ast_exists_extension(c, c->context, exten, 1) && + ast_canmatch_extension(c, c->context, exten, 1)) { /* As long as we're willing to wait, and as long as it's not defined, keep reading digits until we can't possibly get a right answer anymore. */ digit = ast_waitfordigit(c, waittime * 1000); @@ -770,6 +826,32 @@ int pbx_builtin_hangup(struct ast_channel *chan, void *data) return -1; } +int pbx_builtin_stripmsd(struct ast_channel *chan, void *data) +{ + char newexten[AST_MAX_EXTENSION] = ""; + if (!data || !atoi(data)) { + ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n"); + return 0; + } + if (strlen(chan->exten) > atoi(data)) { + strncpy(newexten, chan->exten + atoi(data), sizeof(newexten)); + } + strncpy(chan->exten, newexten, sizeof(chan->exten)); + return 0; +} + +int pbx_builtin_prefix(struct ast_channel *chan, void *data) +{ + char newexten[AST_MAX_EXTENSION] = ""; + if (!data || !strlen(data)) { + ast_log(LOG_DEBUG, "Ignoring, since there is no prefix to add\n"); + return 0; + } + snprintf(newexten, sizeof(newexten), "%s%s", (char *)data, chan->exten); + strncpy(chan->exten, newexten, sizeof(chan->exten)); + return 0; +} + int pbx_builtin_wait(struct ast_channel *chan, void *data) { /* Wait for "n" seconds */ -- cgit v1.2.3