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