Oops
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Trivial application to dial a channel and send an URL on answer
5  * 
6  * Copyright (C) 1999-2004, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/say.h>
23 #include <asterisk/config.h>
24 #include <asterisk/features.h>
25 #include <asterisk/musiconhold.h>
26 #include <asterisk/callerid.h>
27 #include <asterisk/utils.h>
28 #include <asterisk/app.h>
29 #include <asterisk/causes.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <sys/time.h>
37 #include <sys/signal.h>
38 #include <netinet/in.h>
39
40 static char *tdesc = "Dialing Application";
41
42 static char *app = "Dial";
43
44 static char *synopsis = "Place a call and connect to the current channel";
45
46 static char *descrip =
47 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
48 "Requests one or more channels and places specified outgoing calls on them.\n"
49 "As soon as a channel answers, the Dial app will answer the originating\n"
50 "channel (if it needs to be answered) and will bridge a call with the channel\n"
51 "which first answered. All other calls placed by the Dial app will be hung up.\n"
52 "If a timeout is not specified, the Dial application will wait indefinitely\n"
53 "until either one of the called channels answers, the user hangs up, or all\n"
54 "channels return busy or error. In general, the dialer will return 0 if it\n"
55 "was unable to place the call, or the timeout expired. However, if all\n"
56 "channels were busy, and there exists an extension with priority n+101 (where\n"
57 "n is the priority of the dialer instance), then it will be the next\n"
58 "executed extension (this allows you to setup different behavior on busy from\n"
59 "no-answer).\n"
60 "  This application returns -1 if the originating channel hangs up, or if the\n"
61 "call is bridged and either of the parties in the bridge terminate the call.\n"
62 "The option string may contain zero or more of the following characters:\n"
63 "      't' -- allow the called user transfer the calling user by hitting #.\n"
64 "      'T' -- allow the calling user to transfer the call by hitting #.\n"
65 "      'f' -- Forces callerid to be set as the extension of the line \n"
66 "             making/redirecting the outgoing call. For example, some PSTNs\n"
67 "             don't allow callerids from other extensions then the ones\n"
68 "             that are assigned to you.\n"
69 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
70 "      'm' -- provide hold music to the calling party until answered.\n"
71 "      'M(x) -- Executes the macro (x) upon connect of the call\n"
72 "      'h' -- allow callee to hang up by hitting *.\n"
73 "      'H' -- allow caller to hang up by hitting *.\n"
74 "      'C' -- reset call detail record for this call.\n"
75 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
76 "      'g' -- goes on in context if the destination channel hangs up\n"
77 "      'A(x)' -- play an announcement to the called party, using x as file\n"
78 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
79 "      'D([digits])'  -- Send DTMF digit string *after* called party has answered\n"
80 "             but before the bridge. (w=500ms sec pause)\n"
81 "      'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
82 "             repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
83 "             The following special variables are optional:\n"
84 "             * LIMIT_PLAYAUDIO_CALLER    yes|no (default yes)\n"
85 "                                         Play sounds to the caller.\n"
86 "             * LIMIT_PLAYAUDIO_CALLEE    yes|no\n"
87 "                                         Play sounds to the callee.\n"
88 "             * LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
89 "             * LIMIT_CONNECT_FILE        File to play when call begins.\n"
90 "             * LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
91 "                        'timeleft' is a special sound macro to auto-say the time \n"
92 "                        left and is the default.\n\n"
93 "  In addition to transferring the call, a call may be parked and then picked\n"
94 "up by another user.\n"
95 "  The optional URL will be sent to the called party if the channel supports it.\n"
96 "  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
97 "  application will be put into that group (as in SetGroup).\n"
98 "  This application sets the following channel variables upon completion:\n"
99 "      DIALEDTIME    Time from dial to answer\n" 
100 "      ANSWEREDTIME  Time for actual call\n"
101 "      DIALSTATUS    The status of the call as a text string, one of\n"
102 "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
103 "";
104
105 /* We define a customer "local user" structure because we
106    use it not only for keeping track of what is in use but
107    also for keeping track of who we're dialing. */
108
109 struct localuser {
110         struct ast_channel *chan;
111         int stillgoing;
112         int allowredirect_in;
113         int allowredirect_out;
114         int ringbackonly;
115         int musiconhold;
116         int allowdisconnect_in;
117         int allowdisconnect_out;
118         int forcecallerid;
119         struct localuser *next;
120 };
121
122 LOCAL_USER_DECL;
123
124 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
125 {
126         /* Hang up a tree of stuff */
127         struct localuser *oo;
128         while(outgoing) {
129                 /* Hangup any existing lines we have open */
130                 if (outgoing->chan && (outgoing->chan != exception))
131                         ast_hangup(outgoing->chan);
132                 oo = outgoing;
133                 outgoing=outgoing->next;
134                 free(oo);
135         }
136 }
137
138 #define AST_MAX_WATCHERS 256
139
140 #define HANDLE_CAUSE(blah, bleh) do { \
141         switch(cause) { \
142         case AST_CAUSE_BUSY: \
143                 if (bleh->cdr) \
144                         ast_cdr_busy(bleh->cdr); \
145                 numbusy++; \
146         case AST_CAUSE_CONGESTION: \
147         case AST_CAUSE_UNREGISTERED: \
148                 if (bleh->cdr) \
149                         ast_cdr_busy(bleh->cdr); \
150                 numcongestion++; \
151         default: \
152                 numnochan++; \
153         } \
154 } while(0)
155
156
157 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart)
158 {
159         struct localuser *o;
160         int found;
161         int numlines;
162         int numbusy = busystart;
163         int numcongestion = congestionstart;
164         int numnochan = nochanstart;
165         int cause;
166         int orig = *to;
167         struct ast_frame *f;
168         struct ast_channel *peer = NULL;
169         struct ast_channel *watchers[AST_MAX_WATCHERS];
170         int pos;
171         int single;
172         struct ast_channel *winner;
173         
174         single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
175         
176         if (single) {
177                 /* Turn off hold music, etc */
178                 ast_deactivate_generator(in);
179                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
180                 ast_channel_make_compatible(outgoing->chan, in);
181         }
182         
183         
184         while(*to && !peer) {
185                 o = outgoing;
186                 found = -1;
187                 pos = 1;
188                 numlines = 0;
189                 watchers[0] = in;
190                 while(o) {
191                         /* Keep track of important channels */
192                         if (o->stillgoing && o->chan) {
193                                 watchers[pos++] = o->chan;
194                                 found = 1;
195                         }
196                         o = o->next;
197                         numlines++;
198                 }
199                 if (found < 0) {
200                         if (numlines == (numbusy + numcongestion + numnochan)) {
201                                 if (option_verbose > 2)
202                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
203                                 if (numbusy)
204                                         strncpy(status, "BUSY", statussize - 1);
205                                 else if (numcongestion)
206                                         strncpy(status, "CONGESTION", statussize - 1);
207                                 else if (numnochan)
208                                         strncpy(status, "CHANUNAVAIL", statussize - 1);
209                                 /* See if there is a special busy message */
210                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->cid.cid_num)) 
211                                         in->priority+=100;
212                         } else {
213                                 if (option_verbose > 2)
214                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
215                         }
216                         *to = 0;
217                         return NULL;
218                 }
219                 winner = ast_waitfor_n(watchers, pos, to);
220                 o = outgoing;
221                 while(o) {
222                         if (o->stillgoing && o->chan && (o->chan->_state == AST_STATE_UP)) {
223                                 if (!peer) {
224                                         if (option_verbose > 2)
225                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
226                                         peer = o->chan;
227                                         *allowredir_in = o->allowredirect_in;
228                                         *allowredir_out = o->allowredirect_out;
229                                         *allowdisconnect_in = o->allowdisconnect_in;
230                                         *allowdisconnect_out = o->allowdisconnect_out;
231                                 }
232                         } else if (o->chan && (o->chan == winner)) {
233                                 if (!ast_strlen_zero(o->chan->call_forward)) {
234                                         char tmpchan[256]="";
235                                         char *stuff;
236                                         char *tech;
237                                         strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
238                                         if ((stuff = strchr(tmpchan, '/'))) {
239                                                 *stuff = '\0';
240                                                 stuff++;
241                                                 tech = tmpchan;
242                                         } else {
243                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
244                                                 stuff = tmpchan;
245                                                 tech = "Local";
246                                         }
247                                         /* Before processing channel, go ahead and check for forwarding */
248                                         if (option_verbose > 2)
249                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
250                                         /* Setup parameters */
251                                         o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
252                                         if (!o->chan) {
253                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
254                                                 o->stillgoing = 0;
255                                                 HANDLE_CAUSE(cause, in);
256                                         } else {
257                                                 if (o->chan->cid.cid_num)
258                                                         free(o->chan->cid.cid_num);
259                                                 o->chan->cid.cid_num = NULL;
260                                                 if (o->chan->cid.cid_name)
261                                                         free(o->chan->cid.cid_name);
262                                                 o->chan->cid.cid_name = NULL;
263
264                                                 if (o->forcecallerid) {
265                                                         char *newcid = NULL;
266
267                                                         if (strlen(in->macroexten))
268                                                                 newcid = in->macroexten;
269                                                         else
270                                                                 newcid = in->exten;
271                                                         o->chan->cid.cid_num = strdup(newcid);
272                                                         strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
273                                                         o->chan->cdrflags = winner->cdrflags;
274                                                         if (!o->chan->cid.cid_num)
275                                                                 ast_log(LOG_WARNING, "Out of memory\n");
276                                                 } else {
277                                                         if (in->cid.cid_num) {
278                                                                 o->chan->cid.cid_num = strdup(in->cid.cid_num);
279                                                                 if (!o->chan->cid.cid_num)
280                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
281                                                         }
282                                                         if (in->cid.cid_name) {
283                                                                 o->chan->cid.cid_name = strdup(in->cid.cid_name);
284                                                                 if (!o->chan->cid.cid_name)
285                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
286                                                         }
287                                                         strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
288                                                         o->chan->cdrflags = in->cdrflags;
289                                                 }
290
291                                                 if (in->cid.cid_ani) {
292                                                         if (o->chan->cid.cid_ani)
293                                                                 free(o->chan->cid.cid_ani);
294                                                         o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
295                                                         if (o->chan->cid.cid_ani)
296                                                                 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
297                                                         else
298                                                                 ast_log(LOG_WARNING, "Out of memory\n");
299                                                 }
300                                                 if (o->chan->cid.cid_rdnis) 
301                                                         free(o->chan->cid.cid_rdnis);
302                                                 if (!ast_strlen_zero(in->macroexten))
303                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
304                                                 else
305                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
306                                                 if (ast_call(o->chan, tmpchan, 0)) {
307                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
308                                                         o->stillgoing = 0;
309                                                         ast_hangup(o->chan);
310                                                         o->chan = NULL;
311                                                         numnochan++;
312                                                 }
313                                         }
314                                         /* Hangup the original channel now, in case we needed it */
315                                         ast_hangup(winner);
316                                         continue;
317                                 }
318                                 f = ast_read(winner);
319                                 if (f) {
320                                         if (f->frametype == AST_FRAME_CONTROL) {
321                                                 switch(f->subclass) {
322                                             case AST_CONTROL_ANSWER:
323                                                         /* This is our guy if someone answered. */
324                                                         if (!peer) {
325                                                                 if (option_verbose > 2)
326                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
327                                                                 peer = o->chan;
328                                                                 *allowredir_in = o->allowredirect_in;
329                                                                 *allowredir_out = o->allowredirect_out;
330                                                                 *allowdisconnect_in = o->allowdisconnect_in;
331                                                                 *allowdisconnect_out = o->allowdisconnect_out;
332                                                         }
333                                                         break;
334                                                 case AST_CONTROL_BUSY:
335                                                         if (option_verbose > 2)
336                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
337                                                         in->hangupcause = o->chan->hangupcause;
338                                                         ast_hangup(o->chan);
339                                                         o->chan = NULL;
340                                                         o->stillgoing = 0;
341                                                         HANDLE_CAUSE(AST_CAUSE_BUSY, in);
342                                                         break;
343                                                 case AST_CONTROL_CONGESTION:
344                                                         if (option_verbose > 2)
345                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
346                                                         in->hangupcause = o->chan->hangupcause;
347                                                         ast_hangup(o->chan);
348                                                         o->chan = NULL;
349                                                         o->stillgoing = 0;
350                                                         HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
351                                                         break;
352                                                 case AST_CONTROL_RINGING:
353                                                         if (option_verbose > 2)
354                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
355                                                         if (!(*sentringing) && !outgoing->musiconhold) {
356                                                                 ast_indicate(in, AST_CONTROL_RINGING);
357                                                                 (*sentringing)++;
358                                                         }
359                                                         break;
360                                                 case AST_CONTROL_PROGRESS:
361                                                         if (option_verbose > 2)
362                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
363                                                         if (!outgoing->ringbackonly)
364                                                                 ast_indicate(in, AST_CONTROL_PROGRESS);
365                                                         break;
366                                                 case AST_CONTROL_OFFHOOK:
367                                                 case AST_CONTROL_FLASH:
368                                                         /* Ignore going off hook and flash */
369                                                         break;
370                                                 case -1:
371                                                         if (!outgoing->ringbackonly && !outgoing->musiconhold) {
372                                                                 if (option_verbose > 2)
373                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
374                                                                 ast_indicate(in, -1);
375                                                                 (*sentringing) = 0;
376                                                         }
377                                                         break;
378                                                 default:
379                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
380                                                 }
381                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
382                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
383                                                 if (ast_write(in, f)) 
384                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
385                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
386                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
387                                                 if (ast_write(in, f))
388                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
389                                         }
390                                         ast_frfree(f);
391                                 } else {
392                                         in->hangupcause = o->chan->hangupcause;
393                                         ast_hangup(o->chan);
394                                         o->chan = NULL;
395                                         o->stillgoing = 0;
396                                 }
397                         }
398                         o = o->next;
399                 }
400                 if (winner == in) {
401                         f = ast_read(in);
402 #if 0
403                         if (f && (f->frametype != AST_FRAME_VOICE))
404                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
405                         else if (!f || (f->frametype != AST_FRAME_VOICE))
406                                 printf("Hangup received on %s\n", in->name);
407 #endif
408                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
409                                 /* Got hung up */
410                                 *to=-1;
411                                 strncpy(status, "CANCEL", statussize - 1);
412                                 return NULL;
413                         }
414                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
415                                 (f->subclass == '*')) {
416                             if (option_verbose > 3)
417                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
418                                 *to=0;
419                                 strcpy(status, "CANCEL");
420                                 return NULL;
421                         }
422                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
423                                 if (ast_write(outgoing->chan, f))
424                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
425                                 ast_frfree(f);
426                         }
427                 }
428                 if (!*to && (option_verbose > 2))
429                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
430         }
431
432         return peer;
433         
434 }
435
436 static int dial_exec(struct ast_channel *chan, void *data)
437 {
438         int res=-1;
439         struct localuser *u;
440         char *info, *peers, *timeout, *tech, *number, *rest, *cur;
441         char  privdb[256] = "", *s;
442         char  announcemsg[256] = "", *ann;
443         struct localuser *outgoing=NULL, *tmp;
444         struct ast_channel *peer;
445         int to;
446         int allowredir_in=0;
447         int allowredir_out=0;
448         int allowdisconnect_in=0;
449         int allowdisconnect_out=0;
450         int hasmacro = 0;
451         int privacy=0;
452         int announce=0;
453         int resetcdr=0;
454         int numbusy = 0;
455         int numcongestion = 0;
456         int numnochan = 0;
457         int cause;
458         char numsubst[AST_MAX_EXTENSION];
459         char restofit[AST_MAX_EXTENSION];
460         char *transfer = NULL;
461         char *newnum;
462         char *l;
463         char *url=NULL; /* JDG */
464         struct ast_var_t *current;
465         struct varshead *headp, *newheadp;
466         struct ast_var_t *newvar;
467         int go_on=0;
468         unsigned int calldurationlimit=0;
469         char *cdl;
470         time_t now;
471         struct ast_bridge_config config;
472         long timelimit = 0;
473         long play_warning = 0;
474         long warning_freq=0;
475         char *warning_sound=NULL;
476         char *end_sound=NULL;
477         char *start_sound=NULL;
478         char *limitptr;
479         char limitdata[256];
480         char *sdtmfptr;
481         char sdtmfdata[256] = "";
482         char *stack,*var;
483         char *mac = NULL, macroname[256] = "";
484         char status[256]="";
485         char toast[80];
486         int play_to_caller=0,play_to_callee=0;
487         int playargs=0, sentringing=0, moh=0;
488         char *varname;
489         int vartype;
490         char *outbound_group = NULL;
491
492         int digit = 0;
493         time_t start_time, answer_time, end_time;
494
495         if (!data) {
496                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
497                 return -1;
498         }
499
500         if (!(info = ast_strdupa(data))) {
501                 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
502                 return -1;
503         }
504         LOCAL_USER_ADD(u);
505         
506         peers = info;
507         if (peers) {
508                 
509                 timeout = strchr(info, '|');
510                 if (timeout) {
511                         *timeout = '\0';
512                         timeout++;
513                         transfer = strchr(timeout, '|');
514                         if (transfer) {
515                                 *transfer = '\0';
516                                 transfer++;
517                                 /* JDG */
518                                 url = strchr(transfer, '|');
519                                 if (url) {
520                                         *url = '\0';
521                                         url++;
522                                         if (option_debug)
523                                                 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
524                                 } else 
525                                         if (option_debug) {
526                                                 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
527                                         }
528                                 /* /JDG */
529                         }
530                 }
531         } else
532                 timeout = NULL;
533         if (!peers || ast_strlen_zero(peers)) {
534                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
535                 goto out;
536         }
537         
538
539         if (transfer) {
540
541                 /* Extract call duration limit */
542                 if ((cdl = strstr(transfer, "S("))) {
543                         calldurationlimit=atoi(cdl+2);
544                         if (option_verbose > 2)
545                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
546                 } 
547
548                 /* DTMF SCRIPT*/
549                 if ((sdtmfptr = strstr(transfer, "D("))) {
550                         strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
551                         /* Overwrite with X's what was the sdtmf info */
552                         while (*sdtmfptr && (*sdtmfptr != ')')) 
553                                 *(sdtmfptr++) = 'X';
554                         if (*sdtmfptr)
555                                 *sdtmfptr = 'X';
556                         /* Now find the end  */
557                         sdtmfptr = strchr(sdtmfdata, ')');
558                         if (sdtmfptr)
559                                 *sdtmfptr = '\0';
560                         else 
561                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
562                 }
563                 
564                 /* XXX LIMIT SUPPORT */
565                 if ((limitptr = strstr(transfer, "L("))) {
566                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
567                         /* Overwrite with X's what was the limit info */
568                         while(*limitptr && (*limitptr != ')')) 
569                                 *(limitptr++) = 'X';
570                         if (*limitptr)
571                                 *limitptr = 'X';
572                         /* Now find the end */
573                         limitptr = strchr(limitdata, ')');
574                         if (limitptr)
575                                 *limitptr = '\0';
576                         else
577                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
578
579                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
580                         play_to_caller = var ? ast_true(var) : 1;
581                   
582                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
583                         play_to_callee = var ? ast_true(var) : 0;
584                   
585                         if (!play_to_caller && !play_to_callee)
586                                 play_to_caller=1;
587                   
588                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
589                         warning_sound = var ? var : "timeleft";
590
591                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
592                         end_sound = var ? var : NULL;
593
594                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
595                         start_sound = var ? var : NULL;
596
597                         var=stack=limitdata;
598
599                         var = strsep(&stack, ":");
600                         if (var) {
601                                 timelimit = atol(var);
602                                 playargs++;
603                                 var = strsep(&stack, ":");
604                                 if (var) {
605                                         play_warning = atol(var);
606                                         playargs++;
607                                         var = strsep(&stack, ":");
608                                         if(var) {
609                                                 warning_freq = atol(var);
610                                                 playargs++;
611                                         }
612                                 }
613                         }
614                   
615                         if (!timelimit) {
616                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
617                                 warning_sound=NULL;
618                         }
619                         /* undo effect of S(x) in case they are both used */
620                         calldurationlimit=0; 
621                         /* more efficient do it like S(x) does since no advanced opts*/
622                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
623                                 calldurationlimit=timelimit/1000;
624                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
625                         } else if (option_verbose > 2) {
626                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
627                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
628                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
629                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
630                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
631                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
632                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
633                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
634                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
635                         }
636                 }
637                 
638                 /* XXX ANNOUNCE SUPPORT */
639                 if ((ann = strstr(transfer, "A("))) {
640                         announce = 1;
641                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
642                         /* Overwrite with X's what was the announce info */
643                         while(*ann && (*ann != ')')) 
644                                 *(ann++) = 'X';
645                         if (*ann)
646                                 *ann = 'X';
647                         /* Now find the end of the privdb */
648                         ann = strchr(announcemsg, ')');
649                         if (ann)
650                                 *ann = '\0';
651                         else {
652                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
653                                 announce = 0;
654                         }
655                 }
656                 
657                 /* Get the macroname from the dial option string */
658                 if ((mac = strstr(transfer, "M("))) {
659                         hasmacro = 1;
660                         strncpy(macroname, mac + 2, sizeof(macroname) - 1);
661                         while (*mac && (*mac != ')'))
662                                 *(mac++) = 'X';
663                         if (*mac)
664                                 *mac = 'X';
665                         else {
666                                 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
667                                 hasmacro = 0;
668                         }
669                         mac = strchr(macroname, ')');
670                         if (mac)
671                                 *mac = '\0';
672                         else {
673                                 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
674                                 hasmacro = 0;
675                         }
676                 }
677                 /* Extract privacy info from transfer */
678                 if ((s = strstr(transfer, "P("))) {
679                         privacy = 1;
680                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
681                         /* Overwrite with X's what was the privacy info */
682                         while(*s && (*s != ')')) 
683                                 *(s++) = 'X';
684                         if (*s)
685                                 *s = 'X';
686                         /* Now find the end of the privdb */
687                         s = strchr(privdb, ')');
688                         if (s)
689                                 *s = '\0';
690                         else {
691                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
692                                 privacy = 0;
693                         }
694                 } else if (strchr(transfer, 'P')) {
695                         /* No specified privdb */
696                         privacy = 1;
697                 } else if (strchr(transfer, 'C')) {
698                         resetcdr = 1;
699                 }
700         }
701         if (resetcdr && chan->cdr)
702                 ast_cdr_reset(chan->cdr, 0);
703         if (ast_strlen_zero(privdb) && privacy) {
704                 /* If privdb is not specified and we are using privacy, copy from extension */
705                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
706         }
707         if (privacy) {
708                 l = chan->cid.cid_num;
709                 if (!l)
710                         l = "";
711                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
712         }
713
714         /* If a channel group has been specified, get it for use when we create peer channels */
715         outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
716
717         cur = peers;
718         do {
719                 /* Remember where to start next time */
720                 rest = strchr(cur, '&');
721                 if (rest) {
722                         *rest = 0;
723                         rest++;
724                 }
725                 /* Get a technology/[device:]number pair */
726                 tech = cur;
727                 number = strchr(tech, '/');
728                 if (!number) {
729                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
730                         goto out;
731                 }
732                 *number = '\0';
733                 number++;
734                 tmp = malloc(sizeof(struct localuser));
735                 if (!tmp) {
736                         ast_log(LOG_WARNING, "Out of memory\n");
737                         goto out;
738                 }
739                 memset(tmp, 0, sizeof(struct localuser));
740                 if (transfer) {
741                         if (strchr(transfer, 't'))
742                                 tmp->allowredirect_in = 1;
743                         else    tmp->allowredirect_in = 0;
744                         if (strchr(transfer, 'T'))
745                                 tmp->allowredirect_out = 1;
746                         else    tmp->allowredirect_out = 0;
747                         if (strchr(transfer, 'r'))
748                                 tmp->ringbackonly = 1;
749                         else    tmp->ringbackonly = 0;
750                         if (strchr(transfer, 'm'))
751                                 tmp->musiconhold = 1;
752                         else    tmp->musiconhold = 0;
753                         if (strchr(transfer, 'H'))
754                                 allowdisconnect_out = tmp->allowdisconnect_out = 1;
755                         else    allowdisconnect_out = tmp->allowdisconnect_out = 0;
756                         if(strchr(transfer, 'h'))
757                                 allowdisconnect_in = tmp->allowdisconnect_in = 1;
758                         else    allowdisconnect_in = tmp->allowdisconnect_in = 0;
759                         if(strchr(transfer, 'g'))
760                                 go_on=1;
761                         if (strchr(transfer, 'f'))
762                                 tmp->forcecallerid = 1;
763                         else    tmp->forcecallerid = 0;
764                 }
765                 strncpy(numsubst, number, sizeof(numsubst)-1);
766                 /* If we're dialing by extension, look at the extension to know what to dial */
767                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
768                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
769                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
770                         if (option_debug)
771                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
772                 }
773                 /* Request the peer */
774                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
775                 if (!tmp->chan) {
776                         /* If we can't, just go on to the next call */
777                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d)\n", tech, cause);
778                         HANDLE_CAUSE(cause, chan);
779                         cur = rest;
780                         continue;
781                 }
782                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
783                         char tmpchan[256]="";
784                         char *stuff;
785                         char *tech;
786                         strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
787                         if ((stuff = strchr(tmpchan, '/'))) {
788                                 *stuff = '\0';
789                                 stuff++;
790                                 tech = tmpchan;
791                         } else {
792                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
793                                 stuff = tmpchan;
794                                 tech = "Local";
795                         }
796                         /* Before processing channel, go ahead and check for forwarding */
797                         if (option_verbose > 2)
798                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
799                         /* Setup parameters */
800                         ast_hangup(tmp->chan);
801                         tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
802                         if (!tmp->chan) {
803                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause %d)\n", tech, stuff, cause);
804                                 HANDLE_CAUSE(cause, chan);
805                                 cur = rest;
806                                 continue;
807                         }
808                 }
809
810                 /* Contitionally copy channel variables to the newly created channel */
811                 headp = &chan->varshead;
812                 AST_LIST_TRAVERSE(headp, current, entries) {
813                         varname = ast_var_full_name(current);
814                         vartype = 0;
815                         if (varname) {
816                                 if (varname[0] == '_') {
817                                         vartype = 1;
818                                         if (varname[1] == '_')
819                                                 vartype = 2;
820                                 }
821                         }
822                         if (vartype == 1) {
823                                 newvar = ast_var_assign((char*)&(varname[1]), 
824                                                                                                 ast_var_value(current));
825                                 newheadp = &tmp->chan->varshead;
826                                 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
827                                 if (option_debug)
828                                         ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", 
829                                                                                                 ast_var_name(newvar));
830                         } else if (vartype == 2) {
831                                 newvar = ast_var_assign(ast_var_full_name(current), 
832                                                                                                 ast_var_value(current));
833                                 newheadp = &tmp->chan->varshead;
834                                 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
835                                 if (option_debug)
836                                         ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", 
837                                                                                                 ast_var_name(newvar));
838                         } else {
839                                 if (option_debug)
840                                         ast_log(LOG_DEBUG, "Not copying variable %s.\n", 
841                                                                                                 ast_var_name(current));
842                         }
843                 }
844
845                 tmp->chan->appl = "AppDial";
846                 tmp->chan->data = "(Outgoing Line)";
847                 tmp->chan->whentohangup = 0;
848                 if (tmp->chan->cid.cid_num)
849                         free(tmp->chan->cid.cid_num);
850                 tmp->chan->cid.cid_num = NULL;
851                 if (tmp->chan->cid.cid_name)
852                         free(tmp->chan->cid.cid_name);
853                 tmp->chan->cid.cid_name = NULL;
854                 if (tmp->chan->cid.cid_ani)
855                         free(tmp->chan->cid.cid_ani);
856                 tmp->chan->cid.cid_ani = NULL;
857
858                 if (chan->cid.cid_num) 
859                         tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
860                 if (chan->cid.cid_name) 
861                         tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
862                 if (chan->cid.cid_ani) 
863                         tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
864                 
865                 /* Copy language from incoming to outgoing */
866                 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
867                 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
868                 tmp->chan->cdrflags = chan->cdrflags;
869                 if (ast_strlen_zero(tmp->chan->musicclass))
870                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
871                 if (chan->cid.cid_rdnis)
872                         tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
873                 /* Pass callingpres setting */
874                 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
875                 /* Pass type of number */
876                 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
877                 /* Pass type of tns */
878                 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
879                 /* Presense of ADSI CPE on outgoing channel follows ours */
880                 tmp->chan->adsicpe = chan->adsicpe;
881                 /* pass the digital flag */
882                 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
883
884                 /* If we have an outbound group, set this peer channel to it */
885                 if (outbound_group)
886                         ast_app_group_set_channel(tmp->chan, outbound_group);
887
888                 /* Place the call, but don't wait on the answer */
889                 res = ast_call(tmp->chan, numsubst, 0);
890
891                 /* Save the info in cdr's that we called them */
892                 if (chan->cdr)
893                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
894
895                 /* check the results of ast_call */
896                 if (res) {
897                         /* Again, keep going even if there's an error */
898                         if (option_debug)
899                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
900                         else if (option_verbose > 2)
901                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
902                         ast_hangup(tmp->chan);
903                         tmp->chan = NULL;
904                         cur = rest;
905                         continue;
906                 } else
907                         if (option_verbose > 2)
908                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
909                 /* Put them in the list of outgoing thingies...  We're ready now. 
910                    XXX If we're forcibly removed, these outgoing calls won't get
911                    hung up XXX */
912                 tmp->stillgoing = -1;
913                 tmp->next = outgoing;
914                 outgoing = tmp;
915                 /* If this line is up, don't try anybody else */
916                 if (outgoing->chan->_state == AST_STATE_UP)
917                         break;
918                 cur = rest;
919         } while(cur);
920         
921         if (timeout && !ast_strlen_zero(timeout)) {
922                 to = atoi(timeout);
923                 if (to > 0)
924                         to *= 1000;
925                 else
926                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
927         } else
928                 to = -1;
929
930         if (outgoing) {
931                 /* Our status will at least be NOANSWER */
932                 strncpy(status, "NOANSWER", sizeof(status) - 1);
933                 if (outgoing->musiconhold) {
934                         moh=1;
935                         ast_moh_start(chan, NULL);
936                 } else if (outgoing->ringbackonly) {
937                         ast_indicate(chan, AST_CONTROL_RINGING);
938                         sentringing++;
939                 }
940         } else
941                 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
942
943         time(&start_time);
944         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion);
945
946         if (!peer) {
947                 if (to) 
948                         /* Musta gotten hung up */
949                         res = -1;
950                  else 
951                         /* Nobody answered, next please? */
952                         res=0;
953                 
954                 goto out;
955         }
956         if (peer) {
957                 time(&answer_time);
958 #ifdef OSP_SUPPORT
959                 /* Once call is answered, ditch the OSP Handle */
960                 pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
961 #endif          
962                 strncpy(status, "ANSWER", sizeof(status) - 1);
963                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
964                    we will always return with -1 so that it is hung up properly after the 
965                    conversation.  */
966                 hanguptree(outgoing, peer);
967                 outgoing = NULL;
968                 /* If appropriate, log that we have a destination channel */
969                 if (chan->cdr)
970                         ast_cdr_setdestchan(chan->cdr, peer->name);
971                 if (peer->name)
972                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
973                 if (numsubst)
974                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
975                 /* JDG: sendurl */
976                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
977                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
978                         ast_channel_sendurl( peer, url );
979                 } /* /JDG */
980                 if (announce && announcemsg) {
981                         // Start autoservice on the other chan
982                         res = ast_autoservice_start(chan);
983                         // Now Stream the File
984                         if (!res)
985                                 res = ast_streamfile(peer,announcemsg,peer->language);
986                         if (!res) {
987                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
988                         }
989                         // Ok, done. stop autoservice
990                         res = ast_autoservice_stop(chan);
991                         if (digit > 0 && !res)
992                                 res = ast_senddigit(chan, digit); 
993                         else
994                                 res = digit;
995
996                 } else
997                         res = 0;
998
999                 if (hasmacro && macroname) {
1000                         void *app = NULL;
1001
1002                         res = ast_autoservice_start(chan);
1003                         if (res) {
1004                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1005                                 res = -1;
1006                         }
1007
1008                         app = pbx_findapp("Macro");
1009
1010                         if (app && !res) {
1011                                 res = pbx_exec(peer, app, macroname, 1);
1012                                 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1013                                 res = 0;
1014                         } else {
1015                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1016                                 res = -1;
1017                         }
1018
1019                         if (ast_autoservice_stop(chan) < 0) {
1020                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1021                                 res = -1;
1022                         }
1023                 }
1024
1025                 if (!res) {
1026                         if (calldurationlimit > 0) {
1027                                 time(&now);
1028                                 chan->whentohangup = now + calldurationlimit;
1029                         }
1030                         if (!ast_strlen_zero(sdtmfdata)) 
1031                                 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
1032                 }
1033                 
1034                 if (!res) {
1035                         memset(&config,0,sizeof(struct ast_bridge_config));
1036                         config.play_to_caller=play_to_caller;
1037                         config.play_to_callee=play_to_callee;
1038                         config.allowredirect_in = allowredir_in;
1039                         config.allowredirect_out = allowredir_out;
1040                         config.allowdisconnect_in = allowdisconnect_in;
1041                         config.allowdisconnect_out = allowdisconnect_out;
1042                         config.timelimit = timelimit;
1043                         config.play_warning = play_warning;
1044                         config.warning_freq = warning_freq;
1045                         config.warning_sound = warning_sound;
1046                         config.end_sound = end_sound;
1047                         config.start_sound = start_sound;
1048                         if (moh) {
1049                                 moh = 0;
1050                                 ast_moh_stop(chan);
1051                         } else if (sentringing) {
1052                                 sentringing = 0;
1053                                 ast_indicate(chan, -1);
1054                         }
1055                         /* Be sure no generators are left on it */
1056                         ast_deactivate_generator(chan);
1057                         /* Make sure channels are compatible */
1058                         res = ast_channel_make_compatible(chan, peer);
1059                         if (res < 0) {
1060                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1061                                 ast_hangup(peer);
1062                                 return -1;
1063                         }
1064                         res = ast_bridge_call(chan,peer,&config);
1065                         time(&end_time);
1066                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1067                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1068                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1069                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1070                         
1071                 } else 
1072                         res = -1;
1073                 
1074                 if (res != AST_PBX_NO_HANGUP_PEER) {
1075                         if (!chan->_softhangup)
1076                                 chan->hangupcause = peer->hangupcause;
1077                         ast_hangup(peer);
1078                 }
1079         }       
1080 out:
1081         if (moh) {
1082                 moh = 0;
1083                 ast_moh_stop(chan);
1084         } else if (sentringing) {
1085                 sentringing = 0;
1086                 ast_indicate(chan, -1);
1087         }
1088         hanguptree(outgoing, NULL);
1089         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1090         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1091         
1092         LOCAL_USER_REMOVE(u);
1093         
1094         if((go_on>0) && (!chan->_softhangup))
1095             res=0;
1096             
1097         return res;
1098 }
1099
1100 int unload_module(void)
1101 {
1102         STANDARD_HANGUP_LOCALUSERS;
1103         return ast_unregister_application(app);
1104 }
1105
1106 int load_module(void)
1107 {
1108         int res;
1109         res = ast_register_application(app, dial_exec, synopsis, descrip);
1110         return res;
1111 }
1112
1113 char *description(void)
1114 {
1115         return tdesc;
1116 }
1117
1118 int usecount(void)
1119 {
1120         int res;
1121         STANDARD_USECOUNT(res);
1122         return res;
1123 }
1124
1125 char *key()
1126 {
1127         return ASTERISK_GPL_KEY;
1128 }