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.

Data Structures

struct  page_options

Enumerations

enum  { OPT_ARG_ANNOUNCE = 0, OPT_ARG_PREDIAL_CALLEE = 1, OPT_ARG_PREDIAL_CALLER = 2, OPT_ARG_ARRAY_SIZE = 3 }
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), PAGE_PREDIAL_CALLEE = (1 << 7),
  PAGE_PREDIAL_CALLER = (1 << 8)
}

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 void page_state_callback (struct ast_dial *dial)
static void setup_profile_bridge (struct ast_channel *chan, struct page_options *options)
static void setup_profile_caller (struct ast_channel *chan, struct page_options *options)
static void setup_profile_paged (struct ast_channel *chan, struct page_options *options)
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, .support_level = AST_MODULE_SUPPORT_CORE, }
static const char *const app_page = "Page"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_app_option page_opts [128] = { [ 'b' ] = { .flag = PAGE_PREDIAL_CALLEE , .arg_index = OPT_ARG_PREDIAL_CALLEE + 1 }, [ 'B' ] = { .flag = PAGE_PREDIAL_CALLER , .arg_index = OPT_ARG_PREDIAL_CALLER + 1 }, [ 'd' ] = { .flag = PAGE_DUPLEX }, [ 'q' ] = { .flag = PAGE_QUIET }, [ 'r' ] = { .flag = PAGE_RECORD }, [ 's' ] = { .flag = PAGE_SKIP }, [ '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_PREDIAL_CALLEE 
OPT_ARG_PREDIAL_CALLER 
OPT_ARG_ARRAY_SIZE 

Definition at line 146 of file app_page.c.

00146      {
00147    OPT_ARG_ANNOUNCE = 0,
00148    OPT_ARG_PREDIAL_CALLEE = 1,
00149    OPT_ARG_PREDIAL_CALLER = 2,
00150    OPT_ARG_ARRAY_SIZE = 3,
00151 };

Enumerator:
PAGE_DUPLEX 
PAGE_QUIET 
PAGE_RECORD 
PAGE_SKIP 
PAGE_IGNORE_FORWARDS 
PAGE_ANNOUNCE 
PAGE_NOCALLERANNOUNCE 
PAGE_PREDIAL_CALLEE 
PAGE_PREDIAL_CALLER 

Definition at line 134 of file app_page.c.

00134                     {
00135    PAGE_DUPLEX = (1 << 0),
00136    PAGE_QUIET = (1 << 1),
00137    PAGE_RECORD = (1 << 2),
00138    PAGE_SKIP = (1 << 3),
00139    PAGE_IGNORE_FORWARDS = (1 << 4),
00140    PAGE_ANNOUNCE = (1 << 5),
00141    PAGE_NOCALLERANNOUNCE = (1 << 6),
00142    PAGE_PREDIAL_CALLEE = (1 << 7),
00143    PAGE_PREDIAL_CALLER = (1 << 8),
00144 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 429 of file app_page.c.

static void __unreg_module ( void   )  [static]

Definition at line 429 of file app_page.c.

static int load_module ( void   )  [static]

Definition at line 424 of file app_page.c.

References ast_register_application_xml, and page_exec().

00425 {
00426    return ast_register_application_xml(app_page, page_exec);
00427 }

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

Definition at line 250 of file app_page.c.

References app, args, AST_APP_ARG, ast_app_exec_sub(), ast_app_parse_options(), ast_calloc, ast_channel_language(), ast_channel_name(), 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_OPTION_PREDIAL, ast_dial_run(), ast_dial_set_global_timeout(), ast_dial_set_state_callback(), ast_dial_set_user_data(), ast_free, ast_log, ast_random(), ast_replace_subargument_delimiter(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_streamfile(), ast_strlen_zero, ast_test_flag, ast_waitstream(), page_options::flags, LOG_ERROR, LOG_WARNING, NULL, OPT_ARG_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLER, page_options::opts, PAGE_IGNORE_FORWARDS, page_opts, PAGE_PREDIAL_CALLEE, PAGE_PREDIAL_CALLER, PAGE_QUIET, PAGE_SKIP, page_state_callback(), parse(), pbx_exec(), pbx_findapp(), setup_profile_bridge(), setup_profile_caller(), strsep(), timeout, and tmp().

Referenced by load_module().

00251 {
00252    char *tech, *resource, *tmp;
00253    char confbridgeopts[128], originator[AST_CHANNEL_NAME];
00254    struct page_options options = { { 0, }, { 0, } };
00255    unsigned int confid = ast_random();
00256    struct ast_app *app;
00257    int res = 0, pos = 0, i = 0;
00258    struct ast_dial **dial_list;
00259    unsigned int num_dials;
00260    int timeout = 0;
00261    char *parse;
00262 
00263    AST_DECLARE_APP_ARGS(args,
00264       AST_APP_ARG(devices);
00265       AST_APP_ARG(options);
00266       AST_APP_ARG(timeout);
00267    );
00268 
00269    if (ast_strlen_zero(data)) {
00270       ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
00271       return -1;
00272    }
00273 
00274    if (!(app = pbx_findapp("ConfBridge"))) {
00275       ast_log(LOG_WARNING, "There is no ConfBridge application available!\n");
00276       return -1;
00277    };
00278 
00279    parse = ast_strdupa(data);
00280 
00281    AST_STANDARD_APP_ARGS(args, parse);
00282 
00283    ast_copy_string(originator, ast_channel_name(chan), sizeof(originator));
00284    if ((tmp = strchr(originator, '-'))) {
00285       *tmp = '\0';
00286    }
00287 
00288    if (!ast_strlen_zero(args.options)) {
00289       ast_app_parse_options(page_opts, &options.flags, options.opts, args.options);
00290    }
00291 
00292    if (!ast_strlen_zero(args.timeout)) {
00293       timeout = atoi(args.timeout);
00294    }
00295 
00296    snprintf(confbridgeopts, sizeof(confbridgeopts), "ConfBridge,%u", confid);
00297 
00298    /* Count number of extensions in list by number of ampersands + 1 */
00299    num_dials = 1;
00300    tmp = args.devices;
00301    while (*tmp) {
00302       if (*tmp == '&') {
00303          num_dials++;
00304       }
00305       tmp++;
00306    }
00307 
00308    if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
00309       ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
00310       return -1;
00311    }
00312 
00313    if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLER)
00314       && !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLER])) {
00315       ast_replace_subargument_delimiter(options.opts[OPT_ARG_PREDIAL_CALLER]);
00316       ast_app_exec_sub(NULL, chan, options.opts[OPT_ARG_PREDIAL_CALLER], 0);
00317    }
00318 
00319    /* Go through parsing/calling each device */
00320    while ((tech = strsep(&args.devices, "&"))) {
00321       int state = 0;
00322       struct ast_dial *dial = NULL;
00323 
00324       /* don't call the originating device */
00325       if (!strcasecmp(tech, originator))
00326          continue;
00327 
00328       /* If no resource is available, continue on */
00329       if (!(resource = strchr(tech, '/'))) {
00330          ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
00331          continue;
00332       }
00333 
00334       /* Ensure device is not in use if skip option is enabled */
00335       if (ast_test_flag(&options.flags, PAGE_SKIP)) {
00336          state = ast_device_state(tech);
00337          if (state == AST_DEVICE_UNKNOWN) {
00338             ast_log(LOG_WARNING, "Destination '%s' has device state '%s'. Paging anyway.\n", tech, ast_devstate2str(state));
00339          } else if (state != AST_DEVICE_NOT_INUSE) {
00340             ast_log(LOG_WARNING, "Destination '%s' has device state '%s'.\n", tech, ast_devstate2str(state));
00341             continue;
00342          }
00343       }
00344 
00345       *resource++ = '\0';
00346 
00347       /* Create a dialing structure */
00348       if (!(dial = ast_dial_create())) {
00349          ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
00350          continue;
00351       }
00352 
00353       /* Append technology and resource */
00354       if (ast_dial_append(dial, tech, resource, NULL) == -1) {
00355          ast_log(LOG_ERROR, "Failed to add %s to outbound dial\n", tech);
00356          ast_dial_destroy(dial);
00357          continue;
00358       }
00359 
00360       /* Set ANSWER_EXEC as global option */
00361       ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, confbridgeopts);
00362 
00363       if (ast_test_flag(&options.flags, PAGE_PREDIAL_CALLEE)
00364          && !ast_strlen_zero(options.opts[OPT_ARG_PREDIAL_CALLEE])) {
00365          ast_dial_option_global_enable(dial, AST_DIAL_OPTION_PREDIAL, options.opts[OPT_ARG_PREDIAL_CALLEE]);
00366       }
00367 
00368       if (timeout) {
00369          ast_dial_set_global_timeout(dial, timeout * 1000);
00370       }
00371 
00372       if (ast_test_flag(&options.flags, PAGE_IGNORE_FORWARDS)) {
00373          ast_dial_option_global_enable(dial, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL);
00374       }
00375 
00376       ast_dial_set_state_callback(dial, &page_state_callback);
00377       ast_dial_set_user_data(dial, &options);
00378 
00379       /* Run this dial in async mode */
00380       ast_dial_run(dial, chan, 1);
00381 
00382       /* Put in our dialing array */
00383       dial_list[pos++] = dial;
00384    }
00385 
00386    if (!ast_test_flag(&options.flags, PAGE_QUIET)) {
00387       res = ast_streamfile(chan, "beep", ast_channel_language(chan));
00388       if (!res)
00389          res = ast_waitstream(chan, "");
00390    }
00391 
00392    if (!res) {
00393       setup_profile_bridge(chan, &options);
00394       setup_profile_caller(chan, &options);
00395 
00396       snprintf(confbridgeopts, sizeof(confbridgeopts), "%u", confid);
00397       pbx_exec(chan, app, confbridgeopts);
00398    }
00399 
00400    /* Go through each dial attempt cancelling, joining, and destroying */
00401    for (i = 0; i < pos; i++) {
00402       struct ast_dial *dial = dial_list[i];
00403 
00404       /* We have to wait for the async thread to exit as it's possible ConfBridge won't throw them out immediately */
00405       ast_dial_join(dial);
00406 
00407       /* Hangup all channels */
00408       ast_dial_hangup(dial);
00409 
00410       /* Destroy dialing structure */
00411       ast_dial_destroy(dial);
00412    }
00413 
00414    ast_free(dial_list);
00415 
00416    return -1;
00417 }

