Mon Mar 12 2012 21:26:12

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"
Include dependency graph for app_while.c:

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 = AST_BUILDOPT_SUM, .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 107 of file app_while.c.

Referenced by _while_exec(), and get_index().


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 362 of file app_while.c.

static void __unreg_module ( void  ) [static]

Definition at line 362 of file app_while.c.

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

Definition at line 197 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(), ast_exten::label, 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().

{
   int res=0;
   const char *while_pri = NULL;
   char *my_name = NULL;
   const char *condition = NULL, *label = NULL;
   char varname[VAR_SIZE], end_varname[VAR_SIZE];
   const char *prefix = "WHILE";
   size_t size=0;
   int used_index_i = -1, x=0;
   char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";

   if (!chan) {
      /* huh ? */
      return -1;
   }

#if 0
   /* don't want run away loops if the chan isn't even up
      this is up for debate since it slows things down a tad ......

      Debate is over... this prevents While/EndWhile from working
      within the "h" extension.  Not good.
   */
   if (ast_waitfordigit(chan,1) < 0)
      return -1;
#endif

   for (x=0;;x++) {
      if (get_index(chan, prefix, x)) {
         used_index_i = x;
      } else 
         break;
   }
   
   snprintf(used_index, VAR_SIZE, "%d", used_index_i);
   snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
   
   if (!end)
      condition = ast_strdupa(data);

   size = strlen(chan->context) + strlen(chan->exten) + 32;
   my_name = alloca(size);
   memset(my_name, 0, size);
   snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
   
   ast_channel_lock(chan);
   if (end) {
      label = used_index;
   } else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
      label = new_index;
      pbx_builtin_setvar_helper(chan, my_name, label);
   }
   snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
   if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
      while_pri = ast_strdupa(while_pri);
      snprintf(end_varname,VAR_SIZE,"END_%s",varname);
   }
   ast_channel_unlock(chan);
   

   if ((!end && !pbx_checkcondition(condition)) || (end == 2)) {
      /* Condition Met (clean up helper vars) */
      const char *goto_str;
      pbx_builtin_setvar_helper(chan, varname, NULL);
      pbx_builtin_setvar_helper(chan, my_name, NULL);
      snprintf(end_varname,VAR_SIZE,"END_%s",varname);
      ast_channel_lock(chan);
      if ((goto_str = pbx_builtin_getvar_helper(chan, end_varname))) {
         ast_parseable_goto(chan, goto_str);
         pbx_builtin_setvar_helper(chan, end_varname, NULL);
      } else {
         int pri = find_matching_endwhile(chan);
         if (pri > 0) {
            ast_verb(3, "Jumping to priority %d\n", pri);
            chan->priority = pri;
         } else {
            ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
         }
      }
      ast_channel_unlock(chan);
      return res;
   }

   if (!end && !while_pri) {
      char *goto_str;
      size = strlen(chan->context) + strlen(chan->exten) + 32;
      goto_str = alloca(size);
      memset(goto_str, 0, size);
      snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
      pbx_builtin_setvar_helper(chan, varname, goto_str);
   }

   else if (end && while_pri) {
      /* END of loop */
      snprintf(end_varname, VAR_SIZE, "END_%s", varname);
      if (! pbx_builtin_getvar_helper(chan, end_varname)) {
         char *goto_str;
         size = strlen(chan->context) + strlen(chan->exten) + 32;
         goto_str = alloca(size);
         memset(goto_str, 0, size);
         snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
         pbx_builtin_setvar_helper(chan, end_varname, goto_str);
      }
      ast_parseable_goto(chan, while_pri);
   }

   return res;
}
static int find_matching_endwhile ( struct ast_channel chan) [static]

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

{
   struct ast_context *c;
   int res=-1;

   if (ast_rdlock_contexts()) {
      ast_log(LOG_ERROR, "Failed to lock contexts list\n");
      return -1;
   }

   for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
      struct ast_exten *e;

      if (!ast_rdlock_context(c)) {
         if (!strcmp(ast_get_context_name(c), chan->context)) {
            /* This is the matching context we want */
            int cur_priority = chan->priority + 1, level=1;

            for (e = find_matching_priority(c, chan->exten, cur_priority,
               S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
               e;
               e = find_matching_priority(c, chan->exten, ++cur_priority,
                  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
               if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
                  level++;
               } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
                  level--;
               }

               if (level == 0) {
                  res = cur_priority;
                  break;
               }
            }
         }
         ast_unlock_context(c);
         if (res > 0) {
            break;
         }
      }
   }
   ast_unlock_contexts();
   return res;
}
static struct ast_exten* find_matching_priority ( struct ast_context c,
const char *  exten,
int  priority,
const char *  callerid 
) [static, read]

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

{
   struct ast_exten *e;
   struct ast_include *i;
   struct ast_context *c2;

   for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
      if (ast_extension_match(ast_get_extension_name(e), exten)) {
         int needmatch = ast_get_extension_matchcid(e);
         if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
            (!needmatch)) {
            /* This is the matching extension we want */
            struct ast_exten *p;
            for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
               if (priority != ast_get_extension_priority(p))
                  continue;
               return p;
            }
         }
      }
   }

   /* No match; run through includes */
   for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
      for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
         if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
            e = find_matching_priority(c2, exten, priority, callerid);
            if (e)
               return e;
         }
      }
   }
   return NULL;
}
static const char* get_index ( struct ast_channel chan,
const char *  prefix,
int  idx 
) [static]

Definition at line 110 of file app_while.c.

References pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _while_exec(), and while_continue_exec().

                                                                                    {
   char varname[VAR_SIZE];

   snprintf(varname, VAR_SIZE, "%s_%d", prefix, idx);
   return pbx_builtin_getvar_helper(chan, varname);
}
static int unload_module ( void  ) [static]
static int while_continue_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 319 of file app_while.c.

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

Referenced by load_module().

{
   int x;
   const char *prefix = "WHILE", *while_pri=NULL;

   for (x = 0; ; x++) {
      const char *tmp = get_index(chan, prefix, x);
      if (tmp)
         while_pri = tmp;
      else
         break;
   }

   if (while_pri)
      ast_parseable_goto(chan, while_pri);

   return 0;
}
static int while_end_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().

                                                                      {
   return _while_exec(chan, data, 1);
}
static int while_exit_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 315 of file app_while.c.

References _while_exec().

Referenced by load_module().

                                                                       {
   return _while_exec(chan, data, 2);
}
static int while_start_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().

                                                                        {
   return _while_exec(chan, data, 0);
}

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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 362 of file app_while.c.

Definition at line 362 of file app_while.c.

char* continue_app = "ContinueWhile" [static]

Definition at line 105 of file app_while.c.

char* exit_app = "ExitWhile" [static]

Definition at line 104 of file app_while.c.

char* start_app = "While" [static]

Definition at line 102 of file app_while.c.

char* stop_app = "EndWhile" [static]

Definition at line 103 of file app_while.c.