pbx: Create pbx_sw.c for management of 'struct ast_sw'.
This changes context switches from a linked list to a vector, makes 'struct ast_sw' opaque to pbx.c. Although ast_walk_context_switches is maintained the procedure is no longer efficient except for the first call (inc==NULL). This functionality is replaced by two new functions implemented by vector macros. * ast_context_switches_count (AST_VECTOR_SIZE) * ast_context_switches_get (AST_VECTOR_GET) As with ast_walk_context_switches callers of these functions are expected to have locked contexts. Only a few places in Asterisk walked the switches, they have been converted to use the new functions. Change-Id: I08deb016df22eee8288eb03de62593e45a1f0998
This commit is contained in:
parent
3ca6407dab
commit
a36a174c4b
|
@ -1229,9 +1229,9 @@ const char *ast_get_extension_name(struct ast_exten *exten);
|
|||
struct ast_context *ast_get_extension_context(struct ast_exten *exten);
|
||||
const char *ast_get_include_name(const struct ast_include *include);
|
||||
const char *ast_get_ignorepat_name(const struct ast_ignorepat *ip);
|
||||
const char *ast_get_switch_name(struct ast_sw *sw);
|
||||
const char *ast_get_switch_data(struct ast_sw *sw);
|
||||
int ast_get_switch_eval(struct ast_sw *sw);
|
||||
const char *ast_get_switch_name(const struct ast_sw *sw);
|
||||
const char *ast_get_switch_data(const struct ast_sw *sw);
|
||||
int ast_get_switch_eval(const struct ast_sw *sw);
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
@ -1251,7 +1251,7 @@ const char *ast_get_context_registrar(struct ast_context *c);
|
|||
const char *ast_get_extension_registrar(struct ast_exten *e);
|
||||
const char *ast_get_include_registrar(const struct ast_include *i);
|
||||
const char *ast_get_ignorepat_registrar(const struct ast_ignorepat *ip);
|
||||
const char *ast_get_switch_registrar(struct ast_sw *sw);
|
||||
const char *ast_get_switch_registrar(const struct ast_sw *sw);
|
||||
/*! @} */
|
||||
|
||||
/*! @name Walking functions ... */
|
||||
|
@ -1265,7 +1265,8 @@ const struct ast_include *ast_walk_context_includes(const struct ast_context *co
|
|||
const struct ast_include *inc);
|
||||
const struct ast_ignorepat *ast_walk_context_ignorepats(const struct ast_context *con,
|
||||
const struct ast_ignorepat *ip);
|
||||
struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
|
||||
const struct ast_sw *ast_walk_context_switches(const struct ast_context *con,
|
||||
const struct ast_sw *sw);
|
||||
/*! @} */
|
||||
|
||||
/*! @name Iterator functions ... */
|
||||
|
@ -1274,6 +1275,8 @@ int ast_context_includes_count(const struct ast_context *con);
|
|||
const struct ast_include *ast_context_includes_get(const struct ast_context *con, int idx);
|
||||
int ast_context_ignorepats_count(const struct ast_context *con);
|
||||
const struct ast_ignorepat *ast_context_ignorepats_get(const struct ast_context *con, int idx);
|
||||
int ast_context_switches_count(const struct ast_context *con);
|
||||
const struct ast_sw *ast_context_switches_get(const struct ast_context *con, int idx);
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
|
|
194
main/pbx.c
194
main/pbx.c
|
@ -255,16 +255,6 @@ struct ast_exten {
|
|||
char stuff[0];
|
||||
};
|
||||
|
||||
/*! \brief ast_sw: Switch statement in extensions.conf */
|
||||
struct ast_sw {
|
||||
char *name;
|
||||
const char *registrar; /*!< Registrar */
|
||||
char *data; /*!< Data load */
|
||||
int eval;
|
||||
AST_LIST_ENTRY(ast_sw) list;
|
||||
char stuff[0];
|
||||
};
|
||||
|
||||
/*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
|
||||
struct match_char
|
||||
{
|
||||
|
@ -297,10 +287,10 @@ struct ast_context {
|
|||
struct ast_context *next; /*!< Link them together */
|
||||
struct ast_includes includes; /*!< Include other contexts */
|
||||
struct ast_ignorepats ignorepats; /*!< Patterns for which to continue playing dialtone */
|
||||
struct ast_sws alts; /*!< Alternative switches */
|
||||
char *registrar; /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
|
||||
int refcount; /*!< each module that would have created this context should inc/dec this as appropriate */
|
||||
int autohints; /*!< Whether autohints support is enabled or not */
|
||||
AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
|
||||
ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
|
||||
char name[0]; /*!< Name of the context */
|
||||
};
|
||||
|
@ -2375,10 +2365,10 @@ struct fake_context /* this struct is purely for matching in the hashtab */
|
|||
struct ast_context *next;
|
||||
struct ast_includes includes;
|
||||
struct ast_ignorepats ignorepats;
|
||||
struct ast_sws alts;
|
||||
const char *registrar;
|
||||
int refcount;
|
||||
int autohints;
|
||||
AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
|
||||
ast_mutex_t macrolock;
|
||||
char name[256];
|
||||
};
|
||||
|
@ -2433,7 +2423,6 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
int x, res;
|
||||
struct ast_context *tmp = NULL;
|
||||
struct ast_exten *e = NULL, *eroot = NULL;
|
||||
struct ast_sw *sw = NULL;
|
||||
struct ast_exten pattern = {NULL, };
|
||||
struct scoreboard score = {0, };
|
||||
struct ast_str *tmpdata = NULL;
|
||||
|
@ -2657,23 +2646,28 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
}
|
||||
|
||||
/* Check alternative switches */
|
||||
AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
|
||||
struct ast_switch *asw = pbx_findswitch(sw->name);
|
||||
for (idx = 0; idx < ast_context_switches_count(tmp); idx++) {
|
||||
const struct ast_sw *sw = ast_context_switches_get(tmp, idx);
|
||||
struct ast_switch *asw = pbx_findswitch(ast_get_switch_name(sw));
|
||||
ast_switch_f *aswf = NULL;
|
||||
char *datap;
|
||||
const char *datap;
|
||||
|
||||
if (!asw) {
|
||||
ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
|
||||
ast_log(LOG_WARNING, "No such switch '%s'\n", ast_get_switch_name(sw));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Substitute variables now */
|
||||
if (sw->eval) {
|
||||
if (ast_get_switch_eval(sw)) {
|
||||
if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
|
||||
ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
|
||||
continue;
|
||||
}
|
||||
pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
|
||||
pbx_substitute_variables_helper(chan, ast_get_switch_data(sw),
|
||||
ast_str_buffer(tmpdata), ast_str_size(tmpdata));
|
||||
datap = ast_str_buffer(tmpdata);
|
||||
} else {
|
||||
datap = ast_get_switch_data(sw);
|
||||
}
|
||||
|
||||
/* equivalent of extension_match_core() at the switch level */
|
||||
|
@ -2683,7 +2677,6 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
|||
aswf = asw->matchmore;
|
||||
else /* action == E_MATCH */
|
||||
aswf = asw->exists;
|
||||
datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
|
||||
if (!aswf)
|
||||
res = 0;
|
||||
else {
|
||||
|
@ -4819,24 +4812,29 @@ int ast_context_remove_switch(const char *context, const char *sw, const char *d
|
|||
*/
|
||||
int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
|
||||
{
|
||||
struct ast_sw *i;
|
||||
int idx;
|
||||
int ret = -1;
|
||||
|
||||
ast_wrlock_context(con);
|
||||
|
||||
/* walk switches */
|
||||
AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
|
||||
if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
|
||||
(!registrar || !strcmp(i->registrar, registrar))) {
|
||||
for (idx = 0; idx < ast_context_switches_count(con); idx++) {
|
||||
struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
|
||||
|
||||
if (!strcmp(ast_get_switch_name(i), sw) &&
|
||||
!strcmp(ast_get_switch_data(i), data) &&
|
||||
(!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
|
||||
|
||||
/* found, remove from list */
|
||||
ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
|
||||
AST_LIST_REMOVE_CURRENT(list);
|
||||
ast_free(i); /* free switch and return */
|
||||
AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
|
||||
|
||||
/* free switch and return */
|
||||
sw_free(i);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AST_LIST_TRAVERSE_SAFE_END;
|
||||
|
||||
ast_unlock_context(con);
|
||||
|
||||
|
@ -5517,8 +5515,9 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
|
|||
}
|
||||
}
|
||||
if (!rinclude) {
|
||||
struct ast_sw *sw = NULL;
|
||||
while ( (sw = ast_walk_context_switches(c, sw)) ) {
|
||||
for (idx = 0; idx < ast_context_switches_count(c); idx++) {
|
||||
const struct ast_sw *sw = ast_context_switches_get(c, idx);
|
||||
|
||||
snprintf(buf, sizeof(buf), "'%s/%s'",
|
||||
ast_get_switch_name(sw),
|
||||
ast_get_switch_data(sw));
|
||||
|
@ -5836,8 +5835,9 @@ static int manager_show_dialplan_helper(struct mansession *s, const struct messa
|
|||
}
|
||||
}
|
||||
if (!rinclude) {
|
||||
struct ast_sw *sw = NULL;
|
||||
while ( (sw = ast_walk_context_switches(c, sw)) ) {
|
||||
for (idx = 0; idx < ast_context_switches_count(c); idx++) {
|
||||
const struct ast_sw *sw = ast_context_switches_get(c, idx);
|
||||
|
||||
if (!dpc->total_items++)
|
||||
manager_dpsendack(s, m);
|
||||
astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
|
||||
|
@ -6087,6 +6087,7 @@ struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts,
|
|||
tmp->registrar = ast_strdup(registrar);
|
||||
AST_VECTOR_INIT(&tmp->includes, 0);
|
||||
AST_VECTOR_INIT(&tmp->ignorepats, 0);
|
||||
AST_VECTOR_INIT(&tmp->alts, 0);
|
||||
tmp->refcount = 1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
|
||||
|
@ -6138,7 +6139,6 @@ AST_LIST_HEAD_NOLOCK(store_hints, store_hint);
|
|||
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
|
||||
{
|
||||
int idx;
|
||||
struct ast_sw *sw;
|
||||
|
||||
ast_verb(3, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
|
||||
/* copy in the includes, switches, and ignorepats */
|
||||
|
@ -6153,9 +6153,12 @@ static void context_merge_incls_swits_igps_other_registrars(struct ast_context *
|
|||
}
|
||||
|
||||
/* walk through switches */
|
||||
for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
|
||||
if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
|
||||
for (idx = 0; idx < ast_context_switches_count(old); idx++) {
|
||||
const struct ast_sw *sw = ast_context_switches_get(old, idx);
|
||||
|
||||
if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
|
||||
continue; /* not mine */
|
||||
}
|
||||
ast_context_add_switch2(new, ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_eval(sw), ast_get_switch_registrar(sw));
|
||||
}
|
||||
|
||||
|
@ -6622,43 +6625,24 @@ int ast_context_add_switch(const char *context, const char *sw, const char *data
|
|||
int ast_context_add_switch2(struct ast_context *con, const char *value,
|
||||
const char *data, int eval, const char *registrar)
|
||||
{
|
||||
int idx;
|
||||
struct ast_sw *new_sw;
|
||||
struct ast_sw *i;
|
||||
int length;
|
||||
char *p;
|
||||
|
||||
length = sizeof(struct ast_sw);
|
||||
length += strlen(value) + 1;
|
||||
if (data)
|
||||
length += strlen(data);
|
||||
length++;
|
||||
|
||||
/* allocate new sw structure ... */
|
||||
if (!(new_sw = ast_calloc(1, length)))
|
||||
if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
|
||||
return -1;
|
||||
/* ... fill in this structure ... */
|
||||
p = new_sw->stuff;
|
||||
new_sw->name = p;
|
||||
strcpy(new_sw->name, value);
|
||||
p += strlen(value) + 1;
|
||||
new_sw->data = p;
|
||||
if (data) {
|
||||
strcpy(new_sw->data, data);
|
||||
p += strlen(data) + 1;
|
||||
} else {
|
||||
strcpy(new_sw->data, "");
|
||||
p++;
|
||||
}
|
||||
new_sw->eval = eval;
|
||||
new_sw->registrar = registrar;
|
||||
|
||||
/* ... try to lock this context ... */
|
||||
ast_wrlock_context(con);
|
||||
|
||||
/* ... go to last sw and check if context is already swd too... */
|
||||
AST_LIST_TRAVERSE(&con->alts, i, list) {
|
||||
if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
|
||||
ast_free(new_sw);
|
||||
for (idx = 0; idx < ast_context_switches_count(con); idx++) {
|
||||
const struct ast_sw *i = ast_context_switches_get(con, idx);
|
||||
|
||||
if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
|
||||
!strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
|
||||
sw_free(new_sw);
|
||||
ast_unlock_context(con);
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
|
@ -6666,9 +6650,10 @@ int ast_context_add_switch2(struct ast_context *con, const char *value,
|
|||
}
|
||||
|
||||
/* ... sw new context into context list, unlock, return */
|
||||
AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
|
||||
AST_VECTOR_APPEND(&con->alts, new_sw);
|
||||
|
||||
ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
|
||||
ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
|
||||
ast_get_switch_name(new_sw), ast_get_switch_data(new_sw), ast_get_context_name(con));
|
||||
|
||||
ast_unlock_context(con);
|
||||
|
||||
|
@ -7775,7 +7760,6 @@ int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const cha
|
|||
|
||||
static void __ast_internal_context_destroy( struct ast_context *con)
|
||||
{
|
||||
struct ast_sw *sw;
|
||||
struct ast_exten *e, *el, *en;
|
||||
struct ast_context *tmp = con;
|
||||
|
||||
|
@ -7787,6 +7771,10 @@ static void __ast_internal_context_destroy( struct ast_context *con)
|
|||
AST_VECTOR_CALLBACK_VOID(&tmp->ignorepats, ignorepat_free);
|
||||
AST_VECTOR_FREE(&tmp->ignorepats);
|
||||
|
||||
/* Free switches */
|
||||
AST_VECTOR_CALLBACK_VOID(&tmp->alts, sw_free);
|
||||
AST_VECTOR_FREE(&tmp->alts);
|
||||
|
||||
if (tmp->registrar)
|
||||
ast_free(tmp->registrar);
|
||||
|
||||
|
@ -7798,8 +7786,6 @@ static void __ast_internal_context_destroy( struct ast_context *con)
|
|||
if (tmp->pattern_tree)
|
||||
destroy_pattern_tree(tmp->pattern_tree);
|
||||
|
||||
while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
|
||||
ast_free(sw);
|
||||
for (e = tmp->root; e;) {
|
||||
for (en = e->peer; en;) {
|
||||
el = en;
|
||||
|
@ -7846,7 +7832,6 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
|
|||
/* then search thru and remove any extens that match registrar. */
|
||||
struct ast_hashtab_iter *exten_iter;
|
||||
struct ast_hashtab_iter *prio_iter;
|
||||
struct ast_sw *sw = NULL;
|
||||
int idx;
|
||||
|
||||
/* remove any ignorepats whose registrar matches */
|
||||
|
@ -7868,13 +7853,14 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
|
|||
}
|
||||
}
|
||||
/* remove any switches whose registrar matches */
|
||||
AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
|
||||
if (strcmp(sw->registrar,registrar) == 0) {
|
||||
AST_LIST_REMOVE_CURRENT(list);
|
||||
ast_free(sw);
|
||||
for (idx = ast_context_switches_count(tmp) - 1; idx >= 0; idx--) {
|
||||
struct ast_sw *sw = AST_VECTOR_GET(&tmp->alts, idx);
|
||||
|
||||
if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
|
||||
AST_VECTOR_REMOVE_ORDERED(&tmp->alts, idx);
|
||||
sw_free(sw);
|
||||
}
|
||||
}
|
||||
AST_LIST_TRAVERSE_SAFE_END;
|
||||
|
||||
if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
|
||||
exten_iter = ast_hashtab_start_traversal(tmp->root_table);
|
||||
|
@ -7925,7 +7911,7 @@ void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *context
|
|||
/* delete the context if it's registrar matches, is empty, has refcount of 1, */
|
||||
/* it's not empty, if it has includes, ignorepats, or switches that are registered from
|
||||
another registrar. It's not empty if there are any extensions */
|
||||
if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !ast_context_ignorepats_count(tmp) && !ast_context_includes_count(tmp) && AST_LIST_EMPTY(&tmp->alts)) {
|
||||
if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !ast_context_ignorepats_count(tmp) && !ast_context_includes_count(tmp) && !ast_context_switches_count(tmp)) {
|
||||
ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
|
||||
ast_hashtab_remove_this_object(contexttab, tmp);
|
||||
|
||||
|
@ -8364,26 +8350,6 @@ void *ast_get_extension_app_data(struct ast_exten *e)
|
|||
return e ? e->data : NULL;
|
||||
}
|
||||
|
||||
const char *ast_get_switch_name(struct ast_sw *sw)
|
||||
{
|
||||
return sw ? sw->name : NULL;
|
||||
}
|
||||
|
||||
const char *ast_get_switch_data(struct ast_sw *sw)
|
||||
{
|
||||
return sw ? sw->data : NULL;
|
||||
}
|
||||
|
||||
int ast_get_switch_eval(struct ast_sw *sw)
|
||||
{
|
||||
return sw->eval;
|
||||
}
|
||||
|
||||
const char *ast_get_switch_registrar(struct ast_sw *sw)
|
||||
{
|
||||
return sw ? sw->registrar : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walking functions ...
|
||||
*/
|
||||
|
@ -8401,13 +8367,43 @@ struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
|
|||
return exten->next;
|
||||
}
|
||||
|
||||
struct ast_sw *ast_walk_context_switches(struct ast_context *con,
|
||||
struct ast_sw *sw)
|
||||
const struct ast_sw *ast_walk_context_switches(const struct ast_context *con,
|
||||
const struct ast_sw *sw)
|
||||
{
|
||||
if (!sw)
|
||||
return con ? AST_LIST_FIRST(&con->alts) : NULL;
|
||||
else
|
||||
return AST_LIST_NEXT(sw, list);
|
||||
if (sw) {
|
||||
int idx;
|
||||
int next = 0;
|
||||
|
||||
for (idx = 0; idx < ast_context_switches_count(con); idx++) {
|
||||
const struct ast_sw *s = ast_context_switches_get(con, idx);
|
||||
|
||||
if (next) {
|
||||
return s;
|
||||
}
|
||||
|
||||
if (sw == s) {
|
||||
next = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ast_context_switches_count(con)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_context_switches_get(con, 0);
|
||||
}
|
||||
|
||||
int ast_context_switches_count(const struct ast_context *con)
|
||||
{
|
||||
return AST_VECTOR_SIZE(&con->alts);
|
||||
}
|
||||
|
||||
const struct ast_sw *ast_context_switches_get(const struct ast_context *con, int idx)
|
||||
{
|
||||
return AST_VECTOR_GET(&con->alts, idx);
|
||||
}
|
||||
|
||||
struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
|
||||
|
|
|
@ -49,6 +49,12 @@ void include_free(struct ast_include *inc);
|
|||
int include_valid(const struct ast_include *inc);
|
||||
const char *include_rname(const struct ast_include *inc);
|
||||
|
||||
/*! pbx_sw.c */
|
||||
struct ast_sw;
|
||||
AST_VECTOR(ast_sws, struct ast_sw *);
|
||||
struct ast_sw *sw_alloc(const char *value, const char *data, int eval, const char *registrar);
|
||||
void sw_free(struct ast_sw *sw);
|
||||
|
||||
/*! pbx_builtins.c functions needed by pbx.c */
|
||||
int indicate_congestion(struct ast_channel *, const char *);
|
||||
int indicate_busy(struct ast_channel *, const char *);
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2016, CFWare, LLC
|
||||
*
|
||||
* Corey Farrell <git@cfware.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Dialplan switch routines.
|
||||
*
|
||||
* \author Corey Farrell <git@cfware.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_REGISTER_FILE()
|
||||
|
||||
#include "asterisk/_private.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "pbx_private.h"
|
||||
|
||||
/*! \brief ast_sw: Switch statement in extensions.conf */
|
||||
struct ast_sw {
|
||||
const char *name;
|
||||
/*! Registrar */
|
||||
const char *registrar;
|
||||
/*! Data load */
|
||||
const char *data;
|
||||
int eval;
|
||||
AST_LIST_ENTRY(ast_sw) list;
|
||||
char stuff[0];
|
||||
};
|
||||
|
||||
const char *ast_get_switch_name(const struct ast_sw *sw)
|
||||
{
|
||||
return sw ? sw->name : NULL;
|
||||
}
|
||||
|
||||
const char *ast_get_switch_data(const struct ast_sw *sw)
|
||||
{
|
||||
return sw ? sw->data : NULL;
|
||||
}
|
||||
|
||||
int ast_get_switch_eval(const struct ast_sw *sw)
|
||||
{
|
||||
return sw->eval;
|
||||
}
|
||||
|
||||
const char *ast_get_switch_registrar(const struct ast_sw *sw)
|
||||
{
|
||||
return sw ? sw->registrar : NULL;
|
||||
}
|
||||
|
||||
struct ast_sw *sw_alloc(const char *value, const char *data, int eval, const char *registrar)
|
||||
{
|
||||
struct ast_sw *new_sw;
|
||||
int length;
|
||||
char *p;
|
||||
|
||||
if (!data) {
|
||||
data = "";
|
||||
}
|
||||
length = sizeof(struct ast_sw);
|
||||
length += strlen(value) + 1;
|
||||
length += strlen(data) + 1;
|
||||
|
||||
/* allocate new sw structure ... */
|
||||
if (!(new_sw = ast_calloc(1, length))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ... fill in this structure ... */
|
||||
p = new_sw->stuff;
|
||||
new_sw->name = p;
|
||||
strcpy(p, value);
|
||||
|
||||
p += strlen(value) + 1;
|
||||
new_sw->data = p;
|
||||
strcpy(p, data);
|
||||
|
||||
new_sw->eval = eval;
|
||||
new_sw->registrar = registrar;
|
||||
|
||||
return new_sw;
|
||||
}
|
||||
|
||||
void sw_free(struct ast_sw *sw)
|
||||
{
|
||||
ast_free(sw);
|
||||
}
|
||||
|
|
@ -928,7 +928,6 @@ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct a
|
|||
int context_header_written = 0;
|
||||
struct ast_exten *ext, *last_written_e = NULL;
|
||||
int idx;
|
||||
struct ast_sw *sw;
|
||||
|
||||
/* try to lock context and fireout all info */
|
||||
if (ast_rdlock_context(c)) { /* lock failure */
|
||||
|
@ -1016,7 +1015,9 @@ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct a
|
|||
}
|
||||
|
||||
/* walk through switches */
|
||||
for (sw = NULL; (sw = ast_walk_context_switches(c, sw)) ; ) {
|
||||
for (idx = 0; idx < ast_context_switches_count(c); idx++) {
|
||||
const struct ast_sw *sw = ast_context_switches_get(c, idx);
|
||||
|
||||
if (strcmp(ast_get_switch_registrar(sw), registrar) != 0)
|
||||
continue; /* not mine */
|
||||
PUT_CTX_HDR;
|
||||
|
@ -1024,8 +1025,9 @@ static char *handle_cli_dialplan_save(struct ast_cli_entry *e, int cmd, struct a
|
|||
ast_get_switch_name(sw), ast_get_switch_data(sw));
|
||||
}
|
||||
|
||||
if (ast_walk_context_switches(c, NULL))
|
||||
if (ast_context_switches_count(c)) {
|
||||
fprintf(output, "\n");
|
||||
}
|
||||
|
||||
/* fireout ignorepats ... */
|
||||
for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
|
||||
|
|
|
@ -4410,7 +4410,7 @@ static int context_used(struct ael_extension *exten_list, struct ast_context *co
|
|||
{
|
||||
struct ael_extension *exten;
|
||||
/* Check the simple elements first */
|
||||
if (ast_walk_context_extensions(context, NULL) || ast_context_includes_count(context) || ast_context_ignorepats_count(context) || ast_walk_context_switches(context, NULL)) {
|
||||
if (ast_walk_context_extensions(context, NULL) || ast_context_includes_count(context) || ast_context_ignorepats_count(context) || ast_context_switches_count(context)) {
|
||||
return 1;
|
||||
}
|
||||
for (exten = exten_list; exten; exten = exten->next_exten) {
|
||||
|
|
|
@ -670,12 +670,6 @@ const struct ast_include *ast_walk_context_includes(const struct ast_context *co
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
|
||||
struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
||||
struct ast_context *bypass,
|
||||
struct pbx_find_info *q,
|
||||
|
|
|
@ -4448,6 +4448,19 @@ struct ast_sw *localized_walk_context_switches(struct ast_context *con,
|
|||
return ast_walk_context_switches(con, sw);
|
||||
}
|
||||
|
||||
int ast_context_switches_count(struct ast_context *con);
|
||||
int ast_context_switches_count(struct ast_context *con)
|
||||
{
|
||||
int c = 0;
|
||||
struct ast_sw *sw = NULL;
|
||||
|
||||
while ((sw = ast_walk_context_switches(con, sw))) {
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static struct ast_context *ast_context_find(const char *name);
|
||||
|
||||
|
|
Loading…
Reference in New Issue