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