Asterisk - The Open Source Telephony Project GIT-master-a63eec2
Loading...
Searching...
No Matches
Macros | Functions | Variables
app_while.c File Reference

While Loop Implementation. More...

#include "asterisk.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
Include dependency graph for app_while.c:

Go to the source code of this file.

Macros

#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)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int find_matching_endwhile (struct ast_channel *chan)
 
static struct ast_extenfind_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 = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static char * continue_app = "ContinueWhile"
 
static char * exit_app = "ExitWhile"
 
static char * start_app = "While"
 
static char * stop_app = "EndWhile"
 

Detailed Description

While Loop Implementation.

Author
Anthony Minessale anthm.nosp@m.ct@y.nosp@m.ahoo..nosp@m.com

Definition in file app_while.c.

Macro Definition Documentation

◆ VAR_SIZE

#define VAR_SIZE   64

Definition at line 117 of file app_while.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 374 of file app_while.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 374 of file app_while.c.

◆ _while_exec()

static int _while_exec ( struct ast_channel chan,
const char *  data,
int  end 
)
static

Definition at line 209 of file app_while.c.

210{
211 int res=0;
212 const char *while_pri = NULL;
213 char *my_name = NULL;
214 const char *condition = NULL, *label = NULL;
215 char varname[VAR_SIZE], end_varname[VAR_SIZE];
216 const char *prefix = "WHILE";
217 size_t size=0;
218 int used_index_i = -1, x=0;
219 char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
220
221 if (!chan) {
222 /* huh ? */
223 return -1;
224 }
225
226#if 0
227 /* don't want run away loops if the chan isn't even up
228 this is up for debate since it slows things down a tad ......
229
230 Debate is over... this prevents While/EndWhile from working
231 within the "h" extension. Not good.
232 */
233 if (ast_waitfordigit(chan,1) < 0)
234 return -1;
235#endif
236
237 for (x=0;;x++) {
238 if (get_index(chan, prefix, x)) {
239 used_index_i = x;
240 } else
241 break;
242 }
243
244 snprintf(used_index, VAR_SIZE, "%d", used_index_i);
245 snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
246
247 if (!end)
248 condition = ast_strdupa(data);
249
250 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
251 my_name = ast_alloca(size);
252 memset(my_name, 0, size);
253 snprintf(my_name, size, "%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
254
255 ast_channel_lock(chan);
256 if (end) {
257 label = used_index;
258 } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
259 label = new_index;
260 pbx_builtin_setvar_helper(chan, my_name, label);
261 }
262 snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
263 if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
264 while_pri = ast_strdupa(while_pri);
265 snprintf(end_varname,VAR_SIZE,"END_%s",varname);
266 }
267 ast_channel_unlock(chan);
268
269
270 if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
271 /* Condition Met (clean up helper vars) */
272 const char *goto_str;
273 pbx_builtin_setvar_helper(chan, varname, NULL);
274 pbx_builtin_setvar_helper(chan, my_name, NULL);
275 snprintf(end_varname,VAR_SIZE,"END_%s",varname);
276 ast_channel_lock(chan);
277 if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
278 ast_parseable_goto(chan, goto_str);
279 pbx_builtin_setvar_helper(chan, end_varname, NULL);
280 } else {
281 int pri = find_matching_endwhile(chan);
282 if (pri > 0) {
283 ast_verb(3, "Jumping to priority %d\n", pri);
284 ast_channel_priority_set(chan, pri);
285 } else {
286 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));
287 }
288 }
289 ast_channel_unlock(chan);
290 return res;
291 }
292
293 if (!end && !while_pri) {
294 char *goto_str;
295 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
296 goto_str = ast_alloca(size);
297 memset(goto_str, 0, size);
298 snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
299 pbx_builtin_setvar_helper(chan, varname, goto_str);
300 }
301
302 else if (end && while_pri) {
303 /* END of loop */
304 snprintf(end_varname, VAR_SIZE, "END_%s", varname);
305 if (! pbx_builtin_getvar_helper(chan, end_varname)) {
306 char *goto_str;
307 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
308 goto_str = ast_alloca(size);
309 memset(goto_str, 0, size);
310 snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan)+1);
311 pbx_builtin_setvar_helper(chan, end_varname, goto_str);
312 }
313 ast_parseable_goto(chan, while_pri);
314 }
315
316 return res;
317}
static const char * get_index(struct ast_channel *chan, const char *prefix, int idx)
Definition app_while.c:120
#define VAR_SIZE
Definition app_while.c:117
static int find_matching_endwhile(struct ast_channel *chan)
Definition app_while.c:164
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_log
Definition astobj2.c:42
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition channel.c:3145
#define ast_channel_lock(chan)
Definition channel.h:2972
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition channel.h:2973
char * end
Definition eagi_proxy.c:73
static char prefix[MAX_PREFIX]
Definition http.c:144
#define ast_verb(level,...)
#define LOG_WARNING
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition pbx.c:8307
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition pbx.c:8891
#define NULL
Definition resample.c:96

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_strdupa, ast_verb, ast_waitfordigit(), ast_exten::data, end, find_matching_endwhile(), get_index(), ast_exten::label, LOG_WARNING, NULL, 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().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 374 of file app_while.c.

