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