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