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