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, const char *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, const char *data) |
| static int | while_end_exec (struct ast_channel *chan, const char *data) |
| static int | while_exit_exec (struct ast_channel *chan, const char *data) |
| static int | while_start_exec (struct ast_channel *chan, const char *data) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "While Loops and Conditional Execution" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| 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 107 of file app_while.c.
Referenced by _while_exec(), and get_index().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 362 of file app_while.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 362 of file app_while.c.
| static int _while_exec | ( | struct ast_channel * | chan, |
| const char * | data, | ||
| int | end | ||
| ) | [static] |
Definition at line 197 of file app_while.c.
References ast_alloca, ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_priority(), ast_channel_priority_set(), ast_channel_unlock, ast_log(), ast_parseable_goto(), ast_verb, ast_waitfordigit(), find_matching_endwhile(), get_index(), ast_exten::label, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), prefix, 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
/* don't 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(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
my_name = ast_alloca(size);
memset(my_name, 0, size);
snprintf(my_name, size, "%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
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);
ast_channel_priority_set(chan, pri);
} else {
ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
}
}
ast_channel_unlock(chan);
return res;
}
if (!end && !while_pri) {
char *goto_str;
size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
goto_str = ast_alloca(size);
memset(goto_str, 0, size);
snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
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(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
goto_str = ast_alloca(size);
memset(goto_str, 0, size);
snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan)+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 152 of file app_while.c.
References ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_priority(), 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(), find_matching_priority(), LOG_ERROR, and S_COR.
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), ast_channel_context(chan))) {
/* This is the matching context we want */
int cur_priority = ast_channel_priority(chan) + 1, level=1;
for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
e;
e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
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 117 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 110 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 350 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 338 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, |
| const char * | data | ||
| ) | [static] |
Definition at line 319 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, |
| const char * | data | ||
| ) | [static] |
Definition at line 311 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, |
| const char * | data | ||
| ) | [static] |
Definition at line 315 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, |
| const char * | data | ||
| ) | [static] |
Definition at line 307 of file app_while.c.
References _while_exec().
Referenced by load_module().
{
return _while_exec(chan, data, 0);
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "While Loops and Conditional Execution" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 362 of file app_while.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 362 of file app_while.c.
char* continue_app = "ContinueWhile" [static] |
Definition at line 105 of file app_while.c.
char* exit_app = "ExitWhile" [static] |
Definition at line 104 of file app_while.c.
char* start_app = "While" [static] |
Definition at line 102 of file app_while.c.
char* stop_app = "EndWhile" [static] |
Definition at line 103 of file app_while.c.