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) -- Executes the macro (x) upon connect of the call\n"
72 " 'h' -- allow callee to hang up by hitting *.\n"
73 " 'H' -- allow caller to hang up by hitting *.\n"
74 " 'C' -- reset call detail record for this call.\n"
75 " 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
76 " 'g' -- goes on in context if the destination channel hangs up\n"
77 " 'A(x)' -- play an announcement to the called party, using x as file\n"
78 " 'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"
79 " 'D([digits])' -- Send DTMF digit string *after* called party has answered\n"
80 " but before the bridge. (w=500ms sec pause)\n"
81 " 'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
82 " repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
83 " The following special variables are optional:\n"
84 " * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
85 " Play sounds to the caller.\n"
86 " * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
87 " Play sounds to the callee.\n"
88 " * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
89 " * LIMIT_CONNECT_FILE File to play when call begins.\n"
90 " * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
91 " 'timeleft' is a special sound macro to auto-say the time \n"
92 " left and is the default.\n\n"
93 " In addition to transferring the call, a call may be parked and then picked\n"
94 "up by another user.\n"
95 " The optional URL will be sent to the called party if the channel supports it.\n"
96 " If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
97 " application will be put into that group (as in SetGroup).\n"
98 " This application sets the following channel variables upon completion:\n"
99 " DIALEDTIME Time from dial to answer\n"
100 " ANSWEREDTIME Time for actual call\n"
101 " DIALSTATUS The status of the call as a text string, one of\n"
102 " CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
105 /* We define a customer "local user" structure because we
106 use it not only for keeping track of what is in use but
107 also for keeping track of who we're dialing. */
110 struct ast_channel *chan;
112 int allowredirect_in;
113 int allowredirect_out;
116 int allowdisconnect_in;
117 int allowdisconnect_out;
119 struct localuser *next;
124 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
126 /* Hang up a tree of stuff */
127 struct localuser *oo;
129 /* Hangup any existing lines we have open */
130 if (outgoing->chan && (outgoing->chan != exception))
131 ast_hangup(outgoing->chan);
133 outgoing=outgoing->next;
138 #define AST_MAX_WATCHERS 256
140 #define HANDLE_CAUSE(blah, bleh) do { \
142 case AST_CAUSE_BUSY: \
144 ast_cdr_busy(bleh->cdr); \
146 case AST_CAUSE_CONGESTION: \
147 case AST_CAUSE_UNREGISTERED: \
149 ast_cdr_busy(bleh->cdr); \
157 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)
162 int numbusy = busystart;
163 int numcongestion = congestionstart;
164 int numnochan = nochanstart;
168 struct ast_channel *peer = NULL;
169 struct ast_channel *watchers[AST_MAX_WATCHERS];
172 struct ast_channel *winner;
174 single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
177 /* Turn off hold music, etc */
178 ast_deactivate_generator(in);
179 /* If we are calling a single channel, make them compatible for in-band tone purpose */
180 ast_channel_make_compatible(outgoing->chan, in);
184 while(*to && !peer) {
191 /* Keep track of important channels */
192 if (o->stillgoing && o->chan) {
193 watchers[pos++] = o->chan;
200 if (numlines == (numbusy + numcongestion + numnochan)) {
201 if (option_verbose > 2)
202 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
204 strncpy(status, "BUSY", statussize - 1);
205 else if (numcongestion)
206 strncpy(status, "CONGESTION", statussize - 1);
208 strncpy(status, "CHANUNAVAIL", statussize - 1);
209 /* See if there is a special busy message */
210 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->cid.cid_num))
213 if (option_verbose > 2)
214 ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
219 winner = ast_waitfor_n(watchers, pos, to);
222 if (o->stillgoing && o->chan && (o->chan->_state == AST_STATE_UP)) {
224 if (option_verbose > 2)
225 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
227 *allowredir_in = o->allowredirect_in;
228 *allowredir_out = o->allowredirect_out;
229 *allowdisconnect_in = o->allowdisconnect_in;
230 *allowdisconnect_out = o->allowdisconnect_out;
232 } else if (o->chan && (o->chan == winner)) {
233 if (!ast_strlen_zero(o->chan->call_forward)) {
234 char tmpchan[256]="";
237 strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
238 if ((stuff = strchr(tmpchan, '/'))) {
243 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
247 /* Before processing channel, go ahead and check for forwarding */
248 if (option_verbose > 2)
249 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
250 /* Setup parameters */
251 o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
253 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
255 HANDLE_CAUSE(cause, in);
257 if (o->chan->cid.cid_num)
258 free(o->chan->cid.cid_num);
259 o->chan->cid.cid_num = NULL;
260 if (o->chan->cid.cid_name)
261 free(o->chan->cid.cid_name);
262 o->chan->cid.cid_name = NULL;
264 if (o->forcecallerid) {
267 if (strlen(in->macroexten))
268 newcid = in->macroexten;
271 o->chan->cid.cid_num = strdup(newcid);
272 strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
273 o->chan->cdrflags = winner->cdrflags;
274 if (!o->chan->cid.cid_num)
275 ast_log(LOG_WARNING, "Out of memory\n");
277 if (in->cid.cid_num) {
278 o->chan->cid.cid_num = strdup(in->cid.cid_num);
279 if (!o->chan->cid.cid_num)
280 ast_log(LOG_WARNING, "Out of memory\n");
282 if (in->cid.cid_name) {
283 o->chan->cid.cid_name = strdup(in->cid.cid_name);
284 if (!o->chan->cid.cid_name)
285 ast_log(LOG_WARNING, "Out of memory\n");
287 strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
288 o->chan->cdrflags = in->cdrflags;
291 if (in->cid.cid_ani) {
292 if (o->chan->cid.cid_ani)
293 free(o->chan->cid.cid_ani);
294 o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
295 if (o->chan->cid.cid_ani)
296 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
298 ast_log(LOG_WARNING, "Out of memory\n");
300 if (o->chan->cid.cid_rdnis)
301 free(o->chan->cid.cid_rdnis);
302 if (!ast_strlen_zero(in->macroexten))
303 o->chan->cid.cid_rdnis = strdup(in->macroexten);
305 o->chan->cid.cid_rdnis = strdup(in->exten);
306 if (ast_call(o->chan, tmpchan, 0)) {
307 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
314 /* Hangup the original channel now, in case we needed it */
318 f = ast_read(winner);
320 if (f->frametype == AST_FRAME_CONTROL) {
321 switch(f->subclass) {
322 case AST_CONTROL_ANSWER:
323 /* This is our guy if someone answered. */
325 if (option_verbose > 2)
326 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
328 *allowredir_in = o->allowredirect_in;
329 *allowredir_out = o->allowredirect_out;
330 *allowdisconnect_in = o->allowdisconnect_in;
331 *allowdisconnect_out = o->allowdisconnect_out;
334 case AST_CONTROL_BUSY:
335 if (option_verbose > 2)
336 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
337 in->hangupcause = o->chan->hangupcause;
341 HANDLE_CAUSE(AST_CAUSE_BUSY, in);
343 case AST_CONTROL_CONGESTION:
344 if (option_verbose > 2)
345 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
346 in->hangupcause = o->chan->hangupcause;
350 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
352 case AST_CONTROL_RINGING:
353 if (option_verbose > 2)
354 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
355 if (!(*sentringing) && !outgoing->musiconhold) {
356 ast_indicate(in, AST_CONTROL_RINGING);
360 case AST_CONTROL_PROGRESS:
361 if (option_verbose > 2)
362 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
363 if (!outgoing->ringbackonly)
364 ast_indicate(in, AST_CONTROL_PROGRESS);
366 case AST_CONTROL_OFFHOOK:
367 case AST_CONTROL_FLASH:
368 /* Ignore going off hook and flash */
371 if (!outgoing->ringbackonly && !outgoing->musiconhold) {
372 if (option_verbose > 2)
373 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
374 ast_indicate(in, -1);
379 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
381 } else if (single && (f->frametype == AST_FRAME_VOICE) &&
382 !(outgoing->ringbackonly || outgoing->musiconhold)) {
383 if (ast_write(in, f))
384 ast_log(LOG_WARNING, "Unable to forward frame\n");
385 } else if (single && (f->frametype == AST_FRAME_IMAGE) &&
386 !(outgoing->ringbackonly || outgoing->musiconhold)) {
387 if (ast_write(in, f))
388 ast_log(LOG_WARNING, "Unable to forward image\n");
392 in->hangupcause = o->chan->hangupcause;
403 if (f && (f->frametype != AST_FRAME_VOICE))
404 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
405 else if (!f || (f->frametype != AST_FRAME_VOICE))
406 printf("Hangup received on %s\n", in->name);
408 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
411 strncpy(status, "CANCEL", statussize - 1);
414 if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
415 (f->subclass == '*')) {
416 if (option_verbose > 3)
417 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
419 strcpy(status, "CANCEL");
422 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
423 if (ast_write(outgoing->chan, f))
424 ast_log(LOG_WARNING, "Unable to forward voice\n");
428 if (!*to && (option_verbose > 2))
429 ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
436 static int dial_exec(struct ast_channel *chan, void *data)
440 char *info, *peers, *timeout, *tech, *number, *rest, *cur;
441 char privdb[256] = "", *s;
442 char announcemsg[256] = "", *ann;
443 struct localuser *outgoing=NULL, *tmp;
444 struct ast_channel *peer;
447 int allowredir_out=0;
448 int allowdisconnect_in=0;
449 int allowdisconnect_out=0;
455 int numcongestion = 0;
458 char numsubst[AST_MAX_EXTENSION];
459 char restofit[AST_MAX_EXTENSION];
460 char *transfer = NULL;
463 char *url=NULL; /* JDG */
464 struct ast_var_t *current;
465 struct varshead *headp, *newheadp;
466 struct ast_var_t *newvar;
468 unsigned int calldurationlimit=0;
471 struct ast_bridge_config config;
473 long play_warning = 0;
475 char *warning_sound=NULL;
476 char *end_sound=NULL;
477 char *start_sound=NULL;
481 char sdtmfdata[256] = "";
483 char *mac = NULL, macroname[256] = "";
486 int play_to_caller=0,play_to_callee=0;
487 int playargs=0, sentringing=0, moh=0;
490 char *outbound_group = NULL;
493 time_t start_time, answer_time, end_time;
496 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
500 if (!(info = ast_strdupa(data))) {
501 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
509 timeout = strchr(info, '|');
513 transfer = strchr(timeout, '|');
518 url = strchr(transfer, '|');
523 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
526 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
533 if (!peers || ast_strlen_zero(peers)) {
534 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
541 /* Extract call duration limit */
542 if ((cdl = strstr(transfer, "S("))) {
543 calldurationlimit=atoi(cdl+2);
544 if (option_verbose > 2)
545 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);
549 if ((sdtmfptr = strstr(transfer, "D("))) {
550 strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
551 /* Overwrite with X's what was the sdtmf info */
552 while (*sdtmfptr && (*sdtmfptr != ')'))
556 /* Now find the end */
557 sdtmfptr = strchr(sdtmfdata, ')');
561 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
564 /* XXX LIMIT SUPPORT */
565 if ((limitptr = strstr(transfer, "L("))) {
566 strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
567 /* Overwrite with X's what was the limit info */
568 while(*limitptr && (*limitptr != ')'))
572 /* Now find the end */
573 limitptr = strchr(limitdata, ')');
577 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
579 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
580 play_to_caller = var ? ast_true(var) : 1;
582 var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
583 play_to_callee = var ? ast_true(var) : 0;
585 if (!play_to_caller && !play_to_callee)
588 var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
589 warning_sound = var ? var : "timeleft";
591 var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
592 end_sound = var ? var : NULL;
594 var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
595 start_sound = var ? var : NULL;
599 var = strsep(&stack, ":");
601 timelimit = atol(var);
603 var = strsep(&stack, ":");
605 play_warning = atol(var);
607 var = strsep(&stack, ":");
609 warning_freq = atol(var);
616 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
619 /* undo effect of S(x) in case they are both used */
621 /* more efficient do it like S(x) does since no advanced opts*/
622 if (!play_warning && !start_sound && !end_sound && timelimit) {
623 calldurationlimit=timelimit/1000;
624 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
625 } else if (option_verbose > 2) {
626 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
627 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
628 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
629 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
630 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
631 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
632 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
633 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
634 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
638 /* XXX ANNOUNCE SUPPORT */
639 if ((ann = strstr(transfer, "A("))) {
641 strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
642 /* Overwrite with X's what was the announce info */
643 while(*ann && (*ann != ')'))
647 /* Now find the end of the privdb */
648 ann = strchr(announcemsg, ')');
652 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
657 /* Get the macroname from the dial option string */
658 if ((mac = strstr(transfer, "M("))) {
660 strncpy(macroname, mac + 2, sizeof(macroname) - 1);
661 while (*mac && (*mac != ')'))
666 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
669 mac = strchr(macroname, ')');
673 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
677 /* Extract privacy info from transfer */
678 if ((s = strstr(transfer, "P("))) {
680 strncpy(privdb, s + 2, sizeof(privdb) - 1);
681 /* Overwrite with X's what was the privacy info */
682 while(*s && (*s != ')'))
686 /* Now find the end of the privdb */
687 s = strchr(privdb, ')');
691 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
694 } else if (strchr(transfer, 'P')) {
695 /* No specified privdb */
697 } else if (strchr(transfer, 'C')) {
701 if (resetcdr && chan->cdr)
702 ast_cdr_reset(chan->cdr, 0);
703 if (ast_strlen_zero(privdb) && privacy) {
704 /* If privdb is not specified and we are using privacy, copy from extension */
705 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
708 l = chan->cid.cid_num;
711 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
714 /* If a channel group has been specified, get it for use when we create peer channels */
715 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
719 /* Remember where to start next time */
720 rest = strchr(cur, '&');
725 /* Get a technology/[device:]number pair */
727 number = strchr(tech, '/');
729 ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
734 tmp = malloc(sizeof(struct localuser));
736 ast_log(LOG_WARNING, "Out of memory\n");
739 memset(tmp, 0, sizeof(struct localuser));
741 if (strchr(transfer, 't'))
742 tmp->allowredirect_in = 1;
743 else tmp->allowredirect_in = 0;
744 if (strchr(transfer, 'T'))
745 tmp->allowredirect_out = 1;
746 else tmp->allowredirect_out = 0;
747 if (strchr(transfer, 'r'))
748 tmp->ringbackonly = 1;
749 else tmp->ringbackonly = 0;
750 if (strchr(transfer, 'm'))
751 tmp->musiconhold = 1;
752 else tmp->musiconhold = 0;
753 if (strchr(transfer, 'H'))
754 allowdisconnect_out = tmp->allowdisconnect_out = 1;
755 else allowdisconnect_out = tmp->allowdisconnect_out = 0;
756 if(strchr(transfer, 'h'))
757 allowdisconnect_in = tmp->allowdisconnect_in = 1;
758 else allowdisconnect_in = tmp->allowdisconnect_in = 0;
759 if(strchr(transfer, 'g'))
761 if (strchr(transfer, 'f'))
762 tmp->forcecallerid = 1;
763 else tmp->forcecallerid = 0;
765 strncpy(numsubst, number, sizeof(numsubst)-1);
766 /* If we're dialing by extension, look at the extension to know what to dial */
767 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
768 strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
769 snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
771 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
773 /* Request the peer */
774 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
776 /* If we can't, just go on to the next call */
777 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d)\n", tech, cause);
778 HANDLE_CAUSE(cause, chan);
782 if (!ast_strlen_zero(tmp->chan->call_forward)) {
783 char tmpchan[256]="";
786 strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
787 if ((stuff = strchr(tmpchan, '/'))) {
792 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
796 /* Before processing channel, go ahead and check for forwarding */
797 if (option_verbose > 2)
798 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
799 /* Setup parameters */
800 ast_hangup(tmp->chan);
801 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
803 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause %d)\n", tech, stuff, cause);
804 HANDLE_CAUSE(cause, chan);
810 /* Contitionally copy channel variables to the newly created channel */
811 headp = &chan->varshead;
812 AST_LIST_TRAVERSE(headp, current, entries) {
813 varname = ast_var_full_name(current);
816 if (varname[0] == '_') {
818 if (varname[1] == '_')
823 newvar = ast_var_assign((char*)&(varname[1]),
824 ast_var_value(current));
825 newheadp = &tmp->chan->varshead;
826 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
828 ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n",
829 ast_var_name(newvar));
830 } else if (vartype == 2) {
831 newvar = ast_var_assign(ast_var_full_name(current),
832 ast_var_value(current));
833 newheadp = &tmp->chan->varshead;
834 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
836 ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n",
837 ast_var_name(newvar));
840 ast_log(LOG_DEBUG, "Not copying variable %s.\n",
841 ast_var_name(current));
845 tmp->chan->appl = "AppDial";
846 tmp->chan->data = "(Outgoing Line)";
847 tmp->chan->whentohangup = 0;
848 if (tmp->chan->cid.cid_num)
849 free(tmp->chan->cid.cid_num);
850 tmp->chan->cid.cid_num = NULL;
851 if (tmp->chan->cid.cid_name)
852 free(tmp->chan->cid.cid_name);
853 tmp->chan->cid.cid_name = NULL;
854 if (tmp->chan->cid.cid_ani)
855 free(tmp->chan->cid.cid_ani);
856 tmp->chan->cid.cid_ani = NULL;
858 if (chan->cid.cid_num)
859 tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
860 if (chan->cid.cid_name)
861 tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
862 if (chan->cid.cid_ani)
863 tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
865 /* Copy language from incoming to outgoing */
866 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
867 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
868 tmp->chan->cdrflags = chan->cdrflags;
869 if (ast_strlen_zero(tmp->chan->musicclass))
870 strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
871 if (chan->cid.cid_rdnis)
872 tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
873 /* Pass callingpres setting */
874 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
875 /* Pass type of number */
876 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
877 /* Pass type of tns */
878 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
879 /* Presense of ADSI CPE on outgoing channel follows ours */
880 tmp->chan->adsicpe = chan->adsicpe;
881 /* pass the digital flag */
882 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
884 /* If we have an outbound group, set this peer channel to it */
886 ast_app_group_set_channel(tmp->chan, outbound_group);
888 /* Place the call, but don't wait on the answer */
889 res = ast_call(tmp->chan, numsubst, 0);
891 /* Save the info in cdr's that we called them */
893 ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
895 /* check the results of ast_call */
897 /* Again, keep going even if there's an error */
899 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
900 else if (option_verbose > 2)
901 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
902 ast_hangup(tmp->chan);
907 if (option_verbose > 2)
908 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
909 /* Put them in the list of outgoing thingies... We're ready now.
910 XXX If we're forcibly removed, these outgoing calls won't get
912 tmp->stillgoing = -1;
913 tmp->next = outgoing;
915 /* If this line is up, don't try anybody else */
916 if (outgoing->chan->_state == AST_STATE_UP)
921 if (timeout && !ast_strlen_zero(timeout)) {
926 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
931 /* Our status will at least be NOANSWER */
932 strncpy(status, "NOANSWER", sizeof(status) - 1);
933 if (outgoing->musiconhold) {
935 ast_moh_start(chan, NULL);
936 } else if (outgoing->ringbackonly) {
937 ast_indicate(chan, AST_CONTROL_RINGING);
941 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
944 peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion);
948 /* Musta gotten hung up */
951 /* Nobody answered, next please? */
959 /* Once call is answered, ditch the OSP Handle */
960 pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
962 strncpy(status, "ANSWER", sizeof(status) - 1);
963 /* Ah ha! Someone answered within the desired timeframe. Of course after this
964 we will always return with -1 so that it is hung up properly after the
966 hanguptree(outgoing, peer);
968 /* If appropriate, log that we have a destination channel */
970 ast_cdr_setdestchan(chan->cdr, peer->name);
972 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
974 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
976 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
977 ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
978 ast_channel_sendurl( peer, url );
980 if (announce && announcemsg) {
981 // Start autoservice on the other chan
982 res = ast_autoservice_start(chan);
983 // Now Stream the File
985 res = ast_streamfile(peer,announcemsg,peer->language);
987 digit = ast_waitstream(peer, AST_DIGIT_ANY);
989 // Ok, done. stop autoservice
990 res = ast_autoservice_stop(chan);
991 if (digit > 0 && !res)
992 res = ast_senddigit(chan, digit);
999 if (hasmacro && macroname) {
1002 res = ast_autoservice_start(chan);
1004 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1008 app = pbx_findapp("Macro");
1011 res = pbx_exec(peer, app, macroname, 1);
1012 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1015 ast_log(LOG_ERROR, "Could not find application Macro\n");
1019 if (ast_autoservice_stop(chan) < 0) {
1020 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1026 if (calldurationlimit > 0) {
1028 chan->whentohangup = now + calldurationlimit;
1030 if (!ast_strlen_zero(sdtmfdata))
1031 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
1035 memset(&config,0,sizeof(struct ast_bridge_config));
1036 config.play_to_caller=play_to_caller;
1037 config.play_to_callee=play_to_callee;
1038 config.allowredirect_in = allowredir_in;
1039 config.allowredirect_out = allowredir_out;
1040 config.allowdisconnect_in = allowdisconnect_in;
1041 config.allowdisconnect_out = allowdisconnect_out;
1042 config.timelimit = timelimit;
1043 config.play_warning = play_warning;
1044 config.warning_freq = warning_freq;
1045 config.warning_sound = warning_sound;
1046 config.end_sound = end_sound;
1047 config.start_sound = start_sound;
1051 } else if (sentringing) {
1053 ast_indicate(chan, -1);
1055 /* Be sure no generators are left on it */
1056 ast_deactivate_generator(chan);
1057 /* Make sure channels are compatible */
1058 res = ast_channel_make_compatible(chan, peer);
1060 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1064 res = ast_bridge_call(chan,peer,&config);
1066 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1067 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1068 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1069 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1074 if (res != AST_PBX_NO_HANGUP_PEER) {
1075 if (!chan->_softhangup)
1076 chan->hangupcause = peer->hangupcause;
1084 } else if (sentringing) {
1086 ast_indicate(chan, -1);
1088 hanguptree(outgoing, NULL);
1089 pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1090 ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1092 LOCAL_USER_REMOVE(u);
1094 if((go_on>0) && (!chan->_softhangup))
1100 int unload_module(void)
1102 STANDARD_HANGUP_LOCALUSERS;
1103 return ast_unregister_application(app);
1106 int load_module(void)
1109 res = ast_register_application(app, dial_exec, synopsis, descrip);
1113 char *description(void)
1121 STANDARD_USECOUNT(res);
1127 return ASTERISK_GPL_KEY;