bc1cfcb0719052fc7abcaf14c4d325aa47134afe
[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         char *varname;
486         int vartype;
487
488         int digit = 0;
489         time_t start_time, answer_time, end_time;
490
491         if (!data) {
492                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
493                 return -1;
494         }
495
496         if (!(info = ast_strdupa(data))) {
497                 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
498                 return -1;
499         }
500         LOCAL_USER_ADD(u);
501         
502         peers = info;
503         if (peers) {
504                 
505                 timeout = strchr(info, '|');
506                 if (timeout) {
507                         *timeout = '\0';
508                         timeout++;
509                         transfer = strchr(timeout, '|');
510                         if (transfer) {
511                                 *transfer = '\0';
512                                 transfer++;
513                                 /* JDG */
514                                 url = strchr(transfer, '|');
515                                 if (url) {
516                                         *url = '\0';
517                                         url++;
518                                         if (option_debug)
519                                                 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
520                                 } else 
521                                         if (option_debug) {
522                                                 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
523                                         }
524                                 /* /JDG */
525                         }
526                 }
527         } else
528                 timeout = NULL;
529         if (!peers || ast_strlen_zero(peers)) {
530                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
531                 goto out;
532         }
533         
534
535         if (transfer) {
536
537                 /* Extract call duration limit */
538                 if ((cdl = strstr(transfer, "S("))) {
539                         calldurationlimit=atoi(cdl+2);
540                         if (option_verbose > 2)
541                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
542                 } 
543
544                 /* DTMF SCRIPT*/
545                 if ((sdtmfptr = strstr(transfer, "D("))) {
546                         strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
547                         /* Overwrite with X's what was the sdtmf info */
548                         while (*sdtmfptr && (*sdtmfptr != ')')) 
549                                 *(sdtmfptr++) = 'X';
550                         if (*sdtmfptr)
551                                 *sdtmfptr = 'X';
552                         /* Now find the end  */
553                         sdtmfptr = strchr(sdtmfdata, ')');
554                         if (sdtmfptr)
555                                 *sdtmfptr = '\0';
556                         else 
557                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
558                 }
559                 
560                 /* XXX LIMIT SUPPORT */
561                 if ((limitptr = strstr(transfer, "L("))) {
562                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
563                         /* Overwrite with X's what was the limit info */
564                         while(*limitptr && (*limitptr != ')')) 
565                                 *(limitptr++) = 'X';
566                         if (*limitptr)
567                                 *limitptr = 'X';
568                         /* Now find the end */
569                         limitptr = strchr(limitdata, ')');
570                         if (limitptr)
571                                 *limitptr = '\0';
572                         else
573                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
574
575                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
576                         play_to_caller = var ? ast_true(var) : 1;
577                   
578                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
579                         play_to_callee = var ? ast_true(var) : 0;
580                   
581                         if (!play_to_caller && !play_to_callee)
582                                 play_to_caller=1;
583                   
584                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
585                         warning_sound = var ? var : "timeleft";
586
587                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
588                         end_sound = var ? var : NULL;
589
590                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
591                         start_sound = var ? var : NULL;
592
593                         var=stack=limitdata;
594
595                         var = strsep(&stack, ":");
596                         if (var) {
597                                 timelimit = atol(var);
598                                 playargs++;
599                                 var = strsep(&stack, ":");
600                                 if (var) {
601                                         play_warning = atol(var);
602                                         playargs++;
603                                         var = strsep(&stack, ":");
604                                         if(var) {
605                                                 warning_freq = atol(var);
606                                                 playargs++;
607                                         }
608                                 }
609                         }
610                   
611                         if (!timelimit) {
612                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
613                                 warning_sound=NULL;
614                         }
615                         /* undo effect of S(x) in case they are both used */
616                         calldurationlimit=0; 
617                         /* more efficient do it like S(x) does since no advanced opts*/
618                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
619                                 calldurationlimit=timelimit/1000;
620                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
621                         } else if (option_verbose > 2) {
622                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
623                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
624                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
625                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
626                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
627                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
628                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
629                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
630                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
631                         }
632                 }
633                 
634                 /* XXX ANNOUNCE SUPPORT */
635                 if ((ann = strstr(transfer, "A("))) {
636                         announce = 1;
637                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
638                         /* Overwrite with X's what was the announce info */
639                         while(*ann && (*ann != ')')) 
640                                 *(ann++) = 'X';
641                         if (*ann)
642                                 *ann = 'X';
643                         /* Now find the end of the privdb */
644                         ann = strchr(announcemsg, ')');
645                         if (ann)
646                                 *ann = '\0';
647                         else {
648                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
649                                 announce = 0;
650                         }
651                 }
652                 
653                 /* Get the macroname from the dial option string */
654                 if ((mac = strstr(transfer, "M("))) {
655                         hasmacro = 1;
656                         strncpy(macroname, mac + 2, sizeof(macroname) - 1);
657                         while (*mac && (*mac != ')'))
658                                 *(mac++) = 'X';
659                         if (*mac)
660                                 *mac = 'X';
661                         else {
662                                 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
663                                 hasmacro = 0;
664                         }
665                         mac = strchr(macroname, ')');
666                         if (mac)
667                                 *mac = '\0';
668                         else {
669                                 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
670                                 hasmacro = 0;
671                         }
672                 }
673                 /* Extract privacy info from transfer */
674                 if ((s = strstr(transfer, "P("))) {
675                         privacy = 1;
676                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
677                         /* Overwrite with X's what was the privacy info */
678                         while(*s && (*s != ')')) 
679                                 *(s++) = 'X';
680                         if (*s)
681                                 *s = 'X';
682                         /* Now find the end of the privdb */
683                         s = strchr(privdb, ')');
684                         if (s)
685                                 *s = '\0';
686                         else {
687                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
688                                 privacy = 0;
689                         }
690                 } else if (strchr(transfer, 'P')) {
691                         /* No specified privdb */
692                         privacy = 1;
693                 } else if (strchr(transfer, 'C')) {
694                         resetcdr = 1;
695                 }
696         }
697         if (resetcdr && chan->cdr)
698                 ast_cdr_reset(chan->cdr, 0);
699         if (ast_strlen_zero(privdb) && privacy) {
700                 /* If privdb is not specified and we are using privacy, copy from extension */
701                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
702         }
703         if (privacy) {
704                 l = chan->cid.cid_num;
705                 if (!l)
706                         l = "";
707                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
708         }
709         cur = peers;
710         do {
711                 /* Remember where to start next time */
712                 rest = strchr(cur, '&');
713                 if (rest) {
714                         *rest = 0;
715                         rest++;
716                 }
717                 /* Get a technology/[device:]number pair */
718                 tech = cur;
719                 number = strchr(tech, '/');
720                 if (!number) {
721                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
722                         goto out;
723                 }
724                 *number = '\0';
725                 number++;
726                 tmp = malloc(sizeof(struct localuser));
727                 if (!tmp) {
728                         ast_log(LOG_WARNING, "Out of memory\n");
729                         goto out;
730                 }
731                 memset(tmp, 0, sizeof(struct localuser));
732                 if (transfer) {
733                         if (strchr(transfer, 't'))
734                                 tmp->allowredirect_in = 1;
735                         else    tmp->allowredirect_in = 0;
736                         if (strchr(transfer, 'T'))
737                                 tmp->allowredirect_out = 1;
738                         else    tmp->allowredirect_out = 0;
739                         if (strchr(transfer, 'r'))
740                                 tmp->ringbackonly = 1;
741                         else    tmp->ringbackonly = 0;
742                         if (strchr(transfer, 'm'))
743                                 tmp->musiconhold = 1;
744                         else    tmp->musiconhold = 0;
745                         if (strchr(transfer, 'H'))
746                                 allowdisconnect_out = tmp->allowdisconnect_out = 1;
747                         else    allowdisconnect_out = tmp->allowdisconnect_out = 0;
748                         if(strchr(transfer, 'h'))
749                                 allowdisconnect_in = tmp->allowdisconnect_in = 1;
750                         else    allowdisconnect_in = tmp->allowdisconnect_in = 0;
751                         if(strchr(transfer, 'g'))
752                                 go_on=1;
753                         if (strchr(transfer, 'f'))
754                                 tmp->forcecallerid = 1;
755                         else    tmp->forcecallerid = 0;
756                 }
757                 strncpy(numsubst, number, sizeof(numsubst)-1);
758                 /* If we're dialing by extension, look at the extension to know what to dial */
759                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
760                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
761                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
762                         if (option_debug)
763                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
764                 }
765                 /* Request the peer */
766                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
767                 if (!tmp->chan) {
768                         /* If we can't, just go on to the next call */
769                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
770                         HANDLE_CAUSE(cause, chan);
771                         cur = rest;
772                         continue;
773                 }
774                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
775                         char tmpchan[256]="";
776                         char *stuff;
777                         char *tech;
778                         strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
779                         if ((stuff = strchr(tmpchan, '/'))) {
780                                 *stuff = '\0';
781                                 stuff++;
782                                 tech = tmpchan;
783                         } else {
784                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
785                                 stuff = tmpchan;
786                                 tech = "Local";
787                         }
788                         /* Before processing channel, go ahead and check for forwarding */
789                         if (option_verbose > 2)
790                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
791                         /* Setup parameters */
792                         ast_hangup(tmp->chan);
793                         tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
794                         if (!tmp->chan) {
795                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
796                                 HANDLE_CAUSE(cause, chan);
797                                 cur = rest;
798                                 continue;
799                         }
800                 }
801
802                 /* Contitionally copy channel variables to the newly created channel */
803                 headp = &chan->varshead;
804                 AST_LIST_TRAVERSE(headp, current, entries) {
805                         varname = ast_var_full_name(current);
806                         vartype = 0;
807                         if (varname) {
808                                 if (varname[0] == '_') {
809                                         vartype = 1;
810                                         if (varname[1] == '_')
811                                                 vartype = 2;
812                                 }
813                         }
814                         if (vartype == 1) {
815                                 newvar = ast_var_assign((char*)&(varname[1]), 
816                                                                                                 ast_var_value(current));
817                                 newheadp = &tmp->chan->varshead;
818                                 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
819                                 if (option_debug)
820                                         ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", 
821                                                                                                 ast_var_name(newvar));
822                         } else if (vartype == 2) {
823                                 newvar = ast_var_assign(ast_var_full_name(current), 
824                                                                                                 ast_var_value(current));
825                                 newheadp = &tmp->chan->varshead;
826                                 AST_LIST_INSERT_HEAD(newheadp, newvar, entries);
827                                 if (option_debug)
828                                         ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", 
829                                                                                                 ast_var_name(newvar));
830                         } else {
831                                 if (option_debug)
832                                         ast_log(LOG_DEBUG, "Not copying variable %s.\n", 
833                                                                                                 ast_var_name(current));
834                         }
835                 }
836
837                 tmp->chan->appl = "AppDial";
838                 tmp->chan->data = "(Outgoing Line)";
839                 tmp->chan->whentohangup = 0;
840                 if (tmp->chan->cid.cid_num)
841                         free(tmp->chan->cid.cid_num);
842                 tmp->chan->cid.cid_num = NULL;
843                 if (tmp->chan->cid.cid_name)
844                         free(tmp->chan->cid.cid_name);
845                 tmp->chan->cid.cid_name = NULL;
846                 if (tmp->chan->cid.cid_ani)
847                         free(tmp->chan->cid.cid_ani);
848                 tmp->chan->cid.cid_ani = NULL;
849
850                 if (chan->cid.cid_num) 
851                         tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
852                 if (chan->cid.cid_name) 
853                         tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
854                 if (chan->cid.cid_ani) 
855                         tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
856                 
857                 /* Copy language from incoming to outgoing */
858                 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
859                 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
860                 tmp->chan->cdrflags = chan->cdrflags;
861                 if (ast_strlen_zero(tmp->chan->musicclass))
862                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
863                 if (chan->cid.cid_rdnis)
864                         tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
865                 /* Pass callingpres setting */
866                 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
867                 /* Pass type of number */
868                 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
869                 /* Pass type of tns */
870                 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
871                 /* Presense of ADSI CPE on outgoing channel follows ours */
872                 tmp->chan->adsicpe = chan->adsicpe;
873                 /* pass the digital flag */
874                 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
875                 /* Place the call, but don't wait on the answer */
876                 res = ast_call(tmp->chan, numsubst, 0);
877
878                 /* Save the info in cdr's that we called them */
879                 if (chan->cdr)
880                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
881
882                 /* check the results of ast_call */
883                 if (res) {
884                         /* Again, keep going even if there's an error */
885                         if (option_debug)
886                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
887                         else if (option_verbose > 2)
888                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
889                         ast_hangup(tmp->chan);
890                         tmp->chan = NULL;
891                         continue;
892                 } else
893                         if (option_verbose > 2)
894                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
895                 /* Put them in the list of outgoing thingies...  We're ready now. 
896                    XXX If we're forcibly removed, these outgoing calls won't get
897                    hung up XXX */
898                 tmp->stillgoing = -1;
899                 tmp->next = outgoing;
900                 outgoing = tmp;
901                 /* If this line is up, don't try anybody else */
902                 if (outgoing->chan->_state == AST_STATE_UP)
903                         break;
904                 cur = rest;
905         } while(cur);
906         
907         if (timeout && !ast_strlen_zero(timeout)) {
908                 to = atoi(timeout);
909                 if (to > 0)
910                         to *= 1000;
911                 else
912                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
913         } else
914                 to = -1;
915
916         if (outgoing) {
917                 /* Our status will at least be NOANSWER */
918                 strncpy(status, "NOANSWER", sizeof(status) - 1);
919                 if (outgoing->musiconhold) {
920                         moh=1;
921                         ast_moh_start(chan, NULL);
922                 } else if (outgoing->ringbackonly) {
923                         ast_indicate(chan, AST_CONTROL_RINGING);
924                         sentringing++;
925                 }
926         } else
927                 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
928
929         time(&start_time);
930         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion);
931
932         if (!peer) {
933                 if (to) 
934                         /* Musta gotten hung up */
935                         res = -1;
936                  else 
937                         /* Nobody answered, next please? */
938                         res=0;
939                 
940                 goto out;
941         }
942         if (peer) {
943                 time(&answer_time);
944 #ifdef OSP_SUPPORT
945                 /* Once call is answered, ditch the OSP Handle */
946                 pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
947 #endif          
948                 strncpy(status, "ANSWER", sizeof(status) - 1);
949                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
950                    we will always return with -1 so that it is hung up properly after the 
951                    conversation.  */
952                 hanguptree(outgoing, peer);
953                 outgoing = NULL;
954                 /* If appropriate, log that we have a destination channel */
955                 if (chan->cdr)
956                         ast_cdr_setdestchan(chan->cdr, peer->name);
957                 if (peer->name)
958                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
959                 if (numsubst)
960                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
961                 /* JDG: sendurl */
962                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
963                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
964                         ast_channel_sendurl( peer, url );
965                 } /* /JDG */
966                 if (announce && announcemsg) {
967                         // Start autoservice on the other chan
968                         res = ast_autoservice_start(chan);
969                         // Now Stream the File
970                         if (!res)
971                                 res = ast_streamfile(peer,announcemsg,peer->language);
972                         if (!res) {
973                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
974                         }
975                         // Ok, done. stop autoservice
976                         res = ast_autoservice_stop(chan);
977                         if (digit > 0 && !res)
978                                 res = ast_senddigit(chan, digit); 
979                         else
980                                 res = digit;
981
982                 } else
983                         res = 0;
984
985                 if (hasmacro && macroname) {
986                         void *app = NULL;
987
988                         res = ast_autoservice_start(chan);
989                         if (res) {
990                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
991                                 res = -1;
992                         }
993
994                         app = pbx_findapp("Macro");
995
996                         if (app && !res) {
997                                 res = pbx_exec(peer, app, macroname, 1);
998                                 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
999                                 res = 0;
1000                         } else {
1001                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1002                                 res = -1;
1003                         }
1004
1005                         if (ast_autoservice_stop(chan) < 0) {
1006                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1007                                 res = -1;
1008                         }
1009                 }
1010
1011                 if (!res) {
1012                         if (calldurationlimit > 0) {
1013                                 time(&now);
1014                                 chan->whentohangup = now + calldurationlimit;
1015                         }
1016                         if (!ast_strlen_zero(sdtmfdata)) 
1017                                 res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
1018                 }
1019                 
1020                 if (!res) {
1021                         memset(&config,0,sizeof(struct ast_bridge_config));
1022                         config.play_to_caller=play_to_caller;
1023                         config.play_to_callee=play_to_callee;
1024                         config.allowredirect_in = allowredir_in;
1025                         config.allowredirect_out = allowredir_out;
1026                         config.allowdisconnect_in = allowdisconnect_in;
1027                         config.allowdisconnect_out = allowdisconnect_out;
1028                         config.timelimit = timelimit;
1029                         config.play_warning = play_warning;
1030                         config.warning_freq = warning_freq;
1031                         config.warning_sound = warning_sound;
1032                         config.end_sound = end_sound;
1033                         config.start_sound = start_sound;
1034                         if (moh) {
1035                                 moh = 0;
1036                                 ast_moh_stop(chan);
1037                         } else if (sentringing) {
1038                                 sentringing = 0;
1039                                 ast_indicate(chan, -1);
1040                         }
1041                         /* Be sure no generators are left on it */
1042                         ast_deactivate_generator(chan);
1043                         /* Make sure channels are compatible */
1044                         res = ast_channel_make_compatible(chan, peer);
1045                         if (res < 0) {
1046                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1047                                 ast_hangup(peer);
1048                                 return -1;
1049                         }
1050                         res = ast_bridge_call(chan,peer,&config);
1051                         time(&end_time);
1052                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1053                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1054                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1055                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1056                         
1057                 } else 
1058                         res = -1;
1059                 
1060                 if (res != AST_PBX_NO_HANGUP_PEER) {
1061                         if (!chan->_softhangup)
1062                                 chan->hangupcause = peer->hangupcause;
1063                         ast_hangup(peer);
1064                 }
1065         }       
1066 out:
1067         if (moh) {
1068                 moh = 0;
1069                 ast_moh_stop(chan);
1070         } else if (sentringing) {
1071                 sentringing = 0;
1072                 ast_indicate(chan, -1);
1073         }
1074         hanguptree(outgoing, NULL);
1075         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1076         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1077         
1078         LOCAL_USER_REMOVE(u);
1079         
1080         if((go_on>0) && (!chan->_softhangup))
1081             res=0;
1082             
1083         return res;
1084 }
1085
1086 int unload_module(void)
1087 {
1088         STANDARD_HANGUP_LOCALUSERS;
1089         return ast_unregister_application(app);
1090 }
1091
1092 int load_module(void)
1093 {
1094         int res;
1095         res = ast_register_application(app, dial_exec, synopsis, descrip);
1096         return res;
1097 }
1098
1099 char *description(void)
1100 {
1101         return tdesc;
1102 }
1103
1104 int usecount(void)
1105 {
1106         int res;
1107         STANDARD_USECOUNT(res);
1108         return res;
1109 }
1110
1111 char *key()
1112 {
1113         return ASTERISK_GPL_KEY;
1114 }