Merge major BSD mutex and symbol conflict patches (bug #1816) (link patch still pending)
[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/config.h>
24 #include <asterisk/parking.h>
25 #include <asterisk/musiconhold.h>
26 #include <asterisk/callerid.h>
27 #include <asterisk/utils.h>
28 #include <asterisk/app.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <sys/time.h>
36 #include <sys/signal.h>
37 #include <netinet/in.h>
38
39 #include <pthread.h>
40
41 static char *tdesc = "Dialing Application";
42
43 static char *app = "Dial";
44
45 static char *synopsis = "Place a call and connect to the current channel";
46
47 static char *descrip =
48 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
49 "Requests one or more channels and places specified outgoing calls on them.\n"
50 "As soon as a channel answers, the Dial app will answer the originating\n"
51 "channel (if it needs to be answered) and will bridge a call with the channel\n"
52 "which first answered. All other calls placed by the Dial app will be hung up\n"
53 "If a timeout is not specified, the Dial application will wait indefinitely\n"
54 "until either one of the called channels answers, the user hangs up, or all\n"
55 "channels return busy or error. In general, the dialer will return 0 if it\n"
56 "was unable to place the call, or the timeout expired. However, if all\n"
57 "channels were busy, and there exists an extension with priority n+101 (where\n"
58 "n is the priority of the dialer instance), then it will be the next\n"
59 "executed extension (this allows you to setup different behavior on busy from\n"
60 "no-answer).\n"
61 "  This application returns -1 if the originating channel hangs up, or if the\n"
62 "call is bridged and either of the parties in the bridge terminate the call.\n"
63 "The option string may contain zero or more of the following characters:\n"
64 "      't' -- allow the called user transfer the calling user by hitting #.\n"
65 "      'T' -- allow the calling user to transfer the call by hitting #.\n"
66 "      'f' -- Forces callerid to be set as the extension of the line making/redirecting the outgoing call.\n"
67 "             For example, some PSTNs don't allow callerids from other extensions then the ones\n"
68 "             that are assigned to you.\n"
69 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
70 "      'm' -- provide hold music to the calling party until answered.\n"
71 "      'H' -- allow caller to hang up by hitting *.\n"
72 "      'C' -- reset call detail record for this call.\n"
73 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
74 "      'g' -- goes on in context if the destination channel hangs up\n"
75 "      'A(x)' -- play an announcement to the called party, using x as file\n"
76 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
77 "      'D([digits])'  -- Send DTMF digit string *after* called party has answered\n"
78 "                        but before the bridge. (w=500ms sec pause)\n"
79 "      'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left (repeated every 'z' ms)\n"
80 "                     -- Only 'x' is required, 'y' and 'z' are optional.\n"
81 "                     -- The following special variables are optional:\n"
82 "                       ** LIMIT_PLAYAUDIO_CALLER    (default yes) Play sounds to the caller.\n"
83 "                       ** LIMIT_PLAYAUDIO_CALLEE    Play sounds to the callee.\n"
84 "                       ** LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
85 "                       ** LIMIT_CONNECT_FILE        File to play when call begins.\n"
86 "                       ** LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
87 "                     -- 'timeleft' is a special sound macro to auto-say the time left and is the default.\n\n"
88 "  In addition to transferring the call, a call may be parked and then picked\n"
89 "up by another user.\n"
90 "  The optional URL will be sent to the called party if the channel supports\n"
91 "it.\n";
92
93 /* We define a customer "local user" structure because we
94    use it not only for keeping track of what is in use but
95    also for keeping track of who we're dialing. */
96
97 struct localuser {
98         struct ast_channel *chan;
99         int stillgoing;
100         int allowredirect_in;
101         int allowredirect_out;
102         int ringbackonly;
103         int musiconhold;
104         int allowdisconnect;
105         int forcecallerid;
106         struct localuser *next;
107 };
108
109 LOCAL_USER_DECL;
110
111 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
112 {
113         /* Hang up a tree of stuff */
114         struct localuser *oo;
115         while(outgoing) {
116                 /* Hangup any existing lines we have open */
117                 if (outgoing->chan && (outgoing->chan != exception))
118                         ast_hangup(outgoing->chan);
119                 oo = outgoing;
120                 outgoing=outgoing->next;
121                 free(oo);
122         }
123 }
124
125 #define AST_MAX_WATCHERS 256
126
127 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, int *sentringing)
128 {
129         struct localuser *o;
130         int found;
131         int numlines;
132         int numbusies = 0;
133         int orig = *to;
134         struct ast_frame *f;
135         struct ast_channel *peer = NULL;
136         struct ast_channel *watchers[AST_MAX_WATCHERS];
137         int pos;
138         int single;
139         struct ast_channel *winner;
140         
141         single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
142         
143         if (single) {
144                 /* Turn off hold music, etc */
145                 ast_indicate(in, -1);
146                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
147                 ast_channel_make_compatible(outgoing->chan, in);
148         }
149         
150         
151         while(*to && !peer) {
152                 o = outgoing;
153                 found = -1;
154                 pos = 1;
155                 numlines = 0;
156                 watchers[0] = in;
157                 while(o) {
158                         /* Keep track of important channels */
159                         if (o->stillgoing && o->chan) {
160                                 watchers[pos++] = o->chan;
161                                 found = 1;
162                         }
163                         o = o->next;
164                         numlines++;
165                 }
166                 if (found < 0) {
167                         if (numlines == numbusies) {
168                                 if (option_verbose > 2)
169                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
170                                 /* See if there is a special busy message */
171                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) 
172                                         in->priority+=100;
173                         } else {
174                                 if (option_verbose > 2)
175                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
176                         }
177                         *to = 0;
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 (!ast_strlen_zero(o->chan->call_forward)) {
194                                         char tmpchan[256]="";
195                                         char *stuff;
196                                         char *tech;
197                                         strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
198                                         if ((stuff = strchr(tmpchan, '/'))) {
199                                                 *stuff = '\0';
200                                                 stuff++;
201                                                 tech = tmpchan;
202                                         } else {
203                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
204                                                 stuff = tmpchan;
205                                                 tech = "Local";
206                                         }
207                                         /* Before processing channel, go ahead and check for forwarding */
208                                         if (option_verbose > 2)
209                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
210                                         /* Setup parameters */
211                                         ast_hangup(o->chan);
212                                         o->chan = ast_request(tech, in->nativeformats, stuff);
213                                         if (!o->chan) {
214                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
215                                                 o->stillgoing = 0;
216                                                 numbusies++;
217                                         } else {
218                                                 if (o->chan->callerid)
219                                                         free(o->chan->callerid);
220
221                                                 o->chan->callerid = NULL;
222
223                                                 if (o->forcecallerid) {
224                                                         char *newcid = NULL;
225
226                                                         if (strlen(in->macroexten))
227                                                                 newcid = in->macroexten;
228                                                         else
229                                                                 newcid = in->exten;
230                                                         o->chan->callerid = strdup(newcid);
231                                                         if (!o->chan->callerid)
232                                                                 ast_log(LOG_WARNING, "Out of memory\n");
233                                                 } else {
234                                                         if (in->callerid)
235                                                                 o->chan->callerid = strdup(in->callerid);
236                                                         if (!o->chan->callerid)
237                                                                 ast_log(LOG_WARNING, "Out of memory\n");
238                                                 }
239
240                                                 if (in->ani) {
241                                                         if (o->chan->ani)
242                                                                 free(o->chan->ani);
243                                                         o->chan->ani = malloc(strlen(in->ani) + 1);
244                                                         if (o->chan->ani)
245                                                                 strncpy(o->chan->ani, in->ani, strlen(in->ani) + 1);
246                                                         else
247                                                                 ast_log(LOG_WARNING, "Out of memory\n");
248                                                 }
249                                                 if (o->chan->rdnis) 
250                                                         free(o->chan->rdnis);
251                                                 if (!ast_strlen_zero(in->macroexten))
252                                                         o->chan->rdnis = strdup(in->macroexten);
253                                                 else
254                                                         o->chan->rdnis = strdup(in->exten);
255                                                 if (ast_call(o->chan, tmpchan, 0)) {
256                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
257                                                         o->stillgoing = 0;
258                                                         ast_hangup(o->chan);
259                                                         o->chan = NULL;
260                                                         numbusies++;
261                                                 }
262                                         }
263                                         continue;
264                                 }
265                                 f = ast_read(winner);
266                                 if (f) {
267                                         if (f->frametype == AST_FRAME_CONTROL) {
268                                                 switch(f->subclass) {
269                                             case AST_CONTROL_ANSWER:
270                                                         /* This is our guy if someone answered. */
271                                                         if (!peer) {
272                                                                 if (option_verbose > 2)
273                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
274                                                                 peer = o->chan;
275                                                                 *allowredir_in = o->allowredirect_in;
276                                                                 *allowredir_out = o->allowredirect_out;
277                                                                 *allowdisconnect = o->allowdisconnect;
278                                                         }
279                                                         break;
280                                                 case AST_CONTROL_BUSY:
281                                                         if (option_verbose > 2)
282                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
283                                                         in->hangupcause = o->chan->hangupcause;
284                                                         ast_hangup(o->chan);
285                                                         o->chan = NULL;
286                                                         o->stillgoing = 0;
287                                                         if (in->cdr)
288                                                                 ast_cdr_busy(in->cdr);
289                                                         numbusies++;
290                                                         break;
291                                                 case AST_CONTROL_CONGESTION:
292                                                         if (option_verbose > 2)
293                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
294                                                         in->hangupcause = o->chan->hangupcause;
295                                                         ast_hangup(o->chan);
296                                                         o->chan = NULL;
297                                                         o->stillgoing = 0;
298                                                         if (in->cdr)
299                                                                 ast_cdr_busy(in->cdr);
300                                                         numbusies++;
301                                                         break;
302                                                 case AST_CONTROL_RINGING:
303                                                         if (option_verbose > 2)
304                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
305                                                         if (!*sentringing && !outgoing->musiconhold) {
306                                                                 ast_indicate(in, AST_CONTROL_RINGING);
307                                                                 *sentringing++;
308                                                         }
309                                                         break;
310                                                 case AST_CONTROL_PROGRESS:
311                                                         if (option_verbose > 2)
312                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
313                                                         ast_indicate(in, AST_CONTROL_PROGRESS);
314                                                         break;
315                                                 case AST_CONTROL_OFFHOOK:
316                                                         /* Ignore going off hook */
317                                                         break;
318                                                 case -1:
319                                                         if (!outgoing->ringbackonly && !outgoing->musiconhold) {
320                                                                 if (option_verbose > 2)
321                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
322                                                                 ast_indicate(in, -1);
323                                                                 *sentringing = 0;
324                                                         }
325                                                         break;
326                                                 default:
327                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
328                                                 }
329                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
330                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
331                                                 if (ast_write(in, f)) 
332                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
333                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
334                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
335                                                 if (ast_write(in, f))
336                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
337                                         }
338                                         ast_frfree(f);
339                                 } else {
340                                         in->hangupcause = o->chan->hangupcause;
341                                         ast_hangup(o->chan);
342                                         o->chan = NULL;
343                                         o->stillgoing = 0;
344                                 }
345                         }
346                         o = o->next;
347                 }
348                 if (winner == in) {
349                         f = ast_read(in);
350 #if 0
351                         if (f && (f->frametype != AST_FRAME_VOICE))
352                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
353                         else if (!f || (f->frametype != AST_FRAME_VOICE))
354                                 printf("Hangup received on %s\n", in->name);
355 #endif
356                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
357                                 /* Got hung up */
358                                 *to=-1;
359                                 return NULL;
360                         }
361                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
362                                 (f->subclass == '*')) {
363                             if (option_verbose > 3)
364                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
365                                 *to=0;
366                                 return NULL;
367                         }
368                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
369                                 if (ast_write(outgoing->chan, f))
370                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
371                                 ast_frfree(f);
372                         }
373                 }
374                 if (!*to && (option_verbose > 2))
375                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
376         }
377
378         return peer;
379         
380 }
381
382 static int dial_exec(struct ast_channel *chan, void *data)
383 {
384         int res=-1;
385         struct localuser *u;
386         char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
387         char  privdb[256] = "", *s;
388         char  announcemsg[256] = "", *ann;
389         struct localuser *outgoing=NULL, *tmp;
390         struct ast_channel *peer;
391         int to;
392         int allowredir_in=0;
393         int allowredir_out=0;
394         int allowdisconnect=0;
395         int privacy=0;
396         int announce=0;
397         int resetcdr=0;
398         char numsubst[AST_MAX_EXTENSION];
399         char restofit[AST_MAX_EXTENSION];
400         char *transfer = NULL;
401         char *newnum;
402         char callerid[256], *l, *n;
403         char *url=NULL; /* JDG */
404         struct ast_var_t *current;
405         struct varshead *headp, *newheadp;
406         struct ast_var_t *newvar;
407         int go_on=0;
408         unsigned int calldurationlimit=0;
409         char *cdl;
410         time_t now;
411         struct ast_bridge_config config;
412         long timelimit = 0;
413         long play_warning = 0;
414         long warning_freq=0;
415         char *warning_sound=NULL;
416         char *end_sound=NULL;
417         char *start_sound=NULL;
418         char *limitptr;
419         char limitdata[256];
420         char *sdtmfptr;
421         char sdtmfdata[256] = "";
422         char *stack,*var;
423         int play_to_caller=0,play_to_callee=0;
424         int playargs=0, sentringing=0, moh=0;
425         int digit = 0;
426
427         if (!data) {
428                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
429                 return -1;
430         }
431         
432         LOCAL_USER_ADD(u);
433         
434         strncpy(info, (char *)data, sizeof(info) - 1);
435         peers = info;
436         if (peers) {
437                 
438                 timeout = strchr(info, '|');
439                 if (timeout) {
440                         *timeout = '\0';
441                         timeout++;
442                         transfer = strchr(timeout, '|');
443                         if (transfer) {
444                                 *transfer = '\0';
445                                 transfer++;
446                                 /* JDG */
447                                 url = strchr(transfer, '|');
448                                 if (url) {
449                                         *url = '\0';
450                                         url++;
451                                         ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
452                                 } else 
453                                         ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
454                                 /* /JDG */
455                         }
456                 }
457         } else
458                 timeout = NULL;
459         if (!peers || ast_strlen_zero(peers)) {
460                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
461                 goto out;
462         }
463         
464
465         if (transfer) {
466
467                 /* Extract call duration limit */
468                 if ((cdl = strstr(transfer, "S("))) {
469                         calldurationlimit=atoi(cdl+2);
470                         if (option_verbose > 2)
471                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
472                 } 
473
474                 /* DTMF SCRIPT*/
475                 if ((sdtmfptr = strstr(transfer, "D("))) {
476                         strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
477                         /* Overwrite with X's what was the sdtmf info */
478                         while (*sdtmfptr && (*sdtmfptr != ')')) 
479                                 *(sdtmfptr++) = 'X';
480                         if (*sdtmfptr)
481                                 *sdtmfptr = 'X';
482                         /* Now find the end  */
483                         sdtmfptr = strchr(sdtmfdata, ')');
484                         if (sdtmfptr)
485                                 *sdtmfptr = '\0';
486                         else 
487                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
488                 }
489                 
490                 /* XXX LIMIT SUPPORT */
491                 if ((limitptr = strstr(transfer, "L("))) {
492                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
493                         /* Overwrite with X's what was the limit info */
494                         while(*limitptr && (*limitptr != ')')) 
495                                 *(limitptr++) = 'X';
496                         if (*limitptr)
497                                 *limitptr = 'X';
498                         /* Now find the end */
499                         limitptr = strchr(limitdata, ')');
500                         if (limitptr)
501                                 *limitptr = '\0';
502                         else
503                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
504
505                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
506                         play_to_caller = var ? ast_true(var) : 1;
507                   
508                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
509                         play_to_callee = var ? ast_true(var) : 0;
510                   
511                         if (!play_to_caller && !play_to_callee)
512                                 play_to_caller=1;
513                   
514                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
515                         warning_sound = var ? var : "timeleft";
516
517                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
518                         end_sound = var ? var : NULL;
519
520                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
521                         start_sound = var ? var : NULL;
522
523                         var=stack=limitdata;
524
525                         var = strsep(&stack, ":");
526                         if (var) {
527                                 timelimit = atol(var);
528                                 playargs++;
529                                 var = strsep(&stack, ":");
530                                 if (var) {
531                                         play_warning = atol(var);
532                                         playargs++;
533                                         var = strsep(&stack, ":");
534                                         if(var) {
535                                                 warning_freq = atol(var);
536                                                 playargs++;
537                                         }
538                                 }
539                         }
540                   
541                         if (!timelimit) {
542                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
543                                 warning_sound=NULL;
544                         }
545                         /* undo effect of S(x) in case they are both used */
546                         calldurationlimit=0; 
547                         /* more efficient do it like S(x) does since no advanced opts*/
548                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
549                                 calldurationlimit=timelimit/1000;
550                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
551                         } else if (option_verbose > 2) {
552                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
553                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
554                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
555                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
556                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
557                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
558                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
559                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
560                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
561                         }
562                 }
563                 
564                 /* XXX ANNOUNCE SUPPORT */
565                 if ((ann = strstr(transfer, "A("))) {
566                         announce = 1;
567                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
568                         /* Overwrite with X's what was the announce info */
569                         while(*ann && (*ann != ')')) 
570                                 *(ann++) = 'X';
571                         if (*ann)
572                                 *ann = 'X';
573                         /* Now find the end of the privdb */
574                         ann = strchr(announcemsg, ')');
575                         if (ann)
576                                 *ann = '\0';
577                         else {
578                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
579                                 announce = 0;
580                         }
581                 }
582                 /* Extract privacy info from transfer */
583                 if ((s = strstr(transfer, "P("))) {
584                         privacy = 1;
585                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
586                         /* Overwrite with X's what was the privacy info */
587                         while(*s && (*s != ')')) 
588                                 *(s++) = 'X';
589                         if (*s)
590                                 *s = 'X';
591                         /* Now find the end of the privdb */
592                         s = strchr(privdb, ')');
593                         if (s)
594                                 *s = '\0';
595                         else {
596                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
597                                 privacy = 0;
598                         }
599                 } else if (strchr(transfer, 'P')) {
600                         /* No specified privdb */
601                         privacy = 1;
602                 } else if (strchr(transfer, 'C')) {
603                         resetcdr = 1;
604                 }
605         }
606         if (resetcdr && chan->cdr)
607                 ast_cdr_reset(chan->cdr, 0);
608         if (ast_strlen_zero(privdb) && privacy) {
609                 /* If privdb is not specified and we are using privacy, copy from extension */
610                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
611         }
612         if (privacy) {
613                 if (chan->callerid)
614                         strncpy(callerid, chan->callerid, sizeof(callerid));
615                 else
616                         strcpy(callerid, "");
617                 ast_callerid_parse(callerid, &n, &l);
618                 if (l) {
619                         ast_shrink_phone_number(l);
620                 } else
621                         l = "";
622                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
623         }
624         cur = peers;
625         do {
626                 /* Remember where to start next time */
627                 rest = strchr(cur, '&');
628                 if (rest) {
629                         *rest = 0;
630                         rest++;
631                 }
632                 /* Get a technology/[device:]number pair */
633                 tech = cur;
634                 number = strchr(tech, '/');
635                 if (!number) {
636                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
637                         goto out;
638                 }
639                 *number = '\0';
640                 number++;
641                 tmp = malloc(sizeof(struct localuser));
642                 if (!tmp) {
643                         ast_log(LOG_WARNING, "Out of memory\n");
644                         goto out;
645                 }
646                 memset(tmp, 0, sizeof(struct localuser));
647                 if (transfer) {
648                         if (strchr(transfer, 't'))
649                                 tmp->allowredirect_in = 1;
650                         else    tmp->allowredirect_in = 0;
651                         if (strchr(transfer, 'T'))
652                                 tmp->allowredirect_out = 1;
653                         else    tmp->allowredirect_out = 0;
654                         if (strchr(transfer, 'r'))
655                                 tmp->ringbackonly = 1;
656                         else    tmp->ringbackonly = 0;
657                         if (strchr(transfer, 'm'))
658                                 tmp->musiconhold = 1;
659                         else    tmp->musiconhold = 0;
660                         if (strchr(transfer, 'H'))
661                                 allowdisconnect = tmp->allowdisconnect = 1;
662                         else    allowdisconnect = tmp->allowdisconnect = 0;
663                         if(strchr(transfer, 'g'))
664                                 go_on=1;
665                         if (strchr(transfer, 'f'))
666                                 tmp->forcecallerid = 1;
667                         else    tmp->forcecallerid = 0;
668                 }
669                 strncpy(numsubst, number, sizeof(numsubst)-1);
670                 /* If we're dialing by extension, look at the extension to know what to dial */
671                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
672                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
673                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
674                         if (option_debug)
675                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
676                 }
677                 /* Request the peer */
678                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
679                 if (!tmp->chan) {
680                         /* If we can't, just go on to the next call */
681                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
682                         if (chan->cdr)
683                                 ast_cdr_busy(chan->cdr);
684                         free(tmp);
685                         cur = rest;
686                         continue;
687                 }
688                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
689                         char tmpchan[256]="";
690                         char *stuff;
691                         char *tech;
692                         strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
693                         if ((stuff = strchr(tmpchan, '/'))) {
694                                 *stuff = '\0';
695                                 stuff++;
696                                 tech = tmpchan;
697                         } else {
698                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
699                                 stuff = tmpchan;
700                                 tech = "Local";
701                         }
702                         /* Before processing channel, go ahead and check for forwarding */
703                         if (option_verbose > 2)
704                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
705                         /* Setup parameters */
706                         ast_hangup(tmp->chan);
707                         tmp->chan = ast_request(tech, chan->nativeformats, stuff);
708                         if (!tmp->chan) {
709                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
710                                 free(tmp);
711                                 cur = rest;
712                                 continue;
713                         }
714                 }
715                 /* If creating a SIP channel, look for a variable called */
716                 /* VXML_URL in the calling channel and copy it to the    */
717                 /* new channel.                                          */
718                 if (strcasecmp(tech,"SIP")==0)
719                 {
720                         headp=&chan->varshead;
721                         AST_LIST_TRAVERSE(headp,current,entries) {
722                                 if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
723                                 {
724                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
725                                         newheadp=&tmp->chan->varshead;
726                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
727                                         break;
728                                 }
729                         }
730                 }
731                 /* Check for ALERT_INFO in the SetVar list.  This is for   */
732                 /* SIP distinctive ring as per the RFC.  For Cisco 7960s,  */
733                 /* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
734                 /* However, the RFC says it should be a URL.  -km-         */
735
736                 if (strcasecmp(tech,"SIP")==0)
737                 {
738                         headp=&chan->varshead;
739                         AST_LIST_TRAVERSE(headp,current,entries) {
740                                 /* Search for ALERT_INFO */
741                                 if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
742                                 {
743                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
744                                         newheadp=&tmp->chan->varshead;
745                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
746                                         break;
747                                 }
748                         }
749                 }
750                 
751                 tmp->chan->appl = "AppDial";
752                 tmp->chan->data = "(Outgoing Line)";
753                 tmp->chan->whentohangup = 0;
754                 if (tmp->chan->callerid)
755                         free(tmp->chan->callerid);
756                 if (tmp->chan->ani)
757                         free(tmp->chan->ani);
758                 if (chan->callerid)
759                         tmp->chan->callerid = strdup(chan->callerid);
760                 else
761                         tmp->chan->callerid = NULL;
762                 /* Copy language from incoming to outgoing */
763                 strcpy(tmp->chan->language, chan->language);
764                 if (ast_strlen_zero(tmp->chan->musicclass))
765                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
766                 if (chan->ani)
767                         tmp->chan->ani = strdup(chan->ani);
768                 else
769                         tmp->chan->ani = NULL;
770                 /* Pass hidecallerid setting */
771                 tmp->chan->restrictcid = chan->restrictcid;
772                 /* Pass callingpres setting */
773                 tmp->chan->callingpres = chan->callingpres;
774                 /* Presense of ADSI CPE on outgoing channel follows ours */
775                 tmp->chan->adsicpe = chan->adsicpe;
776                 /* pass the digital flag */
777                 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
778                 /* Place the call, but don't wait on the answer */
779                 res = ast_call(tmp->chan, numsubst, 0);
780
781                 /* Save the info in cdr's that we called them */
782                 if (chan->cdr)
783                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
784
785                 /* check the results of ast_call */
786                 if (res) {
787                         /* Again, keep going even if there's an error */
788                         if (option_debug)
789                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
790                         else if (option_verbose > 2)
791                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
792                         ast_hangup(tmp->chan);
793                         free(tmp);
794                         cur = rest;
795                         continue;
796                 } else
797                         if (option_verbose > 2)
798                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
799                 /* Put them in the list of outgoing thingies...  We're ready now. 
800                    XXX If we're forcibly removed, these outgoing calls won't get
801                    hung up XXX */
802                 tmp->stillgoing = -1;
803                 tmp->next = outgoing;
804                 outgoing = tmp;
805                 /* If this line is up, don't try anybody else */
806                 if (outgoing->chan->_state == AST_STATE_UP)
807                         break;
808                 cur = rest;
809         } while(cur);
810         
811         if (timeout && !ast_strlen_zero(timeout)) {
812                 to = atoi(timeout);
813                 if (to > 0)
814                         to *= 1000;
815                 else
816                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
817         } else
818                 to = -1;
819
820         if (outgoing) {
821                 if (outgoing->musiconhold) {
822                         moh=1;
823                         ast_moh_start(chan, NULL);
824                 } else if (outgoing->ringbackonly) {
825                         ast_indicate(chan, AST_CONTROL_RINGING);
826                         sentringing++;
827                 }
828         }
829
830         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &sentringing);
831
832         if (!peer) {
833                 if (to) 
834                         /* Musta gotten hung up */
835                         res = -1;
836                  else 
837                         /* Nobody answered, next please? */
838                         res=0;
839                 
840                 goto out;
841         }
842         if (peer) {
843                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
844                    we will always return with -1 so that it is hung up properly after the 
845                    conversation.  */
846                 hanguptree(outgoing, peer);
847                 outgoing = NULL;
848                 /* If appropriate, log that we have a destination channel */
849                 if (chan->cdr)
850                         ast_cdr_setdestchan(chan->cdr, peer->name);
851                 if (peer->name)
852                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
853                 if (numsubst)
854                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
855                 /* Make sure channels are compatible */
856                 res = ast_channel_make_compatible(chan, peer);
857                 if (res < 0) {
858                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
859                         ast_hangup(peer);
860                         return -1;
861                 }
862                 /* JDG: sendurl */
863                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
864                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
865                         ast_channel_sendurl( peer, url );
866                 } /* /JDG */
867                 if (announce && announcemsg) {
868                         // Start autoservice on the other chan
869                         res = ast_autoservice_start(chan);
870                         // Now Stream the File
871                         if (!res)
872                                 res = ast_streamfile(peer,announcemsg,peer->language);
873                         if (!res) {
874                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
875                         }
876                         // Ok, done. stop autoservice
877                         res = ast_autoservice_stop(chan);
878                         if (digit > 0 && !res)
879                                 res = ast_senddigit(chan, digit); 
880                         else
881                                 res = digit;
882
883                 } else
884                         res = 0;
885
886                 if (!res) {
887                         if (calldurationlimit > 0) {
888                                 time(&now);
889                                 chan->whentohangup = now + calldurationlimit;
890                         }
891                         if (!ast_strlen_zero(sdtmfdata)) 
892                                 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
893                 }
894                 
895                 if (!res) {
896                         memset(&config,0,sizeof(struct ast_bridge_config));
897                         config.play_to_caller=play_to_caller;
898                         config.play_to_callee=play_to_callee;
899                         config.allowredirect_in = allowredir_in;
900                         config.allowredirect_out = allowredir_out;
901                         config.allowdisconnect = allowdisconnect;
902                         config.timelimit = timelimit;
903                         config.play_warning = play_warning;
904                         config.warning_freq = warning_freq;
905                         config.warning_sound = warning_sound;
906                         config.end_sound = end_sound;
907                         config.start_sound = start_sound;
908                         if (moh) {
909                                 moh = 0;
910                                 ast_moh_stop(chan);
911                         } else if (sentringing) {
912                                 sentringing = 0;
913                                 ast_indicate(chan, -1);
914                         }
915                         res = ast_bridge_call(chan,peer,&config);
916                 } else 
917                         res = -1;
918                 
919                 if (res != AST_PBX_NO_HANGUP_PEER) {
920                         if (!chan->_softhangup)
921                                 chan->hangupcause = peer->hangupcause;
922                         ast_hangup(peer);
923                 }
924         }       
925 out:
926         if (moh) {
927                 moh = 0;
928                 ast_moh_stop(chan);
929         } else if (sentringing) {
930                 sentringing = 0;
931                 ast_indicate(chan, -1);
932         }
933         hanguptree(outgoing, NULL);
934         LOCAL_USER_REMOVE(u);
935         
936         if((go_on>0) && (!chan->_softhangup))
937             res=0;
938             
939         return res;
940 }
941
942 int unload_module(void)
943 {
944         STANDARD_HANGUP_LOCALUSERS;
945         return ast_unregister_application(app);
946 }
947
948 int load_module(void)
949 {
950         int res;
951         res = ast_register_application(app, dial_exec, synopsis, descrip);
952         return res;
953 }
954
955 char *description(void)
956 {
957         return tdesc;
958 }
959
960 int usecount(void)
961 {
962         int res;
963         STANDARD_USECOUNT(res);
964         return res;
965 }
966
967 char *key()
968 {
969         return ASTERISK_GPL_KEY;
970 }