Add parkedcalltransfers option for res_features. This basically enables/disables...
[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                 /* Simulate the PBX hanging up */
1839                 if (res != AST_PBX_NO_HANGUP_PEER)
1840                         ast_hangup(peer);
1841                 return res;
1842         } else {
1843                 /*! \todo XXX Play a message XXX */
1844                 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
1845                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1846                 if (option_verbose > 2) 
1847                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1848                 res = -1;
1849         }
1850
1851         ast_module_user_remove(u);
1852
1853         return res;
1854 }
1855
1856 static int handle_showfeatures(int fd, int argc, char *argv[])
1857 {
1858         int i;
1859         int fcount;
1860         struct ast_call_feature *feature;
1861         char format[] = "%-25s %-7s %-7s\n";
1862
1863         ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1864         ast_cli(fd, format, "---------------", "-------", "-------");
1865
1866         ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
1867
1868         fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1869
1870         for (i = 0; i < fcount; i++)
1871         {
1872                 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1873         }
1874         ast_cli(fd, "\n");
1875         ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1876         ast_cli(fd, format, "---------------", "-------", "-------");
1877         if (AST_LIST_EMPTY(&feature_list)) {
1878                 ast_cli(fd, "(none)\n");
1879         }
1880         else {
1881                 AST_LIST_LOCK(&feature_list);
1882                 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1883                         ast_cli(fd, format, feature->sname, "no def", feature->exten);  
1884                 }
1885                 AST_LIST_UNLOCK(&feature_list);
1886         }
1887         ast_cli(fd, "\nCall parking\n");
1888         ast_cli(fd, "------------\n");
1889         ast_cli(fd,"%-20s:      %s\n", "Parking extension", parking_ext);
1890         ast_cli(fd,"%-20s:      %s\n", "Parking context", parking_con);
1891         ast_cli(fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1892         ast_cli(fd,"\n");
1893         
1894         return RESULT_SUCCESS;
1895 }
1896
1897 static char showfeatures_help[] =
1898 "Usage: feature list\n"
1899 "       Lists currently configured features.\n";
1900
1901 static int handle_parkedcalls(int fd, int argc, char *argv[])
1902 {
1903         struct parkeduser *cur;
1904         int numparked = 0;
1905
1906         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1907                 , "Context", "Extension", "Pri", "Timeout");
1908
1909         ast_mutex_lock(&parking_lock);
1910
1911         for (cur = parkinglot; cur; cur = cur->next) {
1912                 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
1913                         ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
1914                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1915
1916                 numparked++;
1917         }
1918         ast_mutex_unlock(&parking_lock);
1919         ast_cli(fd, "%d parked call%s.\n", numparked, ESS(numparked));
1920
1921
1922         return RESULT_SUCCESS;
1923 }
1924
1925 static char showparked_help[] =
1926 "Usage: show parkedcalls\n"
1927 "       Lists currently parked calls.\n";
1928
1929 static struct ast_cli_entry cli_features[] = {
1930         { { "feature", "show", NULL },
1931         handle_showfeatures, "Lists configured features",
1932         showfeatures_help },
1933
1934         { { "show", "parkedcalls", NULL },
1935         handle_parkedcalls, "Lists parked calls",
1936         showparked_help },
1937 };
1938
1939 /*! \brief Dump lot status */
1940 static int manager_parking_status( struct mansession *s, const struct message *m)
1941 {
1942         struct parkeduser *cur;
1943         const char *id = astman_get_header(m,"ActionID");
1944         char idText[256] = "";
1945
1946         if (!ast_strlen_zero(id))
1947                 snprintf(idText, 256, "ActionID: %s\r\n", id);
1948
1949         astman_send_ack(s, m, "Parked calls will follow");
1950
1951         ast_mutex_lock(&parking_lock);
1952
1953         for (cur=parkinglot; cur; cur = cur->next) {
1954                 astman_append(s, "Event: ParkedCall\r\n"
1955                         "Exten: %d\r\n"
1956                         "Channel: %s\r\n"
1957                         "From: %s\r\n"
1958                         "Timeout: %ld\r\n"
1959                         "CallerIDNum: %s\r\n"
1960                         "CallerIDName: %s\r\n"
1961                         "%s"
1962                         "\r\n",
1963                         cur->parkingnum, cur->chan->name, cur->peername,
1964                         (long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL),
1965                         S_OR(cur->chan->cid.cid_num, ""),       /* XXX in other places it is <unknown> */
1966                         S_OR(cur->chan->cid.cid_name, ""),
1967                         idText);
1968         }
1969
1970         astman_append(s,
1971                 "Event: ParkedCallsComplete\r\n"
1972                 "%s"
1973                 "\r\n",idText);
1974
1975         ast_mutex_unlock(&parking_lock);
1976
1977         return RESULT_SUCCESS;
1978 }
1979
1980 static char mandescr_park[] =
1981 "Description: Park a channel.\n"
1982 "Variables: (Names marked with * are required)\n"
1983 "       *Channel: Channel name to park\n"
1984 "       *Channel2: Channel to announce park info to (and return to if timeout)\n"
1985 "       Timeout: Number of milliseconds to wait before callback.\n";  
1986
1987 static int manager_park(struct mansession *s, const struct message *m)
1988 {
1989         const char *channel = astman_get_header(m, "Channel");
1990         const char *channel2 = astman_get_header(m, "Channel2");
1991         const char *timeout = astman_get_header(m, "Timeout");
1992         char buf[BUFSIZ];
1993         int to = 0;
1994         int res = 0;
1995         int parkExt = 0;
1996         struct ast_channel *ch1, *ch2;
1997
1998         if (ast_strlen_zero(channel)) {
1999                 astman_send_error(s, m, "Channel not specified");
2000                 return 0;
2001         }
2002
2003         if (ast_strlen_zero(channel2)) {
2004                 astman_send_error(s, m, "Channel2 not specified");
2005                 return 0;
2006         }
2007
2008         ch1 = ast_get_channel_by_name_locked(channel);
2009         if (!ch1) {
2010                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2011                 astman_send_error(s, m, buf);
2012                 return 0;
2013         }
2014
2015         ch2 = ast_get_channel_by_name_locked(channel2);
2016         if (!ch2) {
2017                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2018                 astman_send_error(s, m, buf);
2019                 ast_channel_unlock(ch1);
2020                 return 0;
2021         }
2022
2023         if (!ast_strlen_zero(timeout)) {
2024                 sscanf(timeout, "%d", &to);
2025         }
2026
2027         res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2028         if (!res) {
2029                 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2030                 astman_send_ack(s, m, "Park successful");
2031         } else {
2032                 astman_send_error(s, m, "Park failure");
2033         }
2034
2035         ast_channel_unlock(ch1);
2036         ast_channel_unlock(ch2);
2037
2038         return 0;
2039 }
2040
2041
2042 int ast_pickup_call(struct ast_channel *chan)
2043 {
2044         struct ast_channel *cur = NULL;
2045         int res = -1;
2046
2047         while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
2048                 if (!cur->pbx && 
2049                         (cur != chan) &&
2050                         (chan->pickupgroup & cur->callgroup) &&
2051                         ((cur->_state == AST_STATE_RINGING) ||
2052                          (cur->_state == AST_STATE_RING))) {
2053                                 break;
2054                 }
2055                 ast_channel_unlock(cur);
2056         }
2057         if (cur) {
2058                 if (option_debug)
2059                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2060                 res = ast_answer(chan);
2061                 if (res)
2062                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2063                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2064                 if (res)
2065                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2066                 res = ast_channel_masquerade(cur, chan);
2067                 if (res)
2068                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
2069                 ast_channel_unlock(cur);
2070         } else  {
2071                 if (option_debug)
2072                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
2073         }
2074         return res;
2075 }
2076
2077 /*! \brief Add parking hints for all defined parking lots */
2078 static void park_add_hints(char *context, int start, int stop)
2079 {
2080         int numext;
2081         char device[AST_MAX_EXTENSION];
2082         char exten[10];
2083
2084         for (numext = start; numext <= stop; numext++) {
2085                 snprintf(exten, sizeof(exten), "%d", numext);
2086                 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2087                 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2088         }
2089 }
2090
2091
2092 static int load_config(void) 
2093 {
2094         int start = 0, end = 0;
2095         int res;
2096         struct ast_context *con = NULL;
2097         struct ast_config *cfg = NULL;
2098         struct ast_variable *var = NULL;
2099         char old_parking_ext[AST_MAX_EXTENSION];
2100         char old_parking_con[AST_MAX_EXTENSION] = "";
2101
2102         if (!ast_strlen_zero(parking_con)) {
2103                 strcpy(old_parking_ext, parking_ext);
2104                 strcpy(old_parking_con, parking_con);
2105         } 
2106
2107         /* Reset to defaults */
2108         strcpy(parking_con, "parkedcalls");
2109         strcpy(parking_con_dial, "park-dial");
2110         strcpy(parking_ext, "700");
2111         strcpy(pickup_ext, "*8");
2112         strcpy(parkmohclass, "default");
2113         courtesytone[0] = '\0';
2114         strcpy(xfersound, "beep");
2115         strcpy(xferfailsound, "pbx-invalid");
2116         parking_start = 701;
2117         parking_stop = 750;
2118         parkfindnext = 0;
2119         adsipark = 0;
2120         comebacktoorigin = 1;
2121         parkaddhints = 0;
2122         parkedcalltransfers = 0;
2123
2124         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2125         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2126         atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2127
2128         cfg = ast_config_load("features.conf");
2129         if (!cfg) {
2130                 ast_log(LOG_WARNING,"Could not load features.conf\n");
2131                 return AST_MODULE_LOAD_DECLINE;
2132         }
2133         for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2134                 if (!strcasecmp(var->name, "parkext")) {
2135                         ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2136                 } else if (!strcasecmp(var->name, "context")) {
2137                         ast_copy_string(parking_con, var->value, sizeof(parking_con));
2138                 } else if (!strcasecmp(var->name, "parkingtime")) {
2139                         if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2140                                 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2141                                 parkingtime = DEFAULT_PARK_TIME;
2142                         } else
2143                                 parkingtime = parkingtime * 1000;
2144                 } else if (!strcasecmp(var->name, "parkpos")) {
2145                         if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2146                                 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);
2147                         } else {
2148                                 parking_start = start;
2149                                 parking_stop = end;
2150                         }
2151                 } else if (!strcasecmp(var->name, "findslot")) {
2152                         parkfindnext = (!strcasecmp(var->value, "next"));
2153                 } else if (!strcasecmp(var->name, "parkinghints")) {
2154                         parkaddhints = ast_true(var->value);
2155                 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2156                         parkedcalltransfers = ast_true(var->value);
2157                 } else if (!strcasecmp(var->name, "adsipark")) {
2158                         adsipark = ast_true(var->value);
2159                 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2160                         if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2161                                 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2162                                 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2163                         } else
2164                                 transferdigittimeout = transferdigittimeout * 1000;
2165                 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2166                         if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2167                                 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2168                                 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2169                         }
2170                 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2171                         if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2172                                 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2173                                 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2174                         } else
2175                                 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2176                 } else if (!strcasecmp(var->name, "courtesytone")) {
2177                         ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2178                 }  else if (!strcasecmp(var->name, "parkedplay")) {
2179                         if (!strcasecmp(var->value, "both"))
2180                                 parkedplay = 2;
2181                         else if (!strcasecmp(var->value, "parked"))
2182                                 parkedplay = 1;
2183                         else
2184                                 parkedplay = 0;
2185                 } else if (!strcasecmp(var->name, "xfersound")) {
2186                         ast_copy_string(xfersound, var->value, sizeof(xfersound));
2187                 } else if (!strcasecmp(var->name, "xferfailsound")) {
2188                         ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2189                 } else if (!strcasecmp(var->name, "pickupexten")) {
2190                         ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2191                 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2192                         comebacktoorigin = ast_true(var->value);
2193                 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2194                         ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2195                 }
2196         }
2197
2198         unmap_features();
2199         for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2200                 if (remap_feature(var->name, var->value))
2201                         ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2202         }
2203
2204         /* Map a key combination to an application*/
2205         ast_unregister_features();
2206         for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2207                 char *tmp_val = ast_strdupa(var->value);
2208                 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class; 
2209                 struct ast_call_feature *feature;
2210
2211                 /* strsep() sets the argument to NULL if match not found, and it
2212                  * is safe to use it with a NULL argument, so we don't check
2213                  * between calls.
2214                  */
2215                 exten = strsep(&tmp_val,",");
2216                 activatedby = strsep(&tmp_val,",");
2217                 app = strsep(&tmp_val,",");
2218                 app_args = strsep(&tmp_val,",");
2219                 moh_class = strsep(&tmp_val,",");
2220
2221                 activateon = strsep(&activatedby, "/"); 
2222
2223                 /*! \todo XXX var_name or app_args ? */
2224                 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2225                         ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2226                                 app, exten, activateon, var->name);
2227                         continue;
2228                 }
2229
2230                 if ((feature = find_feature(var->name))) {
2231                         ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2232                         continue;
2233                 }
2234                                 
2235                 if (!(feature = ast_calloc(1, sizeof(*feature))))
2236                         continue;                                       
2237
2238                 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2239                 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2240                 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2241                 
2242                 if (app_args) 
2243                         ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2244
2245                 if (moh_class)
2246                         ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2247                         
2248                 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2249                 feature->operation = feature_exec_app;
2250                 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2251
2252                 /* Allow caller and calle to be specified for backwards compatability */
2253                 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2254                         ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2255                 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2256                         ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2257                 else {
2258                         ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2259                                 " must be 'self', or 'peer'\n", var->name);
2260                         continue;
2261                 }
2262
2263                 if (ast_strlen_zero(activatedby))
2264                         ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2265                 else if (!strcasecmp(activatedby, "caller"))
2266                         ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2267                 else if (!strcasecmp(activatedby, "callee"))
2268                         ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2269                 else if (!strcasecmp(activatedby, "both"))
2270                         ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2271                 else {
2272                         ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2273                                 " must be 'caller', or 'callee', or 'both'\n", var->name);
2274                         continue;
2275                 }
2276
2277                 ast_register_feature(feature);
2278                         
2279                 if (option_verbose >= 1)
2280                         ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);  
2281         }        
2282         ast_config_destroy(cfg);
2283
2284         /* Remove the old parking extension */
2285         if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))     {
2286                 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2287                                 notify_metermaids(old_parking_ext, old_parking_con);
2288                 if (option_debug)
2289                         ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2290         }
2291         
2292         if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2293                 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2294                 return -1;
2295         }
2296         res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2297         if (parkaddhints)
2298                 park_add_hints(parking_con, parking_start, parking_stop);
2299         if (!res)
2300                 notify_metermaids(ast_parking_ext(), parking_con);
2301         return res;
2302
2303 }
2304
2305 static int reload(void)
2306 {
2307         return load_config();
2308 }
2309
2310 static int load_module(void)
2311 {
2312         int res;
2313         
2314         memset(parking_ext, 0, sizeof(parking_ext));
2315         memset(parking_con, 0, sizeof(parking_con));
2316
2317         if ((res = load_config()))
2318                 return res;
2319         ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2320         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2321         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2322         if (!res)
2323                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2324         if (!res) {
2325                 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2326                 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2327                         "Park a channel", mandescr_park); 
2328         }
2329
2330         res |= ast_devstate_prov_add("Park", metermaidstate);
2331
2332         return res;
2333 }
2334
2335
2336 static int unload_module(void)
2337 {
2338         ast_module_user_hangup_all();
2339
2340         ast_manager_unregister("ParkedCalls");
2341         ast_manager_unregister("Park");
2342         ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
2343         ast_unregister_application(parkcall);
2344         ast_devstate_prov_del("Park");
2345         return ast_unregister_application(parkedcall);
2346 }
2347
2348 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
2349                 .load = load_module,
2350                 .unload = unload_module,
2351                 .reload = reload,
2352                );