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