Wed Jan 8 2020 09:49:57

Asterisk developer's documentation


app_while.c File Reference

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.

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)
 
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static 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

#define VAR_SIZE   64

Definition at line 107 of file app_while.c.

Referenced by _while_exec(), and get_index().

Function Documentation

static void __reg_module ( void  )
static

Definition at line 362 of file app_while.c.

static void __unreg_module ( void  )
static

Definition at line 362 of file app_while.c.

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().

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(chan->context) + strlen(chan->exten) + 32;
239  my_name = ast_alloca(size);
240  memset(my_name, 0, size);
241  snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
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  chan->priority = pri;
273  } else {
274  ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
275  }
276  }
277  ast_channel_unlock(chan);
278  return res;
279  }
280 
281  if (!end && !while_pri) {
282  char *goto_str;
283  size = strlen(chan->context) + strlen(chan->exten) + 32;
284  goto_str = ast_alloca(size);
285  memset(goto_str, 0, size);
286  snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
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(chan->context) + strlen(chan->exten) + 32;
296  goto_str = ast_alloca(size);
297  memset(goto_str, 0, size);
298  snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+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 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
static const char * get_index(struct ast_channel *chan, const char *prefix, int idx)
Definition: app_while.c:110
int priority
Definition: channel.h:841
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:10719
#define ast_verb(level,...)
Definition: logger.h:243
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
#define VAR_SIZE
Definition: app_while.c:107
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11326
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
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...
Definition: pbx.c:10546
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
static int find_matching_endwhile(struct ast_channel *chan)
Definition: app_while.c:152
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static char prefix[MAX_PREFIX]
Definition: http.c:107
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().

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 
162  for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
163  struct ast_exten *e;
164 
165  if (!ast_rdlock_context(c)) {
166  if (!strcmp(ast_get_context_name(c), chan->context)) {
167  /* This is the matching context we want */
168  int cur_priority = chan->priority + 1, level=1;
169 
170  for (e = find_matching_priority(c, chan->exten, cur_priority,
171  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
172  e;
173  e = find_matching_priority(c, chan->exten, ++cur_priority,
174  S_COR(chan->caller.id.number.valid, chan->caller.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 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:11065
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int priority
Definition: channel.h:841
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:11141
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:11042
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#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:83
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:11174
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:11073
#define LOG_ERROR
Definition: logger.h:155
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:11047
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_while.c:117
ast_context: An extension context
Definition: pbx.c:955
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:11060
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static struct ast_exten* find_matching_priority ( struct ast_context c,
const char *  exten,
int  priority,
const char *  callerid 
)
static

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().

118 {
119  struct ast_exten *e;
120  struct ast_include *i;
121  struct ast_context *c2;
122 
123  for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
125  int needmatch = ast_get_extension_matchcid(e);
126  if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
127  (!needmatch)) {
128  /* This is the matching extension we want */
129  struct ast_exten *p;
130  for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
132  continue;
133  return p;
134  }
135  }
136  }
137  }
138 
139  /* No match; run through includes */
140  for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
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 }
struct ast_include * ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
Definition: pbx.c:11203
ast_include: include= support in extensions.conf
Definition: pbx.c:904
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:11103
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
const char * ast_get_include_name(struct ast_include *include)
Definition: pbx.c:11093
int priority
Definition: pbx.c:888
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: pbx.c:11179
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:11136
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:11174
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:11073
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:11197
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:11083
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2943
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:11131
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_while.c:117
ast_context: An extension context
Definition: pbx.c:955
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().

110  {
111  char varname[VAR_SIZE];
112 
113  snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
114  return pbx_builtin_getvar_helper(chan, varname);
115 }
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
#define VAR_SIZE
Definition: app_while.c:107
static char prefix[MAX_PREFIX]
Definition: http.c:107
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().

351 {
352  int res;
353 
358 
359  return res;
360 }
static char * exit_app
Definition: app_while.c:104
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:105
static char * stop_app
Definition: app_while.c:103
static int while_continue_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:319
static int while_exit_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:315
static int while_end_exec(struct ast_channel *chan, const char *data)
Definition: app_while.c:311
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static char * start_app
Definition: app_while.c:102
static int unload_module ( void  )
static

Definition at line 338 of file app_while.c.

References ast_unregister_application().

339 {
340  int res;
341 
346 
347  return res;
348 }
static char * exit_app
Definition: app_while.c:104
static char * continue_app
Definition: app_while.c:105
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static char * stop_app
Definition: app_while.c:103
static char * start_app
Definition: app_while.c:102
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().

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 const char * get_index(struct ast_channel *chan, const char *prefix, int idx)
Definition: app_while.c:110
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11326
static char prefix[MAX_PREFIX]
Definition: http.c:107
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().

311  {
312  return _while_exec(chan, data, 1);
313 }
void * data
Definition: pbx.c:893
static int _while_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_while.c:197
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().

315  {
316  return _while_exec(chan, data, 2);
317 }
void * data
Definition: pbx.c:893
static int _while_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_while.c:197
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().

307  {
308  return _while_exec(chan, data, 0);
309 }
void * data
Definition: pbx.c:893
static int _while_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_while.c:197

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 362 of file app_while.c.

Definition at line 362 of file app_while.c.

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.