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