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