Implement eswitch for evalulating variables at runtime (bug #3168)
authorMark Spencer <markster@digium.com>
Thu, 13 Jan 2005 05:14:56 +0000 (05:14 +0000)
committerMark Spencer <markster@digium.com>
Thu, 13 Jan 2005 05:14:56 +0000 (05:14 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4780 65c4cc65-6c06-0410-ace0-fbb531ad65f3

configs/extensions.conf.sample
include/asterisk/pbx.h
pbx.c
pbx/pbx_config.c

index 7ff155a..ecbaa5a 100755 (executable)
@@ -254,6 +254,12 @@ include => iaxprovider
 ; be substituted in the switch routine itself)
 ;
 ; 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];
 ;
index 33aa1b5..1c48b45 100755 (executable)
@@ -424,16 +424,17 @@ int ast_context_verify_includes(struct ast_context *con);
  * \param context context to which to add the switch
  * \param sw switch to add
  * \param data data to pass to switch
+ * \param eval whether to evaluate variables when running switch
  * \param registrar whoever registered the switch
  * This function registers a switch with the asterisk switch architecture
  * 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)
 /*!
  * 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
 /*!
diff --git a/pbx.c b/pbx.c
index 2b506dc..fcfbb45 100755 (executable)
--- a/pbx.c
+++ b/pbx.c
@@ -56,6 +56,9 @@
 #define EXT_DATA_SIZE 8192
 #endif
 
+#define SWITCH_DATA_LENGTH 256
+
+
 #define        VAR_NORMAL              1
 #define        VAR_SOFTTRAN    2
 #define        VAR_HARDTRAN    3
@@ -95,7 +98,9 @@ struct ast_sw {
        char *name;
        const char *registrar;                  /* Registrar */
        char *data;             /* Data load */
+       int eval;
        struct ast_sw *next;                    /* Link them together */
+       char *tmpdata;
        char stuff[0];
 };
 
@@ -758,16 +763,19 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
                        sw = tmp->alts;
                        while(sw) {
                                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)
-                                               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)
-                                               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
-                                               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) {
                                                /* Got a match */
                                                *swo = asw;
-                                               *data = sw->data;
+                                               *data = sw->eval ? sw->tmpdata : sw->data;
                                                *foundcontext = context;
                                                return NULL;
                                        }
@@ -3612,7 +3620,7 @@ int ast_context_add_include2(struct ast_context *con, const char *value,
  *  EBUSY  - can't lock
  *  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;
 
@@ -3626,7 +3634,7 @@ int ast_context_add_switch(const char *context, const char *sw, const char *data
        while (c) {
                /* ... search for the right one ... */
                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 */
                        ast_unlock_contexts();
                        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
  */
 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 *i, *il = NULL; /* sw, sw_last */
@@ -3660,6 +3668,11 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
        if (data)
                length += strlen(data);
        length++;
+       if (eval) {
+               /* Create buffer for evaluation of variables */
+               length += SWITCH_DATA_LENGTH;
+               length++;
+       }
 
        /* allocate new sw structure ... */
        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);
        p += strlen(value) + 1;
        new_sw->data = p;
-       if (data)
+       if (data) {
                strcpy(new_sw->data, data);
-       else
+               p += strlen(data) + 1;
+       } else {
                strcpy(new_sw->data, "");
+               p++;
+       }
+       if (eval) 
+               new_sw->tmpdata = p;
        new_sw->next      = NULL;
+       new_sw->eval      = eval;
        new_sw->registrar = registrar;
 
        /* ... try to lock this context ... */
index 63c6601..84420ba 100755 (executable)
@@ -1754,7 +1754,7 @@ static int pbx_load_module(void)
                                                pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
                                                if (ast_context_add_ignorepat2(con, realvalue, registrar))
                                                        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;
                                                memset(realvalue, 0, sizeof(realvalue));
                                                if (!strcasecmp(v->name, "switch"))
@@ -1767,7 +1767,7 @@ static int pbx_load_module(void)
                                                data = strsep(&stringp, "");
                                                if (!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);
                                        }
                                        v = v->next;