Asterisk - The Open Source Telephony Project  18.5.0
Macros | Functions | Variables
app_if.c File Reference

If Branch Implementation. More...

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

Go to the source code of this file.

Macros

#define VAR_SIZE   64
 

Functions

static int _if_exec (struct ast_channel *chan, const char *data, int end)
 
 AST_MODULE_INFO_STANDARD_EXTENDED (ASTERISK_GPL_KEY, "If Branch and Conditional Execution")
 
static int find_matching_endif (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 if_end_exec (struct ast_channel *chan, const char *data)
 
static int if_exit_exec (struct ast_channel *chan, const char *data)
 
static int if_start_exec (struct ast_channel *chan, const char *data)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static char * exit_app = "ExitIf"
 
static char * start_app = "If"
 
static char * stop_app = "EndIf"
 

Detailed Description

If Branch Implementation.

Author
Naveen Albert aster.nosp@m.isk@.nosp@m.phrea.nosp@m.knet.nosp@m..org

Definition in file app_if.c.

Macro Definition Documentation

◆ VAR_SIZE

#define VAR_SIZE   64

Definition at line 87 of file app_if.c.

Referenced by _if_exec(), and get_index().

Function Documentation

◆ _if_exec()

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

Definition at line 179 of file app_if.c.

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, find_matching_endif(), get_index(), ast_exten::label, LOG_WARNING, NULL, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), prefix, and VAR_SIZE.

Referenced by if_end_exec(), if_exit_exec(), and if_start_exec().

180 {
181  int res=0;
182  const char *if_pri = NULL;
183  char *my_name = NULL;
184  const char *condition = NULL, *label = NULL;
185  char varname[VAR_SIZE], end_varname[VAR_SIZE];
186  const char *prefix = "IF";
187  size_t size=0;
188  int used_index_i = -1, x=0;
189  char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
190 
191  if (!chan) {
192  return -1;
193  }
194 
195  for (x=0;;x++) {
196  if (get_index(chan, prefix, x)) {
197  used_index_i = x;
198  } else
199  break;
200  }
201 
202  snprintf(used_index, VAR_SIZE, "%d", used_index_i);
203  snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
204 
205  if (!end)
206  condition = ast_strdupa(data);
207 
208  size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
209  my_name = ast_alloca(size);
210  memset(my_name, 0, size);
211  snprintf(my_name, size, "%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
212 
213  ast_channel_lock(chan);
214  if (end) {
215  label = used_index;
216  } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
217  label = new_index;
218  pbx_builtin_setvar_helper(chan, my_name, label);
219  }
220  snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
221  if ((if_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
222  if_pri = ast_strdupa(if_pri);
223  snprintf(end_varname,VAR_SIZE,"END_%s",varname);
224  }
225  ast_channel_unlock(chan);
226 
227  if ((!end && !pbx_checkcondition(condition)) || (end > 0)) {
228  /* Condition Met (clean up helper vars) */
229  const char *goto_str;
230  pbx_builtin_setvar_helper(chan, varname, NULL);
231  pbx_builtin_setvar_helper(chan, my_name, NULL);
232  snprintf(end_varname,VAR_SIZE,"END_%s",varname);
233  ast_channel_lock(chan);
234  if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
235  ast_parseable_goto(chan, goto_str);
236  pbx_builtin_setvar_helper(chan, end_varname, NULL);
237  } else {
238  int pri = find_matching_endif(chan);
239  if (pri > 0) {
240  ast_verb(3, "Jumping to priority %d\n", pri);
241  ast_channel_priority_set(chan, pri);
242  } else if (end == 2) { /* Condition added because of end > 0 instead of end == 2 */
243  ast_log(LOG_WARNING, "Couldn't find matching EndIf? (If at %s@%s priority %d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
244  }
245  }
246  ast_channel_unlock(chan);
247  return res;
248  }
249 
250  if (!end && !if_pri) {
251  char *goto_str;
252  size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
253  goto_str = ast_alloca(size);
254  memset(goto_str, 0, size);
255  snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
256  pbx_builtin_setvar_helper(chan, varname, goto_str);
257  } else if (end && if_pri) {
258  /* END of branch */
259  snprintf(end_varname, VAR_SIZE, "END_%s", varname);
260  if (! pbx_builtin_getvar_helper(chan, end_varname)) {
261  char *goto_str;
262  size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
263  goto_str = ast_alloca(size);
264  memset(goto_str, 0, size);
265  snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan)+1);
266  pbx_builtin_setvar_helper(chan, end_varname, goto_str);
267  }
268  ast_parseable_goto(chan, if_pri);
269  }
270 
271  return res;
272 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define LOG_WARNING
Definition: logger.h:274
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:8321
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:463
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define VAR_SIZE
Definition: app_if.c:87
#define ast_log
Definition: astobj2.c:42
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8859
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_exten(const struct ast_channel *chan)
static int find_matching_endif(struct ast_channel *chan)
Definition: app_if.c:134
static const char * get_index(struct ast_channel *chan, const char *prefix, int idx)
Definition: app_if.c:90
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define ast_channel_unlock(chan)
Definition: channel.h:2946
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...
const char * ast_channel_context(const struct ast_channel *chan)
union ast_frame::@263 data
void ast_channel_priority_set(struct ast_channel *chan, int value)
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ AST_MODULE_INFO_STANDARD_EXTENDED()

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"If Branch and Conditional Execution"   
)

