Mon Mar 12 2012 21:24:07

Asterisk developer's documentation


app_page.c File Reference

page() - Paging application More...

#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/chanvars.h"
#include "asterisk/utils.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
Include dependency graph for app_page.c:

Go to the source code of this file.

Enumerations

enum  { OPT_ARG_ANNOUNCE = 0, OPT_ARG_ARRAY_SIZE = 1 }
enum  page_opt_flags {
  PAGE_DUPLEX = (1 << 0), PAGE_QUIET = (1 << 1), PAGE_RECORD = (1 << 2), PAGE_SKIP = (1 << 3),
  PAGE_IGNORE_FORWARDS = (1 << 4), PAGE_ANNOUNCE = (1 << 5), PAGE_NOCALLERANNOUNCE = (1 << 6)
}

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int load_module (void)
static int page_exec (struct ast_channel *chan, const char *data)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Page Multiple Phones" , .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 const char *const app_page = "Page"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_app_option page_opts [128] = { [ 'd' ] = { .flag = PAGE_DUPLEX }, [ 'q' ] = { .flag = PAGE_QUIET }, [ 'r' ] = { .flag = PAGE_RECORD }, [ 's' ] = { .flag = PAGE_SKIP }, [ 'i' ] = { .flag = PAGE_IGNORE_FORWARDS }, [ 'i' ] = { .flag = PAGE_IGNORE_FORWARDS }, [ 'A' ] = { .flag = PAGE_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'n' ] = { .flag = PAGE_NOCALLERANNOUNCE },}

Detailed Description

page() - Paging application

Author:
Mark Spencer <markster@digium.com>

Definition in file app_page.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
OPT_ARG_ANNOUNCE 
OPT_ARG_ARRAY_SIZE 

Definition at line 124 of file app_page.c.

Enumerator:
PAGE_DUPLEX 
PAGE_QUIET 
PAGE_RECORD 
PAGE_SKIP 
PAGE_IGNORE_FORWARDS 
PAGE_ANNOUNCE 
PAGE_NOCALLERANNOUNCE 

Definition at line 114 of file app_page.c.

                    {
   PAGE_DUPLEX = (1 << 0),
   PAGE_QUIET = (1 << 1),
   PAGE_RECORD = (1 << 2),
   PAGE_SKIP = (1 << 3),
   PAGE_IGNORE_FORWARDS = (1 << 4),
   PAGE_ANNOUNCE = (1 << 5),
   PAGE_NOCALLERANNOUNCE = (1 << 6),
};

Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 313 of file app_page.c.

static void __unreg_module ( void  ) [static]

Definition at line 313 of file app_page.c.

static int load_module ( void  ) [static]

Definition at line 308 of file app_page.c.

References ast_register_application_xml, and page_exec().

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

Definition at line 141 of file app_page.c.

References app, args, AST_APP_ARG, ast_app_parse_options(), ast_calloc, AST_CHANNEL_NAME, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNKNOWN, ast_devstate2str(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), ast_dial_hangup(), ast_dial_join(), AST_DIAL_OPTION_ANSWER_EXEC, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, ast_dial_option_global_enable(), ast_dial_run(), ast_dial_set_global_timeout(), ast_log(), ast_random(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), ast_channel::language, LOG_ERROR, LOG_WARNING, ast_channel::name, OPT_ARG_ANNOUNCE, OPT_ARG_ARRAY_SIZE, ast_dial::options, PAGE_ANNOUNCE, PAGE_DUPLEX, PAGE_IGNORE_FORWARDS, PAGE_NOCALLERANNOUNCE, page_opts, PAGE_QUIET, PAGE_RECORD, PAGE_SKIP, parse(), pbx_exec(), pbx_findapp(), strsep(), and ast_dial::timeout.

Referenced by load_module().

