Implement eswitch for evalulating variables at runtime (bug #3168)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4780 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2005-01-13 05:14:56 +00:00
parent 7c048c0b65
commit 278a0a0891
4 changed files with 39 additions and 13 deletions

View File

@@ -254,6 +254,12 @@ include => iaxprovider
; be substituted in the switch routine itself) ; be substituted in the switch routine itself)
; ;
; lswitch => Loopback/12${EXTEN}@othercontext ; lswitch => Loopback/12${EXTEN}@othercontext
;
; An "eswitch" is like a switch but the evaluation of
; variable substitution is performed at runtime before
; being passed to the switch routine.
;
; eswitch => IAX2/context@${CURSERVER}
[macro-stdexten]; [macro-stdexten];
; ;

View File

@@ -424,16 +424,17 @@ int ast_context_verify_includes(struct ast_context *con);
* \param context context to which to add the switch * \param context context to which to add the switch
* \param sw switch to add * \param sw switch to add
* \param data data to pass to switch * \param data data to pass to switch
* \param eval whether to evaluate variables when running switch
* \param registrar whoever registered the switch * \param registrar whoever registered the switch
* This function registers a switch with the asterisk switch architecture * This function registers a switch with the asterisk switch architecture
* It returns 0 on success, -1 on failure * It returns 0 on success, -1 on failure
*/ */
int ast_context_add_switch(const char *context, const char *sw, const char *data, const char *registrar); int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar);
//! Adds a switch (first param is a ast_context) //! Adds a switch (first param is a ast_context)
/*! /*!
* See ast_context_add_switch() * See ast_context_add_switch()
*/ */
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar); int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar);
//! Remove a switch //! Remove a switch
/*! /*!

37
pbx.c
View File

@@ -56,6 +56,9 @@
#define EXT_DATA_SIZE 8192 #define EXT_DATA_SIZE 8192
#endif #endif
#define SWITCH_DATA_LENGTH 256
#define VAR_NORMAL 1 #define VAR_NORMAL 1
#define VAR_SOFTTRAN 2 #define VAR_SOFTTRAN 2
#define VAR_HARDTRAN 3 #define VAR_HARDTRAN 3
@@ -95,7 +98,9 @@ struct ast_sw {
char *name; char *name;
const char *registrar; /* Registrar */ const char *registrar; /* Registrar */
char *data; /* Data load */ char *data; /* Data load */
int eval;
struct ast_sw *next; /* Link them together */ struct ast_sw *next; /* Link them together */
char *tmpdata;
char stuff[0]; char stuff[0];
}; };
@@ -758,16 +763,19 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
sw = tmp->alts; sw = tmp->alts;
while(sw) { while(sw) {
if ((asw = pbx_findswitch(sw->name))) { if ((asw = pbx_findswitch(sw->name))) {
/* Substitute variables now */
if (sw->eval)
pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
if (action == HELPER_CANMATCH) if (action == HELPER_CANMATCH)
res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->data) : 0; res = asw->canmatch ? asw->canmatch(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
else if (action == HELPER_MATCHMORE) else if (action == HELPER_MATCHMORE)
res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->data) : 0; res = asw->matchmore ? asw->matchmore(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
else else
res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->data) : 0; res = asw->exists ? asw->exists(chan, context, exten, priority, callerid, sw->eval ? sw->tmpdata : sw->data) : 0;
if (res) { if (res) {
/* Got a match */ /* Got a match */
*swo = asw; *swo = asw;
*data = sw->data; *data = sw->eval ? sw->tmpdata : sw->data;
*foundcontext = context; *foundcontext = context;
return NULL; return NULL;
} }
@@ -3612,7 +3620,7 @@ int ast_context_add_include2(struct ast_context *con, const char *value,
* EBUSY - can't lock * EBUSY - can't lock
* ENOENT - no existence of context * ENOENT - no existence of context
*/ */
int ast_context_add_switch(const char *context, const char *sw, const char *data, const char *registrar) int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
{ {
struct ast_context *c; struct ast_context *c;
@@ -3626,7 +3634,7 @@ int ast_context_add_switch(const char *context, const char *sw, const char *data
while (c) { while (c) {
/* ... search for the right one ... */ /* ... search for the right one ... */
if (!strcmp(ast_get_context_name(c), context)) { if (!strcmp(ast_get_context_name(c), context)) {
int ret = ast_context_add_switch2(c, sw, data, registrar); int ret = ast_context_add_switch2(c, sw, data, eval, registrar);
/* ... unlock contexts list and return */ /* ... unlock contexts list and return */
ast_unlock_contexts(); ast_unlock_contexts();
return ret; return ret;
@@ -3648,7 +3656,7 @@ int ast_context_add_switch(const char *context, const char *sw, const char *data
* EINVAL - there is no existence of context for inclusion * EINVAL - there is no existence of context for inclusion
*/ */
int ast_context_add_switch2(struct ast_context *con, const char *value, int ast_context_add_switch2(struct ast_context *con, const char *value,
const char *data, const char *registrar) const char *data, int eval, const char *registrar)
{ {
struct ast_sw *new_sw; struct ast_sw *new_sw;
struct ast_sw *i, *il = NULL; /* sw, sw_last */ struct ast_sw *i, *il = NULL; /* sw, sw_last */
@@ -3660,6 +3668,11 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
if (data) if (data)
length += strlen(data); length += strlen(data);
length++; length++;
if (eval) {
/* Create buffer for evaluation of variables */
length += SWITCH_DATA_LENGTH;
length++;
}
/* allocate new sw structure ... */ /* allocate new sw structure ... */
if (!(new_sw = malloc(length))) { if (!(new_sw = malloc(length))) {
@@ -3675,11 +3688,17 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
strcpy(new_sw->name, value); strcpy(new_sw->name, value);
p += strlen(value) + 1; p += strlen(value) + 1;
new_sw->data = p; new_sw->data = p;
if (data) if (data) {
strcpy(new_sw->data, data); strcpy(new_sw->data, data);
else p += strlen(data) + 1;
} else {
strcpy(new_sw->data, ""); strcpy(new_sw->data, "");
p++;
}
if (eval)
new_sw->tmpdata = p;
new_sw->next = NULL; new_sw->next = NULL;
new_sw->eval = eval;
new_sw->registrar = registrar; new_sw->registrar = registrar;
/* ... try to lock this context ... */ /* ... try to lock this context ... */

View File

@@ -1754,7 +1754,7 @@ static int pbx_load_module(void)
pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1); pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
if (ast_context_add_ignorepat2(con, realvalue, registrar)) if (ast_context_add_ignorepat2(con, realvalue, registrar))
ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt); ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
} else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch")) { } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
char *stringp=NULL; char *stringp=NULL;
memset(realvalue, 0, sizeof(realvalue)); memset(realvalue, 0, sizeof(realvalue));
if (!strcasecmp(v->name, "switch")) if (!strcasecmp(v->name, "switch"))
@@ -1767,7 +1767,7 @@ static int pbx_load_module(void)
data = strsep(&stringp, ""); data = strsep(&stringp, "");
if (!data) if (!data)
data = ""; data = "";
if (ast_context_add_switch2(con, appl, data, registrar)) if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar))
ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt); ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
} }
v = v->next; v = v->next;