00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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: 9607 $")
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
00153 if (ast_strlen_zero(data)) {
00154 ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
00155 return -1;
00156 }
00157
00158 LOCAL_USER_ADD(u);
00159
00160 if (!(app = pbx_findapp("MeetMe"))) {
00161 ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
00162 LOCAL_USER_REMOVE(u);
00163 return -1;
00164 };
00165
00166 options = ast_strdupa(data);
00167 if (!options) {
00168 ast_log(LOG_ERROR, "Out of memory\n");
00169 LOCAL_USER_REMOVE(u);
00170 return -1;
00171 }
00172
00173 tmp = strsep(&options, "|");
00174 if (options)
00175 ast_app_parse_options(page_opts, &flags, NULL, options);
00176
00177 snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
00178 while ((tech = strsep(&tmp, "&"))) {
00179 if ((resource = strchr(tech, '/'))) {
00180 *resource++ = '\0';
00181 launch_page(chan, meetmeopts, tech, resource);
00182 } else {
00183 ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
00184 }
00185 }
00186 if (!ast_test_flag(&flags, PAGE_QUIET)) {
00187 res = ast_streamfile(chan, "beep", chan->language);
00188 if (!res)
00189 res = ast_waitstream(chan, "");
00190 }
00191 if (!res) {
00192 snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
00193 pbx_exec(chan, app, meetmeopts, 1);
00194 }
00195
00196 LOCAL_USER_REMOVE(u);
00197
00198 return -1;
00199 }
00200
00201 int unload_module(void)
00202 {
00203 int res;
00204
00205 res = ast_unregister_application(app_page);
00206
00207 STANDARD_HANGUP_LOCALUSERS;
00208
00209 return res;
00210 }
00211
00212 int load_module(void)
00213 {
00214 return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
00215 }
00216
00217 char *description(void)
00218 {
00219 return (char *) tdesc;
00220 }
00221
00222 int usecount(void)
00223 {
00224 int res;
00225
00226 STANDARD_USECOUNT(res);
00227
00228 return res;
00229 }
00230
00231 char *key()
00232 {
00233 return ASTERISK_GPL_KEY;
00234 }