#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 = "88eaa8f5c1bd988bedd71113385e0886" , .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" |
Definition in file app_while.c.
#define VAR_SIZE 64 |
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_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(), 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().
00198 { 00199 int res=0; 00200 const char *while_pri = NULL; 00201 char *my_name = NULL; 00202 const char *condition = NULL, *label = NULL; 00203 char varname[VAR_SIZE], end_varname[VAR_SIZE]; 00204 const char *prefix = "WHILE"; 00205 size_t size=0; 00206 int used_index_i = -1, x=0; 00207 char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0"; 00208 00209 if (!chan) { 00210 /* huh ? */ 00211 return -1; 00212 } 00213 00214 #if 0 00215 /* don't want run away loops if the chan isn't even up 00216 this is up for debate since it slows things down a tad ...... 00217 00218 Debate is over... this prevents While/EndWhile from working 00219 within the "h" extension. Not good. 00220 */ 00221 if (ast_waitfordigit(chan,1) < 0) 00222 return -1; 00223 #endif 00224 00225 for (x=0;;x++) { 00226 if (get_index(chan, prefix, x)) { 00227 used_index_i = x; 00228 } else 00229 break; 00230 } 00231 00232 snprintf(used_index, VAR_SIZE, "%d", used_index_i); 00233 snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1); 00234 00235 if (!end) 00236 condition = ast_strdupa(data); 00237 00238 size = strlen(chan->context) + strlen(chan->exten) + 32; 00239 my_name = alloca(size); 00240 memset(my_name, 0, size); 00241 snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority); 00242 00243 ast_channel_lock(chan); 00244 if (end) { 00245 label = used_index; 00246 } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) { 00247 label = new_index; 00248 pbx_builtin_setvar_helper(chan, my_name, label); 00249 } 00250 snprintf(varname, VAR_SIZE, "%s_%s", prefix, label); 00251 if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) { 00252 while_pri = ast_strdupa(while_pri); 00253 snprintf(end_varname,VAR_SIZE,"END_%s",varname); 00254 } 00255 ast_channel_unlock(chan); 00256 00257 00258 if ((!end && !pbx_checkcondition(condition)) || (end == 2)) { 00259 /* Condition Met (clean up helper vars) */ 00260 const char *goto_str; 00261 pbx_builtin_setvar_helper(chan, varname, NULL); 00262 pbx_builtin_setvar_helper(chan, my_name, NULL); 00263 snprintf(end_varname,VAR_SIZE,"END_%s",varname); 00264 ast_channel_lock(chan); 00265 if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) { 00266 ast_parseable_goto(chan, goto_str); 00267 pbx_builtin_setvar_helper(chan, end_varname, NULL); 00268 } else { 00269 int pri = find_matching_endwhile(chan); 00270 if (pri > 0) { 00271 ast_verb(3, "Jumping to priority %d\n", pri); 00272 chan->priority = pri; 00273 } else { 00274 ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority); 00275 } 00276 } 00277 ast_channel_unlock(chan); 00278 return res; 00279 } 00280 00281 if (!end && !while_pri) { 00282 char *goto_str; 00283 size = strlen(chan->context) + strlen(chan->exten) + 32; 00284 goto_str = alloca(size); 00285 memset(goto_str, 0, size); 00286 snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority); 00287 pbx_builtin_setvar_helper(chan, varname, goto_str); 00288 } 00289 00290 else if (end && while_pri) { 00291 /* END of loop */ 00292 snprintf(end_varname, VAR_SIZE, "END_%s", varname); 00293 if (! pbx_builtin_getvar_helper(chan, end_varname)) { 00294 char *goto_str; 00295 size = strlen(chan->context) + strlen(chan->exten) + 32; 00296 goto_str = alloca(size); 00297 memset(goto_str, 0, size); 00298 snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1); 00299 pbx_builtin_setvar_helper(chan, end_varname, goto_str); 00300 } 00301 ast_parseable_goto(chan, while_pri); 00302 } 00303 00304 return res; 00305 }
static int find_matching_endwhile | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 152 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::caller, ast_channel::context, ast_channel::exten, find_matching_priority(), ast_party_caller::id, LOG_ERROR, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by _while_exec().
00153 { 00154 struct ast_context *c; 00155 int res=-1; 00156 00157 if (ast_rdlock_contexts()) { 00158 ast_log(LOG_ERROR, "Failed to lock contexts list\n"); 00159 return -1; 00160 } 00161 00162 for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) { 00163 struct ast_exten *e; 00164 00165 if (!ast_rdlock_context(c)) { 00166 if (!strcmp(ast_get_context_name(c), chan->context)) { 00167 /* This is the matching context we want */ 00168 int cur_priority = chan->priority + 1, level=1; 00169 00170 for (e = find_matching_priority(c, chan->exten, cur_priority, 00171 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)); 00172 e; 00173 e = find_matching_priority(c, chan->exten, ++cur_priority, 00174 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 00175 if (!strcasecmp(ast_get_extension_app(e), "WHILE")) { 00176 level++; 00177 } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) { 00178 level--; 00179 } 00180 00181 if (level == 0) { 00182 res = cur_priority; 00183 break; 00184 } 00185 } 00186 } 00187 ast_unlock_context(c); 00188 if (res > 0) { 00189 break; 00190 } 00191 } 00192 } 00193 ast_unlock_contexts(); 00194 return res; 00195 }
static struct ast_exten* find_matching_priority | ( | struct ast_context * | c, | |
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) | [static] |
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(), ast_walk_extension_priorities(), and find_matching_priority().
00118 { 00119 struct ast_exten *e; 00120 struct ast_include *i; 00121 struct ast_context *c2; 00122 00123 for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) { 00124 if (ast_extension_match(ast_get_extension_name(e), exten)) { 00125 int needmatch = ast_get_extension_matchcid(e); 00126 if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) || 00127 (!needmatch)) { 00128 /* This is the matching extension we want */ 00129 struct ast_exten *p; 00130 for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) { 00131 if (priority != ast_get_extension_priority(p)) 00132 continue; 00133 return p; 00134 } 00135 } 00136 } 00137 } 00138 00139 /* No match; run through includes */ 00140 for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) { 00141 for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) { 00142 if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) { 00143 e = find_matching_priority(c2, exten, priority, callerid); 00144 if (e) 00145 return e; 00146 } 00147 } 00148 } 00149 return NULL; 00150 }
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(), ast_heap_remove(), and while_continue_exec().
00110 { 00111 char varname[VAR_SIZE]; 00112 00113 snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx); 00114 return pbx_builtin_getvar_helper(chan, varname); 00115 }
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().
00351 { 00352 int res; 00353 00354 res = ast_register_application_xml(start_app, while_start_exec); 00355 res |= ast_register_application_xml(stop_app, while_end_exec); 00356 res |= ast_register_application_xml(exit_app, while_exit_exec); 00357 res |= ast_register_application_xml(continue_app, while_continue_exec); 00358 00359 return res; 00360 }
static int unload_module | ( | void | ) | [static] |
Definition at line 338 of file app_while.c.
References ast_unregister_application().
00339 { 00340 int res; 00341 00342 res = ast_unregister_application(start_app); 00343 res |= ast_unregister_application(stop_app); 00344 res |= ast_unregister_application(exit_app); 00345 res |= ast_unregister_application(continue_app); 00346 00347 return res; 00348 }
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().
00320 { 00321 int x; 00322 const char *prefix = "WHILE", *while_pri=NULL; 00323 00324 for (x = 0; ; x++) { 00325 const char *tmp = get_index(chan, prefix, x); 00326 if (tmp) 00327 while_pri = tmp; 00328 else 00329 break; 00330 } 00331 00332 if (while_pri) 00333 ast_parseable_goto(chan, while_pri); 00334 00335 return 0; 00336 }
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().
00311 { 00312 return _while_exec(chan, data, 1); 00313 }
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().
00315 { 00316 return _while_exec(chan, data, 2); 00317 }
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().
00307 { 00308 return _while_exec(chan, data, 0); 00309 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .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.