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.
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
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39 #include <sys/signal.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 applicaiton 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"
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"
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\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"
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\n"
97 " A(x) - Play an announcement to the called party, using 'x' as the file.\n"
98 " C - Reset the CDR for this call.\n"
99 " d - Allow the calling user to dial a 1 digit extension while waiting for\n"
100 " a call to be answered. Exit to that extension if it exists in the\n"
101 " current context, or the context defined in the EXITCONTEXT variable,\n"
103 " D([called][:calling]) - Send the specified DTMF strings *after* the called\n"
104 " party has answered, but before the call gets bridged. The 'called'\n"
105 " DTMF string is sent to the called party, and the 'calling' DTMF\n"
106 " string is sent to the calling party. Both parameters can be used\n"
108 " f - Force the callerid of the *calling* channel to be set as the\n"
109 " extension associated with the channel using a dialplan 'hint'.\n"
110 " For example, some PSTNs do not allow CallerID to be set to anything\n"
111 " other than the number assigned to the caller.\n"
112 " g - Proceed with dialplan execution at the current extension if the\n"
113 " destination channel hangs up.\n"
114 " G(context^exten^pri) - If the call is answered, transfer the calling party to\n"
115 " the specified priority and the called party to the specified priority+1.\n"
116 " Optionally, an extension, or extension and context may be specified. \n"
117 " Otherwise, the current extension is used. You cannot use any additional\n"
118 " action post answer options in conjunction with this option.\n"
119 " h - Allow the called party to hang up by sending the '*' DTMF digit.\n"
120 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
121 " i - Asterisk will ignore any forwarding requests it may receive on this\n"
123 " j - Jump to priority n+101 if all of the requested channels were busy.\n"
124 " L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
125 " left. Repeat the warning every 'z' ms. The following special\n"
126 " variables can be used with this option:\n"
127 " * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
128 " Play sounds to the caller.\n"
129 " * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
130 " Play sounds to the callee.\n"
131 " * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
132 " * LIMIT_CONNECT_FILE File to play when call begins.\n"
133 " * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
134 " The default is to say the time remaining.\n"
135 " m([class]) - Provide hold music to the calling party until a requested\n"
136 " channel answers. A specific MusicOnHold class can be\n"
138 " M(x[^arg]) - Execute the Macro for the *called* channel before connecting\n"
139 " to the calling channel. Arguments can be specified to the Macro\n"
140 " using '^' as a delimeter. The Macro can set the variable\n"
141 " MACRO_RESULT to specify the following actions after the Macro is\n"
142 " finished executing.\n"
143 " * ABORT Hangup both legs of the call.\n"
144 " * CONGESTION Behave as if line congestion was encountered.\n"
145 " * BUSY Behave as if a busy signal was encountered. This will also\n"
146 " have the application jump to priority n+101 if the\n"
147 " 'j' option is set.\n"
148 " * CONTINUE Hangup the called party and allow the calling party\n"
149 " to continue dialplan execution at the next priority.\n"
150 " * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
151 " specified priority. Optionally, an extension, or\n"
152 " extension and priority can be specified.\n"
153 " You cannot use any additional action post answer options in conjunction\n"
154 " with this option. Also, pbx services are not run on the peer (called) channel,\n"
155 " so you will not be able to set timeouts via the TIMEOUT() function in this macro.\n"
156 " n - This option is a modifier for the screen/privacy mode. It specifies\n"
157 " that no introductions are to be saved in the priv-callerintros\n"
159 " N - This option is a modifier for the screen/privacy mode. It specifies\n"
160 " that if callerID is present, do not screen the call.\n"
161 " o - Specify that the CallerID that was present on the *calling* channel\n"
162 " be set as the CallerID on the *called* channel. This was the\n"
163 " behavior of Asterisk 1.0 and earlier.\n"
164 " O([x]) - \"Operator Services\" mode (Zaptel channel to Zaptel channel\n"
165 " only, if specified on non-Zaptel interface, it will be ignored).\n"
166 " When the destination answers (presumably an operator services\n"
167 " station), the originator no longer has control of their line.\n"
168 " They may hang up, but the switch will not release their line\n"
169 " until the destination party hangs up (the operator). Specified\n"
170 " without an arg, or with 1 as an arg, the originator hanging up\n"
171 " will cause the phone to ring back immediately. With a 2 specified,\n"
172 " when the \"operator\" flashes the trunk, it will ring their phone\n"
174 " p - This option enables screening mode. This is basically Privacy mode\n"
176 " P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if\n"
177 " it is provided. The current extension is used if a database\n"
178 " family/key is not specified.\n"
179 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
180 " party until the called channel has answered.\n"
181 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
182 " answered the call.\n"
183 " t - Allow the called party to transfer the calling party by sending the\n"
184 " DTMF sequence defined in features.conf.\n"
185 " T - Allow the calling party to transfer the called party by sending the\n"
186 " DTMF sequence defined in features.conf.\n"
187 " w - Allow the called party to enable recording of the call by sending\n"
188 " the DTMF sequence defined for one-touch recording in features.conf.\n"
189 " W - Allow the calling party to enable recording of the call by sending\n"
190 " the DTMF sequence defined for one-touch recording in features.conf.\n"
191 " k - Allow the called party to enable parking of the call by sending\n"
192 " the DTMF sequence defined for call parking in features.conf.\n"
193 " K - Allow the calling party to enable parking of the call by sending\n"
194 " the DTMF sequence defined for call parking in features.conf.\n";
196 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
197 static char *rapp = "RetryDial";
198 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
199 static char *rdescrip =
200 " RetryDial(announce|sleep|retries|dialargs): This application will attempt to\n"
201 "place a call using the normal Dial application. If no channel can be reached,\n"
202 "the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
203 "seconds before retying the call. After 'retires' number of attempts, the\n"
204 "calling channel will continue at the next priority in the dialplan. If the\n"
205 "'retries' setting is set to 0, this application will retry endlessly.\n"
206 " While waiting to retry a call, a 1 digit extension may be dialed. If that\n"
207 "extension exists in either the context defined in ${EXITCONTEXT} or the current\n"
208 "one, The call will jump to that extension immediately.\n"
209 " The 'dialargs' are specified in the same format that arguments are provided\n"
210 "to the Dial application.\n";
213 OPT_ANNOUNCE = (1 << 0),
214 OPT_RESETCDR = (1 << 1),
215 OPT_DTMF_EXIT = (1 << 2),
216 OPT_SENDDTMF = (1 << 3),
217 OPT_FORCECLID = (1 << 4),
218 OPT_GO_ON = (1 << 5),
219 OPT_CALLEE_HANGUP = (1 << 6),
220 OPT_CALLER_HANGUP = (1 << 7),
221 OPT_PRIORITY_JUMP = (1 << 8),
222 OPT_DURATION_LIMIT = (1 << 9),
223 OPT_MUSICBACK = (1 << 10),
224 OPT_CALLEE_MACRO = (1 << 11),
225 OPT_SCREEN_NOINTRO = (1 << 12),
226 OPT_SCREEN_NOCLID = (1 << 13),
227 OPT_ORIGINAL_CLID = (1 << 14),
228 OPT_SCREENING = (1 << 15),
229 OPT_PRIVACY = (1 << 16),
230 OPT_RINGBACK = (1 << 17),
231 OPT_DURATION_STOP = (1 << 18),
232 OPT_CALLEE_TRANSFER = (1 << 19),
233 OPT_CALLER_TRANSFER = (1 << 20),
234 OPT_CALLEE_MONITOR = (1 << 21),
235 OPT_CALLER_MONITOR = (1 << 22),
236 OPT_GOTO = (1 << 23),
237 OPT_OPERMODE = (1 << 24),
238 OPT_CALLEE_PARK = (1 << 25),
239 OPT_CALLER_PARK = (1 << 26),
240 OPT_IGNORE_FORWARDING = (1 << 27),
241 } dial_exec_option_flags;
243 #define DIAL_STILLGOING (1 << 30)
244 #define DIAL_NOFORWARDHTML (1 << 31)
247 OPT_ARG_ANNOUNCE = 0,
250 OPT_ARG_DURATION_LIMIT,
252 OPT_ARG_CALLEE_MACRO,
254 OPT_ARG_DURATION_STOP,
256 /* note: this entry _MUST_ be the last one in the enum */
258 } dial_exec_option_args;
260 AST_APP_OPTIONS(dial_exec_options, {
261 AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
262 AST_APP_OPTION('C', OPT_RESETCDR),
263 AST_APP_OPTION('d', OPT_DTMF_EXIT),
264 AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
265 AST_APP_OPTION('f', OPT_FORCECLID),
266 AST_APP_OPTION('g', OPT_GO_ON),
267 AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
268 AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
269 AST_APP_OPTION('H', OPT_CALLER_HANGUP),
270 AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
271 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
272 AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
273 AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
274 AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
275 AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
276 AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
277 AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
278 AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
279 AST_APP_OPTION('p', OPT_SCREENING),
280 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
281 AST_APP_OPTION('r', OPT_RINGBACK),
282 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
283 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
284 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
285 AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
286 AST_APP_OPTION('W', OPT_CALLER_MONITOR),
287 AST_APP_OPTION('k', OPT_CALLEE_PARK),
288 AST_APP_OPTION('K', OPT_CALLER_PARK),
291 /* We define a custom "local user" structure because we
292 use it not only for keeping track of what is in use but
293 also for keeping track of who we're dialing. */
295 struct dial_localuser {
296 struct ast_channel *chan;
299 struct dial_localuser *next;
303 static void hanguptree(struct dial_localuser *outgoing, struct ast_channel *exception)
305 /* Hang up a tree of stuff */
306 struct dial_localuser *oo;
308 /* Hangup any existing lines we have open */
309 if (outgoing->chan && (outgoing->chan != exception))
310 ast_hangup(outgoing->chan);
312 outgoing=outgoing->next;
317 #define AST_MAX_FORWARDS 8
319 #define AST_MAX_WATCHERS 256
322 * argument to handle_cause() and other functions.
325 struct ast_channel *chan;
331 static void handle_cause(int cause, struct cause_args *num)
333 struct ast_cdr *cdr = num->chan->cdr;
342 case AST_CAUSE_CONGESTION:
348 case AST_CAUSE_UNREGISTERED:
354 case AST_CAUSE_NORMAL_CLEARING:
363 /* free the buffer if allocated, and set the pointer to the second arg */
364 #define S_REPLACE(s, new_val) \
371 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
373 char rexten[2] = { exten, '\0' };
376 if (!ast_goto_if_exists(chan, context, rexten, pri))
379 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
381 else if (!ast_strlen_zero(chan->macrocontext)) {
382 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
390 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
392 const char *context = S_OR(chan->macrocontext, chan->context);
393 const char *exten = S_OR(chan->macroexten, chan->exten);
395 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
398 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
400 manager_event(EVENT_FLAG_CALL, "Dial",
401 "SubEvent: Begin\r\n"
403 "Destination: %s\r\n"
404 "CallerIDNum: %s\r\n"
405 "CallerIDName: %s\r\n"
406 "SrcUniqueID: %s\r\n"
407 "DestUniqueID: %s\r\n",
408 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
409 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
413 static void senddialendevent(const struct ast_channel *src, const char *dialstatus)
415 manager_event(EVENT_FLAG_CALL, "Dial",
418 "DialStatus: %s\r\n",
419 src->name, dialstatus);
422 /* helper function for wait_for_answer() */
423 static void do_forward(struct dial_localuser *o,
424 struct cause_args *num, struct ast_flags *peerflags, int single)
427 struct ast_channel *c = o->chan; /* the winner */
428 struct ast_channel *in = num->chan; /* the input channel */
433 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
434 if ((stuff = strchr(tmpchan, '/'))) {
438 const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
439 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
443 /* Before processing channel, go ahead and check for forwarding */
445 if (o->forwards < AST_MAX_FORWARDS) {
446 if (option_verbose > 2)
447 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
448 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
449 if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
450 if (option_verbose > 2)
451 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
453 cause = AST_CAUSE_BUSY;
455 /* Setup parameters */
456 c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
458 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
460 ast_channel_inherit_variables(in, o->chan);
463 if (option_verbose > 2)
464 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
465 cause = AST_CAUSE_CONGESTION;
469 ast_clear_flag(o, DIAL_STILLGOING);
470 handle_cause(cause, num);
472 char *new_cid_num, *new_cid_name;
473 struct ast_channel *src;
475 ast_rtp_make_compatible(c, in, single);
476 if (ast_test_flag(o, OPT_FORCECLID)) {
477 new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
478 new_cid_name = NULL; /* XXX no name ? */
479 src = c; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
481 new_cid_num = ast_strdup(in->cid.cid_num);
482 new_cid_name = ast_strdup(in->cid.cid_name);
485 ast_string_field_set(c, accountcode, src->accountcode);
486 c->cdrflags = src->cdrflags;
487 S_REPLACE(c->cid.cid_num, new_cid_num);
488 S_REPLACE(c->cid.cid_name, new_cid_name);
490 if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
491 S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
493 S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
494 if (ast_call(c, tmpchan, 0)) {
495 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
496 ast_clear_flag(o, DIAL_STILLGOING);
501 senddialevent(in, c);
502 /* After calling, set callerid to extension */
503 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
504 char cidname[AST_MAX_EXTENSION];
505 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
509 /* Hangup the original channel now, in case we needed it */
513 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,
514 const struct cause_args *num_in, int priority_jump, int *result)
516 struct cause_args num = *num_in;
517 int prestart = num.busy + num.congestion + num.nochan;
519 struct ast_channel *peer = NULL;
520 /* single is set if only one destination is enabled */
521 int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
524 /* Turn off hold music, etc */
525 ast_deactivate_generator(in);
526 /* If we are calling a single channel, make them compatible for in-band tone purpose */
527 ast_channel_make_compatible(outgoing->chan, in);
531 while (*to && !peer) {
532 struct dial_localuser *o;
533 int pos = 0; /* how many channels do we handle */
534 int numlines = prestart;
535 struct ast_channel *winner;
536 struct ast_channel *watchers[AST_MAX_WATCHERS];
538 watchers[pos++] = in;
539 for (o = outgoing; o; o = o->next) {
540 /* Keep track of important channels */
541 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan)
542 watchers[pos++] = o->chan;
545 if (pos == 1) { /* only the input channel is available */
546 if (numlines == (num.busy + num.congestion + num.nochan)) {
547 if (option_verbose > 2)
548 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
550 strcpy(status, "BUSY");
551 else if (num.congestion)
552 strcpy(status, "CONGESTION");
554 strcpy(status, "CHANUNAVAIL");
555 if (ast_opt_priority_jumping || priority_jump)
556 ast_goto_if_exists(in, in->context, in->exten, in->priority + 101);
558 if (option_verbose > 2)
559 ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
564 winner = ast_waitfor_n(watchers, pos, to);
565 for (o = outgoing; o; o = o->next) {
567 struct ast_channel *c = o->chan;
571 if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
573 if (option_verbose > 2)
574 ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
576 ast_copy_flags(peerflags, o,
577 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
578 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
579 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
580 OPT_CALLEE_PARK | OPT_CALLER_PARK |
582 ast_copy_string(c->context, "", sizeof(c->context));
583 ast_copy_string(c->exten, "", sizeof(c->exten));
589 /* here, o->chan == c == winner */
590 if (!ast_strlen_zero(c->call_forward)) {
591 do_forward(o, &num, peerflags, single);
594 f = ast_read(winner);
596 in->hangupcause = c->hangupcause;
599 ast_clear_flag(o, DIAL_STILLGOING);
600 handle_cause(in->hangupcause, &num);
603 if (f->frametype == AST_FRAME_CONTROL) {
604 switch(f->subclass) {
605 case AST_CONTROL_ANSWER:
606 /* This is our guy if someone answered. */
608 if (option_verbose > 2)
609 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
611 ast_copy_flags(peerflags, o,
612 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
613 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
614 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
615 OPT_CALLEE_PARK | OPT_CALLER_PARK |
617 ast_copy_string(c->context, "", sizeof(c->context));
618 ast_copy_string(c->exten, "", sizeof(c->exten));
619 /* Setup early bridge if appropriate */
620 ast_channel_early_bridge(in, peer);
622 /* If call has been answered, then the eventual hangup is likely to be normal hangup */
623 in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
624 c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
626 case AST_CONTROL_BUSY:
627 if (option_verbose > 2)
628 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name);
629 in->hangupcause = c->hangupcause;
632 ast_clear_flag(o, DIAL_STILLGOING);
633 handle_cause(AST_CAUSE_BUSY, &num);
635 case AST_CONTROL_CONGESTION:
636 if (option_verbose > 2)
637 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name);
638 in->hangupcause = c->hangupcause;
641 ast_clear_flag(o, DIAL_STILLGOING);
642 handle_cause(AST_CAUSE_CONGESTION, &num);
644 case AST_CONTROL_RINGING:
645 if (option_verbose > 2)
646 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
647 /* Setup early media if appropriate */
649 ast_channel_early_bridge(in, c);
650 if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
651 ast_indicate(in, AST_CONTROL_RINGING);
655 case AST_CONTROL_PROGRESS:
656 if (option_verbose > 2)
657 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name);
658 /* Setup early media if appropriate */
660 ast_channel_early_bridge(in, c);
661 if (!ast_test_flag(outgoing, OPT_RINGBACK))
662 ast_indicate(in, AST_CONTROL_PROGRESS);
664 case AST_CONTROL_VIDUPDATE:
665 if (option_verbose > 2)
666 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name);
667 ast_indicate(in, AST_CONTROL_VIDUPDATE);
669 case AST_CONTROL_PROCEEDING:
670 if (option_verbose > 2)
671 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
673 ast_channel_early_bridge(in, c);
674 if (!ast_test_flag(outgoing, OPT_RINGBACK))
675 ast_indicate(in, AST_CONTROL_PROCEEDING);
677 case AST_CONTROL_HOLD:
678 if (option_verbose > 2)
679 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name);
680 ast_indicate(in, AST_CONTROL_HOLD);
682 case AST_CONTROL_UNHOLD:
683 if (option_verbose > 2)
684 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name);
685 ast_indicate(in, AST_CONTROL_UNHOLD);
687 case AST_CONTROL_OFFHOOK:
688 case AST_CONTROL_FLASH:
689 /* Ignore going off hook and flash */
692 if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
693 if (option_verbose > 2)
694 ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
695 ast_indicate(in, -1);
701 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
704 /* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */
705 if (f->frametype == AST_FRAME_VOICE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
706 if (ast_write(in, f))
707 ast_log(LOG_WARNING, "Unable to forward voice frame\n");
708 } else if (f->frametype == AST_FRAME_IMAGE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
709 if (ast_write(in, f))
710 ast_log(LOG_WARNING, "Unable to forward image\n");
711 } else if (f->frametype == AST_FRAME_TEXT && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
712 if (ast_write(in, f))
713 ast_log(LOG_WARNING, "Unable to send text\n");
714 } else if (f->frametype == AST_FRAME_HTML && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) {
715 if (ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1)
716 ast_log(LOG_WARNING, "Unable to send URL\n");
722 struct ast_frame *f = ast_read(in);
724 if (f && (f->frametype != AST_FRAME_VOICE))
725 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
726 else if (!f || (f->frametype != AST_FRAME_VOICE))
727 printf("Hangup received on %s\n", in->name);
729 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
732 strcpy(status, "CANCEL");
738 /* now f is guaranteed non-NULL */
739 if (f->frametype == AST_FRAME_DTMF) {
740 if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
741 const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
742 if (onedigit_goto(in, context, (char) f->subclass, 1)) {
743 if (option_verbose > 2)
744 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
746 *result = f->subclass;
747 strcpy(status, "CANCEL");
753 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) &&
754 (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
755 if (option_verbose > 2)
756 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
758 strcpy(status, "CANCEL");
764 /* Forward HTML stuff */
765 if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
766 if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
767 ast_log(LOG_WARNING, "Unable to send URL\n");
770 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
771 if (ast_write(outgoing->chan, f))
772 ast_log(LOG_WARNING, "Unable to forward voice\n");
774 if (single && (f->frametype == AST_FRAME_CONTROL) &&
775 ((f->subclass == AST_CONTROL_HOLD) ||
776 (f->subclass == AST_CONTROL_UNHOLD) ||
777 (f->subclass == AST_CONTROL_VIDUPDATE))) {
778 if (option_verbose > 2)
779 ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
780 ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
784 if (!*to && (option_verbose > 2))
785 ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
791 static void replace_macro_delimiter(char *s)
799 /* returns true if there is a valid privacy reply */
800 static int valid_priv_reply(struct ast_flags *opts, int res)
804 if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5')
806 if (ast_test_flag(opts, OPT_SCREENING) && res <= '4')
811 static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
812 char *parse, unsigned int *calldurationlimit)
814 char *limit_str, *warning_str, *warnfreq_str;
816 int play_to_caller=0,play_to_callee=0;
819 limit_str = strsep(&warnfreq_str, ":");
820 warning_str = strsep(&warnfreq_str, ":");
821 warnfreq_str = parse;
823 config->timelimit = atol(limit_str);
825 config->play_warning = atol(warning_str);
827 config->warning_freq = atol(warnfreq_str);
829 if (!config->timelimit) {
830 ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
831 config->timelimit = config->play_warning = config->warning_freq = 0;
832 config->warning_sound = NULL;
833 return -1; /* error */
834 } else if ( (delta = config->play_warning - config->timelimit) > 0) {
835 int w = config->warning_freq;
837 /* If the first warning is requested _after_ the entire call would end,
838 and no warning frequency is requested, then turn off the warning. If
839 a warning frequency is requested, reduce the 'first warning' time by
840 that frequency until it falls within the call's total time limit.
842 timelim->| delta |<-playwarning
843 0__________________|_________________|
846 so the number of intervals to cut is 1+(delta-1)/w
850 config->play_warning = 0;
852 config->play_warning -= w * ( 1 + (delta-1)/w );
853 if (config->play_warning < 1)
854 config->play_warning = config->warning_freq = 0;
858 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
859 play_to_caller = var ? ast_true(var) : 1;
861 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
862 play_to_callee = var ? ast_true(var) : 0;
864 if (!play_to_caller && !play_to_callee)
867 var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
868 config->warning_sound = S_OR(var, "timeleft");
870 /* The code looking at config wants a NULL, not just "", to decide
871 * that the message should not be played, so we replace "" with NULL.
872 * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
875 var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
876 config->end_sound = S_OR(var, NULL);
877 var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
878 config->start_sound = S_OR(var, NULL);
880 /* undo effect of S(x) in case they are both used */
881 *calldurationlimit = 0;
882 /* more efficient to do it like S(x) does since no advanced opts */
883 if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
884 *calldurationlimit = config->timelimit / 1000;
885 if (option_verbose > 2)
886 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",
888 config->timelimit = play_to_caller = play_to_callee =
889 config->play_warning = config->warning_freq = 0;
890 } else if (option_verbose > 2) {
891 ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
892 ast_verbose(VERBOSE_PREFIX_4 "timelimit = %ld\n", config->timelimit);
893 ast_verbose(VERBOSE_PREFIX_4 "play_warning = %ld\n", config->play_warning);
894 ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
895 ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
896 ast_verbose(VERBOSE_PREFIX_4 "warning_freq = %ld\n", config->warning_freq);
897 ast_verbose(VERBOSE_PREFIX_4 "start_sound = %s\n", S_OR(config->start_sound, ""));
898 ast_verbose(VERBOSE_PREFIX_4 "warning_sound = %s\n", config->warning_sound);
899 ast_verbose(VERBOSE_PREFIX_4 "end_sound = %s\n", S_OR(config->end_sound, ""));
902 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
904 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
908 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags)
910 int res = -1; /* default: error */
911 struct ast_module_user *u;
912 char *rest, *cur; /* scan the list of destinations */
913 struct dial_localuser *outgoing = NULL; /* list of destinations */
914 struct ast_channel *peer;
915 int to; /* timeout */
916 struct cause_args num = { chan, 0, 0, 0 };
918 char numsubst[AST_MAX_EXTENSION];
919 char cidname[AST_MAX_EXTENSION];
922 struct ast_bridge_config config;
923 unsigned int calldurationlimit = 0;
924 char *dtmfcalled = NULL, *dtmfcalling = NULL;
926 int sentringing = 0, moh = 0;
927 const char *outbound_group = NULL;
930 char privintro[1024];
934 AST_DECLARE_APP_ARGS(args,
936 AST_APP_ARG(timeout);
937 AST_APP_ARG(options);
940 struct ast_flags opts = { 0, };
941 char *opt_args[OPT_ARG_ARRAY_SIZE];
943 if (ast_strlen_zero(data)) {
944 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
948 u = ast_module_user_add(chan); /* XXX is this the right place ? */
950 parse = ast_strdupa(data);
952 AST_STANDARD_APP_ARGS(args, parse);
954 memset(&config,0,sizeof(struct ast_bridge_config));
956 if (!ast_strlen_zero(args.options) &&
957 ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options))
960 if (ast_strlen_zero(args.peers)) {
961 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
965 if (ast_test_flag(&opts, OPT_OPERMODE)) {
966 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
967 if (option_verbose > 2)
968 ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
971 if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
972 calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
973 if (!calldurationlimit) {
974 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
977 if (option_verbose > 2)
978 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
981 if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
982 dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
983 dtmfcalled = strsep(&dtmfcalling, ":");
986 if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
987 if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
991 if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
992 ast_cdr_reset(chan->cdr, NULL);
993 if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
994 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
995 if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) {
997 char *l = chan->cid.cid_num; /* XXX watch out, we are overwriting it */
998 if (!ast_strlen_zero(l)) {
999 ast_shrink_phone_number(l);
1000 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1001 if (option_verbose > 2)
1002 ast_verbose(VERBOSE_PREFIX_3 "Privacy DB is '%s', clid is '%s'\n",
1003 opt_args[OPT_ARG_PRIVACY], l);
1004 privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
1007 if (option_verbose > 2)
1008 ast_verbose(VERBOSE_PREFIX_3 "Privacy Screening, clid is '%s'\n", l);
1009 privdb_val = AST_PRIVACY_UNKNOWN;
1014 tnam = ast_strdupa(chan->name);
1015 /* clean the channel name so slashes don't try to end up in disk file name */
1016 for(tn2 = tnam; *tn2; tn2++) {
1018 *tn2 = '='; /* any other chars to be afraid of? */
1020 if (option_verbose > 2)
1021 ast_verbose(VERBOSE_PREFIX_3 "Privacy-- callerid is empty\n");
1023 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
1025 privdb_val = AST_PRIVACY_UNKNOWN;
1028 ast_copy_string(privcid,l,sizeof(privcid));
1030 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 */
1031 if (option_verbose > 2)
1032 ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", privcid);
1033 privdb_val = AST_PRIVACY_ALLOW;
1035 else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) {
1036 if (option_verbose > 2)
1037 ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
1040 if(privdb_val == AST_PRIVACY_DENY ) {
1041 ast_copy_string(status, "NOANSWER", sizeof(status));
1042 if (option_verbose > 2)
1043 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1047 else if(privdb_val == AST_PRIVACY_KILL ) {
1048 ast_copy_string(status, "DONTCALL", sizeof(status));
1049 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1050 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1053 goto out; /* Is this right? */
1055 else if(privdb_val == AST_PRIVACY_TORTURE ) {
1056 ast_copy_string(status, "TORTURE", sizeof(status));
1057 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1058 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1061 goto out; /* is this right??? */
1063 else if(privdb_val == AST_PRIVACY_UNKNOWN ) {
1064 /* Get the user's intro, store it in priv-callerintros/$CID,
1065 unless it is already there-- this should be done before the
1066 call is actually dialed */
1068 /* make sure the priv-callerintros dir actually exists */
1069 snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
1070 if (mkdir(privintro, 0755) && errno != EEXIST) {
1071 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
1076 snprintf(privintro,sizeof(privintro), "priv-callerintros/%s", privcid);
1077 if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
1078 /* the DELUX version of this code would allow this caller the
1079 option to hear and retape their previously recorded intro.
1083 int duration; /* for feedback from play_and_wait */
1084 /* the file doesn't exist yet. Let the caller submit his
1085 vocal intro for posterity */
1086 /* priv-recordintro script:
1088 "At the tone, please say your name:"
1091 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 */
1092 /* don't think we'll need a lock removed, we took care of
1093 conflicts by naming the privintro file */
1095 /* Delete the file regardless since they hung up during recording */
1096 ast_filedelete(privintro, NULL);
1097 if( ast_fileexists(privintro,NULL,NULL ) > 0 )
1098 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
1099 else if (option_verbose > 2)
1100 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1103 if( !ast_streamfile(chan, "vm-dialout", chan->language) )
1104 ast_waitstream(chan, "");
1109 /* If a channel group has been specified, get it for use when we create peer channels */
1110 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1112 ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
1113 /* loop through the list of dial destinations */
1115 while ((cur = strsep(&rest, "&")) ) {
1116 struct dial_localuser *tmp;
1117 /* Get a technology/[device:]number pair */
1119 char *tech = strsep(&number, "/");
1121 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
1124 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
1127 ast_copy_flags(tmp, &opts,
1128 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
1129 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
1130 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
1131 OPT_CALLEE_PARK | OPT_CALLER_PARK |
1132 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
1133 ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);
1135 ast_copy_string(numsubst, number, sizeof(numsubst));
1136 /* Request the peer */
1137 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1139 /* If we can't, just go on to the next call */
1140 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1141 handle_cause(cause, &num);
1142 if (!rest) /* we are on the last destination */
1143 chan->hangupcause = cause;
1146 pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
1147 if (!ast_strlen_zero(tmp->chan->call_forward)) {
1151 ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan));
1152 if ((stuff = strchr(tmpchan, '/'))) {
1156 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
1161 if (tmp->forwards < AST_MAX_FORWARDS) {
1162 if (option_verbose > 2)
1163 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1164 ast_hangup(tmp->chan);
1165 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
1166 if (ast_test_flag(&opts, OPT_IGNORE_FORWARDING)) {
1168 cause = AST_CAUSE_BUSY;
1169 if (option_verbose > 2)
1170 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", chan->name, tech, stuff);
1172 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1175 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1177 ast_channel_inherit_variables(chan, tmp->chan);
1179 if (option_verbose > 2)
1180 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
1181 ast_hangup(tmp->chan);
1183 cause = AST_CAUSE_CONGESTION;
1186 handle_cause(cause, &num);
1191 /* Setup outgoing SDP to match incoming one */
1192 ast_rtp_make_compatible(tmp->chan, chan, !outgoing && !rest);
1194 /* Inherit specially named variables from parent channel */
1195 ast_channel_inherit_variables(chan, tmp->chan);
1197 tmp->chan->appl = "AppDial";
1198 tmp->chan->data = "(Outgoing Line)";
1199 tmp->chan->whentohangup = 0;
1201 S_REPLACE(tmp->chan->cid.cid_num, ast_strdup(chan->cid.cid_num));
1202 S_REPLACE(tmp->chan->cid.cid_name, ast_strdup(chan->cid.cid_name));
1203 S_REPLACE(tmp->chan->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
1204 S_REPLACE(tmp->chan->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
1206 /* Copy language from incoming to outgoing */
1207 ast_string_field_set(tmp->chan, language, chan->language);
1208 ast_string_field_set(tmp->chan, accountcode, chan->accountcode);
1209 tmp->chan->cdrflags = chan->cdrflags;
1210 if (ast_strlen_zero(tmp->chan->musicclass))
1211 ast_string_field_set(tmp->chan, musicclass, chan->musicclass);
1212 /* Pass callingpres setting */
1213 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
1214 /* Pass type of number */
1215 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
1216 /* Pass type of tns */
1217 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
1218 /* Presense of ADSI CPE on outgoing channel follows ours */
1219 tmp->chan->adsicpe = chan->adsicpe;
1220 /* Pass the transfer capability */
1221 tmp->chan->transfercapability = chan->transfercapability;
1223 /* If we have an outbound group, set this peer channel to it */
1225 ast_app_group_set_channel(tmp->chan, outbound_group);
1227 /* Inherit context and extension */
1228 ast_copy_string(tmp->chan->context, chan->context, sizeof(tmp->chan->context));
1229 ast_copy_string(tmp->chan->exten, chan->exten, sizeof(tmp->chan->exten));
1231 /* Place the call, but don't wait on the answer */
1232 res = ast_call(tmp->chan, numsubst, 0);
1234 /* Save the info in cdr's that we called them */
1236 ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
1238 /* check the results of ast_call */
1240 /* Again, keep going even if there's an error */
1242 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1243 if (option_verbose > 2)
1244 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1245 ast_hangup(tmp->chan);
1249 senddialevent(chan, tmp->chan);
1250 if (option_verbose > 2)
1251 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1252 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
1253 ast_set_callerid(tmp->chan, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
1255 /* Put them in the list of outgoing thingies... We're ready now.
1256 XXX If we're forcibly removed, these outgoing calls won't get
1258 ast_set_flag(tmp, DIAL_STILLGOING);
1259 tmp->next = outgoing;
1261 /* If this line is up, don't try anybody else */
1262 if (outgoing->chan->_state == AST_STATE_UP)
1266 if (ast_strlen_zero(args.timeout)) {
1269 to = atoi(args.timeout);
1273 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
1277 strcpy(status, "CHANUNAVAIL");
1279 /* Our status will at least be NOANSWER */
1280 strcpy(status, "NOANSWER");
1281 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1283 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1284 } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
1285 ast_indicate(chan, AST_CONTROL_RINGING);
1291 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), &num, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
1296 } else if (to) { /* Musta gotten hung up */
1298 } else { /* Nobody answered, next please? */
1301 /* almost done, although the 'else' block is 400 lines */
1304 time_t end_time, answer_time = time(NULL);
1305 char toast[80]; /* buffer to set variables */
1307 strcpy(status, "ANSWER");
1308 /* Ah ha! Someone answered within the desired timeframe. Of course after this
1309 we will always return with -1 so that it is hung up properly after the
1311 hanguptree(outgoing, peer);
1313 /* If appropriate, log that we have a destination channel */
1315 ast_cdr_setdestchan(chan->cdr, peer->name);
1317 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1319 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1322 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1323 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
1325 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url);
1326 ast_channel_sendurl( peer, args.url );
1328 if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && privdb_val == AST_PRIVACY_UNKNOWN) {
1332 /* Get the user's intro, store it in priv-callerintros/$CID,
1333 unless it is already there-- this should be done before the
1334 call is actually dialed */
1336 /* all ring indications and moh for the caller has been halted as soon as the
1337 target extension was picked up. We are going to have to kill some
1338 time and make the caller believe the peer hasn't picked up yet */
1340 if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1341 ast_indicate(chan, -1);
1342 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1343 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1344 ast_indicate(chan, AST_CONTROL_RINGING);
1348 /* Start autoservice on the other chan ?? */
1349 res2 = ast_autoservice_start(chan);
1350 /* Now Stream the File */
1351 for (loopcount = 0; loopcount < 3; loopcount++) {
1352 if (res2 && loopcount == 0) /* error in ast_autoservice_start() */
1354 if (!res2) /* on timeout, play the message again */
1355 res2 = ast_play_and_wait(peer,"priv-callpending");
1356 if (!valid_priv_reply(&opts, res2))
1358 /* priv-callpending script:
1359 "I have a caller waiting, who introduces themselves as:"
1362 res2 = ast_play_and_wait(peer,privintro);
1363 if (!valid_priv_reply(&opts, res2))
1365 /* now get input from the called party, as to their choice */
1367 /* XXX can we have both, or they are mutually exclusive ? */
1368 if( ast_test_flag(&opts, OPT_PRIVACY) )
1369 res2 = ast_play_and_wait(peer,"priv-callee-options");
1370 if( ast_test_flag(&opts, OPT_SCREENING) )
1371 res2 = ast_play_and_wait(peer,"screen-callee-options");
1373 /*! \page DialPrivacy Dial Privacy scripts
1374 \par priv-callee-options script:
1375 "Dial 1 if you wish this caller to reach you directly in the future,
1376 and immediately connect to their incoming call
1377 Dial 2 if you wish to send this caller to voicemail now and
1379 Dial 3 to send this caller to the torture menus, now and forevermore.
1380 Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
1381 Dial 5 to allow this caller to come straight thru to you in the future,
1382 but right now, just this once, send them to voicemail."
1383 \par screen-callee-options script:
1384 "Dial 1 if you wish to immediately connect to the incoming call
1385 Dial 2 if you wish to send this caller to voicemail.
1386 Dial 3 to send this caller to the torture menus.
1387 Dial 4 to send this caller to a simple "go away" menu.
1389 if (valid_priv_reply(&opts, res2))
1391 /* invalid option */
1392 res2 = ast_play_and_wait(peer, "vm-sorry");
1395 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
1397 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1398 ast_indicate(chan, -1);
1401 ast_autoservice_stop(chan);
1405 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1406 if (option_verbose > 2)
1407 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
1408 opt_args[OPT_ARG_PRIVACY], privcid);
1409 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
1413 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1414 if (option_verbose > 2)
1415 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n",
1416 opt_args[OPT_ARG_PRIVACY], privcid);
1417 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
1419 ast_copy_string(status, "NOANSWER", sizeof(status));
1420 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1424 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1425 if (option_verbose > 2)
1426 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n",
1427 opt_args[OPT_ARG_PRIVACY], privcid);
1428 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE);
1430 ast_copy_string(status, "TORTURE", sizeof(status));
1433 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1434 goto out; /* Is this right? */
1436 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1437 if (option_verbose > 2)
1438 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n",
1439 opt_args[OPT_ARG_PRIVACY], privcid);
1440 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL);
1443 ast_copy_string(status, "DONTCALL", sizeof(status));
1445 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1446 goto out; /* Is this right? */
1448 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1449 if (option_verbose > 2)
1450 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
1451 opt_args[OPT_ARG_PRIVACY], privcid);
1452 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
1453 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1456 } /* if not privacy, then 5 is the same as "default" case */
1457 default: /* bad input or -1 if failure to start autoservice */
1458 /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */
1459 /* well, there seems basically two choices. Just patch the caller thru immediately,
1460 or,... put 'em thru to voicemail. */
1461 /* since the callee may have hung up, let's do the voicemail thing, no database decision */
1462 ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
1463 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1468 /* XXX once again, this path is only taken in the case '1', so it could be
1469 * moved there, although i am not really sure that this is correct - maybe
1470 * the check applies to other cases as well.
1472 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
1473 just clog things up, and it's not useful information, not being tied to a CID */
1474 if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) {
1475 ast_filedelete(privintro, NULL);
1476 if( ast_fileexists(privintro, NULL, NULL ) > 0 )
1477 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", privintro);
1478 else if (option_verbose > 2)
1479 ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1482 if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
1486 /* Start autoservice on the other chan */
1487 res = ast_autoservice_start(chan);
1488 /* Now Stream the File */
1490 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
1492 digit = ast_waitstream(peer, AST_DIGIT_ANY);
1494 /* Ok, done. stop autoservice */
1495 res = ast_autoservice_stop(chan);
1496 if (digit > 0 && !res)
1497 res = ast_senddigit(chan, digit);
1503 if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
1504 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
1505 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
1506 ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
1508 ast_pbx_start(peer);
1509 hanguptree(outgoing, NULL);
1514 if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
1515 struct ast_app *theapp;
1516 const char *macro_result;
1518 res = ast_autoservice_start(chan);
1520 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1524 theapp = pbx_findapp("Macro");
1526 if (theapp && !res) { /* XXX why check res here ? */
1527 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
1528 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
1530 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1533 ast_log(LOG_ERROR, "Could not find application Macro\n");
1537 if (ast_autoservice_stop(chan) < 0) {
1538 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
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);
1552 ast_set_flag(peerflags, OPT_GO_ON);
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);
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);
1565 } else if (!strcasecmp(macro_result, "ABORT")) {
1566 /* Hangup both ends unless the caller has the g flag */
1568 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
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 (calldurationlimit > 0) {
1582 chan->whentohangup = time(NULL) + calldurationlimit;
1584 if (!ast_strlen_zero(dtmfcalled)) {
1585 if (option_verbose > 2)
1586 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
1587 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1589 if (!ast_strlen_zero(dtmfcalling)) {
1590 if (option_verbose > 2)
1591 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
1592 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1596 if (res) { /* some error */
1598 end_time = time(NULL);
1600 if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1601 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1602 if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1603 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1604 if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1605 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1606 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1607 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1608 if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1609 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1610 if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1611 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1612 if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1613 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
1614 if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1615 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
1620 } else if (sentringing) {
1622 ast_indicate(chan, -1);
1624 /* Be sure no generators are left on it */
1625 ast_deactivate_generator(chan);
1626 /* Make sure channels are compatible */
1627 res = ast_channel_make_compatible(chan, peer);
1629 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1634 if (opermode && !strncmp(chan->name,"Zap",3) && !strncmp(peer->name,"Zap",3)) {
1635 /* XXX what's this special handling for Zap <-> Zap ? */
1636 struct oprmode oprmode;
1638 oprmode.peer = peer;
1639 oprmode.mode = opermode;
1641 ast_channel_setoption(chan,
1642 AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
1644 res = ast_bridge_call(chan,peer,&config);
1645 end_time = time(NULL);
1646 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1647 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1650 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1651 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1653 if (res != AST_PBX_NO_HANGUP_PEER) {
1654 if (!chan->_softhangup)
1655 chan->hangupcause = peer->hangupcause;
1663 } else if (sentringing) {
1665 ast_indicate(chan, -1);
1667 ast_channel_early_bridge(chan, NULL);
1668 hanguptree(outgoing, NULL);
1669 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1670 senddialendevent(chan, status);
1672 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1674 if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
1678 ast_module_user_remove(u); /* XXX probably not the right place for this. */
1682 static int dial_exec(struct ast_channel *chan, void *data)
1684 struct ast_flags peerflags;
1685 memset(&peerflags, 0, sizeof(peerflags));
1686 return dial_exec_full(chan, data, &peerflags);
1689 static int retrydial_exec(struct ast_channel *chan, void *data)
1691 char *announce = NULL, *dialdata = NULL;
1692 const char *context = NULL;
1693 int sleep = 0, loops = 0, res = -1;
1694 struct ast_module_user *u;
1695 struct ast_flags peerflags;
1697 if (ast_strlen_zero(data)) {
1698 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
1702 u = ast_module_user_add(chan);
1704 announce = ast_strdupa(data);
1706 memset(&peerflags, 0, sizeof(peerflags));
1708 if ((dialdata = strchr(announce, '|'))) {
1710 if ((sleep = atoi(dialdata))) {
1713 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1716 if ((dialdata = strchr(dialdata, '|'))) {
1718 if (!(loops = atoi(dialdata))) {
1719 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1725 if ((dialdata = strchr(dialdata, '|'))) {
1728 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1736 loops = -1; /* run forever */
1738 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1742 chan->data = "Retrying";
1743 if (ast_test_flag(chan, AST_FLAG_MOH))
1746 if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) {
1747 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
1748 if (!(res = ast_streamfile(chan, announce, chan->language)))
1749 res = ast_waitstream(chan, AST_DIGIT_ANY);
1750 if (!res && sleep) {
1751 if (!ast_test_flag(chan, AST_FLAG_MOH))
1752 ast_moh_start(chan, NULL, NULL);
1753 res = ast_waitfordigit(chan, sleep);
1756 if (!(res = ast_streamfile(chan, announce, chan->language)))
1757 res = ast_waitstream(chan, "");
1759 if (!ast_test_flag(chan, AST_FLAG_MOH))
1760 ast_moh_start(chan, NULL, NULL);
1762 res = ast_waitfordigit(chan, sleep);
1769 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1770 if (onedigit_goto(chan, context, (char) res, 1)) {
1780 if (ast_test_flag(chan, AST_FLAG_MOH))
1783 ast_module_user_remove(u);
1787 static int unload_module(void)
1791 res = ast_unregister_application(app);
1792 res |= ast_unregister_application(rapp);
1794 ast_module_user_hangup_all();
1799 static int load_module(void)
1803 res = ast_register_application(app, dial_exec, synopsis, descrip);
1804 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1809 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");