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