{
   char *tech, *resource, *tmp;
   char meetmeopts[128], originator[AST_CHANNEL_NAME], *opts[OPT_ARG_ARRAY_SIZE];
   struct ast_flags flags = { 0 };
   unsigned int confid = ast_random();
   struct ast_app *app;
   int res = 0, pos = 0, i = 0;
   struct ast_dial **dial_list;
   unsigned int num_dials;
   int timeout = 0;
   char *parse;

   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(devices);
      AST_APP_ARG(options);
      AST_APP_ARG(timeout);
   );

   if (ast_strlen_zero(data)) {
      ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
      return -1;
   }

   if (!(app = pbx_findapp("MeetMe"))) {
      ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
      return -1;
   };

   parse = ast_strdupa(data);

   AST_STANDARD_APP_ARGS(args, parse);

   ast_copy_string(originator, chan->name, sizeof(originator));
   if ((tmp = strchr(originator, '-'))) {
      *tmp = '\0';
   }

   if (!ast_strlen_zero(args.options)) {
      ast_app_parse_options(page_opts, &flags, opts, args.options);
   }

   if (!ast_strlen_zero(args.timeout)) {
      timeout = atoi(args.timeout);
   }

   if (ast_test_flag(&flags, PAGE_ANNOUNCE) && !ast_strlen_zero(opts[OPT_ARG_ANNOUNCE])) {
      snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)G(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
                   (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), opts[OPT_ARG_ANNOUNCE] );
   } else {
      snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
      (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
   }

   /* Count number of extensions in list by number of ampersands + 1 */
   num_dials = 1;
   tmp = args.devices;
   while (*tmp) {
      if (*tmp == '&') {
         num_dials++;
      }
      tmp++;
   }

   if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
      ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
      return -1;
   }

   /* Go through parsing/calling each device */
   while ((tech = strsep(&args.devices, "&"))) {
      int state = 0;
      struct ast_dial *dial = NULL;

      /* don't call the originating device */
      if (!strcasecmp(tech, originator))
         continue;

      /* If no resource is available, continue on */
      if (!(resource = strchr(tech, '/'))) {
         ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
         continue;
      }

      /* Ensure device is not in use if skip option is enabled */
      if (ast_test_flag(&flags, PAGE_SKIP)) {
         state = ast_device_state(tech);
         if (state == AST_DEVICE_UNKNOWN) {
            ast_log(LOG_WARNING, "Destination '%s' has device state '%s'. Paging anyway.\n", tech, ast_devstate2str(state));
         } else if (state != AST_DEVICE_NOT_INUSE) {
            ast_log(LOG_WARNING, "Destination '%s' has device state '%s'.\n", tech, ast_devstate2str(state));
            continue;
         }
      }

      *resource++ = '\0';

      /* Create a dialing structure */
      if (!(dial = ast_dial_create())) {
         ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
         continue;
      }

      /* Append technology and resource */
      if (ast_dial_append(dial, tech, resource) == -1) {
         ast_log(LOG_ERROR, "Failed to add %s to outbound dial\n", tech);
         continue;
      }

      /* Set ANSWER_EXEC as global option */
      ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);

      if (timeout) {
         ast_dial_set_global_timeout(dial, timeout * 1000);
      }

      if (ast_test_flag(&flags, PAGE_IGNORE_FORWARDS)) {
         ast_dial_option_global_enable(dial, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL);
      }

      /* Run this dial in async mode */
      ast_dial_run(dial, chan, 1);

      /* Put in our dialing array */
      dial_list[pos++] = dial;
   }

   if (!ast_test_flag(&flags, PAGE_QUIET)) {
      res = ast_streamfile(chan, "beep", chan->language);
      if (!res)
         res = ast_waitstream(chan, "");
   }

   if (!res) {
      /* Default behaviour */
      snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"), 
         (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
      if (ast_test_flag(&flags, PAGE_ANNOUNCE) && !ast_strlen_zero(opts[OPT_ARG_ANNOUNCE]) &&
            !ast_test_flag(&flags, PAGE_NOCALLERANNOUNCE)) {
         snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxdG(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"), 
           (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), opts[OPT_ARG_ANNOUNCE] );
      }
      pbx_exec(chan, app, meetmeopts);
   }

   /* Go through each dial attempt cancelling, joining, and destroying */
   for (i = 0; i < pos; i++) {
      struct ast_dial *dial = dial_list[i];

      /* We have to wait for the async thread to exit as it's possible Meetme won't throw them out immediately */
      ast_dial_join(dial);

      /* Hangup all channels */
      ast_dial_hangup(dial);

      /* Destroy dialing structure */
      ast_dial_destroy(dial);
   }

   return -1;
}
static int unload_module ( void  ) [static]

Definition at line 303 of file app_page.c.

References ast_unregister_application().


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Page Multiple Phones" , .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 313 of file app_page.c.

const char* const app_page = "Page" [static]

Definition at line 112 of file app_page.c.

Definition at line 313 of file app_page.c.

struct ast_app_option page_opts[128] = { [ 'd' ] = { .flag = PAGE_DUPLEX }, [ 'q' ] = { .flag = PAGE_QUIET }, [ 'r' ] = { .flag = PAGE_RECORD }, [ 's' ] = { .flag = PAGE_SKIP }, [ 'i' ] = { .flag = PAGE_IGNORE_FORWARDS }, [ 'i' ] = { .flag = PAGE_IGNORE_FORWARDS }, [ 'A' ] = { .flag = PAGE_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'n' ] = { .flag = PAGE_NOCALLERANNOUNCE },} [static]

Definition at line 138 of file app_page.c.

Referenced by page_exec().