static void page_state_callback ( struct ast_dial dial  )  [static]

Definition at line 235 of file app_page.c.

References ast_dial_answered(), ast_dial_get_user_data(), AST_DIAL_RESULT_ANSWERED, ast_dial_state(), setup_profile_bridge(), and setup_profile_paged().

Referenced by page_exec().

00236 {
00237    struct ast_channel *chan;
00238    struct page_options *options;
00239 
00240    if (ast_dial_state(dial) != AST_DIAL_RESULT_ANSWERED ||
00241        !(chan = ast_dial_answered(dial)) ||
00242        !(options = ast_dial_get_user_data(dial))) {
00243       return;
00244    }
00245 
00246    setup_profile_bridge(chan, options);
00247    setup_profile_paged(chan, options);
00248 }

static void setup_profile_bridge ( struct ast_channel chan,
struct page_options options 
) [static]

Definition at line 180 of file app_page.c.

References ast_func_write(), ast_test_flag, page_options::flags, and PAGE_RECORD.

Referenced by page_exec(), and page_state_callback().

00181 {
00182    /* Use default_bridge as a starting point */
00183    ast_func_write(chan, "CONFBRIDGE(bridge,template)", "");
00184    if (ast_test_flag(&options->flags, PAGE_RECORD)) {
00185       ast_func_write(chan, "CONFBRIDGE(bridge,record_conference)", "yes");
00186    }
00187 }

