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