issue #5499
[asterisk/asterisk.git] / res / res_features.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Routines implementing call parking
22  * 
23  */
24
25 #include <pthread.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <sys/time.h>
33 #include <sys/signal.h>
34 #include <netinet/in.h>
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include "asterisk/lock.h"
41 #include "asterisk/file.h"
42 #include "asterisk/logger.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/options.h"
46 #include "asterisk/causes.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/app.h"
50 #include "asterisk/say.h"
51 #include "asterisk/features.h"
52 #include "asterisk/musiconhold.h"
53 #include "asterisk/config.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/manager.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/adsi.h"
58
59 #ifdef __AST_DEBUG_MALLOC
60 static void FREE(void *ptr)
61 {
62         free(ptr);
63 }
64 #else
65 #define FREE free
66 #endif
67
68 #define DEFAULT_PARK_TIME 45000
69 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
70 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
71
72 #define AST_MAX_WATCHERS 256
73
74 static char *parkedcall = "ParkedCall";
75
76 /* No more than 45 seconds parked before you do something with them */
77 static int parkingtime = DEFAULT_PARK_TIME;
78
79 /* Context for which parking is made accessible */
80 static char parking_con[AST_MAX_EXTENSION];
81
82 /* Context for dialback for parking (KLUDGE) */
83 static char parking_con_dial[AST_MAX_EXTENSION];
84
85 /* Extension you type to park the call */
86 static char parking_ext[AST_MAX_EXTENSION];
87
88 static char pickup_ext[AST_MAX_EXTENSION];
89
90 /* Default sounds */
91 static char courtesytone[256];
92 static char xfersound[256];
93 static char xferfailsound[256];
94
95 /* First available extension for parking */
96 static int parking_start;
97
98 /* Last available extension for parking */
99 static int parking_stop;
100
101 static int parking_offset;
102
103 static int parkfindnext;
104
105 static int adsipark;
106
107 static int transferdigittimeout;
108 static int featuredigittimeout;
109
110 /* Default courtesy tone played when party joins conference */
111
112 /* Registrar for operations */
113 static char *registrar = "res_features";
114
115 static char *synopsis = "Answer a parked call";
116
117 static char *descrip = "ParkedCall(exten):"
118 "Used to connect to a parked call.  This application is always\n"
119 "registered internally and does not need to be explicitly added\n"
120 "into the dialplan, although you should include the 'parkedcalls'\n"
121 "context.\n";
122
123 static char *parkcall = "Park";
124
125 static char *synopsis2 = "Park yourself";
126
127 static char *descrip2 = "Park(exten):"
128 "Used to park yourself (typically in combination with a supervised\n"
129 "transfer to know the parking space). This application is always\n"
130 "registered internally and does not need to be explicitly added\n"
131 "into the dialplan, although you should include the 'parkedcalls'\n"
132 "context.\n";
133
134 static struct ast_app *monitor_app=NULL;
135 static int monitor_ok=1;
136
137 struct parkeduser {
138         struct ast_channel *chan;
139         struct timeval start;
140         int parkingnum;
141         /* Where to go if our parking time expires */
142         char context[AST_MAX_CONTEXT];
143         char exten[AST_MAX_EXTENSION];
144         int priority;
145         int parkingtime;
146         int notquiteyet;
147         char peername[1024];
148         unsigned char moh_trys;
149         struct parkeduser *next;
150 };
151
152 static struct parkeduser *parkinglot;
153
154 AST_MUTEX_DEFINE_STATIC(parking_lock);
155
156 static pthread_t parking_thread;
157
158 STANDARD_LOCAL_USER;
159
160 LOCAL_USER_DECL;
161
162 char *ast_parking_ext(void)
163 {
164         return parking_ext;
165 }
166
167 char *ast_pickup_ext(void)
168 {
169         return pickup_ext;
170 }
171
172 struct ast_bridge_thread_obj 
173 {
174         struct ast_bridge_config bconfig;
175         struct ast_channel *chan;
176         struct ast_channel *peer;
177 };
178
179 static void check_goto_on_transfer(struct ast_channel *chan) 
180 {
181         struct ast_channel *xferchan;
182         char *goto_on_transfer;
183
184         goto_on_transfer = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
185
186         if (goto_on_transfer && !ast_strlen_zero(goto_on_transfer) && (xferchan = ast_channel_alloc(0))) {
187                 char *x;
188                 struct ast_frame *f;
189                 
190                 for (x = goto_on_transfer; x && *x; x++)
191                         if (*x == '^')
192                                 *x = '|';
193
194                 strcpy(xferchan->name, chan->name);
195                 /* Make formats okay */
196                 xferchan->readformat = chan->readformat;
197                 xferchan->writeformat = chan->writeformat;
198                 ast_channel_masquerade(xferchan, chan);
199                 ast_parseable_goto(xferchan, goto_on_transfer);
200                 xferchan->_state = AST_STATE_UP;
201                 ast_clear_flag(xferchan, AST_FLAGS_ALL);        
202                 xferchan->_softhangup = 0;
203                 if ((f = ast_read(xferchan))) {
204                         ast_frfree(f);
205                         f = NULL;
206                         ast_pbx_start(xferchan);
207                 } else {
208                         ast_hangup(xferchan);
209                 }
210         }
211 }
212
213 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name);
214
215
216 static void *ast_bridge_call_thread(void *data) 
217 {
218         struct ast_bridge_thread_obj *tobj = data;
219         tobj->chan->appl = "Transferred Call";
220         tobj->chan->data = tobj->peer->name;
221         tobj->peer->appl = "Transferred Call";
222         tobj->peer->data = tobj->chan->name;
223         if (tobj->chan->cdr) {
224                 ast_cdr_reset(tobj->chan->cdr,0);
225                 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
226         }
227         if (tobj->peer->cdr) {
228                 ast_cdr_reset(tobj->peer->cdr,0);
229                 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
230         }
231
232
233         ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
234         ast_hangup(tobj->chan);
235         ast_hangup(tobj->peer);
236         tobj->chan = tobj->peer = NULL;
237         free(tobj);
238         tobj=NULL;
239         return NULL;
240 }
241
242 static void ast_bridge_call_thread_launch(void *data) 
243 {
244         pthread_t thread;
245         pthread_attr_t attr;
246         int result;
247
248         result = pthread_attr_init(&attr);
249         pthread_attr_setschedpolicy(&attr, SCHED_RR);
250         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
251         result = ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
252         result = pthread_attr_destroy(&attr);
253 }
254
255
256
257 static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
258 {
259         int res;
260         int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
261         char tmp[256];
262         char *message[5] = {NULL, NULL, NULL, NULL, NULL};
263
264         snprintf(tmp, sizeof(tmp), "Parked on %d", parkingnum);
265         message[0] = tmp;
266         res = adsi_load_session(chan, NULL, 0, 1);
267         if (res == -1) {
268                 return res;
269         }
270         return adsi_print(chan, message, justify, 1);
271 }
272
273 /*--- ast_park_call: Park a call */
274 /* We put the user in the parking list, then wake up the parking thread to be sure it looks
275            after these channels too */
276 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
277 {
278         struct parkeduser *pu, *cur;
279         int i,x,parking_range;
280         char exten[AST_MAX_EXTENSION];
281         struct ast_context *con;
282
283         pu = malloc(sizeof(struct parkeduser));
284         if (!pu) {
285                 ast_log(LOG_WARNING, "Out of memory\n");
286                 return -1;
287         }
288         memset(pu, 0, sizeof(struct parkeduser));
289         ast_mutex_lock(&parking_lock);
290         parking_range = parking_stop - parking_start+1;
291         for (i = 0; i < parking_range; i++) {
292                 x = (i + parking_offset) % parking_range + parking_start;
293                 cur = parkinglot;
294                 while(cur) {
295                         if (cur->parkingnum == x) 
296                                 break;
297                         cur = cur->next;
298                 }
299                 if (!cur)
300                         break;
301         }
302
303         if (!(i < parking_range)) {
304                 ast_log(LOG_WARNING, "No more parking spaces\n");
305                 free(pu);
306                 ast_mutex_unlock(&parking_lock);
307                 return -1;
308         }
309         if (parkfindnext) 
310                 parking_offset = x - parking_start + 1;
311         chan->appl = "Parked Call";
312         chan->data = NULL; 
313
314         pu->chan = chan;
315         /* Start music on hold */
316         if (chan != peer) {
317                 ast_indicate(pu->chan, AST_CONTROL_HOLD);
318                 ast_moh_start(pu->chan, NULL);
319         }
320         pu->start = ast_tvnow();
321         pu->parkingnum = x;
322         if (timeout > 0)
323                 pu->parkingtime = timeout;
324         else
325                 pu->parkingtime = parkingtime;
326         if (extout)
327                 *extout = x;
328         if (peer) 
329                 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
330
331         /* Remember what had been dialed, so that if the parking
332            expires, we try to come back to the same place */
333         if (!ast_strlen_zero(chan->macrocontext))
334                 ast_copy_string(pu->context, chan->macrocontext, sizeof(pu->context));
335         else
336                 ast_copy_string(pu->context, chan->context, sizeof(pu->context));
337         if (!ast_strlen_zero(chan->macroexten))
338                 ast_copy_string(pu->exten, chan->macroexten, sizeof(pu->exten));
339         else
340                 ast_copy_string(pu->exten, chan->exten, sizeof(pu->exten));
341         if (chan->macropriority)
342                 pu->priority = chan->macropriority;
343         else
344                 pu->priority = chan->priority;
345         pu->next = parkinglot;
346         parkinglot = pu;
347         /* If parking a channel directly, don't quiet yet get parking running on it */
348         if (peer == chan) 
349                 pu->notquiteyet = 1;
350         ast_mutex_unlock(&parking_lock);
351         /* Wake up the (presumably select()ing) thread */
352         pthread_kill(parking_thread, SIGURG);
353         if (option_verbose > 1) 
354                 ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
355
356         manager_event(EVENT_FLAG_CALL, "ParkedCall",
357                 "Exten: %d\r\n"
358                 "Channel: %s\r\n"
359                 "From: %s\r\n"
360                 "Timeout: %ld\r\n"
361                 "CallerID: %s\r\n"
362                 "CallerIDName: %s\r\n\r\n"
363                 ,pu->parkingnum, pu->chan->name, peer->name
364                 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
365                 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
366                 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
367                 );
368
369         if (peer) {
370                 if (adsipark && adsi_available(peer)) {
371                         adsi_announce_park(peer, pu->parkingnum);
372                 }
373                 if (adsipark && adsi_available(peer)) {
374                         adsi_unload_session(peer);
375                 }
376         }
377         con = ast_context_find(parking_con);
378         if (!con) {
379                 con = ast_context_create(NULL, parking_con, registrar);
380                 if (!con) {
381                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
382                 }
383         }
384         if (con) {
385                 snprintf(exten, sizeof(exten), "%d", x);
386                 ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar);
387         }
388         if (peer) 
389                 ast_say_digits(peer, pu->parkingnum, "", peer->language);
390         if (pu->notquiteyet) {
391                 /* Wake up parking thread if we're really done */
392                 ast_moh_start(pu->chan, NULL);
393                 pu->notquiteyet = 0;
394                 pthread_kill(parking_thread, SIGURG);
395         }
396         return 0;
397 }
398
399 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
400 {
401         struct ast_channel *chan;
402         struct ast_frame *f;
403
404         /* Make a new, fake channel that we'll use to masquerade in the real one */
405         chan = ast_channel_alloc(0);
406         if (chan) {
407                 /* Let us keep track of the channel name */
408                 snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name);
409
410                 /* Make formats okay */
411                 chan->readformat = rchan->readformat;
412                 chan->writeformat = rchan->writeformat;
413                 ast_channel_masquerade(chan, rchan);
414
415                 /* Setup the extensions and such */
416                 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
417                 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
418                 chan->priority = rchan->priority;
419
420                 /* Make the masq execute */
421                 f = ast_read(chan);
422                 if (f)
423                         ast_frfree(f);
424                 ast_park_call(chan, peer, timeout, extout);
425         } else {
426                 ast_log(LOG_WARNING, "Unable to create parked channel\n");
427                 return -1;
428         }
429         return 0;
430 }
431
432
433 #define FEATURE_RETURN_HANGUP           -1
434 #define FEATURE_RETURN_SUCCESSBREAK      0
435 #define FEATURE_RETURN_PBX_KEEPALIVE    AST_PBX_KEEPALIVE
436 #define FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER
437 #define FEATURE_RETURN_PASSDIGITS        21
438 #define FEATURE_RETURN_STOREDIGITS       22
439 #define FEATURE_RETURN_SUCCESS           23
440
441 #define FEATURE_SENSE_CHAN      (1 << 0)
442 #define FEATURE_SENSE_PEER      (1 << 1)
443
444
445 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
446 {
447         char *touch_monitor = NULL, *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_format = NULL;
448         int x = 0;
449         size_t len;
450         struct ast_channel *caller_chan = NULL, *callee_chan = NULL;
451
452
453         if(sense == 2) {
454                 caller_chan = peer;
455                 callee_chan = chan;
456         } else {
457                 callee_chan = peer;
458                 caller_chan = chan;
459         }
460         
461         if (!monitor_ok) {
462                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
463                 return -1;
464         }
465
466         if (!monitor_app) { 
467                 if (!(monitor_app = pbx_findapp("Monitor"))) {
468                         monitor_ok=0;
469                         ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
470                         return -1;
471                 }
472         }
473         if (!ast_strlen_zero(courtesytone)) {
474                 if (ast_autoservice_start(callee_chan))
475                         return -1;
476                 if (!ast_streamfile(caller_chan, courtesytone, caller_chan->language)) {
477                         if (ast_waitstream(caller_chan, "") < 0) {
478                                 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
479                                 ast_autoservice_stop(callee_chan);
480                                 return -1;
481                         }
482                 }
483                 if (ast_autoservice_stop(callee_chan))
484                         return -1;
485         }
486         
487         if (callee_chan->monitor) {
488                 if (option_verbose > 3)
489                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
490                 ast_monitor_stop(callee_chan, 1);
491                 return FEATURE_RETURN_SUCCESS;
492         }
493
494         if (caller_chan && callee_chan) {
495                 touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
496                 if (!touch_format)
497                         touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
498
499                 touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
500                 if (!touch_monitor)
501                         touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
502                 
503                 if (touch_monitor) {
504                         len = strlen(touch_monitor) + 50;
505                         args = alloca(len);
506                         snprintf(args, len, "%s|auto-%ld-%s|m", (touch_format) ? touch_format : "wav", time(NULL), touch_monitor);
507                 } else {
508                         caller_chan_id = ast_strdupa(caller_chan->cid.cid_num ? caller_chan->cid.cid_num : caller_chan->name);
509                         callee_chan_id = ast_strdupa(callee_chan->cid.cid_num ? callee_chan->cid.cid_num : callee_chan->name);
510                         len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
511                         args = alloca(len);
512                         snprintf(args, len, "%s|auto-%ld-%s-%s|m", (touch_format) ? touch_format : "wav", time(NULL), caller_chan_id, callee_chan_id);
513                 }
514
515                 for( x = 0; x < strlen(args); x++)
516                         if (args[x] == '/')
517                                 args[x] = '-';
518                 
519                 if (option_verbose > 3)
520                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
521
522                 pbx_exec(callee_chan, monitor_app, args, 1);
523                 
524                 return FEATURE_RETURN_SUCCESS;
525         }
526         
527         ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");   
528         return -1;
529 }
530
531 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
532 {
533         if (option_verbose > 3)
534                 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
535         return FEATURE_RETURN_HANGUP;
536 }
537
538 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
539 {
540         struct ast_channel *transferer;
541         struct ast_channel *transferee;
542         char *transferer_real_context;
543         char newext[256];
544         int res;
545
546         if (sense == FEATURE_SENSE_PEER) {
547                 transferer = peer;
548                 transferee = chan;
549         } else {
550                 transferer = chan;
551                 transferee = peer;
552         }
553         if (!(transferer_real_context = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
554            !(transferer_real_context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
555                 /* Use the non-macro context to transfer the call */
556                 if (!ast_strlen_zero(transferer->macrocontext))
557                         transferer_real_context = transferer->macrocontext;
558                 else
559                         transferer_real_context = transferer->context;
560         }
561         /* Start autoservice on chan while we talk
562            to the originator */
563         ast_indicate(transferee, AST_CONTROL_HOLD);
564         ast_autoservice_start(transferee);
565         ast_moh_start(transferee, NULL);
566
567         memset(newext, 0, sizeof(newext));
568         
569         /* Transfer */
570         if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
571                 ast_moh_stop(transferee);
572                 ast_autoservice_stop(transferee);
573                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
574                 return res;
575         }
576         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
577                 ast_moh_stop(transferee);
578                 ast_autoservice_stop(transferee);
579                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
580                 return res;
581         } else if (res > 0) {
582                 /* If they've typed a digit already, handle it */
583                 newext[0] = (char) res;
584         }
585
586         ast_stopstream(transferer);
587         res = ast_app_dtget(transferer, transferer_real_context, newext, sizeof(newext), 100, transferdigittimeout);
588         if (res < 0) {
589                 ast_moh_stop(transferee);
590                 ast_autoservice_stop(transferee);
591                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
592                 return res;
593         }
594         if (!strcmp(newext, ast_parking_ext())) {
595                 ast_moh_stop(transferee);
596
597                 res = ast_autoservice_stop(transferee);
598                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
599                 if (res)
600                         res = -1;
601                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {
602                         /* We return non-zero, but tell the PBX not to hang the channel when
603                            the thread dies -- We have to be careful now though.  We are responsible for 
604                            hanging up the channel, else it will never be hung up! */
605
606                         if (transferer == peer)
607                                 res = AST_PBX_KEEPALIVE;
608                         else
609                                 res = AST_PBX_NO_HANGUP_PEER;
610                         return res;
611                 } else {
612                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
613                 }
614                 /* XXX Maybe we should have another message here instead of invalid extension XXX */
615         } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
616                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
617                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
618                 ast_moh_stop(transferee);
619                 res=ast_autoservice_stop(transferee);
620                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
621                 if (!transferee->pbx) {
622                         /* Doh!  Use our handy async_goto functions */
623                         if (option_verbose > 2) 
624                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
625                                                                 ,transferee->name, newext, transferer_real_context);
626                         if (ast_async_goto(transferee, transferer_real_context, newext, 1))
627                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
628                         res = -1;
629                 } else {
630                         /* Set the channel's new extension, since it exists, using transferer context */
631                         ast_copy_string(transferee->exten, newext, sizeof(transferee->exten));
632                         ast_copy_string(transferee->context, transferer_real_context, sizeof(transferee->context));
633                         transferee->priority = 0;
634                 }
635                 check_goto_on_transfer(transferer);
636                 return res;
637         } else {
638                 if (option_verbose > 2) 
639                         ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", newext, transferer_real_context);
640         }
641         if (!ast_strlen_zero(xferfailsound))
642                 res = ast_streamfile(transferer, xferfailsound, transferee->language);
643         else
644                 res = 0;
645         if (res) {
646                 ast_moh_stop(transferee);
647                 ast_autoservice_stop(transferee);
648                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
649                 return res;
650         }
651         res = ast_waitstream(transferer, AST_DIGIT_ANY);
652         ast_stopstream(transferer);
653         ast_moh_stop(transferee);
654         res = ast_autoservice_stop(transferee);
655         ast_indicate(transferee, AST_CONTROL_UNHOLD);
656         if (res) {
657                 if (option_verbose > 1)
658                         ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
659                 return res;
660         }
661         return FEATURE_RETURN_SUCCESS;
662 }
663
664 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
665 {
666         struct ast_channel *transferer;
667         struct ast_channel *transferee;
668         struct ast_channel *newchan, *xferchan=NULL;
669         int outstate=0;
670         struct ast_bridge_config bconfig;
671         char *transferer_real_context;
672         char xferto[256],dialstr[265];
673         char *cid_num;
674         char *cid_name;
675         int res;
676         struct ast_frame *f = NULL;
677         struct ast_bridge_thread_obj *tobj;
678
679         ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
680         if (sense == FEATURE_SENSE_PEER) {
681                 transferer = peer;
682                 transferee = chan;
683         } else {
684                 transferer = chan;
685                 transferee = peer;
686         }
687         if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
688            !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
689                 /* Use the non-macro context to transfer the call */
690                 if (!ast_strlen_zero(transferer->macrocontext))
691                         transferer_real_context = transferer->macrocontext;
692                 else
693                         transferer_real_context = transferer->context;
694         }
695         /* Start autoservice on chan while we talk
696            to the originator */
697         ast_indicate(transferee, AST_CONTROL_HOLD);
698         ast_autoservice_start(transferee);
699         ast_moh_start(transferee, NULL);
700         memset(xferto, 0, sizeof(xferto));
701         /* Transfer */
702         if ((res = ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
703                 ast_moh_stop(transferee);
704                 ast_autoservice_stop(transferee);
705                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
706                 return res;
707         }
708         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
709                 ast_moh_stop(transferee);
710                 ast_autoservice_stop(transferee);
711                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
712                 return res;
713         } else if(res > 0) {
714                 /* If they've typed a digit already, handle it */
715                 xferto[0] = (char) res;
716         }
717         if ((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
718                 cid_num = transferer->cid.cid_num;
719                 cid_name = transferer->cid.cid_name;
720                 if (ast_exists_extension(transferer, transferer_real_context,xferto, 1, cid_num)) {
721                         snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context);
722                         newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats), dialstr, 15000, &outstate, cid_num, cid_name);
723                         ast_indicate(transferer, -1);
724                         if (newchan) {
725                                 res = ast_channel_make_compatible(transferer, newchan);
726                                 if (res < 0) {
727                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
728                                         ast_hangup(newchan);
729                                         return -1;
730                                 }
731                                 memset(&bconfig,0,sizeof(struct ast_bridge_config));
732                                 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
733                                 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
734                                 res = ast_bridge_call(transferer,newchan,&bconfig);
735                                 if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
736                                         ast_hangup(newchan);
737                                         if (f) {
738                                                 ast_frfree(f);
739                                                 f = NULL;
740                                         }
741                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(transferer, xfersound, transferer->language)) {
742                                                 if (ast_waitstream(transferer, "") < 0) {
743                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
744                                                 }
745                                         }
746                                         ast_moh_stop(transferee);
747                                         ast_autoservice_stop(transferee);
748                                         ast_indicate(transferee, AST_CONTROL_UNHOLD);
749                                         transferer->_softhangup = 0;
750                                         return FEATURE_RETURN_SUCCESS;
751                                 }
752                                 
753                                 res = ast_channel_make_compatible(transferee, newchan);
754                                 if (res < 0) {
755                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
756                                         ast_hangup(newchan);
757                                         return -1;
758                                 }
759                                 
760                                 
761                                 ast_moh_stop(transferee);
762                                 
763                                 if ((ast_autoservice_stop(transferee) < 0)
764                                    || (ast_waitfordigit(transferee, 100) < 0)
765                                    || (ast_waitfordigit(newchan, 100) < 0) 
766                                    || ast_check_hangup(transferee) 
767                                    || ast_check_hangup(newchan)) {
768                                         ast_hangup(newchan);
769                                         res = -1;
770                                         return -1;
771                                 }
772
773                                 if ((xferchan = ast_channel_alloc(0))) {
774                                         snprintf(xferchan->name, sizeof (xferchan->name), "Transfered/%s",transferee->name);
775                                         /* Make formats okay */
776                                         xferchan->readformat = transferee->readformat;
777                                         xferchan->writeformat = transferee->writeformat;
778                                         ast_channel_masquerade(xferchan, transferee);
779                                         ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
780                                         xferchan->_state = AST_STATE_UP;
781                                         ast_clear_flag(xferchan, AST_FLAGS_ALL);        
782                                         xferchan->_softhangup = 0;
783
784                                         if ((f = ast_read(xferchan))) {
785                                                 ast_frfree(f);
786                                                 f = NULL;
787                                         }
788                                         
789                                 } else {
790                                         ast_hangup(newchan);
791                                         return -1;
792                                 }
793
794                                 newchan->_state = AST_STATE_UP;
795                                 ast_clear_flag(newchan, AST_FLAGS_ALL); 
796                                 newchan->_softhangup = 0;
797
798                                 tobj = malloc(sizeof(struct ast_bridge_thread_obj));
799                                 if (tobj) {
800                                         memset(tobj,0,sizeof(struct ast_bridge_thread_obj));
801                                         tobj->chan = xferchan;
802                                         tobj->peer = newchan;
803                                         tobj->bconfig = *config;
804         
805                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(newchan, xfersound, newchan->language)) {
806                                                 if (ast_waitstream(newchan, "") < 0) {
807                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
808                                                 }
809                                         }
810                                         ast_bridge_call_thread_launch(tobj);
811                                 } else {
812                                         ast_log(LOG_WARNING, "Out of memory!\n");
813                                         ast_hangup(xferchan);
814                                         ast_hangup(newchan);
815                                 }
816                                 return -1;
817                                 
818                         } else {
819                                 ast_moh_stop(transferee);
820                                 ast_autoservice_stop(transferee);
821                                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
822                                 /* any reason besides user requested cancel and busy triggers the failed sound */
823                                 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY && !ast_strlen_zero(xferfailsound)) {
824                                         res = ast_streamfile(transferer, xferfailsound, transferer->language);
825                                         if (!res && (ast_waitstream(transferer, "") < 0)) {
826                                                 return -1;
827                                         }
828                                 }
829                                 return FEATURE_RETURN_SUCCESS;
830                         }
831                 } else {
832                         ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
833                         ast_moh_stop(transferee);
834                         ast_autoservice_stop(transferee);
835                         ast_indicate(transferee, AST_CONTROL_UNHOLD);
836                         res = ast_streamfile(transferer, "beeperr", transferer->language);
837                         if (!res && (ast_waitstream(transferer, "") < 0)) {
838                                 return -1;
839                         }
840                 }
841         }  else {
842                 ast_log(LOG_WARNING, "Did not read data.\n");
843                 res = ast_streamfile(transferer, "beeperr", transferer->language);
844                 if (ast_waitstream(transferer, "") < 0) {
845                         return -1;
846                 }
847         }
848         ast_moh_stop(transferee);
849         ast_autoservice_stop(transferee);
850         ast_indicate(transferee, AST_CONTROL_UNHOLD);
851
852         return FEATURE_RETURN_SUCCESS;
853 }
854
855
856 /* add atxfer and automon as undefined so you can only use em if you configure them */
857 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
858 struct ast_call_feature builtin_features[] = 
859  {
860         { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
861         { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
862         { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
863         { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
864 };
865
866
867 static AST_LIST_HEAD(feature_list,ast_call_feature) feature_list;
868
869 /* register new feature into feature_list*/
870 void ast_register_feature(struct ast_call_feature *feature)
871 {
872         if (!feature) {
873                 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
874                 return;
875         }
876   
877         AST_LIST_LOCK(&feature_list);
878         AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
879         AST_LIST_UNLOCK(&feature_list);
880
881         if (option_verbose >= 2) 
882                 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
883 }
884
885 /* unregister feature from feature_list */
886 void ast_unregister_feature(struct ast_call_feature *feature)
887 {
888         if (!feature) return;
889
890         AST_LIST_LOCK(&feature_list);
891         AST_LIST_REMOVE(&feature_list,feature,feature_entry);
892         AST_LIST_UNLOCK(&feature_list);
893         free(feature);
894 }
895
896 static void ast_unregister_features(void)
897 {
898         struct ast_call_feature *feature;
899
900         AST_LIST_LOCK(&feature_list);
901         while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
902                 free(feature);
903         AST_LIST_UNLOCK(&feature_list);
904 }
905
906 /* find a feature by name */
907 static struct ast_call_feature *find_feature(char *name)
908 {
909         struct ast_call_feature *tmp;
910
911         AST_LIST_LOCK(&feature_list);
912         AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
913                 if (!strcasecmp(tmp->sname, name))
914                         break;
915         }
916         AST_LIST_UNLOCK(&feature_list);
917
918         return tmp;
919 }
920
921 /* exec an app by feature */
922 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
923 {
924         struct ast_app *app;
925         struct ast_call_feature *feature;
926         int res;
927
928         AST_LIST_LOCK(&feature_list);
929         AST_LIST_TRAVERSE(&feature_list,feature,feature_entry) {
930                 if (!strcasecmp(feature->exten,code)) break;
931         }
932         AST_LIST_UNLOCK(&feature_list);
933
934         if (!feature) { /* shouldn't ever happen! */
935                 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
936                 return -1; 
937         }
938         
939         app = pbx_findapp(feature->app);
940         if (app) {
941                 struct ast_channel *work=chan;
942                 if (ast_test_flag(feature,AST_FEATURE_FLAG_CALLEE)) work=peer;
943                 res = pbx_exec(work, app, feature->app_args, 1);
944                 if (res<0) return res; 
945         } else {
946                 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
947                 res = -2;
948         }
949         
950         return FEATURE_RETURN_SUCCESS;
951 }
952
953 static void unmap_features(void)
954 {
955         int x;
956         for (x = 0; x < FEATURES_COUNT; x++)
957                 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
958 }
959
960 static int remap_feature(const char *name, const char *value)
961 {
962         int x;
963         int res = -1;
964         for (x = 0; x < FEATURES_COUNT; x++) {
965                 if (!strcasecmp(name, builtin_features[x].sname)) {
966                         ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
967                         if (option_verbose > 1)
968                                 ast_verbose(VERBOSE_PREFIX_2 "Remapping feature %s (%s) to sequence '%s'\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
969                         res = 0;
970                 } else if (!strcmp(value, builtin_features[x].exten)) 
971                         ast_log(LOG_WARNING, "Sequence '%s' already mapped to function %s (%s) while assigning to %s\n", value, builtin_features[x].fname, builtin_features[x].sname, name);
972         }
973         return res;
974 }
975
976 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
977 {
978         int x;
979         struct ast_flags features;
980         int res = FEATURE_RETURN_PASSDIGITS;
981         struct ast_call_feature *feature;
982         char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
983
984         if (sense == FEATURE_SENSE_CHAN)
985                 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);   
986         else
987                 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);   
988         ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
989
990         for (x=0; x < FEATURES_COUNT; x++) {
991                 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
992                     !ast_strlen_zero(builtin_features[x].exten)) {
993                         /* Feature is up for consideration */
994                         if (!strcmp(builtin_features[x].exten, code)) {
995                                 res = builtin_features[x].operation(chan, peer, config, code, sense);
996                                 break;
997                         } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
998                                 if (res == FEATURE_RETURN_PASSDIGITS)
999                                         res = FEATURE_RETURN_STOREDIGITS;
1000                         }
1001                 }
1002         }
1003
1004
1005         if (dynamic_features && !ast_strlen_zero(dynamic_features)) {
1006                 char *tmp = ast_strdupa(dynamic_features);
1007                 char *tok;
1008
1009                 if (!tmp)
1010                         return res;
1011                 
1012                 while ((tok = strsep(&tmp, "#")) != NULL) {
1013                         feature = find_feature(tok);
1014                         
1015                         if (feature) {
1016                                 /* Feature is up for consideration */
1017                                 if (!strcmp(feature->exten, code)) {
1018                                         if (option_verbose > 2)
1019                                                 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1020                                         res = feature->operation(chan, peer, config, code, sense);
1021                                         break;
1022                                 } else if (!strncmp(feature->exten, code, strlen(code))) {
1023                                         res = FEATURE_RETURN_STOREDIGITS;
1024                                 }
1025                         }
1026                 }
1027         }
1028         
1029         return res;
1030 }
1031
1032 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1033 {
1034         int x;
1035         
1036         ast_clear_flag(config, AST_FLAGS_ALL);  
1037         for (x = 0; x < FEATURES_COUNT; x++) {
1038                 if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
1039                         if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1040                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1041
1042                         if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1043                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1044                 }
1045         }
1046         
1047         if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1048                 char *dynamic_features;
1049
1050                 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1051
1052                 if (dynamic_features) {
1053                         char *tmp = ast_strdupa(dynamic_features);
1054                         char *tok;
1055                         struct ast_call_feature *feature;
1056
1057                         if (!tmp) {
1058                                 return;
1059                         }
1060
1061                         /* while we have a feature */
1062                         while (NULL != (tok = strsep(&tmp, "#"))) {
1063                                 if ((feature = find_feature(tok))) {
1064                                         if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1065                                                 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
1066                                                         ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1067                                                 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
1068                                                         ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1069                                         }
1070                                 }
1071                         }
1072                 }
1073         }
1074 }
1075
1076
1077 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name)
1078 {
1079         int state = 0;
1080         int cause = 0;
1081         int to;
1082         struct ast_channel *chan;
1083         struct ast_channel *monitor_chans[2];
1084         struct ast_channel *active_channel;
1085         struct ast_frame *f = NULL;
1086         int res = 0, ready = 0;
1087         
1088         if ((chan = ast_request(type, format, data, &cause))) {
1089                 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1090                 ast_channel_inherit_variables(caller, chan);    
1091                 if (!ast_call(chan, data, timeout)) {
1092                         struct timeval started;
1093                         int x, len = 0;
1094                         char *disconnect_code = NULL, *dialed_code = NULL;
1095
1096                         ast_indicate(caller, AST_CONTROL_RINGING);
1097                         /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1098                         for (x=0; x < FEATURES_COUNT; x++) {
1099                                 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1100                                         continue;
1101
1102                                 disconnect_code = builtin_features[x].exten;
1103                                 len = strlen(disconnect_code) + 1;
1104                                 dialed_code = alloca(len);
1105                                 memset(dialed_code, 0, len);
1106                                 break;
1107                         }
1108                         x = 0;
1109                         started = ast_tvnow();
1110                         to = timeout;
1111                         while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1112                                 monitor_chans[0] = caller;
1113                                 monitor_chans[1] = chan;
1114                                 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1115
1116                                 /* see if the timeout has been violated */
1117                                 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1118                                         state = AST_CONTROL_UNHOLD;
1119                                         ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1120                                         break; /*doh! timeout*/
1121                                 }
1122
1123                                 if (!active_channel) {
1124                                         continue;
1125                                 }
1126
1127                                 if (chan && (chan == active_channel)){
1128                                         f = ast_read(chan);
1129                                         if (f == NULL) { /*doh! where'd he go?*/
1130                                                 state = AST_CONTROL_HANGUP;
1131                                                 res = 0;
1132                                                 break;
1133                                         }
1134                                         
1135                                         if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1136                                                 if (f->subclass == AST_CONTROL_RINGING) {
1137                                                         state = f->subclass;
1138                                                         if (option_verbose > 2)
1139                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1140                                                         ast_indicate(caller, AST_CONTROL_RINGING);
1141                                                 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1142                                                         state = f->subclass;
1143                                                         ast_frfree(f);
1144                                                         f = NULL;
1145                                                         break;
1146                                                 } else if (f->subclass == AST_CONTROL_ANSWER) {
1147                                                         /* This is what we are hoping for */
1148                                                         state = f->subclass;
1149                                                         ast_frfree(f);
1150                                                         f = NULL;
1151                                                         ready=1;
1152                                                         break;
1153                                                 } else {
1154                                                         ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1155                                                 }
1156                                                 /* else who cares */
1157                                         }
1158
1159                                 } else if (caller && (active_channel == caller)) {
1160                                         f = ast_read(caller);
1161                                         if (f == NULL) { /*doh! where'd he go?*/
1162                                                 if (caller->_softhangup && !chan->_softhangup) {
1163                                                         /* make this a blind transfer */
1164                                                         ready = 1;
1165                                                         break;
1166                                                 }
1167                                                 state = AST_CONTROL_HANGUP;
1168                                                 res = 0;
1169                                                 break;
1170                                         }
1171                                         
1172                                         if (f->frametype == AST_FRAME_DTMF) {
1173                                                 dialed_code[x++] = f->subclass;
1174                                                 dialed_code[x] = '\0';
1175                                                 if (strlen(dialed_code) == len) {
1176                                                         x = 0;
1177                                                 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1178                                                         x = 0;
1179                                                         dialed_code[x] = '\0';
1180                                                 }
1181                                                 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1182                                                         /* Caller Canceled the call */
1183                                                         state = AST_CONTROL_UNHOLD;
1184                                                         ast_frfree(f);
1185                                                         f = NULL;
1186                                                         break;
1187                                                 }
1188                                         }
1189                                 }
1190                                 if (f) {
1191                                         ast_frfree(f);
1192                                 }
1193                         }
1194                 } else
1195                         ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1196         } else {
1197                 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1198                 switch(cause) {
1199                 case AST_CAUSE_BUSY:
1200                         state = AST_CONTROL_BUSY;
1201                         break;
1202                 case AST_CAUSE_CONGESTION:
1203                         state = AST_CONTROL_CONGESTION;
1204                         break;
1205                 }
1206         }
1207         
1208         ast_indicate(caller, -1);
1209         if (chan && ready) {
1210                 if (chan->_state == AST_STATE_UP) 
1211                         state = AST_CONTROL_ANSWER;
1212                 res = 0;
1213         } else if(chan) {
1214                 res = -1;
1215                 ast_hangup(chan);
1216                 chan = NULL;
1217         } else {
1218                 res = -1;
1219         }
1220         
1221         if (outstate)
1222                 *outstate = state;
1223
1224         if (chan && res <= 0) {
1225                 if (!chan->cdr) {
1226                         chan->cdr = ast_cdr_alloc();
1227                 }
1228                 if (chan->cdr) {
1229                         char tmp[256];
1230                         ast_cdr_init(chan->cdr, chan);
1231                         snprintf(tmp, 256, "%s/%s", type, (char *)data);
1232                         ast_cdr_setapp(chan->cdr,"Dial",tmp);
1233                         ast_cdr_update(chan);
1234                         ast_cdr_start(chan->cdr);
1235                         ast_cdr_end(chan->cdr);
1236                         /* If the cause wasn't handled properly */
1237                         if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1238                                 ast_cdr_failed(chan->cdr);
1239                 } else {
1240                         ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1241                 }
1242         }
1243         
1244         return chan;
1245 }
1246
1247 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1248 {
1249         /* Copy voice back and forth between the two channels.  Give the peer
1250            the ability to transfer calls with '#<extension' syntax. */
1251         struct ast_frame *f;
1252         struct ast_channel *who;
1253         char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1254         char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1255         int res;
1256         int diff;
1257         int hasfeatures=0;
1258         int hadfeatures=0;
1259         struct ast_option_header *aoh;
1260         struct timeval start = { 0 , 0 };
1261         struct ast_bridge_config backup_config;
1262         int allowdisconnect_in, allowdisconnect_out, allowredirect_in, allowredirect_out;
1263         char *monitor_exec;
1264
1265         memset(&backup_config, 0, sizeof(backup_config));
1266
1267         config->start_time = ast_tvnow();
1268
1269         if (chan && peer) {
1270                 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1271                 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1272         } else if (chan)
1273                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1274
1275         if (monitor_ok) {
1276                 if (!monitor_app) { 
1277                         if (!(monitor_app = pbx_findapp("Monitor")))
1278                                 monitor_ok=0;
1279                 }
1280                 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
1281                         pbx_exec(chan, monitor_app, monitor_exec, 1);
1282                 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1283                         pbx_exec(peer, monitor_app, monitor_exec, 1);
1284         }
1285         
1286         allowdisconnect_in = ast_test_flag(&(config->features_callee), AST_FEATURE_DISCONNECT);
1287         allowdisconnect_out = ast_test_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
1288         allowredirect_in = ast_test_flag(&(config->features_callee), AST_FEATURE_REDIRECT);
1289         allowredirect_out = ast_test_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
1290         set_config_flags(chan, peer, config);
1291         config->firstpass = 1;
1292
1293         /* Answer if need be */
1294         if (ast_answer(chan))
1295                 return -1;
1296         peer->appl = "Bridged Call";
1297         peer->data = chan->name;
1298
1299         /* copy the userfield from the B-leg to A-leg if applicable */
1300         if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1301                 char tmp[256];
1302                 if (!ast_strlen_zero(chan->cdr->userfield)) {
1303                         snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1304                         ast_cdr_appenduserfield(chan, tmp);
1305                 } else
1306                         ast_cdr_setuserfield(chan, peer->cdr->userfield);
1307                 /* free the peer's cdr without ast_cdr_free complaining */
1308                 free(peer->cdr);
1309                 peer->cdr = NULL;
1310         }
1311         for (;;) {
1312                 if (config->feature_timer)
1313                         start = ast_tvnow();
1314
1315                 res = ast_channel_bridge(chan, peer, config, &f, &who);
1316
1317                 if (config->feature_timer) {
1318                         /* Update time limit for next pass */
1319                         diff = ast_tvdiff_ms(ast_tvnow(), start);
1320                         config->feature_timer -= diff;
1321                         if (hasfeatures) {
1322                                 /* Running on backup config, meaning a feature might be being
1323                                    activated, but that's no excuse to keep things going 
1324                                    indefinitely! */
1325                                 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1326                                         ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1327                                         config->feature_timer = 0;
1328                                         who = chan;
1329                                         if (f)
1330                                                 ast_frfree(f);
1331                                         f = NULL;
1332                                         res = 0;
1333                                 } else if (config->feature_timer <= 0) {
1334                                         /* Not *really* out of time, just out of time for
1335                                            digits to come in for features. */
1336                                         ast_log(LOG_DEBUG, "Timed out for feature!\n");
1337                                         if (!ast_strlen_zero(peer_featurecode)) {
1338                                                 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1339                                                 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1340                                         }
1341                                         if (!ast_strlen_zero(chan_featurecode)) {
1342                                                 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1343                                                 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1344                                         }
1345                                         if (f)
1346                                                 ast_frfree(f);
1347                                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1348                                         if (!hasfeatures) {
1349                                                 /* Restore original (possibly time modified) bridge config */
1350                                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1351                                                 memset(&backup_config, 0, sizeof(backup_config));
1352                                         }
1353                                         hadfeatures = hasfeatures;
1354                                         /* Continue as we were */
1355                                         continue;
1356                                 }
1357                         } else {
1358                                 if (config->feature_timer <=0) {
1359                                         /* We ran out of time */
1360                                         config->feature_timer = 0;
1361                                         who = chan;
1362                                         if (f)
1363                                                 ast_frfree(f);
1364                                         f = NULL;
1365                                         res = 0;
1366                                 }
1367                         }
1368                 }
1369                 if (res < 0) {
1370                         ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1371                         return -1;
1372                 }
1373                 
1374                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
1375                         (f->subclass == AST_CONTROL_CONGESTION)))) {
1376                                 res = -1;
1377                                 break;
1378                 }
1379                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
1380                         if (who == chan)
1381                                 ast_indicate(peer, AST_CONTROL_RINGING);
1382                         else
1383                                 ast_indicate(chan, AST_CONTROL_RINGING);
1384                 }
1385                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
1386                         if (who == chan)
1387                                 ast_indicate(peer, -1);
1388                         else
1389                                 ast_indicate(chan, -1);
1390                 }
1391                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
1392                         if (who == chan)
1393                                 ast_indicate(peer, AST_CONTROL_FLASH);
1394                         else
1395                                 ast_indicate(chan, AST_CONTROL_FLASH);
1396                 }
1397                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
1398                         aoh = f->data;
1399                         /* Forward option Requests */
1400                         if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
1401                                 if (who == chan)
1402                                         ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1403                                 else
1404                                         ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1405                         }
1406                 }
1407                 /* check for '*', if we find it it's time to disconnect */
1408                 if (f && (f->frametype == AST_FRAME_DTMF)) {
1409                         char *featurecode;
1410                         int sense;
1411                         struct ast_channel *other;
1412
1413                         hadfeatures = hasfeatures;
1414                         /* This cannot overrun because the longest feature is one shorter than our buffer */
1415                         if (who == chan) {
1416                                 other = peer;
1417                                 sense = FEATURE_SENSE_CHAN;
1418                                 featurecode = chan_featurecode;
1419                         } else  {
1420                                 other = chan;
1421                                 sense = FEATURE_SENSE_PEER;
1422                                 featurecode = peer_featurecode;
1423                         }
1424                         featurecode[strlen(featurecode)] = f->subclass;
1425                         config->feature_timer = backup_config.feature_timer;
1426                         res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1427                         switch(res) {
1428                         case FEATURE_RETURN_PASSDIGITS:
1429                                 ast_dtmf_stream(other, who, featurecode, 0);
1430                                 /* Fall through */
1431                         case FEATURE_RETURN_SUCCESS:
1432                                 memset(featurecode, 0, sizeof(chan_featurecode));
1433                                 break;
1434                         }
1435                         if (res >= FEATURE_RETURN_PASSDIGITS) {
1436                                 res = 0;
1437                         } else {
1438                                 ast_frfree(f);
1439                                 break;
1440                         }
1441                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1442                         if (hadfeatures && !hasfeatures) {
1443                                 /* Restore backup */
1444                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1445                                 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1446                         } else if (hasfeatures) {
1447                                 if (!hadfeatures) {
1448                                         /* Backup configuration */
1449                                         memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1450                                         /* Setup temporary config options */
1451                                         config->play_warning = 0;
1452                                         ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1453                                         ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1454                                         config->warning_freq = 0;
1455                                         config->warning_sound = NULL;
1456                                         config->end_sound = NULL;
1457                                         config->start_sound = NULL;
1458                                         config->firstpass = 0;
1459                                 }
1460                                 config->feature_timer = featuredigittimeout;
1461                                 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1462                         }
1463                 }
1464                 if (f)
1465                         ast_frfree(f);
1466         }
1467         return res;
1468 }
1469
1470 static void *do_parking_thread(void *ignore)
1471 {
1472         int ms, tms, max;
1473         struct parkeduser *pu, *pl, *pt = NULL;
1474         struct timeval tv;
1475         struct ast_frame *f;
1476         char exten[AST_MAX_EXTENSION];
1477         char *peername,*cp;
1478         char returnexten[AST_MAX_EXTENSION];
1479         struct ast_context *con;
1480         int x;
1481         fd_set rfds, efds;
1482         fd_set nrfds, nefds;
1483         FD_ZERO(&rfds);
1484         FD_ZERO(&efds);
1485
1486         for (;;) {
1487                 ms = -1;
1488                 max = -1;
1489                 ast_mutex_lock(&parking_lock);
1490                 pl = NULL;
1491                 pu = parkinglot;
1492                 FD_ZERO(&nrfds);
1493                 FD_ZERO(&nefds);
1494                 while(pu) {
1495                         if (pu->notquiteyet) {
1496                                 /* Pretend this one isn't here yet */
1497                                 pl = pu;
1498                                 pu = pu->next;
1499                                 continue;
1500                         }
1501                         tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1502                         if (tms > pu->parkingtime) {
1503                                 /* Stop music on hold */
1504                                 ast_moh_stop(pu->chan);
1505                                 ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
1506                                 /* Get chan, exten from derived kludge */
1507                                 if (pu->peername[0]) {
1508                                         peername = ast_strdupa(pu->peername);
1509                                         cp = strrchr(peername, '-');
1510                                         if (cp) 
1511                                                 *cp = 0;
1512                                         con = ast_context_find(parking_con_dial);
1513                                         if (!con) {
1514                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
1515                                                 if (!con) {
1516                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1517                                                 }
1518                                         }
1519                                         if (con) {
1520                                                 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1521                                                 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
1522                                         }
1523                                         ast_copy_string(pu->chan->exten, peername, sizeof(pu->chan->exten));
1524                                         ast_copy_string(pu->chan->context, parking_con_dial, sizeof(pu->chan->context));
1525                                         pu->chan->priority = 1;
1526
1527                                 } else {
1528                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
1529                                            should have their original extensions and such, but we copy to be on the safe side */
1530                                         ast_copy_string(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
1531                                         ast_copy_string(pu->chan->context, pu->context, sizeof(pu->chan->context));
1532                                         pu->chan->priority = pu->priority;
1533                                 }
1534
1535                                 manager_event(EVENT_FLAG_CALL, "ParkedCallTimeOut",
1536                                         "Exten: %d\r\n"
1537                                         "Channel: %s\r\n"
1538                                         "CallerID: %s\r\n"
1539                                         "CallerIDName: %s\r\n\r\n"
1540                                         ,pu->parkingnum, pu->chan->name
1541                                         ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1542                                         ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1543                                         );
1544
1545                                 if (option_verbose > 1) 
1546                                         ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->chan->context, pu->chan->exten, pu->chan->priority);
1547                                 /* Start up the PBX, or hang them up */
1548                                 if (ast_pbx_start(pu->chan))  {
1549                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
1550                                         ast_hangup(pu->chan);
1551                                 }
1552                                 /* And take them out of the parking lot */
1553                                 if (pl) 
1554                                         pl->next = pu->next;
1555                                 else
1556                                         parkinglot = pu->next;
1557                                 pt = pu;
1558                                 pu = pu->next;
1559                                 con = ast_context_find(parking_con);
1560                                 if (con) {
1561                                         snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1562                                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1563                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1564                                 } else
1565                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1566                                 free(pt);
1567                         } else {
1568                                 for (x = 0; x < AST_MAX_FDS; x++) {
1569                                         if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
1570                                                 if (FD_ISSET(pu->chan->fds[x], &efds))
1571                                                         ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
1572                                                 else
1573                                                         ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
1574                                                 pu->chan->fdno = x;
1575                                                 /* See if they need servicing */
1576                                                 f = ast_read(pu->chan);
1577                                                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
1578
1579                                                         manager_event(EVENT_FLAG_CALL, "ParkedCallGiveUp",
1580                                                                 "Exten: %d\r\n"
1581                                                                 "Channel: %s\r\n"
1582                                                                 "CallerID: %s\r\n"
1583                                                                 "CallerIDName: %s\r\n\r\n"
1584                                                                 ,pu->parkingnum, pu->chan->name
1585                                                                 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1586                                                                 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1587                                                                 );
1588
1589                                                         /* There's a problem, hang them up*/
1590                                                         if (option_verbose > 1) 
1591                                                                 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
1592                                                         ast_hangup(pu->chan);
1593                                                         /* And take them out of the parking lot */
1594                                                         if (pl) 
1595                                                                 pl->next = pu->next;
1596                                                         else
1597                                                                 parkinglot = pu->next;
1598                                                         pt = pu;
1599                                                         pu = pu->next;
1600                                                         con = ast_context_find(parking_con);
1601                                                         if (con) {
1602                                                                 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1603                                                                 if (ast_context_remove_extension2(con, exten, 1, NULL))
1604                                                                         ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1605                                                         } else
1606                                                                 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1607                                                         free(pt);
1608                                                         break;
1609                                                 } else {
1610                                                         /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1611                                                         ast_frfree(f);
1612                                                         if (pu->moh_trys < 3 && !pu->chan->generatordata) {
1613                                                                 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source.  Restarting.\n");
1614                                                                 ast_moh_start(pu->chan, NULL);
1615                                                                 pu->moh_trys++;
1616                                                         }
1617                                                         goto std;       /* XXX Ick: jumping into an else statement??? XXX */
1618                                                 }
1619                                         }
1620                                 }
1621                                 if (x >= AST_MAX_FDS) {
1622 std:                                    for (x=0; x<AST_MAX_FDS; x++) {
1623                                                 /* Keep this one for next one */
1624                                                 if (pu->chan->fds[x] > -1) {
1625                                                         FD_SET(pu->chan->fds[x], &nrfds);
1626                                                         FD_SET(pu->chan->fds[x], &nefds);
1627                                                         if (pu->chan->fds[x] > max)
1628                                                                 max = pu->chan->fds[x];
1629                                                 }
1630                                         }
1631                                         /* Keep track of our longest wait */
1632                                         if ((tms < ms) || (ms < 0))
1633                                                 ms = tms;
1634                                         pl = pu;
1635                                         pu = pu->next;
1636                                 }
1637                         }
1638                 }
1639                 ast_mutex_unlock(&parking_lock);
1640                 rfds = nrfds;
1641                 efds = nefds;
1642                 tv = ast_samp2tv(ms, 1000);
1643                 /* Wait for something to happen */
1644                 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1645                 pthread_testcancel();
1646         }
1647         return NULL;    /* Never reached */
1648 }
1649
1650 static int park_call_exec(struct ast_channel *chan, void *data)
1651 {
1652         /* Data is unused at the moment but could contain a parking
1653            lot context eventually */
1654         int res=0;
1655         struct localuser *u;
1656         LOCAL_USER_ADD(u);
1657         /* Setup the exten/priority to be s/1 since we don't know
1658            where this call should return */
1659         strcpy(chan->exten, "s");
1660         chan->priority = 1;
1661         if (chan->_state != AST_STATE_UP)
1662                 res = ast_answer(chan);
1663         if (!res)
1664                 res = ast_safe_sleep(chan, 1000);
1665         if (!res)
1666                 res = ast_park_call(chan, chan, 0, NULL);
1667         LOCAL_USER_REMOVE(u);
1668         if (!res)
1669                 res = AST_PBX_KEEPALIVE;
1670         return res;
1671 }
1672
1673 static int park_exec(struct ast_channel *chan, void *data)
1674 {
1675         int res=0;
1676         struct localuser *u;
1677         struct ast_channel *peer=NULL;
1678         struct parkeduser *pu, *pl=NULL;
1679         char exten[AST_MAX_EXTENSION];
1680         struct ast_context *con;
1681         int park;
1682         int dres;
1683         struct ast_bridge_config config;
1684
1685         if (!data) {
1686                 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
1687                 return -1;
1688         }
1689         LOCAL_USER_ADD(u);
1690         park = atoi((char *)data);
1691         ast_mutex_lock(&parking_lock);
1692         pu = parkinglot;
1693         while(pu) {
1694                 if (pu->parkingnum == park) {
1695                         if (pl)
1696                                 pl->next = pu->next;
1697                         else
1698                                 parkinglot = pu->next;
1699                         break;
1700                 }
1701                 pl = pu;
1702                 pu = pu->next;
1703         }
1704         ast_mutex_unlock(&parking_lock);
1705         if (pu) {
1706                 peer = pu->chan;
1707                 con = ast_context_find(parking_con);
1708                 if (con) {
1709                         snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
1710                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1711                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1712                 } else
1713                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1714
1715                 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
1716                         "Exten: %d\r\n"
1717                         "Channel: %s\r\n"
1718                         "From: %s\r\n"
1719                         "CallerID: %s\r\n"
1720                         "CallerIDName: %s\r\n\r\n"
1721                         ,pu->parkingnum, pu->chan->name, chan->name
1722                         ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1723                         ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1724                         );
1725
1726                 free(pu);
1727         }
1728         /* JK02: it helps to answer the channel if not already up */
1729         if (chan->_state != AST_STATE_UP) {
1730                 ast_answer(chan);
1731         }
1732
1733         if (peer) {
1734                 /* Play a courtesy beep in the calling channel to prefix the bridge connecting */       
1735                 if (!ast_strlen_zero(courtesytone)) {
1736                         if (!ast_streamfile(chan, courtesytone, chan->language)) {
1737                                 if (ast_waitstream(chan, "") < 0) {
1738                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1739                                         ast_hangup(peer);
1740                                         return -1;
1741                                 }
1742                         }
1743                 }
1744  
1745                 ast_moh_stop(peer);
1746                 ast_indicate(peer, AST_CONTROL_UNHOLD);
1747                 res = ast_channel_make_compatible(chan, peer);
1748                 if (res < 0) {
1749                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1750                         ast_hangup(peer);
1751                         return -1;
1752                 }
1753                 /* This runs sorta backwards, since we give the incoming channel control, as if it
1754                    were the person called. */
1755                 if (option_verbose > 2) 
1756                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1757
1758                 memset(&config, 0, sizeof(struct ast_bridge_config));
1759                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1760                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1761                 config.timelimit = 0;
1762                 config.play_warning = 0;
1763                 config.warning_freq = 0;
1764                 config.warning_sound=NULL;
1765                 res = ast_bridge_call(chan, peer, &config);
1766
1767                 /* Simulate the PBX hanging up */
1768                 if (res != AST_PBX_NO_HANGUP_PEER)
1769                         ast_hangup(peer);
1770                 return res;
1771         } else {
1772                 /* XXX Play a message XXX */
1773                 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
1774                 if (!dres)
1775                         dres = ast_waitstream(chan, "");
1776                 else {
1777                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1778                         dres = 0;
1779                 }
1780                 if (option_verbose > 2) 
1781                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1782                 res = -1;
1783         }
1784         LOCAL_USER_REMOVE(u);
1785         return res;
1786 }
1787
1788 static int handle_showfeatures(int fd, int argc, char *argv[])
1789 {
1790         int i;
1791         int fcount;
1792         struct ast_call_feature *feature;
1793         char format[] = "%-25s %-7s %-7s\n";
1794
1795         ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1796         ast_cli(fd, format, "---------------", "-------", "-------");
1797
1798         ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
1799
1800         fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1801
1802         for (i = 0; i < fcount; i++)
1803         {
1804                 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1805         }
1806         ast_cli(fd, "\n");
1807         ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1808         ast_cli(fd, format, "---------------", "-------", "-------");
1809         if (AST_LIST_EMPTY(&feature_list)) {
1810                 ast_cli(fd, "(none)\n");
1811         }
1812         else {
1813                 AST_LIST_LOCK(&feature_list);
1814                 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1815                         ast_cli(fd, format, feature->sname, "no def", feature->exten);  
1816                 }
1817                 AST_LIST_UNLOCK(&feature_list);
1818         }
1819         ast_cli(fd, "\nCall parking\n");
1820         ast_cli(fd, "------------\n");
1821         ast_cli(fd,"%-20s:      %s\n", "Parking extension", parking_ext);
1822         ast_cli(fd,"%-20s:      %s\n", "Parking context", parking_con);
1823         ast_cli(fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1824         ast_cli(fd,"\n");
1825         
1826         return RESULT_SUCCESS;
1827 }
1828
1829 static char showfeatures_help[] =
1830 "Usage: show features\n"
1831 "       Lists currently configured features.\n";
1832
1833 static struct ast_cli_entry showfeatures =
1834 { { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
1835
1836 static int handle_parkedcalls(int fd, int argc, char *argv[])
1837 {
1838         struct parkeduser *cur;
1839         int numparked = 0;
1840
1841         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1842                 , "Context", "Extension", "Pri", "Timeout");
1843
1844         ast_mutex_lock(&parking_lock);
1845
1846         cur = parkinglot;
1847         while(cur) {
1848                 ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
1849                         ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
1850                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1851
1852                 cur = cur->next;
1853                 numparked++;
1854         }
1855         ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
1856
1857         ast_mutex_unlock(&parking_lock);
1858
1859         return RESULT_SUCCESS;
1860 }
1861
1862 static char showparked_help[] =
1863 "Usage: show parkedcalls\n"
1864 "       Lists currently parked calls.\n";
1865
1866 static struct ast_cli_entry showparked =
1867 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1868
1869 /* Dump lot status */
1870 static int manager_parking_status( struct mansession *s, struct message *m )
1871 {
1872         struct parkeduser *cur;
1873         char *id = astman_get_header(m,"ActionID");
1874         char idText[256] = "";
1875
1876         if (id && !ast_strlen_zero(id))
1877                 snprintf(idText,256,"ActionID: %s\r\n",id);
1878
1879         astman_send_ack(s, m, "Parked calls will follow");
1880
1881         ast_mutex_lock(&parking_lock);
1882
1883         cur=parkinglot;
1884         while(cur) {
1885                         ast_cli(s->fd, "Event: ParkedCall\r\n"
1886                         "Exten: %d\r\n"
1887                         "Channel: %s\r\n"
1888                         "Timeout: %ld\r\n"
1889                         "CallerID: %s\r\n"
1890                         "CallerIDName: %s\r\n"
1891                         "%s"
1892                         "\r\n"
1893                         ,cur->parkingnum, cur->chan->name
1894                         ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
1895                         ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
1896                         ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
1897                         ,idText);
1898
1899             cur = cur->next;
1900         }
1901
1902         ast_cli(s->fd,
1903         "Event: ParkedCallsComplete\r\n"
1904         "%s"
1905         "\r\n",idText);
1906
1907         ast_mutex_unlock(&parking_lock);
1908
1909         return RESULT_SUCCESS;
1910 }
1911
1912
1913 int ast_pickup_call(struct ast_channel *chan)
1914 {
1915         struct ast_channel *cur = NULL;
1916         int res = -1;
1917
1918         while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
1919                 if (!cur->pbx && 
1920                         (cur != chan) &&
1921                         (chan->pickupgroup & cur->callgroup) &&
1922                         ((cur->_state == AST_STATE_RINGING) ||
1923                          (cur->_state == AST_STATE_RING))) {
1924                                 break;
1925                 }
1926                 ast_mutex_unlock(&cur->lock);
1927         }
1928         if (cur) {
1929                 if (option_debug)
1930                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
1931                 res = ast_answer(chan);
1932                 if (res)
1933                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
1934                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
1935                 if (res)
1936                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
1937                 res = ast_channel_masquerade(cur, chan);
1938                 if (res)
1939                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
1940                 ast_mutex_unlock(&cur->lock);
1941         } else  {
1942                 if (option_debug)
1943                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
1944         }
1945         return res;
1946 }
1947
1948 static int load_config(void) 
1949 {
1950         int start = 0, end = 0;
1951         struct ast_context *con = NULL;
1952         struct ast_config *cfg = NULL;
1953         struct ast_variable *var = NULL;
1954         char old_parking_ext[AST_MAX_EXTENSION];
1955         char old_parking_con[AST_MAX_EXTENSION];
1956
1957         if (!ast_strlen_zero(parking_con)) {
1958                 strcpy(old_parking_ext, parking_ext);
1959                 strcpy(old_parking_con, parking_con);
1960         } 
1961
1962         /* Reset to defaults */
1963         strcpy(parking_con, "parkedcalls");
1964         strcpy(parking_con_dial, "park-dial");
1965         strcpy(parking_ext, "700");
1966         strcpy(pickup_ext, "*8");
1967         courtesytone[0] = '\0';
1968         strcpy(xfersound, "beep");
1969         strcpy(xferfailsound, "pbx-invalid");
1970         parking_start = 701;
1971         parking_stop = 750;
1972         parkfindnext = 0;
1973
1974         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1975         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1976
1977         cfg = ast_config_load("features.conf");
1978         if (!cfg) {
1979                 cfg = ast_config_load("parking.conf");
1980                 if (cfg)
1981                         ast_log(LOG_NOTICE, "parking.conf is deprecated in favor of 'features.conf'.  Please rename it.\n");
1982         }
1983         if (cfg) {
1984                 var = ast_variable_browse(cfg, "general");
1985                 while(var) {
1986                         if (!strcasecmp(var->name, "parkext")) {
1987                                 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
1988                         } else if (!strcasecmp(var->name, "context")) {
1989                                 ast_copy_string(parking_con, var->value, sizeof(parking_con));
1990                         } else if (!strcasecmp(var->name, "parkingtime")) {
1991                                 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
1992                                         ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
1993                                         parkingtime = DEFAULT_PARK_TIME;
1994                                 } else
1995                                         parkingtime = parkingtime * 1000;
1996                         } else if (!strcasecmp(var->name, "parkpos")) {
1997                                 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
1998                                         ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", var->lineno);
1999                                 } else {
2000                                         parking_start = start;
2001                                         parking_stop = end;
2002                                 }
2003                         } else if (!strcasecmp(var->name, "findslot")) {
2004                                 parkfindnext = (!strcasecmp(var->value, "next"));
2005                         } else if (!strcasecmp(var->name, "adsipark")) {
2006                                 adsipark = ast_true(var->value);
2007                         } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2008                                 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2009                                         ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2010                                         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2011                                 } else
2012                                         transferdigittimeout = transferdigittimeout * 1000;
2013                         } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2014                                 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2015                                         ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2016                                         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2017                                 }
2018                         } else if (!strcasecmp(var->name, "courtesytone")) {
2019                                 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2020                         } else if (!strcasecmp(var->name, "xfersound")) {
2021                                 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2022                         } else if (!strcasecmp(var->name, "xferfailsound")) {
2023                                 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2024                         } else if (!strcasecmp(var->name, "pickupexten")) {
2025                                 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2026                         }
2027                         var = var->next;
2028                 }
2029
2030                 unmap_features();
2031                 var = ast_variable_browse(cfg, "featuremap");
2032                 while(var) {
2033                         if (remap_feature(var->name, var->value))
2034                                 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2035                         var = var->next;
2036                 }
2037
2038                 /* Map a key combination to an application*/
2039                 ast_unregister_features();
2040                 var = ast_variable_browse(cfg, "applicationmap");
2041                 while(var) {
2042                         char *tmp_val=strdup(var->value);
2043                         char *exten, *party=NULL, *app=NULL, *app_args=NULL; 
2044
2045                         if (!tmp_val) { 
2046                                 ast_log(LOG_ERROR, "res_features: strdup failed");
2047                                 continue;
2048                         }
2049                         
2050
2051                         exten=strsep(&tmp_val,",");
2052                         if (exten) party=strsep(&tmp_val,",");
2053                         if (party) app=strsep(&tmp_val,",");
2054
2055                         if (app) app_args=strsep(&tmp_val,",");
2056
2057                         if (!(app && strlen(app)) || !(exten && strlen(exten)) || !(party && strlen(party)) || !(var->name && strlen(var->name))) {
2058                                 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",app,exten,party,var->name);
2059                                 free(tmp_val);
2060                                 var = var->next;
2061                                 continue;
2062                         }
2063
2064                         {
2065                                 struct ast_call_feature *feature=find_feature(var->name);
2066                                 int mallocd=0;
2067                                 
2068                                 if (!feature) {
2069                                         feature=malloc(sizeof(struct ast_call_feature));
2070                                         mallocd=1;
2071                                 }
2072                                 if (!feature) {
2073                                         ast_log(LOG_NOTICE, "Malloc failed at feature mapping\n");
2074                                         free(tmp_val);
2075                                         var = var->next;
2076                                         continue;
2077                                 }
2078
2079                                 memset(feature,0,sizeof(struct ast_call_feature));
2080                                 ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
2081                                 ast_copy_string(feature->app,app,FEATURE_APP_LEN);
2082                                 ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
2083                                 free(tmp_val);
2084                                 
2085                                 if (app_args) 
2086                                         ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
2087                                 
2088                                 ast_copy_string(feature->exten, exten,sizeof(feature->exten));
2089                                 feature->operation=feature_exec_app;
2090                                 ast_set_flag(feature,AST_FEATURE_FLAG_NEEDSDTMF);
2091                                 
2092                                 if (!strcasecmp(party,"caller"))
2093                                         ast_set_flag(feature,AST_FEATURE_FLAG_CALLER);
2094                                 else if (!strcasecmp(party, "callee"))
2095                                         ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
2096                                 else {
2097                                         ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
2098                                         var = var->next;
2099                                         continue;
2100                                 }
2101
2102                                 ast_register_feature(feature);
2103                                 
2104                                 if (option_verbose >=1) ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);  
2105                         }
2106                         var = var->next;
2107                 }        
2108         }
2109         ast_config_destroy(cfg);
2110
2111         /* Remove the old parking extension */
2112         if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))     {
2113                 ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
2114                 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2115         }
2116         
2117         if (!(con = ast_context_find(parking_con))) {
2118                 if (!(con = ast_context_create(NULL, parking_con, registrar))) {
2119                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2120                         return -1;
2121                 }
2122         }
2123         return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
2124 }
2125
2126 int reload(void) {
2127         return load_config();
2128 }
2129
2130 int load_module(void)
2131 {
2132         int res;
2133         
2134         AST_LIST_HEAD_INIT(&feature_list);
2135         memset(parking_ext, 0, sizeof(parking_ext));
2136         memset(parking_con, 0, sizeof(parking_con));
2137
2138         if ((res = load_config()))
2139                 return res;
2140         ast_cli_register(&showparked);
2141         ast_cli_register(&showfeatures);
2142         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2143         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2144         if (!res)
2145                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2146         if (!res) {
2147                 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2148         }
2149         return res;
2150 }
2151
2152
2153 int unload_module(void)
2154 {
2155         STANDARD_HANGUP_LOCALUSERS;
2156
2157         ast_manager_unregister("ParkedCalls");
2158         ast_cli_unregister(&showfeatures);
2159         ast_cli_unregister(&showparked);
2160         ast_unregister_application(parkcall);
2161         return ast_unregister_application(parkedcall);
2162 }
2163
2164 char *description(void)
2165 {
2166         return "Call Features Resource";
2167 }
2168
2169 int usecount(void)
2170 {
2171         /* Never allow parking to be unloaded because it will
2172            unresolve needed symbols in the dialer */
2173 #if 0
2174         int res;
2175         STANDARD_USECOUNT(res);
2176         return res;
2177 #else
2178         return 1;
2179 #endif
2180 }
2181
2182 char *key()
2183 {
2184         return ASTERISK_GPL_KEY;
2185 }