Thu Jul 9 13:40:51 2009

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 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 index)
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static const struct ast_module_infoast_module_info = &__mod_info
static char * continue_app = "ContinueWhile"
static char * continue_desc
static char * continue_synopsis = "Restart a While loop"
static char * exit_app = "ExitWhile"
static char * exit_desc
static char * exit_synopsis = "End a While loop"
static char * start_app = "While"
static char * start_desc
static char * start_synopsis = "Start a while loop"
static char * stop_app = "EndWhile"
static char * stop_desc
static char * stop_synopsis = "End a while loop"


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 60 of file app_while.c.

Referenced by _while_exec(), and get_index().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 312 of file app_while.c.

static void __unreg_module ( void   )  [static]

Definition at line 312 of file app_while.c.

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

Definition at line 146 of file app_while.c.

References ast_log(), ast_parseable_goto(), ast_strdupa, ast_strlen_zero(), ast_verb, ast_waitfordigit(), chan, ast_channel::context, ast_channel::exten, find_matching_endwhile(), get_index(), 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().

00147 {
00148    int res=0;
00149    const char *while_pri = NULL;
00150    char *my_name = NULL;
00151    const char *condition = NULL, *label = NULL;
00152    char varname[VAR_SIZE], end_varname[VAR_SIZE];
00153    const char *prefix = "WHILE";
00154    size_t size=0;
00155    int used_index_i = -1, x=0;
00156    char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
00157 
00158    if (!chan) {
00159       /* huh ? */
00160       return -1;
00161    }
00162 
00163 #if 0
00164    /* dont want run away loops if the chan isn't even up
00165       this is up for debate since it slows things down a tad ......
00166 
00167       Debate is over... this prevents While/EndWhile from working
00168       within the "h" extension.  Not good.
00169    */
00170    if (ast_waitfordigit(chan,1) < 0)
00171       return -1;
00172 #endif
00173 
00174    for (x=0;;x++) {
00175       if (get_index(chan, prefix, x)) {
00176          used_index_i = x;
00177       } else 
00178          break;
00179    }
00180    
00181    snprintf(used_index, VAR_SIZE, "%d", used_index_i);
00182    snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
00183    
00184    if (!end)
00185       condition = ast_strdupa(data);
00186 
00187    size = strlen(chan->context) + strlen(chan->exten) + 32;
00188    my_name = alloca(size);
00189    memset(my_name, 0, size);
00190    snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
00191    
00192    if (ast_strlen_zero(label)) {
00193       if (end) 
00194          label = used_index;
00195       else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
00196          label = new_index;
00197          pbx_builtin_setvar_helper(chan, my_name, label);
00198       }
00199       
00200    }
00201    
00202    snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
00203    while_pri = pbx_builtin_getvar_helper(chan, varname);
00204    
00205    if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
00206       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00207    }
00208    
00209 
00210    if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
00211       /* Condition Met (clean up helper vars) */
00212       const char *goto_str;
00213       pbx_builtin_setvar_helper(chan, varname, NULL);
00214       pbx_builtin_setvar_helper(chan, my_name, NULL);
00215       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00216       if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
00217          ast_parseable_goto(chan, goto_str);
00218          pbx_builtin_setvar_helper(chan, end_varname, NULL);
00219       } else {
00220          int pri = find_matching_endwhile(chan);
00221          if (pri > 0) {
00222             ast_verb(3, "Jumping to priority %d\n", pri);
00223             chan->priority = pri;
00224          } else {
00225             ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
00226          }
00227       }
00228       return res;
00229    }
00230 
00231    if (!end && !while_pri) {
00232       char *goto_str;
00233       size = strlen(chan->context) + strlen(chan->exten) + 32;
00234       goto_str = alloca(size);
00235       memset(goto_str, 0, size);
00236       snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
00237       pbx_builtin_setvar_helper(chan, varname, goto_str);
00238    } 
00239 
00240    else if (end && while_pri) {
00241       /* END of loop */
00242       snprintf(end_varname, VAR_SIZE, "END_%s", varname);
00243       if (! pbx_builtin_getvar_helper(chan, end_varname)) {
00244          char *goto_str;
00245          size = strlen(chan->context) + strlen(chan->exten) + 32;
00246          goto_str = alloca(size);
00247          memset(goto_str, 0, size);
00248          snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
00249          pbx_builtin_setvar_helper(chan, end_varname, goto_str);
00250       }
00251       ast_parseable_goto(chan, while_pri);
00252    }
00253 
00254    return res;
00255 }

static int find_matching_endwhile ( struct ast_channel chan  )  [static]

Definition at line 105 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(), chan, 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().

