4d9d05ccf9a73af393fa263fbcde8d22205a3716
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*
20  *
21  * Trivial application to dial a channel and send an URL on answer
22  * 
23  */
24
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <sys/time.h>
32 #include <sys/signal.h>
33 #include <netinet/in.h>
34
35 #include "asterisk.h"
36
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38
39 #include "asterisk/lock.h"
40 #include "asterisk/file.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/options.h"
45 #include "asterisk/module.h"
46 #include "asterisk/translate.h"
47 #include "asterisk/say.h"
48 #include "asterisk/config.h"
49 #include "asterisk/features.h"
50 #include "asterisk/musiconhold.h"
51 #include "asterisk/callerid.h"
52 #include "asterisk/utils.h"
53 #include "asterisk/app.h"
54 #include "asterisk/causes.h"
55 #include "asterisk/manager.h"
56 #include "asterisk/privacy.h"
57
58 static char *tdesc = "Dialing Application";
59
60 static char *app = "Dial";
61
62 static char *synopsis = "Place a call and connect to the current channel";
63
64 static char *descrip =
65 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
66 "Requests one or more channels and places specified outgoing calls on them.\n"
67 "As soon as a channel answers, the Dial app will answer the originating\n"
68 "channel (if it needs to be answered) and will bridge a call with the channel\n"
69 "which first answered. All other calls placed by the Dial app will be hung up.\n"
70 "If a timeout is not specified, the Dial application will wait indefinitely\n"
71 "until either one of the called channels answers, the user hangs up, or all\n"
72 "channels return busy or error. In general, the dialer will return 0 if it\n"
73 "was unable to place the call, or the timeout expired. However, if all\n"
74 "channels were busy, and there exists an extension with priority n+101 (where\n"
75 "n is the priority of the dialer instance), then it will be the next\n"
76 "executed extension (this allows you to setup different behavior on busy from\n"
77 "no-answer).\n"
78 "  For the Privacy and Screening Modes, the DIALSTATUS variable will be set to DONTCALL, \n"
79 "if the called party chooses to send the calling party to the 'Go Away' script, and \n"
80 "the DIALSTATUS variable will be set to TORTURE, if the called party wants to send the caller to \n"
81 "the TORTURE scripts\n"
82 "  This application returns -1 if the originating channel hangs up, or if the\n"
83 "call is bridged and either of the parties in the bridge terminate the call.\n"
84 "The option string may contain zero or more of the following characters:\n"
85 "       'A(x)' -- play an announcement to the called party, using x as file\n"
86 "       'C' -- reset call detail record for this call.\n"
87 "       'd' -- allow the calling user to dial a 1 digit extension while waiting for a call to\n"
88 "               be answered exiting to that extension if it exists in the context defined by\n"
89 "               ${EXITCONTEXT} or the current context.\n"
90 "       'D([called][:calling])'  -- Send DTMF strings *after* called party has answered, but before the\n"
91 "               call gets bridged. The 'called' DTMF string is sent to the called party, and the\n"
92 "               'calling' DTMF string is sent to the calling party. Both parameters can be used alone.\n"       
93 "       'f' -- Forces callerid to be set as the extension of the line \n"
94 "       'g' -- goes on in context if the destination channel hangs up\n"
95 "       'G(context^exten^pri)' -- If the call is answered transfer both parties to the specified exten.\n"
96 "       'h' -- allow callee to hang up by hitting *.\n"
97 "       'H' -- allow caller to hang up by hitting *.\n"
98 "       'j' -- Jump to n+101 if all of the channels were busy.\n"
99 "       'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
100 "               repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
101 "             The following special variables are optional:\n"
102 "             * LIMIT_PLAYAUDIO_CALLER    yes|no (default yes)\n"
103 "                                         Play sounds to the caller.\n"
104 "             * LIMIT_PLAYAUDIO_CALLEE    yes|no\n"
105 "                                         Play sounds to the callee.\n"
106 "             * LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
107 "             * LIMIT_CONNECT_FILE        File to play when call begins.\n"
108 "             * LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
109 "                        'timeleft' is a special sound macro to auto-say the time \n"
110 "                        left and is the default.\n"
111 "       'm[(class)]' -- provide hold music to the calling party until answered (optionally\n"
112 "                      with the specified class.\n"
113 "       'M(x[^arg])' -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n"
114 "                      Also, the macro can set the MACRO_RESULT variable to do the following:\n"
115 "                     -- ABORT - Hangup both legs of the call.\n"
116 "                     -- CONGESTION - Behave as if line congestion was encountered.\n"
117 "                     -- BUSY - Behave as if a busy signal was encountered. (n+101)\n"
118 "                     -- CONTINUE - Hangup the called party and continue on in the dialplan.\n"
119 "                     -- GOTO:<context>^<exten>^<priority> - Transfer the call.\n"
120 "       'n' -- modifier for screen/privacy mode. No intros are to be saved in the priv-callerintros dir.\n"
121 "       'N' -- modifier for screen/privacy mode. if callerID is present, do not screen the call.\n"
122 "       'o' -- Original (inbound) Caller*ID should be placed on the outbound leg of the call\n" 
123 "             instead of using the destination extension (old style asterisk behavior)\n"
124 "       'p' -- screening mode.  Basically Privacy mode without memory.\n"
125 "       'P[(x)]' -- privacy mode, using 'x' as database if provided, or the extension is used if not provided.\n"
126 "       'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
127 "       'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"       
128 "       't' -- allow the called user to transfer the calling user by hitting #.\n"
129 "       'T' -- allow the calling user to transfer the call by hitting #.\n"
130 "             making/redirecting the outgoing call. For example, some PSTNs\n"
131 "             don't allow callerids from other extensions then the ones\n"
132 "             that are assigned to you.\n"
133 "       'w' -- allow the called user to write the conversation to disk via Monitor\n"
134 "       'W' -- allow the calling user to write the conversation to disk via Monitor\n\n"
135 "  In addition to transferring the call, a call may be parked and then picked\n"
136 "up by another user.\n"
137 "  The optional URL will be sent to the called party if the channel supports it.\n"
138 "  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
139 "  application will be put into that group (as in SetGroup).\n"
140 "  This application sets the following channel variables upon completion:\n"
141 "      DIALEDTIME    Time from dial to answer\n" 
142 "      ANSWEREDTIME  Time for actual call\n"
143 "      DIALSTATUS    The status of the call as a text string, one of\n"
144 "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL | DONTCALL | TORTURE\n"
145 "";
146
147 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
148 static char *rapp = "RetryDial";
149 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
150 static char *rdescrip =
151 "  RetryDial(announce|sleep|loops|Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
152 "Attempt to place a call.  If no channel can be reached, play the file defined by 'announce'\n"
153 "waiting 'sleep' seconds to retry the call.  If the specified number of attempts matches \n"
154 "'loops' the call will continue in the dialplan.  If 'loops' is set to 0, the call will retry endlessly.\n\n"
155 "While waiting, a 1 digit extension may be dialed.  If that extension exists in either\n"
156 "the context defined in ${EXITCONTEXT} or the current one, The call will transfer\n"
157 "to that extension immmediately.\n\n"
158 "All arguments after 'loops' are passed directly to the Dial() application.\n"
159 "";
160
161
162 /* We define a customer "local user" structure because we
163    use it not only for keeping track of what is in use but
164    also for keeping track of who we're dialing. */
165
166 #define DIAL_STILLGOING                 (1 << 0)
167 #define DIAL_ALLOWREDIRECT_IN           (1 << 1)
168 #define DIAL_ALLOWREDIRECT_OUT          (1 << 2)
169 #define DIAL_ALLOWDISCONNECT_IN         (1 << 3)
170 #define DIAL_ALLOWDISCONNECT_OUT        (1 << 4)
171 #define DIAL_RINGBACKONLY               (1 << 5)
172 #define DIAL_MUSICONHOLD                (1 << 6)
173 #define DIAL_FORCECALLERID              (1 << 7)
174 #define DIAL_MONITOR_IN                 (1 << 8)
175 #define DIAL_MONITOR_OUT                (1 << 9)
176 #define DIAL_GO_ON                      (1 << 10)
177 #define DIAL_HALT_ON_DTMF               (1 << 11)
178 #define DIAL_PRESERVE_CALLERID          (1 << 12)
179 #define DIAL_NOFORWARDHTML              (1 << 13)
180
181 struct localuser {
182         struct ast_channel *chan;
183         unsigned int flags;
184         int forwards;
185         struct localuser *next;
186 };
187
188 LOCAL_USER_DECL;
189
190 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
191 {
192         /* Hang up a tree of stuff */
193         struct localuser *oo;
194         while (outgoing) {
195                 /* Hangup any existing lines we have open */
196                 if (outgoing->chan && (outgoing->chan != exception))
197                         ast_hangup(outgoing->chan);
198                 oo = outgoing;
199                 outgoing=outgoing->next;
200                 free(oo);
201         }
202 }
203
204 #define AST_MAX_FORWARDS   8
205
206 #define AST_MAX_WATCHERS 256
207
208 #define HANDLE_CAUSE(cause, chan) do { \
209         switch(cause) { \
210         case AST_CAUSE_BUSY: \
211                 if (chan->cdr) \
212                         ast_cdr_busy(chan->cdr); \
213                 numbusy++; \
214                 break; \
215         case AST_CAUSE_CONGESTION: \
216                 if (chan->cdr) \
217                         ast_cdr_busy(chan->cdr); \
218                 numcongestion++; \
219                 break; \
220         case AST_CAUSE_UNREGISTERED: \
221                 if (chan->cdr) \
222                         ast_cdr_busy(chan->cdr); \
223                 numnochan++; \
224                 break; \
225         default: \
226                 numnochan++; \
227                 break; \
228         } \
229 } while (0)
230
231
232 static int onedigit_goto(struct ast_channel *chan, char *context, char exten, int pri) 
233 {
234         char rexten[2] = { exten, '\0' };
235
236         if (context) {
237                 if (!ast_goto_if_exists(chan, context, rexten, pri))
238                         return 1;
239         } else {
240                 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
241                         return 1;
242                 else if (!ast_strlen_zero(chan->macrocontext)) {
243                         if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
244                                 return 1;
245                 }
246         }
247         return 0;
248 }
249
250
251 static char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
252 {
253         char *context;
254         char *exten;
255         if (!ast_strlen_zero(chan->macrocontext))
256                 context = chan->macrocontext;
257         else
258                 context = chan->context;
259
260         if (!ast_strlen_zero(chan->macroexten))
261                 exten = chan->macroexten;
262         else
263                 exten = chan->exten;
264
265         if (ast_get_hint(NULL, 0, name, namelen, chan, context, exten))
266                 return name;
267         else
268                 return "";
269 }
270
271 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
272 {
273         manager_event(EVENT_FLAG_CALL, "Dial", 
274                            "Source: %s\r\n"
275                            "Destination: %s\r\n"
276                            "CallerID: %s\r\n"
277                            "CallerIDName: %s\r\n"
278                            "SrcUniqueID: %s\r\n"
279                            "DestUniqueID: %s\r\n",
280                            src->name, dst->name, src->cid.cid_num ? src->cid.cid_num : "<unknown>",
281                            src->cid.cid_name ? src->cid.cid_name : "<unknown>", src->uniqueid,
282                            dst->uniqueid);
283 }
284
285 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 priority_jump, int *result)
286 {
287         struct localuser *o;
288         int found;
289         int numlines;
290         int numbusy = busystart;
291         int numcongestion = congestionstart;
292         int numnochan = nochanstart;
293         int prestart = busystart + congestionstart + nochanstart;
294         int cause;
295         int orig = *to;
296         struct ast_frame *f;
297         struct ast_channel *peer = NULL;
298         struct ast_channel *watchers[AST_MAX_WATCHERS];
299         int pos;
300         int single;
301         struct ast_channel *winner;
302         char *context = NULL;
303         char cidname[AST_MAX_EXTENSION];
304
305         single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, DIAL_MUSICONHOLD | DIAL_RINGBACKONLY));
306         
307         if (single) {
308                 /* Turn off hold music, etc */
309                 ast_deactivate_generator(in);
310                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
311                 ast_channel_make_compatible(outgoing->chan, in);
312         }
313         
314         
315         while (*to && !peer) {
316                 o = outgoing;
317                 found = -1;
318                 pos = 1;
319                 numlines = prestart;
320                 watchers[0] = in;
321                 while (o) {
322                         /* Keep track of important channels */
323                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) {
324                                 watchers[pos++] = o->chan;
325                                 found = 1;
326                         }
327                         o = o->next;
328                         numlines++;
329                 }
330                 if (found < 0) {
331                         if (numlines == (numbusy + numcongestion + numnochan)) {
332                                 if (option_verbose > 2)
333                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
334                                 if (numbusy)
335                                         strcpy(status, "BUSY"); 
336                                 else if (numcongestion)
337                                         strcpy(status, "CONGESTION");
338                                 else if (numnochan)
339                                         strcpy(status, "CHANUNAVAIL");
340                                 if (option_priority_jumping || priority_jump)
341                                         ast_goto_if_exists(in, in->context, in->exten, in->priority + 101);
342                         } else {
343                                 if (option_verbose > 2)
344                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
345                         }
346                         *to = 0;
347                         return NULL;
348                 }
349                 winner = ast_waitfor_n(watchers, pos, to);
350                 o = outgoing;
351                 while (o) {
352                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan && (o->chan->_state == AST_STATE_UP)) {
353                                 if (!peer) {
354                                         if (option_verbose > 2)
355                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
356                                         peer = o->chan;
357                                         ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT|DIAL_NOFORWARDHTML);
358                                 }
359                         } else if (o->chan && (o->chan == winner)) {
360                                 if (!ast_strlen_zero(o->chan->call_forward)) {
361                                         char tmpchan[256];
362                                         char *stuff;
363                                         char *tech;
364                                         ast_copy_string(tmpchan, o->chan->call_forward, sizeof(tmpchan));
365                                         if ((stuff = strchr(tmpchan, '/'))) {
366                                                 *stuff = '\0';
367                                                 stuff++;
368                                                 tech = tmpchan;
369                                         } else {
370                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
371                                                 stuff = tmpchan;
372                                                 tech = "Local";
373                                         }
374                                         /* Before processing channel, go ahead and check for forwarding */
375                                         o->forwards++;
376                                         if (o->forwards < AST_MAX_FORWARDS) {
377                                                 if (option_verbose > 2)
378                                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
379                                                 /* Setup parameters */
380                                                 o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
381                                                 if (!o->chan)
382                                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
383                                         } else {
384                                                 if (option_verbose > 2)
385                                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", o->chan->name);
386                                                 cause = AST_CAUSE_CONGESTION;
387                                                 o->chan = NULL;
388                                         }
389                                         if (!o->chan) {
390                                                 ast_clear_flag(o, DIAL_STILLGOING);     
391                                                 HANDLE_CAUSE(cause, in);
392                                         } else {
393                                                 if (o->chan->cid.cid_num)
394                                                         free(o->chan->cid.cid_num);
395                                                 o->chan->cid.cid_num = NULL;
396                                                 if (o->chan->cid.cid_name)
397                                                         free(o->chan->cid.cid_name);
398                                                 o->chan->cid.cid_name = NULL;
399
400                                                 if (ast_test_flag(o, DIAL_FORCECALLERID)) {
401                                                         char *newcid = NULL;
402
403                                                         if (strlen(in->macroexten))
404                                                                 newcid = in->macroexten;
405                                                         else
406                                                                 newcid = in->exten;
407                                                         o->chan->cid.cid_num = strdup(newcid);
408                                                         ast_copy_string(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode));
409                                                         o->chan->cdrflags = winner->cdrflags;
410                                                         if (!o->chan->cid.cid_num)
411                                                                 ast_log(LOG_WARNING, "Out of memory\n");
412                                                 } else {
413                                                         if (in->cid.cid_num) {
414                                                                 o->chan->cid.cid_num = strdup(in->cid.cid_num);
415                                                                 if (!o->chan->cid.cid_num)
416                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
417                                                         }
418                                                         if (in->cid.cid_name) {
419                                                                 o->chan->cid.cid_name = strdup(in->cid.cid_name);
420                                                                 if (!o->chan->cid.cid_name)
421                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
422                                                         }
423                                                         ast_copy_string(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode));
424                                                         o->chan->cdrflags = in->cdrflags;
425                                                 }
426
427                                                 if (in->cid.cid_ani) {
428                                                         if (o->chan->cid.cid_ani)
429                                                                 free(o->chan->cid.cid_ani);
430                                                         o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
431                                                         if (o->chan->cid.cid_ani)
432                                                                 ast_copy_string(o->chan->cid.cid_ani, in->cid.cid_ani, sizeof(o->chan->cid.cid_ani));
433                                                         else
434                                                                 ast_log(LOG_WARNING, "Out of memory\n");
435                                                 }
436                                                 if (o->chan->cid.cid_rdnis) 
437                                                         free(o->chan->cid.cid_rdnis);
438                                                 if (!ast_strlen_zero(in->macroexten))
439                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
440                                                 else
441                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
442                                                 if (ast_call(o->chan, tmpchan, 0)) {
443                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
444                                                         ast_clear_flag(o, DIAL_STILLGOING);     
445                                                         ast_hangup(o->chan);
446                                                         o->chan = NULL;
447                                                         numnochan++;
448                                                 } else {
449                                                         senddialevent(in, o->chan);
450                                                         /* After calling, set callerid to extension */
451                                                         if (!ast_test_flag(peerflags, DIAL_PRESERVE_CALLERID))
452                                                                 ast_set_callerid(o->chan, ast_strlen_zero(in->macroexten) ? in->exten : in->macroexten, get_cid_name(cidname, sizeof(cidname), in), NULL);
453                                                 }
454                                         }
455                                         /* Hangup the original channel now, in case we needed it */
456                                         ast_hangup(winner);
457                                         continue;
458                                 }
459                                 f = ast_read(winner);
460                                 if (f) {
461                                         if (f->frametype == AST_FRAME_CONTROL) {
462                                                 switch(f->subclass) {
463                                                 case AST_CONTROL_ANSWER:
464                                                         /* This is our guy if someone answered. */
465                                                         if (!peer) {
466                                                                 if (option_verbose > 2)
467                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
468                                                                 peer = o->chan;
469                                                                 ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT|DIAL_NOFORWARDHTML);
470                                                         }
471                                                         /* If call has been answered, then the eventual hangup is likely to be normal hangup */
472                                                         in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
473                                                         o->chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
474                                                         break;
475                                                 case AST_CONTROL_BUSY:
476                                                         if (option_verbose > 2)
477                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
478                                                         in->hangupcause = o->chan->hangupcause;
479                                                         ast_hangup(o->chan);
480                                                         o->chan = NULL;
481                                                         ast_clear_flag(o, DIAL_STILLGOING);     
482                                                         HANDLE_CAUSE(AST_CAUSE_BUSY, in);
483                                                         break;
484                                                 case AST_CONTROL_CONGESTION:
485                                                         if (option_verbose > 2)
486                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
487                                                         in->hangupcause = o->chan->hangupcause;
488                                                         ast_hangup(o->chan);
489                                                         o->chan = NULL;
490                                                         ast_clear_flag(o, DIAL_STILLGOING);
491                                                         HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
492                                                         break;
493                                                 case AST_CONTROL_RINGING:
494                                                         if (option_verbose > 2)
495                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
496                                                         if (!(*sentringing) && !ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
497                                                                 ast_indicate(in, AST_CONTROL_RINGING);
498                                                                 (*sentringing)++;
499                                                         }
500                                                         break;
501                                                 case AST_CONTROL_PROGRESS:
502                                                         if (option_verbose > 2)
503                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
504                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
505                                                                 ast_indicate(in, AST_CONTROL_PROGRESS);
506                                                         break;
507                                                 case AST_CONTROL_VIDUPDATE:
508                                                         if (option_verbose > 2)
509                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", o->chan->name,in->name);
510                                                         ast_indicate(in, AST_CONTROL_VIDUPDATE);
511                                                         break;
512                                                 case AST_CONTROL_PROCEEDING:
513                                                         if (option_verbose > 2)
514                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", o->chan->name,in->name);
515                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
516                                                                 ast_indicate(in, AST_CONTROL_PROCEEDING);
517                                                         break;
518                                                 case AST_CONTROL_HOLD:
519                                                         if (option_verbose > 2)
520                                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", o->chan->name);
521                                                         ast_indicate(in, AST_CONTROL_HOLD);
522                                                         break;
523                                                 case AST_CONTROL_UNHOLD:
524                                                         if (option_verbose > 2)
525                                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", o->chan->name);
526                                                         ast_indicate(in, AST_CONTROL_UNHOLD);
527                                                         break;
528                                                 case AST_CONTROL_OFFHOOK:
529                                                 case AST_CONTROL_FLASH:
530                                                         /* Ignore going off hook and flash */
531                                                         break;
532                                                 case -1:
533                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY | DIAL_MUSICONHOLD)) {
534                                                                 if (option_verbose > 2)
535                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
536                                                                 ast_indicate(in, -1);
537                                                                 (*sentringing) = 0;
538                                                         }
539                                                         break;
540                                                 default:
541                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
542                                                 }
543                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
544                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
545                                                 if (ast_write(in, f)) 
546                                                         ast_log(LOG_DEBUG, "Unable to forward frame\n");
547                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
548                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
549                                                 if (ast_write(in, f))
550                                                         ast_log(LOG_DEBUG, "Unable to forward image\n");
551                                         } else if (single && (f->frametype == AST_FRAME_TEXT) && 
552                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
553                                                 if (ast_write(in, f))
554                                                         ast_log(LOG_DEBUG, "Unable to text\n");
555                                         } else if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
556                                                 ast_channel_sendhtml(in, f->subclass, f->data, f->datalen);
557
558                                         ast_frfree(f);
559                                 } else {
560                                         in->hangupcause = o->chan->hangupcause;
561                                         ast_hangup(o->chan);
562                                         o->chan = NULL;
563                                         ast_clear_flag(o, DIAL_STILLGOING);
564                                 }
565                         }
566                         o = o->next;
567                 }
568                 if (winner == in) {
569                         f = ast_read(in);
570 #if 0
571                         if (f && (f->frametype != AST_FRAME_VOICE))
572                                 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
573                         else if (!f || (f->frametype != AST_FRAME_VOICE))
574                                 printf("Hangup received on %s\n", in->name);
575 #endif
576                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
577                                 /* Got hung up */
578                                 *to=-1;
579                                 strcpy(status, "CANCEL");
580                                 if (f)
581                                         ast_frfree(f);
582                                 return NULL;
583                         }
584
585                         if (f && (f->frametype == AST_FRAME_DTMF)) {
586                                 if (ast_test_flag(peerflags, DIAL_HALT_ON_DTMF)) {
587                                         context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
588                                         if (onedigit_goto(in, context, (char) f->subclass, 1)) {
589                                                 if (option_verbose > 3)
590                                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
591                                                 *to=0;
592                                                 *result = f->subclass;
593                                                 strcpy(status, "CANCEL");
594                                                 ast_frfree(f);
595                                                 return NULL;
596                                         }
597                                 }
598
599                                 if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT) && 
600                                                   (f->subclass == '*')) { /* hmm it it not guarenteed to be '*' anymore. */
601                                         if (option_verbose > 3)
602                                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
603                                         *to=0;
604                                         strcpy(status, "CANCEL");
605                                         ast_frfree(f);
606                                         return NULL;
607                                 }
608                         }
609
610                         /* Forward HTML stuff */
611                         if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 
612                                 ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen);
613                         
614
615                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
616                                 if (ast_write(outgoing->chan, f))
617                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
618                         }
619                         if (single && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_VIDUPDATE)) {
620                                 if (option_verbose > 2)
621                                         ast_verbose ( VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", in->name,outgoing->chan->name);
622                                 ast_indicate(outgoing->chan, AST_CONTROL_VIDUPDATE);
623                         }
624                         ast_frfree(f);
625                 }
626                 if (!*to && (option_verbose > 2))
627                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
628         }
629
630         return peer;
631         
632 }
633
634
635 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags)
636 {
637         int res=-1;
638         struct localuser *u;
639         char *info, *peers, *timeout, *tech, *number, *rest, *cur;
640         char privdb[256], *s;
641         char privcid[256];
642         char privintro[1024];
643         char  announcemsg[256] = "", *ann;
644         struct localuser *outgoing=NULL, *tmp;
645         struct ast_channel *peer;
646         int to;
647         int hasmacro = 0;
648         int privacy=0;
649         int screen=0;
650         int no_save_intros = 0;
651         int no_screen_callerid = 0;
652         int announce=0;
653         int resetcdr=0;
654         int numbusy = 0;
655         int numcongestion = 0;
656         int numnochan = 0;
657         int cause;
658         char numsubst[AST_MAX_EXTENSION];
659         char restofit[AST_MAX_EXTENSION];
660         char cidname[AST_MAX_EXTENSION];
661         char *transfer = NULL;
662         char *newnum;
663         char *l;
664         char *url=NULL; /* JDG */
665         int privdb_val=0;
666         unsigned int calldurationlimit=0;
667         char *cdl;
668         time_t now;
669         struct ast_bridge_config config;
670         long timelimit = 0;
671         long play_warning = 0;
672         long warning_freq=0;
673         char *warning_sound=NULL;
674         char *end_sound=NULL;
675         char *start_sound=NULL;
676         char *limitptr;
677         char limitdata[256];
678         char *sdtmfptr;
679         char *dtmfcalled=NULL, *dtmfcalling=NULL;
680         char *stack,*var;
681         char *mac = NULL, *macroname = NULL;
682         char status[256];
683         char toast[80];
684         int play_to_caller=0,play_to_callee=0;
685         int playargs=0, sentringing=0, moh=0;
686         char *mohclass = NULL;
687         char *outbound_group = NULL;
688         char *macro_result = NULL, *macro_transfer_dest = NULL;
689         int digit = 0, result = 0;
690         time_t start_time, answer_time, end_time;
691         struct ast_app *app = NULL;
692         char *dblgoto = NULL;
693         int priority_jump = 0;
694
695         if (!data || ast_strlen_zero(data)) {
696                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
697                 return -1;
698         }
699
700         LOCAL_USER_ADD(u);
701
702         info = ast_strdupa(data);       
703         if (!info) {
704                 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
705                 LOCAL_USER_REMOVE(u);
706                 return -1;
707         }
708         
709         peers = info;
710         if (peers) {
711                 timeout = strchr(info, '|');
712                 if (timeout) {
713                         *timeout = '\0';
714                         timeout++;
715                         transfer = strchr(timeout, '|');
716                         if (transfer) {
717                                 *transfer = '\0';
718                                 transfer++;
719                                 /* JDG */
720                                 url = strchr(transfer, '|');
721                                 if (url) {
722                                         *url = '\0';
723                                         url++;
724                                         if (option_debug)
725                                                 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
726                                 } else 
727                                         if (option_debug) {
728                                                 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
729                                         }
730                                 /* /JDG */
731                         }
732                 }
733         } else
734                 timeout = NULL;
735         if (!peers || ast_strlen_zero(peers)) {
736                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
737                 goto out;
738         }
739         
740
741         if (transfer) {
742
743                 /* Extract call duration limit */
744                 if ((cdl = strstr(transfer, "S("))) {
745                         calldurationlimit=atoi(cdl+2);
746                         if (option_verbose > 2)
747                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",calldurationlimit);                 
748                 } 
749
750                 /* Extract DTMF strings to send upon successfull connect */
751                 if ((sdtmfptr = strstr(transfer, "D("))) {
752                         dtmfcalled = ast_strdupa(sdtmfptr + 2);
753                         dtmfcalling = strchr(dtmfcalled, ')');
754                         if (dtmfcalling)
755                                 *dtmfcalling = '\0';
756                         dtmfcalling = strchr(dtmfcalled, ':');
757                         if (dtmfcalling) {
758                                 *dtmfcalling = '\0';
759                                 dtmfcalling++;
760                         }                               
761                         /* Overwrite with X's what was the sdtmf info */
762                         while (*sdtmfptr && (*sdtmfptr != ')')) 
763                                 *(sdtmfptr++) = 'X';
764                         if (*sdtmfptr)
765                                 *sdtmfptr = 'X';
766                         else 
767                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
768                 }
769   
770                 /* XXX LIMIT SUPPORT */
771                 if ((limitptr = strstr(transfer, "L("))) {
772                         ast_copy_string(limitdata, limitptr + 2, sizeof(limitdata));
773                         /* Overwrite with X's what was the limit info */
774                         while (*limitptr && (*limitptr != ')')) 
775                                 *(limitptr++) = 'X';
776                         if (*limitptr)
777                                 *limitptr = 'X';
778                         /* Now find the end */
779                         limitptr = strchr(limitdata, ')');
780                         if (limitptr)
781                                 *limitptr = '\0';
782                         else
783                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
784
785                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
786                         play_to_caller = var ? ast_true(var) : 1;
787                   
788                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
789                         play_to_callee = var ? ast_true(var) : 0;
790                   
791                         if (!play_to_caller && !play_to_callee)
792                                 play_to_caller=1;
793                   
794                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
795                         warning_sound = var ? var : "timeleft";
796
797                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
798                         end_sound = var ? var : NULL;
799
800                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
801                         start_sound = var ? var : NULL;
802
803                         var=stack=limitdata;
804
805                         var = strsep(&stack, ":");
806                         if (var) {
807                                 timelimit = atol(var);
808                                 playargs++;
809                                 var = strsep(&stack, ":");
810                                 if (var) {
811                                         play_warning = atol(var);
812                                         playargs++;
813                                         var = strsep(&stack, ":");
814                                         if (var) {
815                                                 warning_freq = atol(var);
816                                                 playargs++;
817                                         }
818                                 }
819                         }
820                   
821                         if (!timelimit) {
822                                 timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0;
823                                 warning_sound = NULL;
824                         }
825                         /* undo effect of S(x) in case they are both used */
826                         calldurationlimit = 0; 
827                         /* more efficient do it like S(x) does since no advanced opts*/
828                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
829                                 calldurationlimit = timelimit/1000;
830                                 timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0;
831                         } else if (option_verbose > 2) {
832                                 ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
833                                 ast_verbose(VERBOSE_PREFIX_3 "- timelimit     = %ld\n", timelimit);
834                                 ast_verbose(VERBOSE_PREFIX_3 "- play_warning  = %ld\n", play_warning);
835                                 ast_verbose(VERBOSE_PREFIX_3 "- play_to_caller= %s\n", play_to_caller ? "yes" : "no");
836                                 ast_verbose(VERBOSE_PREFIX_3 "- play_to_callee= %s\n", play_to_callee ? "yes" : "no");
837                                 ast_verbose(VERBOSE_PREFIX_3 "- warning_freq  = %ld\n", warning_freq);
838                                 ast_verbose(VERBOSE_PREFIX_3 "- start_sound   = %s\n", start_sound ? start_sound : "UNDEF");
839                                 ast_verbose(VERBOSE_PREFIX_3 "- warning_sound = %s\n", warning_sound ? warning_sound : "UNDEF");
840                                 ast_verbose(VERBOSE_PREFIX_3 "- end_sound     = %s\n", end_sound ? end_sound : "UNDEF");
841                         }
842                 }
843                 
844                 /* XXX ANNOUNCE SUPPORT */
845                 if ((ann = strstr(transfer, "A("))) {
846                         announce = 1;
847                         ast_copy_string(announcemsg, ann + 2, sizeof(announcemsg));
848                         /* Overwrite with X's what was the announce info */
849                         while (*ann && (*ann != ')')) 
850                                 *(ann++) = 'X';
851                         if (*ann)
852                                 *ann = 'X';
853                         /* Now find the end of the announce */
854                         ann = strchr(announcemsg, ')');
855                         if (ann)
856                                 *ann = '\0';
857                         else {
858                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
859                                 announce = 0;
860                         }
861                 }
862
863                 /* Get the goto from the dial option string */
864                 if ((mac = strstr(transfer, "G("))) {
865
866
867                         dblgoto = ast_strdupa(mac + 2);
868                         while (*mac && (*mac != ')'))
869                                 *(mac++) = 'X';
870                         if (*mac) {
871                                 *mac = 'X';
872                                 mac = strchr(dblgoto, ')');
873                                 if (mac)
874                                         *mac = '\0';
875                                 else {
876                                         ast_log(LOG_WARNING, "Goto flag set without trailing ')'\n");
877                                         dblgoto = NULL;
878                                 }
879                         } else {
880                                 ast_log(LOG_WARNING, "Could not find exten to which we should jump.\n");
881                                 dblgoto = NULL;
882                         }
883                 }
884
885                 /* Get the macroname from the dial option string */
886                 if ((mac = strstr(transfer, "M("))) {
887                         hasmacro = 1;
888                         macroname = ast_strdupa(mac + 2);
889                         while (*mac && (*mac != ')'))
890                                 *(mac++) = 'X';
891                         if (*mac) {
892                                 *mac = 'X';
893                                 mac = strchr(macroname, ')');
894                                 if (mac)
895                                         *mac = '\0';
896                                 else {
897                                         ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
898                                         hasmacro = 0;
899                                 }
900                         } else {
901                                 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
902                                 hasmacro = 0;
903                         }
904                 }
905                 /* Get music on hold class */
906                 if ((mac = strstr(transfer, "m("))) {
907                         mohclass = ast_strdupa(mac + 2);
908                         mac++; /* Leave the "m" in the string */
909                         while (*mac && (*mac != ')'))
910                                 *(mac++) = 'X';
911                         if (*mac) {
912                                 *mac = 'X';
913                                 mac = strchr(mohclass, ')');
914                                 if (mac)
915                                         *mac = '\0';
916                                 else {
917                                         ast_log(LOG_WARNING, "Music on hold class specified without trailing ')'\n");
918                                         mohclass = NULL;
919                                 }
920                         } else {
921                                 ast_log(LOG_WARNING, "Could not find music on hold class to use, assuming default.\n");
922                                 mohclass=NULL;
923                         }
924                 }
925                 /* Extract privacy info from transfer */
926                 if ((s = strstr(transfer, "P("))) {
927                         privacy = 1;
928                         ast_copy_string(privdb, s + 2, sizeof(privdb));
929                         /* Overwrite with X's what was the privacy info */
930                         while (*s && (*s != ')')) 
931                                 *(s++) = 'X';
932                         if (*s)
933                                 *s = 'X';
934                         /* Now find the end of the privdb */
935                         s = strchr(privdb, ')');
936                         if (s)
937                                 *s = '\0';
938                         else {
939                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
940                                 privacy = 0;
941                         }
942                 } else if (strchr(transfer, 'P')) {
943                         /* No specified privdb */
944                         privacy = 1;
945                 } else if (strchr(transfer, 'p')) {
946                         screen = 1;
947                 } else if (strchr(transfer, 'C')) {
948                         resetcdr = 1;
949                 } else if (strchr(transfer, 'j')) {
950                         priority_jump = 1;
951                 }
952                 if (strchr(transfer, 'n')) {
953                         no_save_intros = 1;
954                 } 
955                 if (strchr(transfer, 'N')) {
956                         no_screen_callerid = 1;
957                 }
958         }
959         if (resetcdr && chan->cdr)
960                 ast_cdr_reset(chan->cdr, 0);
961         if (ast_strlen_zero(privdb) && privacy) {
962                 /* If privdb is not specified and we are using privacy, copy from extension */
963                 ast_copy_string(privdb, chan->exten, sizeof(privdb));
964         }
965         if (privacy || screen) {
966                 char callerid[60];
967
968                 l = chan->cid.cid_num;
969                 if (l && !ast_strlen_zero(l)) {
970                         ast_shrink_phone_number(l);
971                         if( privacy ) {
972                                 if (option_verbose > 2)
973                                         ast_verbose( VERBOSE_PREFIX_3  "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
974                                 privdb_val = ast_privacy_check(privdb, l);
975                         }
976                         else {
977                                 if (option_verbose > 2)
978                                         ast_verbose( VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l);
979                                 privdb_val = AST_PRIVACY_UNKNOWN;
980                         }
981                 } else {
982                         char *tnam, *tn2;
983
984                         tnam = ast_strdupa(chan->name);
985                         /* clean the channel name so slashes don't try to end up in disk file name */
986                         for(tn2 = tnam; *tn2; tn2++) {
987                                 if( *tn2=='/')
988                                         *tn2 = '=';  /* any other chars to be afraid of? */
989                         }
990                         if (option_verbose > 2)
991                                 ast_verbose( VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n");
992
993                         snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
994                         l = callerid;
995                         privdb_val = AST_PRIVACY_UNKNOWN;
996                 }
997                 
998                 ast_copy_string(privcid,l,sizeof(privcid));
999
1000                 if( strncmp(privcid,"NOCALLERID",10) != 0 && no_screen_callerid ) { /* if callerid is set, and no_screen_callerid is set also */  
1001                         if (option_verbose > 2)
1002                                 ast_verbose( VERBOSE_PREFIX_3  "CallerID set (%s); N option set; Screening should be off\n", privcid);
1003                         privdb_val = AST_PRIVACY_ALLOW;
1004                 }
1005                 else if( no_screen_callerid && strncmp(privcid,"NOCALLERID",10) == 0 ) {
1006                         if (option_verbose > 2)
1007                                 ast_verbose( VERBOSE_PREFIX_3  "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
1008                 }
1009                 
1010                 if( privdb_val == AST_PRIVACY_DENY ) {
1011                         ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1012                         res=0;
1013                         goto out;
1014                 }
1015                 else if( privdb_val == AST_PRIVACY_KILL ) {
1016                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1017                         res = 0;
1018                         goto out; /* Is this right? */
1019                 }
1020                 else if( privdb_val == AST_PRIVACY_TORTURE ) {
1021                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1022                         res = 0;
1023                         goto out; /* is this right??? */
1024
1025                 }
1026                 else if( privdb_val == AST_PRIVACY_UNKNOWN ) {
1027                         /* Get the user's intro, store it in priv-callerintros/$CID, 
1028                            unless it is already there-- this should be done before the 
1029                            call is actually dialed  */
1030
1031                         /* make sure the priv-callerintros dir exists? */
1032
1033                         snprintf(privintro,sizeof(privintro),"priv-callerintros/%s", privcid);
1034                         if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
1035                                 /* the DELUX version of this code would allow this caller the
1036                                    option to hear and retape their previously recorded intro.
1037                                 */
1038                         }
1039                         else {
1040                                 int duration; /* for feedback from play_and_wait */
1041                                 /* the file doesn't exist yet. Let the caller submit his
1042                                    vocal intro for posterity */
1043                                 /* priv-recordintro script:
1044
1045                                    "At the tone, please say your name:"
1046
1047                                 */
1048                                 ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */
1049                                                                                                                         /* don't think we'll need a lock removed, we took care of
1050                                                                                                                            conflicts by naming the privintro file */
1051                         }
1052                 }
1053         }
1054
1055         /* If a channel group has been specified, get it for use when we create peer channels */
1056         outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1057
1058         cur = peers;
1059         do {
1060                 /* Remember where to start next time */
1061                 rest = strchr(cur, '&');
1062                 if (rest) {
1063                         *rest = 0;
1064                         rest++;
1065                 }
1066                 /* Get a technology/[device:]number pair */
1067                 tech = cur;
1068                 number = strchr(tech, '/');
1069                 if (!number) {
1070                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
1071                         goto out;
1072                 }
1073                 *number = '\0';
1074                 number++;
1075                 tmp = malloc(sizeof(struct localuser));
1076                 if (!tmp) {
1077                         ast_log(LOG_WARNING, "Out of memory\n");
1078                         goto out;
1079                 }
1080                 memset(tmp, 0, sizeof(struct localuser));
1081                 if (transfer) {
1082                         ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_IN);
1083                         ast_set2_flag(tmp, strchr(transfer, 'T'), DIAL_ALLOWREDIRECT_OUT);
1084                         ast_set2_flag(tmp, strchr(transfer, 'r'), DIAL_RINGBACKONLY);   
1085                         ast_set2_flag(tmp, strchr(transfer, 'm'), DIAL_MUSICONHOLD);    
1086                         ast_set2_flag(tmp, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);    
1087                         ast_set2_flag(peerflags, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);      
1088                         ast_set2_flag(tmp, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
1089                         ast_set2_flag(peerflags, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
1090                         ast_set2_flag(tmp, strchr(transfer, 'f'), DIAL_FORCECALLERID);  
1091                         ast_set2_flag(tmp, url, DIAL_NOFORWARDHTML);    
1092                         ast_set2_flag(peerflags, strchr(transfer, 'w'), DIAL_MONITOR_IN);       
1093                         ast_set2_flag(peerflags, strchr(transfer, 'W'), DIAL_MONITOR_OUT);      
1094                         ast_set2_flag(peerflags, strchr(transfer, 'd'), DIAL_HALT_ON_DTMF);     
1095                         ast_set2_flag(peerflags, strchr(transfer, 'g'), DIAL_GO_ON);    
1096                         ast_set2_flag(peerflags, strchr(transfer, 'o'), DIAL_PRESERVE_CALLERID);        
1097                 }
1098                 ast_copy_string(numsubst, number, sizeof(numsubst));
1099                 /* If we're dialing by extension, look at the extension to know what to dial */
1100                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
1101                         /* strlen("BYEXTENSION") == 11 */
1102                         ast_copy_string(restofit, newnum + 11, sizeof(restofit));
1103                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
1104                         if (option_debug)
1105                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
1106                 }
1107                 /* Request the peer */
1108                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1109                 if (!tmp->chan) {
1110                         /* If we can't, just go on to the next call */
1111                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1112                         HANDLE_CAUSE(cause, chan);
1113                         cur = rest;
1114                         if (!cur)
1115                                 chan->hangupcause = cause;
1116                         continue;
1117                 }
1118                 pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
1119                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
1120                         char tmpchan[256];
1121                         char *stuff;
1122                         char *tech;
1123                         ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan));
1124                         if ((stuff = strchr(tmpchan, '/'))) {
1125                                 *stuff = '\0';
1126                                 stuff++;
1127                                 tech = tmpchan;
1128                         } else {
1129                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
1130                                 stuff = tmpchan;
1131                                 tech = "Local";
1132                         }
1133                         tmp->forwards++;
1134                         if (tmp->forwards < AST_MAX_FORWARDS) {
1135                                 if (option_verbose > 2)
1136                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1137                                 ast_hangup(tmp->chan);
1138                                 /* Setup parameters */
1139                                 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1140                                 if (!tmp->chan)
1141                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1142                         } else {
1143                                 if (option_verbose > 2)
1144                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
1145                                 ast_hangup(tmp->chan);
1146                                 tmp->chan = NULL;
1147                                 cause = AST_CAUSE_CONGESTION;
1148                         }
1149                         if (!tmp->chan) {
1150                                 HANDLE_CAUSE(cause, chan);
1151                                 cur = rest;
1152                                 continue;
1153                         }
1154                 }
1155
1156                 /* Inherit specially named variables from parent channel */
1157                 ast_channel_inherit_variables(chan, tmp->chan);
1158
1159                 tmp->chan->appl = "AppDial";
1160                 tmp->chan->data = "(Outgoing Line)";
1161                 tmp->chan->whentohangup = 0;
1162                 if (tmp->chan->cid.cid_num)
1163                         free(tmp->chan->cid.cid_num);
1164                 tmp->chan->cid.cid_num = NULL;
1165                 if (tmp->chan->cid.cid_name)
1166                         free(tmp->chan->cid.cid_name);
1167                 tmp->chan->cid.cid_name = NULL;
1168                 if (tmp->chan->cid.cid_ani)
1169                         free(tmp->chan->cid.cid_ani);
1170                 tmp->chan->cid.cid_ani = NULL;
1171
1172                 if (chan->cid.cid_num) 
1173                         tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
1174                 if (chan->cid.cid_name) 
1175                         tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
1176                 if (chan->cid.cid_ani) 
1177                         tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
1178                 
1179                 /* Copy language from incoming to outgoing */
1180                 ast_copy_string(tmp->chan->language, chan->language, sizeof(tmp->chan->language));
1181                 ast_copy_string(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode));
1182                 tmp->chan->cdrflags = chan->cdrflags;
1183                 if (ast_strlen_zero(tmp->chan->musicclass))
1184                         ast_copy_string(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass));
1185                 if (chan->cid.cid_rdnis)
1186                         tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
1187                 /* Pass callingpres setting */
1188                 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
1189                 /* Pass type of number */
1190                 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
1191                 /* Pass type of tns */
1192                 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
1193                 /* Presense of ADSI CPE on outgoing channel follows ours */
1194                 tmp->chan->adsicpe = chan->adsicpe;
1195                 /* Pass the transfer capability */
1196                 tmp->chan->transfercapability = chan->transfercapability;
1197
1198                 /* If we have an outbound group, set this peer channel to it */
1199                 if (outbound_group)
1200                         ast_app_group_set_channel(tmp->chan, outbound_group);
1201
1202                 /* Place the call, but don't wait on the answer */
1203                 res = ast_call(tmp->chan, numsubst, 0);
1204
1205                 /* Save the info in cdr's that we called them */
1206                 if (chan->cdr)
1207                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
1208
1209                 /* check the results of ast_call */
1210                 if (res) {
1211                         /* Again, keep going even if there's an error */
1212                         if (option_debug)
1213                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1214                         else if (option_verbose > 2)
1215                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1216                         ast_hangup(tmp->chan);
1217                         tmp->chan = NULL;
1218                         cur = rest;
1219                         continue;
1220                 } else {
1221                         senddialevent(chan, tmp->chan);
1222                         if (option_verbose > 2)
1223                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1224                         if (!ast_test_flag(peerflags, DIAL_PRESERVE_CALLERID))
1225                                 ast_set_callerid(tmp->chan, ast_strlen_zero(chan->macroexten) ? chan->exten : chan->macroexten, get_cid_name(cidname, sizeof(cidname), chan), NULL);
1226                 }
1227                 /* Put them in the list of outgoing thingies...  We're ready now. 
1228                    XXX If we're forcibly removed, these outgoing calls won't get
1229                    hung up XXX */
1230                 ast_set_flag(tmp, DIAL_STILLGOING);     
1231                 tmp->next = outgoing;
1232                 outgoing = tmp;
1233                 /* If this line is up, don't try anybody else */
1234                 if (outgoing->chan->_state == AST_STATE_UP)
1235                         break;
1236                 cur = rest;
1237         } while (cur);
1238         
1239         if (timeout && !ast_strlen_zero(timeout)) {
1240                 to = atoi(timeout);
1241                 if (to > 0)
1242                         to *= 1000;
1243                 else
1244                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
1245         } else
1246                 to = -1;
1247
1248         if (outgoing) {
1249                 /* Our status will at least be NOANSWER */
1250                 strcpy(status, "NOANSWER");
1251                 if (ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
1252                         moh=1;
1253                         ast_moh_start(chan, mohclass);
1254                 } else if (ast_test_flag(outgoing, DIAL_RINGBACKONLY)) {
1255                         ast_indicate(chan, AST_CONTROL_RINGING);
1256                         sentringing++;
1257                 }
1258         } else
1259                 strcpy(status, "CHANUNAVAIL");
1260
1261         time(&start_time);
1262         peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, priority_jump, &result);
1263         
1264         if (!peer) {
1265                 if (result) {
1266                         res = result;
1267                 } else if (to) 
1268                         /* Musta gotten hung up */
1269                         res = -1;
1270                 else 
1271                         /* Nobody answered, next please? */
1272                         res = 0;
1273                 
1274                 goto out;
1275         }
1276         if (peer) {
1277                 time(&answer_time);
1278 #ifdef OSP_SUPPORT
1279                 /* Once call is answered, ditch the OSP Handle */
1280                 pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
1281 #endif
1282                 strcpy(status, "ANSWER");
1283                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1284                    we will always return with -1 so that it is hung up properly after the 
1285                    conversation.  */
1286                 hanguptree(outgoing, peer);
1287                 outgoing = NULL;
1288                 /* If appropriate, log that we have a destination channel */
1289                 if (chan->cdr)
1290                         ast_cdr_setdestchan(chan->cdr, peer->name);
1291                 if (peer->name)
1292                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1293
1294                 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1295                 if (!number)
1296                         number = numsubst;
1297                 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1298                 /* JDG: sendurl */
1299                 if ( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1300                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
1301                         ast_channel_sendurl( peer, url );
1302                 } /* /JDG */
1303                 if( privacy || screen ) {
1304                         int res2;
1305                         int loopcount = 0;
1306                         if( privdb_val == AST_PRIVACY_UNKNOWN ) {
1307
1308                                 /* Get the user's intro, store it in priv-callerintros/$CID, 
1309                                    unless it is already there-- this should be done before the 
1310                                    call is actually dialed  */
1311
1312                                 /* all ring indications and moh for the caller has been halted as soon as the 
1313                                    target extension was picked up. We are going to have to kill some
1314                                    time and make the caller believe the peer hasn't picked up yet */
1315
1316                                 if ( strchr(transfer, 'm') ) {
1317                                         ast_indicate(chan, -1);
1318                                         ast_moh_start(chan, mohclass);
1319                                 } else if ( strchr(transfer, 'r') ) {
1320                                         ast_indicate(chan, AST_CONTROL_RINGING);
1321                                         sentringing++;
1322                                 }
1323
1324                                 /* Start autoservice on the other chan ?? */
1325                                 res2 = ast_autoservice_start(chan);
1326                                 /* Now Stream the File */
1327                                 if (!res2) {
1328                                         do {
1329                                                 if (!res2)
1330                                                         res2 = ast_play_and_wait(peer,"priv-callpending");
1331                                                 if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */
1332                                                         res2 = 0;
1333                                                 
1334                                                 /* priv-callpending script: 
1335                                                    "I have a caller waiting, who introduces themselves as:"
1336                                                 */
1337                                                 if (!res2)
1338                                                         res2 = ast_play_and_wait(peer,privintro);
1339                                                 if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */
1340                                                         res2 = 0;
1341                                                 /* now get input from the called party, as to their choice */
1342                                                 if( !res2 ) {
1343                                                         if( privacy )
1344                                                                 res2 = ast_play_and_wait(peer,"priv-callee-options");
1345                                                         if( screen )
1346                                                                 res2 = ast_play_and_wait(peer,"screen-callee-options");
1347                                                 }
1348                                                 /* priv-callee-options script:
1349                                                         "Dial 1 if you wish this caller to reach you directly in the future,
1350                                                                 and immediately connect to their incoming call
1351                                                          Dial 2 if you wish to send this caller to voicemail now and 
1352                                                                 forevermore.
1353                                                          Dial 3 to send this callerr to the torture menus, now and forevermore.
1354                                                          Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
1355                                                          Dial 5 to allow this caller to come straight thru to you in the future,
1356                                                 but right now, just this once, send them to voicemail."
1357                                                 */
1358                                 
1359                                                 /* screen-callee-options script:
1360                                                         "Dial 1 if you wish to immediately connect to the incoming call
1361                                                          Dial 2 if you wish to send this caller to voicemail.
1362                                                          Dial 3 to send this callerr to the torture menus.
1363                                                          Dial 4 to send this caller to a simple "go away" menu.
1364                                                 */
1365                                                 if( !res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4') ) {
1366                                                         /* invalid option */
1367                                                         res2 = ast_play_and_wait(peer,"vm-sorry");
1368                                                 }
1369                                                 loopcount++; /* give the callee a couple chances to make a choice */
1370                                         } while( (!res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4')) && loopcount < 2 );
1371                                 }
1372
1373                                 switch(res2) {
1374                                 case '1':
1375                                         if( privacy ) {
1376                                                 if (option_verbose > 2)
1377                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid);
1378                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW);
1379                                         }
1380                                         break;
1381                                 case '2':
1382                                         if( privacy ) {
1383                                                 if (option_verbose > 2)
1384                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n", privdb, privcid);
1385                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_DENY);
1386                                         }
1387                                         if ( strchr(transfer, 'm') ) {
1388                                                 ast_moh_stop(chan);
1389                                         } else if ( strchr(transfer, 'r') ) {
1390                                                 ast_indicate(chan, -1);
1391                                                 sentringing=0;
1392                                         }
1393                                         res2 = ast_autoservice_stop(chan);
1394                                         ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1395                                         res=0;
1396                                         goto out;
1397                                         break;
1398                                 case '3':
1399                                         if( privacy ) {
1400                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_TORTURE);
1401                                                 if (option_verbose > 2)
1402                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n", privdb, privcid);
1403                                         }
1404                                         ast_copy_string(status, "TORTURE", sizeof(status));
1405                                         
1406                                         res = 0;
1407                                         if ( strchr(transfer, 'm') ) {
1408                                                 ast_moh_stop(chan);
1409                                         } else if ( strchr(transfer, 'r') ) {
1410                                                 ast_indicate(chan, -1);
1411                                                 sentringing=0;
1412                                         }
1413                                         res2 = ast_autoservice_stop(chan);
1414                                         ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1415                                         goto out; /* Is this right? */
1416                                         break;
1417                                 case '4':
1418                                         if( privacy ) {
1419                                                 if (option_verbose > 2)
1420                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n", privdb, privcid);
1421                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_KILL);
1422                                         }
1423
1424                                         ast_copy_string(status, "DONTCALL", sizeof(status));
1425                                         res = 0;
1426                                         if ( strchr(transfer, 'm') ) {
1427                                                 ast_moh_stop(chan);
1428                                         } else if ( strchr(transfer, 'r') ) {
1429                                                 ast_indicate(chan, -1);
1430                                                 sentringing=0;
1431                                         }
1432                                         res2 = ast_autoservice_stop(chan);
1433                                         ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1434                                         goto out; /* Is this right? */
1435                                         break;
1436                                 case '5':
1437                                         if( privacy ) {
1438                                                 if (option_verbose > 2)
1439                                                         ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid);
1440                                                 ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW);
1441                                         
1442                                                 if ( strchr(transfer, 'm') ) {
1443                                                         ast_moh_stop(chan);
1444                                                 } else if ( strchr(transfer, 'r') ) {
1445                                                         ast_indicate(chan, -1);
1446                                                         sentringing=0;
1447                                                 }
1448                                                 res2 = ast_autoservice_stop(chan);
1449                                                 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1450                                                 res=0;
1451                                                 goto out;
1452                                                 break;
1453                                         } /* if not privacy, then 5 is the same as "default" case */
1454                                 default:
1455                                         /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */
1456                                         /* well, there seems basically two choices. Just patch the caller thru immediately,
1457                                                   or,... put 'em thru to voicemail. */
1458                                         /* since the callee may have hung up, let's do the voicemail thing, no database decision */
1459                                         if (option_verbose > 2)
1460                                                 ast_log(LOG_NOTICE,"privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
1461                                         if ( strchr(transfer, 'm') ) {
1462                                                 ast_moh_stop(chan);
1463                                         } else if ( strchr(transfer, 'r') ) {
1464                                                 ast_indicate(chan, -1);
1465                                                 sentringing=0;
1466                                         }
1467                                         res2 = ast_autoservice_stop(chan);
1468                                         ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1469                                         res=0;
1470                                         goto out;
1471                                         break;
1472                                 }
1473                                 if ( strchr(transfer, 'm') ) {
1474                                         ast_moh_stop(chan);
1475                                 } else if ( strchr(transfer, 'r') ) {
1476                                         ast_indicate(chan, -1);
1477                                         sentringing=0;
1478                                 }
1479                                 res2 = ast_autoservice_stop(chan);
1480                                 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll 
1481                                    just clog things up, and it's not useful information, not being tied to a CID */
1482                                 if( strncmp(privcid,"NOCALLERID",10) == 0 || no_save_intros ) {
1483                                         ast_filedelete(privintro, NULL);
1484                                         if( ast_fileexists(privintro,NULL,NULL ) > 0 )
1485                                                 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
1486                                         else if (option_verbose > 2)
1487                                                 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1488                                 }
1489                         }
1490                 }
1491                 if (announce && announcemsg) {
1492                         /* Start autoservice on the other chan */
1493                         res = ast_autoservice_start(chan);
1494                         /* Now Stream the File */
1495                         if (!res)
1496                                 res = ast_streamfile(peer, announcemsg, peer->language);
1497                         if (!res) {
1498                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
1499                         }
1500                         /* Ok, done. stop autoservice */
1501                         res = ast_autoservice_stop(chan);
1502                         if (digit > 0 && !res)
1503                                 res = ast_senddigit(chan, digit); 
1504                         else
1505                                 res = digit;
1506
1507                 } else
1508                         res = 0;
1509
1510                 if (chan && peer && dblgoto) {
1511                         for (mac = dblgoto; *mac; mac++) {
1512                                 if(*mac == '^') {
1513                                         *mac = '|';
1514                                 }
1515                         }
1516                         ast_parseable_goto(chan, dblgoto);
1517                         ast_parseable_goto(peer, dblgoto);
1518                         peer->priority++;
1519                         ast_pbx_start(peer);
1520                         hanguptree(outgoing, NULL);
1521                         LOCAL_USER_REMOVE(u);
1522                         return 0;
1523                 }
1524
1525                 if (hasmacro && macroname) {
1526                         res = ast_autoservice_start(chan);
1527                         if (res) {
1528                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1529                                 res = -1;
1530                         }
1531
1532                         app = pbx_findapp("Macro");
1533
1534                         if (app && !res) {
1535                                 for (res = 0; res<strlen(macroname); res++)
1536                                         if (macroname[res] == '^')
1537                                                 macroname[res] = '|';
1538                                 res = pbx_exec(peer, app, macroname, 1);
1539                                 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1540                                 res = 0;
1541                         } else {
1542                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1543                                 res = -1;
1544                         }
1545
1546                         if (ast_autoservice_stop(chan) < 0) {
1547                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1548                                 res = -1;
1549                         }
1550
1551                         if (!res) {
1552                                 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1553                                         if (!strcasecmp(macro_result, "BUSY")) {
1554                                                 ast_copy_string(status, macro_result, sizeof(status));
1555                                                 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1556                                                         ast_set_flag(peerflags, DIAL_GO_ON);
1557                                                 }
1558                                                 res = -1;
1559                                         }
1560                                         else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1561                                                 ast_copy_string(status, macro_result, sizeof(status));
1562                                                 ast_set_flag(peerflags, DIAL_GO_ON);    
1563                                                 res = -1;
1564                                         }
1565                                         else if (!strcasecmp(macro_result, "CONTINUE")) {
1566                                                 /* hangup peer and keep chan alive assuming the macro has changed 
1567                                                    the context / exten / priority or perhaps 
1568                                                    the next priority in the current exten is desired.
1569                                                 */
1570                                                 ast_set_flag(peerflags, DIAL_GO_ON);    
1571                                                 res = -1;
1572                                         } else if (!strcasecmp(macro_result, "ABORT")) {
1573                                                 /* Hangup both ends unless the caller has the g flag */
1574                                                 res = -1;
1575                                         } else if (!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1576                                                 res = -1;
1577                                                 /* perform a transfer to a new extension */
1578                                                 if (strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
1579                                                         /* no brainer mode... substitute ^ with | and feed it to builtin goto */
1580                                                         for (res=0;res<strlen(macro_transfer_dest);res++)
1581                                                                 if (macro_transfer_dest[res] == '^')
1582                                                                         macro_transfer_dest[res] = '|';
1583
1584                                                         if (!ast_parseable_goto(chan, macro_transfer_dest))
1585                                                                 ast_set_flag(peerflags, DIAL_GO_ON);
1586
1587                                                 }
1588                                         }
1589                                 }
1590                         }
1591                 }
1592
1593                 if (!res) {
1594                         if (calldurationlimit > 0) {
1595                                 time(&now);
1596                                 chan->whentohangup = now + calldurationlimit;
1597                         }
1598                         if (dtmfcalled && !ast_strlen_zero(dtmfcalled)) { 
1599                                 if (option_verbose > 2)
1600                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n",dtmfcalled);
1601                                 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1602                         }
1603                         if (dtmfcalling && !ast_strlen_zero(dtmfcalling)) {
1604                                 if (option_verbose > 2)
1605                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n",dtmfcalling);
1606                                 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1607                         }
1608                 }
1609                 
1610                 if (!res) {
1611                         memset(&config,0,sizeof(struct ast_bridge_config));
1612                         if (play_to_caller)
1613                                 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1614                         if (play_to_callee)
1615                                 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1616                         if (ast_test_flag(peerflags, DIAL_ALLOWREDIRECT_IN))
1617                                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1618                         if (ast_test_flag(peerflags, DIAL_ALLOWREDIRECT_OUT))
1619                                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1620                         if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_IN))
1621                                 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1622                         if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT))
1623                                 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1624                         if (ast_test_flag(peerflags, DIAL_MONITOR_IN))
1625                                 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1626                         if (ast_test_flag(peerflags, DIAL_MONITOR_OUT)) 
1627                                 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1628
1629                         config.timelimit = timelimit;
1630                         config.play_warning = play_warning;
1631                         config.warning_freq = warning_freq;
1632                         config.warning_sound = warning_sound;
1633                         config.end_sound = end_sound;
1634                         config.start_sound = start_sound;
1635                         if (moh) {
1636                                 moh = 0;
1637                                 ast_moh_stop(chan);
1638                         } else if (sentringing) {
1639                                 sentringing = 0;
1640                                 ast_indicate(chan, -1);
1641                         }
1642                         /* Be sure no generators are left on it */
1643                         ast_deactivate_generator(chan);
1644                         /* Make sure channels are compatible */
1645                         res = ast_channel_make_compatible(chan, peer);
1646                         if (res < 0) {
1647                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1648                                 ast_hangup(peer);
1649                                 LOCAL_USER_REMOVE(u);
1650                                 return -1;
1651                         }
1652                         res = ast_bridge_call(chan,peer,&config);
1653                         time(&end_time);
1654                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1655                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1656                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1657                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1658                         
1659                 } else 
1660                         res = -1;
1661                 
1662                 if (res != AST_PBX_NO_HANGUP_PEER) {
1663                         if (!chan->_softhangup)
1664                                 chan->hangupcause = peer->hangupcause;
1665                         ast_hangup(peer);
1666                 }
1667         }       
1668 out:
1669         if (moh) {
1670                 moh = 0;
1671                 ast_moh_stop(chan);
1672         } else if (sentringing) {
1673                 sentringing = 0;
1674                 ast_indicate(chan, -1);
1675         }
1676         hanguptree(outgoing, NULL);
1677         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1678         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1679         
1680         if ((ast_test_flag(peerflags, DIAL_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
1681                 res=0;
1682         
1683         LOCAL_USER_REMOVE(u);    
1684         
1685         return res;
1686 }
1687
1688 static int dial_exec(struct ast_channel *chan, void *data)
1689 {
1690         struct ast_flags peerflags;
1691         memset(&peerflags, 0, sizeof(peerflags));
1692         return dial_exec_full(chan, data, &peerflags);
1693 }
1694
1695 static int retrydial_exec(struct ast_channel *chan, void *data)
1696 {
1697         char *announce = NULL, *context = NULL, *dialdata = NULL;
1698         int sleep = 0, loops = 0, res = 0;
1699         struct localuser *u;
1700         struct ast_flags peerflags;
1701         
1702         if (!data || ast_strlen_zero(data)) {
1703                 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
1704                 return -1;
1705         }       
1706
1707         LOCAL_USER_ADD(u);
1708
1709         announce = ast_strdupa(data);   
1710         if (!announce) {        
1711                 ast_log(LOG_ERROR, "Out of memory!\n");
1712                 LOCAL_USER_REMOVE(u);
1713                 return -1;
1714         }
1715         
1716         memset(&peerflags, 0, sizeof(peerflags));
1717
1718         if ((dialdata = strchr(announce, '|'))) {
1719                 *dialdata = '\0';
1720                 dialdata++;
1721                 if ((sleep = atoi(dialdata))) {
1722                         sleep *= 1000;
1723                 } else {
1724                         ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1725                         LOCAL_USER_REMOVE(u);
1726                         return -1;
1727                 }
1728                 if ((dialdata = strchr(dialdata, '|'))) {
1729                         *dialdata = '\0';
1730                         dialdata++;
1731                         if (!(loops = atoi(dialdata))) {
1732                                 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1733                                 LOCAL_USER_REMOVE(u);
1734                                 return -1;
1735                         }
1736                 }
1737         }
1738         
1739         if ((dialdata = strchr(dialdata, '|'))) {
1740                 *dialdata = '\0';
1741                 dialdata++;
1742         } else {
1743                 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1744                 LOCAL_USER_REMOVE(u);
1745                 return -1;
1746         }
1747                 
1748         if (sleep < 1000)
1749                 sleep = 10000;
1750         
1751         if (!loops)
1752                 loops = -1;
1753         
1754         context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1755         
1756         while (loops) {
1757                 chan->data = "Retrying";
1758                 if (ast_test_flag(chan, AST_FLAG_MOH))
1759                         ast_moh_stop(chan);
1760
1761                 if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) {
1762                         if (ast_test_flag(&peerflags, DIAL_HALT_ON_DTMF)) {
1763                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1764                                         res = ast_waitstream(chan, AST_DIGIT_ANY);
1765                                 if (!res && sleep) {
1766                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1767                                                 ast_moh_start(chan, NULL);
1768                                         res = ast_waitfordigit(chan, sleep);
1769                                 }
1770                         } else {
1771                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1772                                         res = ast_waitstream(chan, "");
1773                                 if (sleep) {
1774                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1775                                                 ast_moh_start(chan, NULL);
1776                                         if (!res) 
1777                                                 res = ast_waitfordigit(chan, sleep);
1778                                 }
1779                         }
1780                 }
1781
1782                 if (res < 0)
1783                         break;
1784                 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1785                         if (onedigit_goto(chan, context, (char) res, 1)) {
1786                                 res = 0;
1787                                 break;
1788                         }
1789                 }
1790                 loops--;
1791         }
1792         
1793         if (ast_test_flag(chan, AST_FLAG_MOH))
1794                 ast_moh_stop(chan);
1795
1796         LOCAL_USER_REMOVE(u);
1797         return loops ? res : 0;
1798
1799 }
1800
1801 int unload_module(void)
1802 {
1803         int res;
1804
1805         res = ast_unregister_application(app);
1806         res |= ast_unregister_application(rapp);
1807
1808         STANDARD_HANGUP_LOCALUSERS;
1809         
1810         return res;
1811 }
1812
1813 int load_module(void)
1814 {
1815         int res;
1816
1817         res = ast_register_application(app, dial_exec, synopsis, descrip);
1818         res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1819         
1820         return res;
1821 }
1822
1823 char *description(void)
1824 {
1825         return tdesc;
1826 }
1827
1828 int usecount(void)
1829 {
1830         int res;
1831         STANDARD_USECOUNT(res);
1832         return res;
1833 }
1834
1835 char *key()
1836 {
1837         return ASTERISK_GPL_KEY;
1838 }