Referenced by load_module().

◆ find_matching_endif()

static int find_matching_endif ( struct ast_channel chan)
static

Definition at line 134 of file app_if.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 _if_exec().

135 {
136  struct ast_context *c;
137  int res = -1;
138 
139  if (ast_rdlock_contexts()) {
140  ast_log(LOG_ERROR, "Failed to lock contexts list\n");
141  return -1;
142  }
143 
144  for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
145  struct ast_exten *e;
146 
147  if (!ast_rdlock_context(c)) {
148  if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
149  /* This is the matching context we want */
150  int cur_priority = ast_channel_priority(chan) + 1, level=1;
151 
152  for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
153  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
154  e;
155  e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
156  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
157  if (!strcasecmp(ast_get_extension_app(e), "IF")) {
158  level++;
159  } else if (!strcasecmp(ast_get_extension_app(e), "ENDIF")) {
160  level--;
161  }
162 
163  if (level == 0) {
164  res = cur_priority;
165  break;
166  }
167  }
168  }
170  if (res > 0) {
171  break;
172  }
173  }
174  }
176  return res;
177 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_if.c:97
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: conf2ael.c:618
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8507
static struct test_val c
#define NULL
Definition: resample.c:96
int ast_channel_priority(const struct ast_channel *chan)
Number structure.
Definition: app_followme.c:154
#define ast_log
Definition: astobj2.c:42
#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:85
const char * ast_channel_exten(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
const char * ast_channel_context(const struct ast_channel *chan)
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8525

◆ 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 97 of file app_if.c.

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(), and NULL.

Referenced by find_matching_endif().

98 {
99  struct ast_exten *e;
100  struct ast_context *c2;
101  int idx;
102 
105  int needmatch = ast_get_extension_matchcid(e);
106  if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
107  (!needmatch)) {
108  /* This is the matching extension we want */
109  struct ast_exten *p;
112  continue;
113  return p;
114  }
115  }
116  }
117  }
118 
119  /* No match; run through includes */
120  for (idx = 0; idx < ast_context_includes_count(c); idx++) {
121  const struct ast_include *i = ast_context_includes_get(c, idx);
122 
123  for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
124  if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
125  e = find_matching_priority(c2, exten, priority, callerid);
126  if (e)
127  return e;
128  }
129  }
130  }
131  return NULL;
132 }
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
static struct ast_exten * find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
Definition: app_if.c:97
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8558
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: conf2ael.c:618
#define NULL
Definition: resample.c:96
static int priority
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:8591
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8697
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: ael_main.c:427
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:4297
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:4063
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:8586
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8702

◆ get_index()

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

Definition at line 90 of file app_if.c.

References pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _if_exec().

90  {
91  char varname[VAR_SIZE];
92 
93  snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
94  return pbx_builtin_getvar_helper(chan, varname);
95 }
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define VAR_SIZE
Definition: app_if.c:87
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ if_end_exec()

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

Definition at line 278 of file app_if.c.

References _if_exec().

Referenced by load_module().

278  {
279  return _if_exec(chan, data, 1);
280 }
static int _if_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_if.c:179

◆ if_exit_exec()

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

Definition at line 282 of file app_if.c.

References _if_exec().

Referenced by load_module().

282  {
283  return _if_exec(chan, data, 2);
284 }
static int _if_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_if.c:179

◆ if_start_exec()

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

Definition at line 274 of file app_if.c.

References _if_exec().

Referenced by load_module().

274  {
275  return _if_exec(chan, data, 0);
276 }
static int _if_exec(struct ast_channel *chan, const char *data, int end)
Definition: app_if.c:179

◆ load_module()

static int load_module ( void  )
static

Definition at line 297 of file app_if.c.

References AST_MODULE_INFO_STANDARD_EXTENDED(), ast_register_application_xml, ASTERISK_GPL_KEY, exit_app, if_end_exec(), if_exit_exec(), if_start_exec(), start_app, and stop_app.

298 {
299  int res;
300 
304 
305  return res;
306 }
static char * exit_app
Definition: app_if.c:85
static int if_start_exec(struct ast_channel *chan, const char *data)
Definition: app_if.c:274
static int if_end_exec(struct ast_channel *chan, const char *data)
Definition: app_if.c:278
static int if_exit_exec(struct ast_channel *chan, const char *data)
Definition: app_if.c:282
static char * start_app
Definition: app_if.c:83
static char * stop_app
Definition: app_if.c:84
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 286 of file app_if.c.

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

287 {
288  int res;
289 
293 
294  return res;
295 }
static char * exit_app
Definition: app_if.c:85
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * start_app
Definition: app_if.c:83
static char * stop_app
Definition: app_if.c:84

Variable Documentation

◆ exit_app

char* exit_app = "ExitIf"
static

Definition at line 85 of file app_if.c.

Referenced by load_module(), and unload_module().

◆ start_app

char* start_app = "If"
static

Definition at line 83 of file app_if.c.

Referenced by load_module(), and unload_module().

◆ stop_app

char* stop_app = "EndIf"
static

Definition at line 84 of file app_if.c.

Referenced by load_module(), and unload_module().