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 transfer the calling user by hitting #.\n"
64 " 'T' -- allow the calling user to transfer the call by hitting #.\n"
65 " 'f' -- Forces callerid to be set as the extension of the line \n"
66 " making/redirecting the outgoing call. For example, some PSTNs\n"
67 " don't allow callerids from other extensions then the ones\n"
68 " that are assigned to you.\n"
69 " 'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
70 " 'm' -- provide hold music to the calling party until answered.\n"
71 " 'M(x[^arg]) -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n"
72 " Also, the macro can set the MACRO_RESULT variable to do the following:\n"
73 " -- ABORT - Hangup both legs of the call.\n"
74 " -- CONGESTION - Behave as if line congestion was encountered.\n"
75 " -- BUSY - Behave as if a busy signal was encountered. (n+101)\n"
76 " -- CONTINUE - Hangup the called party and continue on in the dialplan.\n"
77 " -- GOTO:<context>^<exten>^<priority> - Transfer the call.\n"
78 " 'h' -- allow callee to hang up by hitting *.\n"
79 " 'H' -- allow caller to hang up by hitting *.\n"
80 " 'C' -- reset call detail record for this call.\n"
81 " 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
82 " 'g' -- goes on in context if the destination channel hangs up\n"
83 " 'A(x)' -- play an announcement to the called party, using x as file\n"
84 " 'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"
85 " 'D([digits])' -- Send DTMF digit string *after* called party has answered\n"
86 " but before the bridge. (w=500ms sec pause)\n"
87 " 'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
88 " repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
89 " The following special variables are optional:\n"
90 " * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
91 " Play sounds to the caller.\n"
92 " * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
93 " Play sounds to the callee.\n"
94 " * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
95 " * LIMIT_CONNECT_FILE File to play when call begins.\n"
96 " * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
97 " 'timeleft' is a special sound macro to auto-say the time \n"
98 " left and is the default.\n\n"
99 " In addition to transferring the call, a call may be parked and then picked\n"
100 "up by another user.\n"
101 " The optional URL will be sent to the called party if the channel supports it.\n"
102 " If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
103 " application will be put into that group (as in SetGroup).\n"
104 " This application sets the following channel variables upon completion:\n"
105 " DIALEDTIME Time from dial to answer\n"
106 " ANSWEREDTIME Time for actual call\n"
107 " DIALSTATUS The status of the call as a text string, one of\n"
108 " CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
111 /* We define a customer "local user" structure because we
112 use it not only for keeping track of what is in use but
113 also for keeping track of who we're dialing. */
116 struct ast_channel *chan;
118 int allowredirect_in;
119 int allowredirect_out;
122 int allowdisconnect_in;
123 int allowdisconnect_out;
126 struct localuser *next;
131 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
133 /* Hang up a tree of stuff */
134 struct localuser *oo;
136 /* Hangup any existing lines we have open */
137 if (outgoing->chan && (outgoing->chan != exception))
138 ast_hangup(outgoing->chan);
140 outgoing=outgoing->next;
145 #define AST_MAX_FORWARDS 8
147 #define AST_MAX_WATCHERS 256
149 #define HANDLE_CAUSE(blah, bleh) do { \
151 case AST_CAUSE_BUSY: \
153 ast_cdr_busy(bleh->cdr); \
156 case AST_CAUSE_CONGESTION: \
157 case AST_CAUSE_UNREGISTERED: \
159 ast_cdr_busy(bleh->cdr); \
169 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart)
174 int numbusy = busystart;
175 int numcongestion = congestionstart;
176 int numnochan = nochanstart;
177 int prestart = busystart + congestionstart + nochanstart;
181 struct ast_channel *peer = NULL;
182 struct ast_channel *watchers[AST_MAX_WATCHERS];
185 struct ast_channel *winner;
187 single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
190 /* Turn off hold music, etc */
191 ast_deactivate_generator(in);
192 /* If we are calling a single channel, make them compatible for in-band tone purpose */
193 ast_channel_make_compatible(outgoing->chan, in);
197 while(*to && !peer) {
204 /* Keep track of important channels */
205 if (o->stillgoing && o->chan) {
206 watchers[pos++] = o->chan;
213 if (numlines == (numbusy + numcongestion + numnochan)) {
214 if (option_verbose > 2)
215 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
217 strncpy(status, "BUSY", statussize - 1);
218 else if (numcongestion)
219 strncpy(status, "CONGESTION", statussize - 1);
221 strncpy(status, "CHANUNAVAIL", statussize - 1);
222 /* See if there is a special busy message */
223 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->cid.cid_num))
226 if (option_verbose > 2)
227 ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time (%d, %d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
232 winner = ast_waitfor_n(watchers, pos, to);
235 if (o->stillgoing && o->chan && (o->chan->_state == AST_STATE_UP)) {
237 if (option_verbose > 2)
238 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
240 *allowredir_in = o->allowredirect_in;
241 *allowredir_out = o->allowredirect_out;
242 *allowdisconnect_in = o->allowdisconnect_in;
243 *allowdisconnect_out = o->allowdisconnect_out;
245 } else if (o->chan && (o->chan == winner)) {
246 if (!ast_strlen_zero(o->chan->call_forward)) {
247 char tmpchan[256]="";
250 strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
251 if ((stuff = strchr(tmpchan, '/'))) {
256 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
260 /* Before processing channel, go ahead and check for forwarding */
262 if (o->forwards < AST_MAX_FORWARDS) {
263 if (option_verbose > 2)
264 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
265 /* Setup parameters */
266 o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
268 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
270 if (option_verbose > 2)
271 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", o->chan->name);
272 cause = AST_CAUSE_CONGESTION;
277 HANDLE_CAUSE(cause, in);
279 if (o->chan->cid.cid_num)
280 free(o->chan->cid.cid_num);
281 o->chan->cid.cid_num = NULL;
282 if (o->chan->cid.cid_name)
283 free(o->chan->cid.cid_name);
284 o->chan->cid.cid_name = NULL;
286 if (o->forcecallerid) {
289 if (strlen(in->macroexten))
290 newcid = in->macroexten;
293 o->chan->cid.cid_num = strdup(newcid);
294 strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
295 o->chan->cdrflags = winner->cdrflags;
296 if (!o->chan->cid.cid_num)
297 ast_log(LOG_WARNING, "Out of memory\n");
299 if (in->cid.cid_num) {
300 o->chan->cid.cid_num = strdup(in->cid.cid_num);
301 if (!o->chan->cid.cid_num)
302 ast_log(LOG_WARNING, "Out of memory\n");
304 if (in->cid.cid_name) {
305 o->chan->cid.cid_name = strdup(in->cid.cid_name);
306 if (!o->chan->cid.cid_name)
307 ast_log(LOG_WARNING, "Out of memory\n");
309 strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
310 o->chan->cdrflags = in->cdrflags;
313 if (in->cid.cid_ani) {
314 if (o->chan->cid.cid_ani)
315 free(o->chan->cid.cid_ani);
316 o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
317 if (o->chan->cid.cid_ani)
318 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
320 ast_log(LOG_WARNING, "Out of memory\n");
322 if (o->chan->cid.cid_rdnis)
323 free(o->chan->cid.cid_rdnis);
324 if (!ast_strlen_zero(in->macroexten))
325 o->chan->cid.cid_rdnis = strdup(in->macroexten);
327 o->chan->cid.cid_rdnis = strdup(in->exten);
328 if (ast_call(o->chan, tmpchan, 0)) {
329 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
336 /* Hangup the original channel now, in case we needed it */
340 f = ast_read(winner);
342 if (f->frametype == AST_FRAME_CONTROL) {
343 switch(f->subclass) {
344 case AST_CONTROL_ANSWER:
345 /* This is our guy if someone answered. */
347 if (option_verbose > 2)
348 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
350 *allowredir_in = o->allowredirect_in;
351 *allowredir_out = o->allowredirect_out;
352 *allowdisconnect_in = o->allowdisconnect_in;
353 *allowdisconnect_out = o->allowdisconnect_out;
356 case AST_CONTROL_BUSY:
357 if (option_verbose > 2)
358 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
359 in->hangupcause = o->chan->hangupcause;
363 HANDLE_CAUSE(AST_CAUSE_BUSY, in);
365 case AST_CONTROL_CONGESTION:
366 if (option_verbose > 2)
367 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
368 in->hangupcause = o->chan->hangupcause;
372 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
374 case AST_CONTROL_RINGING:
375 if (option_verbose > 2)
376 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
377 if (!(*sentringing) && !outgoing->musiconhold) {
378 ast_indicate(in, AST_CONTROL_RINGING);
382 case AST_CONTROL_PROGRESS:
383 if (option_verbose > 2)
384 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
385 if (!outgoing->ringbackonly)
386 ast_indicate(in, AST_CONTROL_PROGRESS);
388 case AST_CONTROL_OFFHOOK:
389 case AST_CONTROL_FLASH:
390 /* Ignore going off hook and flash */
393 if (!outgoing->ringbackonly && !outgoing->musiconhold) {
394 if (option_verbose > 2)
395 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
396 ast_indicate(in, -1);
401 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
403 } else if (single && (f->frametype == AST_FRAME_VOICE) &&
404 !(outgoing->ringbackonly || outgoing->musiconhold)) {
405 if (ast_write(in, f))
406 ast_log(LOG_WARNING, "Unable to forward frame\n");
407 } else if (single && (f->frametype == AST_FRAME_IMAGE) &&
408 !(outgoing->ringbackonly || outgoing->musiconhold)) {
409 if (ast_write(in, f))
410 ast_log(LOG_WARNING, "Unable to forward image\n");
414 in->hangupcause = o->chan->hangupcause;
425 if (f && (f->frametype != AST_FRAME_VOICE))
426 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
427 else if (!f || (f->frametype != AST_FRAME_VOICE))
428 printf("Hangup received on %s\n", in->name);
430 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
433 strncpy(status, "CANCEL", statussize - 1);
436 if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
437 (f->subclass == '*')) {
438 if (option_verbose > 3)
439 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
441 strcpy(status, "CANCEL");
444 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
445 if (ast_write(outgoing->chan, f))
446 ast_log(LOG_WARNING, "Unable to forward voice\n");
450 if (!*to && (option_verbose > 2))
451 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
458 static int dial_exec(struct ast_channel *chan, void *data)
462 char *info, *peers, *timeout, *tech, *number, *rest, *cur;
463 char privdb[256] = "", *s;
464 char announcemsg[256] = "", *ann;
465 struct localuser *outgoing=NULL, *tmp;
466 struct ast_channel *peer;
469 int allowredir_out=0;
470 int allowdisconnect_in=0;
471 int allowdisconnect_out=0;
477 int numcongestion = 0;
480 char numsubst[AST_MAX_EXTENSION];
481 char restofit[AST_MAX_EXTENSION];
482 char *transfer = NULL;
485 char *url=NULL; /* JDG */
486 struct ast_var_t *current;
487 struct varshead *headp, *newheadp;
488 struct ast_var_t *newvar;
490 unsigned int calldurationlimit=0;
493 struct ast_bridge_config config;
495 long play_warning = 0;
497 char *warning_sound=NULL;
498 char *end_sound=NULL;
499 char *start_sound=NULL;
503 char sdtmfdata[256] = "";
505 char *mac = NULL, *macroname = NULL;
508 int play_to_caller=0,play_to_callee=0;
509 int playargs=0, sentringing=0, moh=0;
512 char *outbound_group = NULL;
513 char *macro_result = NULL, *macro_transfer_dest = NULL;
515 time_t start_time, answer_time, end_time;
516 struct ast_app *app = NULL;
519 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
523 if (!(info = ast_strdupa(data))) {
524 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
532 timeout = strchr(info, '|');
536 transfer = strchr(timeout, '|');
541 url = strchr(transfer, '|');
546 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
549 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
556 if (!peers || ast_strlen_zero(peers)) {
557 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
564 /* Extract call duration limit */
565 if ((cdl = strstr(transfer, "S("))) {
566 calldurationlimit=atoi(cdl+2);
567 if (option_verbose > 2)
568 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);
572 if ((sdtmfptr = strstr(transfer, "D("))) {
573 strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
574 /* Overwrite with X's what was the sdtmf info */
575 while (*sdtmfptr && (*sdtmfptr != ')'))
579 /* Now find the end */
580 sdtmfptr = strchr(sdtmfdata, ')');
584 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
587 /* XXX LIMIT SUPPORT */
588 if ((limitptr = strstr(transfer, "L("))) {
589 strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
590 /* Overwrite with X's what was the limit info */
591 while(*limitptr && (*limitptr != ')'))
595 /* Now find the end */
596 limitptr = strchr(limitdata, ')');
600 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
602 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
603 play_to_caller = var ? ast_true(var) : 1;
605 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
606 play_to_callee = var ? ast_true(var) : 0;
608 if (!play_to_caller && !play_to_callee)
611 var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
612 warning_sound = var ? var : "timeleft";
614 var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
615 end_sound = var ? var : NULL;
617 var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
618 start_sound = var ? var : NULL;
622 var = strsep(&stack, ":");
624 timelimit = atol(var);
626 var = strsep(&stack, ":");
628 play_warning = atol(var);
630 var = strsep(&stack, ":");
632 warning_freq = atol(var);
639 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
642 /* undo effect of S(x) in case they are both used */
644 /* more efficient do it like S(x) does since no advanced opts*/
645 if (!play_warning && !start_sound && !end_sound && timelimit) {
646 calldurationlimit=timelimit/1000;
647 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
648 } else if (option_verbose > 2) {
649 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
650 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
651 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
652 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
653 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
654 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
655 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
656 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
657 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
661 /* XXX ANNOUNCE SUPPORT */
662 if ((ann = strstr(transfer, "A("))) {
664 strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
665 /* Overwrite with X's what was the announce info */
666 while(*ann && (*ann != ')'))
670 /* Now find the end of the privdb */
671 ann = strchr(announcemsg, ')');
675 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
680 /* Get the macroname from the dial option string */
681 if ((mac = strstr(transfer, "M("))) {
683 macroname = ast_strdupa(mac + 2);
684 while (*mac && (*mac != ')'))
689 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
692 mac = strchr(macroname, ')');
696 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
700 /* Extract privacy info from transfer */
701 if ((s = strstr(transfer, "P("))) {
703 strncpy(privdb, s + 2, sizeof(privdb) - 1);
704 /* Overwrite with X's what was the privacy info */
705 while(*s && (*s != ')'))
709 /* Now find the end of the privdb */
710 s = strchr(privdb, ')');
714 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
717 } else if (strchr(transfer, 'P')) {
718 /* No specified privdb */
720 } else if (strchr(transfer, 'C')) {
724 if (resetcdr && chan->cdr)
725 ast_cdr_reset(chan->cdr, 0);
726 if (ast_strlen_zero(privdb) && privacy) {
727 /* If privdb is not specified and we are using privacy, copy from extension */
728 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
731 l = chan->cid.cid_num;
734 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
737 /* If a channel group has been specified, get it for use when we create peer channels */
738 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
742 /* Remember where to start next time */
743 rest = strchr(cur, '&');
748 /* Get a technology/[device:]number pair */
750 number = strchr(tech, '/');
752 ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
757 tmp = malloc(sizeof(struct localuser));
759 ast_log(LOG_WARNING, "Out of memory\n");
762 memset(tmp, 0, sizeof(struct localuser));
764 if (strchr(transfer, 't'))
765 tmp->allowredirect_in = 1;
766 else tmp->allowredirect_in = 0;
767 if (strchr(transfer, 'T'))
768 tmp->allowredirect_out = 1;
769 else tmp->allowredirect_out = 0;
770 if (strchr(transfer, 'r'))
771 tmp->ringbackonly = 1;
772 else tmp->ringbackonly = 0;
773 if (strchr(transfer, 'm'))
774 tmp->musiconhold = 1;
775 else tmp->musiconhold = 0;
776 if (strchr(transfer, 'H'))
777 allowdisconnect_out = tmp->allowdisconnect_out = 1;
778 else allowdisconnect_out = tmp->allowdisconnect_out = 0;
779 if(strchr(transfer, 'h'))
780 allowdisconnect_in = tmp->allowdisconnect_in = 1;
781 else allowdisconnect_in = tmp->allowdisconnect_in = 0;
782 if(strchr(transfer, 'g'))
784 if (strchr(transfer, 'f'))
785 tmp->forcecallerid = 1;
786 else tmp->forcecallerid = 0;
788 strncpy(numsubst, number, sizeof(numsubst)-1);
789 /* If we're dialing by extension, look at the extension to know what to dial */
790 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
791 strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
792 snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
794 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
796 /* Request the peer */
797 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
799 /* If we can't, just go on to the next call */
800 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d)\n", tech, cause);
801 HANDLE_CAUSE(cause, chan);
805 if (!ast_strlen_zero(tmp->chan->call_forward)) {
806 char tmpchan[256]="";
809 strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
810 if ((stuff = strchr(tmpchan, '/'))) {
815 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
820 if (tmp->forwards < AST_MAX_FORWARDS) {
821 if (option_verbose > 2)
822 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
823 ast_hangup(tmp->chan);
824 /* Setup parameters */
825 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
827 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
829 if (option_verbose > 2)
830 ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
831 ast_hangup(tmp->chan);
833 cause = AST_CAUSE_CONGESTION;
836 HANDLE_CAUSE(cause, chan);
842 /* Contitionally copy channel variables to the newly created channel */
843 headp = &chan->varshead;
844 AST_LIST_TRAVERSE(headp, current, entries) {
845 varname = ast_var_full_name(current);
848 if (varname[0] == '_') {
850 if (varname[1] == '_')
855 newvar = ast_var_assign((char*)&(varname[1]),
856 ast_var_value(current));
857 newheadp = &tmp->chan->varshead;
858 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
860 ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n",
861 ast_var_name(newvar));
862 } else if (vartype == 2) {
863 newvar = ast_var_assign(ast_var_full_name(current),
864 ast_var_value(current));
865 newheadp = &tmp->chan->varshead;
866 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
868 ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n",
869 ast_var_name(newvar));
872 ast_log(LOG_DEBUG, "Not copying variable %s.\n",
873 ast_var_name(current));
877 tmp->chan->appl = "AppDial";
878 tmp->chan->data = "(Outgoing Line)";
879 tmp->chan->whentohangup = 0;
880 if (tmp->chan->cid.cid_num)
881 free(tmp->chan->cid.cid_num);
882 tmp->chan->cid.cid_num = NULL;
883 if (tmp->chan->cid.cid_name)
884 free(tmp->chan->cid.cid_name);
885 tmp->chan->cid.cid_name = NULL;
886 if (tmp->chan->cid.cid_ani)
887 free(tmp->chan->cid.cid_ani);
888 tmp->chan->cid.cid_ani = NULL;
890 if (chan->cid.cid_num)
891 tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
892 if (chan->cid.cid_name)
893 tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
894 if (chan->cid.cid_ani)
895 tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
897 /* Copy language from incoming to outgoing */
898 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
899 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
900 tmp->chan->cdrflags = chan->cdrflags;
901 if (ast_strlen_zero(tmp->chan->musicclass))
902 strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
903 if (chan->cid.cid_rdnis)
904 tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
905 /* Pass callingpres setting */
906 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
907 /* Pass type of number */
908 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
909 /* Pass type of tns */
910 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
911 /* Presense of ADSI CPE on outgoing channel follows ours */
912 tmp->chan->adsicpe = chan->adsicpe;
913 /* pass the digital flag */
914 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
916 /* If we have an outbound group, set this peer channel to it */
918 ast_app_group_set_channel(tmp->chan, outbound_group);
920 /* Place the call, but don't wait on the answer */
921 res = ast_call(tmp->chan, numsubst, 0);
923 /* Save the info in cdr's that we called them */
925 ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
927 /* check the results of ast_call */
929 /* Again, keep going even if there's an error */
931 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
932 else if (option_verbose > 2)
933 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
934 ast_hangup(tmp->chan);
939 if (option_verbose > 2)
940 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
941 /* Put them in the list of outgoing thingies... We're ready now.
942 XXX If we're forcibly removed, these outgoing calls won't get
944 tmp->stillgoing = -1;
945 tmp->next = outgoing;
947 /* If this line is up, don't try anybody else */
948 if (outgoing->chan->_state == AST_STATE_UP)
953 if (timeout && !ast_strlen_zero(timeout)) {
958 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
963 /* Our status will at least be NOANSWER */
964 strncpy(status, "NOANSWER", sizeof(status) - 1);
965 if (outgoing->musiconhold) {
967 ast_moh_start(chan, NULL);
968 } else if (outgoing->ringbackonly) {
969 ast_indicate(chan, AST_CONTROL_RINGING);
973 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
976 peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion);
980 /* Musta gotten hung up */
983 /* Nobody answered, next please? */
991 /* Once call is answered, ditch the OSP Handle */
992 pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
994 strncpy(status, "ANSWER", sizeof(status) - 1);
995 /* Ah ha! Someone answered within the desired timeframe. Of course after this
996 we will always return with -1 so that it is hung up properly after the
998 hanguptree(outgoing, peer);
1000 /* If appropriate, log that we have a destination channel */
1002 ast_cdr_setdestchan(chan->cdr, peer->name);
1004 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1006 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
1008 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1009 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
1010 ast_channel_sendurl( peer, url );
1012 if (announce && announcemsg) {
1013 // Start autoservice on the other chan
1014 res = ast_autoservice_start(chan);
1015 // Now Stream the File
1017 res = ast_streamfile(peer,announcemsg,peer->language);
1019 digit = ast_waitstream(peer, AST_DIGIT_ANY);
1021 // Ok, done. stop autoservice
1022 res = ast_autoservice_stop(chan);
1023 if (digit > 0 && !res)
1024 res = ast_senddigit(chan, digit);
1031 if (hasmacro && macroname) {
1032 res = ast_autoservice_start(chan);
1034 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1038 app = pbx_findapp("Macro");
1041 for(res=0;res<strlen(macroname);res++)
1042 if(macroname[res] == '^')
1043 macroname[res] = '|';
1044 res = pbx_exec(peer, app, macroname, 1);
1045 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1048 ast_log(LOG_ERROR, "Could not find application Macro\n");
1052 if (ast_autoservice_stop(chan) < 0) {
1053 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1058 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1059 if (!strcasecmp(macro_result, "BUSY")) {
1060 strncpy(status, macro_result, sizeof(status) - 1);
1061 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1066 else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1067 strncpy(status, macro_result, sizeof(status) - 1);
1071 else if (!strcasecmp(macro_result, "CONTINUE")) {
1072 /* hangup peer and keep chan alive assuming the macro has changed
1073 the context / exten / priority or perhaps
1074 the next priority in the current exten is desired.
1078 } else if (!strcasecmp(macro_result, "ABORT")) {
1079 /* Hangup both ends unless the caller has the g flag */
1081 } else if(!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1083 /* perform a transfer to a new extension */
1084 if(strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
1085 /* no brainer mode... substitute ^ with | and feed it to builtin goto */
1086 for(res=0;res<strlen(macro_transfer_dest);res++)
1087 if(macro_transfer_dest[res] == '^')
1088 macro_transfer_dest[res] = '|';
1090 if(!ast_parseable_goto(chan, macro_transfer_dest))
1100 if (calldurationlimit > 0) {
1102 chan->whentohangup = now + calldurationlimit;
1104 if (!ast_strlen_zero(sdtmfdata))
1105 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
1109 memset(&config,0,sizeof(struct ast_bridge_config));
1110 config.play_to_caller=play_to_caller;
1111 config.play_to_callee=play_to_callee;
1112 config.allowredirect_in = allowredir_in;
1113 config.allowredirect_out = allowredir_out;
1114 config.allowdisconnect_in = allowdisconnect_in;
1115 config.allowdisconnect_out = allowdisconnect_out;
1116 config.timelimit = timelimit;
1117 config.play_warning = play_warning;
1118 config.warning_freq = warning_freq;
1119 config.warning_sound = warning_sound;
1120 config.end_sound = end_sound;
1121 config.start_sound = start_sound;
1125 } else if (sentringing) {
1127 ast_indicate(chan, -1);
1129 /* Be sure no generators are left on it */
1130 ast_deactivate_generator(chan);
1131 /* Make sure channels are compatible */
1132 res = ast_channel_make_compatible(chan, peer);
1134 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1138 res = ast_bridge_call(chan,peer,&config);
1140 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1141 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1142 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1143 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1148 if (res != AST_PBX_NO_HANGUP_PEER) {
1149 if (!chan->_softhangup)
1150 chan->hangupcause = peer->hangupcause;
1158 } else if (sentringing) {
1160 ast_indicate(chan, -1);
1162 hanguptree(outgoing, NULL);
1163 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1164 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1166 LOCAL_USER_REMOVE(u);
1168 if((go_on>0) && (!chan->_softhangup))
1174 int unload_module(void)
1176 STANDARD_HANGUP_LOCALUSERS;
1177 return ast_unregister_application(app);
1180 int load_module(void)
1183 res = ast_register_application(app, dial_exec, synopsis, descrip);
1187 char *description(void)
1195 STANDARD_USECOUNT(res);
1201 return ASTERISK_GPL_KEY;