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