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