◆ find_matching_endwhile()

static int find_matching_endwhile ( struct ast_channel chan)
static

Definition at line 164 of file app_while.c.

165{
166 struct ast_context *c;
167 int res=-1;
168
169 if (ast_rdlock_contexts()) {
170 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
171 return -1;
172 }
173
175 struct ast_exten *e;
176
177 if (!ast_rdlock_context(c)) {
178 if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
179 /* This is the matching context we want */
180 int cur_priority = ast_channel_priority(chan) + 1, level=1;
181
182 for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
183 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
184 e;
185 e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
186 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
187 if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
188 level++;
189 } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
190 level--;
191 }
192
193 if (level == 0) {
194 res = cur_priority;
195 break;
196 }
197 }
198 }
200 if (res > 0) {
201 break;
202 }
203 }
204 }
206 return res;
207}
struct ast_context * ast_walk_contexts(void)
Definition ael_main.c:401
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition app_while.c:127
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define LOG_ERROR
const char * ast_get_extension_app(struct ast_exten *e)
Definition pbx.c:8582
int ast_unlock_context(struct ast_context *con)
Definition pbx.c:8516
const char * ast_get_context_name(struct ast_context *con)
Definition ael_main.c:421
int ast_rdlock_contexts(void)
Read locks the context list.
Definition pbx.c:8493
int ast_unlock_contexts(void)
Unlocks contexts.
Definition pbx.c:8498
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition pbx.c:8511
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87
ast_context: An extension context
Definition pbx.c:299
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition pbx.c:252
Number structure.
static struct test_val 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(), c, find_matching_priority(), LOG_ERROR, NULL, and S_COR.

Referenced by _while_exec().

◆ find_matching_priority()

static struct ast_exten * find_matching_priority ( struct ast_context c,
const char *  exten,
int  priority,
const char *  callerid 
)
static

Definition at line 127 of file app_while.c.

128{
129 struct ast_exten *e;
130 struct ast_context *c2;
131 int idx;
132
135 int needmatch = ast_get_extension_matchcid(e);
136 if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
137 (!needmatch)) {
138 /* This is the matching extension we want */
139 struct ast_exten *p;
142 continue;
143 return p;
144 }
145 }
146 }
147 }
148
149 /* No match; run through includes */
150 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
151 const struct ast_include *i = ast_context_includes_get(c, idx);
152
153 for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
154 if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
155 e = find_matching_priority(c2, exten, priority, callerid);
156 if (e)
157 return e;
158 }
159 }
160 }
161 return NULL;
162}
static int priority
int ast_get_extension_priority(struct ast_exten *exten)
Definition pbx.c:8544
int ast_get_extension_matchcid(struct ast_exten *e)
Definition pbx.c:8572
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition pbx.c:8577
const char * ast_get_include_name(const struct ast_include *include)
Definition pbx_include.c:50
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition extconf.c:4059
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition extconf.c:4293
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition pbx.c:8709
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition ael_main.c:427
int ast_context_includes_count(const struct ast_context *con)
Definition pbx.c:8704
const char * ast_get_extension_name(struct ast_exten *exten)
Definition pbx.c:8534
ast_include: include= support in extensions.conf
Definition pbx_include.c:37

