Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:48 2009

## Asterisk developer's documentation

# app_page.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (c) 2004 - 2006 Digium, Inc.  All rights reserved.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * This code is released under the GNU General Public License
    00009  * version 2.0.  See LICENSE for more information.
    00010  *
    00011  * See http://www.asterisk.org for more information about
    00012  * the Asterisk project. Please do not directly contact
    00013  * any of the maintainers of this project for assistance;
    00014  * the project provides a web site, mailing lists and IRC
    00015  * channels for your use.
    00016  *
    00017  */
    00018
    00019 /*! \file
    00020  *
    00021  * \brief page() - Paging application
    00022  *
    00023  * \ingroup applications
    00024  */
    00025
    00026 #include <stdio.h>
    00027 #include <stdlib.h>
    00028 #include <unistd.h>
    00029 #include <string.h>
    00030 #include <errno.h>
    00031
    00032 #include "asterisk.h"
    00033
    00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 55588 $")
    00035
    00036 #include "asterisk/options.h"
    00037 #include "asterisk/logger.h"
    00038 #include "asterisk/channel.h"
    00039 #include "asterisk/pbx.h"
    00040 #include "asterisk/module.h"
    00041 #include "asterisk/file.h"
    00042 #include "asterisk/app.h"
    00043 #include "asterisk/chanvars.h"
    00044
    00045
    00046 static const char *tdesc = "Page Multiple Phones";
    00047
    00048 static const char *app_page= "Page";
    00049
    00050 static const char *page_synopsis = "Pages phones";
    00051
    00052 static const char *page_descrip =
    00053 "Page(Technology/Resource&Technology2/Resource2[|options])\n"
    00054 "  Places outbound calls to the given technology / resource and dumps\n"
    00055 "them into a conference bridge as muted participants.  The original\n"
    00056 "caller is dumped into the conference as a speaker and the room is\n"
    00057 "destroyed when the original caller leaves.  Valid options are:\n"
    00058 "        d - full duplex audio\n"
    00059 "        q - quiet, do not play beep to caller\n";
    00060
    00061 STANDARD_LOCAL_USER;
    00062
    00063 LOCAL_USER_DECL;
    00064
    00065 enum {
    00066    PAGE_DUPLEX = (1 << 0),
    00067    PAGE_QUIET = (1 << 1),
    00068 } page_opt_flags;
    00069
    00070 AST_APP_OPTIONS(page_opts, {
    00071    AST_APP_OPTION('d', PAGE_DUPLEX),
    00072    AST_APP_OPTION('q', PAGE_QUIET),
    00073 });
    00074
    00075 struct calloutdata {
    00076    char cidnum[64];
    00077    char cidname[64];
    00078    char tech[64];
    00079    char resource[256];
    00080    char meetmeopts[64];
    00081    struct ast_variable *variables;
    00082 };
    00083
    00084 static void *page_thread(void *data)
    00085 {
    00086    struct calloutdata *cd = data;
    00087    ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
    00088       "MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
    00089    free(cd);
    00090    return NULL;
    00091 }
    00092
    00093 static void launch_page(struct ast_channel *chan, const char *meetmeopts, const char *tech, const char *resource)
    00094 {
    00095    struct calloutdata *cd;
    00096    const char *varname;
    00097    struct ast_variable *lastvar = NULL;
    00098    struct ast_var_t *varptr;
    00099    pthread_t t;
    00100    pthread_attr_t attr;
    00101    cd = malloc(sizeof(struct calloutdata));
    00102    if (cd) {
    00103       memset(cd, 0, sizeof(struct calloutdata));
    00104       ast_copy_string(cd->cidnum, chan->cid.cid_num ? chan->cid.cid_num : "", sizeof(cd->cidnum));
    00105       ast_copy_string(cd->cidname, chan->cid.cid_name ? chan->cid.cid_name : "", sizeof(cd->cidname));
    00106       ast_copy_string(cd->tech, tech, sizeof(cd->tech));
    00107       ast_copy_string(cd->resource, resource, sizeof(cd->resource));
    00108       ast_copy_string(cd->meetmeopts, meetmeopts, sizeof(cd->meetmeopts));
    00109
    00110       AST_LIST_TRAVERSE(&chan->varshead, varptr, entries) {
    00111          if (!(varname = ast_var_full_name(varptr)))
    00112             continue;
    00113          if (varname[0] == '_') {
    00114             struct ast_variable *newvar = NULL;
    00115
    00116             if (varname[1] == '_') {
    00117                newvar = ast_variable_new(varname, ast_var_value(varptr));
    00118             } else {
    00119                newvar = ast_variable_new(&varname[1], ast_var_value(varptr));
    00120             }
    00121
    00122             if (newvar) {
    00123                if (lastvar)
    00124                   lastvar->next = newvar;
    00125                else
    00126                   cd->variables = newvar;
    00127                lastvar = newvar;
    00128             }
    00129          }
    00130       }
    00131
    00132       pthread_attr_init(&attr);
    00133       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    00134       if (ast_pthread_create(&t, &attr, page_thread, cd)) {
    00135          ast_log(LOG_WARNING, "Unable to create paging thread: %s\n", strerror(errno));
    00136          free(cd);
    00137       }
    00138       pthread_attr_destroy(&attr);
    00139    }
    00140 }
    00141
    00142 static int page_exec(struct ast_channel *chan, void *data)
    00143 {
    00144    struct localuser *u;
    00145    char *options;
    00146    char *tech, *resource;
    00147    char meetmeopts[80];
    00148    struct ast_flags flags = { 0 };
    00149    unsigned int confid = rand();
    00150    struct ast_app *app;
    00151    char *tmp;
    00152    int res=0;
    00153    char originator[AST_CHANNEL_NAME];
    00154
    00155    if (ast_strlen_zero(data)) {
    00156       ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
    00157       return -1;
    00158    }
    00159
    00160    LOCAL_USER_ADD(u);
    00161
    00162    if (!(app = pbx_findapp("MeetMe"))) {
    00163       ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
    00164       LOCAL_USER_REMOVE(u);
    00165       return -1;
    00166    };
    00167
    00168    options = ast_strdupa(data);
    00169    if (!options) {
    00170       ast_log(LOG_ERROR, "Out of memory\n");
    00171       LOCAL_USER_REMOVE(u);
    00172       return -1;
    00173    }
    00174
    00175    ast_copy_string(originator, chan->name, sizeof(originator));
    00176    if ((tmp = strchr(originator, '-')))
    00177       *tmp = '\0';
    00178
    00179    tmp = strsep(&options, "|");
    00180    if (options)
    00181       ast_app_parse_options(page_opts, &flags, NULL, options);
    00182
    00183    snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw(5)", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
    00184
    00185    while ((tech = strsep(&tmp, "&"))) {
    00186       /* don't call the originating device */
    00187       if (!strcasecmp(tech, originator))
    00188          continue;
    00189
    00190       if ((resource = strchr(tech, '/'))) {
    00191          *resource++ = '\0';
    00192          launch_page(chan, meetmeopts, tech, resource);
    00193       } else {
    00194          ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
    00195       }
    00196    }
    00197
    00198    if (!ast_test_flag(&flags, PAGE_QUIET)) {
    00199       res = ast_streamfile(chan, "beep", chan->language);
    00200       if (!res)
    00201          res = ast_waitstream(chan, "");
    00202    }
    00203    if (!res) {
    00204       snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
    00205       pbx_exec(chan, app, meetmeopts, 1);
    00206    }
    00207
    00208    LOCAL_USER_REMOVE(u);
    00209
    00210    return -1;
    00211 }
    00212
    00213 int unload_module(void)
    00214 {
    00215    int res;
    00216
    00217    res =  ast_unregister_application(app_page);
    00218
    00219    STANDARD_HANGUP_LOCALUSERS;
    00220
    00221    return res;
    00222 }
    00223
    00224 int load_module(void)
    00225 {
    00226    return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
    00227 }
    00228
    00229 char *description(void)
    00230 {
    00231    return (char *) tdesc;
    00232 }
    00233
    00234 int usecount(void)
    00235 {
    00236    int res;
    00237
    00238    STANDARD_USECOUNT(res);
    00239
    00240    return res;
    00241 }
    00242
    00243 char *key()
    00244 {
    00245    return ASTERISK_GPL_KEY;
    00246 }