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