Tue Aug 20 16:34:47 2013

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.

Defines

#define VAR_SIZE   64

Functions

static int _while_exec (struct ast_channel *chan, const char *data, int end)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"While Loops and Conditional Execution")
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 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 <anthmct@yahoo.com>

Definition in file app_while.c.


Define Documentation

#define VAR_SIZE   64

Definition at line 107 of file app_while.c.

Referenced by _while_exec(), and get_index().


Function Documentation

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

00198 {
00199    int res=0;
00200    const char *while_pri = NULL;
00201    char *my_name = NULL;
00202    const char *condition = NULL, *label = NULL;
00203    char varname[VAR_SIZE], end_varname[VAR_SIZE];
00204    const char *prefix = "WHILE";
00205    size_t size=0;
00206    int used_index_i = -1, x=0;
00207    char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
00208 
00209    if (!chan) {
00210       /* huh ? */
00211       return -1;
00212    }
00213 
00214 #if 0
00215    /* don't want run away loops if the chan isn't even up
00216       this is up for debate since it slows things down a tad ......
00217 
00218       Debate is over... this prevents While/EndWhile from working
00219       within the "h" extension.  Not good.
00220    */
00221    if (ast_waitfordigit(chan,1) < 0)
00222       return -1;
00223 #endif
00224 
00225    for (x=0;;x++) {
00226       if (get_index(chan, prefix, x)) {
00227          used_index_i = x;
00228       } else 
00229          break;
00230    }
00231    
00232    snprintf(used_index, VAR_SIZE, "%d", used_index_i);
00233    snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
00234    
00235    if (!end)
00236       condition = ast_strdupa(data);
00237 
00238    size = strlen(chan->context) + strlen(chan->exten) + 32;
00239    my_name = ast_alloca(size);
00240    memset(my_name, 0, size);
00241    snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
00242    
00243    ast_channel_lock(chan);
00244    if (end) {
00245       label = used_index;
00246    } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
00247       label = new_index;
00248       pbx_builtin_setvar_helper(chan, my_name, label);
00249    }
00250    snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
00251    if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
00252       while_pri = ast_strdupa(while_pri);
00253       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00254    }
00255    ast_channel_unlock(chan);
00256    
00257 
00258    if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
00259       /* Condition Met (clean up helper vars) */
00260       const char *goto_str;
00261       pbx_builtin_setvar_helper(chan, varname, NULL);
00262       pbx_builtin_setvar_helper(chan, my_name, NULL);
00263       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00264       ast_channel_lock(chan);
00265       if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
00266          ast_parseable_goto(chan, goto_str);
00267          pbx_builtin_setvar_helper(chan, end_varname, NULL);
00268       } else {
00269          int pri = find_matching_endwhile(chan);
00270          if (pri > 0) {
00271             ast_verb(3, "Jumping to priority %d\n", pri);
00272             chan->priority = pri;
00273          } else {
00274             ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
00275          }
00276       }
00277       ast_channel_unlock(chan);
00278       return res;
00279    }
00280 
00281    if (!end && !while_pri) {
00282       char *goto_str;
00283       size = strlen(chan->context) + strlen(chan->exten) + 32;
00284       goto_str = ast_alloca(size);
00285       memset(goto_str, 0, size);
00286       snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
00287       pbx_builtin_setvar_helper(chan, varname, goto_str);
00288    }
00289 
00290    else if (end && while_pri) {
00291       /* END of loop */
00292       snprintf(end_varname, VAR_SIZE, "END_%s", varname);
00293       if (! pbx_builtin_getvar_helper(chan, end_varname)) {
00294          char *goto_str;
00295          size = strlen(chan->context) + strlen(chan->exten) + 32;
00296          goto_str = ast_alloca(size);
00297          memset(goto_str, 0, size);
00298          snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
00299          pbx_builtin_setvar_helper(chan, end_varname, goto_str);
00300       }
00301       ast_parseable_goto(chan, while_pri);
00302    }
00303 
00304    return res;
00305 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"While Loops and Conditional Execution"   
)
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().

00153 {
00154    struct ast_context *c;
00155    int res=-1;
00156 
00157    if (ast_rdlock_contexts()) {
00158       ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00159       return -1;
00160    }
00161 
00162    for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
00163       struct ast_exten *e;
00164 
00165       if (!ast_rdlock_context(c)) {
00166          if (!strcmp(ast_get_context_name(c), chan->context)) {
00167             /* This is the matching context we want */
00168             int cur_priority = chan->priority + 1, level=1;
00169 
00170             for (e = find_matching_priority(c, chan->exten, cur_priority,
00171                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
00172                e;
00173                e = find_matching_priority(c, chan->exten, ++cur_priority,
00174                   S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
00175                if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
00176                   level++;
00177                } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
00178                   level--;
00179                }
00180 
00181                if (level == 0) {
00182                   res = cur_priority;
00183                   break;
00184                }
00185             }
00186          }
00187          ast_unlock_context(c);
00188          if (res > 0) {
00189             break;
00190          }
00191       }
00192    }
00193    ast_unlock_contexts();
00194    return res;
00195 }

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

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

00118 {
00119    struct ast_exten *e;
00120    struct ast_include *i;
00121    struct ast_context *c2;
00122 
00123    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
00124       if (ast_extension_match(ast_get_extension_name(e), exten)) {
00125          int needmatch = ast_get_extension_matchcid(e);
00126          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
00127             (!needmatch)) {
00128             /* This is the matching extension we want */
00129             struct ast_exten *p;
00130             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
00131                if (priority != ast_get_extension_priority(p))
00132                   continue;
00133                return p;
00134             }
00135          }
00136       }
00137    }
00138 
00139    /* No match; run through includes */
00140    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
00141       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
00142          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
00143             e = find_matching_priority(c2, exten, priority, callerid);
00144             if (e)
00145                return e;
00146          }
00147       }
00148    }
00149    return NULL;
00150 }

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

00110                                                                                     {
00111    char varname[VAR_SIZE];
00112 
00113    snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
00114    return pbx_builtin_getvar_helper(chan, varname);
00115 }

static int load_module ( void   )  [static]
static int unload_module ( void   )  [static]

Definition at line 338 of file app_while.c.

References ast_unregister_application().

00339 {
00340    int res;
00341    
00342    res = ast_unregister_application(start_app);
00343    res |= ast_unregister_application(stop_app);
00344    res |= ast_unregister_application(exit_app);
00345    res |= ast_unregister_application(continue_app);
00346 
00347    return res;
00348 }

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

00320 {
00321    int x;
00322    const char *prefix = "WHILE", *while_pri=NULL;
00323 
00324    for (x = 0; ; x++) {
00325       const char *tmp = get_index(chan, prefix, x);
00326       if (tmp)
00327          while_pri = tmp;
00328       else
00329          break;
00330    }
00331 
00332    if (while_pri)
00333       ast_parseable_goto(chan, while_pri);
00334 
00335    return 0;
00336 }

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

00311                                                                       {
00312    return _while_exec(chan, data, 1);
00313 }

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

00315                                                                        {
00316    return _while_exec(chan, data, 2);
00317 }

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

00307                                                                         {
00308    return _while_exec(chan, data, 0);
00309 }


Variable Documentation

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.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1