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