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