static void setup_profile_caller ( struct ast_channel chan,
struct page_options options 
) [static]

Definition at line 222 of file app_page.c.

References ast_func_write(), ast_strlen_zero, ast_test_flag, page_options::flags, OPT_ARG_ANNOUNCE, page_options::opts, PAGE_ANNOUNCE, and PAGE_NOCALLERANNOUNCE.

Referenced by page_exec().

00223 {
00224    /* Use default_user as a starting point if not already setup. */
00225    ast_func_write(chan, "CONFBRIDGE(user,template)", "");
00226    ast_func_write(chan, "CONFBRIDGE(user,quiet)", "yes");
00227    ast_func_write(chan, "CONFBRIDGE(user,marked)", "yes");
00228    if (!ast_test_flag(&options->flags, PAGE_NOCALLERANNOUNCE)
00229       && ast_test_flag(&options->flags, PAGE_ANNOUNCE)
00230       && !ast_strlen_zero(options->opts[OPT_ARG_ANNOUNCE])) {
00231       ast_func_write(chan, "CONFBRIDGE(user,announcement)", options->opts[OPT_ARG_ANNOUNCE]);
00232    }
00233 }

static void setup_profile_paged ( struct ast_channel chan,
struct page_options options 
) [static]

Definition at line 198 of file app_page.c.

References ast_func_write(), ast_strlen_zero, ast_test_flag, page_options::flags, OPT_ARG_ANNOUNCE, page_options::opts, PAGE_ANNOUNCE, and PAGE_DUPLEX.

Referenced by page_state_callback().

00199 {
00200    /* Use default_user as a starting point */
00201    ast_func_write(chan, "CONFBRIDGE(user,template)", "");
00202    ast_func_write(chan, "CONFBRIDGE(user,quiet)", "yes");
00203    ast_func_write(chan, "CONFBRIDGE(user,end_marked)", "yes");
00204    if (!ast_test_flag(&options->flags, PAGE_DUPLEX)) {
00205       ast_func_write(chan, "CONFBRIDGE(user,startmuted)", "yes");
00206    }
00207    if (ast_test_flag(&options->flags, PAGE_ANNOUNCE)
00208       && !ast_strlen_zero(options->opts[OPT_ARG_ANNOUNCE])) {
00209       ast_func_write(chan, "CONFBRIDGE(user,announcement)", options->opts[OPT_ARG_ANNOUNCE]);
00210    }
00211 }

static int unload_module ( void   )  [static]

Definition at line 419 of file app_page.c.

References ast_unregister_application().

00420 {
00421    return ast_unregister_application(app_page);
00422 }


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, .support_level = AST_MODULE_SUPPORT_CORE, } [static]

Definition at line 429 of file app_page.c.

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

Definition at line 132 of file app_page.c.

Definition at line 429 of file app_page.c.

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

Definition at line 163 of file app_page.c.

Referenced by page_exec().


Generated on Thu Apr 16 06:28:37 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6