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