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