2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Routines implementing call parking
33 #include <sys/signal.h>
34 #include <netinet/in.h>
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40 #include "asterisk/lock.h"
41 #include "asterisk/file.h"
42 #include "asterisk/logger.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/options.h"
46 #include "asterisk/causes.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/app.h"
50 #include "asterisk/say.h"
51 #include "asterisk/features.h"
52 #include "asterisk/musiconhold.h"
53 #include "asterisk/config.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/manager.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/adsi.h"
58 #include "asterisk/monitor.h"
60 #ifdef __AST_DEBUG_MALLOC
61 static void FREE(void *ptr)
69 #define DEFAULT_PARK_TIME 45000
70 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
71 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
73 #define AST_MAX_WATCHERS 256
75 static char *parkedcall = "ParkedCall";
77 /* No more than 45 seconds parked before you do something with them */
78 static int parkingtime = DEFAULT_PARK_TIME;
80 /* Context for which parking is made accessible */
81 static char parking_con[AST_MAX_EXTENSION];
83 /* Context for dialback for parking (KLUDGE) */
84 static char parking_con_dial[AST_MAX_EXTENSION];
86 /* Extension you type to park the call */
87 static char parking_ext[AST_MAX_EXTENSION];
89 static char pickup_ext[AST_MAX_EXTENSION];
92 static char courtesytone[256];
93 static char xfersound[256];
94 static char xferfailsound[256];
96 /* First available extension for parking */
97 static int parking_start;
99 /* Last available extension for parking */
100 static int parking_stop;
102 static int parking_offset;
104 static int parkfindnext;
108 static int transferdigittimeout;
109 static int featuredigittimeout;
111 /* Default courtesy tone played when party joins conference */
113 /* Registrar for operations */
114 static char *registrar = "res_features";
116 static char *synopsis = "Answer a parked call";
118 static char *descrip = "ParkedCall(exten):"
119 "Used to connect to a parked call. This application is always\n"
120 "registered internally and does not need to be explicitly added\n"
121 "into the dialplan, although you should include the 'parkedcalls'\n"
124 static char *parkcall = "Park";
126 static char *synopsis2 = "Park yourself";
128 static char *descrip2 = "Park(exten):"
129 "Used to park yourself (typically in combination with a supervised\n"
130 "transfer to know the parking space). This application is always\n"
131 "registered internally and does not need to be explicitly added\n"
132 "into the dialplan, although you should include the 'parkedcalls'\n"
135 static struct ast_app *monitor_app=NULL;
136 static int monitor_ok=1;
139 struct ast_channel *chan;
140 struct timeval start;
142 /* Where to go if our parking time expires */
143 char context[AST_MAX_CONTEXT];
144 char exten[AST_MAX_EXTENSION];
149 unsigned char moh_trys;
150 struct parkeduser *next;
153 static struct parkeduser *parkinglot;
155 AST_MUTEX_DEFINE_STATIC(parking_lock);
157 static pthread_t parking_thread;
163 char *ast_parking_ext(void)
168 char *ast_pickup_ext(void)
173 struct ast_bridge_thread_obj
175 struct ast_bridge_config bconfig;
176 struct ast_channel *chan;
177 struct ast_channel *peer;
180 static void check_goto_on_transfer(struct ast_channel *chan)
182 struct ast_channel *xferchan;
183 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
184 char *x, *goto_on_transfer;
187 if (!ast_strlen_zero(val) && (goto_on_transfer = ast_strdupa(val)) && (xferchan = ast_channel_alloc(0))) {
188 for (x = goto_on_transfer; x && *x; x++)
191 strcpy(xferchan->name, chan->name);
192 /* Make formats okay */
193 xferchan->readformat = chan->readformat;
194 xferchan->writeformat = chan->writeformat;
195 ast_channel_masquerade(xferchan, chan);
196 ast_parseable_goto(xferchan, goto_on_transfer);
197 xferchan->_state = AST_STATE_UP;
198 ast_clear_flag(xferchan, AST_FLAGS_ALL);
199 xferchan->_softhangup = 0;
200 if ((f = ast_read(xferchan))) {
203 ast_pbx_start(xferchan);
205 ast_hangup(xferchan);
210 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);
213 static void *ast_bridge_call_thread(void *data)
215 struct ast_bridge_thread_obj *tobj = data;
217 tobj->chan->appl = "Transferred Call";
218 tobj->chan->data = tobj->peer->name;
219 tobj->peer->appl = "Transferred Call";
220 tobj->peer->data = tobj->chan->name;
221 if (tobj->chan->cdr) {
222 ast_cdr_reset(tobj->chan->cdr, NULL);
223 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
225 if (tobj->peer->cdr) {
226 ast_cdr_reset(tobj->peer->cdr, NULL);
227 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
230 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
231 ast_hangup(tobj->chan);
232 ast_hangup(tobj->peer);
233 tobj->chan = tobj->peer = NULL;
239 static void ast_bridge_call_thread_launch(void *data)
243 struct sched_param sched;
245 pthread_attr_init(&attr);
246 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
247 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
248 pthread_attr_destroy(&attr);
249 memset(&sched, 0, sizeof(sched));
250 pthread_setschedparam(thread, SCHED_RR, &sched);
255 static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
258 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
260 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
262 snprintf(tmp, sizeof(tmp), "Parked on %d", parkingnum);
264 res = adsi_load_session(chan, NULL, 0, 1);
268 return adsi_print(chan, message, justify, 1);
271 /*--- ast_park_call: Park a call */
272 /* We put the user in the parking list, then wake up the parking thread to be sure it looks
273 after these channels too */
274 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
276 struct parkeduser *pu, *cur;
277 int i,x,parking_range;
278 char exten[AST_MAX_EXTENSION];
279 struct ast_context *con;
281 pu = malloc(sizeof(struct parkeduser));
283 ast_log(LOG_WARNING, "Out of memory\n");
286 memset(pu, 0, sizeof(struct parkeduser));
287 ast_mutex_lock(&parking_lock);
288 parking_range = parking_stop - parking_start+1;
289 for (i = 0; i < parking_range; i++) {
290 x = (i + parking_offset) % parking_range + parking_start;
293 if (cur->parkingnum == x)
301 if (!(i < parking_range)) {
302 ast_log(LOG_WARNING, "No more parking spaces\n");
304 ast_mutex_unlock(&parking_lock);
308 parking_offset = x - parking_start + 1;
309 chan->appl = "Parked Call";
313 /* Start music on hold */
315 ast_indicate(pu->chan, AST_CONTROL_HOLD);
316 ast_moh_start(pu->chan, NULL);
318 pu->start = ast_tvnow();
321 pu->parkingtime = timeout;
323 pu->parkingtime = parkingtime;
327 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
329 /* Remember what had been dialed, so that if the parking
330 expires, we try to come back to the same place */
331 if (!ast_strlen_zero(chan->macrocontext))
332 ast_copy_string(pu->context, chan->macrocontext, sizeof(pu->context));
334 ast_copy_string(pu->context, chan->context, sizeof(pu->context));
335 if (!ast_strlen_zero(chan->macroexten))
336 ast_copy_string(pu->exten, chan->macroexten, sizeof(pu->exten));
338 ast_copy_string(pu->exten, chan->exten, sizeof(pu->exten));
339 if (chan->macropriority)
340 pu->priority = chan->macropriority;
342 pu->priority = chan->priority;
343 pu->next = parkinglot;
345 /* If parking a channel directly, don't quiet yet get parking running on it */
348 ast_mutex_unlock(&parking_lock);
349 /* Wake up the (presumably select()ing) thread */
350 pthread_kill(parking_thread, SIGURG);
351 if (option_verbose > 1)
352 ast_verbose(VERBOSE_PREFIX_2 "Parked %s on %d. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
354 manager_event(EVENT_FLAG_CALL, "ParkedCall",
360 "CallerIDName: %s\r\n\r\n"
361 ,pu->parkingnum, pu->chan->name, peer->name
362 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
363 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
364 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
368 if (adsipark && adsi_available(peer)) {
369 adsi_announce_park(peer, pu->parkingnum);
371 if (adsipark && adsi_available(peer)) {
372 adsi_unload_session(peer);
375 con = ast_context_find(parking_con);
377 con = ast_context_create(NULL, parking_con, registrar);
379 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
383 snprintf(exten, sizeof(exten), "%d", x);
384 ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar);
387 ast_say_digits(peer, pu->parkingnum, "", peer->language);
388 if (pu->notquiteyet) {
389 /* Wake up parking thread if we're really done */
390 ast_moh_start(pu->chan, NULL);
392 pthread_kill(parking_thread, SIGURG);
397 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
399 struct ast_channel *chan;
402 /* Make a new, fake channel that we'll use to masquerade in the real one */
403 chan = ast_channel_alloc(0);
405 /* Let us keep track of the channel name */
406 snprintf(chan->name, sizeof (chan->name), "Parked/%s",rchan->name);
408 /* Make formats okay */
409 chan->readformat = rchan->readformat;
410 chan->writeformat = rchan->writeformat;
411 ast_channel_masquerade(chan, rchan);
413 /* Setup the extensions and such */
414 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
415 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
416 chan->priority = rchan->priority;
418 /* Make the masq execute */
422 ast_park_call(chan, peer, timeout, extout);
424 ast_log(LOG_WARNING, "Unable to create parked channel\n");
431 #define FEATURE_RETURN_HANGUP -1
432 #define FEATURE_RETURN_SUCCESSBREAK 0
433 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
434 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
435 #define FEATURE_RETURN_PASSDIGITS 21
436 #define FEATURE_RETURN_STOREDIGITS 22
437 #define FEATURE_RETURN_SUCCESS 23
439 #define FEATURE_SENSE_CHAN (1 << 0)
440 #define FEATURE_SENSE_PEER (1 << 1)
443 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
445 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
448 struct ast_channel *caller_chan = NULL, *callee_chan = NULL;
460 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
465 if (!(monitor_app = pbx_findapp("Monitor"))) {
467 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
471 if (!ast_strlen_zero(courtesytone)) {
472 if (ast_autoservice_start(callee_chan))
474 if (!ast_streamfile(caller_chan, courtesytone, caller_chan->language)) {
475 if (ast_waitstream(caller_chan, "") < 0) {
476 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
477 ast_autoservice_stop(callee_chan);
481 if (ast_autoservice_stop(callee_chan))
485 if (callee_chan->monitor) {
486 if (option_verbose > 3)
487 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
488 ast_monitor_stop(callee_chan, 1);
489 return FEATURE_RETURN_SUCCESS;
492 if (caller_chan && callee_chan) {
493 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
494 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
497 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
500 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
503 len = strlen(touch_monitor) + 50;
505 touch_filename = alloca(len);
506 snprintf(touch_filename, len, "auto-%ld-%s", time(NULL), touch_monitor);
507 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
509 caller_chan_id = ast_strdupa(caller_chan->cid.cid_num ? caller_chan->cid.cid_num : caller_chan->name);
510 callee_chan_id = ast_strdupa(callee_chan->cid.cid_num ? callee_chan->cid.cid_num : callee_chan->name);
511 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
513 touch_filename = alloca(len);
514 snprintf(touch_filename, len, "auto-%ld-%s-%s", time(NULL), caller_chan_id, callee_chan_id);
515 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
518 for( x = 0; x < strlen(args); x++)
522 if (option_verbose > 3)
523 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
525 pbx_exec(callee_chan, monitor_app, args, 1);
526 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
527 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
529 return FEATURE_RETURN_SUCCESS;
532 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
536 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
538 if (option_verbose > 3)
539 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
540 return FEATURE_RETURN_HANGUP;
543 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
545 struct ast_channel *transferer;
546 struct ast_channel *transferee;
547 const char *transferer_real_context;
551 if (sense == FEATURE_SENSE_PEER) {
558 if (!(transferer_real_context = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
559 !(transferer_real_context = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
560 /* Use the non-macro context to transfer the call */
561 if (!ast_strlen_zero(transferer->macrocontext))
562 transferer_real_context = transferer->macrocontext;
564 transferer_real_context = transferer->context;
566 /* Start autoservice on chan while we talk
568 ast_indicate(transferee, AST_CONTROL_HOLD);
569 ast_autoservice_start(transferee);
570 ast_moh_start(transferee, NULL);
572 memset(newext, 0, sizeof(newext));
575 if ((res=ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
576 ast_moh_stop(transferee);
577 ast_autoservice_stop(transferee);
578 ast_indicate(transferee, AST_CONTROL_UNHOLD);
581 if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
582 ast_moh_stop(transferee);
583 ast_autoservice_stop(transferee);
584 ast_indicate(transferee, AST_CONTROL_UNHOLD);
586 } else if (res > 0) {
587 /* If they've typed a digit already, handle it */
588 newext[0] = (char) res;
591 ast_stopstream(transferer);
592 res = ast_app_dtget(transferer, transferer_real_context, newext, sizeof(newext), 100, transferdigittimeout);
594 ast_moh_stop(transferee);
595 ast_autoservice_stop(transferee);
596 ast_indicate(transferee, AST_CONTROL_UNHOLD);
599 if (!strcmp(newext, ast_parking_ext())) {
600 ast_moh_stop(transferee);
602 res = ast_autoservice_stop(transferee);
603 ast_indicate(transferee, AST_CONTROL_UNHOLD);
606 else if (!ast_park_call(transferee, transferer, 0, NULL)) {
607 /* We return non-zero, but tell the PBX not to hang the channel when
608 the thread dies -- We have to be careful now though. We are responsible for
609 hanging up the channel, else it will never be hung up! */
611 if (transferer == peer)
612 res = AST_PBX_KEEPALIVE;
614 res = AST_PBX_NO_HANGUP_PEER;
617 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
619 /* XXX Maybe we should have another message here instead of invalid extension XXX */
620 } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
621 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
622 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
623 ast_moh_stop(transferee);
624 res=ast_autoservice_stop(transferee);
625 ast_indicate(transferee, AST_CONTROL_UNHOLD);
626 if (!transferee->pbx) {
627 /* Doh! Use our handy async_goto functions */
628 if (option_verbose > 2)
629 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
630 ,transferee->name, newext, transferer_real_context);
631 if (ast_async_goto(transferee, transferer_real_context, newext, 1))
632 ast_log(LOG_WARNING, "Async goto failed :-(\n");
635 /* Set the channel's new extension, since it exists, using transferer context */
636 ast_copy_string(transferee->exten, newext, sizeof(transferee->exten));
637 ast_copy_string(transferee->context, transferer_real_context, sizeof(transferee->context));
638 transferee->priority = 0;
640 check_goto_on_transfer(transferer);
643 if (option_verbose > 2)
644 ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", newext, transferer_real_context);
646 if (!ast_strlen_zero(xferfailsound))
647 res = ast_streamfile(transferer, xferfailsound, transferee->language);
651 ast_moh_stop(transferee);
652 ast_autoservice_stop(transferee);
653 ast_indicate(transferee, AST_CONTROL_UNHOLD);
656 res = ast_waitstream(transferer, AST_DIGIT_ANY);
657 ast_stopstream(transferer);
658 ast_moh_stop(transferee);
659 res = ast_autoservice_stop(transferee);
660 ast_indicate(transferee, AST_CONTROL_UNHOLD);
662 if (option_verbose > 1)
663 ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
666 return FEATURE_RETURN_SUCCESS;
669 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
671 struct ast_channel *transferer;
672 struct ast_channel *transferee;
673 struct ast_channel *newchan, *xferchan=NULL;
675 struct ast_bridge_config bconfig;
676 const char *transferer_real_context;
677 char xferto[256],dialstr[265];
681 struct ast_frame *f = NULL;
682 struct ast_bridge_thread_obj *tobj;
684 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) XXX\n", chan->name, peer->name, sense);
685 if (sense == FEATURE_SENSE_PEER) {
692 if (!(transferer_real_context=pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT")) &&
693 !(transferer_real_context=pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT"))) {
694 /* Use the non-macro context to transfer the call */
695 if (!ast_strlen_zero(transferer->macrocontext))
696 transferer_real_context = transferer->macrocontext;
698 transferer_real_context = transferer->context;
700 /* Start autoservice on chan while we talk
702 ast_indicate(transferee, AST_CONTROL_HOLD);
703 ast_autoservice_start(transferee);
704 ast_moh_start(transferee, NULL);
705 memset(xferto, 0, sizeof(xferto));
707 if ((res = ast_streamfile(transferer, "pbx-transfer", transferer->language))) {
708 ast_moh_stop(transferee);
709 ast_autoservice_stop(transferee);
710 ast_indicate(transferee, AST_CONTROL_UNHOLD);
713 if ((res=ast_waitstream(transferer, AST_DIGIT_ANY)) < 0) {
714 ast_moh_stop(transferee);
715 ast_autoservice_stop(transferee);
716 ast_indicate(transferee, AST_CONTROL_UNHOLD);
719 /* If they've typed a digit already, handle it */
720 xferto[0] = (char) res;
722 if ((ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout))) {
723 cid_num = transferer->cid.cid_num;
724 cid_name = transferer->cid.cid_name;
725 if (ast_exists_extension(transferer, transferer_real_context,xferto, 1, cid_num)) {
726 snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context);
727 newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats), dialstr, 15000, &outstate, cid_num, cid_name);
728 ast_indicate(transferer, -1);
730 res = ast_channel_make_compatible(transferer, newchan);
732 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
736 memset(&bconfig,0,sizeof(struct ast_bridge_config));
737 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
738 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
739 res = ast_bridge_call(transferer,newchan,&bconfig);
740 if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
746 if (!ast_strlen_zero(xfersound) && !ast_streamfile(transferer, xfersound, transferer->language)) {
747 if (ast_waitstream(transferer, "") < 0) {
748 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
751 ast_moh_stop(transferee);
752 ast_autoservice_stop(transferee);
753 ast_indicate(transferee, AST_CONTROL_UNHOLD);
754 transferer->_softhangup = 0;
755 return FEATURE_RETURN_SUCCESS;
758 res = ast_channel_make_compatible(transferee, newchan);
760 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
766 ast_moh_stop(transferee);
768 if ((ast_autoservice_stop(transferee) < 0)
769 || (ast_waitfordigit(transferee, 100) < 0)
770 || (ast_waitfordigit(newchan, 100) < 0)
771 || ast_check_hangup(transferee)
772 || ast_check_hangup(newchan)) {
778 if ((xferchan = ast_channel_alloc(0))) {
779 snprintf(xferchan->name, sizeof (xferchan->name), "Transfered/%s",transferee->name);
780 /* Make formats okay */
781 xferchan->readformat = transferee->readformat;
782 xferchan->writeformat = transferee->writeformat;
783 ast_channel_masquerade(xferchan, transferee);
784 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
785 xferchan->_state = AST_STATE_UP;
786 ast_clear_flag(xferchan, AST_FLAGS_ALL);
787 xferchan->_softhangup = 0;
789 if ((f = ast_read(xferchan))) {
799 newchan->_state = AST_STATE_UP;
800 ast_clear_flag(newchan, AST_FLAGS_ALL);
801 newchan->_softhangup = 0;
803 tobj = malloc(sizeof(struct ast_bridge_thread_obj));
805 memset(tobj,0,sizeof(struct ast_bridge_thread_obj));
806 tobj->chan = xferchan;
807 tobj->peer = newchan;
808 tobj->bconfig = *config;
810 if (!ast_strlen_zero(xfersound) && !ast_streamfile(newchan, xfersound, newchan->language)) {
811 if (ast_waitstream(newchan, "") < 0) {
812 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
815 ast_bridge_call_thread_launch(tobj);
817 ast_log(LOG_WARNING, "Out of memory!\n");
818 ast_hangup(xferchan);
824 ast_moh_stop(transferee);
825 ast_autoservice_stop(transferee);
826 ast_indicate(transferee, AST_CONTROL_UNHOLD);
827 /* any reason besides user requested cancel and busy triggers the failed sound */
828 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY && !ast_strlen_zero(xferfailsound)) {
829 res = ast_streamfile(transferer, xferfailsound, transferer->language);
830 if (!res && (ast_waitstream(transferer, "") < 0)) {
834 return FEATURE_RETURN_SUCCESS;
837 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
838 ast_moh_stop(transferee);
839 ast_autoservice_stop(transferee);
840 ast_indicate(transferee, AST_CONTROL_UNHOLD);
841 res = ast_streamfile(transferer, "beeperr", transferer->language);
842 if (!res && (ast_waitstream(transferer, "") < 0)) {
847 ast_log(LOG_WARNING, "Did not read data.\n");
848 res = ast_streamfile(transferer, "beeperr", transferer->language);
849 if (ast_waitstream(transferer, "") < 0) {
853 ast_moh_stop(transferee);
854 ast_autoservice_stop(transferee);
855 ast_indicate(transferee, AST_CONTROL_UNHOLD);
857 return FEATURE_RETURN_SUCCESS;
861 /* add atxfer and automon as undefined so you can only use em if you configure them */
862 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
863 struct ast_call_feature builtin_features[] =
865 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
866 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
867 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
868 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
872 static AST_LIST_HEAD(feature_list,ast_call_feature) feature_list;
874 /* register new feature into feature_list*/
875 void ast_register_feature(struct ast_call_feature *feature)
878 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
882 AST_LIST_LOCK(&feature_list);
883 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
884 AST_LIST_UNLOCK(&feature_list);
886 if (option_verbose >= 2)
887 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
890 /* unregister feature from feature_list */
891 void ast_unregister_feature(struct ast_call_feature *feature)
893 if (!feature) return;
895 AST_LIST_LOCK(&feature_list);
896 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
897 AST_LIST_UNLOCK(&feature_list);
901 static void ast_unregister_features(void)
903 struct ast_call_feature *feature;
905 AST_LIST_LOCK(&feature_list);
906 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
908 AST_LIST_UNLOCK(&feature_list);
911 /* find a feature by name */
912 static struct ast_call_feature *find_feature(char *name)
914 struct ast_call_feature *tmp;
916 AST_LIST_LOCK(&feature_list);
917 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
918 if (!strcasecmp(tmp->sname, name))
921 AST_LIST_UNLOCK(&feature_list);
926 /* exec an app by feature */
927 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
930 struct ast_call_feature *feature;
933 AST_LIST_LOCK(&feature_list);
934 AST_LIST_TRAVERSE(&feature_list,feature,feature_entry) {
935 if (!strcasecmp(feature->exten,code)) break;
937 AST_LIST_UNLOCK(&feature_list);
939 if (!feature) { /* shouldn't ever happen! */
940 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
944 app = pbx_findapp(feature->app);
946 struct ast_channel *work=chan;
947 if (ast_test_flag(feature,AST_FEATURE_FLAG_CALLEE)) work=peer;
948 res = pbx_exec(work, app, feature->app_args, 1);
949 if (res<0) return res;
951 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
955 return FEATURE_RETURN_SUCCESS;
958 static void unmap_features(void)
961 for (x = 0; x < FEATURES_COUNT; x++)
962 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
965 static int remap_feature(const char *name, const char *value)
969 for (x = 0; x < FEATURES_COUNT; x++) {
970 if (!strcasecmp(name, builtin_features[x].sname)) {
971 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
972 if (option_verbose > 1)
973 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);
975 } else if (!strcmp(value, builtin_features[x].exten))
976 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);
981 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
984 struct ast_flags features;
985 int res = FEATURE_RETURN_PASSDIGITS;
986 struct ast_call_feature *feature;
987 const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
989 if (sense == FEATURE_SENSE_CHAN)
990 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
992 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
993 ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
995 for (x=0; x < FEATURES_COUNT; x++) {
996 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
997 !ast_strlen_zero(builtin_features[x].exten)) {
998 /* Feature is up for consideration */
999 if (!strcmp(builtin_features[x].exten, code)) {
1000 res = builtin_features[x].operation(chan, peer, config, code, sense);
1002 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1003 if (res == FEATURE_RETURN_PASSDIGITS)
1004 res = FEATURE_RETURN_STOREDIGITS;
1010 if (!ast_strlen_zero(dynamic_features)) {
1011 char *tmp = ast_strdupa(dynamic_features);
1017 while ((tok = strsep(&tmp, "#")) != NULL) {
1018 feature = find_feature(tok);
1021 /* Feature is up for consideration */
1022 if (!strcmp(feature->exten, code)) {
1023 if (option_verbose > 2)
1024 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
1025 res = feature->operation(chan, peer, config, code, sense);
1027 } else if (!strncmp(feature->exten, code, strlen(code))) {
1028 res = FEATURE_RETURN_STOREDIGITS;
1037 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1041 ast_clear_flag(config, AST_FLAGS_ALL);
1042 for (x = 0; x < FEATURES_COUNT; x++) {
1043 if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
1044 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1045 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1047 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1048 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1052 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1053 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1055 if (dynamic_features) {
1056 char *tmp = ast_strdupa(dynamic_features);
1058 struct ast_call_feature *feature;
1064 /* while we have a feature */
1065 while (NULL != (tok = strsep(&tmp, "#"))) {
1066 if ((feature = find_feature(tok))) {
1067 if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1068 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
1069 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1070 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
1071 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1080 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)
1085 struct ast_channel *chan;
1086 struct ast_channel *monitor_chans[2];
1087 struct ast_channel *active_channel;
1088 struct ast_frame *f = NULL;
1089 int res = 0, ready = 0;
1091 if ((chan = ast_request(type, format, data, &cause))) {
1092 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1093 ast_channel_inherit_variables(caller, chan);
1094 if (!ast_call(chan, data, timeout)) {
1095 struct timeval started;
1097 char *disconnect_code = NULL, *dialed_code = NULL;
1099 ast_indicate(caller, AST_CONTROL_RINGING);
1100 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1101 for (x=0; x < FEATURES_COUNT; x++) {
1102 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1105 disconnect_code = builtin_features[x].exten;
1106 len = strlen(disconnect_code) + 1;
1107 dialed_code = alloca(len);
1108 memset(dialed_code, 0, len);
1112 started = ast_tvnow();
1114 while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1115 monitor_chans[0] = caller;
1116 monitor_chans[1] = chan;
1117 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1119 /* see if the timeout has been violated */
1120 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1121 state = AST_CONTROL_UNHOLD;
1122 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1123 break; /*doh! timeout*/
1126 if (!active_channel) {
1130 if (chan && (chan == active_channel)){
1132 if (f == NULL) { /*doh! where'd he go?*/
1133 state = AST_CONTROL_HANGUP;
1138 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1139 if (f->subclass == AST_CONTROL_RINGING) {
1140 state = f->subclass;
1141 if (option_verbose > 2)
1142 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1143 ast_indicate(caller, AST_CONTROL_RINGING);
1144 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1145 state = f->subclass;
1149 } else if (f->subclass == AST_CONTROL_ANSWER) {
1150 /* This is what we are hoping for */
1151 state = f->subclass;
1157 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1159 /* else who cares */
1162 } else if (caller && (active_channel == caller)) {
1163 f = ast_read(caller);
1164 if (f == NULL) { /*doh! where'd he go?*/
1165 if (caller->_softhangup && !chan->_softhangup) {
1166 /* make this a blind transfer */
1170 state = AST_CONTROL_HANGUP;
1175 if (f->frametype == AST_FRAME_DTMF) {
1176 dialed_code[x++] = f->subclass;
1177 dialed_code[x] = '\0';
1178 if (strlen(dialed_code) == len) {
1180 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1182 dialed_code[x] = '\0';
1184 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1185 /* Caller Canceled the call */
1186 state = AST_CONTROL_UNHOLD;
1198 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1200 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1202 case AST_CAUSE_BUSY:
1203 state = AST_CONTROL_BUSY;
1205 case AST_CAUSE_CONGESTION:
1206 state = AST_CONTROL_CONGESTION;
1211 ast_indicate(caller, -1);
1212 if (chan && ready) {
1213 if (chan->_state == AST_STATE_UP)
1214 state = AST_CONTROL_ANSWER;
1227 if (chan && res <= 0) {
1229 chan->cdr = ast_cdr_alloc();
1233 ast_cdr_init(chan->cdr, chan);
1234 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1235 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1236 ast_cdr_update(chan);
1237 ast_cdr_start(chan->cdr);
1238 ast_cdr_end(chan->cdr);
1239 /* If the cause wasn't handled properly */
1240 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1241 ast_cdr_failed(chan->cdr);
1243 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1250 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1252 /* Copy voice back and forth between the two channels. Give the peer
1253 the ability to transfer calls with '#<extension' syntax. */
1254 struct ast_frame *f;
1255 struct ast_channel *who;
1256 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1257 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1262 struct ast_option_header *aoh;
1263 struct timeval start = { 0 , 0 };
1264 struct ast_bridge_config backup_config;
1266 memset(&backup_config, 0, sizeof(backup_config));
1268 config->start_time = ast_tvnow();
1271 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1272 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1274 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1277 const char *monitor_exec;
1278 struct ast_channel *src = NULL;
1280 if (!(monitor_app = pbx_findapp("Monitor")))
1283 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1285 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1288 char *tmp = ast_strdupa(monitor_exec);
1290 pbx_exec(src, monitor_app, tmp, 1);
1292 ast_log(LOG_ERROR, "Monitor failed: out of memory\n");
1297 set_config_flags(chan, peer, config);
1298 config->firstpass = 1;
1300 /* Answer if need be */
1301 if (ast_answer(chan))
1303 peer->appl = "Bridged Call";
1304 peer->data = chan->name;
1306 /* copy the userfield from the B-leg to A-leg if applicable */
1307 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1309 if (!ast_strlen_zero(chan->cdr->userfield)) {
1310 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1311 ast_cdr_appenduserfield(chan, tmp);
1313 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1314 /* free the peer's cdr without ast_cdr_free complaining */
1319 if (config->feature_timer)
1320 start = ast_tvnow();
1322 res = ast_channel_bridge(chan, peer, config, &f, &who);
1324 if (config->feature_timer) {
1325 /* Update time limit for next pass */
1326 diff = ast_tvdiff_ms(ast_tvnow(), start);
1327 config->feature_timer -= diff;
1329 /* Running on backup config, meaning a feature might be being
1330 activated, but that's no excuse to keep things going
1332 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1333 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1334 config->feature_timer = 0;
1340 } else if (config->feature_timer <= 0) {
1341 /* Not *really* out of time, just out of time for
1342 digits to come in for features. */
1343 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1344 if (!ast_strlen_zero(peer_featurecode)) {
1345 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1346 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1348 if (!ast_strlen_zero(chan_featurecode)) {
1349 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1350 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1354 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1356 /* Restore original (possibly time modified) bridge config */
1357 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1358 memset(&backup_config, 0, sizeof(backup_config));
1360 hadfeatures = hasfeatures;
1361 /* Continue as we were */
1365 if (config->feature_timer <=0) {
1366 /* We ran out of time */
1367 config->feature_timer = 0;
1377 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1381 if (!f || ((f->frametype == AST_FRAME_CONTROL) && ((f->subclass == AST_CONTROL_HANGUP) || (f->subclass == AST_CONTROL_BUSY) ||
1382 (f->subclass == AST_CONTROL_CONGESTION)))) {
1386 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RINGING)) {
1388 ast_indicate(peer, AST_CONTROL_RINGING);
1390 ast_indicate(chan, AST_CONTROL_RINGING);
1392 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == -1)) {
1394 ast_indicate(peer, -1);
1396 ast_indicate(chan, -1);
1398 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_FLASH)) {
1400 ast_indicate(peer, AST_CONTROL_FLASH);
1402 ast_indicate(chan, AST_CONTROL_FLASH);
1404 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_OPTION)) {
1406 /* Forward option Requests */
1407 if (aoh && (aoh->flag == AST_OPTION_FLAG_REQUEST)) {
1409 ast_channel_setoption(peer, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1411 ast_channel_setoption(chan, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1414 /* check for '*', if we find it it's time to disconnect */
1415 if (f && (f->frametype == AST_FRAME_DTMF)) {
1418 struct ast_channel *other;
1420 hadfeatures = hasfeatures;
1421 /* This cannot overrun because the longest feature is one shorter than our buffer */
1424 sense = FEATURE_SENSE_CHAN;
1425 featurecode = chan_featurecode;
1428 sense = FEATURE_SENSE_PEER;
1429 featurecode = peer_featurecode;
1431 featurecode[strlen(featurecode)] = f->subclass;
1432 config->feature_timer = backup_config.feature_timer;
1433 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1435 case FEATURE_RETURN_PASSDIGITS:
1436 ast_dtmf_stream(other, who, featurecode, 0);
1438 case FEATURE_RETURN_SUCCESS:
1439 memset(featurecode, 0, sizeof(chan_featurecode));
1442 if (res >= FEATURE_RETURN_PASSDIGITS) {
1448 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1449 if (hadfeatures && !hasfeatures) {
1450 /* Restore backup */
1451 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1452 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1453 } else if (hasfeatures) {
1455 /* Backup configuration */
1456 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1457 /* Setup temporary config options */
1458 config->play_warning = 0;
1459 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1460 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1461 config->warning_freq = 0;
1462 config->warning_sound = NULL;
1463 config->end_sound = NULL;
1464 config->start_sound = NULL;
1465 config->firstpass = 0;
1467 config->feature_timer = featuredigittimeout;
1468 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1477 static void *do_parking_thread(void *ignore)
1480 struct parkeduser *pu, *pl, *pt = NULL;
1482 struct ast_frame *f;
1483 char exten[AST_MAX_EXTENSION];
1485 char returnexten[AST_MAX_EXTENSION];
1486 struct ast_context *con;
1489 fd_set nrfds, nefds;
1496 ast_mutex_lock(&parking_lock);
1502 if (pu->notquiteyet) {
1503 /* Pretend this one isn't here yet */
1508 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1509 if (tms > pu->parkingtime) {
1510 /* Stop music on hold */
1511 ast_moh_stop(pu->chan);
1512 ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
1513 /* Get chan, exten from derived kludge */
1514 if (pu->peername[0]) {
1515 peername = ast_strdupa(pu->peername);
1516 cp = strrchr(peername, '-');
1519 con = ast_context_find(parking_con_dial);
1521 con = ast_context_create(NULL, parking_con_dial, registrar);
1523 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1527 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1528 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
1530 ast_copy_string(pu->chan->exten, peername, sizeof(pu->chan->exten));
1531 ast_copy_string(pu->chan->context, parking_con_dial, sizeof(pu->chan->context));
1532 pu->chan->priority = 1;
1535 /* They've been waiting too long, send them back to where they came. Theoretically they
1536 should have their original extensions and such, but we copy to be on the safe side */
1537 ast_copy_string(pu->chan->exten, pu->exten, sizeof(pu->chan->exten));
1538 ast_copy_string(pu->chan->context, pu->context, sizeof(pu->chan->context));
1539 pu->chan->priority = pu->priority;
1542 manager_event(EVENT_FLAG_CALL, "ParkedCallTimeOut",
1546 "CallerIDName: %s\r\n\r\n"
1547 ,pu->parkingnum, pu->chan->name
1548 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1549 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1552 if (option_verbose > 1)
1553 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);
1554 /* Start up the PBX, or hang them up */
1555 if (ast_pbx_start(pu->chan)) {
1556 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
1557 ast_hangup(pu->chan);
1559 /* And take them out of the parking lot */
1561 pl->next = pu->next;
1563 parkinglot = pu->next;
1566 con = ast_context_find(parking_con);
1568 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1569 if (ast_context_remove_extension2(con, exten, 1, NULL))
1570 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1572 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1575 for (x = 0; x < AST_MAX_FDS; x++) {
1576 if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
1577 if (FD_ISSET(pu->chan->fds[x], &efds))
1578 ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
1580 ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
1582 /* See if they need servicing */
1583 f = ast_read(pu->chan);
1584 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
1586 manager_event(EVENT_FLAG_CALL, "ParkedCallGiveUp",
1590 "CallerIDName: %s\r\n\r\n"
1591 ,pu->parkingnum, pu->chan->name
1592 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1593 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1596 /* There's a problem, hang them up*/
1597 if (option_verbose > 1)
1598 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", pu->chan->name);
1599 ast_hangup(pu->chan);
1600 /* And take them out of the parking lot */
1602 pl->next = pu->next;
1604 parkinglot = pu->next;
1607 con = ast_context_find(parking_con);
1609 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1610 if (ast_context_remove_extension2(con, exten, 1, NULL))
1611 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1613 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1617 /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1619 if (pu->moh_trys < 3 && !pu->chan->generatordata) {
1620 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
1621 ast_moh_start(pu->chan, NULL);
1624 goto std; /* XXX Ick: jumping into an else statement??? XXX */
1628 if (x >= AST_MAX_FDS) {
1629 std: for (x=0; x<AST_MAX_FDS; x++) {
1630 /* Keep this one for next one */
1631 if (pu->chan->fds[x] > -1) {
1632 FD_SET(pu->chan->fds[x], &nrfds);
1633 FD_SET(pu->chan->fds[x], &nefds);
1634 if (pu->chan->fds[x] > max)
1635 max = pu->chan->fds[x];
1638 /* Keep track of our longest wait */
1639 if ((tms < ms) || (ms < 0))
1646 ast_mutex_unlock(&parking_lock);
1649 tv = ast_samp2tv(ms, 1000);
1650 /* Wait for something to happen */
1651 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1652 pthread_testcancel();
1654 return NULL; /* Never reached */
1657 static int park_call_exec(struct ast_channel *chan, void *data)
1659 /* Data is unused at the moment but could contain a parking
1660 lot context eventually */
1662 struct localuser *u;
1664 /* Setup the exten/priority to be s/1 since we don't know
1665 where this call should return */
1666 strcpy(chan->exten, "s");
1668 if (chan->_state != AST_STATE_UP)
1669 res = ast_answer(chan);
1671 res = ast_safe_sleep(chan, 1000);
1673 res = ast_park_call(chan, chan, 0, NULL);
1674 LOCAL_USER_REMOVE(u);
1676 res = AST_PBX_KEEPALIVE;
1680 static int park_exec(struct ast_channel *chan, void *data)
1683 struct localuser *u;
1684 struct ast_channel *peer=NULL;
1685 struct parkeduser *pu, *pl=NULL;
1686 char exten[AST_MAX_EXTENSION];
1687 struct ast_context *con;
1690 struct ast_bridge_config config;
1693 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
1697 park = atoi((char *)data);
1698 ast_mutex_lock(&parking_lock);
1701 if (pu->parkingnum == park) {
1703 pl->next = pu->next;
1705 parkinglot = pu->next;
1711 ast_mutex_unlock(&parking_lock);
1714 con = ast_context_find(parking_con);
1716 snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
1717 if (ast_context_remove_extension2(con, exten, 1, NULL))
1718 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1720 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1722 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
1727 "CallerIDName: %s\r\n\r\n"
1728 ,pu->parkingnum, pu->chan->name, chan->name
1729 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
1730 ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
1735 /* JK02: it helps to answer the channel if not already up */
1736 if (chan->_state != AST_STATE_UP) {
1741 /* Play a courtesy beep in the calling channel to prefix the bridge connecting */
1742 if (!ast_strlen_zero(courtesytone)) {
1743 if (!ast_streamfile(chan, courtesytone, chan->language)) {
1744 if (ast_waitstream(chan, "") < 0) {
1745 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1753 ast_indicate(peer, AST_CONTROL_UNHOLD);
1754 res = ast_channel_make_compatible(chan, peer);
1756 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1760 /* This runs sorta backwards, since we give the incoming channel control, as if it
1761 were the person called. */
1762 if (option_verbose > 2)
1763 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1765 memset(&config, 0, sizeof(struct ast_bridge_config));
1766 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1767 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1768 config.timelimit = 0;
1769 config.play_warning = 0;
1770 config.warning_freq = 0;
1771 config.warning_sound=NULL;
1772 res = ast_bridge_call(chan, peer, &config);
1774 /* Simulate the PBX hanging up */
1775 if (res != AST_PBX_NO_HANGUP_PEER)
1779 /* XXX Play a message XXX */
1780 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
1782 dres = ast_waitstream(chan, "");
1784 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1787 if (option_verbose > 2)
1788 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1791 LOCAL_USER_REMOVE(u);
1795 static int handle_showfeatures(int fd, int argc, char *argv[])
1799 struct ast_call_feature *feature;
1800 char format[] = "%-25s %-7s %-7s\n";
1802 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1803 ast_cli(fd, format, "---------------", "-------", "-------");
1805 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
1807 fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1809 for (i = 0; i < fcount; i++)
1811 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1814 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1815 ast_cli(fd, format, "---------------", "-------", "-------");
1816 if (AST_LIST_EMPTY(&feature_list)) {
1817 ast_cli(fd, "(none)\n");
1820 AST_LIST_LOCK(&feature_list);
1821 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1822 ast_cli(fd, format, feature->sname, "no def", feature->exten);
1824 AST_LIST_UNLOCK(&feature_list);
1826 ast_cli(fd, "\nCall parking\n");
1827 ast_cli(fd, "------------\n");
1828 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
1829 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
1830 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1833 return RESULT_SUCCESS;
1836 static char showfeatures_help[] =
1837 "Usage: show features\n"
1838 " Lists currently configured features.\n";
1840 static struct ast_cli_entry showfeatures =
1841 { { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
1843 static int handle_parkedcalls(int fd, int argc, char *argv[])
1845 struct parkeduser *cur;
1848 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1849 , "Context", "Extension", "Pri", "Timeout");
1851 ast_mutex_lock(&parking_lock);
1855 ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
1856 ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
1857 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1862 ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
1864 ast_mutex_unlock(&parking_lock);
1866 return RESULT_SUCCESS;
1869 static char showparked_help[] =
1870 "Usage: show parkedcalls\n"
1871 " Lists currently parked calls.\n";
1873 static struct ast_cli_entry showparked =
1874 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1876 /* Dump lot status */
1877 static int manager_parking_status( struct mansession *s, struct message *m )
1879 struct parkeduser *cur;
1880 char *id = astman_get_header(m,"ActionID");
1881 char idText[256] = "";
1883 if (!ast_strlen_zero(id))
1884 snprintf(idText,256,"ActionID: %s\r\n",id);
1886 astman_send_ack(s, m, "Parked calls will follow");
1888 ast_mutex_lock(&parking_lock);
1892 ast_cli(s->fd, "Event: ParkedCall\r\n"
1897 "CallerIDName: %s\r\n"
1900 ,cur->parkingnum, cur->chan->name
1901 ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
1902 ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
1903 ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
1910 "Event: ParkedCallsComplete\r\n"
1914 ast_mutex_unlock(&parking_lock);
1916 return RESULT_SUCCESS;
1920 int ast_pickup_call(struct ast_channel *chan)
1922 struct ast_channel *cur = NULL;
1925 while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
1928 (chan->pickupgroup & cur->callgroup) &&
1929 ((cur->_state == AST_STATE_RINGING) ||
1930 (cur->_state == AST_STATE_RING))) {
1933 ast_mutex_unlock(&cur->lock);
1937 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
1938 res = ast_answer(chan);
1940 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
1941 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
1943 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
1944 res = ast_channel_masquerade(cur, chan);
1946 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
1947 ast_mutex_unlock(&cur->lock);
1950 ast_log(LOG_DEBUG, "No call pickup possible...\n");
1955 static int load_config(void)
1957 int start = 0, end = 0;
1958 struct ast_context *con = NULL;
1959 struct ast_config *cfg = NULL;
1960 struct ast_variable *var = NULL;
1961 char old_parking_ext[AST_MAX_EXTENSION];
1962 char old_parking_con[AST_MAX_EXTENSION] = "";
1964 if (!ast_strlen_zero(parking_con)) {
1965 strcpy(old_parking_ext, parking_ext);
1966 strcpy(old_parking_con, parking_con);
1969 /* Reset to defaults */
1970 strcpy(parking_con, "parkedcalls");
1971 strcpy(parking_con_dial, "park-dial");
1972 strcpy(parking_ext, "700");
1973 strcpy(pickup_ext, "*8");
1974 courtesytone[0] = '\0';
1975 strcpy(xfersound, "beep");
1976 strcpy(xferfailsound, "pbx-invalid");
1977 parking_start = 701;
1981 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1982 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1984 cfg = ast_config_load("features.conf");
1986 cfg = ast_config_load("parking.conf");
1988 ast_log(LOG_NOTICE, "parking.conf is deprecated in favor of 'features.conf'. Please rename it.\n");
1991 var = ast_variable_browse(cfg, "general");
1993 if (!strcasecmp(var->name, "parkext")) {
1994 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
1995 } else if (!strcasecmp(var->name, "context")) {
1996 ast_copy_string(parking_con, var->value, sizeof(parking_con));
1997 } else if (!strcasecmp(var->name, "parkingtime")) {
1998 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
1999 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2000 parkingtime = DEFAULT_PARK_TIME;
2002 parkingtime = parkingtime * 1000;
2003 } else if (!strcasecmp(var->name, "parkpos")) {
2004 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2005 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);
2007 parking_start = start;
2010 } else if (!strcasecmp(var->name, "findslot")) {
2011 parkfindnext = (!strcasecmp(var->value, "next"));
2012 } else if (!strcasecmp(var->name, "adsipark")) {
2013 adsipark = ast_true(var->value);
2014 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2015 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2016 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2017 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2019 transferdigittimeout = transferdigittimeout * 1000;
2020 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2021 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2022 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2023 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2025 } else if (!strcasecmp(var->name, "courtesytone")) {
2026 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2027 } else if (!strcasecmp(var->name, "xfersound")) {
2028 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2029 } else if (!strcasecmp(var->name, "xferfailsound")) {
2030 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2031 } else if (!strcasecmp(var->name, "pickupexten")) {
2032 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2038 var = ast_variable_browse(cfg, "featuremap");
2040 if (remap_feature(var->name, var->value))
2041 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2045 /* Map a key combination to an application*/
2046 ast_unregister_features();
2047 var = ast_variable_browse(cfg, "applicationmap");
2049 char *tmp_val=strdup(var->value);
2050 char *exten, *party=NULL, *app=NULL, *app_args=NULL;
2053 ast_log(LOG_ERROR, "res_features: strdup failed");
2058 exten=strsep(&tmp_val,",");
2059 if (exten) party=strsep(&tmp_val,",");
2060 if (party) app=strsep(&tmp_val,",");
2062 if (app) app_args=strsep(&tmp_val,",");
2064 if (!(app && strlen(app)) || !(exten && strlen(exten)) || !(party && strlen(party)) || !(var->name && strlen(var->name))) {
2065 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",app,exten,party,var->name);
2072 struct ast_call_feature *feature=find_feature(var->name);
2076 feature=malloc(sizeof(struct ast_call_feature));
2080 ast_log(LOG_NOTICE, "Malloc failed at feature mapping\n");
2086 memset(feature,0,sizeof(struct ast_call_feature));
2087 ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
2088 ast_copy_string(feature->app,app,FEATURE_APP_LEN);
2089 ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
2093 ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
2095 ast_copy_string(feature->exten, exten,sizeof(feature->exten));
2096 feature->operation=feature_exec_app;
2097 ast_set_flag(feature,AST_FEATURE_FLAG_NEEDSDTMF);
2099 if (!strcasecmp(party,"caller"))
2100 ast_set_flag(feature,AST_FEATURE_FLAG_CALLER);
2101 else if (!strcasecmp(party, "callee"))
2102 ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
2104 ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
2109 ast_register_feature(feature);
2111 if (option_verbose >=1) ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);
2116 ast_config_destroy(cfg);
2118 /* Remove the old parking extension */
2119 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2120 ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
2121 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2124 if (!(con = ast_context_find(parking_con))) {
2125 if (!(con = ast_context_create(NULL, parking_con, registrar))) {
2126 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2130 return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
2134 return load_config();
2137 int load_module(void)
2141 AST_LIST_HEAD_INIT(&feature_list);
2142 memset(parking_ext, 0, sizeof(parking_ext));
2143 memset(parking_con, 0, sizeof(parking_con));
2145 if ((res = load_config()))
2147 ast_cli_register(&showparked);
2148 ast_cli_register(&showfeatures);
2149 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2150 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2152 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2154 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2160 int unload_module(void)
2162 STANDARD_HANGUP_LOCALUSERS;
2164 ast_manager_unregister("ParkedCalls");
2165 ast_cli_unregister(&showfeatures);
2166 ast_cli_unregister(&showparked);
2167 ast_unregister_application(parkcall);
2168 return ast_unregister_application(parkedcall);
2171 char *description(void)
2173 return "Call Features Resource";
2178 /* Never allow parking to be unloaded because it will
2179 unresolve needed symbols in the dialer */
2182 STANDARD_USECOUNT(res);
2191 return ASTERISK_GPL_KEY;