Fri Sep 29 11:13:01 2006

Asterisk developer's documentation


app_while.c File Reference

While Loop and ExecIf Implementations. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.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"

Include dependency graph for app_while.c:

Go to the source code of this file.

Defines

#define ALL_DONE(u, ret)   {LOCAL_USER_REMOVE(u); return ret;}
#define VAR_SIZE   64

Functions

static int _while_exec (struct ast_channel *chan, void *data, int end)
char * description (void)
 Provides a description of the module.
static int execif_exec (struct ast_channel *chan, void *data)
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 char * get_index (struct ast_channel *chan, const char *prefix, int index)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.
static int while_end_exec (struct ast_channel *chan, void *data)
static int while_start_exec (struct ast_channel *chan, void *data)

Variables

static char * exec_app = "ExecIf"
static char * exec_desc
static char * exec_synopsis = "Conditional exec"
 LOCAL_USER_DECL
 STANDARD_LOCAL_USER
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"
static char * tdesc = "While Loops and Conditional Execution"


Detailed Description

While Loop and ExecIf Implementations.

Definition in file app_while.c.


Define Documentation

#define ALL_DONE ( u,
ret   )     {LOCAL_USER_REMOVE(u); return ret;}

Definition at line 45 of file app_while.c.

#define VAR_SIZE   64

Definition at line 122 of file app_while.c.

Referenced by _while_exec(), and get_index().


Function Documentation

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

Definition at line 208 of file app_while.c.

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

Referenced by while_end_exec(), and while_start_exec().

00209 {
00210    int res=0;
00211    struct localuser *u;
00212    char *while_pri = NULL;
00213    char *goto_str = NULL, *my_name = NULL;
00214    char *condition = NULL, *label = NULL;
00215    char varname[VAR_SIZE], end_varname[VAR_SIZE];
00216    const char *prefix = "WHILE";
00217    size_t size=0;
00218    int used_index_i = -1, x=0;
00219    char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
00220    
00221    if (!chan) {
00222       /* huh ? */
00223       return -1;
00224    }
00225 
00226    LOCAL_USER_ADD(u);
00227 
00228    /* dont want run away loops if the chan isn't even up
00229       this is up for debate since it slows things down a tad ......
00230    */
00231    if (ast_waitfordigit(chan,1) < 0)
00232       ALL_DONE(u,-1);
00233 
00234 
00235    for (x=0;;x++) {
00236       if (get_index(chan, prefix, x)) {
00237          used_index_i = x;
00238       } else 
00239          break;
00240    }
00241    
00242    snprintf(used_index, VAR_SIZE, "%d", used_index_i);
00243    snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
00244    
00245    if (!end) {
00246       condition = ast_strdupa((char *) data);
00247    }
00248 
00249    size = strlen(chan->context) + strlen(chan->exten) + 32;
00250    my_name = alloca(size);
00251    memset(my_name, 0, size);
00252    snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
00253    
00254    if (ast_strlen_zero(label)) {
00255       if (end) 
00256          label = used_index;
00257       else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
00258          label = new_index;
00259          pbx_builtin_setvar_helper(chan, my_name, label);
00260       }
00261       
00262    }
00263    
00264    snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
00265    while_pri = pbx_builtin_getvar_helper(chan, varname);
00266    
00267    if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
00268       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00269    }
00270    
00271 
00272    if (!end && !pbx_checkcondition(condition)) {
00273       /* Condition Met (clean up helper vars) */
00274       pbx_builtin_setvar_helper(chan, varname, NULL);
00275       pbx_builtin_setvar_helper(chan, my_name, NULL);
00276         snprintf(end_varname,VAR_SIZE,"END_%s",varname);
00277       if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
00278          pbx_builtin_setvar_helper(chan, end_varname, NULL);
00279          ast_parseable_goto(chan, goto_str);
00280       } else {
00281          int pri = find_matching_endwhile(chan);
00282          if (pri > 0) {
00283             if (option_verbose > 2)
00284                ast_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri);
00285             chan->priority = pri;
00286          } else {
00287             ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
00288          }
00289       }
00290       ALL_DONE(u,res);
00291    }
00292 
00293    if (!end && !while_pri) {
00294       size = strlen(chan->context) + strlen(chan->exten) + 32;
00295       goto_str = alloca(size);
00296       memset(goto_str, 0, size);
00297       snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority);
00298       pbx_builtin_setvar_helper(chan, varname, goto_str);
00299    } 
00300 
00301    else if (end && while_pri) {
00302       /* END of loop */
00303       snprintf(end_varname, VAR_SIZE, "END_%s", varname);
00304       if (! pbx_builtin_getvar_helper(chan, end_varname)) {
00305          size = strlen(chan->context) + strlen(chan->exten) + 32;
00306          goto_str = alloca(size);
00307          memset(goto_str, 0, size);
00308          snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority+1);
00309          pbx_builtin_setvar_helper(chan, end_varname, goto_str);
00310       }
00311       ast_parseable_goto(chan, while_pri);
00312    }
00313    
00314 
00315 
00316 
00317    ALL_DONE(u, res);
00318 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 353 of file app_while.c.

00354 {
00355    return tdesc;
00356 }

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

Definition at line 80 of file app_while.c.

References ALL_DONE, app, ast_log(), ast_strdupa, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, pbx_checkcondition(), pbx_exec(), and pbx_findapp().

Referenced by load_module().

