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