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