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 if (ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]))
968 else opermode = atoi(opt_args[OPT_ARG_OPERMODE]);
969 if (option_verbose > 2)
970 ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
973 if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
974 calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
975 if (!calldurationlimit) {
976 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
979 if (option_verbose > 2)
980 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
983 if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
984 dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
985 dtmfcalled = strsep(&dtmfcalling, ":");
988 if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
989 if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
993 if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
994 ast_cdr_reset(chan->cdr, NULL);
995 if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
996 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
997 if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) {
999 char *l = chan->cid.cid_num; /* XXX watch out, we are overwriting it */
1000 if (!ast_strlen_zero(l)) {
1001 ast_shrink_phone_number(l);
1002 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1003 if (option_verbose > 2)
1004 ast_verbose(VERBOSE_PREFIX_3 "Privacy DB is '%s', clid is '%s'\n",
1005 opt_args[OPT_ARG_PRIVACY], l);
1006 privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
1009 if (option_verbose > 2)
1010 ast_verbose(VERBOSE_PREFIX_3 "Privacy Screening, clid is '%s'\n", l);
1011 privdb_val = AST_PRIVACY_UNKNOWN;
1016 tnam = ast_strdupa(chan->name);
1017 /* clean the channel name so slashes don't try to end up in disk file name */
1018 for(tn2 = tnam; *tn2; tn2++) {
1020 *tn2 = '='; /* any other chars to be afraid of? */
1022 if (option_verbose > 2)
1023 ast_verbose(VERBOSE_PREFIX_3 "Privacy-- callerid is empty\n");
1025 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
1027 privdb_val = AST_PRIVACY_UNKNOWN;
1030 ast_copy_string(privcid,l,sizeof(privcid));
1032 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 */
1033 if (option_verbose > 2)
1034 ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", privcid);
1035 privdb_val = AST_PRIVACY_ALLOW;
1037 else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) {
1038 if (option_verbose > 2)
1039 ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
1042 if(privdb_val == AST_PRIVACY_DENY ) {
1043 ast_copy_string(status, "NOANSWER", sizeof(status));
1044 if (option_verbose > 2)
1045 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1049 else if(privdb_val == AST_PRIVACY_KILL ) {
1050 ast_copy_string(status, "DONTCALL", sizeof(status));
1051 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1052 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1055 goto out; /* Is this right? */
1057 else if(privdb_val == AST_PRIVACY_TORTURE ) {
1058 ast_copy_string(status, "TORTURE", sizeof(status));
1059 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1060 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1063 goto out; /* is this right??? */
1065 else if(privdb_val == AST_PRIVACY_UNKNOWN ) {
1066 /* Get the user's intro, store it in priv-callerintros/$CID,
1067 unless it is already there-- this should be done before the
1068 call is actually dialed */
1070 /* make sure the priv-callerintros dir actually exists */
1071 snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
1072 if (mkdir(privintro, 0755) && errno != EEXIST) {
1073 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
1078 snprintf(privintro,sizeof(privintro), "priv-callerintros/%s", privcid);
1079 if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
1080 /* the DELUX version of this code would allow this caller the
1081 option to hear and retape their previously recorded intro.
1085 int duration; /* for feedback from play_and_wait */
1086 /* the file doesn't exist yet. Let the caller submit his
1087 vocal intro for posterity */
1088 /* priv-recordintro script:
1090 "At the tone, please say your name:"
1093 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 */
1094 /* don't think we'll need a lock removed, we took care of
1095 conflicts by naming the privintro file */
1097 /* Delete the file regardless since they hung up during recording */
1098 ast_filedelete(privintro, NULL);
1099 if( ast_fileexists(privintro,NULL,NULL ) > 0 )
1100 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
1101 else if (option_verbose > 2)
1102 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1105 if( !ast_streamfile(chan, "vm-dialout", chan->language) )
1106 ast_waitstream(chan, "");
1111 /* If a channel group has been specified, get it for use when we create peer channels */
1112 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1114 ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
1115 /* loop through the list of dial destinations */
1117 while ((cur = strsep(&rest, "&")) ) {
1118 struct dial_localuser *tmp;
1119 /* Get a technology/[device:]number pair */
1121 char *tech = strsep(&number, "/");
1123 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
1126 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
1129 ast_copy_flags(tmp, &opts,
1130 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
1131 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
1132 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
1133 OPT_CALLEE_PARK | OPT_CALLER_PARK |
1134 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
1135 ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);
1137 ast_copy_string(numsubst, number, sizeof(numsubst));
1138 /* Request the peer */
1139 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1141 /* If we can't, just go on to the next call */
1142 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1143 handle_cause(cause, &num);
1144 if (!rest) /* we are on the last destination */
1145 chan->hangupcause = cause;
1148 pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
1149 if (!ast_strlen_zero(tmp->chan->call_forward)) {
1153 ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan));
1154 if ((stuff = strchr(tmpchan, '/'))) {
1158 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
1163 if (tmp->forwards < AST_MAX_FORWARDS) {
1164 if (option_verbose > 2)
1165 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1166 ast_hangup(tmp->chan);
1167 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
1168 if (ast_test_flag(&opts, OPT_IGNORE_FORWARDING)) {
1170 cause = AST_CAUSE_BUSY;
1171 if (option_verbose > 2)
1172 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", chan->name, tech, stuff);
1174 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1177 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1179 ast_channel_inherit_variables(chan, tmp->chan);
1181 if (option_verbose > 2)
1182 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
1183 ast_hangup(tmp->chan);
1185 cause = AST_CAUSE_CONGESTION;
1188 handle_cause(cause, &num);
1193 /* Setup outgoing SDP to match incoming one */
1194 ast_rtp_make_compatible(tmp->chan, chan, !outgoing && !rest);
1196 /* Inherit specially named variables from parent channel */
1197 ast_channel_inherit_variables(chan, tmp->chan);
1199 tmp->chan->appl = "AppDial";
1200 tmp->chan->data = "(Outgoing Line)";
1201 tmp->chan->whentohangup = 0;
1203 S_REPLACE(tmp->chan->cid.cid_num, ast_strdup(chan->cid.cid_num));
1204 S_REPLACE(tmp->chan->cid.cid_name, ast_strdup(chan->cid.cid_name));
1205 S_REPLACE(tmp->chan->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
1206 S_REPLACE(tmp->chan->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
1208 /* Copy language from incoming to outgoing */
1209 ast_string_field_set(tmp->chan, language, chan->language);
1210 ast_string_field_set(tmp->chan, accountcode, chan->accountcode);
1211 tmp->chan->cdrflags = chan->cdrflags;
1212 if (ast_strlen_zero(tmp->chan->musicclass))
1213 ast_string_field_set(tmp->chan, musicclass, chan->musicclass);
1214 /* Pass callingpres setting */
1215 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
1216 /* Pass type of number */
1217 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
1218 /* Pass type of tns */
1219 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
1220 /* Presense of ADSI CPE on outgoing channel follows ours */
1221 tmp->chan->adsicpe = chan->adsicpe;
1222 /* Pass the transfer capability */
1223 tmp->chan->transfercapability = chan->transfercapability;
1225 /* If we have an outbound group, set this peer channel to it */
1227 ast_app_group_set_channel(tmp->chan, outbound_group);
1229 /* Inherit context and extension */
1230 ast_copy_string(tmp->chan->context, chan->context, sizeof(tmp->chan->context));
1231 ast_copy_string(tmp->chan->exten, chan->exten, sizeof(tmp->chan->exten));
1233 /* Place the call, but don't wait on the answer */
1234 res = ast_call(tmp->chan, numsubst, 0);
1236 /* Save the info in cdr's that we called them */
1238 ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
1240 /* check the results of ast_call */
1242 /* Again, keep going even if there's an error */
1244 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1245 if (option_verbose > 2)
1246 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1247 ast_hangup(tmp->chan);
1251 senddialevent(chan, tmp->chan);
1252 if (option_verbose > 2)
1253 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1254 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
1255 ast_set_callerid(tmp->chan, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
1257 /* Put them in the list of outgoing thingies... We're ready now.
1258 XXX If we're forcibly removed, these outgoing calls won't get
1260 ast_set_flag(tmp, DIAL_STILLGOING);
1261 tmp->next = outgoing;
1263 /* If this line is up, don't try anybody else */
1264 if (outgoing->chan->_state == AST_STATE_UP)
1268 if (ast_strlen_zero(args.timeout)) {
1271 to = atoi(args.timeout);
1275 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
1279 strcpy(status, "CHANUNAVAIL");
1281 /* Our status will at least be NOANSWER */
1282 strcpy(status, "NOANSWER");
1283 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1285 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1286 } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
1287 ast_indicate(chan, AST_CONTROL_RINGING);
1293 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), &num, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
1298 } else if (to) { /* Musta gotten hung up */
1300 } else { /* Nobody answered, next please? */
1303 /* almost done, although the 'else' block is 400 lines */
1306 time_t end_time, answer_time = time(NULL);
1308 strcpy(status, "ANSWER");
1309 /* Ah ha! Someone answered within the desired timeframe. Of course after this
1310 we will always return with -1 so that it is hung up properly after the
1312 hanguptree(outgoing, peer);
1314 /* If appropriate, log that we have a destination channel */
1316 ast_cdr_setdestchan(chan->cdr, peer->name);
1318 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1320 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1323 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1324 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
1326 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url);
1327 ast_channel_sendurl( peer, args.url );
1329 if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && privdb_val == AST_PRIVACY_UNKNOWN) {
1333 /* Get the user's intro, store it in priv-callerintros/$CID,
1334 unless it is already there-- this should be done before the
1335 call is actually dialed */
1337 /* all ring indications and moh for the caller has been halted as soon as the
1338 target extension was picked up. We are going to have to kill some
1339 time and make the caller believe the peer hasn't picked up yet */
1341 if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1342 ast_indicate(chan, -1);
1343 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1344 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1345 ast_indicate(chan, AST_CONTROL_RINGING);
1349 /* Start autoservice on the other chan ?? */
1350 res2 = ast_autoservice_start(chan);
1351 /* Now Stream the File */
1352 for (loopcount = 0; loopcount < 3; loopcount++) {
1353 if (res2 && loopcount == 0) /* error in ast_autoservice_start() */
1355 if (!res2) /* on timeout, play the message again */
1356 res2 = ast_play_and_wait(peer,"priv-callpending");
1357 if (!valid_priv_reply(&opts, res2))
1359 /* priv-callpending script:
1360 "I have a caller waiting, who introduces themselves as:"
1363 res2 = ast_play_and_wait(peer,privintro);
1364 if (!valid_priv_reply(&opts, res2))
1366 /* now get input from the called party, as to their choice */
1368 /* XXX can we have both, or they are mutually exclusive ? */
1369 if( ast_test_flag(&opts, OPT_PRIVACY) )
1370 res2 = ast_play_and_wait(peer,"priv-callee-options");
1371 if( ast_test_flag(&opts, OPT_SCREENING) )
1372 res2 = ast_play_and_wait(peer,"screen-callee-options");
1374 /*! \page DialPrivacy Dial Privacy scripts
1375 \par priv-callee-options script:
1376 "Dial 1 if you wish this caller to reach you directly in the future,
1377 and immediately connect to their incoming call
1378 Dial 2 if you wish to send this caller to voicemail now and
1380 Dial 3 to send this caller to the torture menus, now and forevermore.
1381 Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
1382 Dial 5 to allow this caller to come straight thru to you in the future,
1383 but right now, just this once, send them to voicemail."
1384 \par screen-callee-options script:
1385 "Dial 1 if you wish to immediately connect to the incoming call
1386 Dial 2 if you wish to send this caller to voicemail.
1387 Dial 3 to send this caller to the torture menus.
1388 Dial 4 to send this caller to a simple "go away" menu.
1390 if (valid_priv_reply(&opts, res2))
1392 /* invalid option */
1393 res2 = ast_play_and_wait(peer, "vm-sorry");
1396 if (ast_test_flag(&opts, OPT_MUSICBACK)) {
1398 } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
1399 ast_indicate(chan, -1);
1402 ast_autoservice_stop(chan);
1406 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1407 if (option_verbose > 2)
1408 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
1409 opt_args[OPT_ARG_PRIVACY], privcid);
1410 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
1414 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1415 if (option_verbose > 2)
1416 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n",
1417 opt_args[OPT_ARG_PRIVACY], privcid);
1418 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
1420 ast_copy_string(status, "NOANSWER", sizeof(status));
1421 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1425 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1426 if (option_verbose > 2)
1427 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n",
1428 opt_args[OPT_ARG_PRIVACY], privcid);
1429 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE);
1431 ast_copy_string(status, "TORTURE", sizeof(status));
1434 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1435 goto out; /* Is this right? */
1437 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1438 if (option_verbose > 2)
1439 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n",
1440 opt_args[OPT_ARG_PRIVACY], privcid);
1441 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL);
1444 ast_copy_string(status, "DONTCALL", sizeof(status));
1446 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1447 goto out; /* Is this right? */
1449 if( ast_test_flag(&opts, OPT_PRIVACY) ) {
1450 if (option_verbose > 2)
1451 ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
1452 opt_args[OPT_ARG_PRIVACY], privcid);
1453 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
1454 ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
1457 } /* if not privacy, then 5 is the same as "default" case */
1458 default: /* bad input or -1 if failure to start autoservice */
1459 /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */
1460 /* well, there seems basically two choices. Just patch the caller thru immediately,
1461 or,... put 'em thru to voicemail. */
1462 /* since the callee may have hung up, let's do the voicemail thing, no database decision */
1463 ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
1464 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1469 /* XXX once again, this path is only taken in the case '1', so it could be
1470 * moved there, although i am not really sure that this is correct - maybe
1471 * the check applies to other cases as well.
1473 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
1474 just clog things up, and it's not useful information, not being tied to a CID */
1475 if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) {
1476 ast_filedelete(privintro, NULL);
1477 if( ast_fileexists(privintro, NULL, NULL ) > 0 )
1478 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", privintro);
1479 else if (option_verbose > 2)
1480 ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
1483 if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
1487 /* Start autoservice on the other chan */
1488 res = ast_autoservice_start(chan);
1489 /* Now Stream the File */
1491 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
1493 digit = ast_waitstream(peer, AST_DIGIT_ANY);
1495 /* Ok, done. stop autoservice */
1496 res = ast_autoservice_stop(chan);
1497 if (digit > 0 && !res)
1498 res = ast_senddigit(chan, digit);
1504 if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
1505 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
1506 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
1507 ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
1509 ast_pbx_start(peer);
1510 hanguptree(outgoing, NULL);
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);
1521 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
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]);
1531 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1534 ast_log(LOG_ERROR, "Could not find application Macro\n");
1538 if (ast_autoservice_stop(chan) < 0) {
1539 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1543 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1544 char *macro_transfer_dest;
1546 if (!strcasecmp(macro_result, "BUSY")) {
1547 ast_copy_string(status, macro_result, sizeof(status));
1548 if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1549 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1550 ast_set_flag(peerflags, OPT_GO_ON);
1553 ast_set_flag(peerflags, OPT_GO_ON);
1555 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1556 ast_copy_string(status, macro_result, sizeof(status));
1557 ast_set_flag(peerflags, OPT_GO_ON);
1559 } else if (!strcasecmp(macro_result, "CONTINUE")) {
1560 /* hangup peer and keep chan alive assuming the macro has changed
1561 the context / exten / priority or perhaps
1562 the next priority in the current exten is desired.
1564 ast_set_flag(peerflags, OPT_GO_ON);
1566 } else if (!strcasecmp(macro_result, "ABORT")) {
1567 /* Hangup both ends unless the caller has the g flag */
1569 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1571 /* perform a transfer to a new extension */
1572 if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
1573 replace_macro_delimiter(macro_transfer_dest);
1574 if (!ast_parseable_goto(chan, macro_transfer_dest))
1575 ast_set_flag(peerflags, OPT_GO_ON);
1583 if (calldurationlimit > 0) {
1584 chan->whentohangup = time(NULL) + calldurationlimit;
1586 if (!ast_strlen_zero(dtmfcalled)) {
1587 if (option_verbose > 2)
1588 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
1589 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1591 if (!ast_strlen_zero(dtmfcalling)) {
1592 if (option_verbose > 2)
1593 ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
1594 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1599 if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1600 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1601 if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1602 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1603 if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1604 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1605 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1606 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1607 if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1608 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1609 if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1610 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1611 if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1612 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
1613 if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1614 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
1619 } else if (sentringing) {
1621 ast_indicate(chan, -1);
1623 /* Be sure no generators are left on it */
1624 ast_deactivate_generator(chan);
1625 /* Make sure channels are compatible */
1626 res = ast_channel_make_compatible(chan, peer);
1628 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1633 if (opermode && (!strncmp(chan->name,"Zap",3)) &&
1634 (!strncmp(peer->name,"Zap",3)))
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);
1648 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1649 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1657 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1658 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1661 if (res != AST_PBX_NO_HANGUP_PEER) {
1662 if (!chan->_softhangup)
1663 chan->hangupcause = peer->hangupcause;
1671 } else if (sentringing) {
1673 ast_indicate(chan, -1);
1675 ast_channel_early_bridge(chan, NULL);
1676 hanguptree(outgoing, NULL);
1677 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1678 senddialendevent(chan, status);
1680 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1682 if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
1686 ast_module_user_remove(u); /* XXX probably not the right place for this. */
1690 static int dial_exec(struct ast_channel *chan, void *data)
1692 struct ast_flags peerflags;
1693 memset(&peerflags, 0, sizeof(peerflags));
1694 return dial_exec_full(chan, data, &peerflags);
1697 static int retrydial_exec(struct ast_channel *chan, void *data)
1699 char *announce = NULL, *dialdata = NULL;
1700 const char *context = NULL;
1701 int sleep = 0, loops = 0, res = -1;
1702 struct ast_module_user *u;
1703 struct ast_flags peerflags;
1705 if (ast_strlen_zero(data)) {
1706 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
1710 u = ast_module_user_add(chan);
1712 announce = ast_strdupa(data);
1714 memset(&peerflags, 0, sizeof(peerflags));
1716 if ((dialdata = strchr(announce, '|'))) {
1718 if ((sleep = atoi(dialdata))) {
1721 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1724 if ((dialdata = strchr(dialdata, '|'))) {
1726 if (!(loops = atoi(dialdata))) {
1727 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1733 if ((dialdata = strchr(dialdata, '|'))) {
1736 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1744 loops = -1; /* run forever */
1746 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1750 chan->data = "Retrying";
1751 if (ast_test_flag(chan, AST_FLAG_MOH))
1754 if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) {
1755 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
1756 if (!(res = ast_streamfile(chan, announce, chan->language)))
1757 res = ast_waitstream(chan, AST_DIGIT_ANY);
1758 if (!res && sleep) {
1759 if (!ast_test_flag(chan, AST_FLAG_MOH))
1760 ast_moh_start(chan, NULL, NULL);
1761 res = ast_waitfordigit(chan, sleep);
1764 if (!(res = ast_streamfile(chan, announce, chan->language)))
1765 res = ast_waitstream(chan, "");
1767 if (!ast_test_flag(chan, AST_FLAG_MOH))
1768 ast_moh_start(chan, NULL, NULL);
1770 res = ast_waitfordigit(chan, sleep);
1777 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1778 if (onedigit_goto(chan, context, (char) res, 1)) {
1788 if (ast_test_flag(chan, AST_FLAG_MOH))
1791 ast_module_user_remove(u);
1795 static int unload_module(void)
1799 res = ast_unregister_application(app);
1800 res |= ast_unregister_application(rapp);
1802 ast_module_user_hangup_all();
1807 static int load_module(void)
1811 res = ast_register_application(app, dial_exec, synopsis, descrip);
1812 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1817 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");