fix seg fault when the parked call that timed out was the last one in the list
[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 #ifdef __AST_DEBUG_MALLOC
63 static void FREE(void *ptr)
64 {
65         free(ptr);
66 }
67 #else
68 #define FREE free
69 #endif
70
71 #define DEFAULT_PARK_TIME 45000
72 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
73 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
74 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
75
76 #define AST_MAX_WATCHERS 256
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), 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
501         int res=0;
502         struct localuser *u;
503         LOCAL_USER_ADD(u);
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         LOCAL_USER_REMOVE(u);
517         if (!res) {
518                 if (sense == FEATURE_SENSE_CHAN)
519                         res = AST_PBX_NO_HANGUP_PEER;
520                 else
521                         res = AST_PBX_KEEPALIVE;
522         }
523         return res;
524
525 }
526
527 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
528 {
529         char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
530         int x = 0;
531         size_t len;
532         struct ast_channel *caller_chan, *callee_chan;
533
534         if (!monitor_ok) {
535                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
536                 return -1;
537         }
538
539         if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
540                 monitor_ok = 0;
541                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
542                 return -1;
543         }
544
545         set_peers(&caller_chan, &callee_chan, peer, chan, sense);
546
547         if (!ast_strlen_zero(courtesytone)) {
548                 if (ast_autoservice_start(callee_chan))
549                         return -1;
550                 if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
551                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
552                         ast_autoservice_stop(callee_chan);
553                         return -1;
554                 }
555                 if (ast_autoservice_stop(callee_chan))
556                         return -1;
557         }
558         
559         if (callee_chan->monitor) {
560                 if (option_verbose > 3)
561                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
562                 ast_monitor_stop(callee_chan, 1);
563                 return FEATURE_RETURN_SUCCESS;
564         }
565
566         if (caller_chan && callee_chan) {
567                 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
568                 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
569
570                 if (!touch_format)
571                         touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
572
573                 if (!touch_monitor)
574                         touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
575         
576                 if (touch_monitor) {
577                         len = strlen(touch_monitor) + 50;
578                         args = alloca(len);
579                         touch_filename = alloca(len);
580                         snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
581                         snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
582                 } else {
583                         caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
584                         callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
585                         len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
586                         args = alloca(len);
587                         touch_filename = alloca(len);
588                         snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
589                         snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
590                 }
591
592                 for( x = 0; x < strlen(args); x++) {
593                         if (args[x] == '/')
594                                 args[x] = '-';
595                 }
596                 
597                 if (option_verbose > 3)
598                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
599
600                 pbx_exec(callee_chan, monitor_app, args);
601                 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
602                 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
603         
604                 return FEATURE_RETURN_SUCCESS;
605         }
606         
607         ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");   
608         return -1;
609 }
610
611 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
612 {
613         if (option_verbose > 3)
614                 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
615         return FEATURE_RETURN_HANGUP;
616 }
617
618 static int finishup(struct ast_channel *chan)
619 {
620         ast_indicate(chan, AST_CONTROL_UNHOLD);
621   
622         return ast_autoservice_stop(chan);
623 }
624
625 /*! \brief Find the context for the transfer */
626 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
627 {
628         const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
629         if (ast_strlen_zero(s))
630                 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
631         if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
632                 s = transferer->macrocontext;
633         if (ast_strlen_zero(s))
634                 s = transferer->context;
635         return s;  
636 }
637
638 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
639 {
640         struct ast_channel *transferer;
641         struct ast_channel *transferee;
642         const char *transferer_real_context;
643         char xferto[256];
644         int res;
645
646         set_peers(&transferer, &transferee, peer, chan, sense);
647         transferer_real_context = real_ctx(transferer, transferee);
648         /* Start autoservice on chan while we talk to the originator */
649         ast_autoservice_start(transferee);
650         ast_indicate(transferee, AST_CONTROL_HOLD);
651
652         memset(xferto, 0, sizeof(xferto));
653         
654         /* Transfer */
655         res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
656         if (res < 0) {
657                 finishup(transferee);
658                 return -1; /* error ? */
659         }
660         if (res > 0)    /* If they've typed a digit already, handle it */
661                 xferto[0] = (char) res;
662
663         ast_stopstream(transferer);
664         res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
665         if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
666                 finishup(transferee);
667                 return res;
668         }
669         if (!strcmp(xferto, ast_parking_ext())) {
670                 res = finishup(transferee);
671                 if (res)
672                         res = -1;
673                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {     /* success */
674                         /* We return non-zero, but tell the PBX not to hang the channel when
675                            the thread dies -- We have to be careful now though.  We are responsible for 
676                            hanging up the channel, else it will never be hung up! */
677
678                         return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
679                 } else {
680                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
681                 }
682                 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
683         } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
684                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
685                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
686                 res=finishup(transferee);
687                 if (!transferee->pbx) {
688                         /* Doh!  Use our handy async_goto functions */
689                         if (option_verbose > 2) 
690                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
691                                                                 ,transferee->name, xferto, transferer_real_context);
692                         if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
693                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
694                         res = -1;
695                 } else {
696                         /* Set the channel's new extension, since it exists, using transferer context */
697                         set_c_e_p(transferee, transferer_real_context, xferto, 0);
698                 }
699                 check_goto_on_transfer(transferer);
700                 return res;
701         } else {
702                 if (option_verbose > 2) 
703                         ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
704         }
705         if (ast_stream_and_wait(transferer, xferfailsound, transferer->language, AST_DIGIT_ANY) < 0 ) {
706                 finishup(transferee);
707                 return -1;
708         }
709         ast_stopstream(transferer);
710         res = finishup(transferee);
711         if (res) {
712                 if (option_verbose > 1)
713                         ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
714                 return res;
715         }
716         return FEATURE_RETURN_SUCCESS;
717 }
718
719 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
720 {
721         if (ast_channel_make_compatible(c, newchan) < 0) {
722                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
723                         c->name, newchan->name);
724                 ast_hangup(newchan);
725                 return -1;
726         }
727         return 0;
728 }
729
730 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
731 {
732         struct ast_channel *transferer;
733         struct ast_channel *transferee;
734         const char *transferer_real_context;
735         char xferto[256] = "";
736         int res;
737         int outstate=0;
738         struct ast_channel *newchan;
739         struct ast_channel *xferchan;
740         struct ast_bridge_thread_obj *tobj;
741         struct ast_bridge_config bconfig;
742         struct ast_frame *f;
743         int l;
744
745         if (option_debug)
746                 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
747         set_peers(&transferer, &transferee, peer, chan, sense);
748         transferer_real_context = real_ctx(transferer, transferee);
749         /* Start autoservice on chan while we talk to the originator */
750         ast_autoservice_start(transferee);
751         ast_indicate(transferee, AST_CONTROL_HOLD);
752         
753         /* Transfer */
754         res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
755         if (res < 0) {
756                 finishup(transferee);
757                 return res;
758         }
759         if (res > 0) /* If they've typed a digit already, handle it */
760                 xferto[0] = (char) res;
761
762         /* this is specific of atxfer */
763         res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
764         if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
765                 finishup(transferee);
766                 return res;
767         }
768         if (res == 0) {
769                 ast_log(LOG_WARNING, "Did not read data.\n");
770                 finishup(transferee);
771                 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
772                         return -1;
773                 return FEATURE_RETURN_SUCCESS;
774         }
775
776         /* valid extension, res == 1 */
777         if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
778                 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
779                 finishup(transferee);
780                 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
781                         return -1;
782                 return FEATURE_RETURN_SUCCESS;
783         }
784
785         l = strlen(xferto);
786         snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);     /* append context */
787         newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
788                 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name);
789         ast_indicate(transferer, -1);
790         if (!newchan) {
791                 finishup(transferee);
792                 /* any reason besides user requested cancel and busy triggers the failed sound */
793                 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
794                                 ast_stream_and_wait(transferer, xferfailsound, transferer->language, ""))
795                         return -1;
796                 return FEATURE_RETURN_SUCCESS;
797         }
798
799         if (check_compat(transferer, newchan))
800                 return -1;
801         memset(&bconfig,0,sizeof(struct ast_bridge_config));
802         ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
803         ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
804         res = ast_bridge_call(transferer, newchan, &bconfig);
805         if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
806                 ast_hangup(newchan);
807                 if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
808                         ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
809                 finishup(transferee);
810                 transferer->_softhangup = 0;
811                 return FEATURE_RETURN_SUCCESS;
812         }
813         
814         if (check_compat(transferee, newchan))
815                 return -1;
816
817         ast_indicate(transferee, AST_CONTROL_UNHOLD);
818         
819         if ((ast_autoservice_stop(transferee) < 0)
820            || (ast_waitfordigit(transferee, 100) < 0)
821            || (ast_waitfordigit(newchan, 100) < 0) 
822            || ast_check_hangup(transferee) 
823            || ast_check_hangup(newchan)) {
824                 ast_hangup(newchan);
825                 return -1;
826         }
827
828         xferchan = ast_channel_alloc(0);
829         if (!xferchan) {
830                 ast_hangup(newchan);
831                 return -1;
832         }
833         ast_string_field_build(xferchan, name, "Transfered/%s", transferee->name);
834         /* Make formats okay */
835         xferchan->readformat = transferee->readformat;
836         xferchan->writeformat = transferee->writeformat;
837         ast_channel_masquerade(xferchan, transferee);
838         ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
839         xferchan->_state = AST_STATE_UP;
840         ast_clear_flag(xferchan, AST_FLAGS_ALL);        
841         xferchan->_softhangup = 0;
842
843         if ((f = ast_read(xferchan)))
844                 ast_frfree(f);
845
846         newchan->_state = AST_STATE_UP;
847         ast_clear_flag(newchan, AST_FLAGS_ALL); 
848         newchan->_softhangup = 0;
849
850         tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
851         if (!tobj) {
852                 ast_hangup(xferchan);
853                 ast_hangup(newchan);
854                 return -1;
855         }
856         tobj->chan = xferchan;
857         tobj->peer = newchan;
858         tobj->bconfig = *config;
859
860         if (ast_stream_and_wait(newchan, xfersound, newchan->language, ""))
861                 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
862         ast_bridge_call_thread_launch(tobj);
863         return -1;      /* XXX meaning the channel is bridged ? */
864 }
865
866
867 /* add atxfer and automon as undefined so you can only use em if you configure them */
868 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
869
870 struct ast_call_feature builtin_features[] = 
871  {
872         { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
873         { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
874         { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
875         { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
876         { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF },
877 };
878
879
880 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
881
882 /*! \brief register new feature into feature_list*/
883 void ast_register_feature(struct ast_call_feature *feature)
884 {
885         if (!feature) {
886                 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
887                 return;
888         }
889   
890         AST_LIST_LOCK(&feature_list);
891         AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
892         AST_LIST_UNLOCK(&feature_list);
893
894         if (option_verbose >= 2) 
895                 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
896 }
897
898 /*! \brief unregister feature from feature_list */
899 void ast_unregister_feature(struct ast_call_feature *feature)
900 {
901         if (!feature)
902                 return;
903
904         AST_LIST_LOCK(&feature_list);
905         AST_LIST_REMOVE(&feature_list,feature,feature_entry);
906         AST_LIST_UNLOCK(&feature_list);
907         free(feature);
908 }
909
910 /*! \brief Remove all features in the list */
911 static void ast_unregister_features(void)
912 {
913         struct ast_call_feature *feature;
914
915         AST_LIST_LOCK(&feature_list);
916         while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
917                 free(feature);
918         AST_LIST_UNLOCK(&feature_list);
919 }
920
921 /*! \brief find a feature by name */
922 static struct ast_call_feature *find_feature(char *name)
923 {
924         struct ast_call_feature *tmp;
925
926         AST_LIST_LOCK(&feature_list);
927         AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
928                 if (!strcasecmp(tmp->sname, name))
929                         break;
930         }
931         AST_LIST_UNLOCK(&feature_list);
932
933         return tmp;
934 }
935
936 /*! \brief exec an app by feature */
937 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
938 {
939         struct ast_app *app;
940         struct ast_call_feature *feature;
941         int res;
942
943         AST_LIST_LOCK(&feature_list);
944         AST_LIST_TRAVERSE(&feature_list,feature,feature_entry) {
945                 if (!strcasecmp(feature->exten,code))
946                         break;
947         }
948         AST_LIST_UNLOCK(&feature_list);
949
950         if (!feature) { /* shouldn't ever happen! */
951                 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
952                 return -1; 
953         }
954         
955         app = pbx_findapp(feature->app);
956         if (app) {
957                 struct ast_channel *work = ast_test_flag(feature,AST_FEATURE_FLAG_CALLEE) ? peer : chan;
958                 res = pbx_exec(work, app, feature->app_args);
959                 if (res == AST_PBX_KEEPALIVE)
960                         return FEATURE_RETURN_PBX_KEEPALIVE;
961                 else if (res == AST_PBX_NO_HANGUP_PEER)
962                         return FEATURE_RETURN_NO_HANGUP_PEER;
963                 else if (res)
964                         return FEATURE_RETURN_SUCCESSBREAK;
965         } else {
966                 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
967                 return -2;
968         }
969         
970         return FEATURE_RETURN_SUCCESS;  /*! \todo XXX should probably return res */
971 }
972
973 static void unmap_features(void)
974 {
975         int x;
976         for (x = 0; x < FEATURES_COUNT; x++)
977                 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
978 }
979
980 static int remap_feature(const char *name, const char *value)
981 {
982         int x;
983         int res = -1;
984         for (x = 0; x < FEATURES_COUNT; x++) {
985                 if (!strcasecmp(name, builtin_features[x].sname)) {
986                         ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
987                         if (option_verbose > 1)
988                                 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);
989                         res = 0;
990                 } else if (!strcmp(value, builtin_features[x].exten)) 
991                         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);
992         }
993         return res;
994 }
995
996 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
997 {
998         int x;
999         struct ast_flags features;
1000         int res = FEATURE_RETURN_PASSDIGITS;
1001         struct ast_call_feature *feature;
1002         const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1003
1004         if (sense == FEATURE_SENSE_CHAN)
1005                 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);   
1006         else
1007                 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);   
1008         if (option_debug > 2)
1009                 ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1010
1011         for (x=0; x < FEATURES_COUNT; x++) {
1012                 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1013                     !ast_strlen_zero(builtin_features[x].exten)) {
1014                         /* Feature is up for consideration */
1015                         if (!strcmp(builtin_features[x].exten, code)) {
1016                                 res = builtin_features[x].operation(chan, peer, config, code, sense);
1017                                 break;
1018                         } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1019                                 if (res == FEATURE_RETURN_PASSDIGITS)
1020                                         res = FEATURE_RETURN_STOREDIGITS;
1021                         }
1022                 }
1023         }
1024
1025
1026         if (!ast_strlen_zero(dynamic_features)) {
1027                 char *tmp = ast_strdupa(dynamic_features);
1028                 char *tok;
1029
1030                 while ((tok = strsep(&tmp, "#")) != NULL) {
1031                         feature = find_feature(tok);
1032                         
1033                         if (feature) {
1034                                 /* Feature is up for consideration */
1035                                 if (!strcmp(feature->exten, code)) {
1036                                         if (option_verbose > 2)
1037                                                 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1038                                         if (sense == FEATURE_SENSE_CHAN)
1039                                                 res = feature->operation(chan, peer, config, code, sense);
1040                                         else
1041                                                 res = feature->operation(peer, chan, config, code, sense);
1042                                         break;
1043                                 } else if (!strncmp(feature->exten, code, strlen(code))) {
1044                                         res = FEATURE_RETURN_STOREDIGITS;
1045                                 }
1046                         }
1047                 }
1048         }
1049         
1050         return res;
1051 }
1052
1053 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1054 {
1055         int x;
1056         
1057         ast_clear_flag(config, AST_FLAGS_ALL);  
1058         for (x = 0; x < FEATURES_COUNT; x++) {
1059                 if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
1060                         if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1061                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1062
1063                         if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1064                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1065                 }
1066         }
1067         
1068         if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1069                 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1070
1071                 if (dynamic_features) {
1072                         char *tmp = ast_strdupa(dynamic_features);
1073                         char *tok;
1074                         struct ast_call_feature *feature;
1075
1076                         /* while we have a feature */
1077                         while ((tok = strsep(&tmp, "#"))) {
1078                                 if ((feature = find_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1079                                         if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
1080                                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1081                                         if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
1082                                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1083                                 }
1084                         }
1085                 }
1086         }
1087 }
1088
1089 /*! \todo XXX Check - this is very similar to the code in channel.c */
1090 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)
1091 {
1092         int state = 0;
1093         int cause = 0;
1094         int to;
1095         struct ast_channel *chan;
1096         struct ast_channel *monitor_chans[2];
1097         struct ast_channel *active_channel;
1098         int res = 0, ready = 0;
1099         
1100         if ((chan = ast_request(type, format, data, &cause))) {
1101                 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1102                 ast_channel_inherit_variables(caller, chan);    
1103                 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1104                 if (!ast_call(chan, data, timeout)) {
1105                         struct timeval started;
1106                         int x, len = 0;
1107                         char *disconnect_code = NULL, *dialed_code = NULL;
1108
1109                         ast_indicate(caller, AST_CONTROL_RINGING);
1110                         /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1111                         for (x=0; x < FEATURES_COUNT; x++) {
1112                                 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1113                                         continue;
1114
1115                                 disconnect_code = builtin_features[x].exten;
1116                                 len = strlen(disconnect_code) + 1;
1117                                 dialed_code = alloca(len);
1118                                 memset(dialed_code, 0, len);
1119                                 break;
1120                         }
1121                         x = 0;
1122                         started = ast_tvnow();
1123                         to = timeout;
1124                         while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1125                                 struct ast_frame *f = NULL;
1126
1127                                 monitor_chans[0] = caller;
1128                                 monitor_chans[1] = chan;
1129                                 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1130
1131                                 /* see if the timeout has been violated */
1132                                 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1133                                         state = AST_CONTROL_UNHOLD;
1134                                         ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1135                                         break; /*doh! timeout*/
1136                                 }
1137
1138                                 if (!active_channel)
1139                                         continue;
1140
1141                                 if (chan && (chan == active_channel)){
1142                                         f = ast_read(chan);
1143                                         if (f == NULL) { /*doh! where'd he go?*/
1144                                                 state = AST_CONTROL_HANGUP;
1145                                                 res = 0;
1146                                                 break;
1147                                         }
1148                                         
1149                                         if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1150                                                 if (f->subclass == AST_CONTROL_RINGING) {
1151                                                         state = f->subclass;
1152                                                         if (option_verbose > 2)
1153                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1154                                                         ast_indicate(caller, AST_CONTROL_RINGING);
1155                                                 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1156                                                         state = f->subclass;
1157                                                         if (option_verbose > 2)
1158                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
1159                                                         ast_indicate(caller, AST_CONTROL_BUSY);
1160                                                         ast_frfree(f);
1161                                                         f = NULL;
1162                                                         break;
1163                                                 } else if (f->subclass == AST_CONTROL_ANSWER) {
1164                                                         /* This is what we are hoping for */
1165                                                         state = f->subclass;
1166                                                         ast_frfree(f);
1167                                                         f = NULL;
1168                                                         ready=1;
1169                                                         break;
1170                                                 } else {
1171                                                         ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1172                                                 }
1173                                                 /* else who cares */
1174                                         }
1175
1176                                 } else if (caller && (active_channel == caller)) {
1177                                         f = ast_read(caller);
1178                                         if (f == NULL) { /*doh! where'd he go?*/
1179                                                 if (caller->_softhangup && !chan->_softhangup) {
1180                                                         /* make this a blind transfer */
1181                                                         ready = 1;
1182                                                         break;
1183                                                 }
1184                                                 state = AST_CONTROL_HANGUP;
1185                                                 res = 0;
1186                                                 break;
1187                                         }
1188                                         
1189                                         if (f->frametype == AST_FRAME_DTMF) {
1190                                                 dialed_code[x++] = f->subclass;
1191                                                 dialed_code[x] = '\0';
1192                                                 if (strlen(dialed_code) == len) {
1193                                                         x = 0;
1194                                                 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1195                                                         x = 0;
1196                                                         dialed_code[x] = '\0';
1197                                                 }
1198                                                 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1199                                                         /* Caller Canceled the call */
1200                                                         state = AST_CONTROL_UNHOLD;
1201                                                         ast_frfree(f);
1202                                                         f = NULL;
1203                                                         break;
1204                                                 }
1205                                         }
1206                                 }
1207                                 if (f)
1208                                         ast_frfree(f);
1209                         } /* end while */
1210                 } else
1211                         ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1212         } else {
1213                 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1214                 switch(cause) {
1215                 case AST_CAUSE_BUSY:
1216                         state = AST_CONTROL_BUSY;
1217                         break;
1218                 case AST_CAUSE_CONGESTION:
1219                         state = AST_CONTROL_CONGESTION;
1220                         break;
1221                 }
1222         }
1223         
1224         ast_indicate(caller, -1);
1225         if (chan && ready) {
1226                 if (chan->_state == AST_STATE_UP) 
1227                         state = AST_CONTROL_ANSWER;
1228                 res = 0;
1229         } else if(chan) {
1230                 res = -1;
1231                 ast_hangup(chan);
1232                 chan = NULL;
1233         } else {
1234                 res = -1;
1235         }
1236         
1237         if (outstate)
1238                 *outstate = state;
1239
1240         if (chan && res <= 0) {
1241                 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1242                         char tmp[256];
1243                         ast_cdr_init(chan->cdr, chan);
1244                         snprintf(tmp, 256, "%s/%s", type, (char *)data);
1245                         ast_cdr_setapp(chan->cdr,"Dial",tmp);
1246                         ast_cdr_update(chan);
1247                         ast_cdr_start(chan->cdr);
1248                         ast_cdr_end(chan->cdr);
1249                         /* If the cause wasn't handled properly */
1250                         if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1251                                 ast_cdr_failed(chan->cdr);
1252                 } else {
1253                         ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1254                 }
1255         }
1256         
1257         return chan;
1258 }
1259
1260 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1261 {
1262         /* Copy voice back and forth between the two channels.  Give the peer
1263            the ability to transfer calls with '#<extension' syntax. */
1264         struct ast_frame *f;
1265         struct ast_channel *who;
1266         char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1267         char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1268         int res;
1269         int diff;
1270         int hasfeatures=0;
1271         int hadfeatures=0;
1272         struct ast_option_header *aoh;
1273         struct timeval start = { 0 , 0 };
1274         struct ast_bridge_config backup_config;
1275
1276         memset(&backup_config, 0, sizeof(backup_config));
1277
1278         config->start_time = ast_tvnow();
1279
1280         if (chan && peer) {
1281                 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1282                 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1283         } else if (chan)
1284                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1285
1286         if (monitor_ok) {
1287                 const char *monitor_exec;
1288                 struct ast_channel *src = NULL;
1289                 if (!monitor_app) { 
1290                         if (!(monitor_app = pbx_findapp("Monitor")))
1291                                 monitor_ok=0;
1292                 }
1293                 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
1294                         src = chan;
1295                 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1296                         src = peer;
1297                 if (monitor_app && src) {
1298                         char *tmp = ast_strdupa(monitor_exec);
1299                         pbx_exec(src, monitor_app, tmp);
1300                 }
1301         }
1302         
1303         set_config_flags(chan, peer, config);
1304         config->firstpass = 1;
1305
1306         /* Answer if need be */
1307         if (ast_answer(chan))
1308                 return -1;
1309         peer->appl = "Bridged Call";
1310         peer->data = chan->name;
1311
1312         /* copy the userfield from the B-leg to A-leg if applicable */
1313         if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1314                 char tmp[256];
1315                 if (!ast_strlen_zero(chan->cdr->userfield)) {
1316                         snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1317                         ast_cdr_appenduserfield(chan, tmp);
1318                 } else
1319                         ast_cdr_setuserfield(chan, peer->cdr->userfield);
1320                 /* free the peer's cdr without ast_cdr_free complaining */
1321                 free(peer->cdr);
1322                 peer->cdr = NULL;
1323         }
1324         for (;;) {
1325                 struct ast_channel *other;      /* used later */
1326                 if (config->feature_timer)
1327                         start = ast_tvnow();
1328
1329                 res = ast_channel_bridge(chan, peer, config, &f, &who);
1330
1331                 if (config->feature_timer) {
1332                         /* Update time limit for next pass */
1333                         diff = ast_tvdiff_ms(ast_tvnow(), start);
1334                         config->feature_timer -= diff;
1335                         if (hasfeatures) {
1336                                 /* Running on backup config, meaning a feature might be being
1337                                    activated, but that's no excuse to keep things going 
1338                                    indefinitely! */
1339                                 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1340                                         if (option_debug)
1341                                                 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1342                                         config->feature_timer = 0;
1343                                         who = chan;
1344                                         if (f)
1345                                                 ast_frfree(f);
1346                                         f = NULL;
1347                                         res = 0;
1348                                 } else if (config->feature_timer <= 0) {
1349                                         /* Not *really* out of time, just out of time for
1350                                            digits to come in for features. */
1351                                         if (option_debug)
1352                                                 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1353                                         if (!ast_strlen_zero(peer_featurecode)) {
1354                                                 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1355                                                 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1356                                         }
1357                                         if (!ast_strlen_zero(chan_featurecode)) {
1358                                                 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1359                                                 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1360                                         }
1361                                         if (f)
1362                                                 ast_frfree(f);
1363                                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1364                                         if (!hasfeatures) {
1365                                                 /* Restore original (possibly time modified) bridge config */
1366                                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1367                                                 memset(&backup_config, 0, sizeof(backup_config));
1368                                         }
1369                                         hadfeatures = hasfeatures;
1370                                         /* Continue as we were */
1371                                         continue;
1372                                 }
1373                         } else {
1374                                 if (config->feature_timer <=0) {
1375                                         /* We ran out of time */
1376                                         config->feature_timer = 0;
1377                                         who = chan;
1378                                         if (f)
1379                                                 ast_frfree(f);
1380                                         f = NULL;
1381                                         res = 0;
1382                                 }
1383                         }
1384                 }
1385                 if (res < 0) {
1386                         ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1387                         return -1;
1388                 }
1389                 
1390                 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1391                                 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 
1392                                         f->subclass == AST_CONTROL_CONGESTION ) ) ) {
1393                         res = -1;
1394                         break;
1395                 }
1396                 /* many things should be sent to the 'other' channel */
1397                 other = (who == chan) ? peer : chan;
1398                 if (f->frametype == AST_FRAME_CONTROL) {
1399                         if (f->subclass == AST_CONTROL_RINGING)
1400                                 ast_indicate(other, AST_CONTROL_RINGING);
1401                         else if (f->subclass == -1)
1402                                 ast_indicate(other, -1);
1403                         else if (f->subclass == AST_CONTROL_FLASH)
1404                                 ast_indicate(other, AST_CONTROL_FLASH);
1405                         else if (f->subclass == AST_CONTROL_OPTION) {
1406                                 aoh = f->data;
1407                                 /* Forward option Requests */
1408                                 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST)
1409                                         ast_channel_setoption(other, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1410                         }
1411                 }
1412                 /* check for '*', if we find it it's time to disconnect */
1413                 if (f->frametype == AST_FRAME_DTMF) {
1414                         char *featurecode;
1415                         int sense;
1416
1417                         hadfeatures = hasfeatures;
1418                         /* This cannot overrun because the longest feature is one shorter than our buffer */
1419                         if (who == chan) {
1420                                 sense = FEATURE_SENSE_CHAN;
1421                                 featurecode = chan_featurecode;
1422                         } else  {
1423                                 sense = FEATURE_SENSE_PEER;
1424                                 featurecode = peer_featurecode;
1425                         }
1426                         /*! append the event to featurecode. we rely on the string being zero-filled, and
1427                          * not overflowing it. 
1428                          * \todo XXX how do we guarantee the latter ?
1429                          */
1430                         featurecode[strlen(featurecode)] = f->subclass;
1431                         /* Get rid of the frame before we start doing "stuff" with the channels */
1432                         ast_frfree(f);
1433                         f = NULL;
1434                         config->feature_timer = backup_config.feature_timer;
1435                         res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1436                         switch(res) {
1437                         case FEATURE_RETURN_PASSDIGITS:
1438                                 ast_dtmf_stream(other, who, featurecode, 0);
1439                                 /* Fall through */
1440                         case FEATURE_RETURN_SUCCESS:
1441                                 memset(featurecode, 0, sizeof(chan_featurecode));
1442                                 break;
1443                         }
1444                         if (res >= FEATURE_RETURN_PASSDIGITS) {
1445                                 res = 0;
1446                         } else 
1447                                 break;
1448                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1449                         if (hadfeatures && !hasfeatures) {
1450                                 /* Restore backup */
1451                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1452                                 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1453                         } else if (hasfeatures) {
1454                                 if (!hadfeatures) {
1455                                         /* Backup configuration */
1456                                         memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1457                                         /* Setup temporary config options */
1458                                         config->play_warning = 0;
1459                                         ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1460                                         ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1461                                         config->warning_freq = 0;
1462                                         config->warning_sound = NULL;
1463                                         config->end_sound = NULL;
1464                                         config->start_sound = NULL;
1465                                         config->firstpass = 0;
1466                                 }
1467                                 config->feature_timer = featuredigittimeout;
1468                                 if (option_debug)
1469                                         ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1470                         }
1471                 }
1472                 if (f)
1473                         ast_frfree(f);
1474         }
1475         return res;
1476 }
1477
1478 static void post_manager_event(const char *s, char *parkingexten, struct ast_channel *chan)
1479 {
1480         manager_event(EVENT_FLAG_CALL, s,
1481                 "Exten: %s\r\n"
1482                 "Channel: %s\r\n"
1483                 "CallerID: %s\r\n"
1484                 "CallerIDName: %s\r\n\r\n",
1485                 parkingexten, 
1486                 chan->name,
1487                 S_OR(chan->cid.cid_num, "<unknown>"),
1488                 S_OR(chan->cid.cid_name, "<unknown>")
1489                 );
1490 }
1491
1492 /*! \brief Take care of parked calls and unpark them if needed */
1493 static void *do_parking_thread(void *ignore)
1494 {
1495         fd_set rfds, efds;      /* results from previous select, to be preserved across loops. */
1496         FD_ZERO(&rfds);
1497         FD_ZERO(&efds);
1498
1499         for (;;) {
1500                 struct parkeduser *pu, *pl, *pt = NULL;
1501                 int ms = -1;    /* select timeout, uninitialized */
1502                 int max = -1;   /* max fd, none there yet */
1503                 fd_set nrfds, nefds;    /* args for the next select */
1504                 FD_ZERO(&nrfds);
1505                 FD_ZERO(&nefds);
1506
1507                 ast_mutex_lock(&parking_lock);
1508                 pl = NULL;
1509                 pu = parkinglot;
1510                 /* navigate the list with prev-cur pointers to support removals */
1511                 while (pu) {
1512                         struct ast_channel *chan = pu->chan;    /* shorthand */
1513                         int tms;        /* timeout for this item */
1514                         int x;          /* fd index in channel */
1515                         struct ast_context *con;
1516
1517                         if (pu->notquiteyet) { /* Pretend this one isn't here yet */
1518                                 pl = pu;
1519                                 pu = pu->next;
1520                                 continue;
1521                         }
1522                         tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1523                         if (tms > pu->parkingtime) {
1524                                 ast_indicate(chan, AST_CONTROL_UNHOLD);
1525                                 /* Get chan, exten from derived kludge */
1526                                 if (pu->peername[0]) {
1527                                         char *peername = ast_strdupa(pu->peername);
1528                                         char *cp = strrchr(peername, '-');
1529                                         if (cp) 
1530                                                 *cp = 0;
1531                                         con = ast_context_find(parking_con_dial);
1532                                         if (!con) {
1533                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
1534                                                 if (!con)
1535                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1536                                         }
1537                                         if (con) {
1538                                                 char returnexten[AST_MAX_EXTENSION];
1539                                                 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1540                                                 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
1541                                         }
1542                                         set_c_e_p(chan, parking_con_dial, peername, 1);
1543                                 } else {
1544                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
1545                                            should have their original extensions and such, but we copy to be on the safe side */
1546                                         set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1547                                 }
1548
1549                                 post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
1550
1551                                 if (option_verbose > 1) 
1552                                         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);
1553                                 /* Start up the PBX, or hang them up */
1554                                 if (ast_pbx_start(chan))  {
1555                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1556                                         ast_hangup(chan);
1557                                 }
1558                                 /* And take them out of the parking lot */
1559                                 if (pl) 
1560                                         pl->next = pu->next;
1561                                 else
1562                                         parkinglot = pu->next;
1563                                 pt = pu;
1564                                 pu = pu->next;
1565                                 con = ast_context_find(parking_con);
1566                                 if (con) {
1567                                         if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1568                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1569                                         else
1570                                                 notify_metermaids(pt->parkingexten, parking_con);
1571                                 } else
1572                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1573                                 free(pt);
1574                         } else {        /* still within parking time, process descriptors */
1575                                 for (x = 0; x < AST_MAX_FDS; x++) {
1576                                         struct ast_frame *f;
1577
1578                                         if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1579                                                 continue;       /* nothing on this descriptor */
1580
1581                                         if (FD_ISSET(chan->fds[x], &efds))
1582                                                 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1583                                         else
1584                                                 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1585                                         chan->fdno = x;
1586
1587                                         /* See if they need servicing */
1588                                         f = ast_read(chan);
1589                                         if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass ==  AST_CONTROL_HANGUP)) {
1590                                                 if (f)
1591                                                         ast_frfree(f);
1592                                                 post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
1593
1594                                                 /* There's a problem, hang them up*/
1595                                                 if (option_verbose > 1) 
1596                                                         ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1597                                                 ast_hangup(chan);
1598                                                 /* And take them out of the parking lot */
1599                                                 if (pl) 
1600                                                         pl->next = pu->next;
1601                                                 else
1602                                                         parkinglot = pu->next;
1603                                                 pt = pu;
1604                                                 pu = pu->next;
1605                                                 con = ast_context_find(parking_con);
1606                                                 if (con) {
1607                                                         if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1608                                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1609                                                 else
1610                                                         notify_metermaids(pt->parkingexten, parking_con);
1611                                                 } else
1612                                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1613                                                 free(pt);
1614                                                 break;
1615                                         } else {
1616                                                 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1617                                                 ast_frfree(f);
1618                                                 if (pu->moh_trys < 3 && !chan->generatordata) {
1619                                                         if (option_debug)
1620                                                                 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source.  Restarting.\n");
1621                                                         ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
1622                                                                 S_OR(parkmohclass, NULL),
1623                                                                 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
1624                                                         pu->moh_trys++;
1625                                                 }
1626                                                 goto std;       /*! \todo XXX Ick: jumping into an else statement??? XXX */
1627                                         }
1628
1629                                 } /* end for */
1630                                 if (x >= AST_MAX_FDS) {
1631 std:                                    for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
1632                                                 if (chan->fds[x] > -1) {
1633                                                         FD_SET(chan->fds[x], &nrfds);
1634                                                         FD_SET(chan->fds[x], &nefds);
1635                                                         if (chan->fds[x] > max)
1636                                                                 max = chan->fds[x];
1637                                                 }
1638                                         }
1639                                         /* Keep track of our shortest wait */
1640                                         if (tms < ms || ms < 0)
1641                                                 ms = tms;
1642                                         pl = pu;
1643                                         pu = pu->next;
1644                                 }
1645                         }
1646                 } /* end while */
1647                 ast_mutex_unlock(&parking_lock);
1648                 rfds = nrfds;
1649                 efds = nefds;
1650                 {
1651                         struct timeval tv = ast_samp2tv(ms, 1000);
1652                         /* Wait for something to happen */
1653                         ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1654                 }
1655                 pthread_testcancel();
1656         }
1657         return NULL;    /* Never reached */
1658 }
1659
1660 /*! \brief Park a call */
1661 static int park_call_exec(struct ast_channel *chan, void *data)
1662 {
1663         /* Data is unused at the moment but could contain a parking
1664            lot context eventually */
1665         int res=0;
1666         struct localuser *u;
1667         LOCAL_USER_ADD(u);
1668         /* Setup the exten/priority to be s/1 since we don't know
1669            where this call should return */
1670         strcpy(chan->exten, "s");
1671         chan->priority = 1;
1672         /* Answer if call is not up */
1673         if (chan->_state != AST_STATE_UP)
1674                 res = ast_answer(chan);
1675         /* Sleep to allow VoIP streams to settle down */
1676         if (!res)
1677                 res = ast_safe_sleep(chan, 1000);
1678         /* Park the call */
1679         if (!res)
1680                 res = ast_park_call(chan, chan, 0, NULL);
1681         LOCAL_USER_REMOVE(u);
1682         if (!res)
1683                 res = AST_PBX_KEEPALIVE;
1684         return res;
1685 }
1686
1687 /*! \brief Pickup parked call */
1688 static int park_exec(struct ast_channel *chan, void *data)
1689 {
1690         int res=0;
1691         struct localuser *u;
1692         struct ast_channel *peer=NULL;
1693         struct parkeduser *pu, *pl=NULL;
1694         struct ast_context *con;
1695         int park;
1696         struct ast_bridge_config config;
1697
1698         if (!data) {
1699                 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
1700                 return -1;
1701         }
1702         LOCAL_USER_ADD(u);
1703         park = atoi((char *)data);
1704         ast_mutex_lock(&parking_lock);
1705         pu = parkinglot;
1706         while(pu) {
1707                 if (pu->parkingnum == park) {
1708                         if (pl)
1709                                 pl->next = pu->next;
1710                         else
1711                                 parkinglot = pu->next;
1712                         break;
1713                 }
1714                 pl = pu;
1715                 pu = pu->next;
1716         }
1717         ast_mutex_unlock(&parking_lock);
1718         if (pu) {
1719                 peer = pu->chan;
1720                 con = ast_context_find(parking_con);
1721                 if (con) {
1722                         if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
1723                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1724                         else
1725                                 notify_metermaids(pu->parkingexten, parking_con);
1726                 } else
1727                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1728
1729                 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
1730                         "Exten: %s\r\n"
1731                         "Channel: %s\r\n"
1732                         "From: %s\r\n"
1733                         "CallerID: %s\r\n"
1734                         "CallerIDName: %s\r\n",
1735                         pu->parkingexten, pu->chan->name, chan->name,
1736                         S_OR(pu->chan->cid.cid_num, "<unknown>"),
1737                         S_OR(pu->chan->cid.cid_name, "<unknown>")
1738                         );
1739
1740                 free(pu);
1741         }
1742         /* JK02: it helps to answer the channel if not already up */
1743         if (chan->_state != AST_STATE_UP)
1744                 ast_answer(chan);
1745
1746         if (peer) {
1747                 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
1748                 
1749                 if (!ast_strlen_zero(courtesytone)) {
1750                         int error = 0;
1751                         ast_indicate(peer, AST_CONTROL_UNHOLD);
1752                         if (parkedplay == 0) {
1753                                 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
1754                         } else if (parkedplay == 1) {
1755                                 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
1756                         } else if (parkedplay == 2) {
1757                                 if (!ast_streamfile(chan, courtesytone, chan->language) &&
1758                                                 !ast_streamfile(peer, courtesytone, chan->language)) {
1759                                         /*! \todo XXX we would like to wait on both! */
1760                                         res = ast_waitstream(chan, "");
1761                                         if (res >= 0)
1762                                                 res = ast_waitstream(peer, "");
1763                                         if (res < 0)
1764                                                 error = 1;
1765                                 }
1766                         }
1767                         if (error) {
1768                                 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1769                                 ast_hangup(peer);
1770                                 return -1;
1771                         }
1772                 } else
1773                         ast_indicate(peer, AST_CONTROL_UNHOLD); 
1774
1775                 res = ast_channel_make_compatible(chan, peer);
1776                 if (res < 0) {
1777                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1778                         ast_hangup(peer);
1779                         return -1;
1780                 }
1781                 /* This runs sorta backwards, since we give the incoming channel control, as if it
1782                    were the person called. */
1783                 if (option_verbose > 2) 
1784                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1785
1786                 memset(&config, 0, sizeof(struct ast_bridge_config));
1787                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1788                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1789                 config.timelimit = 0;
1790                 config.play_warning = 0;
1791                 config.warning_freq = 0;
1792                 config.warning_sound=NULL;
1793                 res = ast_bridge_call(chan, peer, &config);
1794
1795                 /* Simulate the PBX hanging up */
1796                 if (res != AST_PBX_NO_HANGUP_PEER)
1797                         ast_hangup(peer);
1798                 return res;
1799         } else {
1800                 /*! \todo XXX Play a message XXX */
1801                 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
1802                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1803                 if (option_verbose > 2) 
1804                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1805                 res = -1;
1806         }
1807         LOCAL_USER_REMOVE(u);
1808         return res;
1809 }
1810
1811 static int handle_showfeatures(int fd, int argc, char *argv[])
1812 {
1813         int i;
1814         int fcount;
1815         struct ast_call_feature *feature;
1816         char format[] = "%-25s %-7s %-7s\n";
1817
1818         ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1819         ast_cli(fd, format, "---------------", "-------", "-------");
1820
1821         ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
1822
1823         fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1824
1825         for (i = 0; i < fcount; i++)
1826         {
1827                 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1828         }
1829         ast_cli(fd, "\n");
1830         ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1831         ast_cli(fd, format, "---------------", "-------", "-------");
1832         if (AST_LIST_EMPTY(&feature_list)) {
1833                 ast_cli(fd, "(none)\n");
1834         }
1835         else {
1836                 AST_LIST_LOCK(&feature_list);
1837                 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1838                         ast_cli(fd, format, feature->sname, "no def", feature->exten);  
1839                 }
1840                 AST_LIST_UNLOCK(&feature_list);
1841         }
1842         ast_cli(fd, "\nCall parking\n");
1843         ast_cli(fd, "------------\n");
1844         ast_cli(fd,"%-20s:      %s\n", "Parking extension", parking_ext);
1845         ast_cli(fd,"%-20s:      %s\n", "Parking context", parking_con);
1846         ast_cli(fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1847         ast_cli(fd,"\n");
1848         
1849         return RESULT_SUCCESS;
1850 }
1851
1852 static char showfeatures_help[] =
1853 "Usage: show features\n"
1854 "       Lists currently configured features.\n";
1855
1856 static struct ast_cli_entry showfeatures =
1857 { { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
1858
1859 static int handle_parkedcalls(int fd, int argc, char *argv[])
1860 {
1861         struct parkeduser *cur;
1862         int numparked = 0;
1863
1864         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1865                 , "Context", "Extension", "Pri", "Timeout");
1866
1867         ast_mutex_lock(&parking_lock);
1868
1869         for (cur = parkinglot; cur; cur = cur->next) {
1870                 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
1871                         ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
1872                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1873
1874                 numparked++;
1875         }
1876         ast_mutex_unlock(&parking_lock);
1877         ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
1878
1879
1880         return RESULT_SUCCESS;
1881 }
1882
1883 static char showparked_help[] =
1884 "Usage: show parkedcalls\n"
1885 "       Lists currently parked calls.\n";
1886
1887 static struct ast_cli_entry showparked =
1888 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1889
1890 /*! \brief Dump lot status */
1891 static int manager_parking_status( struct mansession *s, struct message *m )
1892 {
1893         struct parkeduser *cur;
1894         char *id = astman_get_header(m,"ActionID");
1895         char idText[256] = "";
1896
1897         if (!ast_strlen_zero(id))
1898                 snprintf(idText, 256, "ActionID: %s\r\n", id);
1899
1900         astman_send_ack(s, m, "Parked calls will follow");
1901
1902         ast_mutex_lock(&parking_lock);
1903
1904         for (cur=parkinglot; cur; cur = cur->next) {
1905                 astman_append(s, "Event: ParkedCall\r\n"
1906                         "Exten: %d\r\n"
1907                         "Channel: %s\r\n"
1908                         "From: %s\r\n"
1909                         "Timeout: %ld\r\n"
1910                         "CallerID: %s\r\n"
1911                         "CallerIDName: %s\r\n"
1912                         "%s"
1913                         "\r\n",
1914                         cur->parkingnum, cur->chan->name, cur->peername,
1915                         (long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL),
1916                         S_OR(cur->chan->cid.cid_num, ""),       /* XXX in other places it is <unknown> */
1917                         S_OR(cur->chan->cid.cid_name, ""),
1918                         idText);
1919         }
1920
1921         astman_append(s,
1922                 "Event: ParkedCallsComplete\r\n"
1923                 "%s"
1924                 "\r\n",idText);
1925
1926         ast_mutex_unlock(&parking_lock);
1927
1928         return RESULT_SUCCESS;
1929 }
1930
1931 static char mandescr_park[] =
1932 "Description: Park a channel.\n"
1933 "Variables: (Names marked with * are required)\n"
1934 "       *Channel: Channel name to park\n"
1935 "       *Channel2: Channel to announce park info to (and return to if timeout)\n"
1936 "       Timeout: Number of milliseconds to wait before callback.\n";  
1937
1938 static int manager_park(struct mansession *s, struct message *m)
1939 {
1940         char *channel = astman_get_header(m, "Channel");
1941         char *channel2 = astman_get_header(m, "Channel2");
1942         char *timeout = astman_get_header(m, "Timeout");
1943         char buf[BUFSIZ];
1944         int to = 0;
1945         int res = 0;
1946         int parkExt = 0;
1947         struct ast_channel *ch1, *ch2;
1948
1949         if (ast_strlen_zero(channel)) {
1950                 astman_send_error(s, m, "Channel not specified");
1951                 return 0;
1952         }
1953
1954         if (ast_strlen_zero(channel2)) {
1955                 astman_send_error(s, m, "Channel2 not specified");
1956                 return 0;
1957         }
1958
1959         ch1 = ast_get_channel_by_name_locked(channel);
1960         if (!ch1) {
1961                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
1962                 astman_send_error(s, m, buf);
1963                 return 0;
1964         }
1965
1966         ch2 = ast_get_channel_by_name_locked(channel2);
1967         if (!ch2) {
1968                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
1969                 astman_send_error(s, m, buf);
1970                 ast_channel_unlock(ch1);
1971                 return 0;
1972         }
1973
1974         if (!ast_strlen_zero(timeout)) {
1975                 sscanf(timeout, "%d", &to);
1976         }
1977
1978         res = ast_masq_park_call(ch1, ch2, to, &parkExt);
1979         if (!res) {
1980                 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
1981                 astman_send_ack(s, m, "Park successful");
1982         } else {
1983                 astman_send_error(s, m, "Park failure");
1984         }
1985
1986         ast_channel_unlock(ch1);
1987         ast_channel_unlock(ch2);
1988
1989         return 0;
1990 }
1991
1992
1993 int ast_pickup_call(struct ast_channel *chan)
1994 {
1995         struct ast_channel *cur = NULL;
1996         int res = -1;
1997
1998         while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
1999                 if (!cur->pbx && 
2000                         (cur != chan) &&
2001                         (chan->pickupgroup & cur->callgroup) &&
2002                         ((cur->_state == AST_STATE_RINGING) ||
2003                          (cur->_state == AST_STATE_RING))) {
2004                                 break;
2005                 }
2006                 ast_channel_unlock(cur);
2007         }
2008         if (cur) {
2009                 if (option_debug)
2010                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2011                 res = ast_answer(chan);
2012                 if (res)
2013                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2014                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2015                 if (res)
2016                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2017                 res = ast_channel_masquerade(cur, chan);
2018                 if (res)
2019                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
2020                 ast_channel_unlock(cur);
2021         } else  {
2022                 if (option_debug)
2023                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
2024         }
2025         return res;
2026 }
2027
2028 /*! \brief Add parking hints for all defined parking lots */
2029 static void park_add_hints(char *context, int start, int stop)
2030 {
2031         int numext;
2032         char device[AST_MAX_EXTENSION];
2033         char exten[10];
2034
2035         for (numext = start; numext <= stop; numext++) {
2036                 snprintf(exten, sizeof(exten), "%d", numext);
2037                 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2038                 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2039         }
2040 }
2041
2042
2043 static int load_config(void) 
2044 {
2045         int start = 0, end = 0;
2046         int res;
2047         struct ast_context *con = NULL;
2048         struct ast_config *cfg = NULL;
2049         struct ast_variable *var = NULL;
2050         char old_parking_ext[AST_MAX_EXTENSION];
2051         char old_parking_con[AST_MAX_EXTENSION] = "";
2052
2053         if (!ast_strlen_zero(parking_con)) {
2054                 strcpy(old_parking_ext, parking_ext);
2055                 strcpy(old_parking_con, parking_con);
2056         } 
2057
2058         /* Reset to defaults */
2059         strcpy(parking_con, "parkedcalls");
2060         strcpy(parking_con_dial, "park-dial");
2061         strcpy(parking_ext, "700");
2062         strcpy(pickup_ext, "*8");
2063         strcpy(parkmohclass, "default");
2064         courtesytone[0] = '\0';
2065         strcpy(xfersound, "beep");
2066         strcpy(xferfailsound, "pbx-invalid");
2067         parking_start = 701;
2068         parking_stop = 750;
2069         parkfindnext = 0;
2070         adsipark = 0;
2071         parkaddhints = 0;
2072
2073         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2074         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2075         atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2076
2077         cfg = ast_config_load("features.conf");
2078         if (cfg) {
2079                 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2080                         if (!strcasecmp(var->name, "parkext")) {
2081                                 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2082                         } else if (!strcasecmp(var->name, "context")) {
2083                                 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2084                         } else if (!strcasecmp(var->name, "parkingtime")) {
2085                                 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2086                                         ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2087                                         parkingtime = DEFAULT_PARK_TIME;
2088                                 } else
2089                                         parkingtime = parkingtime * 1000;
2090                         } else if (!strcasecmp(var->name, "parkpos")) {
2091                                 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2092                                         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);
2093                                 } else {
2094                                         parking_start = start;
2095                                         parking_stop = end;
2096                                 }
2097                         } else if (!strcasecmp(var->name, "findslot")) {
2098                                 parkfindnext = (!strcasecmp(var->value, "next"));
2099                         } else if (!strcasecmp(var->name, "parkinghints")) {
2100                                 parkaddhints = ast_true(var->value);
2101                         } else if (!strcasecmp(var->name, "adsipark")) {
2102                                 adsipark = ast_true(var->value);
2103                         } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2104                                 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2105                                         ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2106                                         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2107                                 } else
2108                                         transferdigittimeout = transferdigittimeout * 1000;
2109                         } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2110                                 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2111                                         ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2112                                         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2113                                 }
2114                         } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2115                                 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2116                                         ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2117                                         atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2118                                 } else
2119                                         atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2120                         } else if (!strcasecmp(var->name, "courtesytone")) {
2121                                 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2122                         }  else if (!strcasecmp(var->name, "parkedplay")) {
2123                                 if (!strcasecmp(var->value, "both"))
2124                                         parkedplay = 2;
2125                                 else if (!strcasecmp(var->value, "parked"))
2126                                         parkedplay = 1;
2127                                 else
2128                                         parkedplay = 0;
2129                         } else if (!strcasecmp(var->name, "xfersound")) {
2130                                 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2131                         } else if (!strcasecmp(var->name, "xferfailsound")) {
2132                                 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2133                         } else if (!strcasecmp(var->name, "pickupexten")) {
2134                                 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2135                         } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2136                                 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2137                         }
2138                 }
2139
2140                 unmap_features();
2141                 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2142                         if (remap_feature(var->name, var->value))
2143                                 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2144                 }
2145
2146                 /* Map a key combination to an application*/
2147                 ast_unregister_features();
2148                 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2149                         char *tmp_val = ast_strdup(var->value);
2150                         char *exten, *party=NULL, *app=NULL, *app_args=NULL; 
2151
2152                         if (!tmp_val) { 
2153                                 /*! \todo XXX No memory. We should probably break, but at least we do not
2154                                  * insist on this entry or we could be stuck in an
2155                                  * infinite loop.
2156                                  */
2157                                 continue;
2158                         }
2159
2160                         /* strsep() sets the argument to NULL if match not found, and it
2161                          * is safe to use it with a NULL argument, so we don't check
2162                          * between calls.
2163                          */
2164                         exten = strsep(&tmp_val,",");
2165                         party = strsep(&tmp_val,",");
2166                         app = strsep(&tmp_val,",");
2167                         app_args = strsep(&tmp_val,",");
2168
2169                         /*! \todo XXX var_name or app_args ? */
2170                         if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(party) || ast_strlen_zero(var->name)) {
2171                                 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",app,exten,party,var->name);
2172                                 free(tmp_val);
2173                                 continue;
2174                         }
2175
2176                         {
2177                                 struct ast_call_feature *feature;
2178                                 int mallocd = 0;
2179                                 
2180                                 if (!(feature = find_feature(var->name))) {
2181                                         mallocd = 1;
2182                                         
2183                                         if (!(feature = ast_calloc(1, sizeof(*feature)))) {
2184                                                 free(tmp_val);
2185                                                 continue;                                       
2186                                         }
2187                                 }
2188
2189                                 ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
2190                                 ast_copy_string(feature->app,app,FEATURE_APP_LEN);
2191                                 ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
2192                                 free(tmp_val);
2193                                 
2194                                 if (app_args) 
2195                                         ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
2196                                 
2197                                 ast_copy_string(feature->exten, exten,sizeof(feature->exten));
2198                                 feature->operation=feature_exec_app;
2199                                 ast_set_flag(feature,AST_FEATURE_FLAG_NEEDSDTMF);
2200                                 
2201                                 if (!strcasecmp(party,"caller"))
2202                                         ast_set_flag(feature,AST_FEATURE_FLAG_CALLER);
2203                                 else if (!strcasecmp(party, "callee"))
2204                                         ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
2205                                 else {
2206                                         ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
2207                                         continue;
2208                                 }
2209
2210                                 ast_register_feature(feature);
2211                                 /* XXX do we need to free it if mallocd ? */
2212                                 
2213                                 if (option_verbose >=1)
2214                                         ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);  
2215                         }
2216                 }        
2217         }
2218         ast_config_destroy(cfg);
2219
2220         /* Remove the old parking extension */
2221         if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con)))     {
2222                 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2223                                 notify_metermaids(old_parking_ext, old_parking_con);
2224                 if (option_debug)
2225                         ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2226         }
2227         
2228         if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2229                 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2230                 return -1;
2231         }
2232         res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
2233         if (parkaddhints)
2234                 park_add_hints(parking_con, parking_start, parking_stop);
2235         if (!res)
2236                 notify_metermaids(ast_parking_ext(), parking_con);
2237         return res;
2238
2239 }
2240
2241 static int reload(void *mod)
2242 {
2243         return load_config();
2244 }
2245
2246 static int load_module(void *mod)
2247 {
2248         int res;
2249         
2250         __mod_desc = mod;
2251         memset(parking_ext, 0, sizeof(parking_ext));
2252         memset(parking_con, 0, sizeof(parking_con));
2253
2254         if ((res = load_config()))
2255                 return res;
2256         ast_cli_register(&showparked);
2257         ast_cli_register(&showfeatures);
2258         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2259         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2260         if (!res)
2261                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2262         if (!res) {
2263                 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2264                 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2265                         "Park a channel", mandescr_park); 
2266         }
2267
2268         res |= ast_devstate_prov_add("Park", metermaidstate);
2269
2270         return res;
2271 }
2272
2273
2274 static int unload_module(void *mod)
2275 {
2276         STANDARD_HANGUP_LOCALUSERS;
2277
2278         ast_manager_unregister("ParkedCalls");
2279         ast_manager_unregister("Park");
2280         ast_cli_unregister(&showfeatures);
2281         ast_cli_unregister(&showparked);
2282         ast_unregister_application(parkcall);
2283         ast_devstate_prov_del("Park");
2284         return ast_unregister_application(parkedcall);
2285 }
2286
2287 static const char *description(void)
2288 {
2289         return "Call Features Resource";
2290 }
2291
2292 static const char *key(void)
2293 {
2294         return ASTERISK_GPL_KEY;
2295 }
2296
2297 STD_MOD(MOD_0 | NO_UNLOAD, reload, NULL, NULL);