Thu Apr 28 2011 17:13:38

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  {
  PAGE_DUPLEX = (1 << 0), PAGE_QUIET = (1 << 1), PAGE_RECORD = (1 << 2), PAGE_SKIP = (1 << 3),
  PAGE_IGNORE_FORWARDS = (1 << 4)
}

Functions

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

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Page Multiple Phones" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static const char * app_page = "Page"
static struct ast_module_infoast_module_info = &__mod_info
enum { ... }  page_opt_flags
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 },}

Detailed Description

page() - Paging application

Author:
Mark Spencer <markster@digium.com>

Definition in file app_page.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
PAGE_DUPLEX 
PAGE_QUIET 
PAGE_RECORD 
PAGE_SKIP 
PAGE_IGNORE_FORWARDS 

Definition at line 104 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_opt_flags;

Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 282 of file app_page.c.

static void __unreg_module ( void  ) [static]

Definition at line 282 of file app_page.c.

static int load_module ( void  ) [static]

Definition at line 277 of file app_page.c.

References ast_register_application_xml, and page_exec().

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

Definition at line 121 of file app_page.c.

References app, 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, ast_dial::options, PAGE_DUPLEX, PAGE_IGNORE_FORWARDS, 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[88], originator[AST_CHANNEL_NAME], *opts[0];
   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);
   }

   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) {
      snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"), 
         (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
      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 272 of file app_page.c.

References ast_unregister_application().


Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Page Multiple Phones" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 282 of file app_page.c.

const char* app_page = "Page" [static]

Definition at line 102 of file app_page.c.

Definition at line 282 of file app_page.c.

enum { ... } page_opt_flags
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 },} [static]

Definition at line 118 of file app_page.c.

Referenced by page_exec().