14550b80f3fe407f364f9f16c3ae4c809be9b9db
[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 <sys/time.h>
32 #include <sys/signal.h>
33 #include <netinet/in.h>
34
35 #include "asterisk/lock.h"
36 #include "asterisk/file.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/options.h"
40 #include "asterisk/causes.h"
41 #include "asterisk/module.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/app.h"
44 #include "asterisk/say.h"
45 #include "asterisk/features.h"
46 #include "asterisk/musiconhold.h"
47 #include "asterisk/config.h"
48 #include "asterisk/cli.h"
49 #include "asterisk/manager.h"
50 #include "asterisk/utils.h"
51 #include "asterisk/adsi.h"
52 #include "asterisk/devicestate.h"
53 #include "asterisk/monitor.h"
54
55 #define DEFAULT_PARK_TIME 45000
56 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
57 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
58 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
59 #define DEFAULT_ATXFER_DROP_CALL 0
60 #define DEFAULT_ATXFER_LOOP_DELAY 10000
61 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
62
63 #define AST_MAX_WATCHERS 256
64
65 enum {
66         AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
67         AST_FEATURE_FLAG_ONPEER =    (1 << 1),
68         AST_FEATURE_FLAG_ONSELF =    (1 << 2),
69         AST_FEATURE_FLAG_BYCALLEE =  (1 << 3),
70         AST_FEATURE_FLAG_BYCALLER =  (1 << 4),
71         AST_FEATURE_FLAG_BYBOTH  =   (3 << 3),
72 };
73
74 struct feature_group_exten {
75         AST_LIST_ENTRY(feature_group_exten) entry;
76         AST_DECLARE_STRING_FIELDS(
77                 AST_STRING_FIELD(exten);
78         );
79         struct ast_call_feature *feature;
80 };
81
82 struct feature_group {
83         AST_LIST_ENTRY(feature_group) entry;
84         AST_DECLARE_STRING_FIELDS(
85                 AST_STRING_FIELD(gname);
86         );
87         AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
88 };
89
90 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
91
92 static char *parkedcall = "ParkedCall";
93
94 static int parkaddhints = 0;                               /*!< Add parking hints automatically */
95 static int parkedcalltransfers = 0;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
96 static int parkedcallreparking = 0;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
97 static int parkingtime = DEFAULT_PARK_TIME;                /*!< No more than 45 seconds parked before you do something with them */
98 static char parking_con[AST_MAX_EXTENSION];                /*!< Context for which parking is made accessible */
99 static char parking_con_dial[AST_MAX_EXTENSION];           /*!< Context for dialback for parking (KLUDGE) */
100 static char parking_ext[AST_MAX_EXTENSION];                /*!< Extension you type to park the call */
101 static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
102 static char parkmohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
103 static int parking_start;                                  /*!< First available extension for parking */
104 static int parking_stop;                                   /*!< Last available extension for parking */
105
106 static char courtesytone[256];                             /*!< Courtesy tone */
107 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
108 static char xfersound[256];                                /*!< Call transfer sound */
109 static char xferfailsound[256];                            /*!< Call transfer failure sound */
110
111 static int parking_offset;
112 static int parkfindnext;
113
114 static int adsipark;
115
116 static int transferdigittimeout;
117 static int featuredigittimeout;
118 static int comebacktoorigin = 1;
119
120 static int atxfernoanswertimeout;
121 static unsigned int atxferdropcall;
122 static unsigned int atxferloopdelay;
123 static unsigned int atxfercallbackretries;
124
125 static char *registrar = "res_features";                   /*!< Registrar for operations */
126
127 /* module and CLI command definitions */
128 static char *synopsis = "Answer a parked call";
129
130 static char *descrip = "ParkedCall(exten): "
131 "Used to connect to a parked call.  This application is always\n"
132 "registered internally and does not need to be explicitly added\n"
133 "into the dialplan, although you should include the 'parkedcalls'\n"
134 "context.  If no extension is provided, then the first available\n"
135 "parked call will be acquired.\n";
136
137 static char *parkcall = "Park";
138
139 static char *synopsis2 = "Park yourself";
140
141 static char *descrip2 = "Park(): "
142 "Used to park yourself (typically in combination with a supervised\n"
143 "transfer to know the parking space). This application is always\n"
144 "registered internally and does not need to be explicitly added\n"
145 "into the dialplan, although you should include the 'parkedcalls'\n"
146 "context (or the context specified in features.conf).\n\n"
147 "If you set the PARKINGEXTEN variable to an extension in your\n"
148 "parking context, Park() will park the call on that extension, unless\n"
149 "it already exists. In that case, execution will continue at next\n"
150 "priority.\n" ;
151
152 static struct ast_app *monitor_app = NULL;
153 static int monitor_ok = 1;
154
155 struct parkeduser {
156         struct ast_channel *chan;                   /*!< Parking channel */
157         struct timeval start;                       /*!< Time the parking started */
158         int parkingnum;                             /*!< Parking lot */
159         char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
160         char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
161         char exten[AST_MAX_EXTENSION];
162         int priority;
163         int parkingtime;                            /*!< Maximum length in parking lot before return */
164         int notquiteyet;
165         char peername[1024];
166         unsigned char moh_trys;
167         AST_LIST_ENTRY(parkeduser) list;
168 };
169
170 static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
171
172 static pthread_t parking_thread;
173
174 const char *ast_parking_ext(void)
175 {
176         return parking_ext;
177 }
178
179 const char *ast_pickup_ext(void)
180 {
181         return pickup_ext;
182 }
183
184 struct ast_bridge_thread_obj 
185 {
186         struct ast_bridge_config bconfig;
187         struct ast_channel *chan;
188         struct ast_channel *peer;
189         unsigned int return_to_pbx:1;
190 };
191
192
193
194 /*!
195  * \brief store context, extension and priority 
196  * \param chan, context, ext, pri
197 */
198 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
199 {
200         ast_copy_string(chan->context, context, sizeof(chan->context));
201         ast_copy_string(chan->exten, ext, sizeof(chan->exten));
202         chan->priority = pri;
203 }
204
205 /*!
206  * \brief Check goto on transfer
207  * \param chan
208  *
209  * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
210  * When found make sure the types are compatible. Check if channel is valid
211  * if so start the new channel else hangup the call. 
212 */
213 static void check_goto_on_transfer(struct ast_channel *chan) 
214 {
215         struct ast_channel *xferchan;
216         const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
217         char *x, *goto_on_transfer;
218         struct ast_frame *f;
219
220         if (ast_strlen_zero(val))
221                 return;
222
223         goto_on_transfer = ast_strdupa(val);
224
225         if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
226                 return;
227
228         for (x = goto_on_transfer; x && *x; x++) {
229                 if (*x == '^')
230                         *x = '|';
231         }
232         /* Make formats okay */
233         xferchan->readformat = chan->readformat;
234         xferchan->writeformat = chan->writeformat;
235         ast_channel_masquerade(xferchan, chan);
236         ast_parseable_goto(xferchan, goto_on_transfer);
237         xferchan->_state = AST_STATE_UP;
238         ast_clear_flag(xferchan, AST_FLAGS_ALL);        
239         xferchan->_softhangup = 0;
240         if ((f = ast_read(xferchan))) {
241                 ast_frfree(f);
242                 f = NULL;
243                 ast_pbx_start(xferchan);
244         } else {
245                 ast_hangup(xferchan);
246         }
247 }
248
249 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate);
250
251 /*!
252  * \brief bridge the call 
253  * \param data thread bridge.
254  *
255  * Set Last Data for respective channels, reset cdr for channels
256  * bridge call, check if we're going back to dialplan
257  * if not hangup both legs of the call
258 */
259 static void *ast_bridge_call_thread(void *data) 
260 {
261         struct ast_bridge_thread_obj *tobj = data;
262         int res;
263
264         tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
265         tobj->chan->data = tobj->peer->name;
266         tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
267         tobj->peer->data = tobj->chan->name;
268
269         if (tobj->chan->cdr) {
270                 ast_cdr_reset(tobj->chan->cdr, NULL);
271                 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
272         }
273         if (tobj->peer->cdr) {
274                 ast_cdr_reset(tobj->peer->cdr, NULL);
275                 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
276         }
277
278         ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
279
280         if (tobj->return_to_pbx) {
281                 if (!ast_check_hangup(tobj->peer)) {
282                         ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
283                         res = ast_pbx_start(tobj->peer);
284                         if (res != AST_PBX_SUCCESS)
285                                 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
286                 } else
287                         ast_hangup(tobj->peer);
288                 if (!ast_check_hangup(tobj->chan)) {
289                         ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
290                         res = ast_pbx_start(tobj->chan);
291                         if (res != AST_PBX_SUCCESS)
292                                 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
293                 } else
294                         ast_hangup(tobj->chan);
295         } else {
296                 ast_hangup(tobj->chan);
297                 ast_hangup(tobj->peer);
298         }
299
300         ast_free(tobj);
301
302         return NULL;
303 }
304
305 /*!
306  * \brief create thread for the parked call
307  * \param data
308  *
309  * Create thread and attributes, call ast_bridge_call_thread
310 */
311 static void ast_bridge_call_thread_launch(void *data) 
312 {
313         pthread_t thread;
314         pthread_attr_t attr;
315         struct sched_param sched;
316
317         pthread_attr_init(&attr);
318         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
319         ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
320         pthread_attr_destroy(&attr);
321         memset(&sched, 0, sizeof(sched));
322         pthread_setschedparam(thread, SCHED_RR, &sched);
323 }
324
325 /*!
326  * \brief Announce call parking by ADSI
327  * \param chan .
328  * \param parkingexten .
329  * Create message to show for ADSI, display message.
330  * \retval 0 on success.
331  * \retval -1 on failure.
332 */
333 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
334 {
335         int res;
336         int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
337         char tmp[256];
338         char *message[5] = {NULL, NULL, NULL, NULL, NULL};
339
340         snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
341         message[0] = tmp;
342         res = ast_adsi_load_session(chan, NULL, 0, 1);
343         if (res == -1)
344                 return res;
345         return ast_adsi_print(chan, message, justify, 1);
346 }
347
348 /*! \brief Notify metermaids that we've changed an extension */
349 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
350 {
351         ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'", 
352                 exten, context, devstate2str(state));
353
354         ast_devstate_changed(state, "park:%s@%s", exten, context);
355 }
356
357 /*! \brief metermaids callback from devicestate.c */
358 static enum ast_device_state metermaidstate(const char *data)
359 {
360         char *context;
361         char *exten;
362
363         context = ast_strdupa(data);
364
365         exten = strsep(&context, "@");
366         if (!context)
367                 return AST_DEVICE_INVALID;
368         
369         ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
370
371         if (!ast_exists_extension(NULL, context, exten, 1, NULL))
372                 return AST_DEVICE_NOT_INUSE;
373
374         return AST_DEVICE_INUSE;
375 }
376
377 /* Park a call */
378 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
379 {
380         struct parkeduser *pu, *cur;
381         int i, x = -1, parking_range;
382         struct ast_context *con;
383         const char *parkingexten;
384         
385         /* Allocate memory for parking data */
386         if (!(pu = ast_calloc(1, sizeof(*pu)))) 
387                 return -1;
388
389         /* Lock parking lot */
390         AST_LIST_LOCK(&parkinglot);
391         /* Check for channel variable PARKINGEXTEN */
392         parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
393         if (!ast_strlen_zero(parkingexten)) {
394                 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
395                         AST_LIST_UNLOCK(&parkinglot);
396                         ast_free(pu);
397                         ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
398                         return 0;       /* Continue execution if possible */
399                 }
400                 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
401                 x = atoi(parkingexten);
402         } else {
403                 /* Select parking space within range */
404                 parking_range = parking_stop - parking_start+1;
405                 for (i = 0; i < parking_range; i++) {
406                         x = (i + parking_offset) % parking_range + parking_start;
407                         AST_LIST_TRAVERSE(&parkinglot, cur, list) {
408                                 if (cur->parkingnum == x)
409                                         break;
410                         }
411                         if (!cur)
412                                 break;
413                 }
414
415                 if (!(i < parking_range)) {
416                         ast_log(LOG_WARNING, "No more parking spaces\n");
417                         ast_free(pu);
418                         AST_LIST_UNLOCK(&parkinglot);
419                         return -1;
420                 }
421                 /* Set pointer for next parking */
422                 if (parkfindnext) 
423                         parking_offset = x - parking_start + 1;
424         }
425         
426         chan->appl = "Parked Call";
427         chan->data = NULL; 
428
429         pu->chan = chan;
430         
431         /* Put the parked channel on hold if we have two different channels */
432         if (chan != peer) {
433                 ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
434                         S_OR(parkmohclass, NULL),
435                         !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
436         }
437         
438         pu->start = ast_tvnow();
439         pu->parkingnum = x;
440         pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
441         if (extout)
442                 *extout = x;
443
444         if (peer) 
445                 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
446
447         /* Remember what had been dialed, so that if the parking
448            expires, we try to come back to the same place */
449         ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
450         ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
451         pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
452         AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
453
454         /* If parking a channel directly, don't quiet yet get parking running on it */
455         if (peer == chan) 
456                 pu->notquiteyet = 1;
457         AST_LIST_UNLOCK(&parkinglot);
458         /* Wake up the (presumably select()ing) thread */
459         pthread_kill(parking_thread, SIGURG);
460         ast_verb(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));
461
462         if (pu->parkingnum != -1)
463                 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
464         manager_event(EVENT_FLAG_CALL, "ParkedCall",
465                 "Exten: %s\r\n"
466                 "Channel: %s\r\n"
467                 "From: %s\r\n"
468                 "Timeout: %ld\r\n"
469                 "CallerIDNum: %s\r\n"
470                 "CallerIDName: %s\r\n",
471                 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
472                 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
473                 S_OR(pu->chan->cid.cid_num, "<unknown>"),
474                 S_OR(pu->chan->cid.cid_name, "<unknown>")
475                 );
476
477         if (peer && adsipark && ast_adsi_available(peer)) {
478                 adsi_announce_park(peer, pu->parkingexten);     /* Only supports parking numbers */
479                 ast_adsi_unload_session(peer);
480         }
481
482         con = ast_context_find(parking_con);
483         if (!con) 
484                 con = ast_context_create(NULL, parking_con, registrar);
485         if (!con)       /* Still no context? Bad */
486                 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
487         /* Tell the peer channel the number of the parking space */
488         if (peer && pu->parkingnum != -1) { /* Only say number if it's a number */
489                 /* Make sure we don't start saying digits to the channel being parked */
490                 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
491                 ast_say_digits(peer, pu->parkingnum, "", peer->language);
492                 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
493         }
494         if (con) {
495                 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
496                         notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
497         }
498         if (pu->notquiteyet) {
499                 /* Wake up parking thread if we're really done */
500                 ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
501                         S_OR(parkmohclass, NULL),
502                         !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
503                 pu->notquiteyet = 0;
504                 pthread_kill(parking_thread, SIGURG);
505         }
506         return 0;
507 }
508
509 /* Park call via masquraded channel */
510 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
511 {
512         struct ast_channel *chan;
513         struct ast_frame *f;
514
515         /* Make a new, fake channel that we'll use to masquerade in the real one */
516         if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
517                 ast_log(LOG_WARNING, "Unable to create parked channel\n");
518                 return -1;
519         }
520
521         /* Make formats okay */
522         chan->readformat = rchan->readformat;
523         chan->writeformat = rchan->writeformat;
524         ast_channel_masquerade(chan, rchan);
525
526         /* Setup the extensions and such */
527         set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
528
529         /* Make the masq execute */
530         f = ast_read(chan);
531         if (f)
532                 ast_frfree(f);
533
534         ast_park_call(chan, peer, timeout, extout);
535         return 0;
536 }
537
538
539 #define FEATURE_RETURN_HANGUP           -1
540 #define FEATURE_RETURN_SUCCESSBREAK      0
541 #define FEATURE_RETURN_PBX_KEEPALIVE    AST_PBX_KEEPALIVE
542 #define FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER
543 #define FEATURE_RETURN_PASSDIGITS        21
544 #define FEATURE_RETURN_STOREDIGITS       22
545 #define FEATURE_RETURN_SUCCESS           23
546 #define FEATURE_RETURN_KEEPTRYING    24
547
548 #define FEATURE_SENSE_CHAN      (1 << 0)
549 #define FEATURE_SENSE_PEER      (1 << 1)
550
551 /*! 
552  * \brief set caller and callee according to the direction 
553  * \param caller, callee, peer, chan, sense
554  *
555  * Detect who triggered feature and set callee/caller variables accordingly
556 */
557 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
558         struct ast_channel *peer, struct ast_channel *chan, int sense)
559 {
560         if (sense == FEATURE_SENSE_PEER) {
561                 *caller = peer;
562                 *callee = chan;
563         } else {
564                 *callee = peer;
565                 *caller = chan;
566         }
567 }
568
569 /*! 
570  * \brief support routing for one touch call parking
571  * \param chan channel parking call
572  * \param peer channel to be parked
573  * \param config unsed
574  * \param code unused
575  * \param sense feature options
576  *
577  * \param data
578  * Setup channel, set return exten,priority to 's,1'
579  * answer chan, sleep chan, park call
580 */
581 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
582 {
583         struct ast_channel *parker;
584         struct ast_channel *parkee;
585         int res = 0;
586         struct ast_module_user *u;
587
588         u = ast_module_user_add(chan);
589
590         set_peers(&parker, &parkee, peer, chan, sense);
591         /* Setup the exten/priority to be s/1 since we don't know
592            where this call should return */
593         strcpy(chan->exten, "s");
594         chan->priority = 1;
595         if (chan->_state != AST_STATE_UP)
596                 res = ast_answer(chan);
597         if (!res)
598                 res = ast_safe_sleep(chan, 1000);
599         if (!res)
600                 res = ast_park_call(parkee, parker, 0, NULL);
601
602         ast_module_user_remove(u);
603
604         if (!res) {
605                 if (sense == FEATURE_SENSE_CHAN)
606                         res = AST_PBX_NO_HANGUP_PEER;
607                 else
608                         res = AST_PBX_KEEPALIVE;
609         }
610         return res;
611
612 }
613
614 /*!
615  * \brief Monitor a channel by DTMF
616  * \param chan channel requesting monitor
617  * \param peer channel to be monitored
618  * \param config
619  * \param code
620  * \param sense feature options
621  *
622  * \param data
623  * Check monitor app enabled, setup channels, both caller/callee chans not null
624  * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
625  * \retval FEATURE_RETURN_SUCCESS on success.
626  * \retval -1 on error.
627 */
628 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
629 {
630         char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
631         int x = 0;
632         size_t len;
633         struct ast_channel *caller_chan, *callee_chan;
634
635         if (!monitor_ok) {
636                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
637                 return -1;
638         }
639
640         if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
641                 monitor_ok = 0;
642                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
643                 return -1;
644         }
645
646         set_peers(&caller_chan, &callee_chan, peer, chan, sense);
647
648         if (!ast_strlen_zero(courtesytone)) {
649                 if (ast_autoservice_start(callee_chan))
650                         return -1;
651                 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
652                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
653                         ast_autoservice_stop(callee_chan);
654                         return -1;
655                 }
656                 if (ast_autoservice_stop(callee_chan))
657                         return -1;
658         }
659         
660         if (callee_chan->monitor) {
661                 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
662                 ast_monitor_stop(callee_chan, 1);
663                 return FEATURE_RETURN_SUCCESS;
664         }
665
666         if (caller_chan && callee_chan) {
667                 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
668                 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
669                 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
670
671                 if (!touch_format)
672                         touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
673
674                 if (!touch_monitor)
675                         touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
676         
677                 if (!touch_monitor_prefix)
678                         touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
679         
680                 if (touch_monitor) {
681                         len = strlen(touch_monitor) + 50;
682                         args = alloca(len);
683                         touch_filename = alloca(len);
684                         snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
685                         snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
686                 } else {
687                         caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
688                         callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
689                         len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
690                         args = alloca(len);
691                         touch_filename = alloca(len);
692                         snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
693                         snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
694                 }
695
696                 for(x = 0; x < strlen(args); x++) {
697                         if (args[x] == '/')
698                                 args[x] = '-';
699                 }
700                 
701                 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
702
703                 pbx_exec(callee_chan, monitor_app, args);
704                 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
705                 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
706         
707                 return FEATURE_RETURN_SUCCESS;
708         }
709         
710         ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");   
711         return -1;
712 }
713
714 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
715 {
716         ast_verb(4, "User hit '%s' to disconnect call.\n", code);
717         return FEATURE_RETURN_HANGUP;
718 }
719
720 static int finishup(struct ast_channel *chan)
721 {
722         ast_indicate(chan, AST_CONTROL_UNHOLD);
723   
724         return ast_autoservice_stop(chan);
725 }
726
727 /*!
728  * \brief Find the context for the transfer
729  * \param transferer
730  * \param transferee
731  * 
732  * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
733  * \return a context string
734 */
735 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
736 {
737         const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
738         if (ast_strlen_zero(s))
739                 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
740         if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
741                 s = transferer->macrocontext;
742         if (ast_strlen_zero(s))
743                 s = transferer->context;
744         return s;  
745 }
746
747 /*!
748  * \brief Blind transfer user to another extension
749  * \param chan channel to be transfered
750  * \param peer channel initiated blind transfer
751  * \param config
752  * \param code
753  * \param data
754  * \param sense  feature options
755  * 
756  * Place chan on hold, check if transferred to parkinglot extension,
757  * otherwise check extension exists and transfer caller.
758  * \retval FEATURE_RETURN_SUCCESS.
759  * \retval -1 on failure.
760 */
761 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
762 {
763         struct ast_channel *transferer;
764         struct ast_channel *transferee;
765         const char *transferer_real_context;
766         char xferto[256];
767         int res;
768
769         set_peers(&transferer, &transferee, peer, chan, sense);
770         transferer_real_context = real_ctx(transferer, transferee);
771         /* Start autoservice on chan while we talk to the originator */
772         ast_autoservice_start(transferee);
773         ast_indicate(transferee, AST_CONTROL_HOLD);
774
775         memset(xferto, 0, sizeof(xferto));
776         
777         /* Transfer */
778         res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
779         if (res < 0) {
780                 finishup(transferee);
781                 return -1; /* error ? */
782         }
783         if (res > 0)    /* If they've typed a digit already, handle it */
784                 xferto[0] = (char) res;
785
786         ast_stopstream(transferer);
787         res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
788         if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
789                 finishup(transferee);
790                 return res;
791         }
792         if (!strcmp(xferto, ast_parking_ext())) {
793                 res = finishup(transferee);
794                 if (res)
795                         res = -1;
796                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {     /* success */
797                         /* We return non-zero, but tell the PBX not to hang the channel when
798                            the thread dies -- We have to be careful now though.  We are responsible for 
799                            hanging up the channel, else it will never be hung up! */
800
801                         return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
802                 } else {
803                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
804                 }
805                 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
806         } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
807                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
808                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
809                 res=finishup(transferee);
810                 if (!transferer->cdr) {
811                         transferer->cdr=ast_cdr_alloc();
812                         if (transferer) {
813                                 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
814                                 ast_cdr_start(transferer->cdr);
815                         }
816                 }
817                 if (transferer->cdr) {
818                         ast_cdr_setdestchan(transferer->cdr, transferee->name);
819                         ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
820                 }
821                 if (!transferee->pbx) {
822                         /* Doh!  Use our handy async_goto functions */
823                         if (option_verbose > 2) 
824                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
825                                                                 ,transferee->name, xferto, transferer_real_context);
826                         if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
827                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
828                 } else {
829                         /* Set the channel's new extension, since it exists, using transferer context */
830                         set_c_e_p(transferee, transferer_real_context, xferto, 0);
831                 }
832                 check_goto_on_transfer(transferer);
833                 return res;
834         } else {
835                 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
836         }
837         if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
838                 finishup(transferee);
839                 return -1;
840         }
841         ast_stopstream(transferer);
842         res = finishup(transferee);
843         if (res) {
844                 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
845                 return res;
846         }
847         return FEATURE_RETURN_SUCCESS;
848 }
849
850 /*!
851  * \brief make channels compatible
852  * \param c
853  * \param newchan
854  * \retval 0 on success.
855  * \retval -1 on failure.
856 */
857 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
858 {
859         if (ast_channel_make_compatible(c, newchan) < 0) {
860                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
861                         c->name, newchan->name);
862                 ast_hangup(newchan);
863                 return -1;
864         }
865         return 0;
866 }
867
868 /*!
869  * \brief Attended transfer
870  * \param chan transfered user
871  * \param peer person transfering call
872  * \param config
873  * \param code
874  * \param sense feature options
875  * 
876  * \param data
877  * Get extension to transfer to, if you cannot generate channel (or find extension) 
878  * return to host channel. After called channel answered wait for hangup of transferer,
879  * bridge call between transfer peer (taking them off hold) to attended transfer channel.
880  *
881  * \return -1 on failure
882 */
883 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
884 {
885         struct ast_channel *transferer;
886         struct ast_channel *transferee;
887         const char *transferer_real_context;
888         char xferto[256] = "";
889         int res;
890         int outstate=0;
891         struct ast_channel *newchan;
892         struct ast_channel *xferchan;
893         struct ast_bridge_thread_obj *tobj;
894         struct ast_bridge_config bconfig;
895         struct ast_frame *f;
896         int l;
897
898         ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
899         set_peers(&transferer, &transferee, peer, chan, sense);
900         transferer_real_context = real_ctx(transferer, transferee);
901         /* Start autoservice on chan while we talk to the originator */
902         ast_autoservice_start(transferee);
903         ast_indicate(transferee, AST_CONTROL_HOLD);
904         
905         /* Transfer */
906         res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
907         if (res < 0) {
908                 finishup(transferee);
909                 return res;
910         }
911         if (res > 0) /* If they've typed a digit already, handle it */
912                 xferto[0] = (char) res;
913
914         /* this is specific of atxfer */
915         res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
916         if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
917                 finishup(transferee);
918                 return res;
919         }
920         if (res == 0) {
921                 ast_log(LOG_WARNING, "Did not read data.\n");
922                 finishup(transferee);
923                 if (ast_stream_and_wait(transferer, "beeperr", ""))
924                         return -1;
925                 return FEATURE_RETURN_SUCCESS;
926         }
927
928         /* valid extension, res == 1 */
929         if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
930                 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
931                 finishup(transferee);
932                 if (ast_stream_and_wait(transferer, "beeperr", ""))
933                         return -1;
934                 return FEATURE_RETURN_SUCCESS;
935         }
936
937         l = strlen(xferto);
938         snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);     /* append context */
939         newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
940                 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
941
942         if (!ast_check_hangup(transferer)) {
943                 /* Transferer is up - old behaviour */
944                 ast_indicate(transferer, -1);
945                 if (!newchan) {
946                         finishup(transferee);
947                         /* any reason besides user requested cancel and busy triggers the failed sound */
948                         if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
949                                 ast_stream_and_wait(transferer, xferfailsound, ""))
950                                 return -1;
951                         if (ast_stream_and_wait(transferer, xfersound, ""))
952                                 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
953                         return FEATURE_RETURN_SUCCESS;
954                 }
955
956                 if (check_compat(transferer, newchan)) {
957                         /* we do mean transferee here, NOT transferer */
958                         finishup(transferee);
959                         return -1;
960                 }
961                 memset(&bconfig,0,sizeof(struct ast_bridge_config));
962                 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
963                 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
964                 res = ast_bridge_call(transferer, newchan, &bconfig);
965                 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
966                         ast_hangup(newchan);
967                         if (ast_stream_and_wait(transferer, xfersound, ""))
968                                 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
969                         finishup(transferee);
970                         transferer->_softhangup = 0;
971                         return FEATURE_RETURN_SUCCESS;
972                 }
973                 if (check_compat(transferee, newchan)) {
974                         finishup(transferee);
975                         return -1;
976                 }
977                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
978
979                 if ((ast_autoservice_stop(transferee) < 0)
980                  || (ast_waitfordigit(transferee, 100) < 0)
981                  || (ast_waitfordigit(newchan, 100) < 0)
982                  || ast_check_hangup(transferee)
983                  || ast_check_hangup(newchan)) {
984                         ast_hangup(newchan);
985                         return -1;
986                 }
987                 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
988                 if (!xferchan) {
989                         ast_hangup(newchan);
990                         return -1;
991                 }
992                 /* Make formats okay */
993                 xferchan->readformat = transferee->readformat;
994                 xferchan->writeformat = transferee->writeformat;
995                 ast_channel_masquerade(xferchan, transferee);
996                 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
997                 xferchan->_state = AST_STATE_UP;
998                 ast_clear_flag(xferchan, AST_FLAGS_ALL);
999                 xferchan->_softhangup = 0;
1000                 if ((f = ast_read(xferchan)))
1001                         ast_frfree(f);
1002                 newchan->_state = AST_STATE_UP;
1003                 ast_clear_flag(newchan, AST_FLAGS_ALL);
1004                 newchan->_softhangup = 0;
1005                 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1006                         ast_hangup(xferchan);
1007                         ast_hangup(newchan);
1008                         return -1;
1009                 }
1010                 tobj->chan = xferchan;
1011                 tobj->peer = newchan;
1012                 tobj->bconfig = *config;
1013
1014                 if (ast_stream_and_wait(newchan, xfersound, ""))
1015                         ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1016                 ast_bridge_call_thread_launch(tobj);
1017                 return -1;      /* XXX meaning the channel is bridged ? */
1018         } else if (!ast_check_hangup(transferee)) {
1019                 /* act as blind transfer */
1020                 if (ast_autoservice_stop(transferee) < 0) {
1021                         ast_hangup(newchan);
1022                         return -1;
1023                 }
1024
1025                 if (!newchan) {
1026                         unsigned int tries = 0;
1027                         char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
1028
1029                         transferer_tech = strsep(&transferer_name, "/");
1030                         transferer_name = strsep(&transferer_name, "-");
1031
1032                         if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
1033                                 ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
1034                                 if (ast_stream_and_wait(transferee, "beeperr", ""))
1035                                         return -1;
1036                                 return FEATURE_RETURN_SUCCESS;
1037                         }
1038
1039                         ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
1040                         newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1041                                 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
1042                         while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1043                                 /* Trying to transfer again */
1044                                 ast_autoservice_start(transferee);
1045                                 ast_indicate(transferee, AST_CONTROL_HOLD);
1046
1047                                 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1048                                         xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
1049                                 if (ast_autoservice_stop(transferee) < 0) {
1050                                         if (newchan)
1051                                                 ast_hangup(newchan);
1052                                         return -1;
1053                                 }
1054                                 if (!newchan) {
1055                                         /* Transfer failed, sleeping */
1056                                         ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1057                                         ast_safe_sleep(transferee, atxferloopdelay);
1058                                         ast_debug(1, "Trying to callback...\n");
1059                                         newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1060                                                 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
1061                                 }
1062                                 tries++;
1063                         }
1064                 }
1065                 if (!newchan)
1066                         return -1;
1067
1068                 /* newchan is up, we should prepare transferee and bridge them */
1069                 if (check_compat(transferee, newchan)) {
1070                         finishup(transferee);
1071                         return -1;
1072                 }
1073                 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1074
1075                 if ((ast_waitfordigit(transferee, 100) < 0)
1076                    || (ast_waitfordigit(newchan, 100) < 0)
1077                    || ast_check_hangup(transferee)
1078                    || ast_check_hangup(newchan)) {
1079                         ast_hangup(newchan);
1080                         return -1;
1081                 }
1082
1083                 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1084                 if (!xferchan) {
1085                         ast_hangup(newchan);
1086                         return -1;
1087                 }
1088                 /* Make formats okay */
1089                 xferchan->readformat = transferee->readformat;
1090                 xferchan->writeformat = transferee->writeformat;
1091                 ast_channel_masquerade(xferchan, transferee);
1092                 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1093                 xferchan->_state = AST_STATE_UP;
1094                 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1095                 xferchan->_softhangup = 0;
1096                 if ((f = ast_read(xferchan)))
1097                         ast_frfree(f);
1098                 newchan->_state = AST_STATE_UP;
1099                 ast_clear_flag(newchan, AST_FLAGS_ALL);
1100                 newchan->_softhangup = 0;
1101                 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1102                         ast_hangup(xferchan);
1103                         ast_hangup(newchan);
1104                         return -1;
1105                 }
1106                 tobj->chan = xferchan;
1107                 tobj->peer = newchan;
1108                 tobj->bconfig = *config;
1109
1110                 if (ast_stream_and_wait(newchan, xfersound, ""))
1111                         ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1112                 ast_bridge_call_thread_launch(tobj);
1113                 return -1;      /* XXX meaning the channel is bridged ? */
1114         } else {
1115                 /* Transferee hung up */
1116                 finishup(transferee);
1117                 return -1;
1118         }
1119 }
1120
1121 /* add atxfer and automon as undefined so you can only use em if you configure them */
1122 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1123
1124 AST_RWLOCK_DEFINE_STATIC(features_lock);
1125
1126 static struct ast_call_feature builtin_features[] = 
1127 {
1128         { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1129         { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1130         { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1131         { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1132         { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1133 };
1134
1135
1136 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1137
1138 /*! \brief register new feature into feature_list*/
1139 void ast_register_feature(struct ast_call_feature *feature)
1140 {
1141         if (!feature) {
1142                 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1143                 return;
1144         }
1145   
1146         AST_LIST_LOCK(&feature_list);
1147         AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1148         AST_LIST_UNLOCK(&feature_list);
1149
1150         ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1151 }
1152
1153 /*! 
1154  * \brief Add new feature group
1155  * \param fgname feature group name.
1156  *
1157  * Add new feature group to the feature group list insert at head of list.
1158  * \note This function MUST be called while feature_groups is locked.
1159 */
1160 static struct feature_group* register_group(const char *fgname)
1161 {
1162         struct feature_group *fg;
1163
1164         if (!fgname) {
1165                 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1166                 return NULL;
1167         }
1168
1169         if (!(fg = ast_calloc(1, sizeof(*fg))))
1170                 return NULL;
1171
1172         if (ast_string_field_init(fg, 128)) {
1173                 ast_free(fg);
1174                 return NULL;
1175         }
1176
1177         ast_string_field_set(fg, gname, fgname);
1178
1179         AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1180
1181         ast_verb(2, "Registered group '%s'\n", fg->gname);
1182
1183         return fg;
1184 }
1185
1186 /*! 
1187  * \brief Add feature to group
1188  * \param fg feature group
1189  * \param exten
1190  * \param feature feature to add.
1191  *
1192  * Check fg and feature specified, add feature to list
1193  * \note This function MUST be called while feature_groups is locked. 
1194 */
1195 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature) 
1196 {
1197         struct feature_group_exten *fge;
1198
1199         if (!(fge = ast_calloc(1, sizeof(*fge))))
1200                 return;
1201
1202         if (ast_string_field_init(fge, 128)) {
1203                 ast_free(fge);
1204                 return;
1205         }
1206
1207         if (!fg) {
1208                 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1209                 return;
1210         }
1211
1212         if (!feature) {
1213                 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1214                 return;
1215         }
1216
1217         ast_string_field_set(fge, exten, (ast_strlen_zero(exten) ? feature->exten : exten));
1218
1219         fge->feature = feature;
1220
1221         AST_LIST_INSERT_HEAD(&fg->features, fge, entry);                
1222
1223         ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1224                                         feature->sname, fg->gname, exten);
1225 }
1226
1227 void ast_unregister_feature(struct ast_call_feature *feature)
1228 {
1229         if (!feature)
1230                 return;
1231
1232         AST_LIST_LOCK(&feature_list);
1233         AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1234         AST_LIST_UNLOCK(&feature_list);
1235         ast_free(feature);
1236 }
1237
1238 /*! \brief Remove all features in the list */
1239 static void ast_unregister_features(void)
1240 {
1241         struct ast_call_feature *feature;
1242
1243         AST_LIST_LOCK(&feature_list);
1244         while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1245                 ast_free(feature);
1246         AST_LIST_UNLOCK(&feature_list);
1247 }
1248
1249 /*! \brief find a call feature by name */
1250 static struct ast_call_feature *find_dynamic_feature(const char *name)
1251 {
1252         struct ast_call_feature *tmp;
1253
1254         AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1255                 if (!strcasecmp(tmp->sname, name))
1256                         break;
1257         }
1258
1259         return tmp;
1260 }
1261
1262 /*! \brief Remove all feature groups in the list */
1263 static void ast_unregister_groups(void)
1264 {
1265         struct feature_group *fg;
1266         struct feature_group_exten *fge;
1267
1268         AST_RWLIST_WRLOCK(&feature_groups);
1269         while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1270                 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1271                         ast_string_field_free_memory(fge);
1272                         ast_free(fge);
1273                 }
1274
1275                 ast_string_field_free_memory(fg);
1276                 ast_free(fg);
1277         }
1278         AST_RWLIST_UNLOCK(&feature_groups);
1279 }
1280
1281 /*! 
1282  * \brief Find a group by name 
1283  * \param name feature name
1284  * \retval feature group on success.
1285  * \retval NULL on failure.
1286 */
1287 static struct feature_group *find_group(const char *name) {
1288         struct feature_group *fg = NULL;
1289
1290         AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1291                 if (!strcasecmp(fg->gname, name))
1292                         break;
1293         }
1294
1295         return fg;
1296 }
1297
1298 void ast_rdlock_call_features(void)
1299 {
1300         ast_rwlock_rdlock(&features_lock);
1301 }
1302
1303 void ast_unlock_call_features(void)
1304 {
1305         ast_rwlock_unlock(&features_lock);
1306 }
1307
1308 struct ast_call_feature *ast_find_call_feature(const char *name)
1309 {
1310         int x;
1311         for (x = 0; x < FEATURES_COUNT; x++) {
1312                 if (!strcasecmp(name, builtin_features[x].sname))
1313                         return &builtin_features[x];
1314         }
1315         return NULL;
1316 }
1317
1318 /*!
1319  * \brief exec an app by feature 
1320  * \param chan,peer,config,code,sense,data
1321  *
1322  * Find a feature, determine which channel activated
1323  * \retval FEATURE_RETURN_PBX_KEEPALIVE,FEATURE_RETURN_NO_HANGUP_PEER
1324  * \retval -1 error.
1325  * \retval -2 when an application cannot be found.
1326 */
1327 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1328 {
1329         struct ast_app *app;
1330         struct ast_call_feature *feature = data;
1331         struct ast_channel *work, *idle;
1332         int res;
1333
1334         if (!feature) { /* shouldn't ever happen! */
1335                 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1336                 return -1; 
1337         }
1338
1339         if (sense == FEATURE_SENSE_CHAN) {
1340                 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1341                         return FEATURE_RETURN_KEEPTRYING;
1342                 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1343                         work = chan;
1344                         idle = peer;
1345                 } else {
1346                         work = peer;
1347                         idle = chan;
1348                 }
1349         } else {
1350                 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1351                         return FEATURE_RETURN_KEEPTRYING;
1352                 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1353                         work = peer;
1354                         idle = chan;
1355                 } else {
1356                         work = chan;
1357                         idle = peer;
1358                 }
1359         }
1360
1361         if (!(app = pbx_findapp(feature->app))) {
1362                 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1363                 return -2;
1364         }
1365
1366         ast_autoservice_start(idle);
1367         
1368         if (!ast_strlen_zero(feature->moh_class))
1369                 ast_moh_start(idle, feature->moh_class, NULL);
1370
1371         res = pbx_exec(work, app, feature->app_args);
1372
1373         if (!ast_strlen_zero(feature->moh_class))
1374                 ast_moh_stop(idle);
1375
1376         ast_autoservice_stop(idle);
1377
1378         if (res == AST_PBX_KEEPALIVE)
1379                 return FEATURE_RETURN_PBX_KEEPALIVE;
1380         else if (res == AST_PBX_NO_HANGUP_PEER)
1381                 return FEATURE_RETURN_NO_HANGUP_PEER;
1382         else if (res)
1383                 return FEATURE_RETURN_SUCCESSBREAK;
1384         
1385         return FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
1386 }
1387
1388 static void unmap_features(void)
1389 {
1390         int x;
1391
1392         ast_rwlock_wrlock(&features_lock);
1393         for (x = 0; x < FEATURES_COUNT; x++)
1394                 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1395         ast_rwlock_unlock(&features_lock);
1396 }
1397
1398 static int remap_feature(const char *name, const char *value)
1399 {
1400         int x, res = -1;
1401
1402         ast_rwlock_wrlock(&features_lock);
1403         for (x = 0; x < FEATURES_COUNT; x++) {
1404                 if (strcasecmp(builtin_features[x].sname, name))
1405                         continue;
1406
1407                 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1408                 res = 0;
1409                 break;
1410         }
1411         ast_rwlock_unlock(&features_lock);
1412
1413         return res;
1414 }
1415
1416 /*!
1417  * \brief Check the dynamic features
1418  * \param chan,peer,config,code,sense
1419  *
1420  * Lock features list, browse for code, unlock list
1421  * \retval res on success.
1422  * \retval -1 on failure.
1423 */
1424 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1425 {
1426         int x;
1427         struct ast_flags features;
1428         int res = FEATURE_RETURN_PASSDIGITS;
1429         struct ast_call_feature *feature;
1430         struct feature_group *fg = NULL;
1431         struct feature_group_exten *fge;
1432         const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1433         char *tmp, *tok;
1434
1435         if (sense == FEATURE_SENSE_CHAN)
1436                 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1437         else
1438                 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1439         ast_debug(3, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1440
1441         ast_rwlock_rdlock(&features_lock);
1442         for (x = 0; x < FEATURES_COUNT; x++) {
1443                 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1444                     !ast_strlen_zero(builtin_features[x].exten)) {
1445                         /* Feature is up for consideration */
1446                         if (!strcmp(builtin_features[x].exten, code)) {
1447                                 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1448                                 break;
1449                         } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1450                                 if (res == FEATURE_RETURN_PASSDIGITS)
1451                                         res = FEATURE_RETURN_STOREDIGITS;
1452                         }
1453                 }
1454         }
1455         ast_rwlock_unlock(&features_lock);
1456
1457         if (ast_strlen_zero(dynamic_features))
1458                 return res;
1459
1460         tmp = ast_strdupa(dynamic_features);
1461
1462         while ((tok = strsep(&tmp, "#"))) {
1463                 AST_RWLIST_RDLOCK(&feature_groups);
1464
1465                 fg = find_group(tok);
1466
1467                 if (fg) {
1468                         AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1469                                 if (strcasecmp(fge->exten, code))
1470                                         continue;
1471
1472                                 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
1473                                 if (res != FEATURE_RETURN_KEEPTRYING) {
1474                                         AST_RWLIST_UNLOCK(&feature_groups);
1475                                         break;
1476                                 }
1477                                 res = FEATURE_RETURN_PASSDIGITS;
1478                         }
1479                         if (fge)
1480                                 break;
1481                 }
1482
1483                 AST_RWLIST_UNLOCK(&feature_groups);
1484                 AST_LIST_LOCK(&feature_list);
1485
1486                 if(!(feature = find_dynamic_feature(tok))) {
1487                         AST_LIST_UNLOCK(&feature_list);
1488                         continue;
1489                 }
1490                         
1491                 /* Feature is up for consideration */
1492                 if (!strcmp(feature->exten, code)) {
1493                         ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1494                         res = feature->operation(chan, peer, config, code, sense, feature);
1495                         if (res != FEATURE_RETURN_KEEPTRYING) {
1496                                 AST_LIST_UNLOCK(&feature_list);
1497                                 break;
1498                         }
1499                         res = FEATURE_RETURN_PASSDIGITS;
1500                 } else if (!strncmp(feature->exten, code, strlen(code)))
1501                         res = FEATURE_RETURN_STOREDIGITS;
1502
1503                 AST_LIST_UNLOCK(&feature_list);
1504         }
1505         
1506         return res;
1507 }
1508
1509 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1510 {
1511         int x;
1512         
1513         ast_clear_flag(config, AST_FLAGS_ALL);
1514
1515         ast_rwlock_rdlock(&features_lock);
1516         for (x = 0; x < FEATURES_COUNT; x++) {
1517                 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1518                         continue;
1519
1520                 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1521                         ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1522
1523                 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1524                         ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1525         }
1526         ast_rwlock_unlock(&features_lock);
1527         
1528         if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1529                 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1530
1531                 if (dynamic_features) {
1532                         char *tmp = ast_strdupa(dynamic_features);
1533                         char *tok;
1534                         struct ast_call_feature *feature;
1535
1536                         /* while we have a feature */
1537                         while ((tok = strsep(&tmp, "#"))) {
1538                                 AST_LIST_LOCK(&feature_list);
1539                                 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1540                                         if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1541                                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1542                                         if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1543                                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1544                                 }
1545                                 AST_LIST_UNLOCK(&feature_list);
1546                         }
1547                 }
1548         }
1549 }
1550
1551 /*! 
1552  * \brief Get feature and dial
1553  * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1554  *
1555  * Request channel, set channel variables, initiate call,check if they want to disconnect
1556  * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1557  * check for answer break loop, set cdr return channel.
1558  *
1559  * \todo XXX Check - this is very similar to the code in channel.c 
1560  * \return always a channel
1561 */
1562 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate)
1563 {
1564         int state = 0;
1565         int cause = 0;
1566         int to;
1567         struct ast_channel *chan;
1568         struct ast_channel *monitor_chans[2];
1569         struct ast_channel *active_channel;
1570         int res = 0, ready = 0;
1571         
1572         if ((chan = ast_request(type, format, data, &cause))) {
1573                 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1574                 ast_channel_inherit_variables(caller, chan);    
1575                 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1576                 if (!chan->cdr) {
1577                         chan->cdr=ast_cdr_alloc();
1578                         if (chan->cdr) {
1579                                 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1580                                 ast_cdr_start(chan->cdr);
1581                         }
1582                 }
1583                         
1584                 if (!ast_call(chan, data, timeout)) {
1585                         struct timeval started;
1586                         int x, len = 0;
1587                         char *disconnect_code = NULL, *dialed_code = NULL;
1588
1589                         ast_indicate(caller, AST_CONTROL_RINGING);
1590                         /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1591                         ast_rwlock_rdlock(&features_lock);
1592                         for (x = 0; x < FEATURES_COUNT; x++) {
1593                                 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1594                                         continue;
1595
1596                                 disconnect_code = builtin_features[x].exten;
1597                                 len = strlen(disconnect_code) + 1;
1598                                 dialed_code = alloca(len);
1599                                 memset(dialed_code, 0, len);
1600                                 break;
1601                         }
1602                         ast_rwlock_unlock(&features_lock);
1603                         x = 0;
1604                         started = ast_tvnow();
1605                         to = timeout;
1606
1607                         ast_poll_channel_add(caller, chan);
1608
1609                         while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1610                                 struct ast_frame *f = NULL;
1611
1612                                 monitor_chans[0] = caller;
1613                                 monitor_chans[1] = chan;
1614                                 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1615
1616                                 /* see if the timeout has been violated */
1617                                 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1618                                         state = AST_CONTROL_UNHOLD;
1619                                         ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1620                                         break; /*doh! timeout*/
1621                                 }
1622
1623                                 if (!active_channel)
1624                                         continue;
1625
1626                                 if (chan && (chan == active_channel)){
1627                                         f = ast_read(chan);
1628                                         if (f == NULL) { /*doh! where'd he go?*/
1629                                                 state = AST_CONTROL_HANGUP;
1630                                                 res = 0;
1631                                                 break;
1632                                         }
1633                                         
1634                                         if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1635                                                 if (f->subclass == AST_CONTROL_RINGING) {
1636                                                         state = f->subclass;
1637                                                         ast_verb(3, "%s is ringing\n", chan->name);
1638                                                         ast_indicate(caller, AST_CONTROL_RINGING);
1639                                                 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1640                                                         state = f->subclass;
1641                                                         ast_verb(3, "%s is busy\n", chan->name);
1642                                                         ast_indicate(caller, AST_CONTROL_BUSY);
1643                                                         ast_frfree(f);
1644                                                         f = NULL;
1645                                                         break;
1646                                                 } else if (f->subclass == AST_CONTROL_ANSWER) {
1647                                                         /* This is what we are hoping for */
1648                                                         state = f->subclass;
1649                                                         ast_frfree(f);
1650                                                         f = NULL;
1651                                                         ready=1;
1652                                                         break;
1653                                                 } else if (f->subclass != -1) {
1654                                                         ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1655                                                 }
1656                                                 /* else who cares */
1657                                         }
1658
1659                                 } else if (caller && (active_channel == caller)) {
1660                                         f = ast_read(caller);
1661                                         if (f == NULL) { /*doh! where'd he go?*/
1662                                                 if (!igncallerstate) {
1663                                                         if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
1664                                                                 /* make this a blind transfer */
1665                                                                 ready = 1;
1666                                                                 break;
1667                                                         }
1668                                                         state = AST_CONTROL_HANGUP;
1669                                                         res = 0;
1670                                                         break;
1671                                                 }
1672                                         } else {
1673                                         
1674                                                 if (f->frametype == AST_FRAME_DTMF) {
1675                                                         dialed_code[x++] = f->subclass;
1676                                                         dialed_code[x] = '\0';
1677                                                         if (strlen(dialed_code) == len) {
1678                                                                 x = 0;
1679                                                         } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1680                                                                 x = 0;
1681                                                                 dialed_code[x] = '\0';
1682                                                         }
1683                                                         if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1684                                                                 /* Caller Canceled the call */
1685                                                                 state = AST_CONTROL_UNHOLD;
1686                                                                 ast_frfree(f);
1687                                                                 f = NULL;
1688                                                                 break;
1689                                                         }
1690                                                 }
1691                                         }
1692                                 }
1693                                 if (f)
1694                                         ast_frfree(f);
1695                         } /* end while */
1696
1697                         ast_poll_channel_del(caller, chan);
1698
1699                 } else
1700                         ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1701         } else {
1702                 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1703                 switch(cause) {
1704                 case AST_CAUSE_BUSY:
1705                         state = AST_CONTROL_BUSY;
1706                         break;
1707                 case AST_CAUSE_CONGESTION:
1708                         state = AST_CONTROL_CONGESTION;
1709                         break;
1710                 }
1711         }
1712         
1713         ast_indicate(caller, -1);
1714         if (chan && ready) {
1715                 if (chan->_state == AST_STATE_UP) 
1716                         state = AST_CONTROL_ANSWER;
1717                 res = 0;
1718         } else if(chan) {
1719                 res = -1;
1720                 ast_hangup(chan);
1721                 chan = NULL;
1722         } else {
1723                 res = -1;
1724         }
1725         
1726         if (outstate)
1727                 *outstate = state;
1728
1729         if (chan && res <= 0) {
1730                 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1731                         char tmp[256];
1732                         ast_cdr_init(chan->cdr, chan);
1733                         snprintf(tmp, 256, "%s/%s", type, (char *)data);
1734                         ast_cdr_setapp(chan->cdr,"Dial",tmp);
1735                         ast_cdr_update(chan);
1736                         ast_cdr_start(chan->cdr);
1737                         ast_cdr_end(chan->cdr);
1738                         /* If the cause wasn't handled properly */
1739                         if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1740                                 ast_cdr_failed(chan->cdr);
1741                 } else {
1742                         ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1743                 }
1744         }
1745         
1746         return chan;
1747 }
1748
1749 /*!
1750  * \brief bridge the call and set CDR
1751  * \param chan,peer,config
1752  * 
1753  * Set start time, check for two channels,check if monitor on
1754  * check for feature activation, create new CDR
1755  * \retval res on success.
1756  * \retval -1 on failure to bridge.
1757 */
1758 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1759 {
1760         /* Copy voice back and forth between the two channels.  Give the peer
1761            the ability to transfer calls with '#<extension' syntax. */
1762         struct ast_frame *f;
1763         struct ast_channel *who;
1764         char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1765         char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1766         int res;
1767         int diff;
1768         int hasfeatures=0;
1769         int hadfeatures=0;
1770         struct ast_option_header *aoh;
1771         struct ast_bridge_config backup_config;
1772         struct ast_cdr *bridge_cdr;
1773
1774         memset(&backup_config, 0, sizeof(backup_config));
1775
1776         config->start_time = ast_tvnow();
1777
1778         if (chan && peer) {
1779                 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1780                 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1781         } else if (chan)
1782                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1783
1784         if (monitor_ok) {
1785                 const char *monitor_exec;
1786                 struct ast_channel *src = NULL;
1787                 if (!monitor_app) { 
1788                         if (!(monitor_app = pbx_findapp("Monitor")))
1789                                 monitor_ok=0;
1790                 }
1791                 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
1792                         src = chan;
1793                 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1794                         src = peer;
1795                 if (monitor_app && src) {
1796                         char *tmp = ast_strdupa(monitor_exec);
1797                         pbx_exec(src, monitor_app, tmp);
1798                 }
1799         }
1800         
1801         set_config_flags(chan, peer, config);
1802         config->firstpass = 1;
1803
1804         /* Answer if need be */
1805         if (ast_answer(chan))
1806                 return -1;
1807         peer->appl = "Bridged Call";
1808         peer->data = chan->name;
1809
1810         /* copy the userfield from the B-leg to A-leg if applicable */
1811         if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1812                 char tmp[256];
1813                 if (!ast_strlen_zero(chan->cdr->userfield)) {
1814                         snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1815                         ast_cdr_appenduserfield(chan, tmp);
1816                 } else
1817                         ast_cdr_setuserfield(chan, peer->cdr->userfield);
1818                 /* free the peer's cdr without ast_cdr_free complaining */
1819                 ast_free(peer->cdr);
1820                 peer->cdr = NULL;
1821         }
1822
1823         for (;;) {
1824                 struct ast_channel *other;      /* used later */
1825
1826                 res = ast_channel_bridge(chan, peer, config, &f, &who);
1827
1828                 if (config->feature_timer) {
1829                         /* Update time limit for next pass */
1830                         diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1831                         config->feature_timer -= diff;
1832                         if (hasfeatures) {
1833                                 /* Running on backup config, meaning a feature might be being
1834                                    activated, but that's no excuse to keep things going 
1835                                    indefinitely! */
1836                                 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1837                                         ast_debug(1, "Timed out, realtime this time!\n");
1838                                         config->feature_timer = 0;
1839                                         who = chan;
1840                                         if (f)
1841                                                 ast_frfree(f);
1842                                         f = NULL;
1843                                         res = 0;
1844                                 } else if (config->feature_timer <= 0) {
1845                                         /* Not *really* out of time, just out of time for
1846                                            digits to come in for features. */
1847                                         ast_debug(1, "Timed out for feature!\n");
1848                                         if (!ast_strlen_zero(peer_featurecode)) {
1849                                                 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
1850                                                 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1851                                         }
1852                                         if (!ast_strlen_zero(chan_featurecode)) {
1853                                                 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
1854                                                 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1855                                         }
1856                                         if (f)
1857                                                 ast_frfree(f);
1858                                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1859                                         if (!hasfeatures) {
1860                                                 /* Restore original (possibly time modified) bridge config */
1861                                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1862                                                 memset(&backup_config, 0, sizeof(backup_config));
1863                                         }
1864                                         hadfeatures = hasfeatures;
1865                                         /* Continue as we were */
1866                                         continue;
1867                                 } else if (!f) {
1868                                         /* The bridge returned without a frame and there is a feature in progress.
1869                                          * However, we don't think the feature has quite yet timed out, so just
1870                                          * go back into the bridge. */
1871                                         continue;
1872                                 }
1873                         } else {
1874                                 if (config->feature_timer <=0) {
1875                                         /* We ran out of time */
1876                                         config->feature_timer = 0;
1877                                         who = chan;
1878                                         if (f)
1879                                                 ast_frfree(f);
1880                                         f = NULL;
1881                                         res = 0;
1882                                 }
1883                         }
1884                 }
1885                 if (res < 0) {
1886                         if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
1887                                 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1888                         return -1;
1889                 }
1890                 
1891                 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1892                                 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 
1893                                         f->subclass == AST_CONTROL_CONGESTION))) {
1894                         res = -1;
1895                         break;
1896                 }
1897                 /* many things should be sent to the 'other' channel */
1898                 other = (who == chan) ? peer : chan;
1899                 if (f->frametype == AST_FRAME_CONTROL) {
1900                         switch (f->subclass) {
1901                         case AST_CONTROL_RINGING:
1902                         case AST_CONTROL_FLASH:
1903                         case -1:
1904                                 ast_indicate(other, f->subclass);
1905                                 break;
1906                         case AST_CONTROL_HOLD:
1907                         case AST_CONTROL_UNHOLD:
1908                                 ast_indicate_data(other, f->subclass, f->data, f->datalen);
1909                                 break;
1910                         case AST_CONTROL_OPTION:
1911                                 aoh = f->data;
1912                                 /* Forward option Requests */
1913                                 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
1914                                         ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 
1915                                                 f->datalen - sizeof(struct ast_option_header), 0);
1916                                 }
1917                                 break;
1918                         }
1919                 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1920                         /* eat it */
1921                 } else if (f->frametype == AST_FRAME_DTMF) {
1922                         char *featurecode;
1923                         int sense;
1924
1925                         hadfeatures = hasfeatures;
1926                         /* This cannot overrun because the longest feature is one shorter than our buffer */
1927                         if (who == chan) {
1928                                 sense = FEATURE_SENSE_CHAN;
1929                                 featurecode = chan_featurecode;
1930                         } else  {
1931                                 sense = FEATURE_SENSE_PEER;
1932                                 featurecode = peer_featurecode;
1933                         }
1934                         /*! append the event to featurecode. we rely on the string being zero-filled, and
1935                          * not overflowing it. 
1936                          * \todo XXX how do we guarantee the latter ?
1937                          */
1938                         featurecode[strlen(featurecode)] = f->subclass;
1939                         /* Get rid of the frame before we start doing "stuff" with the channels */
1940                         ast_frfree(f);
1941                         f = NULL;
1942                         config->feature_timer = backup_config.feature_timer;
1943                         res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1944                         switch(res) {
1945                         case FEATURE_RETURN_PASSDIGITS:
1946                                 ast_dtmf_stream(other, who, featurecode, 0, 0);
1947                                 /* Fall through */
1948                         case FEATURE_RETURN_SUCCESS:
1949                                 memset(featurecode, 0, sizeof(chan_featurecode));
1950                                 break;
1951                         }
1952                         if (res >= FEATURE_RETURN_PASSDIGITS) {
1953                                 res = 0;
1954                         } else 
1955                                 break;
1956                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1957                         if (hadfeatures && !hasfeatures) {
1958                                 /* Restore backup */
1959                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1960                                 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1961                         } else if (hasfeatures) {
1962                                 if (!hadfeatures) {
1963                                         /* Backup configuration */
1964                                         memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1965                                         /* Setup temporary config options */
1966                                         config->play_warning = 0;
1967                                         ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1968                                         ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1969                                         config->warning_freq = 0;
1970                                         config->warning_sound = NULL;
1971                                         config->end_sound = NULL;
1972                                         config->start_sound = NULL;
1973                                         config->firstpass = 0;
1974                                 }
1975                                 config->start_time = ast_tvnow();
1976                                 config->feature_timer = featuredigittimeout;
1977                                 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
1978                         }
1979                 }
1980                 if (f)
1981                         ast_frfree(f);
1982
1983         }
1984         /* arrange the cdrs */
1985         bridge_cdr = ast_cdr_alloc();
1986         if (bridge_cdr) {
1987                 if (chan->cdr && peer->cdr) { /* both of them? merge */
1988                         ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the  destination as a base, but, really, it's random */
1989                         ast_cdr_start(bridge_cdr); /* now is the time to start */
1990                         
1991                         /* absorb the channel cdr */
1992                         ast_cdr_merge(bridge_cdr, chan->cdr);
1993                         if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
1994                                 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1995                         
1996                         /* absorb the peer cdr */
1997                         ast_cdr_merge(bridge_cdr, peer->cdr);
1998                         if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
1999                                 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
2000                         
2001                         peer->cdr = NULL;
2002                         chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2003                 } else if (chan->cdr) {
2004                         /* take the cdr from the channel - literally */
2005                         ast_cdr_init(bridge_cdr,chan);
2006                         /* absorb this data */
2007                         ast_cdr_merge(bridge_cdr, chan->cdr);
2008                         if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
2009                                 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2010                         chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2011                 } else if (peer->cdr) {
2012                         /* take the cdr from the peer - literally */
2013                         ast_cdr_init(bridge_cdr,peer);
2014                         /* absorb this data */
2015                         ast_cdr_merge(bridge_cdr, peer->cdr);
2016                         if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
2017                                 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2018                         peer->cdr = NULL;
2019                         peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2020                 } else {
2021                         /* make up a new cdr */
2022                         ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
2023                         chan->cdr = bridge_cdr; /*  */
2024                 }
2025                 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
2026                         if (strcmp(bridge_cdr->channel, peer->name) != 0)
2027                                 ast_cdr_setdestchan(bridge_cdr, peer->name);
2028                         else
2029                                 ast_cdr_setdestchan(bridge_cdr, chan->name);
2030                 }
2031         }
2032         return res;
2033 }
2034
2035 /*! \brief Output parking event to manager */
2036 static void post_manager_event(const char *s, struct parkeduser *pu)
2037 {
2038         manager_event(EVENT_FLAG_CALL, s,
2039                 "Exten: %s\r\n"
2040                 "Channel: %s\r\n"
2041                 "CallerIDNum: %s\r\n"
2042                 "CallerIDName: %s\r\n\r\n",
2043                 pu->parkingexten, 
2044                 pu->chan->name,
2045                 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2046                 S_OR(pu->chan->cid.cid_name, "<unknown>")
2047                 );
2048 }
2049
2050 /*! 
2051  * \brief Take care of parked calls and unpark them if needed 
2052  * \param ignore unused var.
2053  * 
2054  * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2055  * if so, remove channel from parking lot and return it to the extension that parked it.
2056  * Check if parked channel decided to hangup, wait until next FD via select().
2057 */
2058 static void *do_parking_thread(void *ignore)
2059 {
2060         char parkingslot[AST_MAX_EXTENSION];
2061         fd_set rfds, efds;      /* results from previous select, to be preserved across loops. */
2062
2063         FD_ZERO(&rfds);
2064         FD_ZERO(&efds);
2065
2066         for (;;) {
2067                 struct parkeduser *pu;
2068                 int ms = -1;    /* select timeout, uninitialized */
2069                 int max = -1;   /* max fd, none there yet */
2070                 fd_set nrfds, nefds;    /* args for the next select */
2071                 FD_ZERO(&nrfds);
2072                 FD_ZERO(&nefds);
2073
2074                 AST_LIST_LOCK(&parkinglot);
2075                 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2076                         struct ast_channel *chan = pu->chan;    /* shorthand */
2077                         int tms;        /* timeout for this item */
2078                         int x;          /* fd index in channel */
2079                         struct ast_context *con;
2080
2081                         if (pu->notquiteyet) /* Pretend this one isn't here yet */
2082                                 continue;
2083                         tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2084                         if (tms > pu->parkingtime) {
2085                                 ast_indicate(chan, AST_CONTROL_UNHOLD);
2086                                 /* Get chan, exten from derived kludge */
2087                                 if (pu->peername[0]) {
2088                                         char *peername = ast_strdupa(pu->peername);
2089                                         char *cp = strrchr(peername, '-');
2090                                         char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
2091                                         int i;
2092
2093                                         if (cp) 
2094                                                 *cp = 0;
2095                                         ast_copy_string(peername_flat,peername,sizeof(peername_flat));
2096                                         for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
2097                                                 if (peername_flat[i] == '/') 
2098                                                         peername_flat[i]= '0';
2099                                         }
2100                                         con = ast_context_find(parking_con_dial);
2101                                         if (!con) {
2102                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
2103                                                 if (!con)
2104                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
2105                                         }
2106                                         if (con) {
2107                                                 char returnexten[AST_MAX_EXTENSION];
2108                                                 snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
2109                                                 ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
2110                                         }
2111                                         if (comebacktoorigin) { 
2112                                                 set_c_e_p(chan, parking_con_dial, peername_flat, 1);
2113                                         } else {
2114                                                 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2115                                                 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2116                                                 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
2117                                                 set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
2118                                         }
2119                                 } else {
2120                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
2121                                            should have their original extensions and such, but we copy to be on the safe side */
2122                                         set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2123                                 }
2124
2125                                 post_manager_event("ParkedCallTimeOut", pu);
2126
2127                                 ast_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
2128                                 /* Start up the PBX, or hang them up */
2129                                 if (ast_pbx_start(chan))  {
2130                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
2131                                         ast_hangup(chan);
2132                                 }
2133                                 /* And take them out of the parking lot */
2134                                 AST_LIST_REMOVE_CURRENT(list);
2135                                 con = ast_context_find(parking_con);
2136                                 if (con) {
2137                                         if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2138                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2139                                         else
2140                                                 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2141                                 } else
2142                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2143                                 ast_free(pu);
2144                         } else {        /* still within parking time, process descriptors */
2145                                 for (x = 0; x < AST_MAX_FDS; x++) {
2146                                         struct ast_frame *f;
2147
2148                                         if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
2149                                                 continue;       /* nothing on this descriptor */
2150
2151                                         if (FD_ISSET(chan->fds[x], &efds))
2152                                                 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2153                                         else
2154                                                 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2155                                         chan->fdno = x;
2156
2157                                         /* See if they need servicing */
2158                                         f = ast_read(chan);
2159                                         if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass ==  AST_CONTROL_HANGUP)) {
2160                                                 if (f)
2161                                                         ast_frfree(f);
2162                                                 post_manager_event("ParkedCallGiveUp", pu);
2163
2164                                                 /* There's a problem, hang them up*/
2165                                                 ast_verb(2, "%s got tired of being parked\n", chan->name);
2166                                                 ast_hangup(chan);
2167                                                 /* And take them out of the parking lot */
2168                                                 AST_LIST_REMOVE_CURRENT(list);
2169                                                 con = ast_context_find(parking_con);
2170                                                 if (con) {
2171                                                         if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2172                                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2173                                                         else
2174                                                                 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2175                                                 } else
2176                                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2177                                                 ast_free(pu);
2178                                                 break;
2179                                         } else {
2180                                                 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2181                                                 ast_frfree(f);
2182                                                 if (pu->moh_trys < 3 && !chan->generatordata) {
2183                                                         ast_debug(1, "MOH on parked call stopped by outside source.  Restarting.\n");
2184                                                         ast_indicate_data(chan, AST_CONTROL_HOLD, 
2185                                                                 S_OR(parkmohclass, NULL),
2186                                                                 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
2187                                                         pu->moh_trys++;
2188                                                 }
2189                                                 goto std;       /*! \todo XXX Ick: jumping into an else statement??? XXX */
2190                                         }
2191
2192                                 } /* end for */
2193                                 if (x >= AST_MAX_FDS) {
2194 std:                                    for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2195                                                 if (chan->fds[x] > -1) {
2196                                                         FD_SET(chan->fds[x], &nrfds);
2197                                                         FD_SET(chan->fds[x], &nefds);
2198                                                         if (chan->fds[x] > max)
2199                                                                 max = chan->fds[x];
2200                                                 }
2201                                         }
2202                                         /* Keep track of our shortest wait */
2203                                         if (tms < ms || ms < 0)
2204                                                 ms = tms;
2205                                 }
2206                         }
2207                 } /* end while */
2208                 AST_LIST_TRAVERSE_SAFE_END
2209                 AST_LIST_UNLOCK(&parkinglot);
2210                 rfds = nrfds;
2211                 efds = nefds;
2212                 {
2213                         struct timeval tv = ast_samp2tv(ms, 1000);
2214                         /* Wait for something to happen */
2215                         ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2216                 }
2217                 pthread_testcancel();
2218         }
2219         return NULL;    /* Never reached */
2220 }
2221
2222 /*! \brief Park a call */
2223 static int park_call_exec(struct ast_channel *chan, void *data)
2224 {
2225         /* Data is unused at the moment but could contain a parking
2226            lot context eventually */
2227         int res = 0;
2228         struct ast_module_user *u;
2229
2230         u = ast_module_user_add(chan);
2231
2232         /* Setup the exten/priority to be s/1 since we don't know
2233            where this call should return */
2234         strcpy(chan->exten, "s");
2235         chan->priority = 1;
2236         /* Answer if call is not up */
2237         if (chan->_state != AST_STATE_UP)
2238                 res = ast_answer(chan);
2239         /* Sleep to allow VoIP streams to settle down */
2240         if (!res)
2241                 res = ast_safe_sleep(chan, 1000);
2242         /* Park the call */
2243         if (!res)
2244                 res = ast_park_call(chan, chan, 0, NULL);
2245
2246         ast_module_user_remove(u);
2247
2248         return !res ? AST_PBX_KEEPALIVE : res;
2249 }
2250
2251 /*! \brief Pickup parked call */
2252 static int park_exec(struct ast_channel *chan, void *data)
2253 {
2254         int res = 0;
2255         struct ast_module_user *u;
2256         struct ast_channel *peer=NULL;
2257         struct parkeduser *pu;
2258         struct ast_context *con;
2259         int park = 0;
2260         struct ast_bridge_config config;
2261
2262         u = ast_module_user_add(chan);
2263
2264         if (data)
2265                 park = atoi((char *)data);
2266
2267         AST_LIST_LOCK(&parkinglot);
2268         AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2269                 if (!data || pu->parkingnum == park) {
2270                         AST_LIST_REMOVE_CURRENT(list);
2271                         break;
2272                 }
2273         }
2274         AST_LIST_TRAVERSE_SAFE_END
2275         AST_LIST_UNLOCK(&parkinglot);
2276
2277         if (pu) {
2278                 peer = pu->chan;
2279                 con = ast_context_find(parking_con);
2280                 if (con) {
2281                         if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2282                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2283                         else
2284                                 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2285                 } else
2286                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2287
2288                 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2289                         "Exten: %s\r\n"
2290                         "Channel: %s\r\n"
2291                         "From: %s\r\n"
2292                         "CallerIDNum: %s\r\n"
2293                         "CallerIDName: %s\r\n",
2294                         pu->parkingexten, pu->chan->name, chan->name,
2295                         S_OR(pu->chan->cid.cid_num, "<unknown>"),
2296                         S_OR(pu->chan->cid.cid_name, "<unknown>")
2297                         );
2298
2299                 ast_free(pu);
2300         }
2301         /* JK02: it helps to answer the channel if not already up */
2302         if (chan->_state != AST_STATE_UP)
2303                 ast_answer(chan);
2304
2305         if (peer) {
2306                 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2307                 
2308                 if (!ast_strlen_zero(courtesytone)) {
2309                         int error = 0;
2310                         ast_indicate(peer, AST_CONTROL_UNHOLD);
2311                         if (parkedplay == 0) {
2312                                 error = ast_stream_and_wait(chan, courtesytone, "");
2313                         } else if (parkedplay == 1) {
2314                                 error = ast_stream_and_wait(peer, courtesytone, "");
2315                         } else if (parkedplay == 2) {
2316                                 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2317                                                 !ast_streamfile(peer, courtesytone, chan->language)) {
2318                                         /*! \todo XXX we would like to wait on both! */
2319                                         res = ast_waitstream(chan, "");
2320                                         if (res >= 0)
2321                                                 res = ast_waitstream(peer, "");
2322                                         if (res < 0)
2323                                                 error = 1;
2324                                 }
2325                         }
2326                         if (error) {
2327                                 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2328                                 ast_hangup(peer);
2329                                 return -1;
2330                         }
2331                 } else
2332                         ast_indicate(peer, AST_CONTROL_UNHOLD); 
2333
2334                 res = ast_channel_make_compatible(chan, peer);
2335                 if (res < 0) {
2336                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2337                         ast_hangup(peer);
2338                         return -1;
2339                 }
2340                 /* This runs sorta backwards, since we give the incoming channel control, as if it
2341                    were the person called. */
2342                 ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
2343
2344                 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2345                 ast_cdr_setdestchan(chan->cdr, peer->name);
2346                 memset(&config, 0, sizeof(struct ast_bridge_config));
2347                 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2348                         ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2349                 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2350                         ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2351                 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2352                         ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2353                 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2354                         ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2355                 res = ast_bridge_call(chan, peer, &config);
2356
2357                 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2358                 ast_cdr_setdestchan(chan->cdr, peer->name);
2359
2360                 /* Simulate the PBX hanging up */
2361                 if (res != AST_PBX_NO_HANGUP_PEER)
2362                         ast_hangup(peer);
2363                 return res;
2364         } else {
2365                 /*! \todo XXX Play a message XXX */
2366                 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2367                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2368                 ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2369                 res = -1;
2370         }
2371
2372         ast_module_user_remove(u);
2373
2374         return res;
2375 }
2376
2377 /*!
2378  * \brief CLI command to list configured features
2379  * \param e
2380  * \param cmd
2381  * \param a
2382  *
2383  * \retval CLI_SUCCESS on success.
2384  * \retval NULL when tab completion is used.
2385  */
2386 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) {
2387         int i;
2388         struct ast_call_feature *feature;
2389         char format[] = "%-25s %-7s %-7s\n";
2390
2391         switch (cmd) {
2392         
2393         case CLI_INIT:
2394                 e->command = "features show";
2395                 e->usage =
2396                         "Usage: features show\n"
2397                         "       Lists configured features\n";
2398                 return NULL;
2399         case CLI_GENERATE:
2400                 return NULL;
2401         }
2402
2403         ast_cli(a->fd, format, "Builtin Feature", "Default", "Current");
2404         ast_cli(a->fd, format, "---------------", "-------", "-------");
2405
2406         ast_cli(a->fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
2407
2408         ast_rwlock_rdlock(&features_lock);
2409         for (i = 0; i < FEATURES_COUNT; i++)
2410                 ast_cli(a->fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2411         ast_rwlock_unlock(&features_lock);
2412
2413         ast_cli(a->fd, "\n");
2414         ast_cli(a->fd, format, "Dynamic Feature", "Default", "Current");
2415         ast_cli(a->fd, format, "---------------", "-------", "-------");
2416         if (AST_LIST_EMPTY(&feature_list))
2417                 ast_cli(a->fd, "(none)\n");
2418         else {
2419                 AST_LIST_LOCK(&feature_list);
2420                 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2421                         ast_cli(a->fd, format, feature->sname, "no def", feature->exten);
2422                 AST_LIST_UNLOCK(&feature_list);
2423         }
2424         ast_cli(a->fd, "\nCall parking\n");
2425         ast_cli(a->fd, "------------\n");
2426         ast_cli(a->fd,"%-20s:      %s\n", "Parking extension", parking_ext);
2427         ast_cli(a->fd,"%-20s:      %s\n", "Parking context", parking_con);
2428         ast_cli(a->fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2429         ast_cli(a->fd,"\n");
2430
2431         return CLI_SUCCESS;
2432 }
2433
2434 static char mandescr_bridge[] =
2435 "Description: Bridge together two channels already in the PBX\n"
2436 "Variables: ( Headers marked with * are required )\n"
2437 "   *Channel1: Channel to Bridge to Channel2\n"
2438 "   *Channel2: Channel to Bridge to Channel1\n"
2439 "        Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2440 "\n";
2441
2442 /*!
2443  * \brief Actual bridge
2444  * \param chan
2445  * \param tmpchan
2446  * 
2447  * Stop hold music, lock both channels, masq channels,
2448  * after bridge return channel to next priority.
2449 */
2450 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2451 {
2452         ast_moh_stop(chan);
2453         ast_channel_lock(chan);
2454         ast_setstate(tmpchan, chan->_state);
2455         tmpchan->readformat = chan->readformat;
2456         tmpchan->writeformat = chan->writeformat;
2457         ast_channel_masquerade(tmpchan, chan);
2458         ast_channel_lock(tmpchan);
2459         ast_do_masquerade(tmpchan);
2460         /* when returning from bridge, the channel will continue at the next priority */
2461         ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2462         ast_channel_unlock(tmpchan);
2463         ast_channel_unlock(chan);
2464 }
2465
2466 /*!
2467  * \brief Bridge channels together
2468  * \param s
2469  * \param m
2470  * 
2471  * Make sure valid channels were specified, 
2472  * send errors if any of the channels could not be found/locked, answer channels if needed,
2473  * create the placeholder channels and grab the other channels 
2474  * make the channels compatible, send error if we fail doing so 
2475  * setup the bridge thread object and start the bridge.
2476  * 
2477  * \retval 0 on success or on incorrect use.
2478  * \retval 1 on failure to bridge channels.
2479 */
2480 static int action_bridge(struct mansession *s, const struct message *m)
2481 {
2482         const char *channela = astman_get_header(m, "Channel1");
2483         const char *channelb = astman_get_header(m, "Channel2");
2484         const char *playtone = astman_get_header(m, "Tone");
2485         struct ast_channel *chana = NULL, *chanb = NULL;
2486         struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
2487         struct ast_bridge_thread_obj *tobj = NULL;
2488
2489         /* make sure valid channels were specified */
2490         if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
2491                 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
2492                 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
2493                 if (chana)
2494                         ast_channel_unlock(chana);
2495                 if (chanb)
2496                         ast_channel_unlock(chanb);
2497
2498                 /* send errors if any of the channels could not be found/locked */
2499                 if (!chana) {
2500                         char buf[256];
2501                         snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
2502                         astman_send_error(s, m, buf);
2503                         return 0;
2504                 }
2505                 if (!chanb) {
2506                         char buf[256];
2507                         snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
2508                         astman_send_error(s, m, buf);
2509                         return 0;
2510                 }
2511         } else {
2512                 astman_send_error(s, m, "Missing channel parameter in request");
2513                 return 0;
2514         }
2515
2516         /* Answer the channels if needed */
2517         if (chana->_state != AST_STATE_UP)
2518                 ast_answer(chana);
2519         if (chanb->_state != AST_STATE_UP)
2520                 ast_answer(chanb);
2521
2522         /* create the placeholder channels and grab the other channels */
2523         if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
2524                 NULL, NULL, 0, "Bridge/%s", chana->name))) {
2525                 astman_send_error(s, m, "Unable to create temporary channel!");
2526                 return 1;
2527         }
2528
2529         if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
2530                 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
2531                 astman_send_error(s, m, "Unable to create temporary channels!");
2532                 ast_channel_free(tmpchana);
2533                 return 1;
2534         }
2535
2536         do_bridge_masquerade(chana, tmpchana);
2537         do_bridge_masquerade(chanb, tmpchanb);
2538         
2539         /* make the channels compatible, send error if we fail doing so */
2540         if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
2541                 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
2542                 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
2543                 ast_hangup(tmpchana);
2544                 ast_hangup(tmpchanb);
2545                 return 1;
2546         }
2547
2548         /* setup the bridge thread object and start the bridge */
2549         if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
2550                 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
2551                 astman_send_error(s, m, "Unable to spawn a new bridge thread");
2552                 ast_hangup(tmpchana);
2553                 ast_hangup(tmpchanb);
2554                 return 1;
2555         }
2556
2557         tobj->chan = tmpchana;
2558         tobj->peer = tmpchanb;
2559         tobj->return_to_pbx = 1;
2560         
2561         if (ast_true(playtone)) {
2562                 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
2563                         if (ast_waitstream(tmpchanb, "") < 0)
2564                                 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
2565                 }
2566         }
2567
2568         ast_bridge_call_thread_launch(tobj);
2569
2570         astman_send_ack(s, m, "Launched bridge thread with success");
2571
2572         return 0;
2573 }
2574
2575 /*!
2576  * \brief CLI command to list parked calls
2577  * \param e 
2578  * \param cmd
2579  * \param a
2580  *  
2581  * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
2582  * \retval CLI_SUCCESS on success.
2583  * \retval CLI_SHOWUSAGE on incorrect number of arguments.
2584  * \retval NULL when tab completion is used.
2585 */
2586 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2587 {
2588         struct parkeduser *cur;
2589         int numparked = 0;
2590
2591         switch (cmd) {
2592         case CLI_INIT:
2593                 e->command = "parkedcalls show";
2594                 e->usage =
2595                         "Usage: parkedcalls show\n"
2596                         "       List currently parked calls\n";
2597                 return NULL;
2598         case CLI_GENERATE:
2599                 return NULL;
2600         }
2601
2602         if (a->argc > e->args)
2603                 return CLI_SHOWUSAGE;
2604
2605         ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2606                 , "Context", "Extension", "Pri", "Timeout");
2607
2608         AST_LIST_LOCK(&parkinglot);
2609         AST_LIST_TRAVERSE(&parkinglot, cur, list) {
2610                 ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2611                         ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2612                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2613
2614                 numparked++;
2615         }
2616         AST_LIST_UNLOCK(&parkinglot);
2617         ast_cli(a->fd, "%d parked call%s.\n", numparked, ESS(numparked));
2618
2619
2620         return CLI_SUCCESS;
2621 }
2622
2623 static char *handle_parkedcalls_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2624 {
2625         char *res = handle_parkedcalls(e, cmd, a);
2626         if (cmd == CLI_INIT)
2627                 e->command = "show parkedcalls";
2628         return res;
2629 }
2630
2631 static struct ast_cli_entry cli_show_parkedcalls_deprecated = AST_CLI_DEFINE(handle_parkedcalls_deprecated, "List currently parked calls.");
2632
2633 static struct ast_cli_entry cli_features[] = {
2634         AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
2635         AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls", .deprecate_cmd = &cli_show_parkedcalls_deprecated),
2636 };
2637
2638 /*! 
2639  * \brief Dump parking lot status
2640  * \param s
2641  * \param m
2642  * 
2643  * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
2644  * \return Always RESULT_SUCCESS 
2645 */
2646 static int manager_parking_status(struct mansession *s, const struct message *m)
2647 {
2648         struct parkeduser *cur;
2649         const char *id = astman_get_header(m, "ActionID");
2650         char idText[256] = "";
2651
2652         if (!ast_strlen_zero(id))
2653                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2654
2655         astman_send_ack(s, m, "Parked calls will follow");
2656
2657         AST_LIST_LOCK(&parkinglot);
2658
2659         AST_LIST_TRAVERSE(&parkinglot, cur, list) {
2660                 astman_append(s, "Event: ParkedCall\r\n"
2661                         "Exten: %d\r\n"
2662                         "Channel: %s\r\n"
2663                         "From: %s\r\n"
2664                         "Timeout: %ld\r\n"
2665                         "CallerIDNum: %s\r\n"
2666                         "CallerIDName: %s\r\n"
2667                         "%s"
2668                         "\r\n",
2669                         cur->parkingnum, cur->chan->name, cur->peername,
2670                         (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2671                         S_OR(cur->chan->cid.cid_num, ""),       /* XXX in other places it is <unknown> */
2672                         S_OR(cur->chan->cid.cid_name, ""),
2673                         idText);
2674         }
2675
2676         astman_append(s,
2677                 "Event: ParkedCallsComplete\r\n"
2678                 "%s"
2679                 "\r\n",idText);
2680
2681         AST_LIST_UNLOCK(&parkinglot);
2682
2683         return RESULT_SUCCESS;
2684 }
2685
2686 static char mandescr_park[] =
2687 "Description: Park a channel.\n"
2688 "Variables: (Names marked with * are required)\n"
2689 "       *Channel: Channel name to park\n"
2690 "       *Channel2: Channel to announce park info to (and return to if timeout)\n"
2691 "       Timeout: Number of milliseconds to wait before callback.\n";  
2692
2693 /*!
2694  * \brief Create manager event for parked calls
2695  * \param s
2696  * \param m
2697  *
2698  * Get channels involved in park, create event.
2699  * \return Always 0
2700 */
2701 static int manager_park(struct mansession *s, const struct message *m)
2702 {
2703         const char *channel = astman_get_header(m, "Channel");
2704         const char *channel2 = astman_get_header(m, "Channel2");
2705         const char *timeout = astman_get_header(m, "Timeout");
2706         char buf[BUFSIZ];
2707         int to = 0;
2708         int res = 0;
2709         int parkExt = 0;
2710         struct ast_channel *ch1, *ch2;
2711
2712         if (ast_strlen_zero(channel)) {
2713                 astman_send_error(s, m, "Channel not specified");
2714                 return 0;
2715         }
2716
2717         if (ast_strlen_zero(channel2)) {
2718                 astman_send_error(s, m, "Channel2 not specified");
2719                 return 0;
2720         }
2721
2722         ch1 = ast_get_channel_by_name_locked(channel);
2723         if (!ch1) {
2724                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2725                 astman_send_error(s, m, buf);
2726                 return 0;
2727         }
2728
2729         ch2 = ast_get_channel_by_name_locked(channel2);
2730         if (!ch2) {
2731                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2732                 astman_send_error(s, m, buf);
2733                 ast_channel_unlock(ch1);
2734                 return 0;
2735         }
2736
2737         if (!ast_strlen_zero(timeout)) {
2738                 sscanf(timeout, "%d", &to);
2739         }
2740
2741         res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2742         if (!res) {
2743                 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2744                 astman_send_ack(s, m, "Park successful");
2745         } else {
2746                 astman_send_error(s, m, "Park failure");
2747         }
2748
2749         ast_channel_unlock(ch1);
2750         ast_channel_unlock(ch2);
2751
2752         return 0;
2753 }
2754
2755 /*!
2756  * \brief Pickup a call
2757  * \param chan channel that initiated pickup.
2758  *
2759  * Walk list of channels, checking it is not itself, channel is pbx one,
2760  * check that the callgroup for both channels are the same and the channel is ringing.
2761  * Answer calling channel, flag channel as answered on queue, masq channels together.
2762 */
2763 int ast_pickup_call(struct ast_channel *chan)
2764 {
2765         struct ast_channel *cur = NULL;
2766         int res = -1;
2767
2768         while ((cur = ast_channel_walk_locked(cur)) != NULL) {
2769                 if (!cur->pbx && 
2770                         (cur != chan) &&
2771                         (chan->pickupgroup & cur->callgroup) &&
2772                         ((cur->_state == AST_STATE_RINGING) ||
2773                          (cur->_state == AST_STATE_RING))) {
2774                                 break;
2775                 }
2776                 ast_channel_unlock(cur);
2777         }
2778         if (cur) {
2779                 ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2780                 res = ast_answer(chan);
2781                 if (res)
2782                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2783                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2784                 if (res)
2785                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2786                 res = ast_channel_masquerade(cur, chan);
2787                 if (res)
2788                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
2789                 ast_channel_unlock(cur);
2790         } else  {
2791                 ast_debug(1, "No call pickup possible...\n");
2792         }
2793         return res;
2794 }
2795
2796 /*! 
2797  * \brief Add parking hints for all defined parking lots 
2798  * \param context
2799  * \param start starting parkinglot number
2800  * \param stop ending parkinglot number
2801 */
2802 static void park_add_hints(char *context, int start, int stop)
2803 {
2804         int numext;
2805         char device[AST_MAX_EXTENSION];
2806         char exten[10];
2807
2808         for (numext = start; numext <= stop; numext++) {
2809                 snprintf(exten, sizeof(exten), "%d", numext);
2810                 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2811                 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2812         }
2813 }
2814
2815
2816 static int load_config(void) 
2817 {
2818         int start = 0, end = 0;
2819         int res;
2820         int i;
2821         struct ast_context *con = NULL;
2822         struct ast_config *cfg = NULL;
2823         struct ast_variable *var = NULL;
2824         struct feature_group *fg = NULL;
2825         struct ast_flags config_flags = { 0 };
2826         char old_parking_ext[AST_MAX_EXTENSION];
2827         char old_parking_con[AST_MAX_EXTENSION] = "";
2828         char *ctg; 
2829         static const char *categories[] = { 
2830                 /* Categories in features.conf that are not
2831                  * to be parsed as group categories
2832                  */
2833                 "general",
2834                 "featuremap",
2835                 "applicationmap"
2836         };
2837
2838         if (!ast_strlen_zero(parking_con)) {
2839                 strcpy(old_parking_ext, parking_ext);
2840                 strcpy(old_parking_con, parking_con);
2841         } 
2842
2843         /* Reset to defaults */
2844         strcpy(parking_con, "parkedcalls");
2845         strcpy(parking_con_dial, "park-dial");
2846         strcpy(parking_ext, "700");
2847         strcpy(pickup_ext, "*8");
2848         strcpy(parkmohclass, "default");
2849         courtesytone[0] = '\0';
2850         strcpy(xfersound, "beep");
2851         strcpy(xferfailsound, "pbx-invalid");
2852         parking_start = 701;
2853         parking_stop = 750;
2854         parkfindnext = 0;
2855         adsipark = 0;
2856         comebacktoorigin = 1;
2857         parkaddhints = 0;
2858         parkedcalltransfers = 0;
2859         parkedcallreparking = 0;
2860
2861         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2862         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2863         atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2864         atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2865         atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2866         atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2867
2868         cfg = ast_config_load("features.conf", config_flags);
2869         if (!cfg) {
2870                 ast_log(LOG_WARNING,"Could not load features.conf\n");
2871                 return AST_MODULE_LOAD_DECLINE;
2872         }
2873         for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2874                 if (!strcasecmp(var->name, "parkext")) {
2875                         ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2876                 } else if (!strcasecmp(var->name, "context")) {
2877                         ast_copy_string(parking_con, var->value, sizeof(parking_con));
2878                 } else if (!strcasecmp(var->name, "parkingtime")) {
2879                         if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2880                                 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2881                                 parkingtime = DEFAULT_PARK_TIME;
2882                         } else
2883                                 parkingtime = parkingtime * 1000;
2884                 } else if (!strcasecmp(var->name, "parkpos")) {
2885                         if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2886                                 ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
2887                         } else {
2888                                 parking_start = start;
2889                                 parking_stop = end;
2890                         }
2891                 } else if (!strcasecmp(var->name, "findslot")) {
2892                         parkfindnext = (!strcasecmp(var->value, "next"));
2893                 } else if (!strcasecmp(var->name, "parkinghints")) {
2894                         parkaddhints = ast_true(var->value);
2895                 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2896                         if (!strcasecmp(var->value, "both"))
2897                                 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2898                         else if (!strcasecmp(var->value, "caller"))
2899                                 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2900                         else if (!strcasecmp(var->value, "callee"))
2901                                 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2902                 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2903                         if (!strcasecmp(var->value, "both"))
2904                                 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2905                         else if (!strcasecmp(var->value, "caller"))
2906                                 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2907                         else if (!strcasecmp(var->value, "callee"))
2908                                 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2909                 } else if (!strcasecmp(var->name, "adsipark")) {
2910                         adsipark = ast_true(var->value);
2911                 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2912                         if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2913                                 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2914                                 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2915                         } else
2916                                 transferdigittimeout = transferdigittimeout * 1000;
2917                 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2918                         if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2919                                 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2920                                 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2921                         }
2922                 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2923                         if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2924                                 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2925                                 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2926                         } else
2927                                 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2928                 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2929                         if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2930                                 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2931                                 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2932                         } else 
2933                                 atxferloopdelay *= 1000;
2934                 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2935                         atxferdropcall = ast_true(var->value);
2936                 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2937                         if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2938                                 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2939                                 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2940                         }
2941                 } else if (!strcasecmp(var->name, "courtesytone")) {
2942                         ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2943                 }  else if (!strcasecmp(var->name, "parkedplay")) {
2944                         if (!strcasecmp(var->value, "both"))
2945                                 parkedplay = 2;
2946                         else if (!strcasecmp(var->value, "parked"))
2947                                 parkedplay = 1;
2948                         else
2949                                 parkedplay = 0;
2950                 } else if (!strcasecmp(var->name, "xfersound")) {
2951                         ast_copy_string(xfersound, var->value, sizeof(xfersound));
2952                 } else if (!strcasecmp(var->name, "xferfailsound")) {
2953                         ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2954                 } else if (!strcasecmp(var->name, "pickupexten")) {
2955                         ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2956                 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2957                         comebacktoorigin = ast_true(var->value);
2958                 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2959                         ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2960                 }
2961         }
2962
2963         unmap_features();
2964         for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2965                 if (remap_feature(var->name, var->value))
2966                         ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2967         }
2968
2969         /* Map a key combination to an application*/
2970         ast_unregister_features();
2971         for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2972                 char *tmp_val = ast_strdupa(var->value);
2973                 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class; 
2974                 struct ast_call_feature *feature;
2975
2976                 /* strsep() sets the argument to NULL if match not found, and it
2977                  * is safe to use it with a NULL argument, so we don't check
2978                  * between calls.
2979                  */
2980                 exten = strsep(&tmp_val,",");
2981                 activatedby = strsep(&tmp_val,",");
2982                 app = strsep(&tmp_val,",");
2983                 app_args = strsep(&tmp_val,",");
2984                 moh_class = strsep(&tmp_val,",");
2985
2986                 activateon = strsep(&activatedby, "/"); 
2987
2988                 /*! \todo XXX var_name or app_args ? */
2989                 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2990                         ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2991                                 app, exten, activateon, var->name);
2992                         continue;
2993                 }
2994
2995                 AST_LIST_LOCK(&feature_list);
2996                 if ((feature = find_dynamic_feature(var->name))) {
2997                         AST_LIST_UNLOCK(&feature_list);
2998                         ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2999                         continue;
3000                 }
3001                 AST_LIST_UNLOCK(&feature_list);
3002                                 
3003                 if (!(feature = ast_calloc(1, sizeof(*feature))))
3004                         continue;                                       
3005
3006                 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
3007                 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
3008                 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
3009                 
3010                 if (app_args) 
3011                         ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
3012
3013                 if (moh_class)
3014                         ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
3015                         
3016                 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
3017                 feature->operation = feature_exec_app;
3018                 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
3019
3020                 /* Allow caller and calle to be specified for backwards compatability */
3021                 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
3022                         ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
3023                 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
3024                         ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
3025                 else {
3026                         ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
3027                                 " must be 'self', or 'peer'\n", var->name);
3028                         continue;
3029                 }
3030
3031                 if (ast_strlen_zero(activatedby))
3032                         ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
3033                 else if (!strcasecmp(activatedby, "caller"))
3034                         ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
3035                 else if (!strcasecmp(activatedby, "callee"))
3036                         ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
3037                 else if (!strcasecmp(activatedby, "both"))
3038                         ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
3039                 else {
3040                         ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
3041                                 " must be 'caller', or 'callee', or 'both'\n", var->name);
3042                         continue;
3043                 }
3044
3045                 ast_register_feature(feature);
3046                         
3047                 ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
3048         }
3049
3050         ast_unregister_groups();
3051         AST_RWLIST_WRLOCK(&feature_groups);
3052
3053         ctg = NULL;
3054         while ((ctg = ast_category_browse(cfg, ctg))) {
3055                 for (i = 0; i < ARRAY_LEN(categories); i++) {
3056                         if (!strcasecmp(categories[i], ctg))
3057                                 break;
3058                 }
3059
3060                 if (i < ARRAY_LEN(categories)) 
3061                         continue;
3062
3063                 if (!(fg = register_group(ctg)))
3064                         continue;
3065
3066                 for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
3067                         struct ast_call_feature *feature;
3068
3069                         AST_LIST_LOCK(&feature_list);
3070                         if(!(feature = find_dynamic_feature(var->name)) && 
3071                            !(feature = ast_find_call_feature(var->name))) {
3072                                 AST_LIST_UNLOCK(&feature_list);
3073                                 ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
3074                                 continue;
3075                         }
3076                         AST_LIST_UNLOCK(&feature_list);
3077
3078                         register_group_feature(fg, var->value, feature);
3079                 }
3080         }
3081
3082         AST_RWLIST_UNLOCK(&feature_groups);
3083
3084         ast_config_destroy(cfg);
3085
3086         /* Remove the old parking extension */
3087         if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))     {
3088                 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
3089                                 notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
3090                 ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
3091         }
3092         
3093         if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
3094                 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
3095                 return -1;
3096         }
3097         res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
3098         if (parkaddhints)
3099                 park_add_hints(parking_con, parking_start, parking_stop);
3100         if (!res)
3101                 notify_metermaids(ast_parking_ext(), parking_con, AST_DEVICE_INUSE);
3102         return res;
3103
3104 }
3105
3106 static char *app_bridge = "Bridge";
3107 static char *bridge_synopsis = "Bridge two channels";
3108 static char *bridge_descrip =
3109 "Usage: Bridge(channel[,options])\n"
3110 "       Allows the ability to bridge two channels via the dialplan.\n"
3111 "The current channel is bridged to the specified 'channel'.\n"
3112 "  Options:\n"
3113 "    p - Play a courtesy tone to 'channel'.\n"
3114 "This application sets the following channel variable upon completion:\n"
3115 " BRIDGERESULT    The result of the bridge attempt as a text string, one of\n"
3116 "           SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n";
3117
3118 enum {
3119         BRIDGE_OPT_PLAYTONE = (1 << 0),
3120 };
3121
3122 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
3123         AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
3124 END_OPTIONS );
3125
3126 /*!
3127  * \brief Bridge channels
3128  * \param chan
3129  * \param data channel to bridge with.
3130  * 
3131  * Split data, check we aren't bridging with ourself, check valid channel,
3132  * answer call if not already, check compatible channels, setup bridge config
3133  * now bridge call, if transfered party hangs up return to PBX extension.
3134 */
3135 static int bridge_exec(struct ast_channel *chan, void *data)
3136 {
3137         struct ast_module_user *u;
3138         struct ast_channel *current_dest_chan, *final_dest_chan;
3139         char *tmp_data  = NULL;
3140         struct ast_flags opts = { 0, };
3141         struct ast_bridge_config bconfig = { { 0, }, };
3142
3143         AST_DECLARE_APP_ARGS(args,
3144                 AST_APP_ARG(dest_chan);
3145                 AST_APP_ARG(options);
3146         );
3147         
3148         if (ast_strlen_zero(data)) {
3149                 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
3150                 return -1;
3151         }
3152         
3153         u = ast_module_user_add(chan);
3154
3155         tmp_data = ast_strdupa(data);
3156         AST_STANDARD_APP_ARGS(args, tmp_data);
3157         if (!ast_strlen_zero(args.options))
3158                 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
3159
3160         /* avoid bridge with ourselves */
3161         if (!strncmp(chan->name, args.dest_chan, 
3162                 strlen(chan->name) < strlen(args.dest_chan) ? 
3163                 strlen(chan->name) : strlen(args.dest_chan))) {
3164                 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
3165                 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3166                                         "Response: Failed\r\n"
3167                                         "Reason: Unable to bridge channel to itself\r\n"
3168                                         "Channel1: %s\r\n"
3169                                         "Channel2: %s\r\n",
3170                                         chan->name, args.dest_chan);
3171                 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
3172                 ast_module_user_remove(u);
3173                 return 0;
3174         }
3175
3176         /* make sure we have a valid end point */
3177         if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, 
3178                 strlen(args.dest_chan)))) {
3179                 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
3180                         "cannot get its lock\n", args.dest_chan);
3181                 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3182                                         "Response: Failed\r\n"
3183                                         "Reason: Cannot grab end point\r\n"
3184                                         "Channel1: %s\r\n"
3185                                         "Channel2: %s\r\n", chan->name, args.dest_chan);
3186                 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
3187                 ast_module_user_remove(u);
3188                 return 0;
3189         }
3190         ast_channel_unlock(current_dest_chan);
3191
3192         /* answer the channel if needed */
3193         if (current_dest_chan->_state != AST_STATE_UP)
3194                 ast_answer(current_dest_chan);
3195
3196         /* try to allocate a place holder where current_dest_chan will be placed */
3197         if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, 
3198                 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
3199                 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
3200                 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3201                                         "Response: Failed\r\n"
3202                                         "Reason: cannot create placeholder\r\n"
3203                                         "Channel1: %s\r\n"
3204                                         "Channel2: %s\r\n", chan->name, args.dest_chan);
3205         }
3206         do_bridge_masquerade(current_dest_chan, final_dest_chan);
3207
3208         /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
3209         /* try to make compatible, send error if we fail */
3210         if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
3211                 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
3212                 manager_event(EVENT_FLAG_CALL, "BridgeExec",
3213                                         "Response: Failed\r\n"
3214                                         "Reason: Could not make channels compatible for bridge\r\n"
3215                                         "Channel1: %s\r\n"
3216                                         "Channel2: %s\r\n", chan->name, final_dest_chan->name);
3217                 ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
3218                 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
3219                 ast_module_user_remove(u);
3220                 return 0;
3221         }
3222
3223         /* Report that the bridge will be successfull */
3224         manager_event(EVENT_FLAG_CALL, "BridgeExec",
3225                                 "Response: Success\r\n"
3226                                 "Channel1: %s\r\n"
3227                                 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
3228
3229         /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */       
3230         if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
3231                 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
3232                         if (ast_waitstream(final_dest_chan, "") < 0)
3233                                 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
3234                 }
3235         }
3236         
3237         /* do the bridge */
3238         ast_bridge_call(chan, final_dest_chan, &bconfig);
3239
3240         /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
3241         pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
3242         if (!ast_check_hangup(final_dest_chan)) {
3243                 ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n", 
3244                         final_dest_chan->context, final_dest_chan->exten, 
3245                         final_dest_chan->priority, final_dest_chan->name);
3246
3247                 if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
3248                         ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
3249                         ast_hangup(final_dest_chan);
3250                 } else
3251                         ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
3252         } else {
3253                 ast_debug(1, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
3254                 ast_hangup(final_dest_chan);
3255         }
3256
3257         ast_module_user_remove(u);
3258
3259         return 0;
3260 }
3261
3262 static int reload(void)
3263 {
3264         return load_config();
3265 }
3266
3267 static int load_module(void)
3268 {
3269         int res;
3270
3271         ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);     
3272
3273         memset(parking_ext, 0, sizeof(parking_ext));
3274         memset(parking_con, 0, sizeof(parking_con));
3275
3276         if ((res = load_config()))
3277                 return res;
3278         ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
3279         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
3280         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
3281         if (!res)
3282                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
3283         if (!res) {
3284                 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
3285                 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
3286                         "Park a channel", mandescr_park); 
3287                 ast_manager_register2("Bridge", EVENT_FLAG_COMMAND, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
3288         }
3289
3290         res |= ast_devstate_prov_add("Park", metermaidstate);
3291
3292         return res;
3293 }
3294
3295
3296 static int unload_module(void)
3297 {
3298         ast_manager_unregister("ParkedCalls");
3299         ast_manager_unregister("Bridge");
3300         ast_manager_unregister("Park");
3301         ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
3302         ast_unregister_application(parkcall);
3303         ast_unregister_application(app_bridge);
3304         ast_devstate_prov_del("Park");
3305         return ast_unregister_application(parkedcall);
3306 }
3307
3308 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
3309                 .load = load_module,
3310                 .unload = unload_module,
3311                 .reload = reload,
3312               );