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