add a global option to disable priority jumping in applications (when they get update...
[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 <stdlib.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <sys/time.h>
21 #include <sys/signal.h>
22 #include <netinet/in.h>
23
24 #include "asterisk.h"
25
26 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
27
28 #include "asterisk/lock.h"
29 #include "asterisk/file.h"
30 #include "asterisk/logger.h"
31 #include "asterisk/channel.h"
32 #include "asterisk/pbx.h"
33 #include "asterisk/options.h"
34 #include "asterisk/module.h"
35 #include "asterisk/translate.h"
36 #include "asterisk/say.h"
37 #include "asterisk/config.h"
38 #include "asterisk/features.h"
39 #include "asterisk/musiconhold.h"
40 #include "asterisk/callerid.h"
41 #include "asterisk/utils.h"
42 #include "asterisk/app.h"
43 #include "asterisk/causes.h"
44 #include "asterisk/manager.h"
45 #include "asterisk/privacy.h"
46
47 static char *tdesc = "Dialing Application";
48
49 static char *app = "Dial";
50
51 static char *synopsis = "Place a call and connect to the current channel";
52
53 static char *descrip =
54 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
55 "Requests one or more channels and places specified outgoing calls on them.\n"
56 "As soon as a channel answers, the Dial app will answer the originating\n"
57 "channel (if it needs to be answered) and will bridge a call with the channel\n"
58 "which first answered. All other calls placed by the Dial app will be hung up.\n"
59 "If a timeout is not specified, the Dial application will wait indefinitely\n"
60 "until either one of the called channels answers, the user hangs up, or all\n"
61 "channels return busy or error. In general, the dialer will return 0 if it\n"
62 "was unable to place the call, or the timeout expired. However, if all\n"
63 "channels were busy, and there exists an extension with priority n+101 (where\n"
64 "n is the priority of the dialer instance), then it will be the next\n"
65 "executed extension (this allows you to setup different behavior on busy from\n"
66 "no-answer).\n"
67 "  For the Privacy and Screening Modes, the DIALSTATUS variable will be set to DONTCALL, \n"
68 "if the called party chooses to send the calling party to the 'Go Away' script, and \n"
69 "the DIALSTATUS variable will be set to TORTURE, if the called party wants to send the caller to \n"
70 "the TORTURE scripts\n"
71 "  This application returns -1 if the originating channel hangs up, or if the\n"
72 "call is bridged and either of the parties in the bridge terminate the call.\n"
73 "The option string may contain zero or more of the following characters:\n"
74 "      'd' -- allow the calling user to dial a 1 digit extension while waiting for a call to\n"
75 "             be answered exiting to that extension if it exists in the context defined by\n"
76 "             ${EXITCONTEXT} or the current context.\n"
77 "      't' -- allow the called user to transfer the calling user by hitting #.\n"
78 "      'T' -- allow the calling user to transfer the call by hitting #.\n"
79 "      'w' -- allow the called user to write the conversation to disk via app_monitor\n"
80 "      'W' -- allow the calling user to write the conversation to disk via app_monitor\n"
81 "      'f' -- Forces callerid to be set as the extension of the line \n"
82 "             making/redirecting the outgoing call. For example, some PSTNs\n"
83 "             don't allow callerids from other extensions then the ones\n"
84 "             that are assigned to you.\n"
85 "      'o' -- Original (inbound) Caller*ID should be placed on the outbound leg of the call\n" 
86 "             instead of using the destination extension (old style asterisk behavior)\n"
87 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
88 "      'm[(class)]' -- provide hold music to the calling party until answered (optionally\n"
89 "                      with the specified class.\n"
90 "      'M(x[^arg])' -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n"
91 "                      Also, the macro can set the MACRO_RESULT variable to do the following:\n"
92 "                     -- ABORT - Hangup both legs of the call.\n"
93 "                     -- CONGESTION - Behave as if line congestion was encountered.\n"
94 "                     -- BUSY - Behave as if a busy signal was encountered. (n+101)\n"
95 "                     -- CONTINUE - Hangup the called party and continue on in the dialplan.\n"
96 "                     -- GOTO:<context>^<exten>^<priority> - Transfer the call.\n"
97 "      'h' -- allow callee to hang up by hitting *.\n"
98 "      'H' -- allow caller to hang up by hitting *.\n"
99 "      'C' -- reset call detail record for this call.\n"
100 "      'P[(x)]' -- privacy mode, using 'x' as database if provided, or the extension is used if not provided.\n"
101 "      'p' -- screening mode.  Basically Privacy mode without memory.\n"
102 "       'n' -- modifier for screen/privacy mode. No intros are to be saved in the priv-callerintros dir.\n"
103 "       'N' -- modifier for screen/privacy mode. if callerID is present, do not screen the call.\n"
104 "      'g' -- goes on in context if the destination channel hangs up\n"
105 "      'G(context^exten^pri)' -- If the call is answered transfer both parties to the specified exten.\n"
106 "      'A(x)' -- play an announcement to the called party, using x as file\n"
107 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
108 "      'D([called][:calling])'  -- Send DTMF strings *after* called party has answered, but before the\n"
109 "             call gets bridged. The 'called' DTMF string is sent to the called party, and the\n"
110 "             'calling' DTMF string is sent to the calling party. Both parameters can be used alone.\n"         
111 "      'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
112 "             repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
113 "             The following special variables are optional:\n"
114 "             * LIMIT_PLAYAUDIO_CALLER    yes|no (default yes)\n"
115 "                                         Play sounds to the caller.\n"
116 "             * LIMIT_PLAYAUDIO_CALLEE    yes|no\n"
117 "                                         Play sounds to the callee.\n"
118 "             * LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
119 "             * LIMIT_CONNECT_FILE        File to play when call begins.\n"
120 "             * LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
121 "                        'timeleft' is a special sound macro to auto-say the time \n"
122 "                        left and is the default.\n"
123 "       'j' -- Jump to n+101 if all of the channels were busy.\n\n"
124 "  In addition to transferring the call, a call may be parked and then picked\n"
125 "up by another user.\n"
126 "  The optional URL will be sent to the called party if the channel supports it.\n"
127 "  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
128 "  application will be put into that group (as in SetGroup).\n"
129 "  This application sets the following channel variables upon completion:\n"
130 "      DIALEDTIME    Time from dial to answer\n" 
131 "      ANSWEREDTIME  Time for actual call\n"
132 "      DIALSTATUS    The status of the call as a text string, one of\n"
133 "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL | DONTCALL | TORTURE\n"
134 "";
135
136 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
137 static char *rapp = "RetryDial";
138 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
139 static char *rdescrip =
140 "  RetryDial(announce|sleep|loops|Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
141 "Attempt to place a call.  If no channel can be reached, play the file defined by 'announce'\n"
142 "waiting 'sleep' seconds to retry the call.  If the specified number of attempts matches \n"
143 "'loops' the call will continue in the dialplan.  If 'loops' is set to 0, the call will retry endlessly.\n\n"
144 "While waiting, a 1 digit extension may be dialed.  If that extension exists in either\n"
145 "the context defined in ${EXITCONTEXT} or the current one, The call will transfer\n"
146 "to that extension immmediately.\n\n"
147 "All arguments after 'loops' are passed directly to the Dial() application.\n"
148 "";
149
150
151 /* We define a customer "local user" structure because we
152    use it not only for keeping track of what is in use but
153    also for keeping track of who we're dialing. */
154
155 #define DIAL_STILLGOING                 (1 << 0)
156 #define DIAL_ALLOWREDIRECT_IN           (1 << 1)
157 #define DIAL_ALLOWREDIRECT_OUT          (1 << 2)
158 #define DIAL_ALLOWDISCONNECT_IN         (1 << 3)
159 #define DIAL_ALLOWDISCONNECT_OUT        (1 << 4)
160 #define DIAL_RINGBACKONLY               (1 << 5)
161 #define DIAL_MUSICONHOLD                (1 << 6)
162 #define DIAL_FORCECALLERID              (1 << 7)
163 #define DIAL_MONITOR_IN                 (1 << 8)
164 #define DIAL_MONITOR_OUT                (1 << 9)
165 #define DIAL_GO_ON                      (1 << 10)
166 #define DIAL_HALT_ON_DTMF               (1 << 11)
167 #define DIAL_PRESERVE_CALLERID          (1 << 12)
168 #define DIAL_NOFORWARDHTML              (1 << 13)
169
170 struct localuser {
171         struct ast_channel *chan;
172         unsigned int flags;
173         int forwards;
174         struct localuser *next;
175 };
176
177 LOCAL_USER_DECL;
178
179 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
180 {
181         /* Hang up a tree of stuff */
182         struct localuser *oo;
183         while (outgoing) {
184                 /* Hangup any existing lines we have open */
185                 if (outgoing->chan && (outgoing->chan != exception))
186                         ast_hangup(outgoing->chan);
187                 oo = outgoing;
188                 outgoing=outgoing->next;
189                 free(oo);
190         }
191 }
192
193 #define AST_MAX_FORWARDS   8
194
195 #define AST_MAX_WATCHERS 256
196
197 #define HANDLE_CAUSE(cause, chan) do { \
198         switch(cause) { \
199         case AST_CAUSE_BUSY: \
200                 if (chan->cdr) \
201                         ast_cdr_busy(chan->cdr); \
202                 numbusy++; \
203                 break; \
204         case AST_CAUSE_CONGESTION: \
205                 if (chan->cdr) \
206                         ast_cdr_busy(chan->cdr); \
207                 numcongestion++; \
208                 break; \
209         case AST_CAUSE_UNREGISTERED: \
210                 if (chan->cdr) \
211                         ast_cdr_busy(chan->cdr); \
212                 numnochan++; \
213                 break; \
214         default: \
215                 numnochan++; \
216                 break; \
217         } \
218 } while (0)
219
220
221 static int onedigit_goto(struct ast_channel *chan, char *context, char exten, int pri) 
222 {
223         char rexten[2] = { exten, '\0' };
224
225         if (context) {
226                 if (!ast_goto_if_exists(chan, context, rexten, pri))
227                         return 1;
228         } else {
229                 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
230                         return 1;
231                 else if (!ast_strlen_zero(chan->macrocontext)) {
232                         if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
233                                 return 1;
234                 }
235         }
236         return 0;
237 }
238
239
240 static char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
241 {
242         char *context;
243         char *exten;
244         if (!ast_strlen_zero(chan->macrocontext))
245                 context = chan->macrocontext;
246         else
247                 context = chan->context;
248
249         if (!ast_strlen_zero(chan->macroexten))
250                 exten = chan->macroexten;
251         else
252                 exten = chan->exten;
253
254         if (ast_get_hint(NULL, 0, name, namelen, chan, context, exten))
255                 return name;
256         else
257                 return "";
258 }
259
260 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
261 {
262         manager_event(EVENT_FLAG_CALL, "Dial", 
263                            "Source: %s\r\n"
264                            "Destination: %s\r\n"
265                            "CallerID: %s\r\n"
266                            "CallerIDName: %s\r\n"
267                            "SrcUniqueID: %s\r\n"
268                            "DestUniqueID: %s\r\n",
269                            src->name, dst->name, src->cid.cid_num ? src->cid.cid_num : "<unknown>",
270                            src->cid.cid_name ? src->cid.cid_name : "<unknown>", src->uniqueid,
271                            dst->uniqueid);
272 }
273
274 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 priority_jump, int *result)
275 {
276         struct localuser *o;
277         int found;
278         int numlines;
279         int numbusy = busystart;
280         int numcongestion = congestionstart;
281         int numnochan = nochanstart;
282         int prestart = busystart + congestionstart + nochanstart;
283         int cause;
284         int orig = *to;
285         struct ast_frame *f;
286         struct ast_channel *peer = NULL;
287         struct ast_channel *watchers[AST_MAX_WATCHERS];
288         int pos;
289         int single;
290         struct ast_channel *winner;
291         char *context = NULL;
292         char cidname[AST_MAX_EXTENSION];
293
294         single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, DIAL_MUSICONHOLD | DIAL_RINGBACKONLY));
295         
296         if (single) {
297                 /* Turn off hold music, etc */
298                 ast_deactivate_generator(in);
299                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
300                 ast_channel_make_compatible(outgoing->chan, in);
301         }
302         
303         
304         while (*to && !peer) {
305                 o = outgoing;
306                 found = -1;
307                 pos = 1;
308                 numlines = prestart;
309                 watchers[0] = in;
310                 while (o) {
311                         /* Keep track of important channels */
312                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) {
313                                 watchers[pos++] = o->chan;
314                                 found = 1;
315                         }
316                         o = o->next;
317                         numlines++;
318                 }
319                 if (found < 0) {
320                         if (numlines == (numbusy + numcongestion + numnochan)) {
321                                 if (option_verbose > 2)
322                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
323                                 if (numbusy)
324                                         strcpy(status, "BUSY"); 
325                                 else if (numcongestion)
326                                         strcpy(status, "CONGESTION");
327                                 else if (numnochan)
328                                         strcpy(status, "CHANUNAVAIL");
329                                 if (option_priority_jumping || priority_jump)
330                                         ast_goto_if_exists(in, in->context, in->exten, in->priority + 101);
331                         } else {
332                                 if (option_verbose > 2)
333                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
334                         }
335                         *to = 0;
336                         return NULL;
337                 }
338                 winner = ast_waitfor_n(watchers, pos, to);
339                 o = outgoing;
340                 while (o) {
341                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan && (o->chan->_state == AST_STATE_UP)) {
342                                 if (!peer) {
343                                         if (option_verbose > 2)
344                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
345                                         peer = o->chan;
346                                         ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT|DIAL_NOFORWARDHTML);
347                                 }
348                         } else if (o->chan && (o->chan == winner)) {
349                                 if (!ast_strlen_zero(o->chan->call_forward)) {
350                                         char tmpchan[256]="";
351                                         char *stuff;
352                                         char *tech;
353                                         ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
354                                         if ((stuff = strchr(tmpchan, '/'))) {
355                                                 *stuff = '\0';
356                                                 stuff++;
357                                                 tech = tmpchan;
358                                         } else {
359                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
360                                                 stuff = tmpchan;
361                                                 tech = "Local";
362                                         }
363                                         /* Before processing channel, go ahead and check for forwarding */
364                                         o->forwards++;
365                                         if (o->forwards < AST_MAX_FORWARDS) {
366                                                 if (option_verbose > 2)
367                                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
368                                                 /* Setup parameters */
369                                                 o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
370                                                 if (!o->chan)
371                                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
372                                         } else {
373                                                 if (option_verbose > 2)
374                                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", o->chan->name);
375                                                 cause = AST_CAUSE_CONGESTION;
376                                                 o->chan = NULL;
377                                         }
378                                         if (!o->chan) {
379                                                 ast_clear_flag(o, DIAL_STILLGOING);     
380                                                 HANDLE_CAUSE(cause, in);
381                                         } else {
382                                                 if (o->chan->cid.cid_num)
383                                                         free(o->chan->cid.cid_num);
384                                                 o->chan->cid.cid_num = NULL;
385                                                 if (o->chan->cid.cid_name)
386                                                         free(o->chan->cid.cid_name);
387                                                 o->chan->cid.cid_name = NULL;
388
389                                                 if (ast_test_flag(o, DIAL_FORCECALLERID)) {
390                                                         char *newcid = NULL;
391
392                                                         if (strlen(in->macroexten))
393                                                                 newcid = in->macroexten;
394                                                         else
395                                                                 newcid = in->exten;
396                                                         o->chan->cid.cid_num = strdup(newcid);
397                                                         ast_copy_string(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode));
398                                                         o->chan->cdrflags = winner->cdrflags;
399                                                         if (!o->chan->cid.cid_num)
400                                                                 ast_log(LOG_WARNING, "Out of memory\n");
401                                                 } else {
402                                                         if (in->cid.cid_num) {
403                                                                 o->chan->cid.cid_num = strdup(in->cid.cid_num);
404                                                                 if (!o->chan->cid.cid_num)
405                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
406                                                         }
407                                                         if (in->cid.cid_name) {
408                                                                 o->chan->cid.cid_name = strdup(in->cid.cid_name);
409                                                                 if (!o->chan->cid.cid_name)
410                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
411                                                         }
412                                                         ast_copy_string(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode));
413                                                         o->chan->cdrflags = in->cdrflags;
414                                                 }
415
416                                                 if (in->cid.cid_ani) {
417                                                         if (o->chan->cid.cid_ani)
418                                                                 free(o->chan->cid.cid_ani);
419                                                         o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
420                                                         if (o->chan->cid.cid_ani)
421                                                                 ast_copy_string(o->chan->cid.cid_ani, in->cid.cid_ani, sizeof(o->chan->cid.cid_ani));
422                                                         else
423                                                                 ast_log(LOG_WARNING, "Out of memory\n");
424                                                 }
425                                                 if (o->chan->cid.cid_rdnis) 
426                                                         free(o->chan->cid.cid_rdnis);
427                                                 if (!ast_strlen_zero(in->macroexten))
428                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
429                                                 else
430                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
431                                                 if (ast_call(o->chan, tmpchan, 0)) {
432                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
433                                                         ast_clear_flag(o, DIAL_STILLGOING);     
434                                                         ast_hangup(o->chan);
435                                                         o->chan = NULL;
436                                                         numnochan++;
437                                                 } else {
438                                                         senddialevent(in, o->chan);
439                                                         /* After calling, set callerid to extension */
440                                                         if (!ast_test_flag(peerflags, DIAL_PRESERVE_CALLERID))
441                                                                 ast_set_callerid(o->chan, ast_strlen_zero(in->macroexten) ? in->exten : in->macroexten, get_cid_name(cidname, sizeof(cidname), in), NULL);
442                                                 }
443                                         }
444                                         /* Hangup the original channel now, in case we needed it */
445                                         ast_hangup(winner);
446                                         continue;
447                                 }
448                                 f = ast_read(winner);
449                                 if (f) {
450                                         if (f->frametype == AST_FRAME_CONTROL) {
451                                                 switch(f->subclass) {
452                                             case AST_CONTROL_ANSWER:
453                                                         /* This is our guy if someone answered. */
454                                                         if (!peer) {
455                                                                 if (option_verbose > 2)
456                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
457                                                                 peer = o->chan;
458                                                                 ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT|DIAL_NOFORWARDHTML);
459                                                         }
460                                                         /* If call has been answered, then the eventual hangup is likely to be normal hangup */
461                                                         in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
462                                                         o->chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
463                                                         break;
464                                                 case AST_CONTROL_BUSY:
465                                                         if (option_verbose > 2)
466                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
467                                                         in->hangupcause = o->chan->hangupcause;
468                                                         ast_hangup(o->chan);
469                                                         o->chan = NULL;
470                                                         ast_clear_flag(o, DIAL_STILLGOING);     
471                                                         HANDLE_CAUSE(AST_CAUSE_BUSY, in);
472                                                         break;
473                                                 case AST_CONTROL_CONGESTION:
474                                                         if (option_verbose > 2)
475                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
476                                                         in->hangupcause = o->chan->hangupcause;
477                                                         ast_hangup(o->chan);
478                                                         o->chan = NULL;
479                                                         ast_clear_flag(o, DIAL_STILLGOING);
480                                                         HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
481                                                         break;
482                                                 case AST_CONTROL_RINGING:
483                                                         if (option_verbose > 2)
484                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
485                                                         if (!(*sentringing) && !ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
486                                                                 ast_indicate(in, AST_CONTROL_RINGING);
487                                                                 (*sentringing)++;
488                                                         }
489                                                         break;
490                                                 case AST_CONTROL_PROGRESS:
491                                                         if (option_verbose > 2)
492                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
493                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
494                                                                 ast_indicate(in, AST_CONTROL_PROGRESS);
495                                                         break;
496                                                 case AST_CONTROL_PROCEEDING:
497                                                         if (option_verbose > 2)
498                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", o->chan->name,in->name);
499                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
500                                                                 ast_indicate(in, AST_CONTROL_PROCEEDING);
501                                                         break;
502                                                 case AST_CONTROL_HOLD:
503                                                         if (option_verbose > 2)
504                                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", o->chan->name);
505                                                         ast_indicate(in, AST_CONTROL_HOLD);
506                                                         break;
507                                                 case AST_CONTROL_UNHOLD:
508                                                         if (option_verbose > 2)
509                                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", o->chan->name);
510                                                         ast_indicate(in, AST_CONTROL_UNHOLD);
511                                                         break;
512                                                 case AST_CONTROL_OFFHOOK:
513                                                 case AST_CONTROL_FLASH:
514                                                         /* Ignore going off hook and flash */
515                                                         break;
516                                                 case -1:
517                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY | DIAL_MUSICONHOLD)) {
518                                                                 if (option_verbose > 2)
519                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
520                                                                 ast_indicate(in, -1);
521                                                                 (*sentringing) = 0;
522                                                         }
523                                                         break;
524                                                 default:
525                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
526                                                 }
527                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
528                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
529                                                 if (ast_write(in, f)) 
530                                                         ast_log(LOG_DEBUG, "Unable to forward frame\n");
531                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
532                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
533                                                 if (ast_write(in, f))
534                                                         ast_log(LOG_DEBUG, "Unable to forward image\n");
535                                         } else if (single && (f->frametype == AST_FRAME_TEXT) && 
536                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
537                                                 if (ast_write(in, f))
538                                                         ast_log(LOG_DEBUG, "Unable to text\n");
539                                         } else if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
540                                                 ast_channel_sendhtml(in, f->subclass, f->data, f->datalen);
541
542                                         ast_frfree(f);
543                                 } else {
544                                         in->hangupcause = o->chan->hangupcause;
545                                         ast_hangup(o->chan);
546                                         o->chan = NULL;
547                                         ast_clear_flag(o, DIAL_STILLGOING);
548                                 }
549                         }
550                         o = o->next;
551                 }
552                 if (winner == in) {
553                         f = ast_read(in);
554 #if 0
555                         if (f && (f->frametype != AST_FRAME_VOICE))
556                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
557                         else if (!f || (f->frametype != AST_FRAME_VOICE))
558                                 printf("Hangup received on %s\n", in->name);
559 #endif
560                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
561                                 /* Got hung up */
562                                 *to=-1;
563                                 strcpy(status, "CANCEL");
564                                 if (f)
565                                         ast_frfree(f);
566                                 return NULL;
567                         }
568
569                         if (f && (f->frametype == AST_FRAME_DTMF)) {
570                                 if (ast_test_flag(peerflags, DIAL_HALT_ON_DTMF)) {
571                                         context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
572                                         if (onedigit_goto(in, context, (char) f->subclass, 1)) {
573                                                 if (option_verbose > 3)
574                                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
575                                                 *to=0;
576                                                 *result = f->subclass;
577                                                 strcpy(status, "CANCEL");
578                                                 ast_frfree(f);
579                                                 return NULL;
580                                         }
581                                 }
582
583                                 if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT) && 
584                                                   (f->subclass == '*')) { /* hmm it it not guarenteed to be '*' anymore. */
585                                         if (option_verbose > 3)
586                                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
587                                         *to=0;
588                                         strcpy(status, "CANCEL");
589                                         ast_frfree(f);
590                                         return NULL;
591                                 }
592                         }
593
594                         /* Forward HTML stuff */
595                         if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 
596                                 ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen);
597                         
598
599                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
600                                 if (ast_write(outgoing->chan, f))
601                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
602                                 ast_frfree(f);
603                         }
604                 }
605                 if (!*to && (option_verbose > 2))
606                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
607         }
608
609         return peer;
610         
611 }
612
613
614 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags)
615 {
616         int res=-1;
617         struct localuser *u;
618         char *info, *peers, *timeout, *tech, *number, *rest, *cur;
619         char  privdb[256] = "", *s;
620         char  privcid[256] = "";
621         char privintro[1024];
622         char  announcemsg[256] = "", *ann;
623         struct localuser *outgoing=NULL, *tmp;
624         struct ast_channel *peer;
625         int to;
626         int hasmacro = 0;
627         int privacy=0;
628         int screen=0;
629         int no_save_intros = 0;
630         int no_screen_callerid = 0;
631         int announce=0;
632         int resetcdr=0;
633         int numbusy = 0;
634         int numcongestion = 0;
635         int numnochan = 0;
636         int cause;
637         char numsubst[AST_MAX_EXTENSION];
638         char restofit[AST_MAX_EXTENSION];
639         char cidname[AST_MAX_EXTENSION];
640         char *transfer = NULL;
641         char *newnum;
642         char *l;
643         char *url=NULL; /* JDG */
644         int privdb_val=0;
645         unsigned int calldurationlimit=0;
646         char *cdl;
647         time_t now;
648         struct ast_bridge_config config;
649         long timelimit = 0;
650         long play_warning = 0;
651         long warning_freq=0;
652         char *warning_sound=NULL;
653         char *end_sound=NULL;
654         char *start_sound=NULL;
655         char *limitptr;
656         char limitdata[256];
657         char *sdtmfptr;
658         char *dtmfcalled=NULL, *dtmfcalling=NULL;
659         char *stack,*var;
660         char *mac = NULL, *macroname = NULL;
661         char status[256]="";
662         char toast[80];
663         int play_to_caller=0,play_to_callee=0;
664         int playargs=0, sentringing=0, moh=0;
665         char *mohclass = NULL;
666         char *outbound_group = NULL;
667         char *macro_result = NULL, *macro_transfer_dest = NULL;
668         int digit = 0, result = 0;
669         time_t start_time, answer_time, end_time;
670         struct ast_app *app = NULL;
671         char *dblgoto = NULL;
672         int priority_jump = 0;
673
674         if (!data) {
675                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
676                 return -1;
677         }
678
679         if (!(info = ast_strdupa(data))) {
680                 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
681                 return -1;
682         }
683         LOCAL_USER_ADD(u);
684         
685         peers = info;
686         if (peers) {
687                 
688                 timeout = strchr(info, '|');
689                 if (timeout) {
690                         *timeout = '\0';
691                         timeout++;
692                         transfer = strchr(timeout, '|');
693                         if (transfer) {
694                                 *transfer = '\0';
695                                 transfer++;
696                                 /* JDG */
697                                 url = strchr(transfer, '|');
698                                 if (url) {
699                                         *url = '\0';
700                                         url++;
701                                         if (option_debug)
702                                                 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
703                                 } else 
704                                         if (option_debug) {
705                                                 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
706                                         }
707                                 /* /JDG */
708                         }
709                 }
710         } else
711                 timeout = NULL;
712         if (!peers || ast_strlen_zero(peers)) {
713                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
714                 goto out;
715         }
716         
717
718         if (transfer) {
719
720                 /* Extract call duration limit */
721                 if ((cdl = strstr(transfer, "S("))) {
722                         calldurationlimit=atoi(cdl+2);
723                         if (option_verbose > 2)
724                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",calldurationlimit);                 
725                 } 
726
727                 /* Extract DTMF strings to send upon successfull connect */
728                 if ((sdtmfptr = strstr(transfer, "D("))) {
729                         dtmfcalled = ast_strdupa(sdtmfptr + 2);
730                         dtmfcalling = strchr(dtmfcalled, ')');
731                         if (dtmfcalling)
732                                 *dtmfcalling = '\0';
733                         dtmfcalling = strchr(dtmfcalled, ':');
734                         if (dtmfcalling) {
735                                 *dtmfcalling = '\0';
736                                 dtmfcalling++;
737                         }                               
738                         /* Overwrite with X's what was the sdtmf info */
739                         while (*sdtmfptr && (*sdtmfptr != ')')) 
740                                 *(sdtmfptr++) = 'X';
741                         if (*sdtmfptr)
742                                 *sdtmfptr = 'X';
743                         else 
744                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
745                 }
746   
747                 /* XXX LIMIT SUPPORT */
748                 if ((limitptr = strstr(transfer, "L("))) {
749                         ast_copy_string(limitdata, limitptr + 2, sizeof(limitdata));
750                         /* Overwrite with X's what was the limit info */
751                         while (*limitptr && (*limitptr != ')')) 
752                                 *(limitptr++) = 'X';
753                         if (*limitptr)
754                                 *limitptr = 'X';
755                         /* Now find the end */
756                         limitptr = strchr(limitdata, ')');
757                         if (limitptr)
758                                 *limitptr = '\0';
759                         else
760                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
761
762                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
763                         play_to_caller = var ? ast_true(var) : 1;
764                   
765                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
766                         play_to_callee = var ? ast_true(var) : 0;
767                   
768                         if (!play_to_caller && !play_to_callee)
769                                 play_to_caller=1;
770                   
771                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
772                         warning_sound = var ? var : "timeleft";
773
774                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
775                         end_sound = var ? var : NULL;
776
777                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
778                         start_sound = var ? var : NULL;
779
780                         var=stack=limitdata;
781
782                         var = strsep(&stack, ":");
783                         if (var) {
784                                 timelimit = atol(var);
785                                 playargs++;
786                                 var = strsep(&stack, ":");
787                                 if (var) {
788                                         play_warning = atol(var);
789                                         playargs++;
790                                         var = strsep(&stack, ":");
791                                         if (var) {
792                                                 warning_freq = atol(var);
793                                                 playargs++;
794                                         }
795                                 }
796                         }
797                   
798                         if (!timelimit) {
799                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
800                                 warning_sound=NULL;
801                         }
802                         /* undo effect of S(x) in case they are both used */
803                         calldurationlimit=0; 
804                         /* more efficient do it like S(x) does since no advanced opts*/
805                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
806                                 calldurationlimit=timelimit/1000;
807                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
808                         } else if (option_verbose > 2) {
809                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
810                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
811                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
812                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
813                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
814                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
815                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
816                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
817                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
818                         }
819                 }
820                 
821                 /* XXX ANNOUNCE SUPPORT */
822                 if ((ann = strstr(transfer, "A("))) {
823                         announce = 1;
824                         ast_copy_string(announcemsg, ann + 2, sizeof(announcemsg));
825                         /* Overwrite with X's what was the announce info */
826                         while (*ann && (*ann != ')')) 
827                                 *(ann++) = 'X';
828                         if (*ann)
829                                 *ann = 'X';
830                         /* Now find the end of the announce */
831                         ann = strchr(announcemsg, ')');
832                         if (ann)
833                                 *ann = '\0';
834                         else {
835                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
836                                 announce = 0;
837                         }
838                 }
839
840                 /* Get the goto from the dial option string */
841                 if ((mac = strstr(transfer, "G("))) {
842
843
844                         dblgoto = ast_strdupa(mac + 2);
845                         while (*mac && (*mac != ')'))
846                                 *(mac++) = 'X';
847                         if (*mac) {
848                                 *mac = 'X';
849                                 mac = strchr(dblgoto, ')');
850                                 if (mac)
851                                         *mac = '\0';
852                                 else {
853                                         ast_log(LOG_WARNING, "Goto flag set without trailing ')'\n");
854                                         dblgoto = NULL;
855                                 }
856                         } else {
857                                 ast_log(LOG_WARNING, "Could not find exten to which we should jump.\n");
858                                 dblgoto = NULL;
859                         }
860                 }
861
862                 /* Get the macroname from the dial option string */
863                 if ((mac = strstr(transfer, "M("))) {
864                         hasmacro = 1;
865                         macroname = ast_strdupa(mac + 2);
866                         while (*mac && (*mac != ')'))
867                                 *(mac++) = 'X';
868                         if (*mac) {
869                                 *mac = 'X';
870                                 mac = strchr(macroname, ')');
871                                 if (mac)
872                                         *mac = '\0';
873                                 else {
874                                         ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
875                                         hasmacro = 0;
876                                 }
877                         } else {
878                                 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
879                                 hasmacro = 0;
880                         }
881                 }
882                 /* Get music on hold class */
883                 if ((mac = strstr(transfer, "m("))) {
884                         mohclass = ast_strdupa(mac + 2);
885                         mac++; /* Leave the "m" in the string */
886                         while (*mac && (*mac != ')'))
887                                 *(mac++) = 'X';
888                         if (*mac) {
889                                 *mac = 'X';
890                                 mac = strchr(mohclass, ')');
891                                 if (mac)
892                                         *mac = '\0';
893                                 else {
894                                         ast_log(LOG_WARNING, "Music on hold class specified without trailing ')'\n");
895                                         mohclass = NULL;
896                                 }
897                         } else {
898                                 ast_log(LOG_WARNING, "Could not find music on hold class to use, assuming default.\n");
899                                 mohclass=NULL;
900                         }
901                 }
902                 /* Extract privacy info from transfer */
903                 if ((s = strstr(transfer, "P("))) {
904                         privacy = 1;
905                         ast_copy_string(privdb, s + 2, sizeof(privdb));
906                         /* Overwrite with X's what was the privacy info */
907                         while (*s && (*s != ')')) 
908                                 *(s++) = 'X';
909                         if (*s)
910                                 *s = 'X';
911                         /* Now find the end of the privdb */
912                         s = strchr(privdb, ')');
913                         if (s)
914                                 *s = '\0';
915                         else {
916                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
917                                 privacy = 0;
918                         }
919                 } else if (strchr(transfer, 'P')) {
920                         /* No specified privdb */
921                         privacy = 1;
922                 } else if (strchr(transfer, 'p')) {
923                         screen = 1;
924                 } else if (strchr(transfer, 'C')) {
925                         resetcdr = 1;
926                 } else if (strchr(transfer, 'j')) {
927                         priority_jump = 1;
928                 }
929                 if (strchr(transfer, 'n')) {
930                         no_save_intros = 1;
931                 } 
932                 if (strchr(transfer, 'N')) {
933                         no_screen_callerid = 1;
934                 }
935         }
936         if (resetcdr && chan->cdr)
937                 ast_cdr_reset(chan->cdr, 0);
938         if (ast_strlen_zero(privdb) && privacy) {
939                 /* If privdb is not specified and we are using privacy, copy from extension */
940                 ast_copy_string(privdb, chan->exten, sizeof(privdb));
941         }
942         if (privacy || screen) {
943                 char callerid[60];
944
945                 l = chan->cid.cid_num;
946                 if (l && !ast_strlen_zero(l)) {
947                         ast_shrink_phone_number(l);
948                         if( privacy ) {
949                                 if (option_verbose > 2)
950                                         ast_verbose( VERBOSE_PREFIX_3  "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
951                                 privdb_val = ast_privacy_check(privdb, l);
952                         }
953                         else {
954                                 if (option_verbose > 2)
955                                         ast_verbose( VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l);
956                                 privdb_val = AST_PRIVACY_UNKNOWN;
957                         }
958                 } else {
959                         char *tnam, *tn2;
960
961                         tnam = ast_strdupa(chan->name);
962                         /* clean the channel name so slashes don't try to end up in disk file name */
963                         for(tn2 = tnam; *tn2; tn2++) {
964                                 if( *tn2=='/')
965                                         *tn2 = '=';  /* any other chars to be afraid of? */
966                         }
967                         if (option_verbose > 2)
968                                 ast_verbose( VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n");
969
970                         snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
971                         l = callerid;
972                         privdb_val = AST_PRIVACY_UNKNOWN;
973                 }
974                 
975                 ast_copy_string(privcid,l,sizeof(privcid));
976
977                 if( strncmp(privcid,"NOCALLERID",10) != 0 && no_screen_callerid ) { /* if callerid is set, and no_screen_callerid is set also */  
978                         if (option_verbose > 2)
979                                 ast_verbose( VERBOSE_PREFIX_3  "CallerID set (%s); N option set; Screening should be off\n", privcid);
980                         privdb_val = AST_PRIVACY_ALLOW;
981                 }
982                 else if( no_screen_callerid && strncmp(privcid,"NOCALLERID",10) == 0 ) {
983                         if (option_verbose > 2)
984                                 ast_verbose( VERBOSE_PREFIX_3  "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
985                 }
986                 
987                 if( privdb_val == AST_PRIVACY_DENY ) {
988                         ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
989                         res=0;
990                         goto out;
991                 }
992                 else if( privdb_val == AST_PRIVACY_KILL ) {
993                         if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 201, chan->cid.cid_num)) 
994                                 chan->priority+=200;
995
996                         res = 0;
997                         goto out; /* Is this right? */
998                 }
999                 else if( privdb_val == AST_PRIVACY_TORTURE ) {
1000                         if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 301, chan->cid.cid_num)) 
1001                                 chan->priority+=300;
1002                         res = 0;
1003                         goto out; /* is this right??? */
1004
1005                 }
1006                 else if( privdb_val == AST_PRIVACY_UNKNOWN ) {
1007                         /* Get the user's intro, store it in priv-callerintros/$CID, 
1008                            unless it is already there-- this should be done before the 
1009                            call is actually dialed  */
1010
1011                         /* make sure the priv-callerintros dir exists? */
1012
1013                         snprintf(privintro,sizeof(privintro),"priv-callerintros/%s", privcid);
1014                         if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
1015                                 /* the DELUX version of this code would allow this caller the
1016                                    option to hear and retape their previously recorded intro.
1017                                 */
1018                         }
1019                         else {
1020                                 int duration; /* for feedback from play_and_wait */
1021                                 /* the file doesn't exist yet. Let the caller submit his
1022                                    vocal intro for posterity */
1023                                 /* priv-recordintro script:
1024
1025                                    "At the tone, please say your name:"
1026
1027                                 */
1028                                 ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */
1029                                                                                                                         /* don't think we'll need a lock removed, we took care of
1030                                                                                                                            conflicts by naming the privintro file */
1031                         }
1032                 }
1033         }
1034
1035         /* If a channel group has been specified, get it for use when we create peer channels */
1036         outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1037
1038         cur = peers;
1039         do {
1040                 /* Remember where to start next time */
1041                 rest = strchr(cur, '&');
1042                 if (rest) {
1043                         *rest = 0;
1044                         rest++;
1045                 }
1046                 /* Get a technology/[device:]number pair */
1047                 tech = cur;
1048                 number = strchr(tech, '/');
1049                 if (!number) {
1050                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
1051                         goto out;
1052                 }
1053                 *number = '\0';
1054                 number++;
1055                 tmp = malloc(sizeof(struct localuser));
1056                 if (!tmp) {
1057                         ast_log(LOG_WARNING, "Out of memory\n");
1058                         goto out;
1059                 }
1060                 memset(tmp, 0, sizeof(struct localuser));
1061                 if (transfer) {
1062                         ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_IN);
1063                         ast_set2_flag(tmp, strchr(transfer, 'T'), DIAL_ALLOWREDIRECT_OUT);
1064                         ast_set2_flag(tmp, strchr(transfer, 'r'), DIAL_RINGBACKONLY);   
1065                         ast_set2_flag(tmp, strchr(transfer, 'm'), DIAL_MUSICONHOLD);    
1066                         ast_set2_flag(tmp, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);    
1067                         ast_set2_flag(peerflags, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);      
1068                         ast_set2_flag(tmp, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
1069                         ast_set2_flag(peerflags, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
1070                         ast_set2_flag(tmp, strchr(transfer, 'f'), DIAL_FORCECALLERID);  
1071                         ast_set2_flag(tmp, url, DIAL_NOFORWARDHTML);    
1072                         ast_set2_flag(peerflags, strchr(transfer, 'w'), DIAL_MONITOR_IN);       
1073                         ast_set2_flag(peerflags, strchr(transfer, 'W'), DIAL_MONITOR_OUT);      
1074                         ast_set2_flag(peerflags, strchr(transfer, 'd'), DIAL_HALT_ON_DTMF);     
1075                         ast_set2_flag(peerflags, strchr(transfer, 'g'), DIAL_GO_ON);    
1076                         ast_set2_flag(peerflags, strchr(transfer, 'o'), DIAL_PRESERVE_CALLERID);        
1077                 }
1078                 ast_copy_string(numsubst, number, sizeof(numsubst));
1079                 /* If we're dialing by extension, look at the extension to know what to dial */
1080                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
1081                         /* strlen("BYEXTENSION") == 11 */
1082                         ast_copy_string(restofit, newnum + 11, sizeof(restofit));
1083                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
1084                         if (option_debug)
1085                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
1086                 }
1087                 /* Request the peer */
1088                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1089                 if (!tmp->chan) {
1090                         /* If we can't, just go on to the next call */
1091                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1092                         HANDLE_CAUSE(cause, chan);
1093                         cur = rest;
1094                         continue;
1095                 }
1096                 pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
1097                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
1098                         char tmpchan[256]="";
1099                         char *stuff;
1100                         char *tech;
1101                         ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan));
1102                         if ((stuff = strchr(tmpchan, '/'))) {
1103                                 *stuff = '\0';
1104                                 stuff++;
1105                                 tech = tmpchan;
1106                         } else {
1107                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
1108                                 stuff = tmpchan;
1109                                 tech = "Local";
1110                         }
1111                         tmp->forwards++;
1112                         if (tmp->forwards < AST_MAX_FORWARDS) {
1113                                 if (option_verbose > 2)
1114                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1115                                 ast_hangup(tmp->chan);
1116                                 /* Setup parameters */
1117                                 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1118                                 if (!tmp->chan)
1119                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1120                         } else {
1121                                 if (option_verbose > 2)
1122                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
1123                                 ast_hangup(tmp->chan);
1124                                 tmp->chan = NULL;
1125                                 cause = AST_CAUSE_CONGESTION;
1126                         }
1127                         if (!tmp->chan) {
1128                                 HANDLE_CAUSE(cause, chan);
1129                                 cur = rest;
1130                                 continue;
1131                         }
1132                 }
1133
1134                 /* Inherit specially named variables from parent channel */
1135                 ast_channel_inherit_variables(chan, tmp->chan);
1136
1137                 tmp->chan->appl = "AppDial";
1138                 tmp->chan->data = "(Outgoing Line)";
1139                 tmp->chan->whentohangup = 0;
1140                 if (tmp->chan->cid.cid_num)
1141                         free(tmp->chan->cid.cid_num);
1142                 tmp->chan->cid.cid_num = NULL;
1143                 if (tmp->chan->cid.cid_name)
1144                         free(tmp->chan->cid.cid_name);
1145                 tmp->chan->cid.cid_name = NULL;
1146                 if (tmp->chan->cid.cid_ani)
1147                         free(tmp->chan->cid.cid_ani);
1148                 tmp->chan->cid.cid_ani = NULL;
1149
1150                 if (chan->cid.cid_num) 
1151                         tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
1152                 if (chan->cid.cid_name) 
1153                         tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
1154                 if (chan->cid.cid_ani) 
1155                         tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
1156                 
1157                 /* Copy language from incoming to outgoing */
1158                 ast_copy_string(tmp->chan->language, chan->language, sizeof(tmp->chan->language));
1159                 ast_copy_string(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode));
1160                 tmp->chan->cdrflags = chan->cdrflags;
1161                 if (ast_strlen_zero(tmp->chan->musicclass))
1162                         ast_copy_string(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass));
1163                 if (chan->cid.cid_rdnis)
1164                         tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
1165                 /* Pass callingpres setting */
1166                 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
1167                 /* Pass type of number */
1168                 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
1169                 /* Pass type of tns */
1170                 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
1171                 /* Presense of ADSI CPE on outgoing channel follows ours */
1172                 tmp->chan->adsicpe = chan->adsicpe;
1173                 /* Pass the transfer capability */
1174                 tmp->chan->transfercapability = chan->transfercapability;
1175
1176                 /* If we have an outbound group, set this peer channel to it */
1177                 if (outbound_group)
1178                         ast_app_group_set_channel(tmp->chan, outbound_group);
1179
1180                 /* Place the call, but don't wait on the answer */
1181                 res = ast_call(tmp->chan, numsubst, 0);
1182
1183                 /* Save the info in cdr's that we called them */
1184                 if (chan->cdr)
1185                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
1186
1187                 /* check the results of ast_call */
1188                 if (res) {
1189                         /* Again, keep going even if there's an error */
1190                         if (option_debug)
1191                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1192                         else if (option_verbose > 2)
1193                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1194                         ast_hangup(tmp->chan);
1195                         tmp->chan = NULL;
1196                         cur = rest;
1197                         continue;
1198                 } else {
1199                         senddialevent(chan, tmp->chan);
1200                         if (option_verbose > 2)
1201                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1202                         if (!ast_test_flag(peerflags, DIAL_PRESERVE_CALLERID))
1203                                 ast_set_callerid(tmp->chan, ast_strlen_zero(chan->macroexten) ? chan->exten : chan->macroexten, get_cid_name(cidname, sizeof(cidname), chan), NULL);
1204                 }
1205                 /* Put them in the list of outgoing thingies...  We're ready now. 
1206                    XXX If we're forcibly removed, these outgoing calls won't get
1207                    hung up XXX */
1208                 ast_set_flag(tmp, DIAL_STILLGOING);     
1209                 tmp->next = outgoing;
1210                 outgoing = tmp;
1211                 /* If this line is up, don't try anybody else */
1212                 if (outgoing->chan->_state == AST_STATE_UP)
1213                         break;
1214                 cur = rest;
1215         } while (cur);
1216         
1217         if (timeout && !ast_strlen_zero(timeout)) {
1218                 to = atoi(timeout);
1219                 if (to > 0)
1220                         to *= 1000;
1221                 else
1222                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
1223         } else
1224                 to = -1;
1225
1226         if (outgoing) {
1227                 /* Our status will at least be NOANSWER */
1228                 strcpy(status, "NOANSWER");
1229                 if (ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
1230                         moh=1;
1231                         ast_moh_start(chan, mohclass);
1232                 } else if (ast_test_flag(outgoing, DIAL_RINGBACKONLY)) {
1233                         ast_indicate(chan, AST_CONTROL_RINGING);
1234                         sentringing++;
1235                 }
1236         } else
1237                 strcpy(status, "CHANUNAVAIL");
1238
1239         time(&start_time);
1240         peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, priority_jump, &result);
1241         
1242         if (!peer) {
1243                 if (result) {
1244                         res = result;
1245                 }
1246                 else if (to) 
1247                         /* Musta gotten hung up */
1248                         res = -1;
1249                 else 
1250                         /* Nobody answered, next please? */
1251                         res=0;
1252                 
1253                 goto out;
1254         }
1255         if (peer) {
1256                 time(&answer_time);
1257 #ifdef OSP_SUPPORT
1258                 /* Once call is answered, ditch the OSP Handle */
1259                 pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
1260 #endif
1261                 strcpy(status, "ANSWER");
1262                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1263                    we will always return with -1 so that it is hung up properly after the 
1264                    conversation.  */
1265                 hanguptree(outgoing, peer);
1266                 outgoing = NULL;
1267                 /* If appropriate, log that we have a destination channel */
1268                 if (chan->cdr)
1269                         ast_cdr_setdestchan(chan->cdr, peer->name);
1270                 if (peer->name)
1271                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1272
1273                 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1274                 if (!number)
1275                         number = numsubst;
1276                 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1277                 /* JDG: sendurl */
1278                 if ( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1279                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
1280                         ast_channel_sendurl( peer, url );
1281                 } /* /JDG */
1282                 if( privacy || screen ) {
1283                         int res2;
1284                         int loopcount = 0;
1285                         if( privdb_val == AST_PRIVACY_UNKNOWN ) {
1286
1287                                 /* Get the user's intro, store it in priv-callerintros/$CID, 
1288                                    unless it is already there-- this should be done before the 
1289                                    call is actually dialed  */
1290
1291                                 /* all ring indications and moh for the caller has been halted as soon as the 
1292                                    target extension was picked up. We are going to have to kill some
1293                                    time and make the caller believe the peer hasn't picked up yet */
1294
1295                                 if ( strchr(transfer, 'm') ) {
1296                                         ast_indicate(chan, -1);
1297                                         ast_moh_start(chan, mohclass);
1298                                 } else if ( strchr(transfer, 'r') ) {
1299                                         ast_indicate(chan, AST_CONTROL_RINGING);
1300                                         sentringing++;
1301                                 }
1302
1303                                 /* Start autoservice on the other chan ?? */
1304                                 res2 = ast_autoservice_start(chan);
1305                                 /* Now Stream the File */
1306                                 if (!res2) {
1307                                         do {
1308                                                 if (!res2)
1309                                                         res2 = ast_play_and_wait(peer,"priv-callpending");
1310                                                 if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */
1311                                                         res2 = 0;
1312                                                 
1313                                                 /* priv-callpending script: 
1314                                                    "I have a caller waiting, who introduces themselves as:"
1315                                                 */
1316                                                 if (!res2)
1317                                                         res2 = ast_play_and_wait(peer,privintro);
1318                                                 if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */
1319                                                         res2 = 0;
1320                                                 /* now get input from the called party, as to their choice */
1321                                                 if( !res2 ) {
1322                                                         if( privacy )
1323                                                                 res2 = ast_play_and_wait(peer,"priv-callee-options");
1324                                                         if( screen )
1325                                                                 res2 = ast_play_and_wait(peer,"screen-callee-options");
1326                                                 }
1327                                                 /* priv-callee-options script:
1328                                                         "Dial 1 if you wish this caller to reach you directly in the future,
1329                                                                 and immediately connect to their incoming call
1330                                                          Dial 2 if you wish to send this caller to voicemail now and 
1331                                                                 forevermore.
1332                                                          Dial 3 to send this callerr to the torture menus, now and forevermore.
1333                                                          Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
1334                                                          Dial 5 to allow this caller to come straight thru to you in the future,
1335                                                 but right now, just this once, send them to voicemail."
1336                                                 */
1337                                 
1338                                                 /* screen-callee-options script:
1339                                                         "Dial 1 if you wish to immediately connect to the incoming call
1340                                                          Dial 2 if you wish to send this caller to voicemail.
1341                                                          Dial 3 to send this callerr to the torture menus.
1342                                                          Dial 4 to send this caller to a simple "go away" menu.
1343                                                 */
1344                                                 if( !res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4') ) {
1345                                                         /* invalid option */
1346                                                         res2 = ast_play_and_wait(peer,"vm-sorry");
1347                                                 }
1348                                                 loopcount++; /* give the callee a couple chances to make a choice */
1349                                         } while( (!res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4')) && loopcount < 2 );
1350                                 }
1351
1352                                 switch(res2) {
1353                                 case '1':
1354                                         if( privacy ) {
1355                                                 if (option_verbose > 2)
1356                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid);
1357                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW);
1358                                         }
1359                                         break;
1360                                 case '2':
1361                                         if( privacy ) {
1362                                                 if (option_verbose > 2)
1363                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n", privdb, privcid);
1364                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_DENY);
1365                                         }
1366                                         if ( strchr(transfer, 'm') ) {
1367                                                 ast_moh_stop(chan);
1368                                         } else if ( strchr(transfer, 'r') ) {
1369                                                 ast_indicate(chan, -1);
1370                                                 sentringing=0;
1371                                         }
1372                                         res2 = ast_autoservice_stop(chan);
1373                                         ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1374                                         res=0;
1375                                         goto out;
1376                                         break;
1377                                 case '3':
1378                                         if( privacy ) {
1379                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_TORTURE);
1380                                                 if (option_verbose > 2)
1381                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n", privdb, privcid);
1382                                         }
1383                                         ast_copy_string(status, "TORTURE", sizeof(status));
1384                                         
1385                                         res = 0;
1386                                         if ( strchr(transfer, 'm') ) {
1387                                                 ast_moh_stop(chan);
1388                                         } else if ( strchr(transfer, 'r') ) {
1389                                                 ast_indicate(chan, -1);
1390                                                 sentringing=0;
1391                                         }
1392                                         res2 = ast_autoservice_stop(chan);
1393                                         ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1394                                         goto out; /* Is this right? */
1395                                         break;
1396                                 case '4':
1397                                         if( privacy ) {
1398                                                 if (option_verbose > 2)
1399                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n", privdb, privcid);
1400                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_KILL);
1401                                         }
1402
1403                                         ast_copy_string(status, "DONTCALL", sizeof(status));
1404                                         res = 0;
1405                                         if ( strchr(transfer, 'm') ) {
1406                                                 ast_moh_stop(chan);
1407                                         } else if ( strchr(transfer, 'r') ) {
1408                                                 ast_indicate(chan, -1);
1409                                                 sentringing=0;
1410                                         }
1411                                         res2 = ast_autoservice_stop(chan);
1412                                         ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1413                                         goto out; /* Is this right? */
1414                                         break;
1415                                 case '5':
1416                                         if( privacy ) {
1417                                                 if (option_verbose > 2)
1418                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid);
1419                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW);
1420                                         
1421                                                 if ( strchr(transfer, 'm') ) {
1422                                                         ast_moh_stop(chan);
1423                                                 } else if ( strchr(transfer, 'r') ) {
1424                                                         ast_indicate(chan, -1);
1425                                                         sentringing=0;
1426                                                 }
1427                                                 res2 = ast_autoservice_stop(chan);
1428                                                 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1429                                                 res=0;
1430                                                 goto out;
1431                                                 break;
1432                                         } /* if not privacy, then 5 is the same as "default" case */
1433                                 default:
1434                                         /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */
1435                                         /* well, there seems basically two choices. Just patch the caller thru immediately,
1436                                                   or,... put 'em thru to voicemail. */
1437                                         /* since the callee may have hung up, let's do the voicemail thing, no database decision */
1438                                         if (option_verbose > 2)
1439                                                 ast_log(LOG_NOTICE,"privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
1440                                         if ( strchr(transfer, 'm') ) {
1441                                                 ast_moh_stop(chan);
1442                                         } else if ( strchr(transfer, 'r') ) {
1443                                                 ast_indicate(chan, -1);
1444                                                 sentringing=0;
1445                                         }
1446                                         res2 = ast_autoservice_stop(chan);
1447                                         ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1448                                         res=0;
1449                                         goto out;
1450                                         break;
1451                                 }
1452                                 if ( strchr(transfer, 'm') ) {
1453                                         ast_moh_stop(chan);
1454                                 } else if ( strchr(transfer, 'r') ) {
1455                                         ast_indicate(chan, -1);
1456                                         sentringing=0;
1457                                 }
1458                                 res2 = ast_autoservice_stop(chan);
1459                                 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll 
1460                                    just clog things up, and it's not useful information, not being tied to a CID */
1461                                 if( strncmp(privcid,"NOCALLERID",10) == 0 || no_save_intros ) {
1462                                         ast_filedelete(privintro, NULL);
1463                                         if( ast_fileexists(privintro,NULL,NULL ) > 0 )
1464                                                 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
1465                                         else if (option_verbose > 2)
1466                                                 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1467                                 }
1468                         }
1469                 }
1470                 if (announce && announcemsg) {
1471                         /* Start autoservice on the other chan */
1472                         res = ast_autoservice_start(chan);
1473                         /* Now Stream the File */
1474                         if (!res)
1475                                 res = ast_streamfile(peer,announcemsg,peer->language);
1476                         if (!res) {
1477                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
1478                         }
1479                         /* Ok, done. stop autoservice */
1480                         res = ast_autoservice_stop(chan);
1481                         if (digit > 0 && !res)
1482                                 res = ast_senddigit(chan, digit); 
1483                         else
1484                                 res = digit;
1485
1486                 } else
1487                         res = 0;
1488
1489                 if (chan && peer && dblgoto) {
1490                         for (mac=dblgoto; *mac; mac++) {
1491                                 if(*mac == '^') {
1492                                         *mac = '|';
1493                                 }
1494                         }
1495                         ast_parseable_goto(chan, dblgoto);
1496                         ast_parseable_goto(peer, dblgoto);
1497                         peer->priority++;
1498                         ast_pbx_start(peer);
1499                         hanguptree(outgoing, NULL);
1500                         LOCAL_USER_REMOVE(u);
1501                         return 0;
1502                 }
1503
1504                 if (hasmacro && macroname) {
1505                         res = ast_autoservice_start(chan);
1506                         if (res) {
1507                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1508                                 res = -1;
1509                         }
1510
1511                         app = pbx_findapp("Macro");
1512
1513                         if (app && !res) {
1514                                 for (res=0;res<strlen(macroname);res++)
1515                                         if (macroname[res] == '^')
1516                                                 macroname[res] = '|';
1517                                 res = pbx_exec(peer, app, macroname, 1);
1518                                 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1519                                 res = 0;
1520                         } else {
1521                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1522                                 res = -1;
1523                         }
1524
1525                         if (ast_autoservice_stop(chan) < 0) {
1526                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1527                                 res = -1;
1528                         }
1529
1530                         if (!res) {
1531                                 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1532                                         if (!strcasecmp(macro_result, "BUSY")) {
1533                                                 ast_copy_string(status, macro_result, sizeof(status));
1534                                                 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1535                                                         ast_set_flag(peerflags, DIAL_GO_ON);
1536                                                 }
1537                                                 res = -1;
1538                                         }
1539                                         else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1540                                                 ast_copy_string(status, macro_result, sizeof(status));
1541                                                 ast_set_flag(peerflags, DIAL_GO_ON);    
1542                                                 res = -1;
1543                                         }
1544                                         else if (!strcasecmp(macro_result, "CONTINUE")) {
1545                                                 /* hangup peer and keep chan alive assuming the macro has changed 
1546                                                    the context / exten / priority or perhaps 
1547                                                    the next priority in the current exten is desired.
1548                                                 */
1549                                                 ast_set_flag(peerflags, DIAL_GO_ON);    
1550                                                 res = -1;
1551                                         } else if (!strcasecmp(macro_result, "ABORT")) {
1552                                                 /* Hangup both ends unless the caller has the g flag */
1553                                                 res = -1;
1554                                         } else if (!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1555                                                 res = -1;
1556                                                 /* perform a transfer to a new extension */
1557                                                 if (strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
1558                                                         /* no brainer mode... substitute ^ with | and feed it to builtin goto */
1559                                                         for (res=0;res<strlen(macro_transfer_dest);res++)
1560                                                                 if (macro_transfer_dest[res] == '^')
1561                                                                         macro_transfer_dest[res] = '|';
1562
1563                                                         if (!ast_parseable_goto(chan, macro_transfer_dest))
1564                                                                 ast_set_flag(peerflags, DIAL_GO_ON);
1565
1566                                                 }
1567                                         }
1568                                 }
1569                         }
1570                 }
1571
1572                 if (!res) {
1573                         if (calldurationlimit > 0) {
1574                                 time(&now);
1575                                 chan->whentohangup = now + calldurationlimit;
1576                         }
1577                         if (dtmfcalled && !ast_strlen_zero(dtmfcalled)) { 
1578                                 if (option_verbose > 2)
1579                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n",dtmfcalled);
1580                                 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1581                         }
1582                         if (dtmfcalling && !ast_strlen_zero(dtmfcalling)) {
1583                                 if (option_verbose > 2)
1584                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n",dtmfcalling);
1585                                 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1586                         }
1587                 }
1588                 
1589                 if (!res) {
1590                         memset(&config,0,sizeof(struct ast_bridge_config));
1591                         if (play_to_caller)
1592                                 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1593                         if (play_to_callee)
1594                                 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1595                         if (ast_test_flag(peerflags, DIAL_ALLOWREDIRECT_IN))
1596                                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1597                         if (ast_test_flag(peerflags, DIAL_ALLOWREDIRECT_OUT))
1598                                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1599                         if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_IN))
1600                                 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1601                         if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT))
1602                                 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1603                         if (ast_test_flag(peerflags, DIAL_MONITOR_IN))
1604                                 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1605                         if (ast_test_flag(peerflags, DIAL_MONITOR_OUT)) 
1606                                 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1607
1608                         config.timelimit = timelimit;
1609                         config.play_warning = play_warning;
1610                         config.warning_freq = warning_freq;
1611                         config.warning_sound = warning_sound;
1612                         config.end_sound = end_sound;
1613                         config.start_sound = start_sound;
1614                         if (moh) {
1615                                 moh = 0;
1616                                 ast_moh_stop(chan);
1617                         } else if (sentringing) {
1618                                 sentringing = 0;
1619                                 ast_indicate(chan, -1);
1620                         }
1621                         /* Be sure no generators are left on it */
1622                         ast_deactivate_generator(chan);
1623                         /* Make sure channels are compatible */
1624                         res = ast_channel_make_compatible(chan, peer);
1625                         if (res < 0) {
1626                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1627                                 ast_hangup(peer);
1628                                 return -1;
1629                         }
1630                         res = ast_bridge_call(chan,peer,&config);
1631                         time(&end_time);
1632                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1633                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1634                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1635                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1636                         
1637                 } else 
1638                         res = -1;
1639                 
1640                 if (res != AST_PBX_NO_HANGUP_PEER) {
1641                         if (!chan->_softhangup)
1642                                 chan->hangupcause = peer->hangupcause;
1643                         ast_hangup(peer);
1644                 }
1645         }       
1646 out:
1647         if (moh) {
1648                 moh = 0;
1649                 ast_moh_stop(chan);
1650         } else if (sentringing) {
1651                 sentringing = 0;
1652                 ast_indicate(chan, -1);
1653         }
1654         hanguptree(outgoing, NULL);
1655         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1656         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1657         
1658         LOCAL_USER_REMOVE(u);
1659         
1660         if ((ast_test_flag(peerflags, DIAL_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
1661             res=0;
1662             
1663         return res;
1664 }
1665
1666 static int dial_exec(struct ast_channel *chan, void *data)
1667 {
1668         struct ast_flags peerflags;
1669         memset(&peerflags, 0, sizeof(peerflags));
1670         return dial_exec_full(chan, data, &peerflags);
1671 }
1672
1673 static int retrydial_exec(struct ast_channel *chan, void *data)
1674 {
1675         char *announce = NULL, *context = NULL, *dialdata = NULL;
1676         int sleep = 0, loops = 0, res = 0;
1677         struct localuser *u = NULL;
1678         struct ast_flags peerflags;
1679         
1680         memset(&peerflags, 0, sizeof(peerflags));
1681
1682         LOCAL_USER_ADD(u);
1683         
1684         if (!data || !(announce = ast_strdupa(data))) {
1685                 ast_log(LOG_ERROR, "Out of memory!\n");
1686                 LOCAL_USER_REMOVE(u);
1687                 return -1;
1688         }
1689         
1690         if ((dialdata = strchr(announce, '|'))) {
1691                 *dialdata = '\0';
1692                 dialdata++;
1693                 if ((sleep = atoi(dialdata))) {
1694                         sleep *= 1000;
1695                 } else {
1696                         ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1697                         LOCAL_USER_REMOVE(u);
1698                         return -1;
1699                 }
1700                 if ((dialdata = strchr(dialdata, '|'))) {
1701                         *dialdata = '\0';
1702                         dialdata++;
1703                         if (!(loops = atoi(dialdata))) {
1704                                 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1705                                 LOCAL_USER_REMOVE(u);
1706                                 return -1;
1707                         }
1708                 }
1709         }
1710         
1711         if ((dialdata = strchr(dialdata, '|'))) {
1712                 *dialdata = '\0';
1713                 dialdata++;
1714         } else {
1715                 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1716                 LOCAL_USER_REMOVE(u);
1717                 return -1;
1718         }
1719                 
1720         if (sleep < 1000)
1721                 sleep = 10000;
1722         
1723         if (!loops)
1724                 loops = -1;
1725         
1726         context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1727         
1728         while (loops) {
1729                 chan->data = "Retrying";
1730                 if (ast_test_flag(chan, AST_FLAG_MOH))
1731                         ast_moh_stop(chan);
1732
1733                 if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) {
1734                         if (ast_test_flag(&peerflags, DIAL_HALT_ON_DTMF)) {
1735                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1736                                         res = ast_waitstream(chan, AST_DIGIT_ANY);
1737                                 if (!res && sleep) {
1738                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1739                                                 ast_moh_start(chan, NULL);
1740                                         res = ast_waitfordigit(chan, sleep);
1741                                 }
1742                         } else {
1743                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1744                                         res = ast_waitstream(chan, "");
1745                                 if (sleep) {
1746                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1747                                                 ast_moh_start(chan, NULL);
1748                                         if (!res) 
1749                                                 res = ast_waitfordigit(chan, sleep);
1750                                 }
1751                         }
1752                 }
1753
1754                 if (res < 0)
1755                         break;
1756                 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1757                         if (onedigit_goto(chan, context, (char) res, 1)) {
1758                                 res = 0;
1759                                 break;
1760                         }
1761                 }
1762                 loops--;
1763         }
1764         
1765         if (ast_test_flag(chan, AST_FLAG_MOH))
1766                 ast_moh_stop(chan);
1767
1768         LOCAL_USER_REMOVE(u);
1769         return loops ? res : 0;
1770
1771 }
1772
1773 int unload_module(void)
1774 {
1775         STANDARD_HANGUP_LOCALUSERS;
1776         ast_unregister_application(app);
1777         return ast_unregister_application(rapp);
1778 }
1779
1780 int load_module(void)
1781 {
1782         int res;
1783         if (!(res = ast_register_application(app, dial_exec, synopsis, descrip)))
1784                 res = ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1785         return res;
1786 }
1787
1788 char *description(void)
1789 {
1790         return tdesc;
1791 }
1792
1793 int usecount(void)
1794 {
1795         int res;
1796         STANDARD_USECOUNT(res);
1797         return res;
1798 }
1799
1800 char *key()
1801 {
1802         return ASTERISK_GPL_KEY;
1803 }