Sat Aug 6 00:39:38 2011

Asterisk developer's documentation


app_while.c File Reference

While Loop Implementation. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"

Go to the source code of this file.

Defines

#define ALL_DONE(u, ret)   {ast_module_user_remove(u); return ret;}
#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 | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 ALL_DONE ( u,
ret   )     {ast_module_user_remove(u); return ret;}

Definition at line 47 of file app_while.c.

Referenced by _while_exec().

#define VAR_SIZE   64

Definition at line 78 of file app_while.c.

Referenced by _while_exec(), and get_index().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 339 of file app_while.c.

static void __unreg_module ( void   )  [static]

Definition at line 339 of file app_while.c.

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

Definition at line 164 of file app_while.c.

References ALL_DONE, ast_log(), ast_module_user_add, ast_parseable_goto(), ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfordigit(), ast_module_user::chan, ast_channel::context, ast_channel::exten, find_matching_endwhile(), get_index(), LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), prefix, ast_channel::priority, VAR_SIZE, and VERBOSE_PREFIX_3.

Referenced by while_end_exec(), while_exit_exec(), and while_start_exec().

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

static int find_matching_endwhile ( struct ast_channel chan  )  [static]

Definition at line 123 of file app_while.c.

References ast_get_context_name(), ast_get_extension_app(), ast_lock_context(), ast_lock_contexts(), ast_log(), 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().

00124 {
00125    struct ast_context *c;
00126    int res=-1;
00127 
00128    if (ast_lock_contexts()) {
00129       ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00130       return -1;
00131    }
00132 
00133    for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
00134       struct ast_exten *e;
00135 
00136       if (!ast_lock_context(c)) {
00137          if (!strcmp(ast_get_context_name(c), chan->context)) {
00138             /* This is the matching context we want */
00139             int cur_priority = chan->priority + 1, level=1;
00140 
00141             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)) {
00142                if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
00143                   level++;
00144                } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
00145                   level--;
00146                }
00147 
00148                if (level == 0) {
00149                   res = cur_priority;
00150                   break;
00151                }
00152             }
00153          }
00154          ast_unlock_context(c);
00155          if (res > 0) {
00156             break;
00157          }
00158       }
00159    }
00160    ast_unlock_contexts();
00161    return res;
00162 }

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

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

00089 {
00090    struct ast_exten *e;
00091    struct ast_include *i;
00092    struct ast_context *c2;
00093 
00094    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
00095       if (ast_extension_match(ast_get_extension_name(e), exten)) {
00096          int needmatch = ast_get_extension_matchcid(e);
00097          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
00098             (!needmatch)) {
00099             /* This is the matching extension we want */
00100             struct ast_exten *p;
00101             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
00102                if (priority != ast_get_extension_priority(p))
00103                   continue;
00104                return p;
00105             }
00106          }
00107       }
00108    }
00109 
00110    /* No match; run through includes */
00111    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
00112       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
00113          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
00114             e = find_matching_priority(c2, exten, priority, callerid);
00115             if (e)
00116                return e;
00117          }
00118       }
00119    }
00120    return NULL;
00121 }

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

Definition at line 81 of file app_while.c.

References pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _while_exec(), and while_continue_exec().

00081                                                                                       {
00082    char varname[VAR_SIZE];
00083 
00084    snprintf(varname, VAR_SIZE, "%s_%d", prefix, index);
00085    return pbx_builtin_getvar_helper(chan, varname);
00086 }

static int load_module ( void   )  [static]

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

References ast_module_user_hangup_all, and ast_unregister_application().

00314 {
00315    int res;
00316    
00317    res = ast_unregister_application(start_app);
00318    res |= ast_unregister_application(stop_app);
00319    res |= ast_unregister_application(exit_app);
00320    res |= ast_unregister_application(continue_app);
00321 
00322    ast_module_user_hangup_all();
00323 
00324    return res;
00325 }

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

Definition at line 294 of file app_while.c.

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

Referenced by load_module().

00295 {
00296    int x;
00297    const char *prefix = "WHILE", *while_pri=NULL;
00298 
00299    for (x = 0; ; x++) {
00300       const char *tmp = get_index(chan, prefix, x);
00301       if (tmp)
00302          while_pri = tmp;
00303       else
00304          break;
00305    }
00306 
00307    if (while_pri)
00308       ast_parseable_goto(chan, while_pri);
00309 
00310    return 0;
00311 }

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

Definition at line 286 of file app_while.c.

References _while_exec(), and ast_module_user::chan.

Referenced by load_module().

00286                                                                 {
00287    return _while_exec(chan, data, 1);
00288 }

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

Definition at line 290 of file app_while.c.

References _while_exec(), and ast_module_user::chan.

Referenced by load_module().

00290                                                                  {
00291    return _while_exec(chan, data, 2);
00292 }

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

Definition at line 282 of file app_while.c.

References _while_exec(), and ast_module_user::chan.

Referenced by load_module().

00282                                                                   {
00283    return _while_exec(chan, data, 0);
00284 }


Variable Documentation

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

Definition at line 339 of file app_while.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 339 of file app_while.c.

char* continue_app = "ContinueWhile" [static]

Definition at line 72 of file app_while.c.

char* continue_desc [static]

Initial value:

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

Definition at line 73 of file app_while.c.

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

Definition at line 76 of file app_while.c.

char* exit_app = "ExitWhile" [static]

Definition at line 66 of file app_while.c.

char* exit_desc [static]

Initial value:

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

Definition at line 67 of file app_while.c.

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

Definition at line 70 of file app_while.c.

char* start_app = "While" [static]

Definition at line 50 of file app_while.c.

char* start_desc [static]

Initial value:

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

Definition at line 51 of file app_while.c.

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

Definition at line 56 of file app_while.c.

char* stop_app = "EndWhile" [static]

Definition at line 59 of file app_while.c.

char* stop_desc [static]

Initial value:

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

Definition at line 60 of file app_while.c.

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

Definition at line 64 of file app_while.c.


Generated on Sat Aug 6 00:39:38 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7