More flag on dial tweaks (bug #3254, take two)
[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         struct ast_var_t *current;
492         struct varshead *headp, *newheadp;
493         struct ast_var_t *newvar;
494         unsigned int calldurationlimit=0;
495         char *cdl;
496         time_t now;
497         struct ast_bridge_config config;
498         long timelimit = 0;
499         long play_warning = 0;
500         long warning_freq=0;
501         char *warning_sound=NULL;
502         char *end_sound=NULL;
503         char *start_sound=NULL;
504         char *limitptr;
505         char limitdata[256];
506         char *sdtmfptr;
507         char sdtmfdata[256] = "";
508         char *stack,*var;
509         char *mac = NULL, *macroname = NULL;
510         char status[256]="";
511         char toast[80];
512         int play_to_caller=0,play_to_callee=0;
513         int playargs=0, sentringing=0, moh=0;
514         char *varname;
515         char *mohclass = NULL;
516         int vartype;
517         char *outbound_group = NULL;
518         char *macro_result = NULL, *macro_transfer_dest = NULL;
519         int digit = 0;
520         time_t start_time, answer_time, end_time;
521         struct ast_app *app = NULL;
522
523         if (!data) {
524                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
525                 return -1;
526         }
527
528         if (!(info = ast_strdupa(data))) {
529                 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
530                 return -1;
531         }
532         LOCAL_USER_ADD(u);
533         
534         peers = info;
535         if (peers) {
536                 
537                 timeout = strchr(info, '|');
538                 if (timeout) {
539                         *timeout = '\0';
540                         timeout++;
541                         transfer = strchr(timeout, '|');
542                         if (transfer) {
543                                 *transfer = '\0';
544                                 transfer++;
545                                 /* JDG */
546                                 url = strchr(transfer, '|');
547                                 if (url) {
548                                         *url = '\0';
549                                         url++;
550                                         if (option_debug)
551                                                 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
552                                 } else 
553                                         if (option_debug) {
554                                                 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
555                                         }
556                                 /* /JDG */
557                         }
558                 }
559         } else
560                 timeout = NULL;
561         if (!peers || ast_strlen_zero(peers)) {
562                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
563                 goto out;
564         }
565         
566
567         if (transfer) {
568
569                 /* Extract call duration limit */
570                 if ((cdl = strstr(transfer, "S("))) {
571                         calldurationlimit=atoi(cdl+2);
572                         if (option_verbose > 2)
573                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
574                 } 
575
576                 /* DTMF SCRIPT*/
577                 if ((sdtmfptr = strstr(transfer, "D("))) {
578                         strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
579                         /* Overwrite with X's what was the sdtmf info */
580                         while (*sdtmfptr && (*sdtmfptr != ')')) 
581                                 *(sdtmfptr++) = 'X';
582                         if (*sdtmfptr)
583                                 *sdtmfptr = 'X';
584                         /* Now find the end  */
585                         sdtmfptr = strchr(sdtmfdata, ')');
586                         if (sdtmfptr)
587                                 *sdtmfptr = '\0';
588                         else 
589                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
590                 }
591                 
592                 /* XXX LIMIT SUPPORT */
593                 if ((limitptr = strstr(transfer, "L("))) {
594                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
595                         /* Overwrite with X's what was the limit info */
596                         while(*limitptr && (*limitptr != ')')) 
597                                 *(limitptr++) = 'X';
598                         if (*limitptr)
599                                 *limitptr = 'X';
600                         /* Now find the end */
601                         limitptr = strchr(limitdata, ')');
602                         if (limitptr)
603                                 *limitptr = '\0';
604                         else
605                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
606
607                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
608                         play_to_caller = var ? ast_true(var) : 1;
609                   
610                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
611                         play_to_callee = var ? ast_true(var) : 0;
612                   
613                         if (!play_to_caller && !play_to_callee)
614                                 play_to_caller=1;
615                   
616                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
617                         warning_sound = var ? var : "timeleft";
618
619                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
620                         end_sound = var ? var : NULL;
621
622                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
623                         start_sound = var ? var : NULL;
624
625                         var=stack=limitdata;
626
627                         var = strsep(&stack, ":");
628                         if (var) {
629                                 timelimit = atol(var);
630                                 playargs++;
631                                 var = strsep(&stack, ":");
632                                 if (var) {
633                                         play_warning = atol(var);
634                                         playargs++;
635                                         var = strsep(&stack, ":");
636                                         if(var) {
637                                                 warning_freq = atol(var);
638                                                 playargs++;
639                                         }
640                                 }
641                         }
642                   
643                         if (!timelimit) {
644                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
645                                 warning_sound=NULL;
646                         }
647                         /* undo effect of S(x) in case they are both used */
648                         calldurationlimit=0; 
649                         /* more efficient do it like S(x) does since no advanced opts*/
650                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
651                                 calldurationlimit=timelimit/1000;
652                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
653                         } else if (option_verbose > 2) {
654                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
655                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
656                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
657                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
658                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
659                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
660                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
661                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
662                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
663                         }
664                 }
665                 
666                 /* XXX ANNOUNCE SUPPORT */
667                 if ((ann = strstr(transfer, "A("))) {
668                         announce = 1;
669                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
670                         /* Overwrite with X's what was the announce info */
671                         while(*ann && (*ann != ')')) 
672                                 *(ann++) = 'X';
673                         if (*ann)
674                                 *ann = 'X';
675                         /* Now find the end of the privdb */
676                         ann = strchr(announcemsg, ')');
677                         if (ann)
678                                 *ann = '\0';
679                         else {
680                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
681                                 announce = 0;
682                         }
683                 }
684                 
685                 /* Get the macroname from the dial option string */
686                 if ((mac = strstr(transfer, "M("))) {
687                         hasmacro = 1;
688                         macroname = ast_strdupa(mac + 2);
689                         while (*mac && (*mac != ')'))
690                                 *(mac++) = 'X';
691                         if (*mac)
692                                 *mac = 'X';
693                         else {
694                                 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
695                                 hasmacro = 0;
696                         }
697                         mac = strchr(macroname, ')');
698                         if (mac)
699                                 *mac = '\0';
700                         else {
701                                 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
702                                 hasmacro = 0;
703                         }
704                 }
705                 /* Get music on hold class */
706                 if ((mac = strstr(transfer, "m("))) {
707                         mohclass = ast_strdupa(mac + 2);
708                         mac++; /* Leave the "m" in the string */
709                         while (*mac && (*mac != ')'))
710                                 *(mac++) = 'X';
711                         if (*mac)
712                                 *mac = 'X';
713                         else {
714                                 ast_log(LOG_WARNING, "Could not find music on hold class to use, assuming default.\n");
715                                 mohclass=NULL;
716                         }
717                         mac = strchr(macroname, ')');
718                         if (mac)
719                                 *mac = '\0';
720                         else {
721                                 ast_log(LOG_WARNING, "Music on hold class specified without trailing ')'\n");
722                                 mohclass = NULL;
723                         }
724                 }
725                 /* Extract privacy info from transfer */
726                 if ((s = strstr(transfer, "P("))) {
727                         privacy = 1;
728                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
729                         /* Overwrite with X's what was the privacy info */
730                         while(*s && (*s != ')')) 
731                                 *(s++) = 'X';
732                         if (*s)
733                                 *s = 'X';
734                         /* Now find the end of the privdb */
735                         s = strchr(privdb, ')');
736                         if (s)
737                                 *s = '\0';
738                         else {
739                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
740                                 privacy = 0;
741                         }
742                 } else if (strchr(transfer, 'P')) {
743                         /* No specified privdb */
744                         privacy = 1;
745                 } else if (strchr(transfer, 'C')) {
746                         resetcdr = 1;
747                 }
748         }
749         if (resetcdr && chan->cdr)
750                 ast_cdr_reset(chan->cdr, 0);
751         if (ast_strlen_zero(privdb) && privacy) {
752                 /* If privdb is not specified and we are using privacy, copy from extension */
753                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
754         }
755         if (privacy) {
756                 l = chan->cid.cid_num;
757                 if (!l)
758                         l = "";
759                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
760         }
761
762         /* If a channel group has been specified, get it for use when we create peer channels */
763         outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
764
765         cur = peers;
766         do {
767                 /* Remember where to start next time */
768                 rest = strchr(cur, '&');
769                 if (rest) {
770                         *rest = 0;
771                         rest++;
772                 }
773                 /* Get a technology/[device:]number pair */
774                 tech = cur;
775                 number = strchr(tech, '/');
776                 if (!number) {
777                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
778                         goto out;
779                 }
780                 *number = '\0';
781                 number++;
782                 tmp = malloc(sizeof(struct localuser));
783                 if (!tmp) {
784                         ast_log(LOG_WARNING, "Out of memory\n");
785                         goto out;
786                 }
787                 memset(tmp, 0, sizeof(struct localuser));
788                 if (transfer) {
789                         ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_IN);
790                         ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_OUT);
791                         ast_set2_flag(tmp, strchr(transfer, 'r'), DIAL_RINGBACKONLY);   
792                         ast_set2_flag(tmp, strchr(transfer, 'm'), DIAL_MUSICONHOLD);    
793                         ast_set2_flag(tmp, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);    
794                         ast_set2_flag(&peerflags, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);     
795                         ast_set2_flag(tmp, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
796                         ast_set2_flag(&peerflags, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
797                         ast_set2_flag(tmp, strchr(transfer, 'f'), DIAL_FORCECALLERID);  
798                         ast_set2_flag(tmp, strchr(transfer, 'w'), DIAL_MONITOR_IN);     
799                         ast_set2_flag(tmp, strchr(transfer, 'W'), DIAL_MONITOR_OUT);    
800                         ast_set2_flag(tmp, strchr(transfer, 'g'), DIAL_GO_ON);  
801                 }
802                 strncpy(numsubst, number, sizeof(numsubst)-1);
803                 /* If we're dialing by extension, look at the extension to know what to dial */
804                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
805                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
806                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
807                         if (option_debug)
808                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
809                 }
810                 /* Request the peer */
811                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
812                 if (!tmp->chan) {
813                         /* If we can't, just go on to the next call */
814                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d)\n", tech, cause);
815                         HANDLE_CAUSE(cause, chan);
816                         cur = rest;
817                         continue;
818                 }
819                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
820                         char tmpchan[256]="";
821                         char *stuff;
822                         char *tech;
823                         strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
824                         if ((stuff = strchr(tmpchan, '/'))) {
825                                 *stuff = '\0';
826                                 stuff++;
827                                 tech = tmpchan;
828                         } else {
829                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
830                                 stuff = tmpchan;
831                                 tech = "Local";
832                         }
833                         tmp->forwards++;
834                         if (tmp->forwards < AST_MAX_FORWARDS) {
835                                 if (option_verbose > 2)
836                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
837                                 ast_hangup(tmp->chan);
838                                 /* Setup parameters */
839                                 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
840                                 if (!tmp->chan)
841                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
842                         } else {
843                                 if (option_verbose > 2)
844                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
845                                 ast_hangup(tmp->chan);
846                                 tmp->chan = NULL;
847                                 cause = AST_CAUSE_CONGESTION;
848                         }
849                         if (!tmp->chan) {
850                                 HANDLE_CAUSE(cause, chan);
851                                 cur = rest;
852                                 continue;
853                         }
854                 }
855
856                 /* Contitionally copy channel variables to the newly created channel */
857                 headp = &chan->varshead;
858                 AST_LIST_TRAVERSE(headp, current, entries) {
859                         varname = ast_var_full_name(current);
860                         vartype = 0;
861                         if (varname) {
862                                 if (varname[0] == '_') {
863                                         vartype = 1;
864                                         if (varname[1] == '_')
865                                                 vartype = 2;
866                                 }
867                         }
868                         if (vartype == 1) {
869                                 newvar = ast_var_assign((char*)&(varname[1]), 
870                                                                                                 ast_var_value(current));
871                                 newheadp = &tmp->chan->varshead;
872                                 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
873                                 if (option_debug)
874                                         ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", 
875                                                                                                 ast_var_name(newvar));
876                         } else if (vartype == 2) {
877                                 newvar = ast_var_assign(ast_var_full_name(current), 
878                                                                                                 ast_var_value(current));
879                                 newheadp = &tmp->chan->varshead;
880                                 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
881                                 if (option_debug)
882                                         ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", 
883                                                                                                 ast_var_name(newvar));
884                         } else {
885                                 if (option_debug)
886                                         ast_log(LOG_DEBUG, "Not copying variable %s.\n", 
887                                                                                                 ast_var_name(current));
888                         }
889                 }
890
891                 tmp->chan->appl = "AppDial";
892                 tmp->chan->data = "(Outgoing Line)";
893                 tmp->chan->whentohangup = 0;
894                 if (tmp->chan->cid.cid_num)
895                         free(tmp->chan->cid.cid_num);
896                 tmp->chan->cid.cid_num = NULL;
897                 if (tmp->chan->cid.cid_name)
898                         free(tmp->chan->cid.cid_name);
899                 tmp->chan->cid.cid_name = NULL;
900                 if (tmp->chan->cid.cid_ani)
901                         free(tmp->chan->cid.cid_ani);
902                 tmp->chan->cid.cid_ani = NULL;
903
904                 if (chan->cid.cid_num) 
905                         tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
906                 if (chan->cid.cid_name) 
907                         tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
908                 if (chan->cid.cid_ani) 
909                         tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
910                 
911                 /* Copy language from incoming to outgoing */
912                 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
913                 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
914                 tmp->chan->cdrflags = chan->cdrflags;
915                 if (ast_strlen_zero(tmp->chan->musicclass))
916                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
917                 if (chan->cid.cid_rdnis)
918                         tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
919                 /* Pass callingpres setting */
920                 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
921                 /* Pass type of number */
922                 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
923                 /* Pass type of tns */
924                 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
925                 /* Presense of ADSI CPE on outgoing channel follows ours */
926                 tmp->chan->adsicpe = chan->adsicpe;
927                 /* pass the digital flag */
928                 ast_copy_flags(tmp->chan, chan, AST_FLAG_DIGITAL);
929
930                 /* If we have an outbound group, set this peer channel to it */
931                 if (outbound_group)
932                         ast_app_group_set_channel(tmp->chan, outbound_group);
933
934                 /* Place the call, but don't wait on the answer */
935                 res = ast_call(tmp->chan, numsubst, 0);
936
937                 /* Save the info in cdr's that we called them */
938                 if (chan->cdr)
939                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
940
941                 /* check the results of ast_call */
942                 if (res) {
943                         /* Again, keep going even if there's an error */
944                         if (option_debug)
945                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
946                         else if (option_verbose > 2)
947                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
948                         ast_hangup(tmp->chan);
949                         tmp->chan = NULL;
950                         cur = rest;
951                         continue;
952                 } else
953                         if (option_verbose > 2)
954                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
955                 /* Put them in the list of outgoing thingies...  We're ready now. 
956                    XXX If we're forcibly removed, these outgoing calls won't get
957                    hung up XXX */
958                 ast_set_flag(tmp, DIAL_STILLGOING);     
959                 tmp->next = outgoing;
960                 outgoing = tmp;
961                 /* If this line is up, don't try anybody else */
962                 if (outgoing->chan->_state == AST_STATE_UP)
963                         break;
964                 cur = rest;
965         } while(cur);
966         
967         if (timeout && !ast_strlen_zero(timeout)) {
968                 to = atoi(timeout);
969                 if (to > 0)
970                         to *= 1000;
971                 else
972                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
973         } else
974                 to = -1;
975
976         if (outgoing) {
977                 /* Our status will at least be NOANSWER */
978                 strncpy(status, "NOANSWER", sizeof(status) - 1);
979                 if (ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
980                         moh=1;
981                         ast_moh_start(chan, mohclass);
982                 } else if (ast_test_flag(outgoing, DIAL_RINGBACKONLY)) {
983                         ast_indicate(chan, AST_CONTROL_RINGING);
984                         sentringing++;
985                 }
986         } else
987                 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
988
989         time(&start_time);
990         peer = wait_for_answer(chan, outgoing, &to, &peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion);
991         
992         if (!peer) {
993                 if (to) 
994                         /* Musta gotten hung up */
995                         res = -1;
996                  else 
997                         /* Nobody answered, next please? */
998                         res=0;
999                 
1000                 goto out;
1001         }
1002         if (peer) {
1003                 time(&answer_time);
1004 #ifdef OSP_SUPPORT
1005                 /* Once call is answered, ditch the OSP Handle */
1006                 pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
1007 #endif          
1008                 strncpy(status, "ANSWER", sizeof(status) - 1);
1009                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1010                    we will always return with -1 so that it is hung up properly after the 
1011                    conversation.  */
1012                 hanguptree(outgoing, peer);
1013                 outgoing = NULL;
1014                 /* If appropriate, log that we have a destination channel */
1015                 if (chan->cdr)
1016                         ast_cdr_setdestchan(chan->cdr, peer->name);
1017                 if (peer->name)
1018                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1019                 if (numsubst)
1020                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
1021                 /* JDG: sendurl */
1022                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1023                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
1024                         ast_channel_sendurl( peer, url );
1025                 } /* /JDG */
1026                 if (announce && announcemsg) {
1027                         /* Start autoservice on the other chan */
1028                         res = ast_autoservice_start(chan);
1029                         /* Now Stream the File */
1030                         if (!res)
1031                                 res = ast_streamfile(peer,announcemsg,peer->language);
1032                         if (!res) {
1033                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
1034                         }
1035                         /* Ok, done. stop autoservice */
1036                         res = ast_autoservice_stop(chan);
1037                         if (digit > 0 && !res)
1038                                 res = ast_senddigit(chan, digit); 
1039                         else
1040                                 res = digit;
1041
1042                 } else
1043                         res = 0;
1044
1045                 if (hasmacro && macroname) {
1046                         res = ast_autoservice_start(chan);
1047                         if (res) {
1048                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1049                                 res = -1;
1050                         }
1051
1052                         app = pbx_findapp("Macro");
1053
1054                         if (app && !res) {
1055                                 for(res=0;res<strlen(macroname);res++)
1056                                         if(macroname[res] == '^')
1057                                                 macroname[res] = '|';
1058                                 res = pbx_exec(peer, app, macroname, 1);
1059                                 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1060                                 res = 0;
1061                         } else {
1062                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1063                                 res = -1;
1064                         }
1065
1066                         if (ast_autoservice_stop(chan) < 0) {
1067                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1068                                 res = -1;
1069                         }
1070
1071                         if (!res) {
1072                                 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1073                                         if (!strcasecmp(macro_result, "BUSY")) {
1074                                                 strncpy(status, macro_result, sizeof(status) - 1);
1075                                                 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1076                                                         ast_set_flag(&peerflags, DIAL_GO_ON);
1077                                                 }
1078                                                 res = -1;
1079                                         }
1080                                         else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1081                                                 strncpy(status, macro_result, sizeof(status) - 1);
1082                                                 ast_set_flag(&peerflags, DIAL_GO_ON);   
1083                                                 res = -1;
1084                                         }
1085                                         else if (!strcasecmp(macro_result, "CONTINUE")) {
1086                                                 /* hangup peer and keep chan alive assuming the macro has changed 
1087                                                    the context / exten / priority or perhaps 
1088                                                    the next priority in the current exten is desired.
1089                                                 */
1090                                                 ast_set_flag(&peerflags, DIAL_GO_ON);   
1091                                                 res = -1;
1092                                         } else if (!strcasecmp(macro_result, "ABORT")) {
1093                                                 /* Hangup both ends unless the caller has the g flag */
1094                                                 res = -1;
1095                                         } else if(!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1096                                                 res = -1;
1097                                                 /* perform a transfer to a new extension */
1098                                                 if(strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
1099                                                         /* no brainer mode... substitute ^ with | and feed it to builtin goto */
1100                                                         for(res=0;res<strlen(macro_transfer_dest);res++)
1101                                                                 if(macro_transfer_dest[res] == '^')
1102                                                                         macro_transfer_dest[res] = '|';
1103
1104                                                         if(!ast_parseable_goto(chan, macro_transfer_dest))
1105                                                                 ast_set_flag(&peerflags, DIAL_GO_ON);
1106
1107                                                 }
1108                                         }
1109                                 }
1110                         }
1111                 }
1112
1113                 if (!res) {
1114                         if (calldurationlimit > 0) {
1115                                 time(&now);
1116                                 chan->whentohangup = now + calldurationlimit;
1117                         }
1118                         if (!ast_strlen_zero(sdtmfdata)) 
1119                                 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
1120                 }
1121                 
1122                 if (!res) {
1123                         memset(&config,0,sizeof(struct ast_bridge_config));
1124                         if (play_to_caller)
1125                                 config.features_caller |= AST_FEATURE_PLAY_WARNING;
1126                         if (play_to_callee)
1127                                 config.features_callee |= AST_FEATURE_PLAY_WARNING;
1128                         if (ast_test_flag(&peerflags, DIAL_ALLOWREDIRECT_IN))
1129                                 config.features_callee |= AST_FEATURE_REDIRECT;
1130                         if (ast_test_flag(&peerflags, DIAL_ALLOWREDIRECT_OUT))
1131                                 config.features_caller |= AST_FEATURE_REDIRECT;
1132                         if (ast_test_flag(&peerflags, DIAL_ALLOWDISCONNECT_IN))
1133                                 config.features_callee |= AST_FEATURE_DISCONNECT;
1134                         if (ast_test_flag(&peerflags, DIAL_ALLOWDISCONNECT_OUT))
1135                                 config.features_caller |= AST_FEATURE_DISCONNECT;
1136                         if (ast_test_flag(&peerflags, DIAL_MONITOR_IN))
1137                                 config.features_callee |= AST_FEATURE_AUTOMON;
1138                         if (ast_test_flag(&peerflags, DIAL_MONITOR_OUT))
1139                                 config.features_caller |= AST_FEATURE_AUTOMON;
1140                         config.timelimit = timelimit;
1141                         config.play_warning = play_warning;
1142                         config.warning_freq = warning_freq;
1143                         config.warning_sound = warning_sound;
1144                         config.end_sound = end_sound;
1145                         config.start_sound = start_sound;
1146                         if (moh) {
1147                                 moh = 0;
1148                                 ast_moh_stop(chan);
1149                         } else if (sentringing) {
1150                                 sentringing = 0;
1151                                 ast_indicate(chan, -1);
1152                         }
1153                         /* Be sure no generators are left on it */
1154                         ast_deactivate_generator(chan);
1155                         /* Make sure channels are compatible */
1156                         res = ast_channel_make_compatible(chan, peer);
1157                         if (res < 0) {
1158                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1159                                 ast_hangup(peer);
1160                                 return -1;
1161                         }
1162                         res = ast_bridge_call(chan,peer,&config);
1163                         time(&end_time);
1164                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1165                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1166                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1167                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1168                         
1169                 } else 
1170                         res = -1;
1171                 
1172                 if (res != AST_PBX_NO_HANGUP_PEER) {
1173                         if (!chan->_softhangup)
1174                                 chan->hangupcause = peer->hangupcause;
1175                         ast_hangup(peer);
1176                 }
1177         }       
1178 out:
1179         if (moh) {
1180                 moh = 0;
1181                 ast_moh_stop(chan);
1182         } else if (sentringing) {
1183                 sentringing = 0;
1184                 ast_indicate(chan, -1);
1185         }
1186         hanguptree(outgoing, NULL);
1187         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1188         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1189         
1190         LOCAL_USER_REMOVE(u);
1191         
1192         if((ast_test_flag(&peerflags, DIAL_GO_ON)) && (!chan->_softhangup))
1193             res=0;
1194             
1195         return res;
1196 }
1197
1198 int unload_module(void)
1199 {
1200         STANDARD_HANGUP_LOCALUSERS;
1201         return ast_unregister_application(app);
1202 }
1203
1204 int load_module(void)
1205 {
1206         int res;
1207         res = ast_register_application(app, dial_exec, synopsis, descrip);
1208         return res;
1209 }
1210
1211 char *description(void)
1212 {
1213         return tdesc;
1214 }
1215
1216 int usecount(void)
1217 {
1218         int res;
1219         STANDARD_USECOUNT(res);
1220         return res;
1221 }
1222
1223 char *key()
1224 {
1225         return ASTERISK_GPL_KEY;
1226 }