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