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