update comment to match the state of the code
[asterisk-bristuff.git] / apps / app_dial.c
blobc1bb40b95baa49dfc237a5e16a813559d252ccf4
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
19 /*! \file
21 * \brief dial() & retrydial() - Trivial application to dial a channel and send an URL on answer
23 * \author Mark Spencer <markster@digium.com>
25 * \ingroup applications
28 #include "asterisk.h"
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <sys/time.h>
39 #include <sys/signal.h>
40 #include <sys/stat.h>
41 #include <netinet/in.h>
43 #include "asterisk/lock.h"
44 #include "asterisk/file.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/options.h"
49 #include "asterisk/module.h"
50 #include "asterisk/translate.h"
51 #include "asterisk/say.h"
52 #include "asterisk/config.h"
53 #include "asterisk/features.h"
54 #include "asterisk/musiconhold.h"
55 #include "asterisk/callerid.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/app.h"
58 #include "asterisk/causes.h"
59 #include "asterisk/rtp.h"
60 #include "asterisk/manager.h"
61 #include "asterisk/privacy.h"
62 #include "asterisk/stringfields.h"
64 static char *app = "Dial";
66 static char *synopsis = "Place a call and connect to the current channel";
68 static char *descrip =
69 " Dial(Technology/resource[&Tech2/resource2...][|timeout][|options][|URL]):\n"
70 "This application will place calls to one or more specified channels. As soon\n"
71 "as one of the requested channels answers, the originating channel will be\n"
72 "answered, if it has not already been answered. These two channels will then\n"
73 "be active in a bridged call. All other channels that were requested will then\n"
74 "be hung up.\n"
75 " Unless there is a timeout specified, the Dial application will wait\n"
76 "indefinitely until one of the called channels answers, the user hangs up, or\n"
77 "if all of the called channels are busy or unavailable. Dialplan executing will\n"
78 "continue if no requested channels can be called, or if the timeout expires.\n\n"
79 " This application sets the following channel variables upon completion:\n"
80 " DIALEDTIME - This is the time from dialing a channel until when it\n"
81 " is disconnected.\n"
82 " ANSWEREDTIME - This is the amount of time for actual call.\n"
83 " DIALSTATUS - This is the status of the call:\n"
84 " CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
85 " DONTCALL | TORTURE | INVALIDARGS\n"
86 " For the Privacy and Screening Modes, the DIALSTATUS variable will be set to\n"
87 "DONTCALL if the called party chooses to send the calling party to the 'Go Away'\n"
88 "script. The DIALSTATUS variable will be set to TORTURE if the called party\n"
89 "wants to send the caller to the 'torture' script.\n"
90 " This application will report normal termination if the originating channel\n"
91 "hangs up, or if the call is bridged and either of the parties in the bridge\n"
92 "ends the call.\n"
93 " The optional URL will be sent to the called party if the channel supports it.\n"
94 " If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
95 "application will be put into that group (as in Set(GROUP()=...).\n"
96 " If the OUTBOUND_GROUP_ONCE variable is set, all peer channels created by this\n"
97 "application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP,\n"
98 "however, the variable will be unset after use.\n\n"
99 " Options:\n"
100 " A(x) - Play an announcement to the called party, using 'x' as the file.\n"
101 " C - Reset the CDR for this call.\n"
102 " d - Allow the calling user to dial a 1 digit extension while waiting for\n"
103 " a call to be answered. Exit to that extension if it exists in the\n"
104 " current context, or the context defined in the EXITCONTEXT variable,\n"
105 " if it exists.\n"
106 " D([called][:calling]) - Send the specified DTMF strings *after* the called\n"
107 " party has answered, but before the call gets bridged. The 'called'\n"
108 " DTMF string is sent to the called party, and the 'calling' DTMF\n"
109 " string is sent to the calling party. Both parameters can be used\n"
110 " alone.\n"
111 " f - Force the callerid of the *calling* channel to be set as the\n"
112 " extension associated with the channel using a dialplan 'hint'.\n"
113 " For example, some PSTNs do not allow CallerID to be set to anything\n"
114 " other than the number assigned to the caller.\n"
115 " g - Proceed with dialplan execution at the current extension if the\n"
116 " destination channel hangs up.\n"
117 " G(context^exten^pri) - If the call is answered, transfer the calling party to\n"
118 " the specified priority and the called party to the specified priority+1.\n"
119 " Optionally, an extension, or extension and context may be specified. \n"
120 " Otherwise, the current extension is used. You cannot use any additional\n"
121 " action post answer options in conjunction with this option.\n"
122 " h - Allow the called party to hang up by sending the '*' DTMF digit.\n"
123 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
124 " i - Asterisk will ignore any forwarding requests it may receive on this\n"
125 " dial attempt.\n"
126 " j - Jump to priority n+101 if all of the requested channels were busy.\n"
127 " k - Allow the called party to enable parking of the call by sending\n"
128 " the DTMF sequence defined for call parking in features.conf.\n"
129 " K - Allow the calling party to enable parking of the call by sending\n"
130 " the DTMF sequence defined for call parking in features.conf.\n"
131 " L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
132 " left. Repeat the warning every 'z' ms. The following special\n"
133 " variables can be used with this option:\n"
134 " * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
135 " Play sounds to the caller.\n"
136 " * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
137 " Play sounds to the callee.\n"
138 " * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
139 " * LIMIT_CONNECT_FILE File to play when call begins.\n"
140 " * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
141 " The default is to say the time remaining.\n"
142 " m([class]) - Provide hold music to the calling party until a requested\n"
143 " channel answers. A specific MusicOnHold class can be\n"
144 " specified.\n"
145 " M(x[^arg]) - Execute the Macro for the *called* channel before connecting\n"
146 " to the calling channel. Arguments can be specified to the Macro\n"
147 " using '^' as a delimeter. The Macro can set the variable\n"
148 " MACRO_RESULT to specify the following actions after the Macro is\n"
149 " finished executing.\n"
150 " * ABORT Hangup both legs of the call.\n"
151 " * CONGESTION Behave as if line congestion was encountered.\n"
152 " * BUSY Behave as if a busy signal was encountered. This will also\n"
153 " have the application jump to priority n+101 if the\n"
154 " 'j' option is set.\n"
155 " * CONTINUE Hangup the called party and allow the calling party\n"
156 " to continue dialplan execution at the next priority.\n"
157 " * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
158 " specified priority. Optionally, an extension, or\n"
159 " extension and priority can be specified.\n"
160 " You cannot use any additional action post answer options in conjunction\n"
161 " with this option. Also, pbx services are not run on the peer (called) channel,\n"
162 " so you will not be able to set timeouts via the TIMEOUT() function in this macro.\n"
163 " n - This option is a modifier for the screen/privacy mode. It specifies\n"
164 " that no introductions are to be saved in the priv-callerintros\n"
165 " directory.\n"
166 " N - This option is a modifier for the screen/privacy mode. It specifies\n"
167 " that if callerID is present, do not screen the call.\n"
168 " o - Specify that the CallerID that was present on the *calling* channel\n"
169 " be set as the CallerID on the *called* channel. This was the\n"
170 " behavior of Asterisk 1.0 and earlier.\n"
171 " O([x]) - \"Operator Services\" mode (Zaptel channel to Zaptel channel\n"
172 " only, if specified on non-Zaptel interface, it will be ignored).\n"
173 " When the destination answers (presumably an operator services\n"
174 " station), the originator no longer has control of their line.\n"
175 " They may hang up, but the switch will not release their line\n"
176 " until the destination party hangs up (the operator). Specified\n"
177 " without an arg, or with 1 as an arg, the originator hanging up\n"
178 " will cause the phone to ring back immediately. With a 2 specified,\n"
179 " when the \"operator\" flashes the trunk, it will ring their phone\n"
180 " back.\n"
181 " p - This option enables screening mode. This is basically Privacy mode\n"
182 " without memory.\n"
183 " P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if\n"
184 " it is provided. The current extension is used if a database\n"
185 " family/key is not specified.\n"
186 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
187 " party until the called channel has answered.\n"
188 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
189 " answered the call.\n"
190 " t - Allow the called party to transfer the calling party by sending the\n"
191 " DTMF sequence defined in features.conf.\n"
192 " T - Allow the calling party to transfer the called party by sending the\n"
193 " DTMF sequence defined in features.conf.\n"
194 " w - Allow the called party to enable recording of the call by sending\n"
195 " the DTMF sequence defined for one-touch recording in features.conf.\n"
196 " W - Allow the calling party to enable recording of the call by sending\n"
197 " the DTMF sequence defined for one-touch recording in features.conf.\n";
199 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
200 static char *rapp = "RetryDial";
201 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
202 static char *rdescrip =
203 " RetryDial(announce|sleep|retries|dialargs): This application will attempt to\n"
204 "place a call using the normal Dial application. If no channel can be reached,\n"
205 "the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
206 "seconds before retying the call. After 'retires' number of attempts, the\n"
207 "calling channel will continue at the next priority in the dialplan. If the\n"
208 "'retries' setting is set to 0, this application will retry endlessly.\n"
209 " While waiting to retry a call, a 1 digit extension may be dialed. If that\n"
210 "extension exists in either the context defined in ${EXITCONTEXT} or the current\n"
211 "one, The call will jump to that extension immediately.\n"
212 " The 'dialargs' are specified in the same format that arguments are provided\n"
213 "to the Dial application.\n";
215 enum {
216 OPT_ANNOUNCE = (1 << 0),
217 OPT_RESETCDR = (1 << 1),
218 OPT_DTMF_EXIT = (1 << 2),
219 OPT_SENDDTMF = (1 << 3),
220 OPT_FORCECLID = (1 << 4),
221 OPT_GO_ON = (1 << 5),
222 OPT_CALLEE_HANGUP = (1 << 6),
223 OPT_CALLER_HANGUP = (1 << 7),
224 OPT_PRIORITY_JUMP = (1 << 8),
225 OPT_DURATION_LIMIT = (1 << 9),
226 OPT_MUSICBACK = (1 << 10),
227 OPT_CALLEE_MACRO = (1 << 11),
228 OPT_SCREEN_NOINTRO = (1 << 12),
229 OPT_SCREEN_NOCLID = (1 << 13),
230 OPT_ORIGINAL_CLID = (1 << 14),
231 OPT_SCREENING = (1 << 15),
232 OPT_PRIVACY = (1 << 16),
233 OPT_RINGBACK = (1 << 17),
234 OPT_DURATION_STOP = (1 << 18),
235 OPT_CALLEE_TRANSFER = (1 << 19),
236 OPT_CALLER_TRANSFER = (1 << 20),
237 OPT_CALLEE_MONITOR = (1 << 21),
238 OPT_CALLER_MONITOR = (1 << 22),
239 OPT_GOTO = (1 << 23),
240 OPT_OPERMODE = (1 << 24),
241 OPT_CALLEE_PARK = (1 << 25),
242 OPT_CALLER_PARK = (1 << 26),
243 OPT_IGNORE_FORWARDING = (1 << 27),
244 } dial_exec_option_flags;
246 #define DIAL_STILLGOING (1 << 30)
247 #define DIAL_NOFORWARDHTML (1 << 31)
249 enum {
250 OPT_ARG_ANNOUNCE = 0,
251 OPT_ARG_SENDDTMF,
252 OPT_ARG_GOTO,
253 OPT_ARG_DURATION_LIMIT,
254 OPT_ARG_MUSICBACK,
255 OPT_ARG_CALLEE_MACRO,
256 OPT_ARG_PRIVACY,
257 OPT_ARG_DURATION_STOP,
258 OPT_ARG_OPERMODE,
259 /* note: this entry _MUST_ be the last one in the enum */
260 OPT_ARG_ARRAY_SIZE,
261 } dial_exec_option_args;
263 AST_APP_OPTIONS(dial_exec_options, {
264 AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
265 AST_APP_OPTION('C', OPT_RESETCDR),
266 AST_APP_OPTION('d', OPT_DTMF_EXIT),
267 AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
268 AST_APP_OPTION('f', OPT_FORCECLID),
269 AST_APP_OPTION('g', OPT_GO_ON),
270 AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
271 AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
272 AST_APP_OPTION('H', OPT_CALLER_HANGUP),
273 AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
274 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
275 AST_APP_OPTION('k', OPT_CALLEE_PARK),
276 AST_APP_OPTION('K', OPT_CALLER_PARK),
277 AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
278 AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
279 AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
280 AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
281 AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
282 AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
283 AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
284 AST_APP_OPTION('p', OPT_SCREENING),
285 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
286 AST_APP_OPTION('r', OPT_RINGBACK),
287 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
288 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
289 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
290 AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
291 AST_APP_OPTION('W', OPT_CALLER_MONITOR),
294 #define CAN_EARLY_BRIDGE(flags) (!ast_test_flag(flags, OPT_CALLEE_HANGUP | \
295 OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
296 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | OPT_CALLER_PARK))
298 /* We define a custom "local user" structure because we
299 use it not only for keeping track of what is in use but
300 also for keeping track of who we're dialing. */
302 struct dial_localuser {
303 struct ast_channel *chan;
304 unsigned int flags;
305 int forwards;
306 struct dial_localuser *next;
310 static void hanguptree(struct dial_localuser *outgoing, struct ast_channel *exception)
312 /* Hang up a tree of stuff */
313 struct dial_localuser *oo;
314 while (outgoing) {
315 /* Hangup any existing lines we have open */
316 if (outgoing->chan && (outgoing->chan != exception))
317 ast_hangup(outgoing->chan);
318 oo = outgoing;
319 outgoing=outgoing->next;
320 free(oo);
324 #define AST_MAX_FORWARDS 8
326 #define AST_MAX_WATCHERS 256
328 #define HANDLE_CAUSE(cause, chan) do { \
329 switch(cause) { \
330 case AST_CAUSE_BUSY: \
331 if (chan->cdr) \
332 ast_cdr_busy(chan->cdr); \
333 numbusy++; \
334 break; \
335 case AST_CAUSE_CONGESTION: \
336 if (chan->cdr) \
337 ast_cdr_failed(chan->cdr); \
338 numcongestion++; \
339 break; \
340 case AST_CAUSE_UNREGISTERED: \
341 if (chan->cdr) \
342 ast_cdr_failed(chan->cdr); \
343 numnochan++; \
344 break; \
345 case AST_CAUSE_NORMAL_CLEARING: \
346 break; \
347 default: \
348 numnochan++; \
349 break; \
351 } while (0)
354 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
356 char rexten[2] = { exten, '\0' };
358 if (context) {
359 if (!ast_goto_if_exists(chan, context, rexten, pri))
360 return 1;
361 } else {
362 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
363 return 1;
364 else if (!ast_strlen_zero(chan->macrocontext)) {
365 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
366 return 1;
369 return 0;
373 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
375 const char *context = S_OR(chan->macrocontext, chan->context);
376 const char *exten = S_OR(chan->macroexten, chan->exten);
378 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
381 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
383 /* XXX do we need also CallerIDnum ? */
384 manager_event(EVENT_FLAG_CALL, "Dial",
385 "Source: %s\r\n"
386 "Destination: %s\r\n"
387 "CallerID: %s\r\n"
388 "CallerIDName: %s\r\n"
389 "SrcUniqueID: %s\r\n"
390 "DestUniqueID: %s\r\n",
391 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
392 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
393 dst->uniqueid);
396 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_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)
398 int numbusy = busystart;
399 int numcongestion = congestionstart;
400 int numnochan = nochanstart;
401 int prestart = busystart + congestionstart + nochanstart;
402 int orig = *to;
403 struct ast_channel *peer = NULL;
404 /* single is set if only one destination is enabled */
405 int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
407 if (single) {
408 /* Turn off hold music, etc */
409 ast_deactivate_generator(in);
410 /* If we are calling a single channel, make them compatible for in-band tone purpose */
411 ast_channel_make_compatible(outgoing->chan, in);
415 while (*to && !peer) {
416 struct dial_localuser *o;
417 int pos = 0; /* how many channels do we handle */
418 int numlines = prestart;
419 struct ast_channel *winner;
420 struct ast_channel *watchers[AST_MAX_WATCHERS];
422 watchers[pos++] = in;
423 for (o = outgoing; o; o = o->next) {
424 /* Keep track of important channels */
425 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan)
426 watchers[pos++] = o->chan;
427 numlines++;
429 if (pos == 1) { /* only the input channel is available */
430 if (numlines == (numbusy + numcongestion + numnochan)) {
431 if (option_verbose > 2)
432 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
433 if (numbusy)
434 strcpy(status, "BUSY");
435 else if (numcongestion)
436 strcpy(status, "CONGESTION");
437 else if (numnochan)
438 strcpy(status, "CHANUNAVAIL");
439 if (ast_opt_priority_jumping || priority_jump)
440 ast_goto_if_exists(in, in->context, in->exten, in->priority + 101);
441 } else {
442 if (option_verbose > 2)
443 ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
445 *to = 0;
446 return NULL;
448 winner = ast_waitfor_n(watchers, pos, to);
449 for (o = outgoing; o; o = o->next) {
450 struct ast_frame *f;
451 struct ast_channel *c = o->chan;
453 if (c == NULL)
454 continue;
455 if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
456 if (!peer) {
457 if (option_verbose > 2)
458 ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
459 peer = c;
460 ast_copy_flags(peerflags, o,
461 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
462 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
463 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
464 OPT_CALLEE_PARK | OPT_CALLER_PARK |
465 DIAL_NOFORWARDHTML);
466 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
467 ast_copy_string(c->exten, "", sizeof(c->exten));
469 continue;
471 if (c != winner)
472 continue;
473 if (!ast_strlen_zero(c->call_forward)) {
474 char tmpchan[256];
475 char *stuff;
476 char *tech;
477 int cause;
479 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
480 if ((stuff = strchr(tmpchan, '/'))) {
481 *stuff++ = '\0';
482 tech = tmpchan;
483 } else {
484 const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
485 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
486 stuff = tmpchan;
487 tech = "Local";
489 /* Before processing channel, go ahead and check for forwarding */
490 o->forwards++;
491 if (o->forwards < AST_MAX_FORWARDS) {
492 if (option_verbose > 2)
493 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
494 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
495 if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
496 if (option_verbose > 2)
497 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
498 c = o->chan = NULL;
499 cause = AST_CAUSE_BUSY;
500 } else {
501 /* Setup parameters */
502 if ((c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause))) {
503 if (single)
504 ast_channel_make_compatible(o->chan, in);
505 ast_channel_inherit_variables(in, o->chan);
506 } else
507 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
509 } else {
510 if (option_verbose > 2)
511 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
512 cause = AST_CAUSE_CONGESTION;
513 c = o->chan = NULL;
515 if (!c) {
516 ast_clear_flag(o, DIAL_STILLGOING);
517 HANDLE_CAUSE(cause, in);
518 } else {
519 ast_rtp_make_compatible(c, in, single);
520 if (c->cid.cid_num)
521 free(c->cid.cid_num);
522 c->cid.cid_num = NULL;
523 if (c->cid.cid_name)
524 free(c->cid.cid_name);
525 c->cid.cid_name = NULL;
527 if (ast_test_flag(o, OPT_FORCECLID)) {
528 c->cid.cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
529 ast_string_field_set(c, accountcode, winner->accountcode);
530 c->cdrflags = winner->cdrflags;
531 } else {
532 c->cid.cid_num = ast_strdup(in->cid.cid_num);
533 c->cid.cid_name = ast_strdup(in->cid.cid_name);
534 ast_string_field_set(c, accountcode, in->accountcode);
535 c->cdrflags = in->cdrflags;
538 if (in->cid.cid_ani) {
539 if (c->cid.cid_ani)
540 free(c->cid.cid_ani);
541 c->cid.cid_ani = ast_strdup(in->cid.cid_ani);
543 if (c->cid.cid_rdnis)
544 free(c->cid.cid_rdnis);
545 c->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
546 if (ast_call(c, tmpchan, 0)) {
547 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
548 ast_clear_flag(o, DIAL_STILLGOING);
549 ast_hangup(c);
550 c = o->chan = NULL;
551 numnochan++;
552 } else {
553 senddialevent(in, c);
554 /* After calling, set callerid to extension */
555 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
556 char cidname[AST_MAX_EXTENSION] = "";
557 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
561 /* Hangup the original channel now, in case we needed it */
562 ast_hangup(winner);
563 continue;
565 f = ast_read(winner);
566 if (!f) {
567 in->hangupcause = c->hangupcause;
568 ast_hangup(c);
569 c = o->chan = NULL;
570 ast_clear_flag(o, DIAL_STILLGOING);
571 HANDLE_CAUSE(in->hangupcause, in);
572 continue;
574 if (f->frametype == AST_FRAME_CONTROL) {
575 switch(f->subclass) {
576 case AST_CONTROL_ANSWER:
577 /* This is our guy if someone answered. */
578 if (!peer) {
579 if (option_verbose > 2)
580 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
581 peer = c;
582 ast_copy_flags(peerflags, o,
583 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
584 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
585 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
586 OPT_CALLEE_PARK | OPT_CALLER_PARK |
587 DIAL_NOFORWARDHTML);
588 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
589 ast_copy_string(c->exten, "", sizeof(c->exten));
590 /* Setup RTP early bridge if appropriate */
591 if (CAN_EARLY_BRIDGE(peerflags))
592 ast_rtp_early_bridge(in, peer);
594 /* If call has been answered, then the eventual hangup is likely to be normal hangup */
595 in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
596 c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
597 break;
598 case AST_CONTROL_BUSY:
599 if (option_verbose > 2)
600 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name);
601 in->hangupcause = c->hangupcause;
602 ast_hangup(c);
603 c = o->chan = NULL;
604 ast_clear_flag(o, DIAL_STILLGOING);
605 HANDLE_CAUSE(AST_CAUSE_BUSY, in);
606 break;
607 case AST_CONTROL_CONGESTION:
608 if (option_verbose > 2)
609 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name);
610 in->hangupcause = c->hangupcause;
611 ast_hangup(c);
612 c = o->chan = NULL;
613 ast_clear_flag(o, DIAL_STILLGOING);
614 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
615 break;
616 case AST_CONTROL_RINGING:
617 if (option_verbose > 2)
618 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
619 /* Setup early media if appropriate */
620 if (single && CAN_EARLY_BRIDGE(peerflags))
621 ast_rtp_early_bridge(in, c);
622 if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
623 ast_indicate(in, AST_CONTROL_RINGING);
624 (*sentringing)++;
626 break;
627 case AST_CONTROL_PROGRESS:
628 if (option_verbose > 2)
629 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name);
630 /* Setup early media if appropriate */
631 if (single && CAN_EARLY_BRIDGE(peerflags))
632 ast_rtp_early_bridge(in, c);
633 if (!ast_test_flag(outgoing, OPT_RINGBACK))
634 ast_indicate(in, AST_CONTROL_PROGRESS);
635 break;
636 case AST_CONTROL_VIDUPDATE:
637 if (option_verbose > 2)
638 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name);
639 ast_indicate(in, AST_CONTROL_VIDUPDATE);
640 break;
641 case AST_CONTROL_PROCEEDING:
642 if (option_verbose > 2)
643 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
644 if (single && CAN_EARLY_BRIDGE(peerflags))
645 ast_rtp_early_bridge(in, c);
646 if (!ast_test_flag(outgoing, OPT_RINGBACK))
647 ast_indicate(in, AST_CONTROL_PROCEEDING);
648 break;
649 case AST_CONTROL_HOLD:
650 if (option_verbose > 2)
651 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name);
652 ast_indicate(in, AST_CONTROL_HOLD);
653 break;
654 case AST_CONTROL_UNHOLD:
655 if (option_verbose > 2)
656 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name);
657 ast_indicate(in, AST_CONTROL_UNHOLD);
658 break;
659 case AST_CONTROL_OFFHOOK:
660 case AST_CONTROL_FLASH:
661 /* Ignore going off hook and flash */
662 break;
663 case -1:
664 if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
665 if (option_verbose > 2)
666 ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
667 ast_indicate(in, -1);
668 (*sentringing) = 0;
670 break;
671 default:
672 if (option_debug)
673 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
675 } else if (single) {
676 /* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */
677 if (f->frametype == AST_FRAME_VOICE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
678 if (ast_write(in, f))
679 ast_log(LOG_WARNING, "Unable to forward voice frame\n");
680 } else if (f->frametype == AST_FRAME_IMAGE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
681 if (ast_write(in, f))
682 ast_log(LOG_WARNING, "Unable to forward image\n");
683 } else if (f->frametype == AST_FRAME_TEXT && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
684 if (ast_write(in, f))
685 ast_log(LOG_WARNING, "Unable to send text\n");
686 } else if (f->frametype == AST_FRAME_HTML && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) {
687 if (ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1)
688 ast_log(LOG_WARNING, "Unable to send URL\n");
691 ast_frfree(f);
692 } /* end for */
693 if (winner == in) {
694 struct ast_frame *f = ast_read(in);
695 #if 0
696 if (f && (f->frametype != AST_FRAME_VOICE))
697 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
698 else if (!f || (f->frametype != AST_FRAME_VOICE))
699 printf("Hangup received on %s\n", in->name);
700 #endif
701 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
702 /* Got hung up */
703 *to = -1;
704 ast_cdr_noanswer(in->cdr);
705 strcpy(status, "CANCEL");
706 if (f)
707 ast_frfree(f);
708 return NULL;
711 if (f && (f->frametype == AST_FRAME_DTMF)) {
712 if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
713 const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
714 if (onedigit_goto(in, context, (char) f->subclass, 1)) {
715 if (option_verbose > 2)
716 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
717 *to=0;
718 ast_cdr_noanswer(in->cdr);
719 *result = f->subclass;
720 strcpy(status, "CANCEL");
721 ast_frfree(f);
722 return NULL;
726 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) &&
727 (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
728 if (option_verbose > 2)
729 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
730 *to=0;
731 ast_cdr_noanswer(in->cdr);
732 strcpy(status, "CANCEL");
733 ast_frfree(f);
734 return NULL;
738 /* Forward HTML stuff */
739 if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
740 if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
741 ast_log(LOG_WARNING, "Unable to send URL\n");
744 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) {
745 if (ast_write(outgoing->chan, f))
746 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
748 if (single && (f->frametype == AST_FRAME_CONTROL) &&
749 ((f->subclass == AST_CONTROL_HOLD) ||
750 (f->subclass == AST_CONTROL_UNHOLD) ||
751 (f->subclass == AST_CONTROL_VIDUPDATE))) {
752 if (option_verbose > 2)
753 ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
754 ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
756 ast_frfree(f);
758 if (!*to && (option_verbose > 2))
759 ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
760 if (!*to || ast_check_hangup(in)) {
761 ast_cdr_noanswer(in->cdr);
766 return peer;
769 static void replace_macro_delimiter(char *s)
771 for (; *s; s++)
772 if (*s == '^')
773 *s = '|';
777 /* returns true if there is a valid privacy reply */
778 static int valid_priv_reply(struct ast_flags *opts, int res)
780 if (res < '1')
781 return 0;
782 if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5')
783 return 1;
784 if (ast_test_flag(opts, OPT_SCREENING) && res <= '4')
785 return 1;
786 return 0;
789 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags, int *continue_exec)
791 int res = -1;
792 struct ast_module_user *u;
793 char *rest, *cur;
794 struct dial_localuser *outgoing = NULL;
795 struct ast_channel *peer;
796 int to;
797 int numbusy = 0;
798 int numcongestion = 0;
799 int numnochan = 0;
800 int cause;
801 char numsubst[256];
802 char cidname[AST_MAX_EXTENSION] = "";
803 int privdb_val = 0;
804 unsigned int calldurationlimit = 0;
805 long timelimit = 0;
806 long play_warning = 0;
807 long warning_freq = 0;
808 const char *warning_sound = NULL;
809 const char *end_sound = NULL;
810 const char *start_sound = NULL;
811 char *dtmfcalled = NULL, *dtmfcalling = NULL;
812 char status[256] = "INVALIDARGS";
813 int play_to_caller = 0, play_to_callee = 0;
814 int sentringing = 0, moh = 0;
815 const char *outbound_group = NULL;
816 int result = 0;
817 time_t start_time;
818 char privintro[1024];
819 char privcid[256];
820 char *parse;
821 int opermode = 0;
822 AST_DECLARE_APP_ARGS(args,
823 AST_APP_ARG(peers);
824 AST_APP_ARG(timeout);
825 AST_APP_ARG(options);
826 AST_APP_ARG(url);
828 struct ast_flags opts = { 0, };
829 char *opt_args[OPT_ARG_ARRAY_SIZE];
831 if (ast_strlen_zero(data)) {
832 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
833 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
834 return -1;
837 u = ast_module_user_add(chan);
839 parse = ast_strdupa(data);
841 AST_STANDARD_APP_ARGS(args, parse);
843 if (!ast_strlen_zero(args.options) &&
844 ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options)) {
845 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
846 goto done;
849 if (ast_strlen_zero(args.peers)) {
850 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
851 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
852 goto done;
855 if (ast_test_flag(&opts, OPT_OPERMODE)) {
856 if (ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]))
857 opermode = 1;
858 else opermode = atoi(opt_args[OPT_ARG_OPERMODE]);
859 if (option_verbose > 2)
860 ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
863 if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
864 calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
865 if (!calldurationlimit) {
866 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
867 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
868 goto done;
870 if (option_verbose > 2)
871 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
874 if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
875 dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
876 dtmfcalled = strsep(&dtmfcalling, ":");
879 if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
880 char *limit_str, *warning_str, *warnfreq_str;
881 const char *var;
883 warnfreq_str = opt_args[OPT_ARG_DURATION_LIMIT];
884 limit_str = strsep(&warnfreq_str, ":");
885 warning_str = strsep(&warnfreq_str, ":");
887 timelimit = atol(limit_str);
888 if (warning_str)
889 play_warning = atol(warning_str);
890 if (warnfreq_str)
891 warning_freq = atol(warnfreq_str);
893 if (!timelimit) {
894 ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
895 goto done;
896 } else if (play_warning > timelimit) {
897 /* If the first warning is requested _after_ the entire call would end,
898 and no warning frequency is requested, then turn off the warning. If
899 a warning frequency is requested, reduce the 'first warning' time by
900 that frequency until it falls within the call's total time limit.
903 if (!warning_freq) {
904 play_warning = 0;
905 } else {
906 /* XXX fix this!! */
907 while (play_warning > timelimit)
908 play_warning -= warning_freq;
909 if (play_warning < 1)
910 play_warning = warning_freq = 0;
914 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
915 play_to_caller = var ? ast_true(var) : 1;
917 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
918 play_to_callee = var ? ast_true(var) : 0;
920 if (!play_to_caller && !play_to_callee)
921 play_to_caller = 1;
923 var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
924 warning_sound = S_OR(var, "timeleft");
926 var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
927 end_sound = S_OR(var, NULL); /* XXX not much of a point in doing this! */
929 var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
930 start_sound = S_OR(var, NULL); /* XXX not much of a point in doing this! */
932 /* undo effect of S(x) in case they are both used */
933 calldurationlimit = 0;
934 /* more efficient to do it like S(x) does since no advanced opts */
935 if (!play_warning && !start_sound && !end_sound && timelimit) {
936 calldurationlimit = timelimit / 1000;
937 if (option_verbose > 2)
938 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
939 timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0;
940 } else if (option_verbose > 2) {
941 ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
942 ast_verbose(VERBOSE_PREFIX_4 "timelimit = %ld\n", timelimit);
943 ast_verbose(VERBOSE_PREFIX_4 "play_warning = %ld\n", play_warning);
944 ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
945 ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
946 ast_verbose(VERBOSE_PREFIX_4 "warning_freq = %ld\n", warning_freq);
947 ast_verbose(VERBOSE_PREFIX_4 "start_sound = %s\n", start_sound);
948 ast_verbose(VERBOSE_PREFIX_4 "warning_sound = %s\n", warning_sound);
949 ast_verbose(VERBOSE_PREFIX_4 "end_sound = %s\n", end_sound);
953 if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
954 ast_cdr_reset(chan->cdr, NULL);
955 if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
956 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
957 if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) {
958 char callerid[60];
959 char *l = chan->cid.cid_num; /* XXX watch out, we are overwriting it */
960 if (!ast_strlen_zero(l)) {
961 ast_shrink_phone_number(l);
962 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
963 if (option_verbose > 2)
964 ast_verbose(VERBOSE_PREFIX_3 "Privacy DB is '%s', clid is '%s'\n",
965 opt_args[OPT_ARG_PRIVACY], l);
966 privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
968 else {
969 if (option_verbose > 2)
970 ast_verbose(VERBOSE_PREFIX_3 "Privacy Screening, clid is '%s'\n", l);
971 privdb_val = AST_PRIVACY_UNKNOWN;
973 } else {
974 char *tnam, *tn2;
976 tnam = ast_strdupa(chan->name);
977 /* clean the channel name so slashes don't try to end up in disk file name */
978 for(tn2 = tnam; *tn2; tn2++) {
979 if( *tn2=='/')
980 *tn2 = '='; /* any other chars to be afraid of? */
982 if (option_verbose > 2)
983 ast_verbose(VERBOSE_PREFIX_3 "Privacy-- callerid is empty\n");
985 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
986 l = callerid;
987 privdb_val = AST_PRIVACY_UNKNOWN;
990 ast_copy_string(privcid,l,sizeof(privcid));
992 if( strncmp(privcid,"NOCALLERID",10) != 0 && ast_test_flag(&opts, OPT_SCREEN_NOCLID) ) { /* if callerid is set, and ast_test_flag(&opts, OPT_SCREEN_NOCLID) is set also */
993 if (option_verbose > 2)
994 ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", privcid);
995 privdb_val = AST_PRIVACY_ALLOW;
997 else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) {
998 if (option_verbose > 2)
999 ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
1002 if(privdb_val == AST_PRIVACY_DENY ) {
1003 ast_copy_string(status, "NOANSWER", sizeof(status));
1004 if (option_verbose > 2)
1005 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1006 res=0;
1007 goto out;
1009 else if(privdb_val == AST_PRIVACY_KILL ) {
1010 ast_copy_string(status, "DONTCALL", sizeof(status));
1011 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1012 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1014 res = 0;
1015 goto out; /* Is this right? */
1017 else if(privdb_val == AST_PRIVACY_TORTURE ) {
1018 ast_copy_string(status, "TORTURE", sizeof(status));
1019 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1020 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1022 res = 0;
1023 goto out; /* is this right??? */
1025 else if(privdb_val == AST_PRIVACY_UNKNOWN ) {
1026 /* Get the user's intro, store it in priv-callerintros/$CID,
1027 unless it is already there-- this should be done before the
1028 call is actually dialed */
1030 /* make sure the priv-callerintros dir actually exists */
1031 snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
1032 if (mkdir(privintro, 0755) && errno != EEXIST) {
1033 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
1034 res = -1;
1035 goto out;
1038 snprintf(privintro,sizeof(privintro), "priv-callerintros/%s", privcid);
1039 if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
1040 /* the DELUX version of this code would allow this caller the
1041 option to hear and retape their previously recorded intro.
1044 else {
1045 int duration; /* for feedback from play_and_wait */
1046 /* the file doesn't exist yet. Let the caller submit his
1047 vocal intro for posterity */
1048 /* priv-recordintro script:
1050 "At the tone, please say your name:"
1053 ast_answer(chan);
1054 res = ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */
1055 /* don't think we'll need a lock removed, we took care of
1056 conflicts by naming the privintro file */
1057 if (res == -1) {
1058 /* Delete the file regardless since they hung up during recording */
1059 ast_filedelete(privintro, NULL);
1060 if( ast_fileexists(privintro,NULL,NULL ) > 0 )
1061 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
1062 else if (option_verbose > 2)
1063 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1064 goto out;
1066 if( !ast_streamfile(chan, "vm-dialout", chan->language) )
1067 ast_waitstream(chan, "");
1072 if (continue_exec)
1073 *continue_exec = 0;
1075 /* If a channel group has been specified, get it for use when we create peer channels */
1076 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
1077 outbound_group = ast_strdupa(outbound_group);
1078 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
1079 } else {
1080 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1083 ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
1084 /* loop through the list of dial destinations */
1085 rest = args.peers;
1086 while ((cur = strsep(&rest, "&")) ) {
1087 struct dial_localuser *tmp;
1088 /* Get a technology/[device:]number pair */
1089 char *number = cur;
1090 char *tech = strsep(&number, "/");
1091 if (!number) {
1092 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
1093 goto out;
1095 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
1096 goto out;
1097 if (opts.flags) {
1098 ast_copy_flags(tmp, &opts,
1099 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
1100 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
1101 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
1102 OPT_CALLEE_PARK | OPT_CALLER_PARK |
1103 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
1104 ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);
1106 ast_copy_string(numsubst, number, sizeof(numsubst));
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_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1112 HANDLE_CAUSE(cause, chan);
1113 if (!rest) /* we are on the last destination */
1114 chan->hangupcause = cause;
1115 free(tmp);
1116 continue;
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 tech = tmpchan;
1127 } else {
1128 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
1129 stuff = tmpchan;
1130 tech = "Local";
1132 tmp->forwards++;
1133 if (tmp->forwards < AST_MAX_FORWARDS) {
1134 if (option_verbose > 2)
1135 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1136 ast_hangup(tmp->chan);
1137 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
1138 if (ast_test_flag(&opts, OPT_IGNORE_FORWARDING)) {
1139 tmp->chan = NULL;
1140 cause = AST_CAUSE_BUSY;
1141 if (option_verbose > 2)
1142 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", chan->name, tech, stuff);
1143 } else {
1144 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1146 if (!tmp->chan)
1147 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1148 else
1149 ast_channel_inherit_variables(chan, tmp->chan);
1150 } else {
1151 if (option_verbose > 2)
1152 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
1153 ast_hangup(tmp->chan);
1154 tmp->chan = NULL;
1155 cause = AST_CAUSE_CONGESTION;
1157 if (!tmp->chan) {
1158 HANDLE_CAUSE(cause, chan);
1159 free(tmp);
1160 continue;
1164 /* Setup outgoing SDP to match incoming one */
1165 ast_rtp_make_compatible(tmp->chan, chan, !outgoing && !rest);
1167 /* Inherit specially named variables from parent channel */
1168 ast_channel_inherit_variables(chan, tmp->chan);
1170 tmp->chan->appl = "AppDial";
1171 tmp->chan->data = "(Outgoing Line)";
1172 tmp->chan->whentohangup = 0;
1174 if (tmp->chan->cid.cid_num)
1175 free(tmp->chan->cid.cid_num);
1176 tmp->chan->cid.cid_num = ast_strdup(chan->cid.cid_num);
1178 if (tmp->chan->cid.cid_name)
1179 free(tmp->chan->cid.cid_name);
1180 tmp->chan->cid.cid_name = ast_strdup(chan->cid.cid_name);
1182 if (tmp->chan->cid.cid_ani)
1183 free(tmp->chan->cid.cid_ani);
1184 tmp->chan->cid.cid_ani = ast_strdup(chan->cid.cid_ani);
1186 /* Copy language from incoming to outgoing */
1187 ast_string_field_set(tmp->chan, language, chan->language);
1188 ast_string_field_set(tmp->chan, accountcode, chan->accountcode);
1189 tmp->chan->cdrflags = chan->cdrflags;
1190 if (ast_strlen_zero(tmp->chan->musicclass))
1191 ast_string_field_set(tmp->chan, musicclass, chan->musicclass);
1192 /* XXX don't we free previous values ? */
1193 tmp->chan->cid.cid_rdnis = ast_strdup(chan->cid.cid_rdnis);
1194 /* Pass callingpres setting */
1195 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
1196 /* Pass type of number */
1197 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
1198 /* Pass type of tns */
1199 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
1200 /* Presense of ADSI CPE on outgoing channel follows ours */
1201 tmp->chan->adsicpe = chan->adsicpe;
1202 /* Pass the transfer capability */
1203 tmp->chan->transfercapability = chan->transfercapability;
1205 /* If we have an outbound group, set this peer channel to it */
1206 if (outbound_group)
1207 ast_app_group_set_channel(tmp->chan, outbound_group);
1209 /* Inherit context and extension */
1210 if (!ast_strlen_zero(chan->macrocontext))
1211 ast_copy_string(tmp->chan->dialcontext, chan->macrocontext, sizeof(tmp->chan->dialcontext));
1212 else
1213 ast_copy_string(tmp->chan->dialcontext, chan->context, sizeof(tmp->chan->dialcontext));
1214 if (!ast_strlen_zero(chan->macroexten))
1215 ast_copy_string(tmp->chan->exten, chan->macroexten, sizeof(tmp->chan->exten));
1216 else
1217 ast_copy_string(tmp->chan->exten, chan->exten, sizeof(tmp->chan->exten));
1219 /* Place the call, but don't wait on the answer */
1220 res = ast_call(tmp->chan, numsubst, 0);
1222 /* Save the info in cdr's that we called them */
1223 if (chan->cdr)
1224 ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
1226 /* check the results of ast_call */
1227 if (res) {
1228 /* Again, keep going even if there's an error */
1229 if (option_debug)
1230 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1231 if (option_verbose > 2)
1232 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1233 ast_hangup(tmp->chan);
1234 tmp->chan = NULL;
1235 free(tmp);
1236 continue;
1237 } else {
1238 senddialevent(chan, tmp->chan);
1239 if (option_verbose > 2)
1240 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1241 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
1242 ast_set_callerid(tmp->chan, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
1244 /* Put them in the list of outgoing thingies... We're ready now.
1245 XXX If we're forcibly removed, these outgoing calls won't get
1246 hung up XXX */
1247 ast_set_flag(tmp, DIAL_STILLGOING);
1248 tmp->next = outgoing;
1249 outgoing = tmp;
1250 /* If this line is up, don't try anybody else */
1251 if (outgoing->chan->_state == AST_STATE_UP)
1252 break;
1255 if (ast_strlen_zero(args.timeout)) {
1256 to = -1;
1257 } else {
1258 to = atoi(args.timeout);
1259 if (to > 0)
1260 to *= 1000;
1261 else
1262 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
1265 if (!outgoing) {
1266 strcpy(status, "CHANUNAVAIL");
1267 } else {
1268 /* Our status will at least be NOANSWER */
1269 strcpy(status, "NOANSWER");
1270 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1271 moh = 1;
1272 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1273 char *original_moh = ast_strdupa(chan->musicclass);
1274 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
1275 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1276 ast_string_field_set(chan, musicclass, original_moh);
1277 } else {
1278 ast_moh_start(chan, NULL, NULL);
1280 ast_indicate(chan, AST_CONTROL_PROGRESS);
1281 } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
1282 ast_indicate(chan, AST_CONTROL_RINGING);
1283 sentringing++;
1287 time(&start_time);
1288 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
1290 if (!peer) {
1291 if (result) {
1292 res = result;
1293 } else if (to) { /* Musta gotten hung up */
1294 res = -1;
1295 } else { /* Nobody answered, next please? */
1296 res = 0;
1298 /* almost done, although the 'else' block is 400 lines */
1299 } else {
1300 const char *number;
1301 time_t end_time, answer_time = time(NULL);
1303 strcpy(status, "ANSWER");
1304 /* Ah ha! Someone answered within the desired timeframe. Of course after this
1305 we will always return with -1 so that it is hung up properly after the
1306 conversation. */
1307 hanguptree(outgoing, peer);
1308 outgoing = NULL;
1309 /* If appropriate, log that we have a destination channel */
1310 if (chan->cdr)
1311 ast_cdr_setdestchan(chan->cdr, peer->name);
1312 if (peer->name)
1313 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1315 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1316 if (!number)
1317 number = numsubst;
1318 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1319 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
1320 if (option_debug)
1321 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url);
1322 ast_channel_sendurl( peer, args.url );
1324 if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && privdb_val == AST_PRIVACY_UNKNOWN) {
1325 int res2;
1326 int loopcount = 0;
1328 /* Get the user's intro, store it in priv-callerintros/$CID,
1329 unless it is already there-- this should be done before the
1330 call is actually dialed */
1332 /* all ring indications and moh for the caller has been halted as soon as the
1333 target extension was picked up. We are going to have to kill some
1334 time and make the caller believe the peer hasn't picked up yet */
1336 if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1337 char *original_moh = ast_strdupa(chan->musicclass);
1338 ast_indicate(chan, -1);
1339 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
1340 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1341 ast_string_field_set(chan, musicclass, original_moh);
1342 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1343 ast_indicate(chan, AST_CONTROL_RINGING);
1344 sentringing++;
1347 /* Start autoservice on the other chan ?? */
1348 res2 = ast_autoservice_start(chan);
1349 /* Now Stream the File */
1350 for (loopcount = 0; loopcount < 3; loopcount++) {
1351 if (res2 && loopcount == 0) /* error in ast_autoservice_start() */
1352 break;
1353 if (!res2) /* on timeout, play the message again */
1354 res2 = ast_play_and_wait(peer,"priv-callpending");
1355 if (!valid_priv_reply(&opts, res2))
1356 res2 = 0;
1357 /* priv-callpending script:
1358 "I have a caller waiting, who introduces themselves as:"
1360 if (!res2)
1361 res2 = ast_play_and_wait(peer,privintro);
1362 if (!valid_priv_reply(&opts, res2))
1363 res2 = 0;
1364 /* now get input from the called party, as to their choice */
1365 if( !res2 ) {
1366 /* XXX can we have both, or they are mutually exclusive ? */
1367 if( ast_test_flag(&opts, OPT_PRIVACY) )
1368 res2 = ast_play_and_wait(peer,"priv-callee-options");
1369 if( ast_test_flag(&opts, OPT_SCREENING) )
1370 res2 = ast_play_and_wait(peer,"screen-callee-options");
1372 /*! \page DialPrivacy Dial Privacy scripts
1373 \par priv-callee-options script:
1374 "Dial 1 if you wish this caller to reach you directly in the future,
1375 and immediately connect to their incoming call
1376 Dial 2 if you wish to send this caller to voicemail now and
1377 forevermore.
1378 Dial 3 to send this caller to the torture menus, now and forevermore.
1379 Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
1380 Dial 5 to allow this caller to come straight thru to you in the future,
1381 but right now, just this once, send them to voicemail."
1382 \par screen-callee-options script:
1383 "Dial 1 if you wish to immediately connect to the incoming call
1384 Dial 2 if you wish to send this caller to voicemail.
1385 Dial 3 to send this caller to the torture menus.
1386 Dial 4 to send this caller to a simple "go away" menu.
1388 if (valid_priv_reply(&opts, res2))
1389 break;
1390 /* invalid option */
1391 res2 = ast_play_and_wait(peer, "vm-sorry");
1394 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
1395 ast_moh_stop(chan);
1396 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1397 ast_indicate(chan, -1);
1398 sentringing=0;
1400 ast_autoservice_stop(chan);
1402 switch (res2) {
1403 case '1':
1404 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1405 if (option_verbose > 2)
1406 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
1407 opt_args[OPT_ARG_PRIVACY], privcid);
1408 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
1410 break;
1411 case '2':
1412 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1413 if (option_verbose > 2)
1414 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n",
1415 opt_args[OPT_ARG_PRIVACY], privcid);
1416 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
1418 ast_copy_string(status, "NOANSWER", sizeof(status));
1419 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1420 res=0;
1421 goto out;
1422 case '3':
1423 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1424 if (option_verbose > 2)
1425 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n",
1426 opt_args[OPT_ARG_PRIVACY], privcid);
1427 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE);
1429 ast_copy_string(status, "TORTURE", sizeof(status));
1431 res = 0;
1432 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1433 goto out; /* Is this right? */
1434 case '4':
1435 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1436 if (option_verbose > 2)
1437 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n",
1438 opt_args[OPT_ARG_PRIVACY], privcid);
1439 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL);
1442 ast_copy_string(status, "DONTCALL", sizeof(status));
1443 res = 0;
1444 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1445 goto out; /* Is this right? */
1446 case '5':
1447 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1448 if (option_verbose > 2)
1449 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
1450 opt_args[OPT_ARG_PRIVACY], privcid);
1451 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
1452 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1453 res=0;
1454 goto out;
1455 } /* if not privacy, then 5 is the same as "default" case */
1456 default: /* bad input or -1 if failure to start autoservice */
1457 /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */
1458 /* well, there seems basically two choices. Just patch the caller thru immediately,
1459 or,... put 'em thru to voicemail. */
1460 /* since the callee may have hung up, let's do the voicemail thing, no database decision */
1461 ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
1462 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1463 res=0;
1464 goto out;
1467 /* XXX once again, this path is only taken in the case '1', so it could be
1468 * moved there, although i am not really sure that this is correct - maybe
1469 * the check applies to other cases as well.
1471 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
1472 just clog things up, and it's not useful information, not being tied to a CID */
1473 if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) {
1474 ast_filedelete(privintro, NULL);
1475 if( ast_fileexists(privintro, NULL, NULL ) > 0 )
1476 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", privintro);
1477 else if (option_verbose > 2)
1478 ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1481 if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
1482 res = 0;
1483 } else {
1484 int digit = 0;
1485 /* Start autoservice on the other chan */
1486 res = ast_autoservice_start(chan);
1487 /* Now Stream the File */
1488 if (!res)
1489 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
1490 if (!res) {
1491 digit = ast_waitstream(peer, AST_DIGIT_ANY);
1493 /* Ok, done. stop autoservice */
1494 res = ast_autoservice_stop(chan);
1495 if (digit > 0 && !res)
1496 res = ast_senddigit(chan, digit);
1497 else
1498 res = digit;
1502 if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
1503 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
1504 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
1505 ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
1506 peer->priority++;
1507 ast_pbx_start(peer);
1508 hanguptree(outgoing, NULL);
1509 if (continue_exec)
1510 *continue_exec = 1;
1511 res = 0;
1512 goto done;
1515 if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
1516 struct ast_app *theapp;
1517 const char *macro_result;
1519 res = ast_autoservice_start(chan);
1520 if (res) {
1521 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1522 res = -1;
1525 theapp = pbx_findapp("Macro");
1527 if (theapp && !res) { /* XXX why check res here ? */
1528 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
1529 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
1530 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1531 res = 0;
1532 } else {
1533 ast_log(LOG_ERROR, "Could not find application Macro\n");
1534 res = -1;
1537 if (ast_autoservice_stop(chan) < 0) {
1538 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1539 res = -1;
1542 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1543 char *macro_transfer_dest;
1545 if (!strcasecmp(macro_result, "BUSY")) {
1546 ast_copy_string(status, macro_result, sizeof(status));
1547 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1548 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1549 ast_set_flag(peerflags, OPT_GO_ON);
1551 } else
1552 ast_set_flag(peerflags, OPT_GO_ON);
1553 res = -1;
1554 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1555 ast_copy_string(status, macro_result, sizeof(status));
1556 ast_set_flag(peerflags, OPT_GO_ON);
1557 res = -1;
1558 } else if (!strcasecmp(macro_result, "CONTINUE")) {
1559 /* hangup peer and keep chan alive assuming the macro has changed
1560 the context / exten / priority or perhaps
1561 the next priority in the current exten is desired.
1563 ast_set_flag(peerflags, OPT_GO_ON);
1564 res = -1;
1565 } else if (!strcasecmp(macro_result, "ABORT")) {
1566 /* Hangup both ends unless the caller has the g flag */
1567 res = -1;
1568 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1569 res = -1;
1570 /* perform a transfer to a new extension */
1571 if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
1572 replace_macro_delimiter(macro_transfer_dest);
1573 if (!ast_parseable_goto(chan, macro_transfer_dest))
1574 ast_set_flag(peerflags, OPT_GO_ON);
1581 if (!res) {
1582 if (calldurationlimit > 0) {
1583 peer->whentohangup = time(NULL) + calldurationlimit;
1585 if (!ast_strlen_zero(dtmfcalled)) {
1586 if (option_verbose > 2)
1587 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
1588 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1590 if (!ast_strlen_zero(dtmfcalling)) {
1591 if (option_verbose > 2)
1592 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
1593 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1597 if (!res) {
1598 struct ast_bridge_config config;
1600 memset(&config,0,sizeof(struct ast_bridge_config));
1601 if (play_to_caller)
1602 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1603 if (play_to_callee)
1604 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1605 if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1606 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1607 if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1608 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1609 if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1610 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1611 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1612 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1613 if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1614 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1615 if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1616 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1617 if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1618 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
1619 if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1620 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
1622 config.timelimit = timelimit;
1623 config.play_warning = play_warning;
1624 config.warning_freq = warning_freq;
1625 config.warning_sound = warning_sound;
1626 config.end_sound = end_sound;
1627 config.start_sound = start_sound;
1628 if (moh) {
1629 moh = 0;
1630 ast_moh_stop(chan);
1631 } else if (sentringing) {
1632 sentringing = 0;
1633 ast_indicate(chan, -1);
1635 /* Be sure no generators are left on it */
1636 ast_deactivate_generator(chan);
1637 /* Make sure channels are compatible */
1638 res = ast_channel_make_compatible(chan, peer);
1639 if (res < 0) {
1640 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1641 ast_hangup(peer);
1642 res = -1;
1643 goto done;
1645 if (opermode && (!strncmp(chan->name,"Zap",3)) &&
1646 (!strncmp(peer->name,"Zap",3)))
1648 struct oprmode oprmode;
1650 oprmode.peer = peer;
1651 oprmode.mode = opermode;
1653 ast_channel_setoption(chan,
1654 AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
1656 res = ast_bridge_call(chan,peer,&config);
1657 time(&end_time);
1659 char toast[80];
1660 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1661 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1663 } else {
1664 time(&end_time);
1665 res = -1;
1668 char toast[80];
1669 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1670 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1673 if (res != AST_PBX_NO_HANGUP_PEER) {
1674 if (!chan->_softhangup)
1675 chan->hangupcause = peer->hangupcause;
1676 ast_hangup(peer);
1679 out:
1680 if (moh) {
1681 moh = 0;
1682 ast_moh_stop(chan);
1683 } else if (sentringing) {
1684 sentringing = 0;
1685 ast_indicate(chan, -1);
1687 ast_rtp_early_bridge(chan, NULL);
1688 hanguptree(outgoing, NULL);
1689 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1690 if (option_debug)
1691 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1693 if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE)) {
1694 if (calldurationlimit)
1695 chan->whentohangup = 0;
1696 res = 0;
1699 done:
1700 ast_module_user_remove(u);
1701 return res;
1704 static int dial_exec(struct ast_channel *chan, void *data)
1706 struct ast_flags peerflags;
1708 memset(&peerflags, 0, sizeof(peerflags));
1710 return dial_exec_full(chan, data, &peerflags, NULL);
1713 static int retrydial_exec(struct ast_channel *chan, void *data)
1715 char *announce = NULL, *dialdata = NULL;
1716 const char *context = NULL;
1717 int sleep = 0, loops = 0, res = -1;
1718 struct ast_module_user *u;
1719 struct ast_flags peerflags;
1721 if (ast_strlen_zero(data)) {
1722 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
1723 return -1;
1726 u = ast_module_user_add(chan);
1728 announce = ast_strdupa(data);
1730 memset(&peerflags, 0, sizeof(peerflags));
1732 if ((dialdata = strchr(announce, '|'))) {
1733 *dialdata++ = '\0';
1734 if (sscanf(dialdata, "%d", &sleep) == 1) {
1735 sleep *= 1000;
1736 } else {
1737 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1738 goto done;
1740 if ((dialdata = strchr(dialdata, '|'))) {
1741 *dialdata++ = '\0';
1742 if (sscanf(dialdata, "%d", &loops) != 1) {
1743 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1744 goto done;
1749 if ((dialdata = strchr(dialdata, '|'))) {
1750 *dialdata++ = '\0';
1751 } else {
1752 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1753 goto done;
1756 if (sleep < 1000)
1757 sleep = 10000;
1759 if (!loops)
1760 loops = -1; /* run forever */
1762 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1764 res = 0;
1765 while (loops) {
1766 int continue_exec;
1768 chan->data = "Retrying";
1769 if (ast_test_flag(chan, AST_FLAG_MOH))
1770 ast_moh_stop(chan);
1772 res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec);
1773 if (continue_exec)
1774 break;
1776 if (res == 0) {
1777 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
1778 if (!ast_strlen_zero(announce)) {
1779 if (ast_fileexists(announce, NULL, chan->language) > 0) {
1780 if(!(res = ast_streamfile(chan, announce, chan->language)))
1781 ast_waitstream(chan, AST_DIGIT_ANY);
1782 } else
1783 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
1785 if (!res && sleep) {
1786 if (!ast_test_flag(chan, AST_FLAG_MOH))
1787 ast_moh_start(chan, NULL, NULL);
1788 res = ast_waitfordigit(chan, sleep);
1790 } else {
1791 if (!ast_strlen_zero(announce)) {
1792 if (ast_fileexists(announce, NULL, chan->language) > 0) {
1793 if (!(res = ast_streamfile(chan, announce, chan->language)))
1794 res = ast_waitstream(chan, "");
1795 } else
1796 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
1798 if (sleep) {
1799 if (!ast_test_flag(chan, AST_FLAG_MOH))
1800 ast_moh_start(chan, NULL, NULL);
1801 if (!res)
1802 res = ast_waitfordigit(chan, sleep);
1807 if (res < 0)
1808 break;
1809 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1810 if (onedigit_goto(chan, context, (char) res, 1)) {
1811 res = 0;
1812 break;
1815 loops--;
1817 if (loops == 0)
1818 res = 0;
1819 else if (res == 1)
1820 res = 0;
1822 if (ast_test_flag(chan, AST_FLAG_MOH))
1823 ast_moh_stop(chan);
1824 done:
1825 ast_module_user_remove(u);
1826 return res;
1829 static int unload_module(void)
1831 int res;
1833 res = ast_unregister_application(app);
1834 res |= ast_unregister_application(rapp);
1836 ast_module_user_hangup_all();
1838 return res;
1841 static int load_module(void)
1843 int res;
1845 res = ast_register_application(app, dial_exec, synopsis, descrip);
1846 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1848 return res;
1851 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");