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 }

Generated on Wed Oct 28 15:47:48 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6