Doxygen update
[asterisk/asterisk.git] / res / res_features.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Routines implementing call features
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  */
25
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <sys/time.h>
34 #include <sys/signal.h>
35 #include <netinet/in.h>
36
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include "asterisk/lock.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/options.h"
47 #include "asterisk/causes.h"
48 #include "asterisk/module.h"
49 #include "asterisk/translate.h"
50 #include "asterisk/app.h"
51 #include "asterisk/say.h"
52 #include "asterisk/features.h"
53 #include "asterisk/musiconhold.h"
54 #include "asterisk/config.h"
55 #include "asterisk/cli.h"
56 #include "asterisk/manager.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/adsi.h"
59 #include "asterisk/monitor.h"
60
61 #ifdef __AST_DEBUG_MALLOC
62 static void FREE(void *ptr)
63 {
64         free(ptr);
65 }
66 #else
67 #define FREE free
68 #endif
69
70 #define DEFAULT_PARK_TIME 45000
71 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
72 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
73
74 #define AST_MAX_WATCHERS 256
75
76 static char *parkedcall = "ParkedCall";
77
78 static int parkingtime = DEFAULT_PARK_TIME;             /*!< No more than 45 seconds parked before you do something with them */
79 static char parking_con[AST_MAX_EXTENSION];             /*!< Context for which parking is made accessible */
80 static char parking_con_dial[AST_MAX_EXTENSION];        /*!< Context for dialback for parking (KLUDGE) */
81 static char parking_ext[AST_MAX_EXTENSION];             /*!< Extension you type to park the call */
82 static char pickup_ext[AST_MAX_EXTENSION];              /*!< Call pickup extension */
83 static int parking_start;                               /*!< First available extension for parking */
84 static int parking_stop;                                /*!< Last available extension for parking */
85
86 static char courtesytone[256];                          /*!< Courtesy tone */
87 static int parkedplay = 0;                              /*!< Who to play the courtesy tone to */
88 static char xfersound[256];                             /*!< Call transfer sound */
89 static char xferfailsound[256];                         /*!< Call transfer failure sound */
90
91 static int parking_offset;
92 static int parkfindnext;
93
94 static int adsipark;
95
96 static int transferdigittimeout;
97 static int featuredigittimeout;
98
99 static char *registrar = "res_features";                /*!< Registrar for operations */
100
101 /* module and CLI command definitions */
102 static char *synopsis = "Answer a parked call";
103
104 static char *descrip = "ParkedCall(exten):"
105 "Used to connect to a parked call.  This application is always\n"
106 "registered internally and does not need to be explicitly added\n"
107 "into the dialplan, although you should include the 'parkedcalls'\n"
108 "context.\n";
109
110 static char *parkcall = "Park";
111
112 static char *synopsis2 = "Park yourself";
113
114 static char *descrip2 = "Park(exten):"
115 "Used to park yourself (typically in combination with a supervised\n"
116 "transfer to know the parking space). This application is always\n"
117 "registered internally and does not need to be explicitly added\n"
118 "into the dialplan, although you should include the 'parkedcalls'\n"
119 "context.\n";
120
121 static struct ast_app *monitor_app = NULL;
122 static int monitor_ok = 1;
123
124 struct parkeduser {
125         struct ast_channel *chan;
126         struct timeval start;
127         int parkingnum;
128         /* Where to go if our parking time expires */
129         char context[AST_MAX_CONTEXT];
130         char exten[AST_MAX_EXTENSION];
131         int priority;
132         int parkingtime;
133         int notquiteyet;
134         char peername[1024];
135         unsigned char moh_trys;
136         struct parkeduser *next;
137 };
138
139 static struct parkeduser *parkinglot;
140
141 AST_MUTEX_DEFINE_STATIC(parking_lock);
142
143 static pthread_t parking_thread;
144
145 STANDARD_LOCAL_USER;
146
147 LOCAL_USER_DECL;
148
149 char *ast_parking_ext(void)
150 {
151         return parking_ext;
152 }
153
154 char *ast_pickup_ext(void)
155 {
156         return pickup_ext;
157 }
158
159 struct ast_bridge_thread_obj 
160 {
161         struct ast_bridge_config bconfig;
162         struct ast_channel *chan;
163         struct ast_channel *peer;
164 };
165
166 static void check_goto_on_transfer(struct ast_channel *chan) 
167 {
168         struct ast_channel *xferchan;
169         const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
170         char *x, *goto_on_transfer;
171         struct ast_frame *f;
172
173         if (!ast_strlen_zero(val) && (goto_on_transfer = ast_strdupa(val)) && (xferchan = ast_channel_alloc(0))) {
174                 for (x = goto_on_transfer; x && *x; x++)
175                         if (*x == '^')
176                                 *x = '|';
177                 strcpy(xferchan->name, chan->name);
178                 /* Make formats okay */
179                 xferchan->readformat = chan->readformat;
180                 xferchan->writeformat = chan->writeformat;
181                 ast_channel_masquerade(xferchan, chan);
182                 ast_parseable_goto(xferchan, goto_on_transfer);
183                 xferchan->_state = AST_STATE_UP;
184                 ast_clear_flag(xferchan, AST_FLAGS_ALL);        
185                 xferchan->_softhangup = 0;
186                 if ((f = ast_read(xferchan))) {
187                         ast_frfree(f);
188                         f = NULL;
189                         ast_pbx_start(xferchan);
190                 } else {
191                         ast_hangup(xferchan);
192                 }
193         }
194 }
195
196 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name);
197
198
199 static void *ast_bridge_call_thread(void *data) 
200 {
201         struct ast_bridge_thread_obj *tobj = data;
202
203         tobj->chan->appl = "Transferred Call";
204         tobj->chan->data = tobj->peer->name;
205         tobj->peer->appl = "Transferred Call";
206         tobj->peer->data = tobj->chan->name;
207         if (tobj->chan->cdr) {
208                 ast_cdr_reset(tobj->chan->cdr, NULL);
209                 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
210         }
211         if (tobj->peer->cdr) {
212                 ast_cdr_reset(tobj->peer->cdr, NULL);
213                 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
214         }
215
216         ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
217         ast_hangup(tobj->chan);
218         ast_hangup(tobj->peer);
219         tobj->chan = tobj->peer = NULL;
220         free(tobj);
221         tobj=NULL;
222         return NULL;
223 }
224
225 static void ast_bridge_call_thread_launch(void *data) 
226 {
227         pthread_t thread;
228         pthread_attr_t attr;
229         struct sched_param sched;
230
231         pthread_attr_init(&attr);
232         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
233         ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
234         pthread_attr_destroy(&attr);
235         memset(&sched, 0, sizeof(sched));
236         pthread_setschedparam(thread, SCHED_RR, &sched);
237 }
238
239
240
241 static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
242 {
243         int res;
244         int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
245         char tmp[256];
246         char *message[5] = {NULL, NULL, NULL, NULL, NULL};
247
248         snprintf(tmp, sizeof(tmp), "Parked on %d", parkingnum);
249         message[0] = tmp;
250         res = adsi_load_session(chan, NULL, 0, 1);
251         if (res == -1) {
252                 return res;
253         }
254         return adsi_print(chan, message, justify, 1);
255 }
256
257 /*--- ast_park_call: Park a call */
258 /* We put the user in the parking list, then wake up the parking thread to be sure it looks
259            after these channels too */
260 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
261 {
262         struct parkeduser *pu, *cur;
263         int i,x,parking_range;
264         char exten[AST_MAX_EXTENSION];
265         struct ast_context *con;
266
267         pu = malloc(sizeof(struct parkeduser));
268         if (!pu) {
269                 ast_log(LOG_WARNING, "Out of memory\n");
270                 return -1;
271         }
272         memset(pu, 0, sizeof(struct parkeduser));
273         ast_mutex_lock(&parking_lock);
274         parking_range = parking_stop - parking_start+1;
275         for (i = 0; i < parking_range; i++) {
276                 x = (i + parking_offset) % parking_range + parking_start;
277                 cur = parkinglot;
278                 while(cur) {
279                         if (cur->parkingnum == x) 
280                                 break;
281                         cur = cur->next;
282                 }
283                 if (!cur)
284                         break;
285         }
286
287         if (!(i < parking_range)) {
288                 ast_log(LOG_WARNING, "No more parking spaces\n");
289                 free(pu);
290                 ast_mutex_unlock(&parking_lock);
291                 return -1;
292         }
293         if (parkfindnext) 
294                 parking_offset = x - parking_start + 1;
295         chan->appl = "Parked Call";
296         chan->data = NULL; 
297
298         pu->chan = chan;
299         /* Start music on hold */
300         if (chan != peer) {
301                 ast_indicate(pu->chan, AST_CONTROL_HOLD);
302                 ast_moh_start(pu->chan, NULL);
303         }
304         pu->start = ast_tvnow();
305         pu->parkingnum = x;
306         if (timeout > 0)
307                 pu->parkingtime = timeout;
308         else
309                 pu->parkingtime = parkingtime;
310         if (extout)
311                 *extout = x;
312         if (peer) 
313                 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
314
315         /* Remember what had been dialed, so that if the parking
316            expires, we try to come back to the same place */
317         if (!ast_strlen_zero(chan->macrocontext))
318                 ast_copy_string(pu->context, chan->macrocontext, sizeof(pu->context));
319         else
320                 ast_copy_string(pu->context, chan->context, sizeof(pu->context));
321         if (!ast_strlen_zero(chan->macroexten))
322                 ast_copy_string(pu->exten, chan->macroexten, sizeof(pu->exten));
323         else
324                 ast_copy_string(pu->exten, chan->exten, sizeof(pu->exten));
325         if (chan->macropriority)
326                 pu->priority = chan->macropriority;
327         else
328                 pu->priority = chan->priority;
329         pu->next = parkinglot;
330         parkinglot = pu;
331         /* If parking a channel directly, don't quiet yet get parking running on it */
332         if (peer == chan) 
333                 pu->notquiteyet = 1;
334         ast_mutex_unlock(&parking_lock);
335         /* Wake up the (presumably select()ing) thread */
336         pthread_kill(parking_thread, SIGURG);
337         if (option_verbose > 1) 
338                 ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
339
340         manager_event(EVENT_FLAG_CALL, "ParkedCall",
341                 "Exten: %d\r\n"
342                 "Channel: %s\r\n"
343                 "From: %s\r\n"
344                 "Timeout: %ld\r\n"
345                 "CallerID: %s\r\n"
346                 "CallerIDName: %s\r\n"
347                 ,pu->parkingnum, pu->chan->name, peer->name
348                 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
349                 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
350                 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
351                 );
352
353         if (peer) {
354                 if (adsipark && adsi_available(peer)) {
355                         adsi_announce_park(peer, pu->parkingnum);
356                 }
357                 if (adsipark && adsi_available(peer)) {
358                         adsi_unload_session(peer);
359                 }
360         }
361         con = ast_context_find(parking_con);
362         if (!con) {
363                 con = ast_context_create(NULL, parking_con, registrar);
364                 if (!con) {
365                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
366                 }
367         }
368         if (con) {
369                 snprintf(exten, sizeof(exten), "%d", x);
370                 ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar);
371         }
372         if (peer) 
373                 ast_say_digits(peer, pu->parkingnum, "", peer->language);
374         if (pu->notquiteyet) {
375                 /* Wake up parking thread if we're really done */
376                 ast_moh_start(pu->chan, NULL);
377                 pu->notquiteyet = 0;
378                 pthread_kill(parking_thread, SIGURG);
379         }
380         return 0;
381 }
382
383 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
384 {
385         struct ast_channel *chan;
386         struct ast_frame *f;
387
388         /* Make a new, fake channel that we'll use to masquerade in the real one */
389         chan = ast_channel_alloc(0);
390         if (chan) {
391                 /* Let us keep track of the channel name */
392                 snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name);
393
394                 /* Make formats okay */
395                 chan->readformat = rchan->readformat;
396                 chan->writeformat = rchan->writeformat;
397                 ast_channel_masquerade(chan, rchan);
398
399                 /* Setup the extensions and such */
400                 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
401                 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
402                 chan->priority = rchan->priority;
403
404                 /* Make the masq execute */
405                 f = ast_read(chan);
406                 if (f)
407                         ast_frfree(f);
408                 ast_park_call(chan, peer, timeout, extout);
409         } else {
410                 ast_log(LOG_WARNING, "Unable to create parked channel\n");
411                 return -1;
412         }
413         return 0;
414 }
415
416
417 #define FEATURE_RETURN_HANGUP           -1
418 #define FEATURE_RETURN_SUCCESSBREAK      0
419 #define FEATURE_RETURN_PBX_KEEPALIVE    AST_PBX_KEEPALIVE
420 #define FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER
421 #define FEATURE_RETURN_PASSDIGITS        21
422 #define FEATURE_RETURN_STOREDIGITS       22
423 #define FEATURE_RETURN_SUCCESS           23
424
425 #define FEATURE_SENSE_CHAN      (1 << 0)
426 #define FEATURE_SENSE_PEER      (1 << 1)
427
428
429 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
430 {
431         char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
432         int x = 0;
433         size_t len;
434         struct ast_channel *caller_chan = NULL, *callee_chan = NULL;
435
436
437         if(sense == 2) {
438                 caller_chan = peer;
439                 callee_chan = chan;
440         } else {
441                 callee_chan = peer;
442                 caller_chan = chan;
443         }
444         
445         if (!monitor_ok) {
446                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
447                 return -1;
448         }
449
450         if (!monitor_app) { 
451                 if (!(monitor_app = pbx_findapp("Monitor"))) {
452                         monitor_ok=0;
453                         ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
454                         return -1;
455                 }
456         }
457         if (!ast_strlen_zero(courtesytone)) {
458                 if (ast_autoservice_start(callee_chan))
459                         return -1;
460                 if (!ast_streamfile(caller_chan, courtesytone, caller_chan->language)) {
461                         if (ast_waitstream(caller_chan, "") < 0) {
462                                 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
463                                 ast_autoservice_stop(callee_chan);
464                                 return -1;
465                         }
466                 }
467                 if (ast_autoservice_stop(callee_chan))
468                         return -1;
469         }
470         
471         if (callee_chan->monitor) {
472                 if (option_verbose > 3)
473                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
474                 ast_monitor_stop(callee_chan, 1);
475                 return FEATURE_RETURN_SUCCESS;
476         }
477
478         if (caller_chan && callee_chan) {
479                 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
480                 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
481
482                 if (!touch_format)
483                         touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
484
485                 if (!touch_monitor)
486                         touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
487         
488                 if (touch_monitor) {
489                         len = strlen(touch_monitor) + 50;
490                         args = alloca(len);
491                         touch_filename = alloca(len);
492                         snprintf(touch_filename, len, "auto-%ld-%s", time(NULL), touch_monitor);
493                         snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
494                 } else {
495                         caller_chan_id = ast_strdupa(caller_chan->cid.cid_num ? caller_chan->cid.cid_num : caller_chan->name);
496                         callee_chan_id = ast_strdupa(callee_chan->cid.cid_num ? callee_chan->cid.cid_num : callee_chan->name);
497                         len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
498                         args = alloca(len);
499                         touch_filename = alloca(len);
500                         snprintf(touch_filename, len, "auto-%ld-%s-%s", time(NULL), caller_chan_id, callee_chan_id);
501                         snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
502                 }
503
504                 for( x = 0; x < strlen(args); x++)
505                         if (args[x] == '/')
506                                 args[x] = '-';
507                 
508                 if (option_verbose > 3)
509                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
510
511                 pbx_exec(callee_chan, monitor_app, args, 1);
512                 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
513                 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
514         
515                 return FEATURE_RETURN_SUCCESS;
516         }
517         
518         ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");   
519         return -1;
520 }
521
522 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
523 {
524         if (option_verbose > 3)
525                 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
526         return FEATURE_RETURN_HANGUP;
527 }
528
529 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
530 {
531         struct ast_channel *transferer;
532         struct ast_channel *transferee;
533         const char *transferer_real_context;
534         char newext[256];
535         int res;
536
537         if (sense == FEATURE_SENSE_PEER) {
538                 transferer = peer;
539                 transferee = chan;
540         } else {
541                 transferer = chan;
542                 transferee = peer;
543         }
544         if (!(transferer_real_context = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
545            !(transferer_real_context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
546                 /* Use the non-macro context to transfer the call */
547                 if (!ast_strlen_zero(transferer->macrocontext))
548                         transferer_real_context = transferer->macrocontext;
549                 else
550                         transferer_real_context = transferer->context;
551         }
552         /* Start autoservice on chan while we talk
553            to the originator */
554         ast_indicate(transferee, AST_CONTROL_HOLD);
555         ast_autoservice_start(transferee);
556         ast_moh_start(transferee, NULL);
557
558         memset(newext, 0, sizeof(newext));
559         
560         /* Transfer */
561         if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
562                 ast_moh_stop(transferee);
563                 ast_autoservice_stop(transferee);
564                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
565                 return res;
566         }
567         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
568                 ast_moh_stop(transferee);
569                 ast_autoservice_stop(transferee);
570                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
571                 return res;
572         } else if (res > 0) {
573                 /* If they've typed a digit already, handle it */
574                 newext[0] = (char) res;
575         }
576
577         ast_stopstream(transferer);
578         res = ast_app_dtget(transferer, transferer_real_context, newext, sizeof(newext), 100, transferdigittimeout);
579         if (res < 0) {
580                 ast_moh_stop(transferee);
581                 ast_autoservice_stop(transferee);
582                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
583                 return res;
584         }
585         if (!strcmp(newext, ast_parking_ext())) {
586                 ast_moh_stop(transferee);
587
588                 res = ast_autoservice_stop(transferee);
589                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
590                 if (res)
591                         res = -1;
592                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {
593                         /* We return non-zero, but tell the PBX not to hang the channel when
594                            the thread dies -- We have to be careful now though.  We are responsible for 
595                            hanging up the channel, else it will never be hung up! */
596
597                         if (transferer == peer)
598                                 res = AST_PBX_KEEPALIVE;
599                         else
600                                 res = AST_PBX_NO_HANGUP_PEER;
601                         return res;
602                 } else {
603                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
604                 }
605                 /* XXX Maybe we should have another message here instead of invalid extension XXX */
606         } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
607                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
608                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
609                 ast_moh_stop(transferee);
610                 res=ast_autoservice_stop(transferee);
611                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
612                 if (!transferee->pbx) {
613                         /* Doh!  Use our handy async_goto functions */
614                         if (option_verbose > 2) 
615                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
616                                                                 ,transferee->name, newext, transferer_real_context);
617                         if (ast_async_goto(transferee, transferer_real_context, newext, 1))
618                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
619                         res = -1;
620                 } else {
621                         /* Set the channel's new extension, since it exists, using transferer context */
622                         ast_copy_string(transferee->exten, newext, sizeof(transferee->exten));
623                         ast_copy_string(transferee->context, transferer_real_context, sizeof(transferee->context));
624                         transferee->priority = 0;
625                 }
626                 check_goto_on_transfer(transferer);
627                 return res;
628         } else {
629                 if (option_verbose > 2) 
630                         ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", newext, transferer_real_context);
631         }
632         if (!ast_strlen_zero(xferfailsound))
633                 res = ast_streamfile(transferer, xferfailsound, transferee->language);
634         else
635                 res = 0;
636         if (res) {
637                 ast_moh_stop(transferee);
638                 ast_autoservice_stop(transferee);
639                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
640                 return res;
641         }
642         res = ast_waitstream(transferer, AST_DIGIT_ANY);
643         ast_stopstream(transferer);
644         ast_moh_stop(transferee);
645         res = ast_autoservice_stop(transferee);
646         ast_indicate(transferee, AST_CONTROL_UNHOLD);
647         if (res) {
648                 if (option_verbose > 1)
649                         ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
650                 return res;
651         }
652         return FEATURE_RETURN_SUCCESS;
653 }
654
655 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
656 {
657         struct ast_channel *transferer;
658         struct ast_channel *transferee;
659         struct ast_channel *newchan, *xferchan=NULL;
660         int outstate=0;
661         struct ast_bridge_config bconfig;
662         const char *transferer_real_context;
663         char xferto[256],dialstr[265];
664         char *cid_num;
665         char *cid_name;
666         int res;
667         struct ast_frame *f = NULL;
668         struct ast_bridge_thread_obj *tobj;
669
670         ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
671         if (sense == FEATURE_SENSE_PEER) {
672                 transferer = peer;
673                 transferee = chan;
674         } else {
675                 transferer = chan;
676                 transferee = peer;
677         }
678         if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
679            !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
680                 /* Use the non-macro context to transfer the call */
681                 if (!ast_strlen_zero(transferer->macrocontext))
682                         transferer_real_context = transferer->macrocontext;
683                 else
684                         transferer_real_context = transferer->context;
685         }
686         /* Start autoservice on chan while we talk
687            to the originator */
688         ast_indicate(transferee, AST_CONTROL_HOLD);
689         ast_autoservice_start(transferee);
690         ast_moh_start(transferee, NULL);
691         memset(xferto, 0, sizeof(xferto));
692         /* Transfer */
693         if ((res = ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
694                 ast_moh_stop(transferee);
695                 ast_autoservice_stop(transferee);
696                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
697                 return res;
698         }
699         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
700                 ast_moh_stop(transferee);
701                 ast_autoservice_stop(transferee);
702                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
703                 return res;
704         } else if(res > 0) {
705                 /* If they've typed a digit already, handle it */
706                 xferto[0] = (char) res;
707         }
708         if ((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
709                 cid_num = transferer->cid.cid_num;
710                 cid_name = transferer->cid.cid_name;
711                 if (ast_exists_extension(transferer, transferer_real_context,xferto, 1, cid_num)) {
712                         snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context);
713                         newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats), dialstr, 15000, &outstate, cid_num, cid_name);
714                         ast_indicate(transferer, -1);
715                         if (newchan) {
716                                 res = ast_channel_make_compatible(transferer, newchan);
717                                 if (res < 0) {
718                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
719                                         ast_hangup(newchan);
720                                         return -1;
721                                 }
722                                 memset(&bconfig,0,sizeof(struct ast_bridge_config));
723                                 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
724                                 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
725                                 res = ast_bridge_call(transferer,newchan,&bconfig);
726                                 if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
727                                         ast_hangup(newchan);
728                                         if (f) {
729                                                 ast_frfree(f);
730                                                 f = NULL;
731                                         }
732                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(transferer, xfersound, transferer->language)) {
733                                                 if (ast_waitstream(transferer, "") < 0) {
734                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
735                                                 }
736                                         }
737                                         ast_moh_stop(transferee);
738                                         ast_autoservice_stop(transferee);
739                                         ast_indicate(transferee, AST_CONTROL_UNHOLD);
740                                         transferer->_softhangup = 0;
741                                         return FEATURE_RETURN_SUCCESS;
742                                 }
743                                 
744                                 res = ast_channel_make_compatible(transferee, newchan);
745                                 if (res < 0) {
746                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
747                                         ast_hangup(newchan);
748                                         return -1;
749                                 }
750                                 
751                                 
752                                 ast_moh_stop(transferee);
753                                 
754                                 if ((ast_autoservice_stop(transferee) < 0)
755                                    || (ast_waitfordigit(transferee, 100) < 0)
756                                    || (ast_waitfordigit(newchan, 100) < 0) 
757                                    || ast_check_hangup(transferee) 
758                                    || ast_check_hangup(newchan)) {
759                                         ast_hangup(newchan);
760                                         res = -1;
761                                         return -1;
762                                 }
763
764                                 if ((xferchan = ast_channel_alloc(0))) {
765                                         snprintf(xferchan->name, sizeof (xferchan->name), "Transfered/%s",transferee->name);
766                                         /* Make formats okay */
767                                         xferchan->readformat = transferee->readformat;
768                                         xferchan->writeformat = transferee->writeformat;
769                                         ast_channel_masquerade(xferchan, transferee);
770                                         ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
771                                         xferchan->_state = AST_STATE_UP;
772                                         ast_clear_flag(xferchan, AST_FLAGS_ALL);        
773                                         xferchan->_softhangup = 0;
774
775                                         if ((f = ast_read(xferchan))) {
776                                                 ast_frfree(f);
777                                                 f = NULL;
778                                         }
779                                         
780                                 } else {
781                                         ast_hangup(newchan);
782                                         return -1;
783                                 }
784
785                                 newchan->_state = AST_STATE_UP;
786                                 ast_clear_flag(newchan, AST_FLAGS_ALL); 
787                                 newchan->_softhangup = 0;
788
789                                 tobj = malloc(sizeof(struct ast_bridge_thread_obj));
790                                 if (tobj) {
791                                         memset(tobj,0,sizeof(struct ast_bridge_thread_obj));
792                                         tobj->chan = xferchan;
793                                         tobj->peer = newchan;
794                                         tobj->bconfig = *config;
795         
796                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(newchan, xfersound, newchan->language)) {
797                                                 if (ast_waitstream(newchan, "") < 0) {
798                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
799                                                 }
800                                         }
801                                         ast_bridge_call_thread_launch(tobj);
802                                 } else {
803                                         ast_log(LOG_WARNING, "Out of memory!\n");
804                                         ast_hangup(xferchan);
805                                         ast_hangup(newchan);
806                                 }
807                                 return -1;
808                                 
809                         } else {
810                                 ast_moh_stop(transferee);
811                                 ast_autoservice_stop(transferee);
812                                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
813                                 /* any reason besides user requested cancel and busy triggers the failed sound */
814                                 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY && !ast_strlen_zero(xferfailsound)) {
815                                         res = ast_streamfile(transferer, xferfailsound, transferer->language);
816                                         if (!res && (ast_waitstream(transferer, "") < 0)) {
817                                                 return -1;
818                                         }
819                                 }
820                                 return FEATURE_RETURN_SUCCESS;
821                         }
822                 } else {
823                         ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
824                         ast_moh_stop(transferee);
825                         ast_autoservice_stop(transferee);
826                         ast_indicate(transferee, AST_CONTROL_UNHOLD);
827                         res = ast_streamfile(transferer, "beeperr", transferer->language);
828                         if (!res && (ast_waitstream(transferer, "") < 0)) {
829                                 return -1;
830                         }
831                 }
832         }  else {
833                 ast_log(LOG_WARNING, "Did not read data.\n");
834                 res = ast_streamfile(transferer, "beeperr", transferer->language);
835                 if (ast_waitstream(transferer, "") < 0) {
836                         return -1;
837                 }
838         }
839         ast_moh_stop(transferee);
840         ast_autoservice_stop(transferee);
841         ast_indicate(transferee, AST_CONTROL_UNHOLD);
842
843         return FEATURE_RETURN_SUCCESS;
844 }
845
846
847 /* add atxfer and automon as undefined so you can only use em if you configure them */
848 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
849 struct ast_call_feature builtin_features[] = 
850  {
851         { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
852         { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
853         { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
854         { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
855 };
856
857
858 static AST_LIST_HEAD(feature_list,ast_call_feature) feature_list;
859
860 /* register new feature into feature_list*/
861 void ast_register_feature(struct ast_call_feature *feature)
862 {
863         if (!feature) {
864                 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
865                 return;
866         }
867   
868         AST_LIST_LOCK(&feature_list);
869         AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
870         AST_LIST_UNLOCK(&feature_list);
871
872         if (option_verbose >= 2) 
873                 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
874 }
875
876 /* unregister feature from feature_list */
877 void ast_unregister_feature(struct ast_call_feature *feature)
878 {
879         if (!feature) return;
880
881         AST_LIST_LOCK(&feature_list);
882         AST_LIST_REMOVE(&feature_list,feature,feature_entry);
883         AST_LIST_UNLOCK(&feature_list);
884         free(feature);
885 }
886
887 static void ast_unregister_features(void)
888 {
889         struct ast_call_feature *feature;
890
891         AST_LIST_LOCK(&feature_list);
892         while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
893                 free(feature);
894         AST_LIST_UNLOCK(&feature_list);
895 }
896
897 /* find a feature by name */
898 static struct ast_call_feature *find_feature(char *name)
899 {
900         struct ast_call_feature *tmp;
901
902         AST_LIST_LOCK(&feature_list);
903         AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
904                 if (!strcasecmp(tmp->sname, name))
905                         break;
906         }
907         AST_LIST_UNLOCK(&feature_list);
908
909         return tmp;
910 }
911
912 /* exec an app by feature */
913 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
914 {
915         struct ast_app *app;
916         struct ast_call_feature *feature;
917         int res;
918
919         AST_LIST_LOCK(&feature_list);
920         AST_LIST_TRAVERSE(&feature_list,feature,feature_entry) {
921                 if (!strcasecmp(feature->exten,code)) break;
922         }
923         AST_LIST_UNLOCK(&feature_list);
924
925         if (!feature) { /* shouldn't ever happen! */
926                 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
927                 return -1; 
928         }
929         
930         app = pbx_findapp(feature->app);
931         if (app) {
932                 struct ast_channel *work = chan;
933                 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
934                         work = peer;
935                 res = pbx_exec(work, app, feature->app_args, 1);
936                 if (res < 0)
937                         return res; 
938         } else {
939                 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
940                 return -2;
941         }
942         
943         return FEATURE_RETURN_SUCCESS;
944 }
945
946 static void unmap_features(void)
947 {
948         int x;
949         for (x = 0; x < FEATURES_COUNT; x++)
950                 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
951 }
952
953 static int remap_feature(const char *name, const char *value)
954 {
955         int x;
956         int res = -1;
957         for (x = 0; x < FEATURES_COUNT; x++) {
958                 if (!strcasecmp(name, builtin_features[x].sname)) {
959                         ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
960                         if (option_verbose > 1)
961                                 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);
962                         res = 0;
963                 } else if (!strcmp(value, builtin_features[x].exten)) 
964                         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);
965         }
966         return res;
967 }
968
969 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
970 {
971         int x;
972         struct ast_flags features;
973         int res = FEATURE_RETURN_PASSDIGITS;
974         struct ast_call_feature *feature;
975         const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
976
977         if (sense == FEATURE_SENSE_CHAN)
978                 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);   
979         else
980                 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);   
981         ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
982
983         for (x=0; x < FEATURES_COUNT; x++) {
984                 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
985                     !ast_strlen_zero(builtin_features[x].exten)) {
986                         /* Feature is up for consideration */
987                         if (!strcmp(builtin_features[x].exten, code)) {
988                                 res = builtin_features[x].operation(chan, peer, config, code, sense);
989                                 break;
990                         } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
991                                 if (res == FEATURE_RETURN_PASSDIGITS)
992                                         res = FEATURE_RETURN_STOREDIGITS;
993                         }
994                 }
995         }
996
997
998         if (!ast_strlen_zero(dynamic_features)) {
999                 char *tmp = ast_strdupa(dynamic_features);
1000                 char *tok;
1001
1002                 if (!tmp)
1003                         return res;
1004                 
1005                 while ((tok = strsep(&tmp, "#")) != NULL) {
1006                         feature = find_feature(tok);
1007                         
1008                         if (feature) {
1009                                 /* Feature is up for consideration */
1010                                 if (!strcmp(feature->exten, code)) {
1011                                         if (option_verbose > 2)
1012                                                 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1013                                         res = feature->operation(chan, peer, config, code, sense);
1014                                         break;
1015                                 } else if (!strncmp(feature->exten, code, strlen(code))) {
1016                                         res = FEATURE_RETURN_STOREDIGITS;
1017                                 }
1018                         }
1019                 }
1020         }
1021         
1022         return res;
1023 }
1024
1025 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1026 {
1027         int x;
1028         
1029         ast_clear_flag(config, AST_FLAGS_ALL);  
1030         for (x = 0; x < FEATURES_COUNT; x++) {
1031                 if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
1032                         if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1033                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1034
1035                         if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1036                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1037                 }
1038         }
1039         
1040         if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1041                 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1042
1043                 if (dynamic_features) {
1044                         char *tmp = ast_strdupa(dynamic_features);
1045                         char *tok;
1046                         struct ast_call_feature *feature;
1047
1048                         if (!tmp) {
1049                                 return;
1050                         }
1051
1052                         /* while we have a feature */
1053                         while (NULL != (tok = strsep(&tmp, "#"))) {
1054                                 if ((feature = find_feature(tok))) {
1055                                         if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1056                                                 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
1057                                                         ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1058                                                 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
1059                                                         ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1060                                         }
1061                                 }
1062                         }
1063                 }
1064         }
1065 }
1066
1067
1068 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name)
1069 {
1070         int state = 0;
1071         int cause = 0;
1072         int to;
1073         struct ast_channel *chan;
1074         struct ast_channel *monitor_chans[2];
1075         struct ast_channel *active_channel;
1076         struct ast_frame *f = NULL;
1077         int res = 0, ready = 0;
1078         
1079         if ((chan = ast_request(type, format, data, &cause))) {
1080                 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1081                 ast_channel_inherit_variables(caller, chan);    
1082                 if (!ast_call(chan, data, timeout)) {
1083                         struct timeval started;
1084                         int x, len = 0;
1085                         char *disconnect_code = NULL, *dialed_code = NULL;
1086
1087                         ast_indicate(caller, AST_CONTROL_RINGING);
1088                         /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1089                         for (x=0; x < FEATURES_COUNT; x++) {
1090                                 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1091                                         continue;
1092
1093                                 disconnect_code = builtin_features[x].exten;
1094                                 len = strlen(disconnect_code) + 1;
1095                                 dialed_code = alloca(len);
1096                                 memset(dialed_code, 0, len);
1097                                 break;
1098                         }
1099                         x = 0;
1100                         started = ast_tvnow();
1101                         to = timeout;
1102                         while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1103                                 monitor_chans[0] = caller;
1104                                 monitor_chans[1] = chan;
1105                                 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1106
1107                                 /* see if the timeout has been violated */
1108                                 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1109                                         state = AST_CONTROL_UNHOLD;
1110                                         ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1111                                         break; /*doh! timeout*/
1112                                 }
1113
1114                                 if (!active_channel) {
1115                                         continue;
1116                                 }
1117
1118                                 if (chan && (chan == active_channel)){
1119                                         f = ast_read(chan);
1120                                         if (f == NULL) { /*doh! where'd he go?*/
1121                                                 state = AST_CONTROL_HANGUP;
1122                                                 res = 0;
1123                                                 break;
1124                                         }
1125                                         
1126                                         if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1127                                                 if (f->subclass == AST_CONTROL_RINGING) {
1128                                                         state = f->subclass;
1129                                                         if (option_verbose > 2)
1130                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1131                                                         ast_indicate(caller, AST_CONTROL_RINGING);
1132                                                 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1133                                                         state = f->subclass;
1134                                                         ast_frfree(f);
1135                                                         f = NULL;
1136                                                         break;
1137                                                 } else if (f->subclass == AST_CONTROL_ANSWER) {
1138                                                         /* This is what we are hoping for */
1139                                                         state = f->subclass;
1140                                                         ast_frfree(f);
1141                                                         f = NULL;
1142                                                         ready=1;
1143                                                         break;
1144                                                 } else {
1145                                                         ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1146                                                 }
1147                                                 /* else who cares */
1148                                         }
1149
1150                                 } else if (caller && (active_channel == caller)) {
1151                                         f = ast_read(caller);
1152                                         if (f == NULL) { /*doh! where'd he go?*/
1153                                                 if (caller->_softhangup && !chan->_softhangup) {
1154                                                         /* make this a blind transfer */
1155                                                         ready = 1;
1156                                                         break;
1157                                                 }
1158                                                 state = AST_CONTROL_HANGUP;
1159                                                 res = 0;
1160                                                 break;
1161                                         }
1162                                         
1163                                         if (f->frametype == AST_FRAME_DTMF) {
1164                                                 dialed_code[x++] = f->subclass;
1165                                                 dialed_code[x] = '\0';
1166                                                 if (strlen(dialed_code) == len) {
1167                                                         x = 0;
1168                                                 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1169                                                         x = 0;
1170                                                         dialed_code[x] = '\0';
1171                                                 }
1172                                                 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1173                                                         /* Caller Canceled the call */
1174                                                         state = AST_CONTROL_UNHOLD;
1175                                                         ast_frfree(f);
1176                                                         f = NULL;
1177                                                         break;
1178                                                 }
1179                                         }
1180                                 }
1181                                 if (f) {
1182                                         ast_frfree(f);
1183                                 }
1184                         }
1185                 } else
1186                         ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1187         } else {
1188                 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1189                 switch(cause) {
1190                 case AST_CAUSE_BUSY:
1191                         state = AST_CONTROL_BUSY;
1192                         break;
1193                 case AST_CAUSE_CONGESTION:
1194                         state = AST_CONTROL_CONGESTION;
1195                         break;
1196                 }
1197         }
1198         
1199         ast_indicate(caller, -1);
1200         if (chan && ready) {
1201                 if (chan->_state == AST_STATE_UP) 
1202                         state = AST_CONTROL_ANSWER;
1203                 res = 0;
1204         } else if(chan) {
1205                 res = -1;
1206                 ast_hangup(chan);
1207                 chan = NULL;
1208         } else {
1209                 res = -1;
1210         }
1211         
1212         if (outstate)
1213                 *outstate = state;
1214
1215         if (chan && res <= 0) {
1216                 if (!chan->cdr) {
1217                         chan->cdr = ast_cdr_alloc();
1218                 }
1219                 if (chan->cdr) {
1220                         char tmp[256];
1221                         ast_cdr_init(chan->cdr, chan);
1222                         snprintf(tmp, 256, "%s/%s", type, (char *)data);
1223                         ast_cdr_setapp(chan->cdr,"Dial",tmp);
1224                         ast_cdr_update(chan);
1225                         ast_cdr_start(chan->cdr);
1226                         ast_cdr_end(chan->cdr);
1227                         /* If the cause wasn't handled properly */
1228                         if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1229                                 ast_cdr_failed(chan->cdr);
1230                 } else {
1231                         ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1232                 }
1233         }
1234         
1235         return chan;
1236 }
1237
1238 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1239 {
1240         /* Copy voice back and forth between the two channels.  Give the peer
1241            the ability to transfer calls with '#<extension' syntax. */
1242         struct ast_frame *f;
1243         struct ast_channel *who;
1244         char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1245         char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1246         int res;
1247         int diff;
1248         int hasfeatures=0;
1249         int hadfeatures=0;
1250         struct ast_option_header *aoh;
1251         struct timeval start = { 0 , 0 };
1252         struct ast_bridge_config backup_config;
1253
1254         memset(&backup_config, 0, sizeof(backup_config));
1255
1256         config->start_time = ast_tvnow();
1257
1258         if (chan && peer) {
1259                 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1260                 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1261         } else if (chan)
1262                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1263
1264         if (monitor_ok) {
1265                 const char *monitor_exec;
1266                 struct ast_channel *src = NULL;
1267                 if (!monitor_app) { 
1268                         if (!(monitor_app = pbx_findapp("Monitor")))
1269                                 monitor_ok=0;
1270                 }
1271                 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
1272                         src = chan;
1273                 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1274                         src = peer;
1275                 if (src) {
1276                         char *tmp = ast_strdupa(monitor_exec);
1277                         if (tmp) {
1278                                 pbx_exec(src, monitor_app, tmp, 1);
1279                         } else {
1280                                 ast_log(LOG_ERROR, "Monitor failed: out of memory\n");
1281                         }
1282                 }
1283         }
1284         
1285         set_config_flags(chan, peer, config);
1286         config->firstpass = 1;
1287
1288         /* Answer if need be */
1289         if (ast_answer(chan))
1290                 return -1;
1291         peer->appl = "Bridged Call";
1292         peer->data = chan->name;
1293
1294         /* copy the userfield from the B-leg to A-leg if applicable */
1295         if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1296                 char tmp[256];
1297                 if (!ast_strlen_zero(chan->cdr->userfield)) {
1298                         snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1299                         ast_cdr_appenduserfield(chan, tmp);
1300                 } else
1301                         ast_cdr_setuserfield(chan, peer->cdr->userfield);
1302                 /* free the peer's cdr without ast_cdr_free complaining */
1303                 free(peer->cdr);
1304                 peer->cdr = NULL;
1305         }
1306         for (;;) {
1307                 if (config->feature_timer)
1308                         start = ast_tvnow();
1309
1310                 res = ast_channel_bridge(chan, peer, config, &f, &who);
1311
1312                 if (config->feature_timer) {
1313                         /* Update time limit for next pass */
1314                         diff = ast_tvdiff_ms(ast_tvnow(), start);
1315                         config->feature_timer -= diff;
1316                         if (hasfeatures) {
1317                                 /* Running on backup config, meaning a feature might be being
1318                                    activated, but that's no excuse to keep things going 
1319                                    indefinitely! */
1320                                 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1321                                         ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1322                                         config->feature_timer = 0;
1323                                         who = chan;
1324                                         if (f)
1325                                                 ast_frfree(f);
1326                                         f = NULL;
1327                                         res = 0;
1328                                 } else if (config->feature_timer <= 0) {
1329                                         /* Not *really* out of time, just out of time for
1330                                            digits to come in for features. */
1331                                         ast_log(LOG_DEBUG, "Timed out for feature!\n");
1332                                         if (!ast_strlen_zero(peer_featurecode)) {
1333                                                 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1334                                                 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1335                                         }
1336                                         if (!ast_strlen_zero(chan_featurecode)) {
1337                                                 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1338                                                 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1339                                         }
1340                                         if (f)
1341                                                 ast_frfree(f);
1342                                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1343                                         if (!hasfeatures) {
1344                                                 /* Restore original (possibly time modified) bridge config */
1345                                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1346                                                 memset(&backup_config, 0, sizeof(backup_config));
1347                                         }
1348                                         hadfeatures = hasfeatures;
1349                                         /* Continue as we were */
1350                                         continue;
1351                                 }
1352                         } else {
1353                                 if (config->feature_timer <=0) {
1354                                         /* We ran out of time */
1355                                         config->feature_timer = 0;
1356                                         who = chan;
1357                                         if (f)
1358                                                 ast_frfree(f);
1359                                         f = NULL;
1360                                         res = 0;
1361                                 }
1362                         }
1363                 }
1364                 if (res < 0) {
1365                         ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1366                         return -1;
1367                 }
1368                 
1369                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
1370                         (f->subclass == AST_CONTROL_CONGESTION)))) {
1371                                 res = -1;
1372                                 break;
1373                 }
1374                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
1375                         if (who == chan)
1376                                 ast_indicate(peer, AST_CONTROL_RINGING);
1377                         else
1378                                 ast_indicate(chan, AST_CONTROL_RINGING);
1379                 }
1380                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
1381                         if (who == chan)
1382                                 ast_indicate(peer, -1);
1383                         else
1384                                 ast_indicate(chan, -1);
1385                 }
1386                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
1387                         if (who == chan)
1388                                 ast_indicate(peer, AST_CONTROL_FLASH);
1389                         else
1390                                 ast_indicate(chan, AST_CONTROL_FLASH);
1391                 }
1392                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
1393                         aoh = f->data;
1394                         /* Forward option Requests */
1395                         if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
1396                                 if (who == chan)
1397                                         ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1398                                 else
1399                                         ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1400                         }
1401                 }
1402                 /* check for '*', if we find it it's time to disconnect */
1403                 if (f && (f->frametype == AST_FRAME_DTMF)) {
1404                         char *featurecode;
1405                         int sense;
1406                         struct ast_channel *other;
1407
1408                         hadfeatures = hasfeatures;
1409                         /* This cannot overrun because the longest feature is one shorter than our buffer */
1410                         if (who == chan) {
1411                                 other = peer;
1412                                 sense = FEATURE_SENSE_CHAN;
1413                                 featurecode = chan_featurecode;
1414                         } else  {
1415                                 other = chan;
1416                                 sense = FEATURE_SENSE_PEER;
1417                                 featurecode = peer_featurecode;
1418                         }
1419                         featurecode[strlen(featurecode)] = f->subclass;
1420                         config->feature_timer = backup_config.feature_timer;
1421                         res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1422                         switch(res) {
1423                         case FEATURE_RETURN_PASSDIGITS:
1424                                 ast_dtmf_stream(other, who, featurecode, 0);
1425                                 /* Fall through */
1426                         case FEATURE_RETURN_SUCCESS:
1427                                 memset(featurecode, 0, sizeof(chan_featurecode));
1428                                 break;
1429                         }
1430                         if (res >= FEATURE_RETURN_PASSDIGITS) {
1431                                 res = 0;
1432                         } else {
1433                                 ast_frfree(f);
1434                                 break;
1435                         }
1436                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1437                         if (hadfeatures && !hasfeatures) {
1438                                 /* Restore backup */
1439                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1440                                 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1441                         } else if (hasfeatures) {
1442                                 if (!hadfeatures) {
1443                                         /* Backup configuration */
1444                                         memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1445                                         /* Setup temporary config options */
1446                                         config->play_warning = 0;
1447                                         ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1448                                         ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1449                                         config->warning_freq = 0;
1450                                         config->warning_sound = NULL;
1451                                         config->end_sound = NULL;
1452                                         config->start_sound = NULL;
1453                                         config->firstpass = 0;
1454                                 }
1455                                 config->feature_timer = featuredigittimeout;
1456                                 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1457                         }
1458                 }
1459                 if (f)
1460                         ast_frfree(f);
1461         }
1462         return res;
1463 }
1464
1465 static void *do_parking_thread(void *ignore)
1466 {
1467         int ms, tms, max;
1468         struct parkeduser *pu, *pl, *pt = NULL;
1469         struct timeval tv;
1470         struct ast_frame *f;
1471         char exten[AST_MAX_EXTENSION];
1472         char *peername,*cp;
1473         char returnexten[AST_MAX_EXTENSION];
1474         struct ast_context *con;
1475         int x;
1476         fd_set rfds, efds;
1477         fd_set nrfds, nefds;
1478         FD_ZERO(&rfds);
1479         FD_ZERO(&efds);
1480
1481         for (;;) {
1482                 ms = -1;
1483                 max = -1;
1484                 ast_mutex_lock(&parking_lock);
1485                 pl = NULL;
1486                 pu = parkinglot;
1487                 FD_ZERO(&nrfds);
1488                 FD_ZERO(&nefds);
1489                 while(pu) {
1490                         if (pu->notquiteyet) {
1491                                 /* Pretend this one isn't here yet */
1492                                 pl = pu;
1493                                 pu = pu->next;
1494                                 continue;
1495                         }
1496                         tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1497                         if (tms > pu->parkingtime) {
1498                                 /* Stop music on hold */
1499                                 ast_moh_stop(pu->chan);
1500                                 ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
1501                                 /* Get chan, exten from derived kludge */
1502                                 if (pu->peername[0]) {
1503                                         peername = ast_strdupa(pu->peername);
1504                                         cp = strrchr(peername, '-');
1505                                         if (cp) 
1506                                                 *cp = 0;
1507                                         con = ast_context_find(parking_con_dial);
1508                                         if (!con) {
1509                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
1510                                                 if (!con) {
1511                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1512                                                 }
1513                                         }
1514                                         if (con) {
1515                                                 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1516                                                 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
1517                                         }
1518                                         ast_copy_string(pu->chan->exten, peername, sizeof(pu->chan->exten));
1519                                         ast_copy_string(pu->chan->context, parking_con_dial, sizeof(pu->chan->context));
1520                                         pu->chan->priority = 1;
1521
1522                                 } else {
1523                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
1524                                            should have their original extensions and such, but we copy to be on the safe side */
1525                                         ast_copy_string(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
1526                                         ast_copy_string(pu->chan->context, pu->context, sizeof(pu->chan->context));
1527                                         pu->chan->priority = pu->priority;
1528                                 }
1529
1530                                 manager_event(EVENT_FLAG_CALL, "ParkedCallTimeOut",
1531                                         "Exten: %d\r\n"
1532                                         "Channel: %s\r\n"
1533                                         "CallerID: %s\r\n"
1534                                         "CallerIDName: %s\r\n"
1535                                         ,pu->parkingnum, pu->chan->name
1536                                         ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1537                                         ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1538                                         );
1539
1540                                 if (option_verbose > 1) 
1541                                         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);
1542                                 /* Start up the PBX, or hang them up */
1543                                 if (ast_pbx_start(pu->chan))  {
1544                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
1545                                         ast_hangup(pu->chan);
1546                                 }
1547                                 /* And take them out of the parking lot */
1548                                 if (pl) 
1549                                         pl->next = pu->next;
1550                                 else
1551                                         parkinglot = pu->next;
1552                                 pt = pu;
1553                                 pu = pu->next;
1554                                 con = ast_context_find(parking_con);
1555                                 if (con) {
1556                                         snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1557                                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1558                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1559                                 } else
1560                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1561                                 free(pt);
1562                         } else {
1563                                 for (x = 0; x < AST_MAX_FDS; x++) {
1564                                         if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
1565                                                 if (FD_ISSET(pu->chan->fds[x], &efds))
1566                                                         ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
1567                                                 else
1568                                                         ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
1569                                                 pu->chan->fdno = x;
1570                                                 /* See if they need servicing */
1571                                                 f = ast_read(pu->chan);
1572                                                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
1573                                                         if (f)
1574                                                                 ast_frfree(f);
1575                                                         manager_event(EVENT_FLAG_CALL, "ParkedCallGiveUp",
1576                                                                 "Exten: %d\r\n"
1577                                                                 "Channel: %s\r\n"
1578                                                                 "CallerID: %s\r\n"
1579                                                                 "CallerIDName: %s\r\n"
1580                                                                 ,pu->parkingnum, pu->chan->name
1581                                                                 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1582                                                                 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1583                                                                 );
1584
1585                                                         /* There's a problem, hang them up*/
1586                                                         if (option_verbose > 1) 
1587                                                                 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
1588                                                         ast_hangup(pu->chan);
1589                                                         /* And take them out of the parking lot */
1590                                                         if (pl) 
1591                                                                 pl->next = pu->next;
1592                                                         else
1593                                                                 parkinglot = pu->next;
1594                                                         pt = pu;
1595                                                         pu = pu->next;
1596                                                         con = ast_context_find(parking_con);
1597                                                         if (con) {
1598                                                                 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1599                                                                 if (ast_context_remove_extension2(con, exten, 1, NULL))
1600                                                                         ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1601                                                         } else
1602                                                                 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1603                                                         free(pt);
1604                                                         break;
1605                                                 } else {
1606                                                         /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1607                                                         ast_frfree(f);
1608                                                         if (pu->moh_trys < 3 && !pu->chan->generatordata) {
1609                                                                 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source.  Restarting.\n");
1610                                                                 ast_moh_start(pu->chan, NULL);
1611                                                                 pu->moh_trys++;
1612                                                         }
1613                                                         goto std;       /* XXX Ick: jumping into an else statement??? XXX */
1614                                                 }
1615                                         }
1616                                 }
1617                                 if (x >= AST_MAX_FDS) {
1618 std:                                    for (x=0; x<AST_MAX_FDS; x++) {
1619                                                 /* Keep this one for next one */
1620                                                 if (pu->chan->fds[x] > -1) {
1621                                                         FD_SET(pu->chan->fds[x], &nrfds);
1622                                                         FD_SET(pu->chan->fds[x], &nefds);
1623                                                         if (pu->chan->fds[x] > max)
1624                                                                 max = pu->chan->fds[x];
1625                                                 }
1626                                         }
1627                                         /* Keep track of our longest wait */
1628                                         if ((tms < ms) || (ms < 0))
1629                                                 ms = tms;
1630                                         pl = pu;
1631                                         pu = pu->next;
1632                                 }
1633                         }
1634                 }
1635                 ast_mutex_unlock(&parking_lock);
1636                 rfds = nrfds;
1637                 efds = nefds;
1638                 tv = ast_samp2tv(ms, 1000);
1639                 /* Wait for something to happen */
1640                 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1641                 pthread_testcancel();
1642         }
1643         return NULL;    /* Never reached */
1644 }
1645
1646 static int park_call_exec(struct ast_channel *chan, void *data)
1647 {
1648         /* Data is unused at the moment but could contain a parking
1649            lot context eventually */
1650         int res=0;
1651         struct localuser *u;
1652         LOCAL_USER_ADD(u);
1653         /* Setup the exten/priority to be s/1 since we don't know
1654            where this call should return */
1655         strcpy(chan->exten, "s");
1656         chan->priority = 1;
1657         if (chan->_state != AST_STATE_UP)
1658                 res = ast_answer(chan);
1659         if (!res)
1660                 res = ast_safe_sleep(chan, 1000);
1661         if (!res)
1662                 res = ast_park_call(chan, chan, 0, NULL);
1663         LOCAL_USER_REMOVE(u);
1664         if (!res)
1665                 res = AST_PBX_KEEPALIVE;
1666         return res;
1667 }
1668
1669 static int park_exec(struct ast_channel *chan, void *data)
1670 {
1671         int res=0;
1672         struct localuser *u;
1673         struct ast_channel *peer=NULL;
1674         struct parkeduser *pu, *pl=NULL;
1675         char exten[AST_MAX_EXTENSION];
1676         struct ast_context *con;
1677         int park;
1678         int dres;
1679         struct ast_bridge_config config;
1680
1681         if (!data) {
1682                 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
1683                 return -1;
1684         }
1685         LOCAL_USER_ADD(u);
1686         park = atoi((char *)data);
1687         ast_mutex_lock(&parking_lock);
1688         pu = parkinglot;
1689         while(pu) {
1690                 if (pu->parkingnum == park) {
1691                         if (pl)
1692                                 pl->next = pu->next;
1693                         else
1694                                 parkinglot = pu->next;
1695                         break;
1696                 }
1697                 pl = pu;
1698                 pu = pu->next;
1699         }
1700         ast_mutex_unlock(&parking_lock);
1701         if (pu) {
1702                 peer = pu->chan;
1703                 con = ast_context_find(parking_con);
1704                 if (con) {
1705                         snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
1706                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1707                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1708                 } else
1709                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1710
1711                 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
1712                         "Exten: %d\r\n"
1713                         "Channel: %s\r\n"
1714                         "From: %s\r\n"
1715                         "CallerID: %s\r\n"
1716                         "CallerIDName: %s\r\n"
1717                         ,pu->parkingnum, pu->chan->name, chan->name
1718                         ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1719                         ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1720                         );
1721
1722                 free(pu);
1723         }
1724         /* JK02: it helps to answer the channel if not already up */
1725         if (chan->_state != AST_STATE_UP) {
1726                 ast_answer(chan);
1727         }
1728
1729         if (peer) {
1730                 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
1731                 
1732                 if (!ast_strlen_zero(courtesytone)) {
1733                         if (parkedplay == 0) {
1734                                 if (!ast_streamfile(chan, courtesytone, chan->language)) {
1735                                         if (ast_waitstream(chan, "") < 0) {
1736                                                 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1737                                                 ast_hangup(peer);
1738                                                 return -1;
1739                                         }
1740                                 }
1741                                 ast_moh_stop(peer);
1742                                 ast_indicate(peer, AST_CONTROL_UNHOLD);
1743                         } else {
1744                                 ast_moh_stop(peer);
1745                                 ast_indicate(peer, AST_CONTROL_UNHOLD);
1746                                 if (parkedplay == 2) {
1747                                         if (!ast_streamfile(chan, courtesytone, chan->language) && !ast_streamfile(peer, courtesytone, chan->language)) {
1748                                                 res = ast_waitstream(chan, "");
1749                                                 if (res >= 0)
1750                                                         res = ast_waitstream(peer, "");
1751                                                 if (res < 0) {
1752                                                         ast_log(LOG_WARNING, "Failed to play courtesy tones!\n");
1753                                                         ast_hangup(peer);
1754                                                         return -1;
1755                                                 }
1756                                         }
1757                                 } else if (parkedplay == 1) {
1758                                         if (!ast_streamfile(peer, courtesytone, chan->language)) {
1759                                                 if (ast_waitstream(peer, "") < 0) {
1760                                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1761                                                         ast_hangup(peer);
1762                                                         return -1;
1763                                                 }
1764                                         }
1765                                 }
1766                         }
1767                 }
1768  
1769                 res = ast_channel_make_compatible(chan, peer);
1770                 if (res < 0) {
1771                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1772                         ast_hangup(peer);
1773                         return -1;
1774                 }
1775                 /* This runs sorta backwards, since we give the incoming channel control, as if it
1776                    were the person called. */
1777                 if (option_verbose > 2) 
1778                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1779
1780                 memset(&config, 0, sizeof(struct ast_bridge_config));
1781                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1782                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1783                 config.timelimit = 0;
1784                 config.play_warning = 0;
1785                 config.warning_freq = 0;
1786                 config.warning_sound=NULL;
1787                 res = ast_bridge_call(chan, peer, &config);
1788
1789                 /* Simulate the PBX hanging up */
1790                 if (res != AST_PBX_NO_HANGUP_PEER)
1791                         ast_hangup(peer);
1792                 return res;
1793         } else {
1794                 /* XXX Play a message XXX */
1795                 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
1796                 if (!dres)
1797                         dres = ast_waitstream(chan, "");
1798                 else {
1799                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1800                         dres = 0;
1801                 }
1802                 if (option_verbose > 2) 
1803                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1804                 res = -1;
1805         }
1806         LOCAL_USER_REMOVE(u);
1807         return res;
1808 }
1809
1810 static int handle_showfeatures(int fd, int argc, char *argv[])
1811 {
1812         int i;
1813         int fcount;
1814         struct ast_call_feature *feature;
1815         char format[] = "%-25s %-7s %-7s\n";
1816
1817         ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1818         ast_cli(fd, format, "---------------", "-------", "-------");
1819
1820         ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
1821
1822         fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1823
1824         for (i = 0; i < fcount; i++)
1825         {
1826                 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1827         }
1828         ast_cli(fd, "\n");
1829         ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1830         ast_cli(fd, format, "---------------", "-------", "-------");
1831         if (AST_LIST_EMPTY(&feature_list)) {
1832                 ast_cli(fd, "(none)\n");
1833         }
1834         else {
1835                 AST_LIST_LOCK(&feature_list);
1836                 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1837                         ast_cli(fd, format, feature->sname, "no def", feature->exten);  
1838                 }
1839                 AST_LIST_UNLOCK(&feature_list);
1840         }
1841         ast_cli(fd, "\nCall parking\n");
1842         ast_cli(fd, "------------\n");
1843         ast_cli(fd,"%-20s:      %s\n", "Parking extension", parking_ext);
1844         ast_cli(fd,"%-20s:      %s\n", "Parking context", parking_con);
1845         ast_cli(fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1846         ast_cli(fd,"\n");
1847         
1848         return RESULT_SUCCESS;
1849 }
1850
1851 static char showfeatures_help[] =
1852 "Usage: show features\n"
1853 "       Lists currently configured features.\n";
1854
1855 static struct ast_cli_entry showfeatures =
1856 { { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
1857
1858 static int handle_parkedcalls(int fd, int argc, char *argv[])
1859 {
1860         struct parkeduser *cur;
1861         int numparked = 0;
1862
1863         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1864                 , "Context", "Extension", "Pri", "Timeout");
1865
1866         ast_mutex_lock(&parking_lock);
1867
1868         cur = parkinglot;
1869         while(cur) {
1870                 ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
1871                         ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
1872                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1873
1874                 cur = cur->next;
1875                 numparked++;
1876         }
1877         ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
1878
1879         ast_mutex_unlock(&parking_lock);
1880
1881         return RESULT_SUCCESS;
1882 }
1883
1884 static char showparked_help[] =
1885 "Usage: show parkedcalls\n"
1886 "       Lists currently parked calls.\n";
1887
1888 static struct ast_cli_entry showparked =
1889 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1890
1891 /* Dump lot status */
1892 static int manager_parking_status( struct mansession *s, struct message *m )
1893 {
1894         struct parkeduser *cur;
1895         char *id = astman_get_header(m,"ActionID");
1896         char idText[256] = "";
1897
1898         if (!ast_strlen_zero(id))
1899                 snprintf(idText,256,"ActionID: %s\r\n",id);
1900
1901         astman_send_ack(s, m, "Parked calls will follow");
1902
1903         ast_mutex_lock(&parking_lock);
1904
1905         cur=parkinglot;
1906         while(cur) {
1907                         ast_cli(s->fd, "Event: ParkedCall\r\n"
1908                         "Exten: %d\r\n"
1909                         "Channel: %s\r\n"
1910                         "From: %s\r\n"
1911                         "Timeout: %ld\r\n"
1912                         "CallerID: %s\r\n"
1913                         "CallerIDName: %s\r\n"
1914                         "%s"
1915                         "\r\n"
1916                         ,cur->parkingnum, cur->chan->name, cur->peername
1917                         ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
1918                         ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
1919                         ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
1920                         ,idText);
1921
1922             cur = cur->next;
1923         }
1924
1925         ast_cli(s->fd,
1926         "Event: ParkedCallsComplete\r\n"
1927         "%s"
1928         "\r\n",idText);
1929
1930         ast_mutex_unlock(&parking_lock);
1931
1932         return RESULT_SUCCESS;
1933 }
1934
1935
1936 int ast_pickup_call(struct ast_channel *chan)
1937 {
1938         struct ast_channel *cur = NULL;
1939         int res = -1;
1940
1941         while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
1942                 if (!cur->pbx && 
1943                         (cur != chan) &&
1944                         (chan->pickupgroup & cur->callgroup) &&
1945                         ((cur->_state == AST_STATE_RINGING) ||
1946                          (cur->_state == AST_STATE_RING))) {
1947                                 break;
1948                 }
1949                 ast_mutex_unlock(&cur->lock);
1950         }
1951         if (cur) {
1952                 if (option_debug)
1953                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
1954                 res = ast_answer(chan);
1955                 if (res)
1956                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
1957                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
1958                 if (res)
1959                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
1960                 res = ast_channel_masquerade(cur, chan);
1961                 if (res)
1962                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
1963                 ast_mutex_unlock(&cur->lock);
1964         } else  {
1965                 if (option_debug)
1966                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
1967         }
1968         return res;
1969 }
1970
1971 static int load_config(void) 
1972 {
1973         int start = 0, end = 0;
1974         struct ast_context *con = NULL;
1975         struct ast_config *cfg = NULL;
1976         struct ast_variable *var = NULL;
1977         char old_parking_ext[AST_MAX_EXTENSION];
1978         char old_parking_con[AST_MAX_EXTENSION] = "";
1979
1980         if (!ast_strlen_zero(parking_con)) {
1981                 strcpy(old_parking_ext, parking_ext);
1982                 strcpy(old_parking_con, parking_con);
1983         } 
1984
1985         /* Reset to defaults */
1986         strcpy(parking_con, "parkedcalls");
1987         strcpy(parking_con_dial, "park-dial");
1988         strcpy(parking_ext, "700");
1989         strcpy(pickup_ext, "*8");
1990         courtesytone[0] = '\0';
1991         strcpy(xfersound, "beep");
1992         strcpy(xferfailsound, "pbx-invalid");
1993         parking_start = 701;
1994         parking_stop = 750;
1995         parkfindnext = 0;
1996
1997         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1998         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1999
2000         cfg = ast_config_load("features.conf");
2001         if (!cfg) {
2002                 cfg = ast_config_load("parking.conf");
2003                 if (cfg)
2004                         ast_log(LOG_NOTICE, "parking.conf is deprecated in favor of 'features.conf'.  Please rename it.\n");
2005         }
2006         if (cfg) {
2007                 var = ast_variable_browse(cfg, "general");
2008                 while(var) {
2009                         if (!strcasecmp(var->name, "parkext")) {
2010                                 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2011                         } else if (!strcasecmp(var->name, "context")) {
2012                                 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2013                         } else if (!strcasecmp(var->name, "parkingtime")) {
2014                                 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2015                                         ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2016                                         parkingtime = DEFAULT_PARK_TIME;
2017                                 } else
2018                                         parkingtime = parkingtime * 1000;
2019                         } else if (!strcasecmp(var->name, "parkpos")) {
2020                                 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2021                                         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);
2022                                 } else {
2023                                         parking_start = start;
2024                                         parking_stop = end;
2025                                 }
2026                         } else if (!strcasecmp(var->name, "findslot")) {
2027                                 parkfindnext = (!strcasecmp(var->value, "next"));
2028                         } else if (!strcasecmp(var->name, "adsipark")) {
2029                                 adsipark = ast_true(var->value);
2030                         } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2031                                 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2032                                         ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2033                                         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2034                                 } else
2035                                         transferdigittimeout = transferdigittimeout * 1000;
2036                         } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2037                                 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2038                                         ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2039                                         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2040                                 }
2041                         } else if (!strcasecmp(var->name, "courtesytone")) {
2042                                 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2043                         }  else if (!strcasecmp(var->name, "parkedplay")) {
2044                                 if (!strcasecmp(var->value, "both"))
2045                                         parkedplay = 2;
2046                                 else if (!strcasecmp(var->value, "parked"))
2047                                         parkedplay = 1;
2048                                 else
2049                                         parkedplay = 0;
2050                         } else if (!strcasecmp(var->name, "xfersound")) {
2051                                 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2052                         } else if (!strcasecmp(var->name, "xferfailsound")) {
2053                                 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2054                         } else if (!strcasecmp(var->name, "pickupexten")) {
2055                                 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2056                         }
2057                         var = var->next;
2058                 }
2059
2060                 unmap_features();
2061                 var = ast_variable_browse(cfg, "featuremap");
2062                 while(var) {
2063                         if (remap_feature(var->name, var->value))
2064                                 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2065                         var = var->next;
2066                 }
2067
2068                 /* Map a key combination to an application*/
2069                 ast_unregister_features();
2070                 var = ast_variable_browse(cfg, "applicationmap");
2071                 while(var) {
2072                         char *tmp_val=strdup(var->value);
2073                         char *exten, *party=NULL, *app=NULL, *app_args=NULL; 
2074
2075                         if (!tmp_val) { 
2076                                 ast_log(LOG_ERROR, "res_features: strdup failed");
2077                                 continue;
2078                         }
2079                         
2080
2081                         exten=strsep(&tmp_val,",");
2082                         if (exten) party=strsep(&tmp_val,",");
2083                         if (party) app=strsep(&tmp_val,",");
2084
2085                         if (app) app_args=strsep(&tmp_val,",");
2086
2087                         if (!(app && strlen(app)) || !(exten && strlen(exten)) || !(party && strlen(party)) || !(var->name && strlen(var->name))) {
2088                                 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",app,exten,party,var->name);
2089                                 free(tmp_val);
2090                                 var = var->next;
2091                                 continue;
2092                         }
2093
2094                         {
2095                                 struct ast_call_feature *feature=find_feature(var->name);
2096                                 int mallocd=0;
2097                                 
2098                                 if (!feature) {
2099                                         feature=malloc(sizeof(struct ast_call_feature));
2100                                         mallocd=1;
2101                                 }
2102                                 if (!feature) {
2103                                         ast_log(LOG_NOTICE, "Malloc failed at feature mapping\n");
2104                                         free(tmp_val);
2105                                         var = var->next;
2106                                         continue;
2107                                 }
2108
2109                                 memset(feature,0,sizeof(struct ast_call_feature));
2110                                 ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
2111                                 ast_copy_string(feature->app,app,FEATURE_APP_LEN);
2112                                 ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
2113                                 free(tmp_val);
2114                                 
2115                                 if (app_args) 
2116                                         ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
2117                                 
2118                                 ast_copy_string(feature->exten, exten,sizeof(feature->exten));
2119                                 feature->operation=feature_exec_app;
2120                                 ast_set_flag(feature,AST_FEATURE_FLAG_NEEDSDTMF);
2121                                 
2122                                 if (!strcasecmp(party,"caller"))
2123                                         ast_set_flag(feature,AST_FEATURE_FLAG_CALLER);
2124                                 else if (!strcasecmp(party, "callee"))
2125                                         ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
2126                                 else {
2127                                         ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
2128                                         var = var->next;
2129                                         continue;
2130                                 }
2131
2132                                 ast_register_feature(feature);
2133                                 
2134                                 if (option_verbose >=1) ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);  
2135                         }
2136                         var = var->next;
2137                 }        
2138         }
2139         ast_config_destroy(cfg);
2140
2141         /* Remove the old parking extension */
2142         if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))     {
2143                 ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
2144                 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2145         }
2146         
2147         if (!(con = ast_context_find(parking_con))) {
2148                 if (!(con = ast_context_create(NULL, parking_con, registrar))) {
2149                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2150                         return -1;
2151                 }
2152         }
2153         return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
2154 }
2155
2156 int reload(void) {
2157         return load_config();
2158 }
2159
2160 int load_module(void)
2161 {
2162         int res;
2163         
2164         AST_LIST_HEAD_INIT(&feature_list);
2165         memset(parking_ext, 0, sizeof(parking_ext));
2166         memset(parking_con, 0, sizeof(parking_con));
2167
2168         if ((res = load_config()))
2169                 return res;
2170         ast_cli_register(&showparked);
2171         ast_cli_register(&showfeatures);
2172         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2173         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2174         if (!res)
2175                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2176         if (!res) {
2177                 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2178         }
2179         return res;
2180 }
2181
2182
2183 int unload_module(void)
2184 {
2185         STANDARD_HANGUP_LOCALUSERS;
2186
2187         ast_manager_unregister("ParkedCalls");
2188         ast_cli_unregister(&showfeatures);
2189         ast_cli_unregister(&showparked);
2190         ast_unregister_application(parkcall);
2191         return ast_unregister_application(parkedcall);
2192 }
2193
2194 char *description(void)
2195 {
2196         return "Call Features Resource";
2197 }
2198
2199 int usecount(void)
2200 {
2201         /* Never allow parking to be unloaded because it will
2202            unresolve needed symbols in the dialer */
2203 #if 0
2204         int res;
2205         STANDARD_USECOUNT(res);
2206         return res;
2207 #else
2208         return 1;
2209 #endif
2210 }
2211
2212 char *key()
2213 {
2214         return ASTERISK_GPL_KEY;
2215 }