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
00027
00028
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <sys/types.h>
00034
00035 #include "asterisk.h"
00036
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00038
00039 #include "asterisk/file.h"
00040 #include "asterisk/logger.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/pbx.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/features.h"
00045 #include "asterisk/options.h"
00046 #include "asterisk/logger.h"
00047 #include "asterisk/say.h"
00048 #include "asterisk/lock.h"
00049
00050 static char *tdesc = "Call Parking and Announce Application";
00051
00052 static char *app = "ParkAndAnnounce";
00053
00054 static char *synopsis = "Park and Announce";
00055
00056 static char *descrip =
00057 " ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
00058 "Park a call into the parkinglot and announce the call over the console.\n"
00059 "announce template: colon separated list of files to announce, the word PARKED\n"
00060 " will be replaced by a say_digits of the ext the call is parked in\n"
00061 "timeout: time in seconds before the call returns into the return context.\n"
00062 "dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
00063 "return_context: the goto style label to jump the call back into after timeout. default=prio+1\n";
00064
00065
00066 STANDARD_LOCAL_USER;
00067
00068 LOCAL_USER_DECL;
00069
00070 static int parkandannounce_exec(struct ast_channel *chan, void *data)
00071 {
00072 int res=0;
00073 char *return_context;
00074 int l, lot, timeout = 0, dres;
00075 char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
00076 char *template, *tpl_working, *tpl_current;
00077 char *tmp[100];
00078 int looptemp=0,i=0;
00079 char *s,*orig_s;
00080
00081 struct ast_channel *dchan;
00082 struct outgoing_helper oh;
00083 int outstate;
00084
00085 struct localuser *u;
00086
00087 if (ast_strlen_zero(data)) {
00088 ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
00089 return -1;
00090 }
00091
00092 LOCAL_USER_ADD(u);
00093
00094 l=strlen(data)+2;
00095 orig_s=malloc(l);
00096 if(!orig_s) {
00097 ast_log(LOG_WARNING, "Out of memory\n");
00098 LOCAL_USER_REMOVE(u);
00099 return -1;
00100 }
00101 s=orig_s;
00102 strncpy(s,data,l);
00103
00104 template=strsep(&s,"|");
00105 if(! template) {
00106 ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
00107 free(orig_s);
00108 LOCAL_USER_REMOVE(u);
00109 return -1;
00110 }
00111
00112 if(s) {
00113 timeout = atoi(strsep(&s, "|"));
00114 timeout *= 1000;
00115 }
00116 dial=strsep(&s, "|");
00117 if(!dial) {
00118 ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
00119 free(orig_s);
00120 LOCAL_USER_REMOVE(u);
00121 return -1;
00122 } else {
00123 dialtech=strsep(&dial, "/");
00124 dialstr=dial;
00125 ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
00126 }
00127
00128 return_context = s;
00129
00130 if(return_context != NULL) {
00131
00132
00133 working = return_context;
00134 context = strsep(&working, "|");
00135 exten = strsep(&working, "|");
00136 if(!exten) {
00137
00138 priority = context;
00139 exten = NULL;
00140 context = NULL;
00141 } else {
00142 priority = strsep(&working, "|");
00143 if(!priority) {
00144
00145 priority = exten;
00146 exten = context;
00147 context = NULL;
00148 }
00149 }
00150 if(atoi(priority) < 0) {
00151 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
00152 free(orig_s);
00153 LOCAL_USER_REMOVE(u);
00154 return -1;
00155 }
00156
00157 chan->priority = atoi(priority);
00158 if(exten && strcasecmp(exten, "BYEXTENSION"))
00159 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
00160 if(context)
00161 strncpy(chan->context, context, sizeof(chan->context)-1);
00162 } else {
00163 chan->priority++;
00164 }
00165
00166 if(option_verbose > 2) {
00167 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
00168 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
00169 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
00170 }
00171 }
00172
00173
00174
00175
00176 ast_masq_park_call(chan, NULL, timeout, &lot);
00177
00178 res=-1;
00179
00180 ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
00181
00182
00183
00184 memset(&oh, 0, sizeof(oh));
00185 oh.parent_channel = chan;
00186 dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
00187
00188 if(dchan) {
00189 if(dchan->_state == AST_STATE_UP) {
00190 if(option_verbose > 3)
00191 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
00192 } else {
00193 if(option_verbose > 3)
00194 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
00195 ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
00196 ast_hangup(dchan);
00197 free(orig_s);
00198 LOCAL_USER_REMOVE(u);
00199 return -1;
00200 }
00201 } else {
00202 ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
00203 free(orig_s);
00204 LOCAL_USER_REMOVE(u);
00205 return -1;
00206 }
00207
00208 ast_stopstream(dchan);
00209
00210
00211
00212 ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
00213
00214 tpl_working = template;
00215 tpl_current=strsep(&tpl_working, ":");
00216
00217 while(tpl_current && looptemp < sizeof(tmp)) {
00218 tmp[looptemp]=tpl_current;
00219 looptemp++;
00220 tpl_current=strsep(&tpl_working,":");
00221 }
00222
00223 for(i=0; i<looptemp; i++) {
00224 ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
00225 if(!strcmp(tmp[i], "PARKED")) {
00226 ast_say_digits(dchan, lot, "", dchan->language);
00227 } else {
00228 dres = ast_streamfile(dchan, tmp[i], dchan->language);
00229 if(!dres) {
00230 dres = ast_waitstream(dchan, "");
00231 } else {
00232 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
00233 dres = 0;
00234 }
00235 }
00236 }
00237
00238 ast_stopstream(dchan);
00239 ast_hangup(dchan);
00240 free(orig_s);
00241
00242 LOCAL_USER_REMOVE(u);
00243
00244 return res;
00245 }
00246
00247
00248
00249 int unload_module(void)
00250 {
00251 int res;
00252
00253 res = ast_unregister_application(app);
00254
00255 STANDARD_HANGUP_LOCALUSERS;
00256
00257 return res;
00258 }
00259
00260 int load_module(void)
00261 {
00262
00263 return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
00264 }
00265
00266 char *description(void)
00267 {
00268 return tdesc;
00269 }
00270
00271 int usecount(void)
00272 {
00273 int res;
00274 STANDARD_USECOUNT(res);
00275 return res;
00276 }
00277
00278 char *key()
00279 {
00280 return ASTERISK_GPL_KEY;
00281 }