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