Fix parking issue (bug #3396)
[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 : "")
282                                 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "")
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], *ptr;
462         int res;
463         int len;
464
465         if (sense == FEATURE_SENSE_PEER) {
466                 transferer = peer;
467                 transferee = chan;
468         } else {
469                 transferer = chan;
470                 transferee = peer;
471         }
472         if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
473            !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
474                 /* Use the non-macro context to transfer the call */
475                 if (!ast_strlen_zero(transferer->macrocontext))
476                         transferer_real_context = transferer->macrocontext;
477                 else
478                         transferer_real_context = transferer->context;
479         }
480         /* Start autoservice on chan while we talk
481            to the originator */
482         ast_indicate(transferee, AST_CONTROL_HOLD);
483         ast_autoservice_start(transferee);
484         ast_moh_start(transferee, NULL);
485
486         memset(newext, 0, sizeof(newext));
487         ptr = newext;
488
489         /* Transfer */
490         if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
491                 ast_moh_stop(transferee);
492                 ast_autoservice_stop(transferee);
493                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
494                 return res;
495         }
496         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
497                 ast_moh_stop(transferee);
498                 ast_autoservice_stop(transferee);
499                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
500                 return res;
501         }
502         ast_stopstream(transferer);
503         if (res > 0) {
504                 /* If they've typed a digit already, handle it */
505                 newext[0] = res;
506                 ptr++;
507                 len--;
508         }
509
510         res = ast_app_dtget(transferer, transferer_real_context, newext, sizeof(newext), 100, transferdigittimeout);
511         if (res < 0) {
512                 ast_moh_stop(transferee);
513                 ast_autoservice_stop(transferee);
514                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
515                 return res;
516         }
517         if (!strcmp(newext, ast_parking_ext())) {
518                 ast_moh_stop(transferee);
519
520                 res = ast_autoservice_stop(transferee);
521                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
522                 if (res)
523                         res = -1;
524                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {
525                         /* We return non-zero, but tell the PBX not to hang the channel when
526                            the thread dies -- We have to be careful now though.  We are responsible for 
527                            hanging up the channel, else it will never be hung up! */
528
529                         if (transferer==peer)
530                                 res=AST_PBX_KEEPALIVE;
531                         else
532                                 res=AST_PBX_NO_HANGUP_PEER;
533                         return res;
534                 } else {
535                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
536                 }
537                 /* XXX Maybe we should have another message here instead of invalid extension XXX */
538         } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
539                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
540                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
541                 ast_moh_stop(transferee);
542                 res=ast_autoservice_stop(transferee);
543                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
544                 if (!transferee->pbx) {
545                         /* Doh!  Use our handy async_goto functions */
546                         if (option_verbose > 2) 
547                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
548                                                                 ,transferee->name, newext, transferer_real_context);
549                         if (ast_async_goto(transferee, transferer_real_context, newext, 1))
550                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
551                         res = -1;
552                 } else {
553                         /* Set the channel's new extension, since it exists, using transferer context */
554                         strncpy(transferee->exten, newext, sizeof(transferee->exten)-1);
555                         strncpy(transferee->context, transferer_real_context, sizeof(transferee->context)-1);
556                         transferee->priority = 0;
557                 }
558                 return res;
559         } else {
560                 if (option_verbose > 2) 
561                         ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", newext, transferer_real_context);
562         }
563         if (!ast_strlen_zero(xferfailsound))
564                 res = ast_streamfile(transferer, xferfailsound, transferee->language);
565         else
566                 res = 0;
567         if (res) {
568                 ast_moh_stop(transferee);
569                 ast_autoservice_stop(transferee);
570                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
571                 return res;
572         }
573         res = ast_waitstream(transferer, AST_DIGIT_ANY);
574         ast_stopstream(transferer);
575         ast_moh_stop(transferee);
576         res = ast_autoservice_stop(transferee);
577         ast_indicate(transferee, AST_CONTROL_UNHOLD);
578         if (res) {
579                 if (option_verbose > 1)
580                         ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
581                 return res;
582         }
583         return FEATURE_RETURN_SUCCESS;
584 }
585
586 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
587 {
588         struct ast_channel *transferer;
589         struct ast_channel *transferee;
590         struct ast_channel *newchan, *xferchan=NULL;
591         int outstate=0;
592         struct ast_bridge_config bconfig;
593         char *transferer_real_context;
594         char xferto[256],dialstr[265];
595         char *cid_num;
596         char *cid_name;
597         int res;
598         struct ast_frame *f = NULL;
599         struct ast_bridge_thread_obj *tobj;
600
601         ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
602         if (sense == FEATURE_SENSE_PEER) {
603                 transferer = peer;
604                 transferee = chan;
605         } else {
606                 transferer = chan;
607                 transferee = peer;
608         }
609         if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
610            !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
611                 /* Use the non-macro context to transfer the call */
612                 if (!ast_strlen_zero(transferer->macrocontext))
613                         transferer_real_context = transferer->macrocontext;
614                 else
615                         transferer_real_context = transferer->context;
616         }
617         /* Start autoservice on chan while we talk
618            to the originator */
619         ast_indicate(transferee, AST_CONTROL_HOLD);
620         ast_autoservice_start(transferee);
621         ast_moh_start(transferee, NULL);
622
623         /* Transfer */
624         if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
625                 ast_moh_stop(transferee);
626                 ast_autoservice_stop(transferee);
627                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
628                 return res;
629         }
630         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
631                 ast_moh_stop(transferee);
632                 ast_autoservice_stop(transferee);
633                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
634                 return res;
635         }
636         if ((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
637                 cid_num = transferer->cid.cid_num;
638                 cid_name = transferer->cid.cid_name;
639                 if (ast_exists_extension(transferer, transferer_real_context,xferto, 1, cid_num)) {
640                         snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context);
641                         if ((newchan = ast_request_and_dial("Local", ast_best_codec(transferer->nativeformats), dialstr,30000, &outstate, cid_num, cid_name))) {
642                                 res = ast_channel_make_compatible(transferer, newchan);
643                                 if (res < 0) {
644                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
645                                         ast_hangup(newchan);
646                                         return -1;
647                                 }
648                                 memset(&bconfig,0,sizeof(struct ast_bridge_config));
649                                 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
650                                 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
651                                 res = ast_bridge_call(transferer,newchan,&bconfig);
652                                 if (newchan->_softhangup || newchan->_state != AST_STATE_UP) {
653                                         ast_hangup(newchan);
654                                         if (f) {
655                                                 ast_frfree(f);
656                                                 f = NULL;
657                                         }
658                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(transferer, xfersound, transferer->language)) {
659                                                 if (ast_waitstream(transferer, "") < 0) {
660                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
661                                                 }
662                                         }
663                                         ast_moh_stop(transferee);
664                                         ast_autoservice_stop(transferee);
665                                         ast_indicate(transferee, AST_CONTROL_UNHOLD);
666                                         transferer->_softhangup = 0;
667                                         return FEATURE_RETURN_SUCCESS;
668                                 }
669                                 
670                                 res = ast_channel_make_compatible(transferee, newchan);
671                                 if (res < 0) {
672                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
673                                         ast_hangup(newchan);
674                                         return -1;
675                                 }
676                                 
677                                 
678                                 ast_moh_stop(transferee);
679                                 
680                                 if ((ast_autoservice_stop(transferee) < 0)
681                                    ||(ast_waitfordigit(transferee,100) < 0)
682                                    || (ast_waitfordigit(newchan,100) < 0) 
683                                    || ast_check_hangup(transferee) 
684                                    || ast_check_hangup(newchan)) {
685                                         ast_hangup(newchan);
686                                         res = -1;
687                                         return -1;
688                                 }
689
690                                 if ((xferchan = ast_channel_alloc(0))) {
691                                         snprintf(xferchan->name, sizeof (xferchan->name), "Transfered/%s",transferee->name);
692                                         /* Make formats okay */
693                                         xferchan->readformat = transferee->readformat;
694                                         xferchan->writeformat = transferee->writeformat;
695                                         ast_channel_masquerade(xferchan, transferee);
696                                         ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
697                                         xferchan->_state = AST_STATE_UP;
698                                         ast_clear_flag(xferchan, AST_FLAGS_ALL);        
699                                         xferchan->_softhangup = 0;
700
701                                         if ((f = ast_read(xferchan))) {
702                                                 ast_frfree(f);
703                                                 f = NULL;
704                                         }
705                                         
706                                 } else {
707                                         ast_hangup(newchan);
708                                         return -1;
709                                 }
710
711                                 newchan->_state = AST_STATE_UP;
712                                 ast_clear_flag(newchan, AST_FLAGS_ALL); 
713                                 newchan->_softhangup = 0;
714
715                                 tobj = malloc(sizeof(struct ast_bridge_thread_obj));
716                                 if (tobj) {
717                                         memset(tobj,0,sizeof(struct ast_bridge_thread_obj));
718                                         tobj->chan = xferchan;
719                                         tobj->peer = newchan;
720                                         tobj->bconfig = *config;
721         
722                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(newchan, xfersound, newchan->language)) {
723                                                 if (ast_waitstream(newchan, "") < 0) {
724                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
725                                                 }
726                                         }
727                                         ast_bridge_call_thread_launch(tobj);
728                                 } else {
729                                         ast_log(LOG_WARNING, "Out of memory!\n");
730                                         ast_hangup(xferchan);
731                                         ast_hangup(newchan);
732                                 }
733                                 return -1;
734                                 
735                         } else {
736                                 ast_log(LOG_WARNING, "Unable to create channel Local/%s do you have chan_local?\n",dialstr);
737                                 ast_moh_stop(transferee);
738                                 ast_autoservice_stop(transferee);
739                                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
740                                 if (!ast_strlen_zero(xferfailsound)) {
741                                         res = ast_streamfile(transferer, xferfailsound, transferer->language);
742                                         if (!res && (ast_waitstream(transferer, "") < 0)) {
743                                                 return -1;
744                                         }
745                                 }
746                                 return -1;
747                         }
748                 } else {
749                         ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
750                         ast_moh_stop(transferee);
751                         ast_autoservice_stop(transferee);
752                         ast_indicate(transferee, AST_CONTROL_UNHOLD);
753                         res = ast_streamfile(transferer, "beeperr", transferer->language);
754                         if (!res && (ast_waitstream(transferer, "") < 0)) {
755                                 return -1;
756                         }
757                 }
758         }  else {
759                 ast_log(LOG_WARNING, "Did not read data.\n");
760                 res = ast_streamfile(transferer, "beeperr", transferer->language);
761                 if (ast_waitstream(transferer, "") < 0) {
762                         return -1;
763                 }
764         }
765         ast_moh_stop(transferee);
766         ast_autoservice_stop(transferee);
767         ast_indicate(transferee, AST_CONTROL_UNHOLD);
768
769         return FEATURE_RETURN_SUCCESS;
770 }
771
772 struct ast_call_feature {
773         int feature_mask;
774         char *fname;
775         char *sname;
776         char exten[FEATURE_MAX_LEN];
777         char default_exten[FEATURE_MAX_LEN];
778         int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense);
779         unsigned int flags;
780 };
781
782 /* add atxfer and automon as undefined so you can only use em if you configure them */
783 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
784 struct ast_call_feature builtin_features[] = 
785 {
786         { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
787         { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
788         { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
789         { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
790 };
791
792 static void unmap_features(void)
793 {
794         int x;
795         for (x=0;x<FEATURES_COUNT;x++)
796                 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
797 }
798
799 static int remap_feature(const char *name, const char *value)
800 {
801         int x;
802         int res = -1;
803         for (x=0;x<FEATURES_COUNT;x++) {
804                 if (!strcasecmp(name, builtin_features[x].sname)) {
805                         strncpy(builtin_features[x].exten, value, sizeof(builtin_features[x].exten) - 1);
806                         if (option_verbose > 1)
807                                 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);
808                         res = 0;
809                 } else if (!strcmp(value, builtin_features[x].exten)) 
810                         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);
811         }
812         return res;
813 }
814
815 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
816 {
817         int x;
818         struct ast_flags features;
819         int res = FEATURE_RETURN_PASSDIGITS;
820
821         if (sense == FEATURE_SENSE_CHAN)
822                 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);   
823         else
824                 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);   
825         ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
826         for (x=0;x<FEATURES_COUNT;x++) {
827                 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
828                     !ast_strlen_zero(builtin_features[x].exten)) {
829                         /* Feature is up for consideration */
830                         if (!strcmp(builtin_features[x].exten, code)) {
831                                 res = builtin_features[x].operation(chan, peer, config, code, sense);
832                                 break;
833                         } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
834                                 if (res == FEATURE_RETURN_PASSDIGITS)
835                                         res = FEATURE_RETURN_STOREDIGITS;
836                         }
837                 }
838         }
839         return res;
840 }
841
842 static void set_config_flags(struct ast_bridge_config *config)
843 {
844         int x;
845         ast_clear_flag(config, AST_FLAGS_ALL);  
846         for (x=0;x<FEATURES_COUNT;x++) {
847                 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask)) {
848                         if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
849                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
850                 }
851                 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask)) {
852                         if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
853                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
854                 }
855         }
856 }
857
858 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
859 {
860         /* Copy voice back and forth between the two channels.  Give the peer
861            the ability to transfer calls with '#<extension' syntax. */
862         struct ast_frame *f;
863         struct ast_channel *who;
864         char chan_featurecode[FEATURE_MAX_LEN + 1]="";
865         char peer_featurecode[FEATURE_MAX_LEN + 1]="";
866         int res;
867         int diff;
868         int hasfeatures=0;
869         int hadfeatures=0;
870         struct ast_option_header *aoh;
871         struct timeval start, end;
872         struct ast_bridge_config backup_config;
873         int allowdisconnect_in,allowdisconnect_out,allowredirect_in,allowredirect_out;
874         char *monitor_exec;
875
876         memset(&backup_config, 0, sizeof(backup_config));
877
878         if (chan && peer) {
879                 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
880                 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
881         } else if (chan)
882                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
883
884         if (monitor_ok) {
885                 if (!monitor_app) { 
886                         if (!(monitor_app = pbx_findapp("Monitor")))
887                                 monitor_ok=0;
888                 }
889                 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
890                         pbx_exec(chan, monitor_app, monitor_exec, 1);
891                 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
892                         pbx_exec(peer, monitor_app, monitor_exec, 1);
893         }
894         
895         allowdisconnect_in = ast_test_flag(&(config->features_callee), AST_FEATURE_DISCONNECT);
896         allowdisconnect_out = ast_test_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
897         allowredirect_in = ast_test_flag(&(config->features_callee), AST_FEATURE_REDIRECT);
898         allowredirect_out = ast_test_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
899         set_config_flags(config);
900         config->firstpass = 1;
901
902         /* Answer if need be */
903         if (ast_answer(chan))
904                 return -1;
905         peer->appl = "Bridged Call";
906         peer->data = chan->name;
907         /* copy the userfield from the B-leg to A-leg if applicable */
908         if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
909                 char tmp[256];
910                 if (!ast_strlen_zero(chan->cdr->userfield)) {
911                         snprintf(tmp, sizeof(tmp), "%s;%s",chan->cdr->userfield, peer->cdr->userfield);
912                         ast_cdr_appenduserfield(chan, tmp);
913                 } else
914                         ast_cdr_setuserfield(chan, peer->cdr->userfield);
915                 /* free the peer's cdr without ast_cdr_free complaining */
916                 free(peer->cdr);
917                 peer->cdr = NULL;
918         }
919         for (;;) {
920                 if (config->timelimit)
921                         gettimeofday(&start, NULL);
922                 res = ast_channel_bridge(chan,peer,config,&f, &who);
923                 if (config->timelimit) {
924                         /* Update time limit for next pass */
925                         gettimeofday(&end, NULL);
926                         diff = (end.tv_sec - start.tv_sec) * 1000;
927                         diff += (end.tv_usec - start.tv_usec) / 1000;
928                         config->timelimit -= diff;
929                         if (hasfeatures) {
930                                 /* Running on backup config, meaning a feature might be being
931                                    activated, but that's no excuse to keep things going 
932                                    indefinitely! */
933                                 if (backup_config.timelimit && ((backup_config.timelimit -= diff) <= 0)) {
934                                         ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
935                                         config->timelimit = 0;
936                                         who = chan;
937                                         if (f)
938                                                 ast_frfree(f);
939                                         f = NULL;
940                                         res = 0;
941                                 } else if (config->timelimit <= 0) {
942                                         /* Not *really* out of time, just out of time for
943                                            digits to come in for features. */
944                                         ast_log(LOG_DEBUG, "Timed out for feature!\n");
945                                         if (!ast_strlen_zero(peer_featurecode)) {
946                                                 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
947                                                 memset(peer_featurecode, 0, sizeof(peer_featurecode));
948                                         }
949                                         if (!ast_strlen_zero(chan_featurecode)) {
950                                                 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
951                                                 memset(chan_featurecode, 0, sizeof(chan_featurecode));
952                                         }
953                                         if (f)
954                                                 ast_frfree(f);
955                                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
956                                         if (!hasfeatures) {
957                                                 /* Restore original (possibly time modified) bridge config */
958                                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
959                                                 memset(&backup_config, 0, sizeof(backup_config));
960                                         }
961                                         hadfeatures = hasfeatures;
962                                         /* Continue as we were */
963                                         continue;
964                                 }
965                         } else {
966                                 if (config->timelimit <=0) {
967                                         /* We ran out of time */
968                                         config->timelimit = 0;
969                                         who = chan;
970                                         if (f)
971                                                 ast_frfree(f);
972                                         f = NULL;
973                                         res = 0;
974                                 }
975                         }
976                 }
977                 if (res < 0) {
978                         ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
979                         return -1;
980                 }
981                 
982                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
983                         (f->subclass == AST_CONTROL_CONGESTION)))) {
984                                 res = -1;
985                                 break;
986                 }
987                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
988                         if (who == chan)
989                                 ast_indicate(peer, AST_CONTROL_RINGING);
990                         else
991                                 ast_indicate(chan, AST_CONTROL_RINGING);
992                 }
993                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
994                         if (who == chan)
995                                 ast_indicate(peer, -1);
996                         else
997                                 ast_indicate(chan, -1);
998                 }
999                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
1000                         if (who == chan)
1001                                 ast_indicate(peer, AST_CONTROL_FLASH);
1002                         else
1003                                 ast_indicate(chan, AST_CONTROL_FLASH);
1004                 }
1005                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
1006                         aoh = f->data;
1007                         /* Forward option Requests */
1008                         if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
1009                                 if (who == chan)
1010                                         ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1011                                 else
1012                                         ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1013                         }
1014                 }
1015                 /* check for '*', if we find it it's time to disconnect */
1016                 if (f && (f->frametype == AST_FRAME_DTMF)) {
1017                         char *featurecode;
1018                         int sense;
1019                         struct ast_channel *other;
1020                         hadfeatures = hasfeatures;
1021                         /* This cannot overrun because the longest feature is one shorter than our buffer */
1022                         if (who == chan) {
1023                                 other = peer;
1024                                 sense = FEATURE_SENSE_CHAN;
1025                                 featurecode = chan_featurecode;
1026                         } else  {
1027                                 other = chan;
1028                                 sense = FEATURE_SENSE_PEER;
1029                                 featurecode = peer_featurecode;
1030                         }
1031                         featurecode[strlen(featurecode)] = f->subclass;
1032                         config->timelimit = backup_config.timelimit;
1033                         res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1034                         switch(res) {
1035                         case FEATURE_RETURN_PASSDIGITS:
1036                                 ast_dtmf_stream(other, who, featurecode, 0);
1037                                 /* Fall through */
1038                         case FEATURE_RETURN_SUCCESS:
1039                                 memset(featurecode, 0, sizeof(chan_featurecode));
1040                                 break;
1041                         }
1042                         if (res >= FEATURE_RETURN_PASSDIGITS) {
1043                                 res = 0;
1044                         } else {
1045                                 ast_frfree(f);
1046                                 break;
1047                         }
1048                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1049                         if (hadfeatures && !hasfeatures) {
1050                                 /* Restore backup */
1051                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1052                                 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1053                         } else if (hasfeatures) {
1054                                 if (!hadfeatures) {
1055                                         /* Backup configuration */
1056                                         memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1057                                         /* Setup temporary config options */
1058                                         config->play_warning = 0;
1059                                         ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1060                                         ast_clear_flag(&(config->features_callee),AST_FEATURE_PLAY_WARNING);
1061                                         config->warning_freq = 0;
1062                                         config->warning_sound = NULL;
1063                                         config->end_sound = NULL;
1064                                         config->start_sound = NULL;
1065                                         config->firstpass = 0;
1066                                 }
1067                                 config->timelimit = featuredigittimeout;
1068                                 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->timelimit);
1069                         }
1070                 }
1071                 if (f)
1072                         ast_frfree(f);
1073         }
1074         return res;
1075 }
1076
1077 static void *do_parking_thread(void *ignore)
1078 {
1079         int ms, tms, max;
1080         struct parkeduser *pu, *pl, *pt = NULL;
1081         struct timeval tv;
1082         struct ast_frame *f;
1083         char exten[AST_MAX_EXTENSION];
1084         char *peername,*cp;
1085         struct ast_context *con;
1086         int x;
1087         fd_set rfds, efds;
1088         fd_set nrfds, nefds;
1089         FD_ZERO(&rfds);
1090         FD_ZERO(&efds);
1091
1092         for (;;) {
1093                 ms = -1;
1094                 max = -1;
1095                 ast_mutex_lock(&parking_lock);
1096                 pl = NULL;
1097                 pu = parkinglot;
1098                 FD_ZERO(&nrfds);
1099                 FD_ZERO(&nefds);
1100                 while(pu) {
1101                         if (pu->notquiteyet) {
1102                                 /* Pretend this one isn't here yet */
1103                                 pl = pu;
1104                                 pu = pu->next;
1105                                 continue;
1106                         }
1107                         gettimeofday(&tv, NULL);
1108                         tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
1109                         if (tms > pu->parkingtime) {
1110                                 /* Stop music on hold */
1111                                 ast_moh_stop(pu->chan);
1112                                 ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
1113                                 /* Get chan, exten from derived kludge */
1114                                 if (pu->peername[0]) {
1115                                         peername = ast_strdupa(pu->peername);
1116                                         cp = strrchr(peername, '-');
1117                                         if (cp) 
1118                                                 *cp = 0;
1119                                         con = ast_context_find(parking_con_dial);
1120                                         if (!con) {
1121                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
1122                                                 if (!con) {
1123                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1124                                                 }
1125                                         }
1126                                         if (con) {
1127                                                 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(peername), free, registrar);
1128                                         }
1129                                         strncpy(pu->chan->exten, peername, sizeof(pu->chan->exten) - 1);
1130                                         strncpy(pu->chan->context, parking_con_dial, sizeof(pu->chan->context) - 1);
1131                                         pu->chan->priority = 1;
1132
1133                                 } else {
1134                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
1135                                            should have their original extensions and such, but we copy to be on the safe side */
1136                                         strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1);
1137                                         strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1);
1138                                         pu->chan->priority = pu->priority;
1139                                 }
1140                                 if (option_verbose > 1) 
1141                                         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);
1142                                 /* Start up the PBX, or hang them up */
1143                                 if (ast_pbx_start(pu->chan))  {
1144                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
1145                                         ast_hangup(pu->chan);
1146                                 }
1147                                 /* And take them out of the parking lot */
1148                                 if (pl) 
1149                                         pl->next = pu->next;
1150                                 else
1151                                         parkinglot = pu->next;
1152                                 pt = pu;
1153                                 pu = pu->next;
1154                                 con = ast_context_find(parking_con);
1155                                 if (con) {
1156                                         snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1157                                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1158                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1159                                 } else
1160                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1161                                 free(pt);
1162                         } else {
1163                                 for (x=0; x<AST_MAX_FDS; x++) {
1164                                         if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
1165                                                 if (FD_ISSET(pu->chan->fds[x], &efds))
1166                                                         ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
1167                                                 else
1168                                                         ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
1169                                                 pu->chan->fdno = x;
1170                                                 /* See if they need servicing */
1171                                                 f = ast_read(pu->chan);
1172                                                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
1173                                                         /* There's a problem, hang them up*/
1174                                                         if (option_verbose > 1) 
1175                                                                 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
1176                                                         ast_hangup(pu->chan);
1177                                                         /* And take them out of the parking lot */
1178                                                         if (pl) 
1179                                                                 pl->next = pu->next;
1180                                                         else
1181                                                                 parkinglot = pu->next;
1182                                                         pt = pu;
1183                                                         pu = pu->next;
1184                                                         con = ast_context_find(parking_con);
1185                                                         if (con) {
1186                                                                 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1187                                                                 if (ast_context_remove_extension2(con, exten, 1, NULL))
1188                                                                         ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1189                                                         } else
1190                                                                 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1191                                                         free(pt);
1192                                                         break;
1193                                                 } else {
1194                                                         /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1195                                                         ast_frfree(f);
1196                                                         goto std;       /* XXX Ick: jumping into an else statement??? XXX */
1197                                                 }
1198                                         }
1199                                 }
1200                                 if (x >= AST_MAX_FDS) {
1201 std:                                    for (x=0; x<AST_MAX_FDS; x++) {
1202                                                 /* Keep this one for next one */
1203                                                 if (pu->chan->fds[x] > -1) {
1204                                                         FD_SET(pu->chan->fds[x], &nrfds);
1205                                                         FD_SET(pu->chan->fds[x], &nefds);
1206                                                         if (pu->chan->fds[x] > max)
1207                                                                 max = pu->chan->fds[x];
1208                                                 }
1209                                         }
1210                                         /* Keep track of our longest wait */
1211                                         if ((tms < ms) || (ms < 0))
1212                                                 ms = tms;
1213                                         pl = pu;
1214                                         pu = pu->next;
1215                                 }
1216                         }
1217                 }
1218                 ast_mutex_unlock(&parking_lock);
1219                 rfds = nrfds;
1220                 efds = nefds;
1221                 tv.tv_sec = ms / 1000;
1222                 tv.tv_usec = (ms % 1000) * 1000;
1223                 /* Wait for something to happen */
1224                 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1225                 pthread_testcancel();
1226         }
1227         return NULL;    /* Never reached */
1228 }
1229
1230 static int park_call_exec(struct ast_channel *chan, void *data)
1231 {
1232         /* Data is unused at the moment but could contain a parking
1233            lot context eventually */
1234         int res=0;
1235         struct localuser *u;
1236         LOCAL_USER_ADD(u);
1237         /* Setup the exten/priority to be s/1 since we don't know
1238            where this call should return */
1239         strcpy(chan->exten, "s");
1240         chan->priority = 1;
1241         if (chan->_state != AST_STATE_UP)
1242                 res = ast_answer(chan);
1243         if (!res)
1244                 res = ast_safe_sleep(chan, 1000);
1245         if (!res)
1246                 res = ast_park_call(chan, chan, 0, NULL);
1247         LOCAL_USER_REMOVE(u);
1248         if (!res)
1249                 res = AST_PBX_KEEPALIVE;
1250         return res;
1251 }
1252
1253 static int park_exec(struct ast_channel *chan, void *data)
1254 {
1255         int res=0;
1256         struct localuser *u;
1257         struct ast_channel *peer=NULL;
1258         struct parkeduser *pu, *pl=NULL;
1259         char exten[AST_MAX_EXTENSION];
1260         struct ast_context *con;
1261         int park;
1262         int dres;
1263         struct ast_bridge_config config;
1264
1265         if (!data) {
1266                 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
1267                 return -1;
1268         }
1269         LOCAL_USER_ADD(u);
1270         park = atoi((char *)data);
1271         ast_mutex_lock(&parking_lock);
1272         pu = parkinglot;
1273         while(pu) {
1274                 if (pu->parkingnum == park) {
1275                         if (pl)
1276                                 pl->next = pu->next;
1277                         else
1278                                 parkinglot = pu->next;
1279                         break;
1280                 }
1281                 pl = pu;
1282                 pu = pu->next;
1283         }
1284         ast_mutex_unlock(&parking_lock);
1285         if (pu) {
1286                 peer = pu->chan;
1287                 con = ast_context_find(parking_con);
1288                 if (con) {
1289                         snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
1290                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1291                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1292                 } else
1293                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1294                 free(pu);
1295         }
1296         /* JK02: it helps to answer the channel if not already up */
1297         if (chan->_state != AST_STATE_UP) {
1298                 ast_answer(chan);
1299         }
1300
1301         if (peer) {
1302                 /* Play a courtesy beep in the calling channel to prefix the bridge connecting */       
1303                 if (!ast_strlen_zero(courtesytone)) {
1304                         if (!ast_streamfile(chan, courtesytone, chan->language)) {
1305                                 if (ast_waitstream(chan, "") < 0) {
1306                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1307                                         ast_hangup(peer);
1308                                         return -1;
1309                                 }
1310                         }
1311                 }
1312  
1313                 ast_moh_stop(peer);
1314                 ast_indicate(peer, AST_CONTROL_UNHOLD);
1315                 res = ast_channel_make_compatible(chan, peer);
1316                 if (res < 0) {
1317                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1318                         ast_hangup(peer);
1319                         return -1;
1320                 }
1321                 /* This runs sorta backwards, since we give the incoming channel control, as if it
1322                    were the person called. */
1323                 if (option_verbose > 2) 
1324                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1325
1326                 memset(&config,0,sizeof(struct ast_bridge_config));
1327                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1328                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1329                 config.timelimit = 0;
1330                 config.play_warning = 0;
1331                 config.warning_freq = 0;
1332                 config.warning_sound=NULL;
1333                 res = ast_bridge_call(chan,peer,&config);
1334
1335                 /* Simulate the PBX hanging up */
1336                 if (res != AST_PBX_NO_HANGUP_PEER)
1337                         ast_hangup(peer);
1338                 return res;
1339         } else {
1340                 /* XXX Play a message XXX */
1341                 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
1342                 if (!dres)
1343                         dres = ast_waitstream(chan, "");
1344                  else {
1345                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1346                         dres = 0;
1347                 }
1348                 if (option_verbose > 2) 
1349                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
1350                 res = -1;
1351         }
1352         LOCAL_USER_REMOVE(u);
1353         return res;
1354 }
1355
1356 static int handle_parkedcalls(int fd, int argc, char *argv[])
1357 {
1358         struct parkeduser *cur;
1359
1360         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1361                 , "Context", "Extension", "Pri", "Timeout");
1362
1363         ast_mutex_lock(&parking_lock);
1364
1365         cur = parkinglot;
1366         while(cur) {
1367                 ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
1368                         ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
1369                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1370
1371                 cur = cur->next;
1372         }
1373
1374         ast_mutex_unlock(&parking_lock);
1375
1376         return RESULT_SUCCESS;
1377 }
1378
1379 static char showparked_help[] =
1380 "Usage: show parkedcalls\n"
1381 "       Lists currently parked calls.\n";
1382
1383 static struct ast_cli_entry showparked =
1384 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1385 /* Dump lot status */
1386 static int manager_parking_status( struct mansession *s, struct message *m )
1387 {
1388         struct parkeduser *cur;
1389         char *id = astman_get_header(m,"ActionID");
1390         char idText[256] = "";
1391
1392         if (id && !ast_strlen_zero(id))
1393                 snprintf(idText,256,"ActionID: %s\r\n",id);
1394
1395         astman_send_ack(s, m, "Parked calls will follow");
1396
1397         ast_mutex_lock(&parking_lock);
1398
1399         cur=parkinglot;
1400         while(cur) {
1401                         ast_mutex_lock(&s->lock);
1402                 ast_cli(s->fd, "Event: ParkedCall\r\n"
1403                         "Exten: %d\r\n"
1404                         "Channel: %s\r\n"
1405                         "Timeout: %ld\r\n"
1406                         "CallerID: %s\r\n"
1407                         "CallerIDName: %s\r\n"
1408                         "%s"
1409                         "\r\n"
1410                         ,cur->parkingnum, cur->chan->name
1411                         ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
1412                         ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
1413                         ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
1414                         ,idText);
1415                         ast_mutex_unlock(&s->lock);
1416
1417             cur = cur->next;
1418         }
1419
1420         ast_cli(s->fd,
1421         "Event: ParkedCallsComplete\r\n"
1422         "%s"
1423         "\r\n",idText);
1424
1425         ast_mutex_unlock(&parking_lock);
1426
1427         return RESULT_SUCCESS;
1428 }
1429
1430
1431 static int load_config(void) 
1432 {
1433         int start = 0, end = 0;
1434         struct ast_context *con = NULL;
1435         struct ast_config *cfg = NULL;
1436         struct ast_variable *var = NULL;
1437         
1438         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1439         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1440
1441         cfg = ast_config_load("features.conf");
1442         if (!cfg) {
1443                 cfg = ast_config_load("parking.conf");
1444                 if (cfg)
1445                         ast_log(LOG_NOTICE, "parking.conf is deprecated in favor of 'features.conf'.  Please rename it.\n");
1446         }
1447         if (cfg) {
1448                 var = ast_variable_browse(cfg, "general");
1449                 while(var) {
1450                         if (!strcasecmp(var->name, "parkext")) {
1451                                 strncpy(parking_ext, var->value, sizeof(parking_ext) - 1);
1452                         } else if (!strcasecmp(var->name, "context")) {
1453                                 strncpy(parking_con, var->value, sizeof(parking_con) - 1);
1454                         } else if (!strcasecmp(var->name, "parkingtime")) {
1455                                 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
1456                                         ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
1457                                         parkingtime = DEFAULT_PARK_TIME;
1458                                 } else
1459                                         parkingtime = parkingtime * 1000;
1460                         } else if (!strcasecmp(var->name, "parkpos")) {
1461                                 if (sscanf(var->value, "%i-%i", &start, &end) != 2) {
1462                                         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);
1463                                 } else {
1464                                         parking_start = start;
1465                                         parking_stop = end;
1466                                 }
1467                         } else if (!strcasecmp(var->name, "adsipark")) {
1468                                 adsipark = ast_true(var->value);
1469                         } else if (!strcasecmp(var->name, "transferdigittimeout")) {
1470                                 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
1471                                         ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
1472                                         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1473                                 } else
1474                                         transferdigittimeout = transferdigittimeout * 1000;
1475                         } else if (!strcasecmp(var->name, "featuredigittimeout")) {
1476                                 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (transferdigittimeout < 1)) {
1477                                         ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
1478                                         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1479                                 }
1480                         } else if (!strcasecmp(var->name, "courtesytone")) {
1481                                 strncpy(courtesytone, var->value, sizeof(courtesytone) - 1);
1482                         } else if (!strcasecmp(var->name, "xfersound")) {
1483                                 strncpy(xfersound, var->value, sizeof(xfersound) - 1);
1484                         } else if (!strcasecmp(var->name, "xferfailsound")) {
1485                                 strncpy(xferfailsound, var->value, sizeof(xferfailsound) - 1);
1486                         } else if (!strcasecmp(var->name, "pickupexten")) {
1487                                 strncpy(pickup_ext, var->value, sizeof(pickup_ext) - 1);
1488                         }
1489                         var = var->next;
1490                 }
1491                 unmap_features();
1492                 var = ast_variable_browse(cfg, "featuremap");
1493                 while(var) {
1494                         if (remap_feature(var->name, var->value))
1495                                 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
1496                         var = var->next;
1497                 }
1498                 ast_config_destroy(cfg);
1499         }
1500         
1501         if (con)
1502                 ast_context_remove_extension2(con, ast_parking_ext(), 1, registrar);
1503         
1504         if (!(con = ast_context_find(parking_con))) {
1505                 if (!(con = ast_context_create(NULL, parking_con, registrar))) {
1506                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
1507                         return -1;
1508                 }
1509         }
1510         return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""),free, registrar);
1511 }
1512
1513 int reload(void) {
1514         return load_config();
1515 }
1516
1517 int load_module(void)
1518 {
1519         int res;
1520         if ((res = load_config()))
1521                 return res;
1522         ast_cli_register(&showparked);
1523         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
1524         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
1525         if (!res)
1526                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
1527         if (!res) {
1528                 ast_manager_register( "ParkedCalls", 0, manager_parking_status, "List parked calls" );
1529         }
1530         return res;
1531 }
1532
1533 int ast_pickup_call(struct ast_channel *chan)
1534 {
1535         struct ast_channel *cur;
1536         int res = -1;
1537         cur = ast_channel_walk_locked(NULL);
1538         while(cur) {
1539                 if (!cur->pbx && 
1540                         (cur != chan) &&
1541                         (chan->pickupgroup & cur->callgroup) &&
1542                         ((cur->_state == AST_STATE_RINGING) ||
1543                          (cur->_state == AST_STATE_RING))) {
1544                                 break;
1545                 }
1546                 ast_mutex_unlock(&cur->lock);
1547                 cur = ast_channel_walk_locked(cur);
1548         }
1549         if (cur) {
1550                 if (option_debug)
1551                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
1552                 res = ast_answer(chan);
1553                 if (res)
1554                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
1555                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
1556                 if (res)
1557                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
1558                 res = ast_channel_masquerade(cur, chan);
1559                 if (res)
1560                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
1561                 ast_mutex_unlock(&cur->lock);
1562         } else  {
1563                 if (option_debug)
1564                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
1565         }
1566         return res;
1567 }
1568
1569 int unload_module(void)
1570 {
1571         STANDARD_HANGUP_LOCALUSERS;
1572
1573         ast_manager_unregister( "ParkedCalls" );
1574         ast_cli_unregister(&showparked);
1575         ast_unregister_application(parkcall);
1576         return ast_unregister_application(parkedcall);
1577 }
1578
1579 char *description(void)
1580 {
1581         return "Call Parking Resource";
1582 }
1583
1584 int usecount(void)
1585 {
1586         /* Never allow parking to be unloaded because it will
1587            unresolve needed symbols in the dialer */
1588 #if 0
1589         int res;
1590         STANDARD_USECOUNT(res);
1591         return res;
1592 #else
1593         return 1;
1594 #endif
1595 }
1596
1597 char *key()
1598 {
1599         return ASTERISK_GPL_KEY;
1600 }