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