aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-03-10 21:48:20 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-03-10 21:48:20 +0000
commitd7a3bcf49b7224604a90914d4256fd02efbbfcc9 (patch)
treedff4bf7db6d813c70ce9ad1d03b9e41527b7c6eb
parent5f074afc2205cd5859857437dd9ff8944d20d1a4 (diff)
(closes issue #6019)
Reported by: ssokol Patches: 20080304__bug6019.diff.txt uploaded by Corydon76 (license 14) Tested by: putnopvut git-svn-id: http://svn.digium.com/svn/asterisk/trunk@107231 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--include/asterisk/pbx.h5
-rw-r--r--main/pbx.c94
-rw-r--r--pbx/pbx_config.c26
3 files changed, 110 insertions, 15 deletions
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 14e7af4b2..f7b97e8f2 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -839,6 +839,11 @@ int pbx_set_autofallthrough(int newval);
the old linear-search algorithm. Returns previous value. */
int pbx_set_extenpatternmatchnew(int newval);
+/*! Set "overrideswitch" field. If set and of nonzero length, all contexts
+ * will be tried directly through the named switch prior to any other
+ * matching within that context. */
+void pbx_set_overrideswitch(const char *newval);
+
/*!
* \note This function will handle locking the channel as needed.
*/
diff --git a/main/pbx.c b/main/pbx.c
index 2e3260a34..029b68b8a 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -123,6 +123,8 @@ AST_APP_OPTIONS(waitexten_opts, {
struct ast_context;
struct ast_app;
+AST_THREADSTORAGE(switch_data);
+
/*!
\brief ast_exten: An extension
The dialplan is saved as a linked list with each context
@@ -166,7 +168,6 @@ struct ast_sw {
char *data; /*!< Data load */
int eval;
AST_LIST_ENTRY(ast_sw) list;
- char *tmpdata;
char stuff[0];
};
@@ -413,6 +414,7 @@ static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
static int autofallthrough = 1;
static int extenpatternmatchnew = 0;
+static char *overrideswitch = NULL;
/*! \brief Subscription for device state change events */
static struct ast_event_sub *device_state_sub;
@@ -1644,6 +1646,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
struct ast_sw *sw = NULL;
struct ast_exten pattern = {NULL, };
struct scoreboard score = {0, };
+ struct ast_str *tmpdata = NULL;
pattern.label = label;
pattern.priority = priority;
@@ -1707,6 +1710,65 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
log_match_char_tree(tmp->pattern_tree, ":: ");
#endif
+ do {
+ if (!ast_strlen_zero(overrideswitch)) {
+ char *osw = ast_strdupa(overrideswitch), *name;
+ struct ast_switch *asw;
+ ast_switch_f *aswf = NULL;
+ char *datap;
+ int eval = 0;
+
+ name = strsep(&osw, "/");
+ asw = pbx_findswitch(name);
+
+ if (!asw) {
+ ast_log(LOG_WARNING, "No such switch '%s'\n", name);
+ break;
+ }
+
+ if (osw && strchr(osw, '$')) {
+ eval = 1;
+ }
+
+ if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
+ ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
+ break;
+ } else if (eval) {
+ /* Substitute variables now */
+ pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len);
+ datap = tmpdata->str;
+ } else {
+ datap = osw;
+ }
+
+ /* equivalent of extension_match_core() at the switch level */
+ if (action == E_CANMATCH)
+ aswf = asw->canmatch;
+ else if (action == E_MATCHMORE)
+ aswf = asw->matchmore;
+ else /* action == E_MATCH */
+ aswf = asw->exists;
+ if (!aswf) {
+ res = 0;
+ } else {
+ if (chan) {
+ ast_autoservice_start(chan);
+ }
+ res = aswf(chan, context, exten, priority, callerid, datap);
+ if (chan) {
+ ast_autoservice_stop(chan);
+ }
+ }
+ if (res) { /* Got a match */
+ q->swo = asw;
+ q->data = datap;
+ q->foundcontext = context;
+ /* XXX keep status = STATUS_NO_CONTEXT ? */
+ return NULL;
+ }
+ }
+ } while (0);
+
if (extenpatternmatchnew) {
new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
eroot = score.exten;
@@ -1828,8 +1890,13 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
}
/* Substitute variables now */
- if (sw->eval)
- pbx_substitute_variables_helper(chan, sw->data, sw->tmpdata, SWITCH_DATA_LENGTH - 1);
+ if (sw->eval) {
+ if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
+ ast_log(LOG_WARNING, "Can't evaluate switch?!");
+ continue;
+ }
+ pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len);
+ }
/* equivalent of extension_match_core() at the switch level */
if (action == E_CANMATCH)
@@ -1838,7 +1905,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
aswf = asw->matchmore;
else /* action == E_MATCH */
aswf = asw->exists;
- datap = sw->eval ? sw->tmpdata : sw->data;
+ datap = sw->eval ? tmpdata->str : sw->data;
if (!aswf)
res = 0;
else {
@@ -3618,6 +3685,18 @@ int pbx_set_extenpatternmatchnew(int newval)
return oldval;
}
+void pbx_set_overrideswitch(const char *newval)
+{
+ if (overrideswitch) {
+ ast_free(overrideswitch);
+ }
+ if (!ast_strlen_zero(newval)) {
+ overrideswitch = ast_strdup(newval);
+ } else {
+ overrideswitch = NULL;
+ }
+}
+
/*!
* \brief lookup for a context with a given name,
* \retval with conlock held if found.
@@ -5781,11 +5860,6 @@ 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 = ast_calloc(1, length)))
@@ -5803,8 +5877,6 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
strcpy(new_sw->data, "");
p++;
}
- if (eval)
- new_sw->tmpdata = p;
new_sw->eval = eval;
new_sw->registrar = registrar;
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index bf707a950..a35585a6e 100644
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -47,6 +47,7 @@ static int write_protect_config = 1;
static int autofallthrough_config = 1;
static int clearglobalvars_config = 0;
static int extenpatternmatchnew_config = 0;
+static char *overrideswitch_config = NULL;
AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
@@ -701,7 +702,7 @@ static char *complete_dialplan_add_include(struct ast_cli_args *a)
*/
static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char filename[256];
+ char filename[256], overrideswitch[256] = "";
struct ast_context *c;
struct ast_config *cfg;
struct ast_variable *v;
@@ -781,11 +782,15 @@ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct a
}
/* fireout general info */
- fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\nextenpatternmatchnew=%s\n\n",
+ if (overrideswitch_config) {
+ snprintf(overrideswitch, sizeof(overrideswitch), "overrideswitch=%s\n", overrideswitch_config);
+ }
+ fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\nautofallthrough=%s\nclearglobalvars=%s\n%sextenpatternmatchnew=%s\n\n",
static_config ? "yes" : "no",
write_protect_config ? "yes" : "no",
autofallthrough_config ? "yes" : "no",
clearglobalvars_config ? "yes" : "no",
+ overrideswitch_config ? overrideswitch : "",
extenpatternmatchnew_config ? "yes" : "no");
if ((v = ast_variable_browse(cfg, "globals"))) {
@@ -1353,6 +1358,9 @@ static int unload_module(void)
{
if (static_config && !write_protect_config)
ast_cli_unregister(&cli_dialplan_save);
+ if (overrideswitch_config) {
+ ast_free(overrideswitch_config);
+ }
ast_cli_unregister_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry));
ast_context_destroy(NULL, registrar);
return 0;
@@ -1369,7 +1377,7 @@ static int pbx_load_config(const char *config_file)
struct ast_variable *v;
const char *cxt;
const char *aft;
- const char *newpm;
+ const char *newpm, *ovsw;
struct ast_flags config_flags = { 0 };
cfg = ast_config_load(config_file, config_flags);
if (!cfg)
@@ -1383,7 +1391,16 @@ static int pbx_load_config(const char *config_file)
if ((newpm = ast_variable_retrieve(cfg, "general", "extenpatternmatchnew")))
extenpatternmatchnew_config = ast_true(newpm);
clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general", "clearglobalvars"));
-
+ if ((ovsw = ast_variable_retrieve(cfg, "general", "overrideswitch"))) {
+ if (overrideswitch_config) {
+ ast_free(overrideswitch_config);
+ }
+ if (!ast_strlen_zero(ovsw)) {
+ overrideswitch_config = ast_strdup(ovsw);
+ } else {
+ overrideswitch_config = NULL;
+ }
+ }
if ((cxt = ast_variable_retrieve(cfg, "general", "userscontext")))
ast_copy_string(userscontext, cxt, sizeof(userscontext));
@@ -1640,6 +1657,7 @@ static int pbx_load_module(void)
for (con = NULL; (con = ast_walk_contexts(con));)
ast_context_verify_includes(con);
+ pbx_set_overrideswitch(overrideswitch_config);
pbx_set_autofallthrough(autofallthrough_config);
pbx_set_extenpatternmatchnew(extenpatternmatchnew_config);