References ast_context_includes_count(), ast_context_includes_get(), 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_contexts(), ast_walk_extension_priorities(), c, find_matching_priority(), NULL, and priority.

Referenced by find_matching_endwhile(), and find_matching_priority().

◆ get_index()

static const char * get_index ( struct ast_channel chan,
const char *  prefix,
int  idx 
)
static

Definition at line 120 of file app_while.c.

120 {
121 char varname[VAR_SIZE];
122
123 snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
124 return pbx_builtin_getvar_helper(chan, varname);
125}

References pbx_builtin_getvar_helper(), prefix, and VAR_SIZE.

Referenced by _while_exec(), and while_continue_exec().

◆ load_module()

static int load_module ( void  )
static

Definition at line 362 of file app_while.c.

363{
364 int res;
365
370
371 return res;
372}
static char * stop_app
Definition app_while.c:113
static int while_end_exec(struct ast_channel *chan, const char *data)
Definition app_while.c:323
static int while_exit_exec(struct ast_channel *chan, const char *data)
Definition app_while.c:327
static char * exit_app
Definition app_while.c:114
static int while_start_exec(struct ast_channel *chan, const char *data)
Definition app_while.c:319
static char * continue_app
Definition app_while.c:115
static int while_continue_exec(struct ast_channel *chan, const char *data)
Definition app_while.c:331
static char * start_app
Definition app_while.c:112
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition module.h:640

References ast_register_application_xml, continue_app, exit_app, start_app, stop_app, while_continue_exec(), while_end_exec(), while_exit_exec(), and while_start_exec().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 350 of file app_while.c.

351{
352 int res;
353
358
359 return res;
360}
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:392

References ast_unregister_application(), continue_app, exit_app, start_app, and stop_app.

◆ while_continue_exec()

static int while_continue_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 331 of file app_while.c.

332{
333 int x;
334 const char *prefix = "WHILE", *while_pri=NULL;
335
336 for (x = 0; ; x++) {
337 const char *tmp = get_index(chan, prefix, x);
338 if (tmp)
339 while_pri = tmp;
340 else
341 break;
342 }
343
344 if (while_pri)
345 ast_parseable_goto(chan, while_pri);
346
347 return 0;
348}

References ast_parseable_goto(), get_index(), NULL, and prefix.

Referenced by load_module().

◆ while_end_exec()

static int while_end_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 323 of file app_while.c.

323 {
324 return _while_exec(chan, data, 1);
325}
static int _while_exec(struct ast_channel *chan, const char *data, int end)
Definition app_while.c:209

References _while_exec(), and ast_exten::data.

Referenced by load_module().

◆ while_exit_exec()

static int while_exit_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 327 of file app_while.c.

327 {
328 return _while_exec(chan, data, 2);
329}

References _while_exec(), and ast_exten::data.

Referenced by load_module().

◆ while_start_exec()

static int while_start_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 319 of file app_while.c.

319 {
320 return _while_exec(chan, data, 0);
321}

References _while_exec(), and ast_exten::data.

Referenced by load_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "While Loops and Conditional Execution" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 374 of file app_while.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 374 of file app_while.c.

◆ continue_app

char* continue_app = "ContinueWhile"
static

Definition at line 115 of file app_while.c.

Referenced by load_module(), and unload_module().

◆ exit_app

char* exit_app = "ExitWhile"
static

Definition at line 114 of file app_while.c.

Referenced by load_module(), and unload_module().

◆ start_app

char* start_app = "While"
static

Definition at line 112 of file app_while.c.

Referenced by load_module(), and unload_module().

◆ stop_app

char* stop_app = "EndWhile"
static

Definition at line 113 of file app_while.c.

Referenced by load_module(), and unload_module().