allow sounds to be configurable
[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-2004, 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 <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/app.h>
23 #include <asterisk/say.h>
24 #include <asterisk/channel_pvt.h>
25 #include <asterisk/features.h>
26 #include <asterisk/musiconhold.h>
27 #include <asterisk/config.h>
28 #include <asterisk/cli.h>
29 #include <asterisk/manager.h>
30 #include <asterisk/utils.h>
31 #include <asterisk/adsi.h>
32 #include <pthread.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <sys/time.h>
40 #include <sys/signal.h>
41 #include <netinet/in.h>
42
43 #define DEFAULT_PARK_TIME 45000
44 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
45 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
46
47 static char *parkedcall = "ParkedCall";
48
49 /* No more than 45 seconds parked before you do something with them */
50 static int parkingtime = DEFAULT_PARK_TIME;
51
52 /* Context for which parking is made accessible */
53 static char parking_con[AST_MAX_EXTENSION] = "parkedcalls";
54
55 /* Context for dialback for parking (KLUDGE) */
56 static char parking_con_dial[AST_MAX_EXTENSION] = "park-dial";
57
58 /* Extension you type to park the call */
59 static char parking_ext[AST_MAX_EXTENSION] = "700";
60
61 static char pickup_ext[AST_MAX_EXTENSION] = "*8";
62
63 /* First available extension for parking */
64 static int parking_start = 701;
65
66 /* Last available extension for parking */
67 static int parking_stop = 750;
68
69 static int adsipark = 0;
70
71 static int transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
72 static int featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
73
74 /* Default courtesy tone played when party joins conference */
75 static char courtesytone[256] = "";
76
77 /* Default sounds */
78 static char xfersound[256] = "beep";
79 static char xferfailsound[256] = "beeperr";
80
81
82 /* Registrar for operations */
83 static char *registrar = "res_features";
84
85 static char *synopsis = "Answer a parked call";
86
87 static char *descrip = "ParkedCall(exten):"
88 "Used to connect to a parked call.  This application is always\n"
89 "registered internally and does not need to be explicitly added\n"
90 "into the dialplan, although you should include the 'parkedcalls'\n"
91 "context.\n";
92
93 static char *parkcall = "Park";
94
95 static char *synopsis2 = "Park yourself";
96
97 static char *descrip2 = "Park(exten):"
98 "Used to park yourself (typically in combination with a supervised\n"
99 "transfer to know the parking space). This application is always\n"
100 "registered internally and does not need to be explicitly added\n"
101 "into the dialplan, although you should include the 'parkedcalls'\n"
102 "context.\n";
103
104 static struct ast_app *monitor_app=NULL;
105 static int monitor_ok=1;
106
107 struct parkeduser {
108         struct ast_channel *chan;
109         struct timeval start;
110         int parkingnum;
111         /* Where to go if our parking time expires */
112         char context[AST_MAX_EXTENSION];
113         char exten[AST_MAX_EXTENSION];
114         int priority;
115         int parkingtime;
116         int notquiteyet;
117         char peername[1024];
118         struct parkeduser *next;
119 };
120
121 static struct parkeduser *parkinglot;
122
123 AST_MUTEX_DEFINE_STATIC(parking_lock);
124
125 static pthread_t parking_thread;
126
127 STANDARD_LOCAL_USER;
128
129 LOCAL_USER_DECL;
130
131 char *ast_parking_ext(void)
132 {
133         return parking_ext;
134 }
135
136 char *ast_pickup_ext(void)
137 {
138         return pickup_ext;
139 }
140
141 struct ast_bridge_thread_obj 
142 {
143         struct ast_bridge_config bconfig;
144         struct ast_channel *chan;
145         struct ast_channel *peer;
146 };
147
148 static void *ast_bridge_call_thread(void *data) 
149 {
150         struct ast_bridge_thread_obj *tobj = data;
151         tobj->chan->appl = "Transferred Call";
152         tobj->chan->data = tobj->peer->name;
153         tobj->peer->appl = "Transferred Call";
154         tobj->peer->data = tobj->chan->name;
155         if (tobj->chan->cdr) {
156                 ast_cdr_reset(tobj->chan->cdr,0);
157                 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
158         }
159         if (tobj->peer->cdr) {
160                 ast_cdr_reset(tobj->peer->cdr,0);
161                 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
162         }
163
164
165         ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
166         ast_hangup(tobj->chan);
167         ast_hangup(tobj->peer);
168         tobj->chan = tobj->peer = NULL;
169         free(tobj);
170         tobj=NULL;
171         return NULL;
172 }
173
174 static void ast_bridge_call_thread_launch(void *data) 
175 {
176         pthread_t thread;
177         pthread_attr_t attr;
178         int result;
179
180         result = pthread_attr_init(&attr);
181         pthread_attr_setschedpolicy(&attr, SCHED_RR);
182         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
183         result = ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
184         result = pthread_attr_destroy(&attr);
185 }
186
187
188
189 static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
190 {
191         int res;
192         int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
193         char tmp[256] = "";
194         char *message[5] = {NULL, NULL, NULL, NULL, NULL};
195
196         snprintf(tmp, sizeof(tmp), "Parked on %d", parkingnum);
197         message[0] = tmp;
198         res = adsi_load_session(chan, NULL, 0, 1);
199         if (res == -1) {
200                 return res;
201         }
202         return adsi_print(chan, message, justify, 1);
203 }
204
205 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
206 {
207         /* We put the user in the parking list, then wake up the parking thread to be sure it looks
208            after these channels too */
209         struct parkeduser *pu, *cur;
210         int x;
211         char exten[AST_MAX_EXTENSION];
212         struct ast_context *con;
213         pu = malloc(sizeof(struct parkeduser));
214         if (pu) {
215                 memset(pu,0,sizeof(struct parkeduser));
216                 ast_mutex_lock(&parking_lock);
217                 for (x=parking_start;x<=parking_stop;x++) {
218                         cur = parkinglot;
219                         while(cur) {
220                                 if (cur->parkingnum == x) 
221                                         break;
222                                 cur = cur->next;
223                         }
224                         if (!cur)
225                                 break;
226                 }
227                 if (x <= parking_stop) {
228                         chan->appl = "Parked Call";
229                         chan->data = NULL; 
230
231                         pu->chan = chan;
232                         /* Start music on hold */
233                         if (chan != peer)
234                                 ast_moh_start(pu->chan, NULL);
235                         gettimeofday(&pu->start, NULL);
236                         pu->parkingnum = x;
237                         if (timeout > 0)
238                                 pu->parkingtime = timeout;
239                         else
240                                 pu->parkingtime = parkingtime;
241                         if (extout)
242                                 *extout = x;
243                         if (peer)
244                         {
245                                 strncpy(pu->peername,peer->name,sizeof(pu->peername) - 1);
246                         }
247                         /* Remember what had been dialed, so that if the parking
248                            expires, we try to come back to the same place */
249                         if (!ast_strlen_zero(chan->macrocontext))
250                                 strncpy(pu->context, chan->macrocontext, sizeof(pu->context)-1);
251                         else
252                                 strncpy(pu->context, chan->context, sizeof(pu->context)-1);
253                         if (!ast_strlen_zero(chan->macroexten))
254                                 strncpy(pu->exten, chan->macroexten, sizeof(pu->exten)-1);
255                         else
256                                 strncpy(pu->exten, chan->exten, sizeof(pu->exten)-1);
257                         if (chan->macropriority)
258                                 pu->priority = chan->macropriority;
259                         else
260                                 pu->priority = chan->priority;
261                         pu->next = parkinglot;
262                         parkinglot = pu;
263                         /* If parking a channel directly, don't quiet yet get parking running on it */
264                         if (peer == chan) 
265                                 pu->notquiteyet = 1;
266                         ast_mutex_unlock(&parking_lock);
267                         /* Wake up the (presumably select()ing) thread */
268                         pthread_kill(parking_thread, SIGURG);
269                         if (option_verbose > 1) 
270                                 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));
271
272                         manager_event(EVENT_FLAG_CALL, "ParkedCall",
273                                 "Exten: %d\r\n"
274                                 "Channel: %s\r\n"
275                                 "From: %s\r\n"
276                                 "Timeout: %ld\r\n"
277                                 "CallerID: %s\r\n"
278                                 "CallerIDName: %s\r\n\r\n"
279                                 ,pu->parkingnum, pu->chan->name, peer->name
280                                 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
281                                 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "")
282                                 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "")
283                                 );
284
285                         if (peer) {
286                                 if (adsipark && adsi_available(peer)) {
287                                         adsi_announce_park(peer, pu->parkingnum);
288                                 }
289                                 if (adsipark && adsi_available(peer)) {
290                                         adsi_unload_session(peer);
291                                 }
292                                 if (pu->notquiteyet) {
293                                         /* Wake up parking thread if we're really done */
294                                         ast_moh_start(pu->chan, NULL);
295                                         pu->notquiteyet = 0;
296                                         pthread_kill(parking_thread, SIGURG);
297                                 }
298                         }
299                         con = ast_context_find(parking_con);
300                         if (!con) {
301                                 con = ast_context_create(NULL,parking_con, registrar);
302                                 if (!con) {
303                                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
304                                 }
305                         }
306                         if (con) {
307                                 snprintf(exten, sizeof(exten), "%d", x);
308                                 ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), free, registrar);
309                         }
310                         if (peer) ast_say_digits(peer, pu->parkingnum, "", peer->language);
311                         return 0;
312                 } else {
313                         ast_log(LOG_WARNING, "No more parking spaces\n");
314                         free(pu);
315                         ast_mutex_unlock(&parking_lock);
316                         return -1;
317                 }
318         } else {
319                 ast_log(LOG_WARNING, "Out of memory\n");
320                 return -1;
321         }
322         return 0;
323 }
324
325 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
326 {
327         struct ast_channel *chan;
328         struct ast_frame *f;
329         /* Make a new, fake channel that we'll use to masquerade in the real one */
330         chan = ast_channel_alloc(0);
331         if (chan) {
332                 /* Let us keep track of the channel name */
333                 snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name);
334                 /* Make formats okay */
335                 chan->readformat = rchan->readformat;
336                 chan->writeformat = rchan->writeformat;
337                 ast_channel_masquerade(chan, rchan);
338                 /* Setup the extensions and such */
339                 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
340                 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
341                 chan->priority = rchan->priority;
342                 /* Make the masq execute */
343                 f = ast_read(chan);
344                 if (f)
345                         ast_frfree(f);
346                 ast_park_call(chan, peer, timeout, extout);
347         } else {
348                 ast_log(LOG_WARNING, "Unable to create parked channel\n");
349                 return -1;
350         }
351         return 0;
352 }
353
354
355 #define FEATURE_RETURN_HANGUP           -1
356 #define FEATURE_RETURN_SUCCESSBREAK      0
357 #define FEATURE_RETURN_PBX_KEEPALIVE    AST_PBX_KEEPALIVE
358 #define FEATURE_RETURN_NO_HANGUP_PEER   AST_PBX_NO_HANGUP_PEER
359 #define FEATURE_RETURN_PASSDIGITS        21
360 #define FEATURE_RETURN_STOREDIGITS       22
361 #define FEATURE_RETURN_SUCCESS           23
362
363 #define FEATURE_SENSE_CHAN      (1 << 0)
364 #define FEATURE_SENSE_PEER      (1 << 1)
365 #define FEATURE_MAX_LEN         11
366
367 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
368 {
369         char *args;
370         if (option_verbose > 3)
371         ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call.\n", code);
372         if (monitor_ok) {
373                 if (!monitor_app) { 
374                         if (!(monitor_app = pbx_findapp("Monitor")))
375                                 monitor_ok=0;
376                 }
377                 /* Copy to local variable just in case one of the channels goes away */
378                 args = pbx_builtin_getvar_helper(chan, "TOUCH_MONITOR");
379                 if (!args)
380                         args = pbx_builtin_getvar_helper(peer, "TOUCH_MONITOR");
381                 if (!args)
382                         args = "WAV||m";
383
384                 pbx_exec(peer, monitor_app, args, 1);
385                 return FEATURE_RETURN_SUCCESS;
386         }
387
388         return -1;
389 }
390
391 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
392 {
393         if (option_verbose > 3)
394                 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
395         return FEATURE_RETURN_HANGUP;
396 }
397
398 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
399 {
400         struct ast_channel *transferer;
401         struct ast_channel *transferee;
402         char *transferer_real_context;
403         char newext[256], *ptr;
404         int res;
405         int len;
406
407         ast_log(LOG_NOTICE, "XXX Blind Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
408         if (sense == FEATURE_SENSE_PEER) {
409                 transferer = peer;
410                 transferee = chan;
411         } else {
412                 transferer = chan;
413                 transferee = peer;
414         }
415         if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
416            !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
417                 /* Use the non-macro context to transfer the call */
418                 if (!ast_strlen_zero(transferer->macrocontext))
419                         transferer_real_context = transferer->macrocontext;
420                 else
421                         transferer_real_context = transferer->context;
422         }
423         /* Start autoservice on chan while we talk
424            to the originator */
425         ast_autoservice_start(transferee);
426         ast_moh_start(transferee, NULL);
427
428         memset(newext, 0, sizeof(newext));
429         ptr = newext;
430
431         /* Transfer */
432         if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
433                 ast_moh_stop(transferee);
434                 ast_autoservice_stop(transferee);
435                 return res;
436         }
437         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
438                 ast_moh_stop(transferee);
439                 ast_autoservice_stop(transferee);
440                 return res;
441         }
442         ast_stopstream(transferer);
443         if (res > 0) {
444                 /* If they've typed a digit already, handle it */
445                 newext[0] = res;
446                 ptr++;
447                 len--;
448         }
449
450         res = ast_app_dtget(transferer, transferer_real_context, newext, sizeof(newext), 100, transferdigittimeout);
451         if (res < 0) {
452                 ast_moh_stop(transferee);
453                 ast_autoservice_stop(transferee);
454                 return res;
455         }
456         if (!strcmp(newext, ast_parking_ext())) {
457                 ast_moh_stop(transferee);
458
459                 if (ast_autoservice_stop(transferee))
460                         res = -1;
461                 else if (!ast_park_call(transferee, transferer, 0, NULL)) {
462                         /* We return non-zero, but tell the PBX not to hang the channel when
463                            the thread dies -- We have to be careful now though.  We are responsible for 
464                            hanging up the channel, else it will never be hung up! */
465
466                         if (transferer==peer)
467                                 res=AST_PBX_KEEPALIVE;
468                         else
469                                 res=AST_PBX_NO_HANGUP_PEER;
470                         return res;
471                 } else {
472                         ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
473                 }
474                 /* XXX Maybe we should have another message here instead of invalid extension XXX */
475         } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
476                 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
477                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
478                 ast_moh_stop(transferee);
479                 res=ast_autoservice_stop(transferee);
480                 if (!transferee->pbx) {
481                         /* Doh!  Use our handy async_goto functions */
482                         if (option_verbose > 2) 
483                                 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
484                                                                 ,transferee->name, newext, transferer_real_context);
485                         if (ast_async_goto(transferee, transferer_real_context, newext, 1))
486                                 ast_log(LOG_WARNING, "Async goto failed :-(\n");
487                         res = -1;
488                 } else {
489                         /* Set the channel's new extension, since it exists, using transferer context */
490                         strncpy(transferee->exten, newext, sizeof(transferee->exten)-1);
491                         strncpy(transferee->context, transferer_real_context, sizeof(transferee->context)-1);
492                         transferee->priority = 0;
493                 }
494                 return res;
495         } else {
496                 if (option_verbose > 2) 
497                         ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", newext, transferer_real_context);
498         }
499         res = ast_streamfile(transferer, xferfailsound, transferee->language);
500         if (res) {
501                 ast_moh_stop(transferee);
502                 ast_autoservice_stop(transferee);
503                 return res;
504         }
505         res = ast_waitstream(transferer, AST_DIGIT_ANY);
506         ast_stopstream(transferer);
507         ast_moh_stop(transferee);
508         res = ast_autoservice_stop(transferee);
509         if (res) {
510                 if (option_verbose > 1)
511                         ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
512                 return res;
513         }
514         return FEATURE_RETURN_SUCCESS;
515 }
516
517 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
518 {
519         struct ast_channel *transferer;
520         struct ast_channel *transferee;
521         struct ast_channel *newchan, *xferchan=NULL;
522         int outstate=0;
523         struct ast_bridge_config bconfig;
524         char *transferer_real_context;
525         char xferto[256],dialstr[265];
526         char *cid_num;
527         char *cid_name;
528         int res;
529         struct ast_frame *f = NULL;
530         struct ast_bridge_thread_obj *tobj;
531
532         ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
533         if (sense == FEATURE_SENSE_PEER) {
534                 transferer = peer;
535                 transferee = chan;
536         } else {
537                 transferer = chan;
538                 transferee = peer;
539         }
540         if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
541            !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
542                 /* Use the non-macro context to transfer the call */
543                 if (!ast_strlen_zero(transferer->macrocontext))
544                         transferer_real_context = transferer->macrocontext;
545                 else
546                         transferer_real_context = transferer->context;
547         }
548         /* Start autoservice on chan while we talk
549            to the originator */
550         ast_autoservice_start(transferee);
551         ast_moh_start(transferee, NULL);
552
553         /* Transfer */
554         if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
555                 ast_moh_stop(transferee);
556                 ast_autoservice_stop(transferee);
557                 return res;
558         }
559         if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
560                 ast_moh_stop(transferee);
561                 ast_autoservice_stop(transferee);
562                 return res;
563         }
564         if((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
565                 cid_num = transferer->cid.cid_num;
566                 cid_name = transferer->cid.cid_name;
567                 if (ast_exists_extension(transferer, transferer_real_context,xferto, 1, cid_num)) {
568                         snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context);
569                         if((newchan = ast_request_and_dial("Local", ast_best_codec(transferer->nativeformats), dialstr,30000, &outstate, cid_num, cid_name))) {
570                                 res = ast_channel_make_compatible(transferer, newchan);
571                                 if (res < 0) {
572                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
573                                         ast_hangup(newchan);
574                                         return -1;
575                                 }
576                                 memset(&bconfig,0,sizeof(struct ast_bridge_config));
577                                 bconfig.features_caller |= AST_FEATURE_DISCONNECT;
578                                 bconfig.features_callee |= AST_FEATURE_DISCONNECT;
579                                 res = ast_bridge_call(transferer,newchan,&bconfig);
580                                 if(newchan->_softhangup || newchan->_state != AST_STATE_UP) {
581                                         ast_hangup(newchan);
582                                         if (f) {
583                                                 ast_frfree(f);
584                                                 f = NULL;
585                                         }
586                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(transferer, xfersound, transferer->language)) {
587                                                 if (ast_waitstream(transferer, "") < 0) {
588                                                         ast_log(LOG_WARNING, "Failed to play %s\n", xfersound);
589                                                 }
590                                         }
591                                         ast_moh_stop(transferee);
592                                         ast_autoservice_stop(transferee);
593                                         transferer->_softhangup = 0;
594                                         return FEATURE_RETURN_SUCCESS;
595                                 }
596                                 
597                                 res = ast_channel_make_compatible(transferee, newchan);
598                                 if (res < 0) {
599                                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
600                                         ast_hangup(newchan);
601                                         return -1;
602                                 }
603                                 
604                                 
605                                 ast_moh_stop(transferee);
606                                 
607                                 if((ast_autoservice_stop(transferee) < 0)
608                                    ||(ast_waitfordigit(transferee,100) < 0)
609                                    || (ast_waitfordigit(newchan,100) < 0) 
610                                    || ast_check_hangup(transferee) 
611                                    || ast_check_hangup(newchan)) {
612                                         ast_hangup(newchan);
613                                         res = -1;
614                                         return -1;
615                                 }
616
617                                 if ((xferchan = ast_channel_alloc(0))) {
618                                         snprintf(xferchan->name, sizeof (xferchan->name), "Transfered/%s",transferee->name);
619                                         /* Make formats okay */
620                                         xferchan->readformat = transferee->readformat;
621                                         xferchan->writeformat = transferee->writeformat;
622                                         ast_channel_masquerade(xferchan, transferee);
623                                         ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
624                                         xferchan->_state = AST_STATE_UP;
625                                         xferchan->flags = 0;
626                                         xferchan->_softhangup = 0;
627
628                                         if((f = ast_read(xferchan))) {
629                                                 ast_frfree(f);
630                                                 f = NULL;
631                                         }
632                                         
633                                 } else {
634                                         ast_hangup(newchan);
635                                         return -1;
636                                 }
637
638                                 newchan->_state = AST_STATE_UP;
639                                 newchan->flags = 0;
640                                 newchan->_softhangup = 0;
641
642                                 tobj = malloc(sizeof(struct ast_bridge_thread_obj));
643                                 if (tobj) {
644                                         memset(tobj,0,sizeof(struct ast_bridge_thread_obj));
645                                         tobj->chan = xferchan;
646                                         tobj->peer = newchan;
647                                         tobj->bconfig = *config;
648         
649                                         if (!ast_strlen_zero(xfersound) && !ast_streamfile(newchan, xfersound, newchan->language)) {
650                                                 if (ast_waitstream(newchan, "") < 0) {
651                                                         ast_log(LOG_WARNING, "Failed to play %s!\n", xfersound);
652                                                 }
653                                         }
654                                         ast_bridge_call_thread_launch(tobj);
655                                 } else {
656                                         ast_log(LOG_WARNING, "Out of memory!\n");
657                                         ast_hangup(xferchan);
658                                         ast_hangup(newchan);
659                                 }
660                                 return -1;
661                                 
662                         } else {
663                                 ast_log(LOG_WARNING, "Unable to create channel Local/%s do you have chan_local?\n",dialstr);
664                                 ast_moh_stop(transferee);
665                                 ast_autoservice_stop(transferee);
666                                 if(!ast_strlen_zero(xferfailsound)) {
667                                         res = ast_streamfile(transferer, xferfailsound, transferer->language);
668                                         if (!res && (ast_waitstream(transferer, "") < 0)) {
669                                                 return -1;
670                                         }
671                                 }
672                                 return -1;
673                         }
674                 } else {
675                         ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
676                         ast_moh_stop(transferee);
677                         ast_autoservice_stop(transferee);
678                         if(!ast_strlen_zero(xferfailsound)) {
679                                 res = ast_streamfile(transferer, xferfailsound, transferer->language);
680                                 if (!res && (ast_waitstream(transferer, "") < 0)) {
681                                         return -1;
682                                 }
683                         }
684                 }
685         }  else {
686                 ast_log(LOG_WARNING, "Did not read data.\n");
687                 if(!ast_strlen_zero(xferfailsound)) {
688                         res = ast_streamfile(transferer, xferfailsound, transferer->language);
689                         if (ast_waitstream(transferer, "") < 0) {
690                                 return -1;
691                         }
692                 }
693         }
694         ast_moh_stop(transferee);
695         ast_autoservice_stop(transferee);
696
697
698         return FEATURE_RETURN_SUCCESS;
699 }
700
701 struct ast_call_feature {
702         int feature_mask;
703         char *fname;
704         char *sname;
705         char exten[FEATURE_MAX_LEN];
706         char default_exten[FEATURE_MAX_LEN];
707         int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense);
708         unsigned int flags;
709 };
710
711 /* add atxfer and automon as undefined so you can only use em if you configure them */
712 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
713 struct ast_call_feature builtin_features[] = 
714 {
715         { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
716         { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
717         { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
718         { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
719 };
720
721 static void unmap_features(void)
722 {
723         int x;
724         for (x=0;x<FEATURES_COUNT;x++)
725                 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
726 }
727
728 static int remap_feature(const char *name, const char *value)
729 {
730         int x;
731         int res = -1;
732         for (x=0;x<FEATURES_COUNT;x++) {
733                 if (!strcasecmp(name, builtin_features[x].sname)) {
734                         strncpy(builtin_features[x].exten, value, sizeof(builtin_features[x].exten) - 1);
735                         if (option_verbose > 1)
736                                 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);
737                         res = 0;
738                 } else if (!strcmp(value, builtin_features[x].exten)) 
739                         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);
740         }
741         return res;
742 }
743
744 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
745 {
746         int x;
747         unsigned int features;
748         int res = FEATURE_RETURN_PASSDIGITS;
749
750         if (sense == FEATURE_SENSE_CHAN)
751                 features = config->features_caller;
752         else
753                 features = config->features_callee;
754         ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features);
755         for (x=0;x<FEATURES_COUNT;x++) {
756                 if ((features & builtin_features[x].feature_mask) &&
757                     !ast_strlen_zero(builtin_features[x].exten)) {
758                         /* Feature is up for consideration */
759                         if (!strcmp(builtin_features[x].exten, code)) {
760                                 res = builtin_features[x].operation(chan, peer, config, code, sense);
761                                 break;
762                         } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
763                                 if (res == FEATURE_RETURN_PASSDIGITS)
764                                         res = FEATURE_RETURN_STOREDIGITS;
765                         }
766                 }
767         }
768         return res;
769 }
770
771 static void set_config_flags(struct ast_bridge_config *config)
772 {
773         int x;
774         config->flags = 0;
775         for (x=0;x<FEATURES_COUNT;x++) {
776                 if (config->features_caller & builtin_features[x].feature_mask) {
777                         if (builtin_features[x].flags & AST_FEATURE_FLAG_NEEDSDTMF)
778                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
779                 }
780                 if (config->features_callee & builtin_features[x].feature_mask) {
781                         if (builtin_features[x].flags & AST_FEATURE_FLAG_NEEDSDTMF)
782                                 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
783                 }
784         }
785 }
786
787 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
788 {
789         /* Copy voice back and forth between the two channels.  Give the peer
790            the ability to transfer calls with '#<extension' syntax. */
791         struct ast_frame *f;
792         struct ast_channel *who;
793         char chan_featurecode[FEATURE_MAX_LEN + 1]="";
794         char peer_featurecode[FEATURE_MAX_LEN + 1]="";
795         int res;
796         int diff;
797         int hasfeatures=0;
798         int hadfeatures=0;
799         struct ast_option_header *aoh;
800         struct timeval start, end;
801         struct ast_bridge_config backup_config;
802         int allowdisconnect_in,allowdisconnect_out,allowredirect_in,allowredirect_out;
803         char *monitor_exec;
804
805         memset(&backup_config, 0, sizeof(backup_config));
806
807         if (chan && peer) {
808                 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
809                 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
810         } else if (chan)
811                 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
812
813         if (monitor_ok) {
814                 if (!monitor_app) { 
815                         if (!(monitor_app = pbx_findapp("Monitor")))
816                                 monitor_ok=0;
817                 }
818                 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 
819                         pbx_exec(chan, monitor_app, monitor_exec, 1);
820                 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
821                         pbx_exec(peer, monitor_app, monitor_exec, 1);
822         }
823         
824         allowdisconnect_in = (config->features_callee & AST_FEATURE_DISCONNECT);
825         allowdisconnect_out = (config->features_caller & AST_FEATURE_DISCONNECT);
826         allowredirect_in = (config->features_callee & AST_FEATURE_REDIRECT);
827         allowredirect_out = (config->features_caller & AST_FEATURE_REDIRECT);
828         set_config_flags(config);
829         config->firstpass = 1;
830
831         /* Answer if need be */
832         if (ast_answer(chan))
833                 return -1;
834         peer->appl = "Bridged Call";
835         peer->data = chan->name;
836         /* copy the userfield from the B-leg to A-leg if applicable */
837         if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
838                 char tmp[256];
839                 if (!ast_strlen_zero(chan->cdr->userfield)) {
840                         snprintf(tmp, sizeof(tmp), "%s;%s",chan->cdr->userfield, peer->cdr->userfield);
841                         ast_cdr_appenduserfield(chan, tmp);
842                 } else
843                         ast_cdr_setuserfield(chan, peer->cdr->userfield);
844                 /* free the peer's cdr without ast_cdr_free complaining */
845                 free(peer->cdr);
846                 peer->cdr = NULL;
847         }
848         for (;;) {
849                 if (config->timelimit)
850                         gettimeofday(&start, NULL);
851                 res = ast_channel_bridge(chan,peer,config,&f, &who);
852                 if (config->timelimit) {
853                         /* Update time limit for next pass */
854                         gettimeofday(&end, NULL);
855                         diff = (end.tv_sec - start.tv_sec) * 1000;
856                         diff += (end.tv_usec - start.tv_usec) / 1000;
857                         config->timelimit -= diff;
858                         if (hasfeatures) {
859                                 /* Running on backup config, meaning a feature might be being
860                                    activated, but that's no excuse to keep things going 
861                                    indefinitely! */
862                                 if (backup_config.timelimit && ((backup_config.timelimit -= diff) <= 0)) {
863                                         ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
864                                         config->timelimit = 0;
865                                         who = chan;
866                                         if (f)
867                                                 ast_frfree(f);
868                                         f = NULL;
869                                         res = 0;
870                                 } else if (config->timelimit <= 0) {
871                                         /* Not *really* out of time, just out of time for
872                                            digits to come in for features. */
873                                         ast_log(LOG_DEBUG, "Timed out for feature!\n");
874                                         if (!ast_strlen_zero(peer_featurecode)) {
875                                                 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
876                                                 memset(peer_featurecode, 0, sizeof(peer_featurecode));
877                                         }
878                                         if (!ast_strlen_zero(chan_featurecode)) {
879                                                 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
880                                                 memset(chan_featurecode, 0, sizeof(chan_featurecode));
881                                         }
882                                         if (f)
883                                                 ast_frfree(f);
884                                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
885                                         if (!hasfeatures) {
886                                                 /* Restore original (possibly time modified) bridge config */
887                                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
888                                                 memset(&backup_config, 0, sizeof(backup_config));
889                                         }
890                                         hadfeatures = hasfeatures;
891                                         /* Continue as we were */
892                                         continue;
893                                 }
894                         } else {
895                                 if (config->timelimit <=0) {
896                                         /* We ran out of time */
897                                         config->timelimit = 0;
898                                         who = chan;
899                                         if (f)
900                                                 ast_frfree(f);
901                                         f = NULL;
902                                         res = 0;
903                                 }
904                         }
905                 }
906                 if (res < 0) {
907                         ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
908                         return -1;
909                 }
910                 
911                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) || 
912                         (f->subclass == AST_CONTROL_CONGESTION)))) {
913                                 res = -1;
914                                 break;
915                 }
916                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
917                         if (who == chan)
918                                 ast_indicate(peer, AST_CONTROL_RINGING);
919                         else
920                                 ast_indicate(chan, AST_CONTROL_RINGING);
921                 }
922                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
923                         if (who == chan)
924                                 ast_indicate(peer, -1);
925                         else
926                                 ast_indicate(chan, -1);
927                 }
928                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
929                         if (who == chan)
930                                 ast_indicate(peer, AST_CONTROL_FLASH);
931                         else
932                                 ast_indicate(chan, AST_CONTROL_FLASH);
933                 }
934                 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
935                         aoh = f->data;
936                         /* Forward option Requests */
937                         if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
938                                 if (who == chan)
939                                         ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
940                                 else
941                                         ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
942                         }
943                 }
944                 /* check for '*', if we find it it's time to disconnect */
945                 if (f && (f->frametype == AST_FRAME_DTMF)) {
946                         char *featurecode;
947                         int sense;
948                         struct ast_channel *other;
949                         hadfeatures = hasfeatures;
950                         /* This cannot overrun because the longest feature is one shorter than our buffer */
951                         if (who == chan) {
952                                 other = peer;
953                                 sense = FEATURE_SENSE_CHAN;
954                                 featurecode = chan_featurecode;
955                         } else  {
956                                 other = chan;
957                                 sense = FEATURE_SENSE_PEER;
958                                 featurecode = peer_featurecode;
959                         }
960                         featurecode[strlen(featurecode)] = f->subclass;
961                         res = ast_feature_interpret(chan, peer, config, featurecode, sense);
962                         switch(res) {
963                         case FEATURE_RETURN_PASSDIGITS:
964                                 ast_dtmf_stream(other, who, featurecode, 0);
965                                 /* Fall through */
966                         case FEATURE_RETURN_SUCCESS:
967                                 memset(featurecode, 0, sizeof(chan_featurecode));
968                                 break;
969                         }
970                         if (res >= FEATURE_RETURN_PASSDIGITS) {
971                                 res = 0;
972                         } else {
973                                 ast_frfree(f);
974                                 break;
975                         }
976                         hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
977                         if (hadfeatures && !hasfeatures) {
978                                 /* Restore backup */
979                                 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
980                                 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
981                         } else if (hasfeatures) {
982                                 if (!hadfeatures) {
983                                         /* Backup configuration */
984                                         memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
985                                         /* Setup temporary config options */
986                                         config->play_warning = 0;
987                                         config->features_caller &= ~(AST_FEATURE_PLAY_WARNING);
988                                         config->features_callee &= ~(AST_FEATURE_PLAY_WARNING);
989                                         config->warning_freq = 0;
990                                         config->warning_sound = NULL;
991                                         config->end_sound = NULL;
992                                         config->start_sound = NULL;
993                                         config->firstpass = 0;
994                                 }
995                                 config->timelimit = featuredigittimeout;
996                                 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->timelimit);
997                         }
998                 }
999                 if (f)
1000                         ast_frfree(f);
1001         }
1002         return res;
1003 }
1004
1005 static void *do_parking_thread(void *ignore)
1006 {
1007         int ms, tms, max;
1008         struct parkeduser *pu, *pl, *pt = NULL;
1009         struct timeval tv;
1010         struct ast_frame *f;
1011         char exten[AST_MAX_EXTENSION];
1012         char *peername,*cp;
1013         struct ast_context *con;
1014         int x;
1015         int gc=0;
1016         fd_set rfds, efds;
1017         fd_set nrfds, nefds;
1018         FD_ZERO(&rfds);
1019         FD_ZERO(&efds);
1020
1021         for (;;) {
1022                 ms = -1;
1023                 max = -1;
1024                 ast_mutex_lock(&parking_lock);
1025                 pl = NULL;
1026                 pu = parkinglot;
1027                 FD_ZERO(&nrfds);
1028                 FD_ZERO(&nefds);
1029                 while(pu) {
1030                         if (pu->notquiteyet) {
1031                                 /* Pretend this one isn't here yet */
1032                                 pl = pu;
1033                                 pu = pu->next;
1034                                 continue;
1035                         }
1036                         if (gc < 5 && !pu->chan->generator) {
1037                                 gc++;
1038                                 ast_moh_start(pu->chan,NULL);
1039                         }
1040                         gettimeofday(&tv, NULL);
1041                         tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
1042                         if (tms > pu->parkingtime) {
1043                                 /* Stop music on hold */
1044                                 ast_moh_stop(pu->chan);
1045                                 /* Get chan, exten from derived kludge */
1046                                 if (pu->peername[0]) {
1047                                         peername = ast_strdupa(pu->peername);
1048                                         cp = strrchr(peername, '-');
1049                                         if (cp) 
1050                                                 *cp = 0;
1051                                         con = ast_context_find(parking_con_dial);
1052                                         if (!con) {
1053                                                 con = ast_context_create(NULL, parking_con_dial, registrar);
1054                                                 if (!con) {
1055                                                         ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1056                                                 }
1057                                         }
1058                                         if (con) {
1059                                                 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(peername), free, registrar);
1060                                         }
1061                                         strncpy(pu->chan->exten, peername, sizeof(pu->chan->exten) - 1);
1062                                         strncpy(pu->chan->context, parking_con_dial, sizeof(pu->chan->context) - 1);
1063                                         pu->chan->priority = 1;
1064
1065                                 } else {
1066                                         /* They've been waiting too long, send them back to where they came.  Theoretically they
1067                                            should have their original extensions and such, but we copy to be on the safe side */
1068                                         strncpy(pu->chan->exten, pu->exten, sizeof(pu->chan->exten)-1);
1069                                         strncpy(pu->chan->context, pu->context, sizeof(pu->chan->context)-1);
1070                                         pu->chan->priority = pu->priority;
1071                                 }
1072                                 if (option_verbose > 1) 
1073                                         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);
1074                                 /* Start up the PBX, or hang them up */
1075                                 if (ast_pbx_start(pu->chan))  {
1076                                         ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
1077                                         ast_hangup(pu->chan);
1078                                 }
1079                                 /* And take them out of the parking lot */
1080                                 if (pl) 
1081                                         pl->next = pu->next;
1082                                 else
1083                                         parkinglot = pu->next;
1084                                 pt = pu;
1085                                 pu = pu->next;
1086                                 con = ast_context_find(parking_con);
1087                                 if (con) {
1088                                         snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1089                                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1090                                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1091                                 } else
1092                                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1093                                 free(pt);
1094                         } else {
1095                                 for (x=0; x<AST_MAX_FDS; x++) {
1096                                         if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
1097                                                 if (FD_ISSET(pu->chan->fds[x], &efds))
1098                                                         ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
1099                                                 else
1100                                                         ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
1101                                                 pu->chan->fdno = x;
1102                                                 /* See if they need servicing */
1103                                                 f = ast_read(pu->chan);
1104                                                 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
1105                                                         /* There's a problem, hang them up*/
1106                                                         if (option_verbose > 1) 
1107                                                                 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
1108                                                         ast_hangup(pu->chan);
1109                                                         /* And take them out of the parking lot */
1110                                                         if (pl) 
1111                                                                 pl->next = pu->next;
1112                                                         else
1113                                                                 parkinglot = pu->next;
1114                                                         pt = pu;
1115                                                         pu = pu->next;
1116                                                         con = ast_context_find(parking_con);
1117                                                         if (con) {
1118                                                                 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1119                                                                 if (ast_context_remove_extension2(con, exten, 1, NULL))
1120                                                                         ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1121                                                         } else
1122                                                                 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1123                                                         free(pt);
1124                                                         break;
1125                                                 } else {
1126                                                         /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1127                                                         ast_frfree(f);
1128                                                         goto std;       /* XXX Ick: jumping into an else statement??? XXX */
1129                                                 }
1130                                         }
1131                                 }
1132                                 if (x >= AST_MAX_FDS) {
1133 std:                                    for (x=0; x<AST_MAX_FDS; x++) {
1134                                                 /* Keep this one for next one */
1135                                                 if (pu->chan->fds[x] > -1) {
1136                                                         FD_SET(pu->chan->fds[x], &nrfds);
1137                                                         FD_SET(pu->chan->fds[x], &nefds);
1138                                                         if (pu->chan->fds[x] > max)
1139                                                                 max = pu->chan->fds[x];
1140                                                 }
1141                                         }
1142                                         /* Keep track of our longest wait */
1143                                         if ((tms < ms) || (ms < 0))
1144                                                 ms = tms;
1145                                         pl = pu;
1146                                         pu = pu->next;
1147                                 }
1148                         }
1149                 }
1150                 ast_mutex_unlock(&parking_lock);
1151                 rfds = nrfds;
1152                 efds = nefds;
1153                 tv.tv_sec = ms / 1000;
1154                 tv.tv_usec = (ms % 1000) * 1000;
1155                 /* Wait for something to happen */
1156                 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1157                 pthread_testcancel();
1158         }
1159         return NULL;    /* Never reached */
1160 }
1161
1162 static int park_call_exec(struct ast_channel *chan, void *data)
1163 {
1164         /* Data is unused at the moment but could contain a parking
1165            lot context eventually */
1166         int res=0;
1167         struct localuser *u;
1168         LOCAL_USER_ADD(u);
1169         /* Setup the exten/priority to be s/1 since we don't know
1170            where this call should return */
1171         strcpy(chan->exten, "s");
1172         chan->priority = 1;
1173         if (chan->_state != AST_STATE_UP)
1174                 res = ast_answer(chan);
1175         if (!res)
1176                 res = ast_safe_sleep(chan, 1000);
1177         if (!res)
1178                 res = ast_park_call(chan, chan, 0, NULL);
1179         LOCAL_USER_REMOVE(u);
1180         if (!res)
1181                 res = AST_PBX_KEEPALIVE;
1182         return res;
1183 }
1184
1185 static int park_exec(struct ast_channel *chan, void *data)
1186 {
1187         int res=0;
1188         struct localuser *u;
1189         struct ast_channel *peer=NULL;
1190         struct parkeduser *pu, *pl=NULL;
1191         char exten[AST_MAX_EXTENSION];
1192         struct ast_context *con;
1193         int park;
1194         int dres;
1195         struct ast_bridge_config config;
1196
1197         if (!data) {
1198                 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
1199                 return -1;
1200         }
1201         LOCAL_USER_ADD(u);
1202         park = atoi((char *)data);
1203         ast_mutex_lock(&parking_lock);
1204         pu = parkinglot;
1205         while(pu) {
1206                 if (pu->parkingnum == park) {
1207                         if (pl)
1208                                 pl->next = pu->next;
1209                         else
1210                                 parkinglot = pu->next;
1211                         break;
1212                 }
1213                 pl = pu;
1214                 pu = pu->next;
1215         }
1216         ast_mutex_unlock(&parking_lock);
1217         if (pu) {
1218                 peer = pu->chan;
1219                 con = ast_context_find(parking_con);
1220                 if (con) {
1221                         snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
1222                         if (ast_context_remove_extension2(con, exten, 1, NULL))
1223                                 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1224                 } else
1225                         ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1226                 free(pu);
1227         }
1228         /* JK02: it helps to answer the channel if not already up */
1229         if (chan->_state != AST_STATE_UP) {
1230                 ast_answer(chan);
1231         }
1232
1233         if (peer) {
1234                 /* Play a courtesy beep in the calling channel to prefix the bridge connecting */       
1235                 if (!ast_strlen_zero(courtesytone)) {
1236                         if (!ast_streamfile(chan, courtesytone, chan->language)) {
1237                                 if (ast_waitstream(chan, "") < 0) {
1238                                         ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1239                                         ast_hangup(peer);
1240                                         return -1;
1241                                 }
1242                         }
1243                 }
1244  
1245                 ast_moh_stop(peer);
1246                 res = ast_channel_make_compatible(chan, peer);
1247                 if (res < 0) {
1248                         ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1249                         ast_hangup(peer);
1250                         return -1;
1251                 }
1252                 /* This runs sorta backwards, since we give the incoming channel control, as if it
1253                    were the person called. */
1254                 if (option_verbose > 2) 
1255                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1256
1257                 memset(&config,0,sizeof(struct ast_bridge_config));
1258                 config.features_callee |= AST_FEATURE_REDIRECT;
1259                 config.features_caller |= AST_FEATURE_REDIRECT;
1260                 config.timelimit = 0;
1261                 config.play_warning = 0;
1262                 config.warning_freq = 0;
1263                 config.warning_sound=NULL;
1264                 res = ast_bridge_call(chan,peer,&config);
1265
1266                 /* Simulate the PBX hanging up */
1267                 if (res != AST_PBX_NO_HANGUP_PEER)
1268                         ast_hangup(peer);
1269                 return res;
1270         } else {
1271                 /* XXX Play a message XXX */
1272                 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
1273                 if (!dres)
1274                         dres = ast_waitstream(chan, "");
1275                  else {
1276                         ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1277                         dres = 0;
1278                 }
1279                 if (option_verbose > 2) 
1280                         ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to non-existant parked call %d\n", chan->name, park);
1281                 res = -1;
1282         }
1283         LOCAL_USER_REMOVE(u);
1284         return res;
1285 }
1286
1287 static int handle_parkedcalls(int fd, int argc, char *argv[])
1288 {
1289         struct parkeduser *cur;
1290
1291         ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1292                 , "Context", "Extension", "Pri", "Timeout");
1293
1294         ast_mutex_lock(&parking_lock);
1295
1296         cur = parkinglot;
1297         while(cur) {
1298                 ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
1299                         ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
1300                         ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1301
1302                 cur = cur->next;
1303         }
1304
1305         ast_mutex_unlock(&parking_lock);
1306
1307         return RESULT_SUCCESS;
1308 }
1309
1310 static char showparked_help[] =
1311 "Usage: show parkedcalls\n"
1312 "       Lists currently parked calls.\n";
1313
1314 static struct ast_cli_entry showparked =
1315 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1316 /* Dump lot status */
1317 static int manager_parking_status( struct mansession *s, struct message *m )
1318 {
1319         struct parkeduser *cur;
1320         char *id = astman_get_header(m,"ActionID");
1321         char idText[256] = "";
1322
1323         if (id && !ast_strlen_zero(id))
1324                 snprintf(idText,256,"ActionID: %s\r\n",id);
1325
1326         astman_send_ack(s, m, "Parked calls will follow");
1327
1328         ast_mutex_lock(&parking_lock);
1329
1330         cur=parkinglot;
1331         while(cur) {
1332                         ast_mutex_lock(&s->lock);
1333                 ast_cli(s->fd, "Event: ParkedCall\r\n"
1334                         "Exten: %d\r\n"
1335                         "Channel: %s\r\n"
1336                         "Timeout: %ld\r\n"
1337                         "CallerID: %s\r\n"
1338                         "CallerIDName: %s\r\n"
1339                         "%s"
1340                         "\r\n"
1341                         ,cur->parkingnum, cur->chan->name
1342                         ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
1343                         ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
1344                         ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
1345                         ,idText);
1346                         ast_mutex_unlock(&s->lock);
1347
1348             cur = cur->next;
1349         }
1350
1351         ast_cli(s->fd,
1352         "Event: ParkedCallsComplete\r\n"
1353         "%s"
1354         "\r\n",idText);
1355
1356         ast_mutex_unlock(&parking_lock);
1357
1358         return RESULT_SUCCESS;
1359 }
1360
1361
1362
1363 int load_module(void)
1364 {
1365         int res;
1366         int start, end;
1367         struct ast_context *con;
1368         struct ast_config *cfg;
1369         struct ast_variable *var;
1370
1371         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1372         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1373
1374         ast_cli_register(&showparked);
1375
1376         cfg = ast_load("features.conf");
1377         if (!cfg) {
1378                 cfg = ast_load("parking.conf");
1379                 if (cfg)
1380                         ast_log(LOG_NOTICE, "parking.conf is deprecated in favor of 'features.conf'.  Please rename it.\n");
1381         }
1382         if (cfg) {
1383                 var = ast_variable_browse(cfg, "general");
1384                 while(var) {
1385                         if (!strcasecmp(var->name, "parkext")) {
1386                                 strncpy(parking_ext, var->value, sizeof(parking_ext) - 1);
1387                         } else if (!strcasecmp(var->name, "context")) {
1388                                 strncpy(parking_con, var->value, sizeof(parking_con) - 1);
1389                         } else if (!strcasecmp(var->name, "parkingtime")) {
1390                                 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
1391                                         ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
1392                                         parkingtime = DEFAULT_PARK_TIME;
1393                                 } else
1394                                         parkingtime = parkingtime * 1000;
1395                         } else if (!strcasecmp(var->name, "parkpos")) {
1396                                 if (sscanf(var->value, "%i-%i", &start, &end) != 2) {
1397                                         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);
1398                                 } else {
1399                                         parking_start = start;
1400                                         parking_stop = end;
1401                                 }
1402                         } else if (!strcasecmp(var->name, "adsipark")) {
1403                                 adsipark = ast_true(var->value);
1404                         } else if (!strcasecmp(var->name, "transferdigittimeout")) {
1405                                 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
1406                                         ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
1407                                         transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1408                                 } else
1409                                         transferdigittimeout = transferdigittimeout * 1000;
1410                         } else if (!strcasecmp(var->name, "featuredigittimeout")) {
1411                                 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (transferdigittimeout < 1)) {
1412                                         ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
1413                                         featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1414                                 }
1415                         } else if (!strcasecmp(var->name, "courtesytone")) {
1416                                 strncpy(courtesytone, strcmp(var->value, "undef") ? var->value : "", sizeof(courtesytone) - 1);
1417                         } else if (!strcasecmp(var->name, "xfersound")) {
1418                                 strncpy(xfersound, strcmp(var->value, "undef") ? var->value : "", sizeof(xfersound) - 1);
1419                         } else if (!strcasecmp(var->name, "xferfailsound")) {
1420                                 strncpy(xferfailsound, strcmp(var->value, "undef") ? var->value : "", sizeof(xferfailsound) - 1);
1421                         } else if (!strcasecmp(var->name, "pickupexten")) {
1422                                 strncpy(pickup_ext, strcmp(var->value, "undef") ? var->value : "", sizeof(pickup_ext) - 1);
1423                         }
1424                         var = var->next;
1425                 }
1426                 unmap_features();
1427                 var = ast_variable_browse(cfg, "featuremap");
1428                 while(var) {
1429                         if (remap_feature(var->name, var->value))
1430                                 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
1431                         var = var->next;
1432                 }
1433                 ast_destroy(cfg);
1434         }
1435         con = ast_context_find(parking_con);
1436         if (!con) {
1437                 con = ast_context_create(NULL,parking_con, registrar);
1438                 if (!con) {
1439                         ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
1440                         return -1;
1441                 }
1442         }
1443         ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""),free, registrar);
1444         ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
1445         res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
1446         if (!res)
1447                 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
1448         if (!res) {
1449                 ast_manager_register( "ParkedCalls", 0, manager_parking_status, "List parked calls" );
1450         }
1451         return res;
1452 }
1453
1454 int ast_pickup_call(struct ast_channel *chan)
1455 {
1456         struct ast_channel *cur;
1457         int res = -1;
1458         cur = ast_channel_walk_locked(NULL);
1459         while(cur) {
1460                 if (!cur->pbx && 
1461                         (cur != chan) &&
1462                         (chan->pickupgroup & cur->callgroup) &&
1463                         ((cur->_state == AST_STATE_RINGING) ||
1464                          (cur->_state == AST_STATE_RING))) {
1465                                 break;
1466                 }
1467                 ast_mutex_unlock(&cur->lock);
1468                 cur = ast_channel_walk_locked(cur);
1469         }
1470         if (cur) {
1471                 if (option_debug)
1472                         ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
1473                 res = ast_answer(chan);
1474                 if (res)
1475                         ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
1476                 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
1477                 if (res)
1478                         ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
1479                 res = ast_channel_masquerade(cur, chan);
1480                 if (res)
1481                         ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);           /* Done */
1482                 ast_mutex_unlock(&cur->lock);
1483         } else  {
1484                 if (option_debug)
1485                         ast_log(LOG_DEBUG, "No call pickup possible...\n");
1486         }
1487         return res;
1488 }
1489
1490 int unload_module(void)
1491 {
1492         STANDARD_HANGUP_LOCALUSERS;
1493
1494         ast_manager_unregister( "ParkedCalls" );
1495         ast_cli_unregister(&showparked);
1496         ast_unregister_application(parkcall);
1497         return ast_unregister_application(parkedcall);
1498 }
1499
1500 char *description(void)
1501 {
1502         return "Call Parking Resource";
1503 }
1504
1505 int usecount(void)
1506 {
1507         /* Never allow parking to be unloaded because it will
1508            unresolve needed symbols in the dialer */
1509 #if 0
1510         int res;
1511         STANDARD_USECOUNT(res);
1512         return res;
1513 #else
1514         return 1;
1515 #endif
1516 }
1517
1518 char *key()
1519 {
1520         return ASTERISK_GPL_KEY;
1521 }