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