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