Sat Sep 16 07:28:05 2006

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: 42783 $")
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    }
00139 }
00140 
00141 static int page_exec(struct ast_channel *chan, void *data)
00142 {
00143    struct localuser *u;
00144    char *options;
00145    char *tech, *resource;
00146    char meetmeopts[80];
00147    struct ast_flags flags = { 0 };
00148    unsigned int confid = rand();
00149    struct ast_app *app;
00150    char *tmp;
00151    int res=0;
00152    char originator[AST_CHANNEL_NAME];
00153 
00154    if (ast_strlen_zero(data)) {
00155       ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
00156       return -1;
00157    }
00158 
00159    LOCAL_USER_ADD(u);
00160 
00161    if (!(app = pbx_findapp("MeetMe"))) {
00162       ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
00163       LOCAL_USER_REMOVE(u);
00164       return -1;
00165    };
00166 
00167    options = ast_strdupa(data);
00168    if (!options) {
00169       ast_log(LOG_ERROR, "Out of memory\n");
00170       LOCAL_USER_REMOVE(u);
00171       return -1;
00172    }
00173 
00174    ast_copy_string(originator, chan->name, sizeof(originator));
00175    if ((tmp = strchr(originator, '-')))
00176       *tmp = '\0';
00177 
00178    tmp = strsep(&options, "|");
00179    if (options)
00180       ast_app_parse_options(page_opts, &flags, NULL, options);
00181 
00182    snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw(5)", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
00183 
00184    while ((tech = strsep(&tmp, "&"))) {
00185       /* don't call the originating device */
00186       if (!strcasecmp(tech, originator))
00187          continue;
00188 
00189       if ((resource = strchr(tech, '/'))) {
00190          *resource++ = '\0';
00191          launch_page(chan, meetmeopts, tech, resource);
00192       } else {
00193          ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
00194       }
00195    }
00196 
00197    if (!ast_test_flag(&flags, PAGE_QUIET)) {
00198       res = ast_streamfile(chan, "beep", chan->language);
00199       if (!res)
00200          res = ast_waitstream(chan, "");
00201    }
00202    if (!res) {
00203       snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
00204       pbx_exec(chan, app, meetmeopts, 1);
00205    }
00206 
00207    LOCAL_USER_REMOVE(u);
00208 
00209    return -1;
00210 }
00211 
00212 int unload_module(void)
00213 {
00214    int res;
00215 
00216    res =  ast_unregister_application(app_page);
00217 
00218    STANDARD_HANGUP_LOCALUSERS;
00219 
00220    return res;
00221 }
00222 
00223 int load_module(void)
00224 {
00225    return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
00226 }
00227 
00228 char *description(void)
00229 {
00230    return (char *) tdesc;
00231 }
00232 
00233 int usecount(void)
00234 {
00235    int res;
00236 
00237    STANDARD_USECOUNT(res);
00238 
00239    return res;
00240 }
00241 
00242 char *key()
00243 {
00244    return ASTERISK_GPL_KEY;
00245 }

Generated on Sat Sep 16 07:28:05 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7