00080                                                              {
00081    int res=0;
00082    struct localuser *u;
00083    char *myapp = NULL;
00084    char *mydata = NULL;
00085    char *expr = NULL;
00086    struct ast_app *app = NULL;
00087 
00088    LOCAL_USER_ADD(u);
00089 
00090    expr = ast_strdupa(data);
00091    if (!expr) {
00092       ast_log(LOG_ERROR, "Out of memory\n");
00093       LOCAL_USER_REMOVE(u);
00094       return -1;
00095    }
00096 
00097    if ((myapp = strchr(expr,'|'))) {
00098       *myapp = '\0';
00099       myapp++;
00100       if ((mydata = strchr(myapp,'|'))) {
00101          *mydata = '\0';
00102          mydata++;
00103       } else
00104          mydata = "";
00105 
00106       if (pbx_checkcondition(expr)) { 
00107          if ((app = pbx_findapp(myapp))) {
00108             res = pbx_exec(chan, app, mydata, 1);
00109          } else {
00110             ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
00111             res = -1;
00112          }
00113       }
00114    } else {
00115       ast_log(LOG_ERROR,"Invalid Syntax.\n");
00116       res = -1;
00117    }
00118       
00119    ALL_DONE(u,res);
00120 }

static int find_matching_endwhile ( struct ast_channel chan  )  [static]

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

00168 {
00169    struct ast_context *c;
00170    int res=-1;
00171 
00172    if (ast_lock_contexts()) {
00173       ast_log(LOG_ERROR, "Failed to lock contexts list\n");
00174       return -1;
00175    }
00176 
00177    for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
00178       struct ast_exten *e;
00179 
00180       if (!ast_lock_context(c)) {
00181          if (!strcmp(ast_get_context_name(c), chan->context)) {
00182             /* This is the matching context we want */
00183             int cur_priority = chan->priority + 1, level=1;
00184 
00185             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)) {
00186                if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
00187                   level++;
00188                } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
00189                   level--;
00190                }
00191 
00192                if (level == 0) {
00193                   res = cur_priority;
00194                   break;
00195                }
00196             }
00197          }
00198          ast_unlock_context(c);
00199          if (res > 0) {
00200             break;
00201          }
00202       }
00203    }
00204    ast_unlock_contexts();
00205    return res;
00206 }

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

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

00133 {
00134    struct ast_exten *e;
00135    struct ast_include *i;
00136    struct ast_context *c2;
00137 
00138    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
00139       if (ast_extension_match(ast_get_extension_name(e), exten)) {
00140          int needmatch = ast_get_extension_matchcid(e);
00141          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
00142             (!needmatch)) {
00143             /* This is the matching extension we want */
00144             struct ast_exten *p;
00145             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
00146                if (priority != ast_get_extension_priority(p))
00147                   continue;
00148                return p;
00149             }
00150          }
00151       }
00152    }
00153 
00154    /* No match; run through includes */
00155    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
00156       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
00157          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
00158             e = find_matching_priority(c2, exten, priority, callerid);
00159             if (e)
00160                return e;
00161          }
00162       }
00163    }
00164    return NULL;
00165 }

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

Definition at line 125 of file app_while.c.

References pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _while_exec().

00125                                                                                 {
00126    char varname[VAR_SIZE];
00127 
00128    snprintf(varname, VAR_SIZE, "%s_%d", prefix, index);
00129    return pbx_builtin_getvar_helper(chan, varname);
00130 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 365 of file app_while.c.

References ASTERISK_GPL_KEY.

00366 {
00367    return ASTERISK_GPL_KEY;
00368 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 342 of file app_while.c.

References ast_register_application(), execif_exec(), while_end_exec(), and while_start_exec().

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 329 of file app_while.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

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

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 358 of file app_while.c.

References STANDARD_USECOUNT.

00359 {
00360    int res;
00361    STANDARD_USECOUNT(res);
00362    return res;
00363 }

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

Definition at line 324 of file app_while.c.

References _while_exec(), and localuser::chan.

Referenced by load_module().

00324                                                                 {
00325    return _while_exec(chan, data, 1);
00326 }

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

Definition at line 320 of file app_while.c.

References _while_exec(), and localuser::chan.

Referenced by load_module().

00320                                                                   {
00321    return _while_exec(chan, data, 0);
00322 }


Variable Documentation

char* exec_app = "ExecIf" [static]

Definition at line 48 of file app_while.c.

char* exec_desc [static]

Initial value:

 
"Usage:  ExecIF (<expr>|<app>|<data>)\n"
"If <expr> is true, execute and return the result of <app>(<data>).\n"
"If <expr> is true, but <app> is not found, then the application\n"
"will return a non-zero value."

Definition at line 49 of file app_while.c.

char* exec_synopsis = "Conditional exec" [static]

Definition at line 54 of file app_while.c.

LOCAL_USER_DECL

Definition at line 78 of file app_while.c.

STANDARD_LOCAL_USER

Definition at line 76 of file app_while.c.

char* start_app = "While" [static]

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

char* start_synopsis = "Start A While Loop" [static]

Definition at line 62 of file app_while.c.

char* stop_app = "EndWhile" [static]

Definition at line 65 of file app_while.c.

char* stop_desc [static]

Initial value:

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

Definition at line 66 of file app_while.c.

char* stop_synopsis = "End A While Loop" [static]

Definition at line 70 of file app_while.c.

char* tdesc = "While Loops and Conditional Execution" [static]

Definition at line 72 of file app_while.c.


Generated on Fri Sep 29 11:13:02 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7