While Loop Implementation. More...
#include "asterisk.h"#include "asterisk/pbx.h"#include "asterisk/module.h"#include "asterisk/channel.h"
Go to the source code of this file.
Defines | |
| #define | VAR_SIZE 64 |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | _while_exec (struct ast_channel *chan, void *data, int end) |
| static int | find_matching_endwhile (struct ast_channel *chan) |
| static struct ast_exten * | find_matching_priority (struct ast_context *c, const char *exten, int priority, const char *callerid) |
| static const char * | get_index (struct ast_channel *chan, const char *prefix, int idx) |
| static int | load_module (void) |
| static int | unload_module (void) |
| static int | while_continue_exec (struct ast_channel *chan, void *data) |
| static int | while_end_exec (struct ast_channel *chan, void *data) |
| static int | while_exit_exec (struct ast_channel *chan, void *data) |
| static int | while_start_exec (struct ast_channel *chan, void *data) |
Variables | |
| static struct ast_module_info __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "While Loops and Conditional Execution" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static char * | continue_app = "ContinueWhile" |
| static char * | exit_app = "ExitWhile" |
| static char * | start_app = "While" |
| static char * | stop_app = "EndWhile" |
While Loop Implementation.
Definition in file app_while.c.
| #define VAR_SIZE 64 |
Definition at line 103 of file app_while.c.
Referenced by _while_exec(), and get_index().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 354 of file app_while.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 354 of file app_while.c.
| static int _while_exec | ( | struct ast_channel * | chan, |
| void * | data, | ||
| int | end | ||
| ) | [static] |
Definition at line 189 of file app_while.c.
References ast_channel_lock, ast_channel_unlock, ast_log(), ast_parseable_goto(), ast_strdupa, ast_verb, ast_waitfordigit(), ast_channel::context, ast_channel::exten, find_matching_endwhile(), get_index(), ast_exten::label, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), prefix, ast_channel::priority, and VAR_SIZE.
Referenced by while_end_exec(), while_exit_exec(), and while_start_exec().
{
int res=0;
const char *while_pri = NULL;
char *my_name = NULL;
const char *condition = NULL, *label = NULL;
char varname[VAR_SIZE], end_varname[VAR_SIZE];
const char *prefix = "WHILE";
size_t size=0;
int used_index_i = -1, x=0;
char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
if (!chan) {
/* huh ? */
return -1;
}
#if 0
/* dont want run away loops if the chan isn't even up
this is up for debate since it slows things down a tad ......
Debate is over... this prevents While/EndWhile from working
within the "h" extension. Not good.
*/
if (ast_waitfordigit(chan,1) < 0)
return -1;
#endif
for (x=0;;x++) {
if (get_index(chan, prefix, x)) {
used_index_i = x;
} else
break;
}
snprintf(used_index, VAR_SIZE, "%d", used_index_i);
snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
if (!end)
condition = ast_strdupa(data);
size = strlen(chan->context) + strlen(chan->exten) + 32;
my_name = alloca(size);
memset(my_name, 0, size);
snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
ast_channel_lock(chan);
if (end) {
label = used_index;
} else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
label = new_index;
pbx_builtin_setvar_helper(chan, my_name, label);
}
snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
while_pri = ast_strdupa(while_pri);
snprintf(end_varname,VAR_SIZE,"END_%s",varname);
}
ast_channel_unlock(chan);
if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
/* Condition Met (clean up helper vars) */
const char *goto_str;
pbx_builtin_setvar_helper(chan, varname, NULL);
pbx_builtin_setvar_helper(chan, my_name, NULL);
snprintf(end_varname,VAR_SIZE,"END_%s",varname);
ast_channel_lock(chan);
if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
ast_parseable_goto(chan, goto_str);
pbx_builtin_setvar_helper(chan, end_varname, NULL);
} else {
int pri = find_matching_endwhile(chan);
if (pri > 0) {
ast_verb(3, "Jumping to priority %d\n", pri);
chan->priority = pri;
} else {
ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
}
}
ast_channel_unlock(chan);
return res;
}
if (!end && !while_pri) {
char *goto_str;
size = strlen(chan->context) + strlen(chan->exten) + 32;
goto_str = alloca(size);
memset(goto_str, 0, size);
snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
pbx_builtin_setvar_helper(chan, varname, goto_str);
}
else if (end && while_pri) {
/* END of loop */
snprintf(end_varname, VAR_SIZE, "END_%s", varname);
if (! pbx_builtin_getvar_helper(chan, end_varname)) {
char *goto_str;
size = strlen(chan->context) + strlen(chan->exten) + 32;
goto_str = alloca(size);
memset(goto_str, 0, size);
snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
pbx_builtin_setvar_helper(chan, end_varname, goto_str);
}
ast_parseable_goto(chan, while_pri);
}
return res;
}
| static int find_matching_endwhile | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 148 of file app_while.c.
References ast_get_context_name(), ast_get_extension_app(), ast_log(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, find_matching_priority(), LOG_ERROR, and ast_channel::priority.
Referenced by _while_exec().
{
struct ast_context *c;
int res=-1;
if (ast_rdlock_contexts()) {
ast_log(LOG_ERROR, "Failed to lock contexts list\n");
return -1;
}
for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
struct ast_exten *e;
if (!ast_rdlock_context(c)) {
if (!strcmp(ast_get_context_name(c), chan->context)) {
/* This is the matching context we want */
int cur_priority = chan->priority + 1, level=1;
for (e = find_matching_priority(c, chan->exten, cur_priority, chan->cid.cid_num); e; e = find_matching_priority(c, chan->exten, ++cur_priority, chan->cid.cid_num)) {
if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
level++;
} else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
level--;
}
if (level == 0) {
res = cur_priority;
break;
}
}
}
ast_unlock_context(c);
if (res > 0) {
break;
}
}
}
ast_unlock_contexts();
return res;
}
| static struct ast_exten* find_matching_priority | ( | struct ast_context * | c, |
| const char * | exten, | ||
| int | priority, | ||
| const char * | callerid | ||
| ) | [static, read] |
Definition at line 113 of file app_while.c.
References ast_extension_match(), ast_get_context_name(), ast_get_extension_cidmatch(), ast_get_extension_matchcid(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_include_name(), ast_walk_context_extensions(), ast_walk_context_includes(), ast_walk_contexts(), and ast_walk_extension_priorities().
Referenced by find_matching_endwhile().
{
struct ast_exten *e;
struct ast_include *i;
struct ast_context *c2;
for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
if (ast_extension_match(ast_get_extension_name(e), exten)) {
int needmatch = ast_get_extension_matchcid(e);
if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
(!needmatch)) {
/* This is the matching extension we want */
struct ast_exten *p;
for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
if (priority != ast_get_extension_priority(p))
continue;
return p;
}
}
}
}
/* No match; run through includes */
for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
e = find_matching_priority(c2, exten, priority, callerid);
if (e)
return e;
}
}
}
return NULL;
}
| static const char* get_index | ( | struct ast_channel * | chan, |
| const char * | prefix, | ||
| int | idx | ||
| ) | [static] |
Definition at line 106 of file app_while.c.
References pbx_builtin_getvar_helper(), and VAR_SIZE.
Referenced by _while_exec(), and while_continue_exec().
{
char varname[VAR_SIZE];
snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
return pbx_builtin_getvar_helper(chan, varname);
}
| static int load_module | ( | void | ) | [static] |
Definition at line 342 of file app_while.c.
References ast_register_application_xml, while_continue_exec(), while_end_exec(), while_exit_exec(), and while_start_exec().
{
int res;
res = ast_register_application_xml(start_app, while_start_exec);
res |= ast_register_application_xml(stop_app, while_end_exec);
res |= ast_register_application_xml(exit_app, while_exit_exec);
res |= ast_register_application_xml(continue_app, while_continue_exec);
return res;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 330 of file app_while.c.
References ast_unregister_application().
{
int res;
res = ast_unregister_application(start_app);
res |= ast_unregister_application(stop_app);
res |= ast_unregister_application(exit_app);
res |= ast_unregister_application(continue_app);
return res;
}
| static int while_continue_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Definition at line 311 of file app_while.c.
References ast_parseable_goto(), get_index(), and prefix.
Referenced by load_module().
{
int x;
const char *prefix = "WHILE", *while_pri=NULL;
for (x = 0; ; x++) {
const char *tmp = get_index(chan, prefix, x);
if (tmp)
while_pri = tmp;
else
break;
}
if (while_pri)
ast_parseable_goto(chan, while_pri);
return 0;
}
| static int while_end_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Definition at line 303 of file app_while.c.
References _while_exec().
Referenced by load_module().
{
return _while_exec(chan, data, 1);
}
| static int while_exit_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Definition at line 307 of file app_while.c.
References _while_exec().
Referenced by load_module().
{
return _while_exec(chan, data, 2);
}
| static int while_start_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Definition at line 299 of file app_while.c.
References _while_exec().
Referenced by load_module().
{
return _while_exec(chan, data, 0);
}
struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "While Loops and Conditional Execution" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static] |
Definition at line 354 of file app_while.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 354 of file app_while.c.
char* continue_app = "ContinueWhile" [static] |
Definition at line 101 of file app_while.c.
char* exit_app = "ExitWhile" [static] |
Definition at line 100 of file app_while.c.
char* start_app = "While" [static] |
Definition at line 98 of file app_while.c.
char* stop_app = "EndWhile" [static] |
Definition at line 99 of file app_while.c.