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