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