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