Save the dstchannel before the call gets answered so that we would know what destinat...
[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 && o->chan) {
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 && (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 && (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                                                         ast_hangup(o->chan);
232                                                         o->chan = NULL;
233                                                         o->stillgoing = 0;
234                                                         if (in->cdr)
235                                                                 ast_cdr_busy(in->cdr);
236                                                         numbusies++;
237                                                         break;
238                                                 case AST_CONTROL_CONGESTION:
239                                                         if (option_verbose > 2)
240                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
241                                                         ast_hangup(o->chan);
242                                                         o->chan = NULL;
243                                                         o->stillgoing = 0;
244                                                         if (in->cdr)
245                                                                 ast_cdr_busy(in->cdr);
246                                                         numbusies++;
247                                                         break;
248                                                 case AST_CONTROL_RINGING:
249                                                         if (option_verbose > 2)
250                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
251                                                         if (!sentringing && !moh) {
252                                                                 ast_indicate(in, AST_CONTROL_RINGING);
253                                                                 sentringing++;
254                                                                 ringind++;
255                                                         }
256                                                         break;
257                                                 case AST_CONTROL_PROGRESS:
258                                                         if (option_verbose > 2)
259                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
260                                                         ast_indicate(in, AST_CONTROL_PROGRESS);
261                                                         break;
262                                                 case AST_CONTROL_OFFHOOK:
263                                                         /* Ignore going off hook */
264                                                         break;
265                                                 case -1:
266                                                         if (option_verbose > 2)
267                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
268                                                         ast_indicate(in, -1);
269                                                         break;
270                                                 default:
271                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
272                                                 }
273                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
274                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
275                                                 if (ast_write(in, f)) 
276                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
277                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
278                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
279                                                 if (ast_write(in, f))
280                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
281                                         }
282                                         ast_frfree(f);
283                                 } else {
284                                         ast_hangup(o->chan);
285                                         o->chan = NULL;
286                                         o->stillgoing = 0;
287                                 }
288                         }
289                         o = o->next;
290                 }
291                 if (winner == in) {
292                         f = ast_read(in);
293 #if 0
294                         if (f && (f->frametype != AST_FRAME_VOICE))
295                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
296                         else if (!f || (f->frametype != AST_FRAME_VOICE))
297                                 printf("Hangup received on %s\n", in->name);
298 #endif
299                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
300                                 /* Got hung up */
301                                 *to=-1;
302                                 return NULL;
303                         }
304                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
305                                 (f->subclass == '*')) {
306                             if (option_verbose > 3)
307                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
308                                 *to=0;
309                                 return NULL;
310                         }
311                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
312                                 if (ast_write(outgoing->chan, f))
313                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
314                                 ast_frfree(f);
315                         }
316                 }
317                 if (!*to && (option_verbose > 2))
318                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
319         }
320         if (moh) {
321                 ast_moh_stop(in);
322         } else if (ringind) {
323                 ast_indicate(in, -1);
324         }
325
326         return peer;
327         
328 }
329
330 static int dial_exec(struct ast_channel *chan, void *data)
331 {
332         int res=-1;
333         struct localuser *u;
334         char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
335         char  privdb[256] = "", *s;
336         struct localuser *outgoing=NULL, *tmp;
337         struct ast_channel *peer;
338         int to;
339         int allowredir_in=0;
340         int allowredir_out=0;
341         int allowdisconnect=0;
342         int privacy=0;
343         int resetcdr=0;
344         int clearchannel=0;
345         char numsubst[AST_MAX_EXTENSION];
346         char restofit[AST_MAX_EXTENSION];
347         char *transfer = NULL;
348         char *newnum;
349         char callerid[256], *l, *n;
350         char *url=NULL; /* JDG */
351         struct ast_var_t *current;
352         struct varshead *headp, *newheadp;
353         struct ast_var_t *newvar;
354         
355         if (!data) {
356                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
357                 return -1;
358         }
359         
360         LOCAL_USER_ADD(u);
361         
362         /* Parse our arguments XXX Check for failure XXX */
363         strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
364         peers = info;
365         if (peers) {
366                 timeout = strchr(info, '|');
367                 if (timeout) {
368                         *timeout = '\0';
369                         timeout++;
370                         transfer = strchr(timeout, '|');
371                         if (transfer) {
372                                 *transfer = '\0';
373                                 transfer++;
374                                 /* JDG */
375                                 url = strchr(transfer, '|');
376                                 if (url) {
377                                         *url = '\0';
378                                         url++;
379                                         ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
380                                 } else 
381                                         ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
382                                 /* /JDG */
383                         }
384                 }
385         } else
386                 timeout = NULL;
387         if (!peers || !strlen(peers)) {
388                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
389                 goto out;
390         }
391         
392
393         if (transfer) {
394                 /* Extract privacy info from transfer */
395                 if ((s = strstr(transfer, "P("))) {
396                         privacy = 1;
397                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
398                         /* Overwrite with X's what was the privacy info */
399                         while(*s && (*s != ')')) 
400                                 *(s++) = 'X';
401                         if (*s)
402                                 *s = 'X';
403                         /* Now find the end of the privdb */
404                         s = strchr(privdb, ')');
405                         if (s)
406                                 *s = '\0';
407                         else {
408                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing '('\n");
409                                 privacy = 0;
410                         }
411                 } else if (strchr(transfer, 'P')) {
412                         /* No specified privdb */
413                         privacy = 1;
414                 } else if (strchr(transfer, 'C')) {
415                         resetcdr = 1;
416                 }
417         }
418         if (resetcdr && chan->cdr)
419                 ast_cdr_reset(chan->cdr, 0);
420         if (!strlen(privdb) && privacy) {
421                 /* If privdb is not specified and we are using privacy, copy from extension */
422                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
423         }
424         if (privacy) {
425                 if (chan->callerid)
426                         strncpy(callerid, chan->callerid, sizeof(callerid));
427                 else
428                         strcpy(callerid, "");
429                 ast_callerid_parse(callerid, &n, &l);
430                 if (l) {
431                         ast_shrink_phone_number(l);
432                 } else
433                         l = "";
434                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
435         }
436         cur = peers;
437         do {
438                 /* Remember where to start next time */
439                 rest = strchr(cur, '&');
440                 if (rest) {
441                         *rest = 0;
442                         rest++;
443                 }
444                 /* Get a technology/[device:]number pair */
445                 tech = cur;
446                 number = strchr(tech, '/');
447                 if (!number) {
448                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
449                         goto out;
450                 }
451                 *number = '\0';
452                 number++;
453                 tmp = malloc(sizeof(struct localuser));
454                 if (!tmp) {
455                         ast_log(LOG_WARNING, "Out of memory\n");
456                         goto out;
457                 }
458                 memset(tmp, 0, sizeof(struct localuser));
459                 if (transfer) {
460                         if (strchr(transfer, 't'))
461                                 tmp->allowredirect_in = 1;
462                         else    tmp->allowredirect_in = 0;
463                         if (strchr(transfer, 'T'))
464                                 tmp->allowredirect_out = 1;
465                         else    tmp->allowredirect_out = 0;
466                         if (strchr(transfer, 'r'))
467                                 tmp->ringbackonly = 1;
468                         else    tmp->ringbackonly = 0;
469                         if (strchr(transfer, 'm'))
470                                 tmp->musiconhold = 1;
471                         else    tmp->musiconhold = 0;
472                         if (strchr(transfer, 'd'))
473                                 tmp->dataquality = 1;
474                         else    tmp->dataquality = 0;
475                         if (strchr(transfer, 'H'))
476                                 allowdisconnect = tmp->allowdisconnect = 1;
477                         else    allowdisconnect = tmp->allowdisconnect = 0;
478                         if (strchr(transfer, 'c'))
479                                 clearchannel = 1;
480             else    
481                                 clearchannel = 0;
482                 }
483                 strncpy(numsubst, number, sizeof(numsubst)-1);
484                 /* If we're dialing by extension, look at the extension to know what to dial */
485                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
486                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
487                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
488                         if (option_debug)
489                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
490                 }
491                 /* Request the peer */
492                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
493                 if (!tmp->chan) {
494                         /* If we can't, just go on to the next call */
495                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
496                         if (chan->cdr)
497                                 ast_cdr_busy(chan->cdr);
498                         free(tmp);
499                         cur = rest;
500                         continue;
501                 }
502                 if (strlen(tmp->chan->call_forward)) {
503                         char tmpchan[256];
504                         if (option_verbose > 2)
505                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
506                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
507                         ast_hangup(tmp->chan);
508                         tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
509                         if (!tmp->chan) {
510                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
511                                 free(tmp);
512                                 cur = rest;
513                                 continue;
514                         }
515                 }
516                 /* If creating a SIP channel, look for a variable called */
517                 /* VXML_URL in the calling channel and copy it to the    */
518                 /* new channel.                                          */
519                 if (strcasecmp(tech,"SIP")==0)
520                 {
521                         headp=&chan->varshead;
522                         AST_LIST_TRAVERSE(headp,current,entries) {
523                                 if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
524                                 {
525                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
526                                         newheadp=&tmp->chan->varshead;
527                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
528                                         break;
529                                 }
530                         }
531                 }
532                 /* Check for ALERT_INFO in the SetVar list.  This is for   */
533                 /* SIP distinctive ring as per the RFC.  For Cisco 7960s,  */
534                 /* SetVar(ALERT_INFO=<x>) where x is an integer.  However, */
535                 /* the RFC says it should be a URL.  -- km-                */
536
537                 if (strcasecmp(tech,"SIP")==0)
538                 {
539                         headp=&chan->varshead;
540                         AST_LIST_TRAVERSE(headp,current,entries) {
541                                 /* Search for ALERT_INFO */
542                                 if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
543                                 {
544                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
545                                         newheadp=&tmp->chan->varshead;
546                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
547                                         break;
548                                 }
549                         }
550                 }
551                 
552                 tmp->chan->appl = "AppDial";
553                 tmp->chan->data = "(Outgoing Line)";
554                 tmp->chan->whentohangup = 0;
555                 if (tmp->chan->callerid)
556                         free(tmp->chan->callerid);
557                 if (tmp->chan->ani)
558                         free(tmp->chan->ani);
559                 if (chan->callerid)
560                         tmp->chan->callerid = strdup(chan->callerid);
561                 else
562                         tmp->chan->callerid = NULL;
563                 if (chan->ani)
564                         tmp->chan->ani = strdup(chan->ani);
565                 else
566                         tmp->chan->ani = NULL;
567                 /* Presense of ADSI CPE on outgoing channel follows ours */
568                 tmp->chan->adsicpe = chan->adsicpe;
569                 /* Place the call, but don't wait on the answer */
570                 res = ast_call(tmp->chan, numsubst, 0);
571
572                 /* Save the info in cdr's that we called them */
573                 if (chan->cdr)
574                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
575
576                 /* check the restuls of ast_call */
577                 if (res) {
578                         /* Again, keep going even if there's an error */
579                         if (option_debug)
580                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
581                         else if (option_verbose > 2)
582                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
583                         ast_hangup(tmp->chan);
584                         free(tmp);
585                         cur = rest;
586                         continue;
587                 } else
588                         if (option_verbose > 2)
589                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
590                 /* Put them in the list of outgoing thingies...  We're ready now. 
591                    XXX If we're forcibly removed, these outgoing calls won't get
592                    hung up XXX */
593                 tmp->stillgoing = -1;
594                 tmp->next = outgoing;
595                 outgoing = tmp;
596                 /* If this line is up, don't try anybody else */
597                 if (outgoing->chan->_state == AST_STATE_UP)
598                         break;
599                 cur = rest;
600         } while(cur);
601         
602         if (timeout && strlen(timeout))
603                 to = atoi(timeout) * 1000;
604         else
605                 to = -1;
606         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
607         if (!peer) {
608                 if (to) 
609                         /* Musta gotten hung up */
610                         res = -1;
611                  else 
612                         /* Nobody answered, next please? */
613                         res=0;
614                 
615                 goto out;
616         }
617         if (peer) {
618                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
619                    we will always return with -1 so that it is hung up properly after the 
620                    conversation.  */
621                 if (!strcmp(chan->type,"Zap"))
622                 {
623                         int x = 2;
624                         if (tmp->dataquality || clearchannel) x = 0;
625                         ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
626                 }                       
627                 if (!strcmp(peer->type,"Zap"))
628                 {
629                         int x = 2;
630                         if (tmp->dataquality || clearchannel) x = 0;
631                         ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
632                 }                       
633                 hanguptree(outgoing, peer);
634                 outgoing = NULL;
635                 /* If appropriate, log that we have a destination channel */
636                 if (chan->cdr)
637                         ast_cdr_setdestchan(chan->cdr, peer->name);
638                 if (peer->name)
639                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
640                 if (numsubst)
641                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
642                 /* Make sure channels are compatible */
643                 res = ast_channel_make_compatible(chan, peer);
644                 if (res < 0) {
645                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
646                         ast_hangup(peer);
647                         return -1;
648                 }
649                 /* JDG: sendurl */
650                 if( url && strlen(url) && ast_channel_supports_html(peer) ) {
651                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
652                         ast_channel_sendurl( peer, url );
653                 } /* /JDG */
654                 if (clearchannel)
655                 {
656                         int x = 0;
657                         ast_channel_setoption(chan,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
658                         ast_channel_setoption(peer,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
659                 }
660                 res = ast_bridge_call(chan, peer, allowredir_in, allowredir_out, allowdisconnect | clearchannel);
661                 if (clearchannel)
662                 {
663                         int x = 1;
664                         ast_channel_setoption(chan,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
665                         ast_channel_setoption(peer,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
666                 }
667
668                 if (res != AST_PBX_NO_HANGUP_PEER)
669                         ast_hangup(peer);
670         }       
671 out:
672         hanguptree(outgoing, NULL);
673         LOCAL_USER_REMOVE(u);
674         return res;
675 }
676
677 int unload_module(void)
678 {
679         STANDARD_HANGUP_LOCALUSERS;
680         return ast_unregister_application(app);
681 }
682
683 int load_module(void)
684 {
685         int res;
686         res = ast_register_application(app, dial_exec, synopsis, descrip);
687         return res;
688 }
689
690 char *description(void)
691 {
692         return tdesc;
693 }
694
695 int usecount(void)
696 {
697         int res;
698         STANDARD_USECOUNT(res);
699         return res;
700 }
701
702 char *key()
703 {
704         return ASTERISK_GPL_KEY;
705 }