Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 105 of file app_while.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 362 of file app_while.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 362 of file app_while.c.

◆ _while_exec()

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

Definition at line 197 of file app_while.c.

198{
199 int res=0;
200 const char *while_pri = NULL;
201 char *my_name = NULL;
202 const char *condition = NULL, *label = NULL;
203 char varname[VAR_SIZE], end_varname[VAR_SIZE];
204 const char *prefix = "WHILE";
205 size_t size=0;
206 int used_index_i = -1, x=0;
207 char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
208
209 if (!chan) {
210 /* huh ? */
211 return -1;
212 }
213
214#if 0
215 /* don't want run away loops if the chan isn't even up
216 this is up for debate since it slows things down a tad ......
217
218 Debate is over... this prevents While/EndWhile from working
219 within the "h" extension. Not good.
220 */
221 if (ast_waitfordigit(chan,1) < 0)
222 return -1;
223#endif
224
225 for (x=0;;x++) {
226 if (get_index(chan, prefix, x)) {
227 used_index_i = x;
228 } else
229 break;
230 }
231
232 snprintf(used_index, VAR_SIZE, "%d", used_index_i);
233 snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
234
235 if (!end)
236 condition = ast_strdupa(data);
237
238 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
239 my_name = ast_alloca(size);
240 memset(my_name, 0, size);
241 snprintf(my_name, size, "%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
242
243 ast_channel_lock(chan);
244 if (end) {
245 label = used_index;
246 } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
247 label = new_index;
248 pbx_builtin_setvar_helper(chan, my_name, label);
249 }
250 snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
251 if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
252 while_pri = ast_strdupa(while_pri);
253 snprintf(end_varname,VAR_SIZE,"END_%s",varname);
254 }
255 ast_channel_unlock(chan);
256
257
258 if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
259 /* Condition Met (clean up helper vars) */
260 const char *goto_str;
261 pbx_builtin_setvar_helper(chan, varname, NULL);
262 pbx_builtin_setvar_helper(chan, my_name, NULL);
263 snprintf(end_varname,VAR_SIZE,"END_%s",varname);
264 ast_channel_lock(chan);
265 if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
266 ast_parseable_goto(chan, goto_str);
267 pbx_builtin_setvar_helper(chan, end_varname, NULL);
268 } else {
269 int pri = find_matching_endwhile(chan);
270 if (pri > 0) {
271 ast_verb(3, "Jumping to priority %d\n", pri);
272 ast_channel_priority_set(chan, pri);
273 } else {
274 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));
275 }
276 }
277 ast_channel_unlock(chan);
278 return res;
279 }
280
281 if (!end && !while_pri) {
282 char *goto_str;
283 size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
284 goto_str = ast_alloca(size);
285 memset(goto_str, 0, size);
286 snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
287 pbx_builtin_setvar_helper(chan, varname, goto_str);
288 }
289
290 else if (end && while_pri) {
291 /* END of loop */
292 snprintf(end_varname, VAR_SIZE, "END_%s", varname);
293 if (! pbx_builtin_getvar_helper(chan, end_varname)) {
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)+1);
299 pbx_builtin_setvar_helper(chan, end_varname, goto_str);
300 }
301 ast_parseable_goto(chan, while_pri);
302 }
303
304 return res;
305}
static const char * get_index(struct ast_channel *chan, const char *prefix, int idx)
Definition: app_while.c:108
#define VAR_SIZE
Definition: app_while.c:105
static int find_matching_endwhile(struct ast_channel *chan)
Definition: app_while.c:152
#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:3175
#define ast_channel_lock(chan)
Definition: channel.h:2922
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:2923
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:8282
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8866
#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 362 of file app_while.c.

◆ find_matching_endwhile()

static int find_matching_endwhile ( struct ast_channel chan)
static

Definition at line 152 of file app_while.c.

153{
154 struct ast_context *c;
155 int res=-1;
156
157 if (ast_rdlock_contexts()) {
158 ast_log(LOG_ERROR, "Failed to lock contexts list\n");
159 return -1;
160 }
161
163 struct ast_exten *e;
164
165 if (!ast_rdlock_context(c)) {
166 if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
167 /* This is the matching context we want */
168 int cur_priority = ast_channel_priority(chan) + 1, level=1;
169
170 for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
171 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
172 e;
173 e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
174 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
175 if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
176 level++;
177 } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
178 level--;
179 }
180
181 if (level == 0) {
182 res = cur_priority;
183 break;
184 }
185 }
186 }
188 if (res > 0) {
189 break;
190 }
191 }
192 }
194 return res;
195}
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_while.c:115
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:8557
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
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:8468
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8486
#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:284
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
Number structure.
Definition: app_followme.c:154
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 115 of file app_while.c.

116{
117 struct ast_exten *e;
118 struct ast_context *c2;
119 int idx;
120
123 int needmatch = ast_get_extension_matchcid(e);
124 if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
125 (!needmatch)) {
126 /* This is the matching extension we want */
127 struct ast_exten *p;
130 continue;
131 return p;
132 }
133 }
134 }
135 }
136
137 /* No match; run through includes */
138 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
139 const struct ast_include *i = ast_context_includes_get(c, idx);
140
141 for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
142 if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
143 e = find_matching_priority(c2, exten, priority, callerid);
144 if (e)
145 return e;
146 }
147 }
148 }
149 return NULL;
150}
static int priority
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8519
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:8547
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:8552
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:8684
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:8679
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8509
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 108 of file app_while.c.

108 {
109 char varname[VAR_SIZE];
110
111 snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
112 return pbx_builtin_getvar_helper(chan, varname);
113}

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 350 of file app_while.c.

351{
352 int res;
353
358
359 return res;
360}
static char * stop_app
Definition: app_while.c:101
static int while_end_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:311
static int while_exit_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:315
static char * exit_app
Definition: app_while.c:102
static int while_start_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:307
static char * continue_app
Definition: app_while.c:103
static int while_continue_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:319
static char * start_app
Definition: app_while.c:100
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

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 338 of file app_while.c.

339{
340 int res;
341
346
347 return res;
348}
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 319 of file app_while.c.

320{
321 int x;
322 const char *prefix = "WHILE", *while_pri=NULL;
323
324 for (x = 0; ; x++) {
325 const char *tmp = get_index(chan, prefix, x);
326 if (tmp)
327 while_pri = tmp;
328 else
329 break;
330 }
331
332 if (while_pri)
333 ast_parseable_goto(chan, while_pri);
334
335 return 0;
336}
static int tmp()
Definition: bt_open.c:389

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

Referenced by load_module().

◆ while_end_exec()

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

Definition at line 311 of file app_while.c.

311 {
312 return _while_exec(chan, data, 1);
313}
static int _while_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_while.c:197

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 315 of file app_while.c.

315 {
316 return _while_exec(chan, data, 2);
317}

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 307 of file app_while.c.

307 {
308 return _while_exec(chan, data, 0);
309}

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 362 of file app_while.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 362 of file app_while.c.

◆ continue_app

char* continue_app = "ContinueWhile"
static

Definition at line 103 of file app_while.c.

Referenced by load_module(), and unload_module().

◆ exit_app

char* exit_app = "ExitWhile"
static

Definition at line 102 of file app_while.c.

Referenced by load_module(), and unload_module().

◆ start_app

char* start_app = "While"
static

Definition at line 100 of file app_while.c.

Referenced by load_module(), and unload_module().

◆ stop_app

char* stop_app = "EndWhile"
static

Definition at line 101 of file app_while.c.

Referenced by load_module(), and unload_module().