Fri Nov 12 11:52:59 2010

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"
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, void *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, void *data)
static int while_end_exec (struct ast_channel *chan, void *data)
static int while_exit_exec (struct ast_channel *chan, void *data)
static int while_start_exec (struct ast_channel *chan, void *data)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, }
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 103 of file app_while.c.

Referenced by _while_exec(), and get_index().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 354 of file app_while.c.

static void __unreg_module ( void   )  [static]

Definition at line 354 of file app_while.c.

static int _while_exec ( struct ast_channel chan,
void *  data,
int  end 
) [static]

Definition at line 189 of file app_while.c.

References ast_channel_lock, ast_channel_unlock, ast_log(), ast_parseable_goto(), 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().

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

static int find_matching_endwhile ( struct ast_channel chan  )  [static]

Definition at line 148 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::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, find_matching_priority(), LOG_ERROR, and ast_channel::priority.

Referenced by _while_exec().

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

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

Definition at line 113 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().

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

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

Definition at line 106 of file app_while.c.

References pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _while_exec(), and while_continue_exec().

00106                                                                                     {
00107    char varname[VAR_SIZE];
00108 
00109    snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
00110    return pbx_builtin_getvar_helper(chan, varname);
00111 }

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

Definition at line 330 of file app_while.c.

References ast_unregister_application().

00331 {
00332    int res;
00333    
00334    res = ast_unregister_application(start_app);
00335    res |= ast_unregister_application(stop_app);
00336    res |= ast_unregister_application(exit_app);
00337    res |= ast_unregister_application(continue_app);
00338 
00339    return res;
00340 }

static int while_continue_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 311 of file app_while.c.

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

Referenced by load_module().

00312 {
00313    int x;
00314    const char *prefix = "WHILE", *while_pri=NULL;
00315 
00316    for (x = 0; ; x++) {
00317       const char *tmp = get_index(chan, prefix, x);
00318       if (tmp)
00319          while_pri = tmp;
00320       else
00321          break;
00322    }
00323 
00324    if (while_pri)
00325       ast_parseable_goto(chan, while_pri);
00326 
00327    return 0;
00328 }

static int while_end_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 303 of file app_while.c.

References _while_exec().

Referenced by load_module().

00303                                                                 {
00304    return _while_exec(chan, data, 1);
00305 }

static int while_exit_exec ( struct ast_channel chan,
void *  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, 2);
00309 }

static int while_start_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 299 of file app_while.c.

References _while_exec().

Referenced by load_module().

00299                                                                   {
00300    return _while_exec(chan, data, 0);
00301 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 354 of file app_while.c.

Definition at line 354 of file app_while.c.

char* continue_app = "ContinueWhile" [static]

Definition at line 101 of file app_while.c.

char* exit_app = "ExitWhile" [static]

Definition at line 100 of file app_while.c.

char* start_app = "While" [static]

Definition at line 98 of file app_while.c.

char* stop_app = "EndWhile" [static]

Definition at line 99 of file app_while.c.


Generated by  doxygen 1.6.2