2 * Asterisk -- A telephony toolkit for Linux.
4 * Trivial application to dial a channel and send an URL on answer
6 * Copyright (C) 1999-2004, Digium, Inc.
8 * Mark Spencer <markster@digium.com>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/say.h>
23 #include <asterisk/config.h>
24 #include <asterisk/features.h>
25 #include <asterisk/musiconhold.h>
26 #include <asterisk/callerid.h>
27 #include <asterisk/utils.h>
28 #include <asterisk/app.h>
29 #include <asterisk/causes.h>
37 #include <sys/signal.h>
38 #include <netinet/in.h>
40 static char *tdesc = "Dialing Application";
42 static char *app = "Dial";
44 static char *synopsis = "Place a call and connect to the current channel";
46 static char *descrip =
47 " Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
48 "Requests one or more channels and places specified outgoing calls on them.\n"
49 "As soon as a channel answers, the Dial app will answer the originating\n"
50 "channel (if it needs to be answered) and will bridge a call with the channel\n"
51 "which first answered. All other calls placed by the Dial app will be hung up.\n"
52 "If a timeout is not specified, the Dial application will wait indefinitely\n"
53 "until either one of the called channels answers, the user hangs up, or all\n"
54 "channels return busy or error. In general, the dialer will return 0 if it\n"
55 "was unable to place the call, or the timeout expired. However, if all\n"
56 "channels were busy, and there exists an extension with priority n+101 (where\n"
57 "n is the priority of the dialer instance), then it will be the next\n"
58 "executed extension (this allows you to setup different behavior on busy from\n"
60 " This application returns -1 if the originating channel hangs up, or if the\n"
61 "call is bridged and either of the parties in the bridge terminate the call.\n"
62 "The option string may contain zero or more of the following characters:\n"
63 " 't' -- allow the called user to transfer the calling user by hitting #.\n"
64 " 'T' -- allow the calling user to transfer the call by hitting #.\n"
65 " 'w' -- allow the called user to write the conversation to disk via app_monitor\n"
66 " 'W' -- allow the calling user to write the conversation to disk via app_monitor\n"
67 " 'f' -- Forces callerid to be set as the extension of the line \n"
68 " making/redirecting the outgoing call. For example, some PSTNs\n"
69 " don't allow callerids from other extensions then the ones\n"
70 " that are assigned to you.\n"
71 " 'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
72 " 'm[(class)]' -- provide hold music to the calling party until answered (optionally\n"
73 " with the specified class.\n"
74 " 'M(x[^arg]) -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n"
75 " Also, the macro can set the MACRO_RESULT variable to do the following:\n"
76 " -- ABORT - Hangup both legs of the call.\n"
77 " -- CONGESTION - Behave as if line congestion was encountered.\n"
78 " -- BUSY - Behave as if a busy signal was encountered. (n+101)\n"
79 " -- CONTINUE - Hangup the called party and continue on in the dialplan.\n"
80 " -- GOTO:<context>^<exten>^<priority> - Transfer the call.\n"
81 " 'h' -- allow callee to hang up by hitting *.\n"
82 " 'H' -- allow caller to hang up by hitting *.\n"
83 " 'C' -- reset call detail record for this call.\n"
84 " 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
85 " 'g' -- goes on in context if the destination channel hangs up\n"
86 " 'A(x)' -- play an announcement to the called party, using x as file\n"
87 " 'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"
88 " 'D([digits])' -- Send DTMF digit string *after* called party has answered\n"
89 " but before the bridge. (w=500ms sec pause)\n"
90 " 'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
91 " repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
92 " The following special variables are optional:\n"
93 " * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
94 " Play sounds to the caller.\n"
95 " * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
96 " Play sounds to the callee.\n"
97 " * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
98 " * LIMIT_CONNECT_FILE File to play when call begins.\n"
99 " * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
100 " 'timeleft' is a special sound macro to auto-say the time \n"
101 " left and is the default.\n\n"
102 " In addition to transferring the call, a call may be parked and then picked\n"
103 "up by another user.\n"
104 " The optional URL will be sent to the called party if the channel supports it.\n"
105 " If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
106 " application will be put into that group (as in SetGroup).\n"
107 " This application sets the following channel variables upon completion:\n"
108 " DIALEDTIME Time from dial to answer\n"
109 " ANSWEREDTIME Time for actual call\n"
110 " DIALSTATUS The status of the call as a text string, one of\n"
111 " CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
114 /* We define a customer "local user" structure because we
115 use it not only for keeping track of what is in use but
116 also for keeping track of who we're dialing. */
118 #define DIAL_STILLGOING (1 << 0)
119 #define DIAL_ALLOWREDIRECT_IN (1 << 1)
120 #define DIAL_ALLOWREDIRECT_OUT (1 << 2)
121 #define DIAL_ALLOWDISCONNECT_IN (1 << 3)
122 #define DIAL_ALLOWDISCONNECT_OUT (1 << 4)
123 #define DIAL_RINGBACKONLY (1 << 5)
124 #define DIAL_MUSICONHOLD (1 << 6)
125 #define DIAL_FORCECALLERID (1 << 7)
126 #define DIAL_MONITOR_IN (1 << 8)
127 #define DIAL_MONITOR_OUT (1 << 9)
128 #define DIAL_GO_ON (1 << 10)
131 struct ast_channel *chan;
134 struct localuser *next;
139 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
141 /* Hang up a tree of stuff */
142 struct localuser *oo;
144 /* Hangup any existing lines we have open */
145 if (outgoing->chan && (outgoing->chan != exception))
146 ast_hangup(outgoing->chan);
148 outgoing=outgoing->next;
153 #define AST_MAX_FORWARDS 8
155 #define AST_MAX_WATCHERS 256
157 #define HANDLE_CAUSE(cause, chan) do { \
159 case AST_CAUSE_BUSY: \
161 ast_cdr_busy(chan->cdr); \
164 case AST_CAUSE_CONGESTION: \
165 case AST_CAUSE_UNREGISTERED: \
167 ast_cdr_busy(chan->cdr); \
177 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart)
182 int numbusy = busystart;
183 int numcongestion = congestionstart;
184 int numnochan = nochanstart;
185 int prestart = busystart + congestionstart + nochanstart;
189 struct ast_channel *peer = NULL;
190 struct ast_channel *watchers[AST_MAX_WATCHERS];
193 struct ast_channel *winner;
195 single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, DIAL_MUSICONHOLD | DIAL_RINGBACKONLY));
198 /* Turn off hold music, etc */
199 ast_deactivate_generator(in);
200 /* If we are calling a single channel, make them compatible for in-band tone purpose */
201 ast_channel_make_compatible(outgoing->chan, in);
205 while(*to && !peer) {
212 /* Keep track of important channels */
213 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) {
214 watchers[pos++] = o->chan;
221 if (numlines == (numbusy + numcongestion + numnochan)) {
222 if (option_verbose > 2)
223 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
225 strncpy(status, "BUSY", statussize - 1);
226 else if (numcongestion)
227 strncpy(status, "CONGESTION", statussize - 1);
229 strncpy(status, "CHANUNAVAIL", statussize - 1);
230 /* See if there is a special busy message */
231 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->cid.cid_num))
234 if (option_verbose > 2)
235 ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
240 winner = ast_waitfor_n(watchers, pos, to);
243 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan && (o->chan->_state == AST_STATE_UP)) {
245 if (option_verbose > 2)
246 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
248 ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT);
250 } else if (o->chan && (o->chan == winner)) {
251 if (!ast_strlen_zero(o->chan->call_forward)) {
252 char tmpchan[256]="";
255 strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
256 if ((stuff = strchr(tmpchan, '/'))) {
261 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
265 /* Before processing channel, go ahead and check for forwarding */
267 if (o->forwards < AST_MAX_FORWARDS) {
268 if (option_verbose > 2)
269 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
270 /* Setup parameters */
271 o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
273 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
275 if (option_verbose > 2)
276 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", o->chan->name);
277 cause = AST_CAUSE_CONGESTION;
281 ast_clear_flag(o, DIAL_STILLGOING);
282 HANDLE_CAUSE(cause, in);
284 if (o->chan->cid.cid_num)
285 free(o->chan->cid.cid_num);
286 o->chan->cid.cid_num = NULL;
287 if (o->chan->cid.cid_name)
288 free(o->chan->cid.cid_name);
289 o->chan->cid.cid_name = NULL;
291 if (ast_test_flag(o, DIAL_FORCECALLERID)) {
294 if (strlen(in->macroexten))
295 newcid = in->macroexten;
298 o->chan->cid.cid_num = strdup(newcid);
299 strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
300 o->chan->cdrflags = winner->cdrflags;
301 if (!o->chan->cid.cid_num)
302 ast_log(LOG_WARNING, "Out of memory\n");
304 if (in->cid.cid_num) {
305 o->chan->cid.cid_num = strdup(in->cid.cid_num);
306 if (!o->chan->cid.cid_num)
307 ast_log(LOG_WARNING, "Out of memory\n");
309 if (in->cid.cid_name) {
310 o->chan->cid.cid_name = strdup(in->cid.cid_name);
311 if (!o->chan->cid.cid_name)
312 ast_log(LOG_WARNING, "Out of memory\n");
314 strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
315 o->chan->cdrflags = in->cdrflags;
318 if (in->cid.cid_ani) {
319 if (o->chan->cid.cid_ani)
320 free(o->chan->cid.cid_ani);
321 o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
322 if (o->chan->cid.cid_ani)
323 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
325 ast_log(LOG_WARNING, "Out of memory\n");
327 if (o->chan->cid.cid_rdnis)
328 free(o->chan->cid.cid_rdnis);
329 if (!ast_strlen_zero(in->macroexten))
330 o->chan->cid.cid_rdnis = strdup(in->macroexten);
332 o->chan->cid.cid_rdnis = strdup(in->exten);
333 if (ast_call(o->chan, tmpchan, 0)) {
334 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
335 ast_clear_flag(o, DIAL_STILLGOING);
341 /* Hangup the original channel now, in case we needed it */
345 f = ast_read(winner);
347 if (f->frametype == AST_FRAME_CONTROL) {
348 switch(f->subclass) {
349 case AST_CONTROL_ANSWER:
350 /* This is our guy if someone answered. */
352 if (option_verbose > 2)
353 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
355 ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT);
357 /* If call has been answered, then the eventual hangup is likely to be normal hangup */
358 in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
359 o->chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
361 case AST_CONTROL_BUSY:
362 if (option_verbose > 2)
363 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
364 in->hangupcause = o->chan->hangupcause;
367 ast_clear_flag(o, DIAL_STILLGOING);
368 HANDLE_CAUSE(AST_CAUSE_BUSY, in);
370 case AST_CONTROL_CONGESTION:
371 if (option_verbose > 2)
372 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
373 in->hangupcause = o->chan->hangupcause;
376 ast_clear_flag(o, DIAL_STILLGOING);
377 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
379 case AST_CONTROL_RINGING:
380 if (option_verbose > 2)
381 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
382 if (!(*sentringing) && !ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
383 ast_indicate(in, AST_CONTROL_RINGING);
387 case AST_CONTROL_PROGRESS:
388 if (option_verbose > 2)
389 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
390 if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
391 ast_indicate(in, AST_CONTROL_PROGRESS);
393 case AST_CONTROL_OFFHOOK:
394 case AST_CONTROL_FLASH:
395 /* Ignore going off hook and flash */
398 if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY | DIAL_MUSICONHOLD)) {
399 if (option_verbose > 2)
400 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
401 ast_indicate(in, -1);
406 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
408 } else if (single && (f->frametype == AST_FRAME_VOICE) &&
409 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY) || ast_test_flag(outgoing, DIAL_MUSICONHOLD))) {
410 if (ast_write(in, f))
411 ast_log(LOG_WARNING, "Unable to forward frame\n");
412 } else if (single && (f->frametype == AST_FRAME_IMAGE) &&
413 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY) || ast_test_flag(outgoing, DIAL_MUSICONHOLD))) {
414 if (ast_write(in, f))
415 ast_log(LOG_WARNING, "Unable to forward image\n");
419 in->hangupcause = o->chan->hangupcause;
422 ast_clear_flag(o, DIAL_STILLGOING);
430 if (f && (f->frametype != AST_FRAME_VOICE))
431 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
432 else if (!f || (f->frametype != AST_FRAME_VOICE))
433 printf("Hangup received on %s\n", in->name);
435 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
438 strncpy(status, "CANCEL", statussize - 1);
443 if (f && (f->frametype == AST_FRAME_DTMF) && ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT) &&
444 (f->subclass == '*')) {
445 if (option_verbose > 3)
446 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
448 strcpy(status, "CANCEL");
452 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
453 if (ast_write(outgoing->chan, f))
454 ast_log(LOG_WARNING, "Unable to forward voice\n");
458 if (!*to && (option_verbose > 2))
459 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
466 static int dial_exec(struct ast_channel *chan, void *data)
470 char *info, *peers, *timeout, *tech, *number, *rest, *cur;
471 char privdb[256] = "", *s;
472 char announcemsg[256] = "", *ann;
473 struct localuser *outgoing=NULL, *tmp;
474 struct ast_channel *peer;
476 struct ast_flags peerflags={0};
482 int numcongestion = 0;
485 char numsubst[AST_MAX_EXTENSION];
486 char restofit[AST_MAX_EXTENSION];
487 char *transfer = NULL;
490 char *url=NULL; /* JDG */
491 struct ast_var_t *current;
492 struct varshead *headp, *newheadp;
493 struct ast_var_t *newvar;
494 unsigned int calldurationlimit=0;
497 struct ast_bridge_config config;
499 long play_warning = 0;
501 char *warning_sound=NULL;
502 char *end_sound=NULL;
503 char *start_sound=NULL;
507 char sdtmfdata[256] = "";
509 char *mac = NULL, *macroname = NULL;
512 int play_to_caller=0,play_to_callee=0;
513 int playargs=0, sentringing=0, moh=0;
515 char *mohclass = NULL;
517 char *outbound_group = NULL;
518 char *macro_result = NULL, *macro_transfer_dest = NULL;
520 time_t start_time, answer_time, end_time;
521 struct ast_app *app = NULL;
524 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
528 if (!(info = ast_strdupa(data))) {
529 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
537 timeout = strchr(info, '|');
541 transfer = strchr(timeout, '|');
546 url = strchr(transfer, '|');
551 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
554 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
561 if (!peers || ast_strlen_zero(peers)) {
562 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
569 /* Extract call duration limit */
570 if ((cdl = strstr(transfer, "S("))) {
571 calldurationlimit=atoi(cdl+2);
572 if (option_verbose > 2)
573 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);
577 if ((sdtmfptr = strstr(transfer, "D("))) {
578 strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
579 /* Overwrite with X's what was the sdtmf info */
580 while (*sdtmfptr && (*sdtmfptr != ')'))
584 /* Now find the end */
585 sdtmfptr = strchr(sdtmfdata, ')');
589 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
592 /* XXX LIMIT SUPPORT */
593 if ((limitptr = strstr(transfer, "L("))) {
594 strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
595 /* Overwrite with X's what was the limit info */
596 while(*limitptr && (*limitptr != ')'))
600 /* Now find the end */
601 limitptr = strchr(limitdata, ')');
605 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
607 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
608 play_to_caller = var ? ast_true(var) : 1;
610 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
611 play_to_callee = var ? ast_true(var) : 0;
613 if (!play_to_caller && !play_to_callee)
616 var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
617 warning_sound = var ? var : "timeleft";
619 var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
620 end_sound = var ? var : NULL;
622 var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
623 start_sound = var ? var : NULL;
627 var = strsep(&stack, ":");
629 timelimit = atol(var);
631 var = strsep(&stack, ":");
633 play_warning = atol(var);
635 var = strsep(&stack, ":");
637 warning_freq = atol(var);
644 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
647 /* undo effect of S(x) in case they are both used */
649 /* more efficient do it like S(x) does since no advanced opts*/
650 if (!play_warning && !start_sound && !end_sound && timelimit) {
651 calldurationlimit=timelimit/1000;
652 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
653 } else if (option_verbose > 2) {
654 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
655 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
656 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
657 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
658 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
659 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
660 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
661 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
662 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
666 /* XXX ANNOUNCE SUPPORT */
667 if ((ann = strstr(transfer, "A("))) {
669 strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
670 /* Overwrite with X's what was the announce info */
671 while(*ann && (*ann != ')'))
675 /* Now find the end of the privdb */
676 ann = strchr(announcemsg, ')');
680 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
685 /* Get the macroname from the dial option string */
686 if ((mac = strstr(transfer, "M("))) {
688 macroname = ast_strdupa(mac + 2);
689 while (*mac && (*mac != ')'))
694 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
697 mac = strchr(macroname, ')');
701 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
705 /* Get music on hold class */
706 if ((mac = strstr(transfer, "m("))) {
707 mohclass = ast_strdupa(mac + 2);
708 mac++; /* Leave the "m" in the string */
709 while (*mac && (*mac != ')'))
714 ast_log(LOG_WARNING, "Could not find music on hold class to use, assuming default.\n");
717 mac = strchr(macroname, ')');
721 ast_log(LOG_WARNING, "Music on hold class specified without trailing ')'\n");
725 /* Extract privacy info from transfer */
726 if ((s = strstr(transfer, "P("))) {
728 strncpy(privdb, s + 2, sizeof(privdb) - 1);
729 /* Overwrite with X's what was the privacy info */
730 while(*s && (*s != ')'))
734 /* Now find the end of the privdb */
735 s = strchr(privdb, ')');
739 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
742 } else if (strchr(transfer, 'P')) {
743 /* No specified privdb */
745 } else if (strchr(transfer, 'C')) {
749 if (resetcdr && chan->cdr)
750 ast_cdr_reset(chan->cdr, 0);
751 if (ast_strlen_zero(privdb) && privacy) {
752 /* If privdb is not specified and we are using privacy, copy from extension */
753 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
756 l = chan->cid.cid_num;
759 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
762 /* If a channel group has been specified, get it for use when we create peer channels */
763 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
767 /* Remember where to start next time */
768 rest = strchr(cur, '&');
773 /* Get a technology/[device:]number pair */
775 number = strchr(tech, '/');
777 ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
782 tmp = malloc(sizeof(struct localuser));
784 ast_log(LOG_WARNING, "Out of memory\n");
787 memset(tmp, 0, sizeof(struct localuser));
789 ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_IN);
790 ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_OUT);
791 ast_set2_flag(tmp, strchr(transfer, 'r'), DIAL_RINGBACKONLY);
792 ast_set2_flag(tmp, strchr(transfer, 'm'), DIAL_MUSICONHOLD);
793 ast_set2_flag(tmp, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);
794 ast_set2_flag(&peerflags, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);
795 ast_set2_flag(tmp, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
796 ast_set2_flag(&peerflags, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
797 ast_set2_flag(tmp, strchr(transfer, 'f'), DIAL_FORCECALLERID);
798 ast_set2_flag(tmp, strchr(transfer, 'w'), DIAL_MONITOR_IN);
799 ast_set2_flag(tmp, strchr(transfer, 'W'), DIAL_MONITOR_OUT);
800 ast_set2_flag(tmp, strchr(transfer, 'g'), DIAL_GO_ON);
802 strncpy(numsubst, number, sizeof(numsubst)-1);
803 /* If we're dialing by extension, look at the extension to know what to dial */
804 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
805 strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
806 snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
808 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
810 /* Request the peer */
811 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
813 /* If we can't, just go on to the next call */
814 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d)\n", tech, cause);
815 HANDLE_CAUSE(cause, chan);
819 if (!ast_strlen_zero(tmp->chan->call_forward)) {
820 char tmpchan[256]="";
823 strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
824 if ((stuff = strchr(tmpchan, '/'))) {
829 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
834 if (tmp->forwards < AST_MAX_FORWARDS) {
835 if (option_verbose > 2)
836 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
837 ast_hangup(tmp->chan);
838 /* Setup parameters */
839 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
841 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
843 if (option_verbose > 2)
844 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
845 ast_hangup(tmp->chan);
847 cause = AST_CAUSE_CONGESTION;
850 HANDLE_CAUSE(cause, chan);
856 /* Contitionally copy channel variables to the newly created channel */
857 headp = &chan->varshead;
858 AST_LIST_TRAVERSE(headp, current, entries) {
859 varname = ast_var_full_name(current);
862 if (varname[0] == '_') {
864 if (varname[1] == '_')
869 newvar = ast_var_assign((char*)&(varname[1]),
870 ast_var_value(current));
871 newheadp = &tmp->chan->varshead;
872 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
874 ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n",
875 ast_var_name(newvar));
876 } else if (vartype == 2) {
877 newvar = ast_var_assign(ast_var_full_name(current),
878 ast_var_value(current));
879 newheadp = &tmp->chan->varshead;
880 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
882 ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n",
883 ast_var_name(newvar));
886 ast_log(LOG_DEBUG, "Not copying variable %s.\n",
887 ast_var_name(current));
891 tmp->chan->appl = "AppDial";
892 tmp->chan->data = "(Outgoing Line)";
893 tmp->chan->whentohangup = 0;
894 if (tmp->chan->cid.cid_num)
895 free(tmp->chan->cid.cid_num);
896 tmp->chan->cid.cid_num = NULL;
897 if (tmp->chan->cid.cid_name)
898 free(tmp->chan->cid.cid_name);
899 tmp->chan->cid.cid_name = NULL;
900 if (tmp->chan->cid.cid_ani)
901 free(tmp->chan->cid.cid_ani);
902 tmp->chan->cid.cid_ani = NULL;
904 if (chan->cid.cid_num)
905 tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
906 if (chan->cid.cid_name)
907 tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
908 if (chan->cid.cid_ani)
909 tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
911 /* Copy language from incoming to outgoing */
912 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
913 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
914 tmp->chan->cdrflags = chan->cdrflags;
915 if (ast_strlen_zero(tmp->chan->musicclass))
916 strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
917 if (chan->cid.cid_rdnis)
918 tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
919 /* Pass callingpres setting */
920 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
921 /* Pass type of number */
922 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
923 /* Pass type of tns */
924 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
925 /* Presense of ADSI CPE on outgoing channel follows ours */
926 tmp->chan->adsicpe = chan->adsicpe;
927 /* pass the digital flag */
928 ast_copy_flags(tmp->chan, chan, AST_FLAG_DIGITAL);
930 /* If we have an outbound group, set this peer channel to it */
932 ast_app_group_set_channel(tmp->chan, outbound_group);
934 /* Place the call, but don't wait on the answer */
935 res = ast_call(tmp->chan, numsubst, 0);
937 /* Save the info in cdr's that we called them */
939 ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
941 /* check the results of ast_call */
943 /* Again, keep going even if there's an error */
945 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
946 else if (option_verbose > 2)
947 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
948 ast_hangup(tmp->chan);
953 if (option_verbose > 2)
954 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
955 /* Put them in the list of outgoing thingies... We're ready now.
956 XXX If we're forcibly removed, these outgoing calls won't get
958 ast_set_flag(tmp, DIAL_STILLGOING);
959 tmp->next = outgoing;
961 /* If this line is up, don't try anybody else */
962 if (outgoing->chan->_state == AST_STATE_UP)
967 if (timeout && !ast_strlen_zero(timeout)) {
972 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
977 /* Our status will at least be NOANSWER */
978 strncpy(status, "NOANSWER", sizeof(status) - 1);
979 if (ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
981 ast_moh_start(chan, mohclass);
982 } else if (ast_test_flag(outgoing, DIAL_RINGBACKONLY)) {
983 ast_indicate(chan, AST_CONTROL_RINGING);
987 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
990 peer = wait_for_answer(chan, outgoing, &to, &peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion);
994 /* Musta gotten hung up */
997 /* Nobody answered, next please? */
1005 /* Once call is answered, ditch the OSP Handle */
1006 pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
1008 strncpy(status, "ANSWER", sizeof(status) - 1);
1009 /* Ah ha! Someone answered within the desired timeframe. Of course after this
1010 we will always return with -1 so that it is hung up properly after the
1012 hanguptree(outgoing, peer);
1014 /* If appropriate, log that we have a destination channel */
1016 ast_cdr_setdestchan(chan->cdr, peer->name);
1018 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1020 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
1022 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1023 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
1024 ast_channel_sendurl( peer, url );
1026 if (announce && announcemsg) {
1027 /* Start autoservice on the other chan */
1028 res = ast_autoservice_start(chan);
1029 /* Now Stream the File */
1031 res = ast_streamfile(peer,announcemsg,peer->language);
1033 digit = ast_waitstream(peer, AST_DIGIT_ANY);
1035 /* Ok, done. stop autoservice */
1036 res = ast_autoservice_stop(chan);
1037 if (digit > 0 && !res)
1038 res = ast_senddigit(chan, digit);
1045 if (hasmacro && macroname) {
1046 res = ast_autoservice_start(chan);
1048 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1052 app = pbx_findapp("Macro");
1055 for(res=0;res<strlen(macroname);res++)
1056 if(macroname[res] == '^')
1057 macroname[res] = '|';
1058 res = pbx_exec(peer, app, macroname, 1);
1059 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1062 ast_log(LOG_ERROR, "Could not find application Macro\n");
1066 if (ast_autoservice_stop(chan) < 0) {
1067 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1072 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1073 if (!strcasecmp(macro_result, "BUSY")) {
1074 strncpy(status, macro_result, sizeof(status) - 1);
1075 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1076 ast_set_flag(&peerflags, DIAL_GO_ON);
1080 else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1081 strncpy(status, macro_result, sizeof(status) - 1);
1082 ast_set_flag(&peerflags, DIAL_GO_ON);
1085 else if (!strcasecmp(macro_result, "CONTINUE")) {
1086 /* hangup peer and keep chan alive assuming the macro has changed
1087 the context / exten / priority or perhaps
1088 the next priority in the current exten is desired.
1090 ast_set_flag(&peerflags, DIAL_GO_ON);
1092 } else if (!strcasecmp(macro_result, "ABORT")) {
1093 /* Hangup both ends unless the caller has the g flag */
1095 } else if(!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1097 /* perform a transfer to a new extension */
1098 if(strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
1099 /* no brainer mode... substitute ^ with | and feed it to builtin goto */
1100 for(res=0;res<strlen(macro_transfer_dest);res++)
1101 if(macro_transfer_dest[res] == '^')
1102 macro_transfer_dest[res] = '|';
1104 if(!ast_parseable_goto(chan, macro_transfer_dest))
1105 ast_set_flag(&peerflags, DIAL_GO_ON);
1114 if (calldurationlimit > 0) {
1116 chan->whentohangup = now + calldurationlimit;
1118 if (!ast_strlen_zero(sdtmfdata))
1119 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
1123 memset(&config,0,sizeof(struct ast_bridge_config));
1125 config.features_caller |= AST_FEATURE_PLAY_WARNING;
1127 config.features_callee |= AST_FEATURE_PLAY_WARNING;
1128 if (ast_test_flag(&peerflags, DIAL_ALLOWREDIRECT_IN))
1129 config.features_callee |= AST_FEATURE_REDIRECT;
1130 if (ast_test_flag(&peerflags, DIAL_ALLOWREDIRECT_OUT))
1131 config.features_caller |= AST_FEATURE_REDIRECT;
1132 if (ast_test_flag(&peerflags, DIAL_ALLOWDISCONNECT_IN))
1133 config.features_callee |= AST_FEATURE_DISCONNECT;
1134 if (ast_test_flag(&peerflags, DIAL_ALLOWDISCONNECT_OUT))
1135 config.features_caller |= AST_FEATURE_DISCONNECT;
1136 if (ast_test_flag(&peerflags, DIAL_MONITOR_IN))
1137 config.features_callee |= AST_FEATURE_AUTOMON;
1138 if (ast_test_flag(&peerflags, DIAL_MONITOR_OUT))
1139 config.features_caller |= AST_FEATURE_AUTOMON;
1140 config.timelimit = timelimit;
1141 config.play_warning = play_warning;
1142 config.warning_freq = warning_freq;
1143 config.warning_sound = warning_sound;
1144 config.end_sound = end_sound;
1145 config.start_sound = start_sound;
1149 } else if (sentringing) {
1151 ast_indicate(chan, -1);
1153 /* Be sure no generators are left on it */
1154 ast_deactivate_generator(chan);
1155 /* Make sure channels are compatible */
1156 res = ast_channel_make_compatible(chan, peer);
1158 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1162 res = ast_bridge_call(chan,peer,&config);
1164 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1165 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1166 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1167 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1172 if (res != AST_PBX_NO_HANGUP_PEER) {
1173 if (!chan->_softhangup)
1174 chan->hangupcause = peer->hangupcause;
1182 } else if (sentringing) {
1184 ast_indicate(chan, -1);
1186 hanguptree(outgoing, NULL);
1187 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1188 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1190 LOCAL_USER_REMOVE(u);
1192 if((ast_test_flag(&peerflags, DIAL_GO_ON)) && (!chan->_softhangup))
1198 int unload_module(void)
1200 STANDARD_HANGUP_LOCALUSERS;
1201 return ast_unregister_application(app);
1204 int load_module(void)
1207 res = ast_register_application(app, dial_exec, synopsis, descrip);
1211 char *description(void)
1219 STANDARD_USECOUNT(res);
1225 return ASTERISK_GPL_KEY;