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