METERMAIDS:
[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 int parking_start;                                  /*!< First available extension for parking */
87 static int parking_stop;                                   /*!< Last available extension for parking */
88
89 static char courtesytone[256];                             /*!< Courtesy tone */
90 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
91 static char xfersound[256];                                /*!< Call transfer sound */
92 static char xferfailsound[256];                            /*!< Call transfer failure sound */
93
94 static int parking_offset;
95 static int parkfindnext;
96
97 static int adsipark;
98
99 static int transferdigittimeout;
100 static int featuredigittimeout;
101
102 static int atxfernoanswertimeout;
103
104 static char *registrar = "res_features";                   /*!< Registrar for operations */
105
106 /* module and CLI command definitions */
107 static char *synopsis = "Answer a parked call";
108
109 static char *descrip = "ParkedCall(exten):"
110 "Used to connect to a parked call.  This application is always\n"
111 "registered internally and does not need to be explicitly added\n"
112 "into the dialplan, although you should include the 'parkedcalls'\n"
113 "context.\n";
114
115 static char *parkcall = "Park";
116
117 static char *synopsis2 = "Park yourself";
118
119 static char *descrip2 = "Park():"
120 "Used to park yourself (typically in combination with a supervised\n"
121 "transfer to know the parking space). This application is always\n"
122 "registered internally and does not need to be explicitly added\n"
123 "into the dialplan, although you should include the 'parkedcalls'\n"
124 "context (or the context specified in features.conf).\n\n"
125 "If you set the PARKINGEXTEN variable to an extension in your\n"
126 "parking context, park() will park the call on that extension, unless\n"
127 "it already exists. In that case, execution will continue at next\n"
128 "priority.\n" ;
129
130 static struct ast_app *monitor_app = NULL;
131 static int monitor_ok = 1;
132
133 struct parkeduser {
134         struct ast_channel *chan;                   /*!< Parking channel */
135         struct timeval start;                       /*!< Time the parking started */
136         int parkingnum;                             /*!< Parking lot */
137         char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
138         char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
139         char exten[AST_MAX_EXTENSION];
140         int priority;
141         int parkingtime;                            /*!< Maximum length in parking lot before return */
142         int notquiteyet;
143         char peername[1024];
144         unsigned char moh_trys;
145         struct parkeduser *next;
146 };
147
148 static struct parkeduser *parkinglot;
149
150 AST_MUTEX_DEFINE_STATIC(parking_lock);  /*!< protects all static variables above */
151
152 static pthread_t parking_thread;
153
154 char *ast_parking_ext(void)
155 {
156         return parking_ext;
157 }
158
159 char *ast_pickup_ext(void)
160 {
161         return pickup_ext;
162 }
163
164 struct ast_bridge_thread_obj 
165 {
166         struct ast_bridge_config bconfig;
167         struct ast_channel *chan;
168         struct ast_channel *peer;
169 };
170
171 /*! \brief store context, priority and extension */
172 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
173 {
174         ast_copy_string(chan->context, context, sizeof(chan->context));
175         ast_copy_string(chan->exten, ext, sizeof(chan->exten));
176         chan->priority = pri;
177 }
178
179 static void check_goto_on_transfer(struct ast_channel *chan) 
180 {
181         struct ast_channel *xferchan;
182         const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
183         char *x, *goto_on_transfer;
184         struct ast_frame *f;
185
186         if (ast_strlen_zero(val))
187                 return;
188
189         goto_on_transfer = ast_strdupa(val);
190
191         if (!(xferchan = ast_channel_alloc(0)))
192                 return;
193
194         for (x = goto_on_transfer; x && *x; x++) {
195                 if (*x == '^')
196                         *x = '|';
197         }
198         ast_string_field_set(xferchan, name, chan->name);
199         /* Make formats okay */
200         xferchan->readformat = chan->readformat;
201         xferchan->writeformat = chan->writeformat;
202         ast_channel_masquerade(xferchan, chan);
203         ast_parseable_goto(xferchan, goto_on_transfer);
204         xferchan->_state = AST_STATE_UP;
205         ast_clear_flag(xferchan, AST_FLAGS_ALL);        
206         xferchan->_softhangup = 0;
207         if ((f = ast_read(xferchan))) {
208                 ast_frfree(f);
209                 f = NULL;
210                 ast_pbx_start(xferchan);
211         } else {
212                 ast_hangup(xferchan);
213         }
214 }
215
216 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);
217
218
219 static void *ast_bridge_call_thread(void *data) 
220 {
221         struct ast_bridge_thread_obj *tobj = data;
222
223         tobj->chan->appl = "Transferred Call";
224         tobj->chan->data = tobj->peer->name;
225         tobj->peer->appl = "Transferred Call";
226         tobj->peer->data = tobj->chan->name;
227         if (tobj->chan->cdr) {
228                 ast_cdr_reset(tobj->chan->cdr, NULL);
229                 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
230         }
231         if (tobj->peer->cdr) {
232                 ast_cdr_reset(tobj->peer->cdr, NULL);
233                 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
234         }
235
236         ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
237         ast_hangup(tobj->chan);
238         ast_hangup(tobj->peer);
239         bzero(tobj, sizeof(*tobj)); /*! \todo XXX for safety */
240         free(tobj);
241         return NULL;
242 }
243
244 static void ast_bridge_call_thread_launch(void *data) 
245 {
246         pthread_t thread;
247         pthread_attr_t attr;
248         struct sched_param sched;
249
250         pthread_attr_init(&attr);
251         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
252         ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
253         pthread_attr_destroy(&attr);
254         memset(&sched, 0, sizeof(sched));
255         pthread_setschedparam(thread, SCHED_RR, &sched);
256 }
257
258 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
259 {
260         int res;
261         int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
262         char tmp[256];
263         char *message[5] = {NULL, NULL, NULL, NULL, NULL};
264
265         snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
266         message[0] = tmp;
267         res = adsi_load_session(chan, NULL, 0, 1);
268         if (res == -1)
269                 return res;
270         return adsi_print(chan, message, justify, 1);
271 }
272
273 /*! \brief Notify metermaids that we've changed an extension */
274 static void notify_metermaids(char *exten, char *context)
275 {
276         if (option_debug > 3)
277                 ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
278
279         /* Send notification to devicestate subsystem */
280         ast_device_state_changed("park:%s@%s", exten, context);
281         return;
282 }
283
284 /*! \brief metermaids callback from devicestate.c */
285 static int metermaidstate(const char *data)
286 {
287         int res = AST_DEVICE_INVALID;
288         char *context = ast_strdupa(data);
289         char *exten;
290
291         exten = strsep(&context, "@");
292         if (!context)
293                 return res;
294         
295         if (option_debug > 3)
296                 ast_log(LOG_DEBUG, "Checking state of exten %s in context %s\n", exten, context);
297
298         res = ast_exists_extension(NULL, context, exten, 1, NULL);
299
300         if (!res)
301                 return AST_DEVICE_NOT_INUSE;
302         else
303                 return AST_DEVICE_INUSE;
304 }
305
306 /*! \brief Park a call 
307         \note We put the user in the parking list, then wake up the parking thread to be sure it looks
308         after these channels too */
309 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
310 {
311         struct parkeduser *pu, *cur;
312         int i, x = -1, parking_range;
313         struct ast_context *con;
314         const char *parkingexten;
315         
316         /* Allocate memory for parking data */
317         if (!(pu = ast_calloc(1, sizeof(*pu)))) 
318                 return -1;
319
320         /* Lock parking lot */
321         ast_mutex_lock(&parking_lock);
322         /* Check for channel variable PARKINGEXTEN */
323         parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
324         if (!ast_strlen_zero(parkingexten)) {
325                 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
326                         ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
327                         return 0;       /* Continue execution if possible */
328                 }
329                 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
330         } else {
331                 /* Select parking space within range */
332                 parking_range = parking_stop - parking_start+1;
333                 for (i = 0; i < parking_range; i++) {
334                         x = (i + parking_offset) % parking_range + parking_start;
335                         cur = parkinglot;
336                         while(cur) {
337                                 if (cur->parkingnum == x) 
338                                         break;
339                                 cur = cur->next;
340                         }
341                         if (!cur)
342                                 break;
343                 }
344
345                 if (!(i < parking_range)) {
346                         ast_log(LOG_WARNING, "No more parking spaces\n");
347                         free(pu);
348                         ast_mutex_unlock(&parking_lock);
349                         return -1;
350                 }
351                 /* Set pointer for next parking */
352                 if (parkfindnext) 
353                         parking_offset = x - parking_start + 1;
354         }
355         
356         chan->appl = "Parked Call";
357         chan->data = NULL; 
358
359         pu->chan = chan;
360         
361         /* Start music on hold if we have two different channels */
362         if (chan != peer) {
363                 ast_indicate(pu->chan, AST_CONTROL_HOLD);       /* Indicate to peer that we're on hold */
364                 ast_moh_start(pu->chan, NULL);
365         }
366         pu->start = ast_tvnow();
367         pu->parkingnum = x;
368         pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
369         if (extout)
370                 *extout = x;
371
372         if (peer) 
373                 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
374
375         /* Remember what had been dialed, so that if the parking
376            expires, we try to come back to the same place */
377         ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
378         ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
379         pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
380         pu->next = parkinglot;
381         parkinglot = pu;
382
383         /* If parking a channel directly, don't quiet yet get parking running on it */
384         if (peer == chan) 
385                 pu->notquiteyet = 1;
386         ast_mutex_unlock(&parking_lock);
387         /* Wake up the (presumably select()ing) thread */
388         pthread_kill(parking_thread, SIGURG);
389         if (option_verbose > 1) 
390                 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));
391
392         if (pu->parkingnum != -1)
393                 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
394         manager_event(EVENT_FLAG_CALL, "ParkedCall",
395                 "Exten: %s\r\n"
396                 "Channel: %s\r\n"
397                 "From: %s\r\n"
398                 "Timeout: %ld\r\n"
399                 "CallerID: %s\r\n"
400                 "CallerIDName: %s\r\n",
401                 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
402                 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
403                 S_OR(pu->chan->cid.cid_num, "<unknown>"),
404                 S_OR(pu->chan->cid.cid_name, "<unknown>")
405                 );
406
407         if (peer && adsipark && adsi_available(peer)) {
408                 adsi_announce_park(peer, pu->parkingexten);     /* Only supports parking numbers */
409                 adsi_unload_session(peer);
410         }
411
412         con = ast_context_find(parking_con);
413         if (!con) 
414                 con = ast_context_create(NULL, parking_con, registrar);
415         if (!con)       /* Still no context? Bad */
416                 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
417         else {          /* Add extension to context */
418                 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), FREE, registrar))
419                         notify_metermaids(pu->parkingexten, parking_con);
420         }
421         /* Tell the peer channel the number of the parking space */
422         if (peer && !pu->parkingnum == -1) /* Only say number if it's a number */
423                 ast_say_digits(peer, pu->parkingnum, "", peer->language);
424         if (pu->notquiteyet) {
425                 /* Wake up parking thread if we're really done */
426                 ast_moh_start(pu->chan, NULL);
427                 pu->notquiteyet = 0;
428                 pthread_kill(parking_thread, SIGURG);
429         }
430         return 0;
431 }
432
433 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
434 {
435         struct ast_channel *chan;
436         struct ast_frame *f;
437
438         /* Make a new, fake channel that we'll use to masquerade in the real one */
439         if (!(chan = ast_channel_alloc(0))) {
440                 ast_log(LOG_WARNING, "Unable to create parked channel\n");
441                 return -1;
442         }
443         /* Let us keep track of the channel name */
444         ast_string_field_build(chan, name, "Parked/%s",rchan->name);
445
446         /* Make formats okay */
447         chan->readformat = rchan->readformat;
448         chan->writeformat = rchan->writeformat;
449         ast_channel_masquerade(chan, rchan);
450
451         /* Setup the extensions and such */
452         set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
453
454         /* Make the masq execute */
455         f = ast_read(chan);
456         if (f)
457                 ast_frfree(f);
458
459         ast_park_call(chan, peer, timeout, extout);
460         return 0;
461 }
462
463
464 #define FEATURE_RETURN_HANGUP           -1
465 #define FEATURE_RETURN_SUCCESSBREAK      0
466 #define FEATURE_RETURN_PBX_KEEPALIVE    AST_PBX_KEEPALIVE
467 #define FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER
468 #define FEATURE_RETURN_PASSDIGITS        21
469 #define FEATURE_RETURN_STOREDIGITS       22
470 #define FEATURE_RETURN_SUCCESS           23
471
472 #define FEATURE_SENSE_CHAN      (1 << 0)
473 #define FEATURE_SENSE_PEER      (1 << 1)
474
475 /*! \brief
476  * set caller and callee according to the direction
477  */
478 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
479         struct ast_channel *peer, struct ast_channel *chan, int sense)
480 {
481         if (sense == FEATURE_SENSE_PEER) {
482                 *caller = peer;
483                 *callee = chan;
484         } else {
485                 *callee = peer;
486                 *caller = chan;
487         }
488 }
489
490 /*! \brief support routing for one touch call parking */
491 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
492 {
493         struct ast_channel *parker;
494         struct ast_channel *parkee;
495
496         int res=0;
497         struct localuser *u;
498         LOCAL_USER_ADD(u);
499
500         set_peers(&parker, &parkee, peer, chan, sense);
501         /* Setup the exten/priority to be s/1 since we don't know
502            where this call should return */
503         strcpy(chan->exten, "s");
504         chan->priority = 1;
505         if (chan->_state != AST_STATE_UP)
506                 res = ast_answer(chan);
507         if (!res)
508                 res = ast_safe_sleep(chan, 1000);
509         if (!res)
510                 res = ast_park_call(parkee, parker, 0, NULL);
511         LOCAL_USER_REMOVE(u);
512         if (!res) {
513                 if (sense == FEATURE_SENSE_CHAN)
514                         res = AST_PBX_NO_HANGUP_PEER;
515                 else
516                         res = AST_PBX_KEEPALIVE;
517         }
518         return res;
519
520 }
521
522 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
523 {
524         char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
525         int x = 0;
526         size_t len;
527         struct ast_channel *caller_chan, *callee_chan;
528
529         if (!monitor_ok) {
530                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
531                 return -1;
532         }
533
534         if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
535                 monitor_ok = 0;
536                 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
537                 return -1;
538         }
539
540         set_peers(&caller_chan, &callee_chan, peer, chan, sense);
541
542         if (!ast_strlen_zero(courtesytone)) {
543                 if (ast_autoservice_start(callee_chan))
544                         return -1;
545                 if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
546                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
547                         ast_autoservice_stop(callee_chan);
548                         return -1;
549                 }
550                 if (ast_autoservice_stop(callee_chan))
551                         return -1;
552         }
553         
554         if (callee_chan->monitor) {
555                 if (option_verbose > 3)
556                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
557                 ast_monitor_stop(callee_chan, 1);
558                 return FEATURE_RETURN_SUCCESS;
559         }
560
561         if (caller_chan && callee_chan) {
562                 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
563                 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
564
565                 if (!touch_format)
566                         touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
567
568                 if (!touch_monitor)
569                         touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
570         
571                 if (touch_monitor) {
572                         len = strlen(touch_monitor) + 50;
573                         args = alloca(len);
574                         touch_filename = alloca(len);
575                         snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
576                         snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
577                 } else {
578                         caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
579                         callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
580                         len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
581                         args = alloca(len);
582                         touch_filename = alloca(len);
583                         snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
584                         snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
585                 }
586
587                 for( x = 0; x < strlen(args); x++) {
588                         if (args[x] == '/')
589                                 args[x] = '-';
590                 }
591                 
592                 if (option_verbose > 3)
593                         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
594
595                 pbx_exec(callee_chan, monitor_app, args);
596                 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
597                 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
598         
599                 return FEATURE_RETURN_SUCCESS;
600         }
601         
602         ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");   
603         return -1;
604 }
605
606 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
607 {
608         if (option_verbose > 3)
609                 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
610         return FEATURE_RETURN_HANGUP;
611 }
612
613 static int finishup(struct ast_channel *chan)
614 {
615         int res;
616   
617         ast_moh_stop(chan);
618         res = ast_autoservice_stop(chan);
619         ast_indicate(chan, AST_CONTROL_UNHOLD);
620         return res;
621 }
622
623 /*! \brief Find the context for the transfer */
624 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
625 {
626         const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
627         if (ast_strlen_zero(s))
628                 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
629         if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
630                 s = transferer->macrocontext;
631         if (ast_strlen_zero(s))
632                 s = transferer->context;
633         return s;  
634 }
635
636 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
637 {
638         struct ast_channel *transferer;
639         struct ast_channel *transferee;
640         const char *transferer_real_context;
641         char xferto[256];
642         int res;
643
644         set_peers(&transferer, &transferee, peer, chan, sense);
645         transferer_real_context = real_ctx(transferer, transferee);
646         /* Start autoservice on chan while we talk to the originator */
647         ast_indicate(transferee, AST_CONTROL_HOLD);
648         ast_autoservice_start(transferee);
649         ast_moh_start(transferee, NULL);
650
651         memset(xferto, 0, sizeof(xferto));
652         
653         /* Transfer */
654         res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
655         if (res < 0) {
656                 finishup(transferee);
657                 return -1; /* error ? */
658         }
659         if (res > 0)    /* If they've typed a digit already, handle it */
660                 xferto[0] = (char) res;
661
662         ast_stopstream(transferer);
663         res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
664         if (res < 0) {  /* hangup, would be 0 for invalid and 1 for valid */
665                 finishup(transferee);
666                 return res;
667         }
668         if (!strcmp(xferto, ast_parking_ext())) {
669                 res = finishup(transferee);
670                 if (res)
671                         res = -1;
672                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {     /* success */
673                         /* We return non-zero, but tell the PBX not to hang the channel when
674                            the thread dies -- We have to be careful now though.  We are responsible for 
675                            hanging up the channel, else it will never be hung up! */
676
677                         return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
678                 } else {
679                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
680                 }
681                 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
682         } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
683                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
684                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
685                 res=finishup(transferee);
686                 if (!transferee->pbx) {
687                         /* Doh!  Use our handy async_goto functions */
688                         if (option_verbose > 2) 
689                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
690                                                                 ,transferee->name, xferto, transferer_real_context);
691                         if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
692                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
693                         res = -1;
694                 } else {
695                         /* Set the channel's new extension, since it exists, using transferer context */
696                         set_c_e_p(transferee, transferer_real_context, xferto, 0);
697                 }
698                 check_goto_on_transfer(transferer);
699                 return res;
700         } else {
701                 if (option_verbose > 2) 
702                         ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
703         }
704         if (ast_stream_and_wait(transferer, xferfailsound, transferer->language, AST_DIGIT_ANY) < 0 ) {
705                 finishup(transferee);
706                 return -1;
707         }
708         ast_stopstream(transferer);
709         res = finishup(transferee);
710         if (res) {
711                 if (option_verbose > 1)
712                         ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
713                 return res;
714         }
715         return FEATURE_RETURN_SUCCESS;
716 }
717
718 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
719 {
720         if (ast_channel_make_compatible(c, newchan) < 0) {
721                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
722                         c->name, newchan->name);
723                 ast_hangup(newchan);
724                 return -1;
725         }
726         return 0;
727 }
728
729 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
730 {
731         struct ast_channel *transferer;
732         struct ast_channel *transferee;
733         const char *transferer_real_context;
734         char xferto[256];
735         int res;
736         int outstate=0;
737         struct ast_channel *newchan;
738         struct ast_channel *xferchan;
739         struct ast_bridge_thread_obj *tobj;
740         struct ast_bridge_config bconfig;
741         struct ast_frame *f;
742         int l;
743
744         if (option_debug)
745                 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
746         set_peers(&transferer, &transferee, peer, chan, sense);
747         transferer_real_context = real_ctx(transferer, transferee);
748         /* Start autoservice on chan while we talk to the originator */
749         ast_indicate(transferee, AST_CONTROL_HOLD);
750         ast_autoservice_start(transferee);
751         ast_moh_start(transferee, NULL);
752         memset(xferto, 0, sizeof(xferto));
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_moh_stop(transferee);
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                                 /* Stop music on hold */
1525                                 ast_moh_stop(chan);
1526                                 ast_indicate(chan, AST_CONTROL_UNHOLD);
1527                                 /* Get chan, exten from derived kludge */
1528                                 if (pu->peername[0]) {
1529                                         char *peername = ast_strdupa(pu->peername);
1530                                         char *cp = strrchr(peername, '-');
1531                                         if (cp) 
1532                                                 *cp = 0;
1533                                         con = ast_context_find(parking_con_dial);
1534                                         if (!con) {
1535                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
1536                                                 if (!con)
1537                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1538                                         }
1539                                         if (con) {
1540                                                 char returnexten[AST_MAX_EXTENSION];
1541                                                 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1542                                                 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
1543                                         }
1544                                         set_c_e_p(chan, parking_con_dial, peername, 1);
1545                                 } else {
1546                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
1547                                            should have their original extensions and such, but we copy to be on the safe side */
1548                                         set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1549                                 }
1550
1551                                 post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
1552
1553                                 if (option_verbose > 1) 
1554                                         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);
1555                                 /* Start up the PBX, or hang them up */
1556                                 if (ast_pbx_start(chan))  {
1557                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1558                                         ast_hangup(chan);
1559                                 }
1560                                 /* And take them out of the parking lot */
1561                                 if (pl) 
1562                                         pl->next = pu->next;
1563                                 else
1564                                         parkinglot = pu->next;
1565                                 pt = pu;
1566                                 pu = pu->next;
1567                                 con = ast_context_find(parking_con);
1568                                 if (con) {
1569                                         if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1570                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1571                                         else
1572                                                 notify_metermaids(pu->parkingexten, parking_con);
1573                                 } else
1574                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1575                                 free(pt);
1576                         } else {        /* still within parking time, process descriptors */
1577                                 for (x = 0; x < AST_MAX_FDS; x++) {
1578                                         struct ast_frame *f;
1579
1580                                         if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1581                                                 continue;       /* nothing on this descriptor */
1582
1583                                         if (FD_ISSET(chan->fds[x], &efds))
1584                                                 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1585                                         else
1586                                                 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1587                                         chan->fdno = x;
1588
1589                                         /* See if they need servicing */
1590                                         f = ast_read(chan);
1591                                         if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass ==  AST_CONTROL_HANGUP)) {
1592                                                 if (f)
1593                                                         ast_frfree(f);
1594                                                 post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
1595
1596                                                 /* There's a problem, hang them up*/
1597                                                 if (option_verbose > 1) 
1598                                                         ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1599                                                 ast_hangup(chan);
1600                                                 /* And take them out of the parking lot */
1601                                                 if (pl) 
1602                                                         pl->next = pu->next;
1603                                                 else
1604                                                         parkinglot = pu->next;
1605                                                 pt = pu;
1606                                                 pu = pu->next;
1607                                                 con = ast_context_find(parking_con);
1608                                                 if (con) {
1609                                                         if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
1610                                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1611                                                 else
1612                                                         notify_metermaids(pt->parkingexten, parking_con);
1613                                                 } else
1614                                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1615                                                 free(pt);
1616                                                 break;
1617                                         } else {
1618                                                 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1619                                                 ast_frfree(f);
1620                                                 if (pu->moh_trys < 3 && !chan->generatordata) {
1621                                                         if (option_debug)
1622                                                                 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source.  Restarting.\n");
1623                                                         ast_moh_start(chan, NULL);
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_moh_stop(peer);
1752                         ast_indicate(peer, AST_CONTROL_UNHOLD);
1753                         if (parkedplay == 0) {
1754                                 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
1755                         } else if (parkedplay == 1) {
1756                                 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
1757                         } else if (parkedplay == 2) {
1758                                 if (!ast_streamfile(chan, courtesytone, chan->language) &&
1759                                                 !ast_streamfile(peer, courtesytone, chan->language)) {
1760                                         /*! \todo XXX we would like to wait on both! */
1761                                         res = ast_waitstream(chan, "");
1762                                         if (res >= 0)
1763                                                 res = ast_waitstream(peer, "");
1764                                         if (res < 0)
1765                                                 error = 1;
1766                                 }
1767                         }
1768                         if (error) {
1769                                 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1770                                 ast_hangup(peer);
1771                                 return -1;
1772                         }
1773                 } else {
1774                         ast_moh_stop(peer);
1775                         ast_indicate(peer, AST_CONTROL_UNHOLD); 
1776                 }
1777
1778                 res = ast_channel_make_compatible(chan, peer);
1779                 if (res < 0) {
1780                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1781                         ast_hangup(peer);
1782                         return -1;
1783                 }
1784                 /* This runs sorta backwards, since we give the incoming channel control, as if it
1785                    were the person called. */
1786                 if (option_verbose > 2) 
1787                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1788
1789                 memset(&config, 0, sizeof(struct ast_bridge_config));
1790                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1791                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1792                 config.timelimit = 0;
1793                 config.play_warning = 0;
1794                 config.warning_freq = 0;
1795                 config.warning_sound=NULL;
1796                 res = ast_bridge_call(chan, peer, &config);
1797
1798                 /* Simulate the PBX hanging up */
1799                 if (res != AST_PBX_NO_HANGUP_PEER)
1800                         ast_hangup(peer);
1801                 return res;
1802         } else {
1803                 /*! \todo XXX Play a message XXX */
1804                 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
1805                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1806                 if (option_verbose > 2) 
1807                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1808                 res = -1;
1809         }
1810         LOCAL_USER_REMOVE(u);
1811         return res;
1812 }
1813
1814 static int handle_showfeatures(int fd, int argc, char *argv[])
1815 {
1816         int i;
1817         int fcount;
1818         struct ast_call_feature *feature;
1819         char format[] = "%-25s %-7s %-7s\n";
1820
1821         ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1822         ast_cli(fd, format, "---------------", "-------", "-------");
1823
1824         ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());          /* default hardcoded above, so we'll hardcode it here */
1825
1826         fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1827
1828         for (i = 0; i < fcount; i++)
1829         {
1830                 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1831         }
1832         ast_cli(fd, "\n");
1833         ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1834         ast_cli(fd, format, "---------------", "-------", "-------");
1835         if (AST_LIST_EMPTY(&feature_list)) {
1836                 ast_cli(fd, "(none)\n");
1837         }
1838         else {
1839                 AST_LIST_LOCK(&feature_list);
1840                 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1841                         ast_cli(fd, format, feature->sname, "no def", feature->exten);  
1842                 }
1843                 AST_LIST_UNLOCK(&feature_list);
1844         }
1845         ast_cli(fd, "\nCall parking\n");
1846         ast_cli(fd, "------------\n");
1847         ast_cli(fd,"%-20s:      %s\n", "Parking extension", parking_ext);
1848         ast_cli(fd,"%-20s:      %s\n", "Parking context", parking_con);
1849         ast_cli(fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1850         ast_cli(fd,"\n");
1851         
1852         return RESULT_SUCCESS;
1853 }
1854
1855 static char showfeatures_help[] =
1856 "Usage: show features\n"
1857 "       Lists currently configured features.\n";
1858
1859 static struct ast_cli_entry showfeatures =
1860 { { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
1861
1862 static int handle_parkedcalls(int fd, int argc, char *argv[])
1863 {
1864         struct parkeduser *cur;
1865         int numparked = 0;
1866
1867         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1868                 , "Context", "Extension", "Pri", "Timeout");
1869
1870         ast_mutex_lock(&parking_lock);
1871
1872         for (cur = parkinglot; cur; cur = cur->next) {
1873                 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
1874                         ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
1875                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1876
1877                 numparked++;
1878         }
1879         ast_mutex_unlock(&parking_lock);
1880         ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
1881
1882
1883         return RESULT_SUCCESS;
1884 }
1885
1886 static char showparked_help[] =
1887 "Usage: show parkedcalls\n"
1888 "       Lists currently parked calls.\n";
1889
1890 static struct ast_cli_entry showparked =
1891 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1892
1893 /*! \brief Dump lot status */
1894 static int manager_parking_status( struct mansession *s, struct message *m )
1895 {
1896         struct parkeduser *cur;
1897         char *id = astman_get_header(m,"ActionID");
1898         char idText[256] = "";
1899
1900         if (!ast_strlen_zero(id))
1901                 snprintf(idText, 256, "ActionID: %s\r\n", id);
1902
1903         astman_send_ack(s, m, "Parked calls will follow");
1904
1905         ast_mutex_lock(&parking_lock);
1906
1907         for (cur=parkinglot; cur; cur = cur->next) {
1908                 astman_append(s, "Event: ParkedCall\r\n"
1909                         "Exten: %d\r\n"
1910                         "Channel: %s\r\n"
1911                         "From: %s\r\n"
1912                         "Timeout: %ld\r\n"
1913                         "CallerID: %s\r\n"
1914                         "CallerIDName: %s\r\n"
1915                         "%s"
1916                         "\r\n",
1917                         cur->parkingnum, cur->chan->name, cur->peername,
1918                         (long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL),
1919                         S_OR(cur->chan->cid.cid_num, ""),       /* XXX in other places it is <unknown> */
1920                         S_OR(cur->chan->cid.cid_name, ""),
1921                         idText);
1922         }
1923
1924         astman_append(s,
1925                 "Event: ParkedCallsComplete\r\n"
1926                 "%s"
1927                 "\r\n",idText);
1928
1929         ast_mutex_unlock(&parking_lock);
1930
1931         return RESULT_SUCCESS;
1932 }
1933
1934 static char mandescr_park[] =
1935 "Description: Park a channel.\n"
1936 "Variables: (Names marked with * are required)\n"
1937 "       *Channel: Channel name to park\n"
1938 "       *Channel2: Channel to announce park info to (and return to if timeout)\n"
1939 "       Timeout: Number of milliseconds to wait before callback.\n";  
1940
1941 static int manager_park(struct mansession *s, struct message *m)
1942 {
1943         char *channel = astman_get_header(m, "Channel");
1944         char *channel2 = astman_get_header(m, "Channel2");
1945         char *timeout = astman_get_header(m, "Timeout");
1946         char buf[BUFSIZ];
1947         int to = 0;
1948         int res = 0;
1949         int parkExt = 0;
1950         struct ast_channel *ch1, *ch2;
1951
1952         if (ast_strlen_zero(channel)) {
1953                 astman_send_error(s, m, "Channel not specified");
1954                 return 0;
1955         }
1956
1957         if (ast_strlen_zero(channel2)) {
1958                 astman_send_error(s, m, "Channel2 not specified");
1959                 return 0;
1960         }
1961
1962         ch1 = ast_get_channel_by_name_locked(channel);
1963         if (!ch1) {
1964                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
1965                 astman_send_error(s, m, buf);
1966                 return 0;
1967         }
1968
1969         ch2 = ast_get_channel_by_name_locked(channel2);
1970         if (!ch2) {
1971                 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
1972                 astman_send_error(s, m, buf);
1973                 ast_channel_unlock(ch1);
1974                 return 0;
1975         }
1976
1977         if (!ast_strlen_zero(timeout)) {
1978                 sscanf(timeout, "%d", &to);
1979         }
1980
1981         res = ast_masq_park_call(ch1, ch2, to, &parkExt);
1982         if (!res) {
1983                 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
1984                 astman_send_ack(s, m, "Park successful");
1985         } else {
1986                 astman_send_error(s, m, "Park failure");
1987         }
1988
1989         ast_channel_unlock(ch1);
1990         ast_channel_unlock(ch2);
1991
1992         return 0;
1993 }
1994
1995
1996 int ast_pickup_call(struct ast_channel *chan)
1997 {
1998         struct ast_channel *cur = NULL;
1999         int res = -1;
2000
2001         while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
2002                 if (!cur->pbx && 
2003                         (cur != chan) &&
2004                         (chan->pickupgroup & cur->callgroup) &&
2005                         ((cur->_state == AST_STATE_RINGING) ||
2006                          (cur->_state == AST_STATE_RING))) {
2007                                 break;
2008                 }
2009                 ast_channel_unlock(cur);
2010         }
2011         if (cur) {
2012                 if (option_debug)
2013                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2014                 res = ast_answer(chan);
2015                 if (res)
2016                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2017                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2018                 if (res)
2019                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2020                 res = ast_channel_masquerade(cur, chan);
2021                 if (res)
2022                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
2023                 ast_channel_unlock(cur);
2024         } else  {
2025                 if (option_debug)
2026                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
2027         }
2028         return res;
2029 }
2030
2031 /*! \brief Add parking hints for all defined parking lots */
2032 static void park_add_hints(char *context, int start, int stop)
2033 {
2034         int numext;
2035         char device[AST_MAX_EXTENSION];
2036         char exten[10];
2037
2038         for (numext = start; numext <= stop; numext++) {
2039                 snprintf(exten, sizeof(exten), "%d", numext);
2040                 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2041                 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2042         }
2043 }
2044
2045
2046 static int load_config(void) 
2047 {
2048         int start = 0, end = 0;
2049         int res;
2050         struct ast_context *con = NULL;
2051         struct ast_config *cfg = NULL;
2052         struct ast_variable *var = NULL;
2053         char old_parking_ext[AST_MAX_EXTENSION];
2054         char old_parking_con[AST_MAX_EXTENSION] = "";
2055
2056         if (!ast_strlen_zero(parking_con)) {
2057                 strcpy(old_parking_ext, parking_ext);
2058                 strcpy(old_parking_con, parking_con);
2059         } 
2060
2061         /* Reset to defaults */
2062         strcpy(parking_con, "parkedcalls");
2063         strcpy(parking_con_dial, "park-dial");
2064         strcpy(parking_ext, "700");
2065         strcpy(pickup_ext, "*8");
2066         courtesytone[0] = '\0';
2067         strcpy(xfersound, "beep");
2068         strcpy(xferfailsound, "pbx-invalid");
2069         parking_start = 701;
2070         parking_stop = 750;
2071         parkfindnext = 0;
2072         adsipark = 0;
2073         parkaddhints = 0;
2074
2075         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2076         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2077         atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2078
2079         cfg = ast_config_load("features.conf");
2080         if (cfg) {
2081                 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2082                         if (!strcasecmp(var->name, "parkext")) {
2083                                 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2084                         } else if (!strcasecmp(var->name, "context")) {
2085                                 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2086                         } else if (!strcasecmp(var->name, "parkingtime")) {
2087                                 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2088                                         ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2089                                         parkingtime = DEFAULT_PARK_TIME;
2090                                 } else
2091                                         parkingtime = parkingtime * 1000;
2092                         } else if (!strcasecmp(var->name, "parkpos")) {
2093                                 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2094                                         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);
2095                                 } else {
2096                                         parking_start = start;
2097                                         parking_stop = end;
2098                                 }
2099                         } else if (!strcasecmp(var->name, "findslot")) {
2100                                 parkfindnext = (!strcasecmp(var->value, "next"));
2101                         } else if (!strcasecmp(var->name, "parkinghints")) {
2102                                 parkaddhints = ast_true(var->value);
2103                         } else if (!strcasecmp(var->name, "adsipark")) {
2104                                 adsipark = ast_true(var->value);
2105                         } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2106                                 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2107                                         ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2108                                         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2109                                 } else
2110                                         transferdigittimeout = transferdigittimeout * 1000;
2111                         } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2112                                 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2113                                         ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2114                                         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2115                                 }
2116                         } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2117                                 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2118                                         ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2119                                         atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2120                                 } else
2121                                         atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2122                         } else if (!strcasecmp(var->name, "courtesytone")) {
2123                                 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2124                         }  else if (!strcasecmp(var->name, "parkedplay")) {
2125                                 if (!strcasecmp(var->value, "both"))
2126                                         parkedplay = 2;
2127                                 else if (!strcasecmp(var->value, "parked"))
2128                                         parkedplay = 1;
2129                                 else
2130                                         parkedplay = 0;
2131                         } else if (!strcasecmp(var->name, "xfersound")) {
2132                                 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2133                         } else if (!strcasecmp(var->name, "xferfailsound")) {
2134                                 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2135                         } else if (!strcasecmp(var->name, "pickupexten")) {
2136                                 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
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);