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