00106 {
00107    struct ast_context *c;
00108    int res=-1;
00109 
00110    if (ast_rdlock_contexts()) {
00111       ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00112       return -1;
00113    }
00114 
00115    for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
00116       struct ast_exten *e;
00117 
00118       if (!ast_rdlock_context(c)) {
00119          if (!strcmp(ast_get_context_name(c), chan->context)) {
00120             /* This is the matching context we want */
00121             int cur_priority = chan->priority + 1, level=1;
00122 
00123             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)) {
00124                if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
00125                   level++;
00126                } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
00127                   level--;
00128                }
00129 
00130                if (level == 0) {
00131                   res = cur_priority;
00132                   break;
00133                }
00134             }
00135          }
00136          ast_unlock_context(c);
00137          if (res > 0) {
00138             break;
00139          }
00140       }
00141    }
00142    ast_unlock_contexts();
00143    return res;
00144 }

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

Definition at line 70 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(), and find_matching_priority().

00071 {
00072    struct ast_exten *e;
00073    struct ast_include *i;
00074    struct ast_context *c2;
00075 
00076    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
00077       if (ast_extension_match(ast_get_extension_name(e), exten)) {
00078          int needmatch = ast_get_extension_matchcid(e);
00079          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
00080             (!needmatch)) {
00081             /* This is the matching extension we want */
00082             struct ast_exten *p;
00083             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
00084                if (priority != ast_get_extension_priority(p))
00085                   continue;
00086                return p;
00087             }
00088          }
00089       }
00090    }
00091 
00092    /* No match; run through includes */
00093    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
00094       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
00095          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
00096             e = find_matching_priority(c2, exten, priority, callerid);
00097             if (e)
00098                return e;
00099          }
00100       }
00101    }
00102    return NULL;
00103 }

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

Definition at line 63 of file app_while.c.

References chan, pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _while_exec(), and while_continue_exec().

00063                                                                                       {
00064    char varname[VAR_SIZE];
00065 
00066    snprintf(varname, VAR_SIZE, "%s_%d", prefix, index);
00067    return pbx_builtin_getvar_helper(chan, varname);
00068 }

static int load_module ( void   )  [static]

Definition at line 300 of file app_while.c.

References ast_register_application, while_continue_exec(), while_end_exec(), while_exit_exec(), and while_start_exec().

static int unload_module ( void   )  [static]

Definition at line 288 of file app_while.c.

References ast_unregister_application().

00289 {
00290    int res;
00291    
00292    res = ast_unregister_application(start_app);
00293    res |= ast_unregister_application(stop_app);
00294    res |= ast_unregister_application(exit_app);
00295    res |= ast_unregister_application(continue_app);
00296 
00297    return res;
00298 }

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

Definition at line 269 of file app_while.c.

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

Referenced by load_module().

00270 {
00271    int x;
00272    const char *prefix = "WHILE", *while_pri=NULL;
00273 
00274    for (x = 0; ; x++) {
00275       const char *tmp = get_index(chan, prefix, x);
00276       if (tmp)
00277          while_pri = tmp;
00278       else
00279          break;
00280    }
00281 
00282    if (while_pri)
00283       ast_parseable_goto(chan, while_pri);
00284 
00285    return 0;
00286 }

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

Definition at line 261 of file app_while.c.

References _while_exec(), and chan.

Referenced by load_module().

00261                                                                 {
00262    return _while_exec(chan, data, 1);
00263 }

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

Definition at line 265 of file app_while.c.

References _while_exec(), and chan.

Referenced by load_module().

00265                                                                  {
00266    return _while_exec(chan, data, 2);
00267 }

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

Definition at line 257 of file app_while.c.

References _while_exec(), and chan.

Referenced by load_module().

00257                                                                   {
00258    return _while_exec(chan, data, 0);
00259 }


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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static]

Definition at line 312 of file app_while.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 312 of file app_while.c.

char* continue_app = "ContinueWhile" [static]

Definition at line 55 of file app_while.c.

char* continue_desc [static]

Initial value:

"  ContinueWhile(): Returns to the top of the while loop and re-evaluates the conditional.\n"

Definition at line 56 of file app_while.c.

char* continue_synopsis = "Restart a While loop" [static]

Definition at line 58 of file app_while.c.

char* exit_app = "ExitWhile" [static]

Definition at line 50 of file app_while.c.

char* exit_desc [static]

Initial value:

"  ExitWhile(): Exits a While() loop, whether or not the conditional has been satisfied.\n"

Definition at line 51 of file app_while.c.

char* exit_synopsis = "End a While loop" [static]

Definition at line 53 of file app_while.c.

char* start_app = "While" [static]

Definition at line 36 of file app_while.c.

char* start_desc [static]

Initial value:

 
"  While(<expr>): Start a While Loop.  Execution will return to this\n"
"point when EndWhile() is called until expr is no longer true.\n"

Definition at line 37 of file app_while.c.

char* start_synopsis = "Start a while loop" [static]

Definition at line 41 of file app_while.c.

char* stop_app = "EndWhile" [static]

Definition at line 44 of file app_while.c.

char* stop_desc [static]

Initial value:

 
"  EndWhile(): Return to the previous called While()\n"

Definition at line 45 of file app_while.c.

char* stop_synopsis = "End a while loop" [static]

Definition at line 48 of file app_while.c.


Generated on Thu Jul 9 13:40:51 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7