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