Fri Jun 19 12:10:05 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 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
static 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 311 of file app_while.c.

static void __unreg_module ( void   )  [static]

Definition at line 311 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_channel_lock, ast_channel_unlock, ast_log(), ast_parseable_goto(), ast_strdupa, 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    ast_channel_lock(chan);
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    snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
00200    if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
00201       while_pri = ast_strdupa(while_pri);
00202       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00203    }
00204    ast_channel_unlock(chan);
00205    
00206 
00207    if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
00208       /* Condition Met (clean up helper vars) */
00209       const char *goto_str;
00210       pbx_builtin_setvar_helper(chan, varname, NULL);
00211       pbx_builtin_setvar_helper(chan, my_name, NULL);
00212       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00213       ast_channel_lock(chan);
00214       if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
00215          ast_parseable_goto(chan, goto_str);
00216          pbx_builtin_setvar_helper(chan, end_varname, NULL);
00217       } else {
00218          int pri = find_matching_endwhile(chan);
00219          if (pri > 0) {
00220             ast_verb(3, "Jumping to priority %d\n", pri);
00221             chan->priority = pri;
00222          } else {
00223             ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
00224          }
00225       }
00226       ast_channel_unlock(chan);
00227       return res;
00228    }
00229 
00230    if (!end && !while_pri) {
00231       char *goto_str;
00232       size = strlen(chan->context) + strlen(chan->exten) + 32;
00233       goto_str = alloca(size);
00234       memset(goto_str, 0, size);
00235       snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
00236       pbx_builtin_setvar_helper(chan, varname, goto_str);
00237    }
00238 
00239    else if (end && while_pri) {
00240       /* END of loop */
00241       snprintf(end_varname, VAR_SIZE, "END_%s", varname);
00242       if (! pbx_builtin_getvar_helper(chan, end_varname)) {
00243          char *goto_str;
00244          size = strlen(chan->context) + strlen(chan->exten) + 32;
00245          goto_str = alloca(size);
00246          memset(goto_str, 0, size);
00247          snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
00248          pbx_builtin_setvar_helper(chan, end_varname, goto_str);
00249       }
00250       ast_parseable_goto(chan, while_pri);
00251    }
00252 
00253    return res;
00254 }

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  idx 
) [static]

Definition at line 63 of file app_while.c.

References chan, pbx_builtin_getvar_helper(), and VAR_SIZE.

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

static int load_module ( void   )  [static]

Definition at line 299 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 287 of file app_while.c.

References ast_unregister_application().

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

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

Definition at line 268 of file app_while.c.

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

Referenced by load_module().

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

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

Definition at line 260 of file app_while.c.

References _while_exec(), and chan.

Referenced by load_module().

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

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

Definition at line 264 of file app_while.c.

References _while_exec(), and chan.

Referenced by load_module().

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

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

Definition at line 256 of file app_while.c.

References _while_exec(), and chan.

Referenced by load_module().

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


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

Definition at line 311 of file app_while.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 311 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 Fri Jun 19 12:10:06 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7