When detecting a hairpin, redirect to the appropriate local extension (bug #1974)
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Trivial application to dial a channel and send an URL on answer
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
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 <stdlib.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <sys/time.h>
36 #include <sys/signal.h>
37 #include <netinet/in.h>
38
39 static char *tdesc = "Dialing Application";
40
41 static char *app = "Dial";
42
43 static char *synopsis = "Place a call and connect to the current channel";
44
45 static char *descrip =
46 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
47 "Requests one or more channels and places specified outgoing calls on them.\n"
48 "As soon as a channel answers, the Dial app will answer the originating\n"
49 "channel (if it needs to be answered) and will bridge a call with the channel\n"
50 "which first answered. All other calls placed by the Dial app will be hung up\n"
51 "If a timeout is not specified, the Dial application will wait indefinitely\n"
52 "until either one of the called channels answers, the user hangs up, or all\n"
53 "channels return busy or error. In general, the dialer will return 0 if it\n"
54 "was unable to place the call, or the timeout expired. However, if all\n"
55 "channels were busy, and there exists an extension with priority n+101 (where\n"
56 "n is the priority of the dialer instance), then it will be the next\n"
57 "executed extension (this allows you to setup different behavior on busy from\n"
58 "no-answer).\n"
59 "  This application returns -1 if the originating channel hangs up, or if the\n"
60 "call is bridged and either of the parties in the bridge terminate the call.\n"
61 "The option string may contain zero or more of the following characters:\n"
62 "      't' -- allow the called user transfer the calling user by hitting #.\n"
63 "      'T' -- allow the calling user to transfer the call by hitting #.\n"
64 "      'f' -- Forces callerid to be set as the extension of the line \n"
65 "             making/redirecting the outgoing call. For example, some PSTNs\n"
66 "             don't allow callerids from other extensions then the ones\n"
67 "             that are assigned to you.\n"
68 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
69 "      'm' -- provide hold music to the calling party until answered.\n"
70 "      'h' -- allow callee to hang up by hitting *.\n"
71 "      'H' -- allow caller to hang up by hitting *.\n"
72 "      'C' -- reset call detail record for this call.\n"
73 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
74 "      'g' -- goes on in context if the destination channel hangs up\n"
75 "      'A(x)' -- play an announcement to the called party, using x as file\n"
76 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
77 "      'D([digits])'  -- Send DTMF digit string *after* called party has answered\n"
78 "             but before the bridge. (w=500ms sec pause)\n"
79 "      'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
80 "             repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
81 "             The following special variables are optional:\n"
82 "             * LIMIT_PLAYAUDIO_CALLER    yes|no (default yes)\n"
83 "                                         Play sounds to the caller.\n"
84 "             * LIMIT_PLAYAUDIO_CALLEE    yes|no\n"
85 "                                         Play sounds to the callee.\n"
86 "             * LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
87 "             * LIMIT_CONNECT_FILE        File to play when call begins.\n"
88 "             * LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
89 "                        'timeleft' is a special sound macro to auto-say the time \n"
90 "                        left and is the default.\n\n"
91 "  In addition to transferring the call, a call may be parked and then picked\n"
92 "up by another user.\n"
93 "  The optional URL will be sent to the called party if the channel supports it.\n"
94 "  This application sets the following channel variables upon completion:\n"
95 "      DIALEDTIME    Time from dial to answer\n" 
96 "      ANSWEREDTIME  Time for actual call\n"
97 "      DIALSTATUS    The status of the call as a text string, one of\n"
98 "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
99 "";
100
101 /* We define a customer "local user" structure because we
102    use it not only for keeping track of what is in use but
103    also for keeping track of who we're dialing. */
104
105 struct localuser {
106         struct ast_channel *chan;
107         int stillgoing;
108         int allowredirect_in;
109         int allowredirect_out;
110         int ringbackonly;
111         int musiconhold;
112         int allowdisconnect_in;
113         int allowdisconnect_out;
114         int forcecallerid;
115         struct localuser *next;
116 };
117
118 LOCAL_USER_DECL;
119
120 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
121 {
122         /* Hang up a tree of stuff */
123         struct localuser *oo;
124         while(outgoing) {
125                 /* Hangup any existing lines we have open */
126                 if (outgoing->chan && (outgoing->chan != exception))
127                         ast_hangup(outgoing->chan);
128                 oo = outgoing;
129                 outgoing=outgoing->next;
130                 free(oo);
131         }
132 }
133
134 #define AST_MAX_WATCHERS 256
135
136 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)
137 {
138         struct localuser *o;
139         int found;
140         int numlines;
141         int numbusy = 0;
142         int numcongestion = 0;
143         int numnochan = 0;
144         int orig = *to;
145         struct ast_frame *f;
146         struct ast_channel *peer = NULL;
147         struct ast_channel *watchers[AST_MAX_WATCHERS];
148         int pos;
149         int single;
150         struct ast_channel *winner;
151         
152         single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
153         
154         if (single) {
155                 /* Turn off hold music, etc */
156                 ast_deactivate_generator(in);
157                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
158                 ast_channel_make_compatible(outgoing->chan, in);
159         }
160         
161         
162         while(*to && !peer) {
163                 o = outgoing;
164                 found = -1;
165                 pos = 1;
166                 numlines = 0;
167                 watchers[0] = in;
168                 while(o) {
169                         /* Keep track of important channels */
170                         if (o->stillgoing && o->chan) {
171                                 watchers[pos++] = o->chan;
172                                 found = 1;
173                         }
174                         o = o->next;
175                         numlines++;
176                 }
177                 if (found < 0) {
178                         if (numlines == (numbusy + numcongestion + numnochan)) {
179                                 if (option_verbose > 2)
180                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
181                                 if (numbusy)
182                                         strncpy(status, "BUSY", statussize - 1);
183                                 else if (numcongestion)
184                                         strncpy(status, "CONGESTION", statussize - 1);
185                                 else if (numnochan)
186                                         strncpy(status, "CHANUNAVAIL", statussize - 1);
187                                 /* See if there is a special busy message */
188                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) 
189                                         in->priority+=100;
190                         } else {
191                                 if (option_verbose > 2)
192                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
193                         }
194                         *to = 0;
195                         return NULL;
196                 }
197                 winner = ast_waitfor_n(watchers, pos, to);
198                 o = outgoing;
199                 while(o) {
200                         if (o->stillgoing && o->chan && (o->chan->_state == AST_STATE_UP)) {
201                                 if (!peer) {
202                                         if (option_verbose > 2)
203                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
204                                         peer = o->chan;
205                                         *allowredir_in = o->allowredirect_in;
206                                         *allowredir_out = o->allowredirect_out;
207                                         *allowdisconnect_in = o->allowdisconnect_in;
208                                         *allowdisconnect_out = o->allowdisconnect_out;
209                                 }
210                         } else if (o->chan && (o->chan == winner)) {
211                                 if (!ast_strlen_zero(o->chan->call_forward)) {
212                                         char tmpchan[256]="";
213                                         char *stuff;
214                                         char *tech;
215                                         strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
216                                         if ((stuff = strchr(tmpchan, '/'))) {
217                                                 *stuff = '\0';
218                                                 stuff++;
219                                                 tech = tmpchan;
220                                         } else {
221                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
222                                                 stuff = tmpchan;
223                                                 tech = "Local";
224                                         }
225                                         /* Before processing channel, go ahead and check for forwarding */
226                                         if (option_verbose > 2)
227                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
228                                         /* Setup parameters */
229                                         o->chan = ast_request(tech, in->nativeformats, stuff);
230                                         if (!o->chan) {
231                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
232                                                 o->stillgoing = 0;
233                                                 numnochan++;
234                                         } else {
235                                                 if (o->chan->callerid)
236                                                         free(o->chan->callerid);
237
238                                                 o->chan->callerid = NULL;
239
240                                                 if (o->forcecallerid) {
241                                                         char *newcid = NULL;
242
243                                                         if (strlen(in->macroexten))
244                                                                 newcid = in->macroexten;
245                                                         else
246                                                                 newcid = in->exten;
247                                                         o->chan->callerid = strdup(newcid);
248                                                         strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
249                                                         o->chan->cdrflags = winner->cdrflags;
250                                                         if (!o->chan->callerid)
251                                                                 ast_log(LOG_WARNING, "Out of memory\n");
252                                                 } else {
253                                                         if (in->callerid) {
254                                                                 o->chan->callerid = strdup(in->callerid);
255                                                                 if (!o->chan->callerid)
256                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
257                                                         }
258                                                         strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
259                                                         o->chan->cdrflags = in->cdrflags;
260                                                 }
261
262                                                 if (in->ani) {
263                                                         if (o->chan->ani)
264                                                                 free(o->chan->ani);
265                                                         o->chan->ani = malloc(strlen(in->ani) + 1);
266                                                         if (o->chan->ani)
267                                                                 strncpy(o->chan->ani, in->ani, strlen(in->ani));
268                                                         else
269                                                                 ast_log(LOG_WARNING, "Out of memory\n");
270                                                 }
271                                                 if (o->chan->rdnis) 
272                                                         free(o->chan->rdnis);
273                                                 if (!ast_strlen_zero(in->macroexten))
274                                                         o->chan->rdnis = strdup(in->macroexten);
275                                                 else
276                                                         o->chan->rdnis = strdup(in->exten);
277                                                 if (ast_call(o->chan, tmpchan, 0)) {
278                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
279                                                         o->stillgoing = 0;
280                                                         ast_hangup(o->chan);
281                                                         o->chan = NULL;
282                                                         numnochan++;
283                                                 }
284                                         }
285                                         /* Hangup the original channel now, in case we needed it */
286                                         ast_hangup(winner);
287                                         continue;
288                                 }
289                                 f = ast_read(winner);
290                                 if (f) {
291                                         if (f->frametype == AST_FRAME_CONTROL) {
292                                                 switch(f->subclass) {
293                                             case AST_CONTROL_ANSWER:
294                                                         /* This is our guy if someone answered. */
295                                                         if (!peer) {
296                                                                 if (option_verbose > 2)
297                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
298                                                                 peer = o->chan;
299                                                                 *allowredir_in = o->allowredirect_in;
300                                                                 *allowredir_out = o->allowredirect_out;
301                                                                 *allowdisconnect_in = o->allowdisconnect_in;
302                                                                 *allowdisconnect_out = o->allowdisconnect_out;
303                                                         }
304                                                         break;
305                                                 case AST_CONTROL_BUSY:
306                                                         if (option_verbose > 2)
307                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
308                                                         in->hangupcause = o->chan->hangupcause;
309                                                         ast_hangup(o->chan);
310                                                         o->chan = NULL;
311                                                         o->stillgoing = 0;
312                                                         if (in->cdr)
313                                                                 ast_cdr_busy(in->cdr);
314                                                         numbusy++;
315                                                         break;
316                                                 case AST_CONTROL_CONGESTION:
317                                                         if (option_verbose > 2)
318                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
319                                                         in->hangupcause = o->chan->hangupcause;
320                                                         ast_hangup(o->chan);
321                                                         o->chan = NULL;
322                                                         o->stillgoing = 0;
323                                                         if (in->cdr)
324                                                                 ast_cdr_busy(in->cdr);
325                                                         numcongestion++;
326                                                         break;
327                                                 case AST_CONTROL_RINGING:
328                                                         if (option_verbose > 2)
329                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
330                                                         if (!(*sentringing) && !outgoing->musiconhold) {
331                                                                 ast_indicate(in, AST_CONTROL_RINGING);
332                                                                 (*sentringing)++;
333                                                         }
334                                                         break;
335                                                 case AST_CONTROL_PROGRESS:
336                                                         if (option_verbose > 2)
337                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
338                                                         ast_indicate(in, AST_CONTROL_PROGRESS);
339                                                         break;
340                                                 case AST_CONTROL_OFFHOOK:
341                                                         /* Ignore going off hook */
342                                                         break;
343                                                 case -1:
344                                                         if (!outgoing->ringbackonly && !outgoing->musiconhold) {
345                                                                 if (option_verbose > 2)
346                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
347                                                                 ast_indicate(in, -1);
348                                                                 (*sentringing) = 0;
349                                                         }
350                                                         break;
351                                                 default:
352                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
353                                                 }
354                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
355                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
356                                                 if (ast_write(in, f)) 
357                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
358                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
359                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
360                                                 if (ast_write(in, f))
361                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
362                                         }
363                                         ast_frfree(f);
364                                 } else {
365                                         in->hangupcause = o->chan->hangupcause;
366                                         ast_hangup(o->chan);
367                                         o->chan = NULL;
368                                         o->stillgoing = 0;
369                                 }
370                         }
371                         o = o->next;
372                 }
373                 if (winner == in) {
374                         f = ast_read(in);
375 #if 0
376                         if (f && (f->frametype != AST_FRAME_VOICE))
377                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
378                         else if (!f || (f->frametype != AST_FRAME_VOICE))
379                                 printf("Hangup received on %s\n", in->name);
380 #endif
381                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
382                                 /* Got hung up */
383                                 *to=-1;
384                                 strncpy(status, "CANCEL", statussize - 1);
385                                 return NULL;
386                         }
387                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
388                                 (f->subclass == '*')) {
389                             if (option_verbose > 3)
390                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
391                                 *to=0;
392                                 strcpy(status, "CANCEL");
393                                 return NULL;
394                         }
395                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
396                                 if (ast_write(outgoing->chan, f))
397                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
398                                 ast_frfree(f);
399                         }
400                 }
401                 if (!*to && (option_verbose > 2))
402                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
403         }
404
405         return peer;
406         
407 }
408
409 static int dial_exec(struct ast_channel *chan, void *data)
410 {
411         int res=-1;
412         struct localuser *u;
413         char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
414         char  privdb[256] = "", *s;
415         char  announcemsg[256] = "", *ann;
416         struct localuser *outgoing=NULL, *tmp;
417         struct ast_channel *peer;
418         int to;
419         int allowredir_in=0;
420         int allowredir_out=0;
421         int allowdisconnect_in=0;
422         int allowdisconnect_out=0;
423         int privacy=0;
424         int announce=0;
425         int resetcdr=0;
426         char numsubst[AST_MAX_EXTENSION];
427         char restofit[AST_MAX_EXTENSION];
428         char *transfer = NULL;
429         char *newnum;
430         char callerid[256] = "", *l, *n;
431         char *url=NULL; /* JDG */
432         struct ast_var_t *current;
433         struct varshead *headp, *newheadp;
434         struct ast_var_t *newvar;
435         int go_on=0;
436         unsigned int calldurationlimit=0;
437         char *cdl;
438         time_t now;
439         struct ast_bridge_config config;
440         long timelimit = 0;
441         long play_warning = 0;
442         long warning_freq=0;
443         char *warning_sound=NULL;
444         char *end_sound=NULL;
445         char *start_sound=NULL;
446         char *limitptr;
447         char limitdata[256];
448         char *sdtmfptr;
449         char sdtmfdata[256] = "";
450         char *stack,*var;
451         char status[256]="";
452         char toast[80];
453         int play_to_caller=0,play_to_callee=0;
454         int playargs=0, sentringing=0, moh=0;
455         int digit = 0;
456         time_t start_time, answer_time, end_time;
457
458         if (!data) {
459                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
460                 return -1;
461         }
462         
463         LOCAL_USER_ADD(u);
464         
465         strncpy(info, (char *)data, sizeof(info) - 1);
466         peers = info;
467         if (peers) {
468                 
469                 timeout = strchr(info, '|');
470                 if (timeout) {
471                         *timeout = '\0';
472                         timeout++;
473                         transfer = strchr(timeout, '|');
474                         if (transfer) {
475                                 *transfer = '\0';
476                                 transfer++;
477                                 /* JDG */
478                                 url = strchr(transfer, '|');
479                                 if (url) {
480                                         *url = '\0';
481                                         url++;
482                                         ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
483                                 } else 
484                                         ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
485                                 /* /JDG */
486                         }
487                 }
488         } else
489                 timeout = NULL;
490         if (!peers || ast_strlen_zero(peers)) {
491                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
492                 goto out;
493         }
494         
495
496         if (transfer) {
497
498                 /* Extract call duration limit */
499                 if ((cdl = strstr(transfer, "S("))) {
500                         calldurationlimit=atoi(cdl+2);
501                         if (option_verbose > 2)
502                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
503                 } 
504
505                 /* DTMF SCRIPT*/
506                 if ((sdtmfptr = strstr(transfer, "D("))) {
507                         strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
508                         /* Overwrite with X's what was the sdtmf info */
509                         while (*sdtmfptr && (*sdtmfptr != ')')) 
510                                 *(sdtmfptr++) = 'X';
511                         if (*sdtmfptr)
512                                 *sdtmfptr = 'X';
513                         /* Now find the end  */
514                         sdtmfptr = strchr(sdtmfdata, ')');
515                         if (sdtmfptr)
516                                 *sdtmfptr = '\0';
517                         else 
518                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
519                 }
520                 
521                 /* XXX LIMIT SUPPORT */
522                 if ((limitptr = strstr(transfer, "L("))) {
523                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
524                         /* Overwrite with X's what was the limit info */
525                         while(*limitptr && (*limitptr != ')')) 
526                                 *(limitptr++) = 'X';
527                         if (*limitptr)
528                                 *limitptr = 'X';
529                         /* Now find the end */
530                         limitptr = strchr(limitdata, ')');
531                         if (limitptr)
532                                 *limitptr = '\0';
533                         else
534                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
535
536                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
537                         play_to_caller = var ? ast_true(var) : 1;
538                   
539                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
540                         play_to_callee = var ? ast_true(var) : 0;
541                   
542                         if (!play_to_caller && !play_to_callee)
543                                 play_to_caller=1;
544                   
545                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
546                         warning_sound = var ? var : "timeleft";
547
548                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
549                         end_sound = var ? var : NULL;
550
551                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
552                         start_sound = var ? var : NULL;
553
554                         var=stack=limitdata;
555
556                         var = strsep(&stack, ":");
557                         if (var) {
558                                 timelimit = atol(var);
559                                 playargs++;
560                                 var = strsep(&stack, ":");
561                                 if (var) {
562                                         play_warning = atol(var);
563                                         playargs++;
564                                         var = strsep(&stack, ":");
565                                         if(var) {
566                                                 warning_freq = atol(var);
567                                                 playargs++;
568                                         }
569                                 }
570                         }
571                   
572                         if (!timelimit) {
573                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
574                                 warning_sound=NULL;
575                         }
576                         /* undo effect of S(x) in case they are both used */
577                         calldurationlimit=0; 
578                         /* more efficient do it like S(x) does since no advanced opts*/
579                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
580                                 calldurationlimit=timelimit/1000;
581                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
582                         } else if (option_verbose > 2) {
583                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
584                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
585                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
586                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
587                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
588                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
589                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
590                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
591                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
592                         }
593                 }
594                 
595                 /* XXX ANNOUNCE SUPPORT */
596                 if ((ann = strstr(transfer, "A("))) {
597                         announce = 1;
598                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
599                         /* Overwrite with X's what was the announce info */
600                         while(*ann && (*ann != ')')) 
601                                 *(ann++) = 'X';
602                         if (*ann)
603                                 *ann = 'X';
604                         /* Now find the end of the privdb */
605                         ann = strchr(announcemsg, ')');
606                         if (ann)
607                                 *ann = '\0';
608                         else {
609                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
610                                 announce = 0;
611                         }
612                 }
613                 /* Extract privacy info from transfer */
614                 if ((s = strstr(transfer, "P("))) {
615                         privacy = 1;
616                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
617                         /* Overwrite with X's what was the privacy info */
618                         while(*s && (*s != ')')) 
619                                 *(s++) = 'X';
620                         if (*s)
621                                 *s = 'X';
622                         /* Now find the end of the privdb */
623                         s = strchr(privdb, ')');
624                         if (s)
625                                 *s = '\0';
626                         else {
627                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
628                                 privacy = 0;
629                         }
630                 } else if (strchr(transfer, 'P')) {
631                         /* No specified privdb */
632                         privacy = 1;
633                 } else if (strchr(transfer, 'C')) {
634                         resetcdr = 1;
635                 }
636         }
637         if (resetcdr && chan->cdr)
638                 ast_cdr_reset(chan->cdr, 0);
639         if (ast_strlen_zero(privdb) && privacy) {
640                 /* If privdb is not specified and we are using privacy, copy from extension */
641                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
642         }
643         if (privacy) {
644                 if (chan->callerid)
645                         strncpy(callerid, chan->callerid, sizeof(callerid) - 1);
646                 else
647                         callerid[0] = '\0';
648                 ast_callerid_parse(callerid, &n, &l);
649                 if (l) {
650                         ast_shrink_phone_number(l);
651                 } else
652                         l = "";
653                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
654         }
655         cur = peers;
656         do {
657                 /* Remember where to start next time */
658                 rest = strchr(cur, '&');
659                 if (rest) {
660                         *rest = 0;
661                         rest++;
662                 }
663                 /* Get a technology/[device:]number pair */
664                 tech = cur;
665                 number = strchr(tech, '/');
666                 if (!number) {
667                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
668                         goto out;
669                 }
670                 *number = '\0';
671                 number++;
672                 tmp = malloc(sizeof(struct localuser));
673                 if (!tmp) {
674                         ast_log(LOG_WARNING, "Out of memory\n");
675                         goto out;
676                 }
677                 memset(tmp, 0, sizeof(struct localuser));
678                 if (transfer) {
679                         if (strchr(transfer, 't'))
680                                 tmp->allowredirect_in = 1;
681                         else    tmp->allowredirect_in = 0;
682                         if (strchr(transfer, 'T'))
683                                 tmp->allowredirect_out = 1;
684                         else    tmp->allowredirect_out = 0;
685                         if (strchr(transfer, 'r'))
686                                 tmp->ringbackonly = 1;
687                         else    tmp->ringbackonly = 0;
688                         if (strchr(transfer, 'm'))
689                                 tmp->musiconhold = 1;
690                         else    tmp->musiconhold = 0;
691                         if (strchr(transfer, 'H'))
692                                 allowdisconnect_out = tmp->allowdisconnect_out = 1;
693                         else    allowdisconnect_out = tmp->allowdisconnect_out = 0;
694                         if(strchr(transfer, 'h'))
695                                 allowdisconnect_in = tmp->allowdisconnect_in = 1;
696                         else    allowdisconnect_in = tmp->allowdisconnect_in = 0;
697                         if(strchr(transfer, 'g'))
698                                 go_on=1;
699                         if (strchr(transfer, 'f'))
700                                 tmp->forcecallerid = 1;
701                         else    tmp->forcecallerid = 0;
702                 }
703                 strncpy(numsubst, number, sizeof(numsubst)-1);
704                 /* If we're dialing by extension, look at the extension to know what to dial */
705                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
706                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
707                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
708                         if (option_debug)
709                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
710                 }
711                 /* Request the peer */
712                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
713                 if (!tmp->chan) {
714                         /* If we can't, just go on to the next call */
715                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
716                         if (chan->cdr)
717                                 ast_cdr_busy(chan->cdr);
718                         free(tmp);
719                         cur = rest;
720                         continue;
721                 }
722                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
723                         char tmpchan[256]="";
724                         char *stuff;
725                         char *tech;
726                         strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
727                         if ((stuff = strchr(tmpchan, '/'))) {
728                                 *stuff = '\0';
729                                 stuff++;
730                                 tech = tmpchan;
731                         } else {
732                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
733                                 stuff = tmpchan;
734                                 tech = "Local";
735                         }
736                         /* Before processing channel, go ahead and check for forwarding */
737                         if (option_verbose > 2)
738                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
739                         /* Setup parameters */
740                         ast_hangup(tmp->chan);
741                         tmp->chan = ast_request(tech, chan->nativeformats, stuff);
742                         if (!tmp->chan) {
743                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
744                                 free(tmp);
745                                 cur = rest;
746                                 continue;
747                         }
748                 }
749                 /* If creating a SIP channel, look for a variable called */
750                 /* VXML_URL in the calling channel and copy it to the    */
751                 /* new channel.                                          */
752
753                 /* Check for ALERT_INFO in the SetVar list.  This is for   */
754                 /* SIP distinctive ring as per the RFC.  For Cisco 7960s,  */
755                 /* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
756                 /* However, the RFC says it should be a URL.  -km-         */
757                 headp=&chan->varshead;
758                 AST_LIST_TRAVERSE(headp,current,entries) {
759                         if (!strcasecmp(ast_var_name(current),"VXML_URL") ||
760                             !strcasecmp(ast_var_name(current), "ALERT_INFO") ||
761                                 !strcasecmp(ast_var_name(current), "OSPTOKEN") ||
762                                 !strcasecmp(ast_var_name(current), "OSPHANDLE"))
763                         {
764                                 newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
765                                 newheadp=&tmp->chan->varshead;
766                                 AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
767                         }
768                 }
769                 
770                 tmp->chan->appl = "AppDial";
771                 tmp->chan->data = "(Outgoing Line)";
772                 tmp->chan->whentohangup = 0;
773                 if (tmp->chan->callerid)
774                         free(tmp->chan->callerid);
775                 if (tmp->chan->ani)
776                         free(tmp->chan->ani);
777                 if (chan->callerid)
778                         tmp->chan->callerid = strdup(chan->callerid);
779                 else
780                         tmp->chan->callerid = NULL;
781                 /* Copy language from incoming to outgoing */
782                 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
783                 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
784                 tmp->chan->cdrflags = chan->cdrflags;
785                 if (ast_strlen_zero(tmp->chan->musicclass))
786                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
787                 if (chan->ani)
788                         tmp->chan->ani = strdup(chan->ani);
789                 else
790                         tmp->chan->ani = NULL;
791                 /* Pass hidecallerid setting */
792                 tmp->chan->restrictcid = chan->restrictcid;
793                 /* Pass callingpres setting */
794                 tmp->chan->callingpres = chan->callingpres;
795                 /* Presense of ADSI CPE on outgoing channel follows ours */
796                 tmp->chan->adsicpe = chan->adsicpe;
797                 /* pass the digital flag */
798                 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
799                 /* Place the call, but don't wait on the answer */
800                 res = ast_call(tmp->chan, numsubst, 0);
801
802                 /* Save the info in cdr's that we called them */
803                 if (chan->cdr)
804                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
805
806                 /* check the results of ast_call */
807                 if (res) {
808                         /* Again, keep going even if there's an error */
809                         if (option_debug)
810                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
811                         else if (option_verbose > 2)
812                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
813                         ast_hangup(tmp->chan);
814                         free(tmp);
815                         cur = rest;
816                         continue;
817                 } else
818                         if (option_verbose > 2)
819                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
820                 /* Put them in the list of outgoing thingies...  We're ready now. 
821                    XXX If we're forcibly removed, these outgoing calls won't get
822                    hung up XXX */
823                 tmp->stillgoing = -1;
824                 tmp->next = outgoing;
825                 outgoing = tmp;
826                 /* If this line is up, don't try anybody else */
827                 if (outgoing->chan->_state == AST_STATE_UP)
828                         break;
829                 cur = rest;
830         } while(cur);
831         
832         if (timeout && !ast_strlen_zero(timeout)) {
833                 to = atoi(timeout);
834                 if (to > 0)
835                         to *= 1000;
836                 else
837                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
838         } else
839                 to = -1;
840
841         if (outgoing) {
842                 /* Our status will at least be NOANSWER */
843                 strncpy(status, "NOANSWER", sizeof(status) - 1);
844                 if (outgoing->musiconhold) {
845                         moh=1;
846                         ast_moh_start(chan, NULL);
847                 } else if (outgoing->ringbackonly) {
848                         ast_indicate(chan, AST_CONTROL_RINGING);
849                         sentringing++;
850                 }
851         } else
852                 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
853
854         time(&start_time);
855         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status));
856
857         if (!peer) {
858                 if (to) 
859                         /* Musta gotten hung up */
860                         res = -1;
861                  else 
862                         /* Nobody answered, next please? */
863                         res=0;
864                 
865                 goto out;
866         }
867         if (peer) {
868                 time(&answer_time);
869 #ifdef OSP_SUPPORT
870                 /* Once call is answered, ditch the OSP Handle */
871                 pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
872 #endif          
873                 strncpy(status, "ANSWER", sizeof(status) - 1);
874                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
875                    we will always return with -1 so that it is hung up properly after the 
876                    conversation.  */
877                 hanguptree(outgoing, peer);
878                 outgoing = NULL;
879                 /* If appropriate, log that we have a destination channel */
880                 if (chan->cdr)
881                         ast_cdr_setdestchan(chan->cdr, peer->name);
882                 if (peer->name)
883                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
884                 if (numsubst)
885                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
886                 /* JDG: sendurl */
887                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
888                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
889                         ast_channel_sendurl( peer, url );
890                 } /* /JDG */
891                 if (announce && announcemsg) {
892                         // Start autoservice on the other chan
893                         res = ast_autoservice_start(chan);
894                         // Now Stream the File
895                         if (!res)
896                                 res = ast_streamfile(peer,announcemsg,peer->language);
897                         if (!res) {
898                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
899                         }
900                         // Ok, done. stop autoservice
901                         res = ast_autoservice_stop(chan);
902                         if (digit > 0 && !res)
903                                 res = ast_senddigit(chan, digit); 
904                         else
905                                 res = digit;
906
907                 } else
908                         res = 0;
909
910                 if (!res) {
911                         if (calldurationlimit > 0) {
912                                 time(&now);
913                                 chan->whentohangup = now + calldurationlimit;
914                         }
915                         if (!ast_strlen_zero(sdtmfdata)) 
916                                 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
917                 }
918                 
919                 if (!res) {
920                         memset(&config,0,sizeof(struct ast_bridge_config));
921                         config.play_to_caller=play_to_caller;
922                         config.play_to_callee=play_to_callee;
923                         config.allowredirect_in = allowredir_in;
924                         config.allowredirect_out = allowredir_out;
925                         config.allowdisconnect_in = allowdisconnect_in;
926                         config.allowdisconnect_out = allowdisconnect_out;
927                         config.timelimit = timelimit;
928                         config.play_warning = play_warning;
929                         config.warning_freq = warning_freq;
930                         config.warning_sound = warning_sound;
931                         config.end_sound = end_sound;
932                         config.start_sound = start_sound;
933                         if (moh) {
934                                 moh = 0;
935                                 ast_moh_stop(chan);
936                         } else if (sentringing) {
937                                 sentringing = 0;
938                                 ast_indicate(chan, -1);
939                         }
940                         /* Be sure no generators are left on it */
941                         ast_deactivate_generator(chan);
942                         /* Make sure channels are compatible */
943                         res = ast_channel_make_compatible(chan, peer);
944                         if (res < 0) {
945                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
946                                 ast_hangup(peer);
947                                 return -1;
948                         }
949                         res = ast_bridge_call(chan,peer,&config);
950                         time(&end_time);
951                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
952                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
953                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
954                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
955                         
956                 } else 
957                         res = -1;
958                 
959                 if (res != AST_PBX_NO_HANGUP_PEER) {
960                         if (!chan->_softhangup)
961                                 chan->hangupcause = peer->hangupcause;
962                         ast_hangup(peer);
963                 }
964         }       
965 out:
966         if (moh) {
967                 moh = 0;
968                 ast_moh_stop(chan);
969         } else if (sentringing) {
970                 sentringing = 0;
971                 ast_indicate(chan, -1);
972         }
973         hanguptree(outgoing, NULL);
974         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
975         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
976         
977         LOCAL_USER_REMOVE(u);
978         
979         if((go_on>0) && (!chan->_softhangup))
980             res=0;
981             
982         return res;
983 }
984
985 int unload_module(void)
986 {
987         STANDARD_HANGUP_LOCALUSERS;
988         return ast_unregister_application(app);
989 }
990
991 int load_module(void)
992 {
993         int res;
994         res = ast_register_application(app, dial_exec, synopsis, descrip);
995         return res;
996 }
997
998 char *description(void)
999 {
1000         return tdesc;
1001 }
1002
1003 int usecount(void)
1004 {
1005         int res;
1006         STANDARD_USECOUNT(res);
1007         return res;
1008 }
1009
1010 char *key()
1011 {
1012         return ASTERISK_GPL_KEY;
1013 }