Merge 'T' and other dialing enhancements
[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/parking.h>
24 #include <asterisk/musiconhold.h>
25 #include <asterisk/callerid.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <sys/time.h>
33 #include <sys/signal.h>
34 #include <netinet/in.h>
35
36 #include <pthread.h>
37
38 static char *tdesc = "Dialing Application";
39
40 static char *app = "Dial";
41
42 static char *synopsis = "Place an call and connect to the current channel";
43
44 static char *descrip =
45 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
46 "Requests  one  or more channels and places specified outgoing calls on them.\n"
47 "As soon as a  channel  answers, the  Dial  app  will  answer the originating\n"
48 "channel (if it needs to be answered) and will bridge a call with the channel\n"
49 "which first answered. All other calls placed by the Dial app will be hunp up\n"
50 "If a timeout is not specified, the Dial  application  will wait indefinitely\n"
51 "until either one of the  called channels  answers, the user hangs up, or all\n"
52 "channels return busy or  error. In general,  the dialler will return 0 if it\n"
53 "was  unable  to  place  the  call, or the timeout expired.  However, if  all\n"
54 "channels were busy, and there exists an extension with priority n+101 (where\n"
55 "n is the priority of  the  dialler  instance), then  it  will  be  the  next\n"
56 "executed extension (this allows you to setup different behavior on busy from\n"
57 "no-answer).\n"
58 "  This application returns -1 if the originating channel hangs up, or if the\n"
59 "call is bridged and  either of the parties in the bridge terminate the call.\n"
60 "The option string may contain zero or more of the following characters:\n"
61 "      't' -- allow the called user transfer the calling user\n"
62 "      'T' -- to allow the calling user to transfer the call.\n"
63 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
64 "      'm' -- provide hold music to the calling party until answered.\n"
65 "      'd' -- data-quality (modem) call (minimum delay).\n"
66 "      'c' -- clear-channel data call (PRI-PRI only).\n"
67 "      'H' -- allow caller to hang up by hitting *.\n"
68 "      'C' -- reset call detail record for this call.\n"
69 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
70 "  In addition to transferring the call, a call may be parked and then picked\n"
71 "up by another user.\n"
72 "  The optionnal URL will be sent to the called party if the channel supports\n"
73 "it.\n";
74
75 /* We define a customer "local user" structure because we
76    use it not only for keeping track of what is in use but
77    also for keeping track of who we're dialing. */
78
79 struct localuser {
80         struct ast_channel *chan;
81         int stillgoing;
82         int allowredirect_in;
83         int allowredirect_out;
84         int ringbackonly;
85         int musiconhold;
86         int dataquality;
87         int allowdisconnect;
88         struct localuser *next;
89 };
90
91 LOCAL_USER_DECL;
92
93 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
94 {
95         /* Hang up a tree of stuff */
96         struct localuser *oo;
97         while(outgoing) {
98                 /* Hangup any existing lines we have open */
99                 if (outgoing->chan && (outgoing->chan != exception))
100                         ast_hangup(outgoing->chan);
101                 oo = outgoing;
102                 outgoing=outgoing->next;
103                 free(oo);
104         }
105 }
106
107 #define MAX 256
108
109 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect)
110 {
111         struct localuser *o;
112         int found;
113         int numlines;
114         int sentringing = 0;
115         int numbusies = 0;
116         int orig = *to;
117         struct ast_frame *f;
118         struct ast_channel *peer = NULL;
119         struct ast_channel *watchers[MAX];
120         int pos;
121         int single;
122         int moh=0;
123         int ringind=0;
124         struct ast_channel *winner;
125         
126         single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
127         
128         if (single) {
129                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
130                 ast_channel_make_compatible(outgoing->chan, in);
131         }
132         
133         if (outgoing) {
134                 moh = outgoing->musiconhold;
135                 ringind = outgoing->ringbackonly;
136                 if (outgoing->musiconhold) {
137                         ast_moh_start(in, NULL);
138                 } else if (outgoing->ringbackonly) {
139                         ast_indicate(in, AST_CONTROL_RINGING);
140                 }
141         }
142         
143         while(*to && !peer) {
144                 o = outgoing;
145                 found = -1;
146                 pos = 1;
147                 numlines = 0;
148                 watchers[0] = in;
149                 while(o) {
150                         /* Keep track of important channels */
151                         if (o->stillgoing) {
152                                 watchers[pos++] = o->chan;
153                                 found = 1;
154                         }
155                         o = o->next;
156                         numlines++;
157                 }
158                 if (found < 0) {
159                         if (numlines == numbusies) {
160                                 if (option_verbose > 2)
161                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
162                                 /* See if there is a special busy message */
163                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) 
164                                         in->priority+=100;
165                         } else {
166                                 if (option_verbose > 2)
167                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
168                         }
169                         *to = 0;
170                         /* if no one available we'd better stop MOH/ringing to */
171                         if (moh) {
172                                 ast_moh_stop(in);
173                         } else if (ringind) {
174                                 ast_indicate(in, -1);
175                         }
176                         return NULL;
177                 }
178                 winner = ast_waitfor_n(watchers, pos, to);
179                 o = outgoing;
180                 while(o) {
181                         if (o->stillgoing && (o->chan->_state == AST_STATE_UP)) {
182                                 if (!peer) {
183                                         if (option_verbose > 2)
184                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
185                                         peer = o->chan;
186                                         *allowredir_in = o->allowredirect_in;
187                                         *allowredir_out = o->allowredirect_out;
188                                         *allowdisconnect = o->allowdisconnect;
189                                 }
190                         } else if (o->chan == winner) {
191                                 if (strlen(o->chan->call_forward)) {
192                                         char tmpchan[256];
193                                         /* Before processing channel, go ahead and check for forwarding */
194                                         if (option_verbose > 2)
195                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s@%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->context, o->chan->name);
196                                         /* Setup parameters */
197                                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context);
198                                         ast_hangup(o->chan);
199                                         o->chan = ast_request("Local", in->nativeformats, tmpchan);
200                                         if (!o->chan) {
201                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
202                                                 o->stillgoing = 0;
203                                                 numbusies++;
204                                         } else if (ast_call(o->chan, tmpchan, 0)) {
205                                                 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
206                                                 o->stillgoing = 0;
207                                                 ast_hangup(o->chan);
208                                                 o->chan = NULL;
209                                                         numbusies++;
210                                         }
211                                         continue;
212                                 }
213                                 f = ast_read(winner);
214                                 if (f) {
215                                         if (f->frametype == AST_FRAME_CONTROL) {
216                                                 switch(f->subclass) {
217                                             case AST_CONTROL_ANSWER:
218                                                         /* This is our guy if someone answered. */
219                                                         if (!peer) {
220                                                                 if (option_verbose > 2)
221                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
222                                                                 peer = o->chan;
223                                                                 *allowredir_in = o->allowredirect_in;
224                                                                 *allowredir_out = o->allowredirect_out;
225                                                                 *allowdisconnect = o->allowdisconnect;
226                                                         }
227                                                         break;
228                                                 case AST_CONTROL_BUSY:
229                                                         if (option_verbose > 2)
230                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
231                                                         o->stillgoing = 0;
232                                                         if (in->cdr)
233                                                                 ast_cdr_busy(in->cdr);
234                                                         numbusies++;
235                                                         break;
236                                                 case AST_CONTROL_CONGESTION:
237                                                         if (option_verbose > 2)
238                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
239                                                         o->stillgoing = 0;
240                                                         if (in->cdr)
241                                                                 ast_cdr_busy(in->cdr);
242                                                         numbusies++;
243                                                         break;
244                                                 case AST_CONTROL_RINGING:
245                                                         if (option_verbose > 2)
246                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
247                                                         if (!sentringing && !moh) {
248                                                                 ast_indicate(in, AST_CONTROL_RINGING);
249                                                                 sentringing++;
250                                                                 ringind++;
251                                                         }
252                                                         break;
253                                                 case AST_CONTROL_PROGRESS:
254                                                         if (option_verbose > 2)
255                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
256                                                         ast_indicate(in, AST_CONTROL_PROGRESS);
257                                                         break;
258                                                 case AST_CONTROL_OFFHOOK:
259                                                         /* Ignore going off hook */
260                                                         break;
261                                                 case -1:
262                                                         if (option_verbose > 2)
263                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
264                                                         ast_indicate(in, -1);
265                                                         break;
266                                                 default:
267                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
268                                                 }
269                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
270                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
271                                                 if (ast_write(in, f)) 
272                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
273                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
274                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
275                                                 if (ast_write(in, f))
276                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
277                                         }
278                                         ast_frfree(f);
279                                 } else {
280                                         o->stillgoing = 0;
281                                 }
282                         }
283                         o = o->next;
284                 }
285                 if (winner == in) {
286                         f = ast_read(in);
287 #if 0
288                         if (f && (f->frametype != AST_FRAME_VOICE))
289                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
290                         else if (!f || (f->frametype != AST_FRAME_VOICE))
291                                 printf("Hangup received on %s\n", in->name);
292 #endif
293                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
294                                 /* Got hung up */
295                                 *to=-1;
296                                 return NULL;
297                         }
298                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
299                                 (f->subclass == '*')) {
300                             if (option_verbose > 3)
301                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
302                                 *to=0;
303                                 return NULL;
304                         }
305                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
306                                 if (ast_write(outgoing->chan, f))
307                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
308                         }
309                 }
310                 if (!*to && (option_verbose > 2))
311                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
312         }
313         if (moh) {
314                 ast_moh_stop(in);
315         } else if (ringind) {
316                 ast_indicate(in, -1);
317         }
318
319         return peer;
320         
321 }
322
323 static int dial_exec(struct ast_channel *chan, void *data)
324 {
325         int res=-1;
326         struct localuser *u;
327         char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
328         char  privdb[256] = "", *s;
329         struct localuser *outgoing=NULL, *tmp;
330         struct ast_channel *peer;
331         int to;
332         int allowredir_in=0;
333         int allowredir_out=0;
334         int allowdisconnect=0;
335         int privacy=0;
336         int resetcdr=0;
337         int clearchannel=0;
338         char numsubst[AST_MAX_EXTENSION];
339         char restofit[AST_MAX_EXTENSION];
340         char *transfer = NULL;
341         char *newnum;
342         char callerid[256], *l, *n;
343         char *url=NULL; /* JDG */
344         struct ast_var_t *current;
345         struct varshead *headp, *newheadp;
346         struct ast_var_t *newvar;
347         
348         if (!data) {
349                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
350                 return -1;
351         }
352         
353         LOCAL_USER_ADD(u);
354         
355         /* Parse our arguments XXX Check for failure XXX */
356         strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
357         peers = info;
358         if (peers) {
359                 timeout = strchr(info, '|');
360                 if (timeout) {
361                         *timeout = '\0';
362                         timeout++;
363                         transfer = strchr(timeout, '|');
364                         if (transfer) {
365                                 *transfer = '\0';
366                                 transfer++;
367                                 /* JDG */
368                                 url = strchr(transfer, '|');
369                                 if (url) {
370                                         *url = '\0';
371                                         url++;
372                                         ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
373                                 } else 
374                                         ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
375                                 /* /JDG */
376                         }
377                 }
378         } else
379                 timeout = NULL;
380         if (!peers || !strlen(peers)) {
381                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
382                 goto out;
383         }
384         
385
386         if (transfer) {
387                 /* Extract privacy info from transfer */
388                 if ((s = strstr(transfer, "P("))) {
389                         privacy = 1;
390                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
391                         /* Overwrite with X's what was the privacy info */
392                         while(*s && (*s != ')')) 
393                                 *(s++) = 'X';
394                         if (*s)
395                                 *s = 'X';
396                         /* Now find the end of the privdb */
397                         s = strchr(privdb, ')');
398                         if (s)
399                                 *s = '\0';
400                         else {
401                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing '('\n");
402                                 privacy = 0;
403                         }
404                 } else if (strchr(transfer, 'P')) {
405                         /* No specified privdb */
406                         privacy = 1;
407                 } else if (strchr(transfer, 'C')) {
408                         resetcdr = 1;
409                 }
410         }
411         if (resetcdr && chan->cdr)
412                 ast_cdr_reset(chan->cdr, 0);
413         if (!strlen(privdb) && privacy) {
414                 /* If privdb is not specified and we are using privacy, copy from extension */
415                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
416         }
417         if (privacy) {
418                 if (chan->callerid)
419                         strncpy(callerid, chan->callerid, sizeof(callerid));
420                 else
421                         strcpy(callerid, "");
422                 ast_callerid_parse(callerid, &n, &l);
423                 if (l) {
424                         ast_shrink_phone_number(l);
425                 } else
426                         l = "";
427                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
428         }
429         cur = peers;
430         do {
431                 /* Remember where to start next time */
432                 rest = strchr(cur, '&');
433                 if (rest) {
434                         *rest = 0;
435                         rest++;
436                 }
437                 /* Get a technology/[device:]number pair */
438                 tech = cur;
439                 number = strchr(tech, '/');
440                 if (!number) {
441                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
442                         goto out;
443                 }
444                 *number = '\0';
445                 number++;
446                 tmp = malloc(sizeof(struct localuser));
447                 if (!tmp) {
448                         ast_log(LOG_WARNING, "Out of memory\n");
449                         goto out;
450                 }
451                 memset(tmp, 0, sizeof(struct localuser));
452                 if (transfer) {
453                         if (strchr(transfer, 't'))
454                                 tmp->allowredirect_in = 1;
455                         else    tmp->allowredirect_in = 0;
456                         if (strchr(transfer, 'T'))
457                                 tmp->allowredirect_out = 1;
458                         else    tmp->allowredirect_out = 0;
459                         if (strchr(transfer, 'r'))
460                                 tmp->ringbackonly = 1;
461                         else    tmp->ringbackonly = 0;
462                         if (strchr(transfer, 'm'))
463                                 tmp->musiconhold = 1;
464                         else    tmp->musiconhold = 0;
465                         if (strchr(transfer, 'd'))
466                                 tmp->dataquality = 1;
467                         else    tmp->dataquality = 0;
468                         if (strchr(transfer, 'H'))
469                                 allowdisconnect = tmp->allowdisconnect = 1;
470                         else    allowdisconnect = tmp->allowdisconnect = 0;
471                         if (strchr(transfer, 'c'))
472                                 clearchannel = 1;
473             else    
474                                 clearchannel = 0;
475                 }
476                 strncpy(numsubst, number, sizeof(numsubst)-1);
477                 /* If we're dialing by extension, look at the extension to know what to dial */
478                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
479                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
480                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
481                         if (option_debug)
482                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
483                 }
484                 /* Request the peer */
485                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
486                 if (!tmp->chan) {
487                         /* If we can't, just go on to the next call */
488                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
489                         if (chan->cdr)
490                                 ast_cdr_busy(chan->cdr);
491                         free(tmp);
492                         cur = rest;
493                         continue;
494                 }
495                 if (strlen(tmp->chan->call_forward)) {
496                         char tmpchan[256];
497                         if (option_verbose > 2)
498                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
499                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
500                         ast_hangup(tmp->chan);
501                         tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
502                         if (!tmp->chan) {
503                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
504                                 free(tmp);
505                                 cur = rest;
506                                 continue;
507                         }
508                 }
509                 /* If creating a SIP channel, look for a variable called */
510                 /* VXML_URL in the calling channel and copy it to the    */
511                 /* new channel.                                          */
512                 if (strcasecmp(tech,"SIP")==0)
513                 {
514                         headp=&chan->varshead;
515                         AST_LIST_TRAVERSE(headp,current,entries) {
516                                 if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
517                                 {
518                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
519                                         newheadp=&tmp->chan->varshead;
520                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
521                                         break;
522                                 }
523                         }
524                 }
525                 /* Check for ALERT_INFO in the SetVar list.  This is for   */
526                 /* SIP distinctive ring as per the RFC.  For Cisco 7960s,  */
527                 /* SetVar(ALERT_INFO=<x>) where x is an integer.  However, */
528                 /* the RFC says it should be a URL.  -- km-                */
529
530                 if (strcasecmp(tech,"SIP")==0)
531                 {
532                         headp=&chan->varshead;
533                         AST_LIST_TRAVERSE(headp,current,entries) {
534                                 /* Search for ALERT_INFO */
535                                 if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
536                                 {
537                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
538                                         newheadp=&tmp->chan->varshead;
539                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
540                                         break;
541                                 }
542                         }
543                 }
544                 
545                 tmp->chan->appl = "AppDial";
546                 tmp->chan->data = "(Outgoing Line)";
547                 tmp->chan->whentohangup = 0;
548                 if (tmp->chan->callerid)
549                         free(tmp->chan->callerid);
550                 if (tmp->chan->ani)
551                         free(tmp->chan->ani);
552                 if (chan->callerid)
553                         tmp->chan->callerid = strdup(chan->callerid);
554                 else
555                         tmp->chan->callerid = NULL;
556                 if (chan->ani)
557                         tmp->chan->ani = strdup(chan->ani);
558                 else
559                         tmp->chan->ani = NULL;
560                 /* Presense of ADSI CPE on outgoing channel follows ours */
561                 tmp->chan->adsicpe = chan->adsicpe;
562                 /* Place the call, but don't wait on the answer */
563                 res = ast_call(tmp->chan, numsubst, 0);
564                 if (res) {
565                         /* Again, keep going even if there's an error */
566                         if (option_debug)
567                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
568                         else if (option_verbose > 2)
569                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
570                         ast_hangup(tmp->chan);
571                         free(tmp);
572                         cur = rest;
573                         continue;
574                 } else
575                         if (option_verbose > 2)
576                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
577                 /* Put them in the list of outgoing thingies...  We're ready now. 
578                    XXX If we're forcibly removed, these outgoing calls won't get
579                    hung up XXX */
580                 tmp->stillgoing = -1;
581                 tmp->next = outgoing;
582                 outgoing = tmp;
583                 /* If this line is up, don't try anybody else */
584                 if (outgoing->chan->_state == AST_STATE_UP)
585                         break;
586                 cur = rest;
587         } while(cur);
588         
589         if (timeout && strlen(timeout))
590                 to = atoi(timeout) * 1000;
591         else
592                 to = -1;
593         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
594         if (!peer) {
595                 if (to) 
596                         /* Musta gotten hung up */
597                         res = -1;
598                  else 
599                         /* Nobody answered, next please? */
600                         res=0;
601                 
602                 goto out;
603         }
604         if (peer) {
605                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
606                    we will always return with -1 so that it is hung up properly after the 
607                    conversation.  */
608                 if (!strcmp(chan->type,"Zap"))
609                 {
610                         int x = 2;
611                         if (tmp->dataquality || clearchannel) x = 0;
612                         ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
613                 }                       
614                 if (!strcmp(peer->type,"Zap"))
615                 {
616                         int x = 2;
617                         if (tmp->dataquality || clearchannel) x = 0;
618                         ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
619                 }                       
620                 hanguptree(outgoing, peer);
621                 outgoing = NULL;
622                 /* If appropriate, log that we have a destination channel */
623                 if (chan->cdr)
624                         ast_cdr_setdestchan(chan->cdr, peer->name);
625                 if (peer->name)
626                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
627                 if (numsubst)
628                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
629                 /* Make sure channels are compatible */
630                 res = ast_channel_make_compatible(chan, peer);
631                 if (res < 0) {
632                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
633                         ast_hangup(peer);
634                         return -1;
635                 }
636                 /* JDG: sendurl */
637                 if( url && strlen(url) && ast_channel_supports_html(peer) ) {
638                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
639                         ast_channel_sendurl( peer, url );
640                 } /* /JDG */
641                 if (clearchannel)
642                 {
643                         int x = 0;
644                         ast_channel_setoption(chan,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
645                         ast_channel_setoption(peer,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
646                 }
647                 res = ast_bridge_call(chan, peer, allowredir_in, allowredir_out, allowdisconnect | clearchannel);
648                 if (clearchannel)
649                 {
650                         int x = 1;
651                         ast_channel_setoption(chan,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
652                         ast_channel_setoption(peer,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
653                 }
654
655                 if (res != AST_PBX_NO_HANGUP_PEER)
656                         ast_hangup(peer);
657         }       
658 out:
659         hanguptree(outgoing, NULL);
660         LOCAL_USER_REMOVE(u);
661         return res;
662 }
663
664 int unload_module(void)
665 {
666         STANDARD_HANGUP_LOCALUSERS;
667         return ast_unregister_application(app);
668 }
669
670 int load_module(void)
671 {
672         int res;
673         res = ast_register_application(app, dial_exec, synopsis, descrip);
674         return res;
675 }
676
677 char *description(void)
678 {
679         return tdesc;
680 }
681
682 int usecount(void)
683 {
684         int res;
685         STANDARD_USECOUNT(res);
686         return res;
687 }
688
689 char *key()
690 {
691         return ASTERISK_GPL_KEY;
692 }