Wed Apr 6 11:29:53 2011

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
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 358 of file app_while.c.

static void __unreg_module ( void   )  [static]

Definition at line 358 of file app_while.c.

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

Definition at line 193 of file app_while.c.

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

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

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::caller, ast_channel::context, ast_channel::exten, find_matching_priority(), ast_party_caller::id, LOG_ERROR, ast_party_id::number, ast_channel::priority, S_COR, ast_party_number::str, and ast_party_number::valid.

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,
00167                S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
00168                e;
00169                e = find_matching_priority(c, chan->exten, ++cur_priority,
00170                   S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
00171                if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
00172                   level++;
00173                } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
00174                   level--;
00175                }
00176 
00177                if (level == 0) {
00178                   res = cur_priority;
00179                   break;
00180                }
00181             }
00182          }
00183          ast_unlock_context(c);
00184          if (res > 0) {
00185             break;
00186          }
00187       }
00188    }
00189    ast_unlock_contexts();
00190    return res;
00191 }

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

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(), ast_walk_extension_priorities(), and find_matching_priority().

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(), ast_heap_remove(), 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]

Definition at line 346 of file app_while.c.

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

static int unload_module ( void   )  [static]

Definition at line 334 of file app_while.c.

References ast_unregister_application().

00335 {
00336    int res;
00337    
00338    res = ast_unregister_application(start_app);
00339    res |= ast_unregister_application(stop_app);
00340    res |= ast_unregister_application(exit_app);
00341    res |= ast_unregister_application(continue_app);
00342 
00343    return res;
00344 }

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

Definition at line 315 of file app_while.c.

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

Referenced by load_module().

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

static int while_end_exec ( struct ast_channel chan,
const char *  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, 1);
00309 }

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

Definition at line 311 of file app_while.c.

References _while_exec().

Referenced by load_module().

00311                                                                        {
00312    return _while_exec(chan, data, 2);
00313 }

static int while_start_exec ( struct ast_channel chan,
const char *  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, 0);
00305 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 358 of file app_while.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 358 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 on Wed Apr 6 11:29:53 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7