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.

Defines

#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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
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 <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 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_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(), 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().

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(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
00239    my_name = ast_alloca(size);
00240    memset(my_name, 0, size);
00241    snprintf(my_name, size, "%s_%s_%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
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             ast_channel_priority_set(chan, pri);
00273          } else {
00274             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));
00275          }
00276       }
00277       ast_channel_unlock(chan);
00278       return res;
00279    }
00280 
00281    if (!end && !while_pri) {
00282       char *goto_str;
00283       size = strlen(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
00284       goto_str = ast_alloca(size);
00285       memset(goto_str, 0, size);
00286       snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan));
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(ast_channel_context(chan)) + strlen(ast_channel_exten(chan)) + 32;
00296          goto_str = ast_alloca(size);
00297          memset(goto_str, 0, size);
00298          snprintf(goto_str, size, "%s,%s,%d", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan)+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 }

static int find_matching_endwhile ( struct ast_channel chan  )  [static]

Definition at line 152 of file app_while.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, e, find_matching_priority(), LOG_ERROR, NULL, and S_COR.

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), ast_channel_context(chan))) {
00167             /* This is the matching context we want */
00168             int cur_priority = ast_channel_priority(chan) + 1, level=1;
00169 
00170             for (e = find_matching_priority(c, ast_channel_exten(chan), cur_priority,
00171                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
00172                e;
00173                e = find_matching_priority(c, ast_channel_exten(chan), ++cur_priority,
00174                   S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->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(), ast_walk_extension_priorities(), e, find_matching_priority(), and NULL.

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

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

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.

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.


Generated on Thu Apr 16 06:28:51 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6