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