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