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