Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 = "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, .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:3203
#define ast_channel_lock(chan)
Definition: channel.h:2970
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:2971
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:8297
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8881
#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}
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
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: extconf.c:4024
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8572
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8506
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:8483
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8488
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8501
#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.
Definition: app_followme.c:157
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:8534
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:8562
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:8567
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:4061
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:4295
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8699
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:8694
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8524
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 = "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, .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().