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