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