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 int | _while_exec (struct ast_channel *chan, const char *data, int end) |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"While Loops and Conditional Execution") | |
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 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 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_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().
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 = ast_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 = ast_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 = ast_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 }
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"While Loops and Conditional Execution" | ||||
) |
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, 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().
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(), 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 }
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.