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