35221aa93a7d8d1c92e93d49c09098fabcfa3ecd
[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 a 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 hung 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 dialer 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 dialer 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 "      'H' -- allow caller to hang up by hitting *.\n"
66 "      'C' -- reset call detail record for this call.\n"
67 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
68 "      'g' -- goes on in context if the destination channel hangs up\n"
69 "      'A(x)' -- play an announcement to the called party, using x as file\n"
70 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
71 "  In addition to transferring the call, a call may be parked and then picked\n"
72 "up by another user.\n"
73 "  The optional URL will be sent to the called party if the channel supports\n"
74 "it.\n";
75
76 /* We define a customer "local user" structure because we
77    use it not only for keeping track of what is in use but
78    also for keeping track of who we're dialing. */
79
80 struct localuser {
81         struct ast_channel *chan;
82         int stillgoing;
83         int allowredirect_in;
84         int allowredirect_out;
85         int ringbackonly;
86         int musiconhold;
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                 /* Turn off hold music, etc */
130                 ast_indicate(in, -1);
131                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
132                 ast_channel_make_compatible(outgoing->chan, in);
133         }
134         
135         if (outgoing) {
136                 moh = outgoing->musiconhold;
137                 ringind = outgoing->ringbackonly;
138                 if (outgoing->musiconhold) {
139                         ast_moh_start(in, NULL);
140                 } else if (outgoing->ringbackonly) {
141                         ast_indicate(in, AST_CONTROL_RINGING);
142                         sentringing++;
143                 }
144         }
145         
146         while(*to && !peer) {
147                 o = outgoing;
148                 found = -1;
149                 pos = 1;
150                 numlines = 0;
151                 watchers[0] = in;
152                 while(o) {
153                         /* Keep track of important channels */
154                         if (o->stillgoing && o->chan) {
155                                 watchers[pos++] = o->chan;
156                                 found = 1;
157                         }
158                         o = o->next;
159                         numlines++;
160                 }
161                 if (found < 0) {
162                         if (numlines == numbusies) {
163                                 if (option_verbose > 2)
164                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
165                                 /* See if there is a special busy message */
166                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) 
167                                         in->priority+=100;
168                         } else {
169                                 if (option_verbose > 2)
170                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
171                         }
172                         *to = 0;
173                         /* if no one available we'd better stop MOH/ringing to */
174                         if (moh) {
175                                 ast_moh_stop(in);
176                         } else if (sentringing) {
177                                 ast_indicate(in, -1);
178                         }
179                         return NULL;
180                 }
181                 winner = ast_waitfor_n(watchers, pos, to);
182                 o = outgoing;
183                 while(o) {
184                         if (o->stillgoing && o->chan && (o->chan->_state == AST_STATE_UP)) {
185                                 if (!peer) {
186                                         if (option_verbose > 2)
187                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
188                                         peer = o->chan;
189                                         *allowredir_in = o->allowredirect_in;
190                                         *allowredir_out = o->allowredirect_out;
191                                         *allowdisconnect = o->allowdisconnect;
192                                 }
193                         } else if (o->chan && (o->chan == winner)) {
194                                 if (strlen(o->chan->call_forward)) {
195                                         char tmpchan[256];
196                                         /* Before processing channel, go ahead and check for forwarding */
197                                         if (option_verbose > 2)
198                                                 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);
199                                         /* Setup parameters */
200                                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context);
201                                         ast_hangup(o->chan);
202                                         o->chan = ast_request("Local", in->nativeformats, tmpchan);
203                                         if (!o->chan) {
204                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
205                                                 o->stillgoing = 0;
206                                                 numbusies++;
207                                         } else {
208                                                 if (in->callerid) {
209                                                         if (o->chan->callerid)
210                                                                 free(o->chan->callerid);
211                                                         o->chan->callerid = malloc(strlen(in->callerid) + 1);
212                                                         if (o->chan->callerid)
213                                                                 strncpy(o->chan->callerid, in->callerid, strlen(in->callerid) + 1);
214                                                         else
215                                                                 ast_log(LOG_WARNING, "Out of memory\n");
216                                                 }
217                                                 if (in->ani) {
218                                                         if (o->chan->ani)
219                                                                 free(o->chan->ani);
220                                                         o->chan->ani = malloc(strlen(in->ani) + 1);
221                                                         if (o->chan->ani)
222                                                                 strncpy(o->chan->ani, in->ani, strlen(in->ani) + 1);
223                                                         else
224                                                                 ast_log(LOG_WARNING, "Out of memory\n");
225                                                 }
226                                                 if (o->chan->rdnis) 
227                                                         free(o->chan->rdnis);
228                                                 if (strlen(in->macroexten))
229                                                         o->chan->rdnis = strdup(in->macroexten);
230                                                 else
231                                                         o->chan->rdnis = strdup(in->exten);
232                                                 if (ast_call(o->chan, tmpchan, 0)) {
233                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
234                                                         o->stillgoing = 0;
235                                                         ast_hangup(o->chan);
236                                                         o->chan = NULL;
237                                                         numbusies++;
238                                                 }
239                                         }
240                                         continue;
241                                 }
242                                 f = ast_read(winner);
243                                 if (f) {
244                                         if (f->frametype == AST_FRAME_CONTROL) {
245                                                 switch(f->subclass) {
246                                             case AST_CONTROL_ANSWER:
247                                                         /* This is our guy if someone answered. */
248                                                         if (!peer) {
249                                                                 if (option_verbose > 2)
250                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
251                                                                 peer = o->chan;
252                                                                 *allowredir_in = o->allowredirect_in;
253                                                                 *allowredir_out = o->allowredirect_out;
254                                                                 *allowdisconnect = o->allowdisconnect;
255                                                         }
256                                                         break;
257                                                 case AST_CONTROL_BUSY:
258                                                         if (option_verbose > 2)
259                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
260                                                         in->hangupcause = o->chan->hangupcause;
261                                                         ast_hangup(o->chan);
262                                                         o->chan = NULL;
263                                                         o->stillgoing = 0;
264                                                         if (in->cdr)
265                                                                 ast_cdr_busy(in->cdr);
266                                                         numbusies++;
267                                                         break;
268                                                 case AST_CONTROL_CONGESTION:
269                                                         if (option_verbose > 2)
270                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
271                                                         in->hangupcause = o->chan->hangupcause;
272                                                         ast_hangup(o->chan);
273                                                         o->chan = NULL;
274                                                         o->stillgoing = 0;
275                                                         if (in->cdr)
276                                                                 ast_cdr_busy(in->cdr);
277                                                         numbusies++;
278                                                         break;
279                                                 case AST_CONTROL_RINGING:
280                                                         if (option_verbose > 2)
281                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
282                                                         if (!sentringing && !moh) {
283                                                                 ast_indicate(in, AST_CONTROL_RINGING);
284                                                                 sentringing++;
285                                                         }
286                                                         break;
287                                                 case AST_CONTROL_PROGRESS:
288                                                         if (option_verbose > 2)
289                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
290                                                         ast_indicate(in, AST_CONTROL_PROGRESS);
291                                                         break;
292                                                 case AST_CONTROL_OFFHOOK:
293                                                         /* Ignore going off hook */
294                                                         break;
295                                                 case -1:
296                                                         if (!ringind && !moh) {
297                                                                 if (option_verbose > 2)
298                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
299                                                                 ast_indicate(in, -1);
300                                                                 sentringing = 0;
301                                                         }
302                                                         break;
303                                                 default:
304                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
305                                                 }
306                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
307                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
308                                                 if (ast_write(in, f)) 
309                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
310                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
311                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
312                                                 if (ast_write(in, f))
313                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
314                                         }
315                                         ast_frfree(f);
316                                 } else {
317                                         in->hangupcause = o->chan->hangupcause;
318                                         ast_hangup(o->chan);
319                                         o->chan = NULL;
320                                         o->stillgoing = 0;
321                                 }
322                         }
323                         o = o->next;
324                 }
325                 if (winner == in) {
326                         f = ast_read(in);
327 #if 0
328                         if (f && (f->frametype != AST_FRAME_VOICE))
329                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
330                         else if (!f || (f->frametype != AST_FRAME_VOICE))
331                                 printf("Hangup received on %s\n", in->name);
332 #endif
333                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
334                                 /* Got hung up */
335                                 *to=-1;
336                                 return NULL;
337                         }
338                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
339                                 (f->subclass == '*')) {
340                             if (option_verbose > 3)
341                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
342                                 *to=0;
343                                 return NULL;
344                         }
345                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
346                                 if (ast_write(outgoing->chan, f))
347                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
348                                 ast_frfree(f);
349                         }
350                 }
351                 if (!*to && (option_verbose > 2))
352                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
353         }
354         if (moh) {
355                 ast_moh_stop(in);
356         } else if (sentringing) {
357                 ast_indicate(in, -1);
358         }
359
360         return peer;
361         
362 }
363
364 static int dial_exec(struct ast_channel *chan, void *data)
365 {
366         int res=-1;
367         struct localuser *u;
368         char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
369         char  privdb[256] = "", *s;
370         char  announcemsg[256] = "", *ann;
371         struct localuser *outgoing=NULL, *tmp;
372         struct ast_channel *peer;
373         int to;
374         int allowredir_in=0;
375         int allowredir_out=0;
376         int allowdisconnect=0;
377         int privacy=0;
378         int announce=0;
379         int resetcdr=0;
380         char numsubst[AST_MAX_EXTENSION];
381         char restofit[AST_MAX_EXTENSION];
382         char *transfer = NULL;
383         char *newnum;
384         char callerid[256], *l, *n;
385         char *url=NULL; /* JDG */
386         struct ast_var_t *current;
387         struct varshead *headp, *newheadp;
388         struct ast_var_t *newvar;
389         int go_on=0;
390         unsigned int calldurationlimit=0;
391         char *cdl;
392         time_t now;
393         
394         if (!data) {
395                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
396                 return -1;
397         }
398         
399         LOCAL_USER_ADD(u);
400         
401         strncpy(info, (char *)data, sizeof(info) - 1);
402         peers = info;
403         if (peers) {
404                 
405                 timeout = strchr(info, '|');
406                 if (timeout) {
407                         *timeout = '\0';
408                         timeout++;
409                         transfer = strchr(timeout, '|');
410                         if (transfer) {
411                                 *transfer = '\0';
412                                 transfer++;
413                                 /* JDG */
414                                 url = strchr(transfer, '|');
415                                 if (url) {
416                                         *url = '\0';
417                                         url++;
418                                         ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
419                                 } else 
420                                         ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
421                                 /* /JDG */
422                         }
423                 }
424         } else
425                 timeout = NULL;
426         if (!peers || !strlen(peers)) {
427                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
428                 goto out;
429         }
430         
431
432         if (transfer) {
433                 /* Extract call duration limit */
434                 if ((cdl = strstr(transfer, "S("))) {
435                         calldurationlimit=atoi(cdl+2);
436                         if (option_verbose > 2)
437                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
438                 } 
439                 
440                 /* XXX ANNOUNCE SUPPORT */
441                 if ((ann = strstr(transfer, "A("))) {
442                         announce = 1;
443                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
444                         /* Overwrite with X's what was the announce info */
445                         while(*ann && (*ann != ')')) 
446                                 *(ann++) = 'X';
447                         if (*ann)
448                                 *ann = 'X';
449                         /* Now find the end of the privdb */
450                         ann = strchr(announcemsg, ')');
451                         if (ann)
452                                 *ann = '\0';
453                         else {
454                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
455                                 announce = 0;
456                         }
457                 }
458                 /* Extract privacy info from transfer */
459                 if ((s = strstr(transfer, "P("))) {
460                         privacy = 1;
461                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
462                         /* Overwrite with X's what was the privacy info */
463                         while(*s && (*s != ')')) 
464                                 *(s++) = 'X';
465                         if (*s)
466                                 *s = 'X';
467                         /* Now find the end of the privdb */
468                         s = strchr(privdb, ')');
469                         if (s)
470                                 *s = '\0';
471                         else {
472                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
473                                 privacy = 0;
474                         }
475                 } else if (strchr(transfer, 'P')) {
476                         /* No specified privdb */
477                         privacy = 1;
478                 } else if (strchr(transfer, 'C')) {
479                         resetcdr = 1;
480                 }
481         }
482         if (resetcdr && chan->cdr)
483                 ast_cdr_reset(chan->cdr, 0);
484         if (!strlen(privdb) && privacy) {
485                 /* If privdb is not specified and we are using privacy, copy from extension */
486                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
487         }
488         if (privacy) {
489                 if (chan->callerid)
490                         strncpy(callerid, chan->callerid, sizeof(callerid));
491                 else
492                         strcpy(callerid, "");
493                 ast_callerid_parse(callerid, &n, &l);
494                 if (l) {
495                         ast_shrink_phone_number(l);
496                 } else
497                         l = "";
498                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
499         }
500         cur = peers;
501         do {
502                 /* Remember where to start next time */
503                 rest = strchr(cur, '&');
504                 if (rest) {
505                         *rest = 0;
506                         rest++;
507                 }
508                 /* Get a technology/[device:]number pair */
509                 tech = cur;
510                 number = strchr(tech, '/');
511                 if (!number) {
512                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
513                         goto out;
514                 }
515                 *number = '\0';
516                 number++;
517                 tmp = malloc(sizeof(struct localuser));
518                 if (!tmp) {
519                         ast_log(LOG_WARNING, "Out of memory\n");
520                         goto out;
521                 }
522                 memset(tmp, 0, sizeof(struct localuser));
523                 if (transfer) {
524                         if (strchr(transfer, 't'))
525                                 tmp->allowredirect_in = 1;
526                         else    tmp->allowredirect_in = 0;
527                         if (strchr(transfer, 'T'))
528                                 tmp->allowredirect_out = 1;
529                         else    tmp->allowredirect_out = 0;
530                         if (strchr(transfer, 'r'))
531                                 tmp->ringbackonly = 1;
532                         else    tmp->ringbackonly = 0;
533                         if (strchr(transfer, 'm'))
534                                 tmp->musiconhold = 1;
535                         else    tmp->musiconhold = 0;
536                         if (strchr(transfer, 'H'))
537                                 allowdisconnect = tmp->allowdisconnect = 1;
538                         else    allowdisconnect = tmp->allowdisconnect = 0;
539                         if(strchr(transfer, 'g'))
540                                 go_on=1;
541                 }
542                 strncpy(numsubst, number, sizeof(numsubst)-1);
543                 /* If we're dialing by extension, look at the extension to know what to dial */
544                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
545                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
546                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
547                         if (option_debug)
548                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
549                 }
550                 /* Request the peer */
551                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
552                 if (!tmp->chan) {
553                         /* If we can't, just go on to the next call */
554                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
555                         if (chan->cdr)
556                                 ast_cdr_busy(chan->cdr);
557                         free(tmp);
558                         cur = rest;
559                         continue;
560                 }
561                 if (strlen(tmp->chan->call_forward)) {
562                         char tmpchan[256];
563                         if (option_verbose > 2)
564                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
565                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
566                         ast_hangup(tmp->chan);
567                         tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
568                         if (!tmp->chan) {
569                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
570                                 free(tmp);
571                                 cur = rest;
572                                 continue;
573                         }
574                 }
575                 /* If creating a SIP channel, look for a variable called */
576                 /* VXML_URL in the calling channel and copy it to the    */
577                 /* new channel.                                          */
578                 if (strcasecmp(tech,"SIP")==0)
579                 {
580                         headp=&chan->varshead;
581                         AST_LIST_TRAVERSE(headp,current,entries) {
582                                 if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
583                                 {
584                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
585                                         newheadp=&tmp->chan->varshead;
586                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
587                                         break;
588                                 }
589                         }
590                 }
591                 /* Check for ALERT_INFO in the SetVar list.  This is for   */
592                 /* SIP distinctive ring as per the RFC.  For Cisco 7960s,  */
593                 /* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
594                 /* However, the RFC says it should be a URL.  -km-         */
595
596                 if (strcasecmp(tech,"SIP")==0)
597                 {
598                         headp=&chan->varshead;
599                         AST_LIST_TRAVERSE(headp,current,entries) {
600                                 /* Search for ALERT_INFO */
601                                 if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
602                                 {
603                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
604                                         newheadp=&tmp->chan->varshead;
605                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
606                                         break;
607                                 }
608                         }
609                 }
610                 
611                 tmp->chan->appl = "AppDial";
612                 tmp->chan->data = "(Outgoing Line)";
613                 tmp->chan->whentohangup = 0;
614                 if (tmp->chan->callerid)
615                         free(tmp->chan->callerid);
616                 if (tmp->chan->ani)
617                         free(tmp->chan->ani);
618                 if (chan->callerid)
619                         tmp->chan->callerid = strdup(chan->callerid);
620                 else
621                         tmp->chan->callerid = NULL;
622                 /* Copy language from incoming to outgoing */
623                 strcpy(tmp->chan->language, chan->language);
624                 if (!strlen(tmp->chan->musicclass))
625                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
626                 if (chan->ani)
627                         tmp->chan->ani = strdup(chan->ani);
628                 else
629                         tmp->chan->ani = NULL;
630                 /* Pass hidecallerid setting */
631                 tmp->chan->restrictcid = chan->restrictcid;
632                 /* Pass callingpres setting */
633                 tmp->chan->callingpres = chan->callingpres;
634                 /* Presense of ADSI CPE on outgoing channel follows ours */
635                 tmp->chan->adsicpe = chan->adsicpe;
636                 /* pass the digital flag */
637                 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
638                 /* Place the call, but don't wait on the answer */
639                 res = ast_call(tmp->chan, numsubst, 0);
640
641                 /* Save the info in cdr's that we called them */
642                 if (chan->cdr)
643                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
644
645                 /* check the restuls of ast_call */
646                 if (res) {
647                         /* Again, keep going even if there's an error */
648                         if (option_debug)
649                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
650                         else if (option_verbose > 2)
651                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
652                         ast_hangup(tmp->chan);
653                         free(tmp);
654                         cur = rest;
655                         continue;
656                 } else
657                         if (option_verbose > 2)
658                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
659                 /* Put them in the list of outgoing thingies...  We're ready now. 
660                    XXX If we're forcibly removed, these outgoing calls won't get
661                    hung up XXX */
662                 tmp->stillgoing = -1;
663                 tmp->next = outgoing;
664                 outgoing = tmp;
665                 /* If this line is up, don't try anybody else */
666                 if (outgoing->chan->_state == AST_STATE_UP)
667                         break;
668                 cur = rest;
669         } while(cur);
670         
671         if (timeout && strlen(timeout))
672                 to = atoi(timeout) * 1000;
673         else
674                 to = -1;
675         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
676         if (!peer) {
677                 if (to) 
678                         /* Musta gotten hung up */
679                         res = -1;
680                  else 
681                         /* Nobody answered, next please? */
682                         res=0;
683                 
684                 goto out;
685         }
686         if (peer) {
687                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
688                    we will always return with -1 so that it is hung up properly after the 
689                    conversation.  */
690                 hanguptree(outgoing, peer);
691                 outgoing = NULL;
692                 /* If appropriate, log that we have a destination channel */
693                 if (chan->cdr)
694                         ast_cdr_setdestchan(chan->cdr, peer->name);
695                 if (peer->name)
696                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
697                 if (numsubst)
698                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
699                 /* Make sure channels are compatible */
700                 res = ast_channel_make_compatible(chan, peer);
701                 if (res < 0) {
702                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
703                         ast_hangup(peer);
704                         return -1;
705                 }
706                 /* JDG: sendurl */
707                 if( url && strlen(url) && ast_channel_supports_html(peer) ) {
708                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
709                         ast_channel_sendurl( peer, url );
710                 } /* /JDG */
711                 if (announce && announcemsg)
712                 {
713                         int res2;
714                         // Start autoservice on the other chan
715                         res2 = ast_autoservice_start(chan);
716                         // Now Stream the File
717                         if (!res2)
718                                 res2 = ast_streamfile(peer,announcemsg,peer->language);
719                         if (!res2)
720                                 res2 = ast_waitstream(peer,"");
721                         // Ok, done. stop autoservice
722                         res2 = ast_autoservice_stop(chan);
723                 }
724                 if (calldurationlimit > 0) {
725                         time(&now);
726                         chan->whentohangup = now + calldurationlimit;
727                 }
728                 res = ast_bridge_call(chan, peer, allowredir_in, allowredir_out, allowdisconnect);
729
730                 if (res != AST_PBX_NO_HANGUP_PEER)
731                         ast_hangup(peer);
732         }       
733 out:
734         hanguptree(outgoing, NULL);
735         LOCAL_USER_REMOVE(u);
736         
737         if((go_on>0) && (!chan->_softhangup))
738             res=0;
739             
740         return res;
741 }
742
743 int unload_module(void)
744 {
745         STANDARD_HANGUP_LOCALUSERS;
746         return ast_unregister_application(app);
747 }
748
749 int load_module(void)
750 {
751         int res;
752         res = ast_register_application(app, dial_exec, synopsis, descrip);
753         return res;
754 }
755
756 char *description(void)
757 {
758         return tdesc;
759 }
760
761 int usecount(void)
762 {
763         int res;
764         STANDARD_USECOUNT(res);
765         return res;
766 }
767
768 char *key()
769 {
770         return ASTERISK_GPL_KEY;
771 }