2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, 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 features as call pickup, parking and transfer
23 * \author Mark Spencer <markster@digium.com>
34 #include <sys/signal.h>
35 #include <netinet/in.h>
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
41 #include "asterisk/lock.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/options.h"
47 #include "asterisk/causes.h"
48 #include "asterisk/module.h"
49 #include "asterisk/translate.h"
50 #include "asterisk/app.h"
51 #include "asterisk/say.h"
52 #include "asterisk/features.h"
53 #include "asterisk/musiconhold.h"
54 #include "asterisk/config.h"
55 #include "asterisk/cli.h"
56 #include "asterisk/manager.h"
57 #include "asterisk/utils.h"
58 #include "asterisk/adsi.h"
59 #include "asterisk/monitor.h"
61 #ifdef __AST_DEBUG_MALLOC
62 static void FREE(void *ptr)
70 #define DEFAULT_PARK_TIME 45000
71 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
72 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
74 #define AST_MAX_WATCHERS 256
76 static char *parkedcall = "ParkedCall";
78 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
79 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
80 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
81 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
82 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
83 static int parking_start; /*!< First available extension for parking */
84 static int parking_stop; /*!< Last available extension for parking */
86 static char courtesytone[256]; /*!< Courtesy tone */
87 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
88 static char xfersound[256]; /*!< Call transfer sound */
89 static char xferfailsound[256]; /*!< Call transfer failure sound */
91 static int parking_offset;
92 static int parkfindnext;
96 static int transferdigittimeout;
97 static int featuredigittimeout;
99 static char *registrar = "res_features"; /*!< Registrar for operations */
101 /* module and CLI command definitions */
102 static char *synopsis = "Answer a parked call";
104 static char *descrip = "ParkedCall(exten):"
105 "Used to connect to a parked call. This application is always\n"
106 "registered internally and does not need to be explicitly added\n"
107 "into the dialplan, although you should include the 'parkedcalls'\n"
110 static char *parkcall = "Park";
112 static char *synopsis2 = "Park yourself";
114 static char *descrip2 = "Park():"
115 "Used to park yourself (typically in combination with a supervised\n"
116 "transfer to know the parking space). This application is always\n"
117 "registered internally and does not need to be explicitly added\n"
118 "into the dialplan, although you should include the 'parkedcalls'\n"
121 static struct ast_app *monitor_app = NULL;
122 static int monitor_ok = 1;
125 struct ast_channel *chan;
126 struct timeval start;
128 /* Where to go if our parking time expires */
129 char context[AST_MAX_CONTEXT];
130 char exten[AST_MAX_EXTENSION];
135 unsigned char moh_trys;
136 struct parkeduser *next;
139 static struct parkeduser *parkinglot;
141 AST_MUTEX_DEFINE_STATIC(parking_lock); /*!< protects all static variables above */
143 static pthread_t parking_thread;
145 char *ast_parking_ext(void)
150 char *ast_pickup_ext(void)
155 struct ast_bridge_thread_obj
157 struct ast_bridge_config bconfig;
158 struct ast_channel *chan;
159 struct ast_channel *peer;
162 /*! \brief store context, priority and extension */
163 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
165 ast_copy_string(chan->context, context, sizeof(chan->context));
166 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
167 chan->priority = pri;
170 static void check_goto_on_transfer(struct ast_channel *chan)
172 struct ast_channel *xferchan;
173 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
174 char *x, *goto_on_transfer;
177 if (ast_strlen_zero(val))
180 goto_on_transfer = ast_strdupa(val);
182 if (!(xferchan = ast_channel_alloc(0)))
185 for (x = goto_on_transfer; x && *x; x++) {
189 ast_string_field_set(xferchan, name, chan->name);
190 /* Make formats okay */
191 xferchan->readformat = chan->readformat;
192 xferchan->writeformat = chan->writeformat;
193 ast_channel_masquerade(xferchan, chan);
194 ast_parseable_goto(xferchan, goto_on_transfer);
195 xferchan->_state = AST_STATE_UP;
196 ast_clear_flag(xferchan, AST_FLAGS_ALL);
197 xferchan->_softhangup = 0;
198 if ((f = ast_read(xferchan))) {
201 ast_pbx_start(xferchan);
203 ast_hangup(xferchan);
207 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);
210 static void *ast_bridge_call_thread(void *data)
212 struct ast_bridge_thread_obj *tobj = data;
214 tobj->chan->appl = "Transferred Call";
215 tobj->chan->data = tobj->peer->name;
216 tobj->peer->appl = "Transferred Call";
217 tobj->peer->data = tobj->chan->name;
218 if (tobj->chan->cdr) {
219 ast_cdr_reset(tobj->chan->cdr, NULL);
220 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
222 if (tobj->peer->cdr) {
223 ast_cdr_reset(tobj->peer->cdr, NULL);
224 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
227 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
228 ast_hangup(tobj->chan);
229 ast_hangup(tobj->peer);
230 bzero(tobj, sizeof(*tobj)); /*! \todo XXX for safety */
235 static void ast_bridge_call_thread_launch(void *data)
239 struct sched_param sched;
241 pthread_attr_init(&attr);
242 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
243 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
244 pthread_attr_destroy(&attr);
245 memset(&sched, 0, sizeof(sched));
246 pthread_setschedparam(thread, SCHED_RR, &sched);
249 static int adsi_announce_park(struct ast_channel *chan, int parkingnum)
252 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
254 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
256 snprintf(tmp, sizeof(tmp), "Parked on %d", parkingnum);
258 res = adsi_load_session(chan, NULL, 0, 1);
261 return adsi_print(chan, message, justify, 1);
264 /*! \brief Park a call
265 We put the user in the parking list, then wake up the parking thread to be sure it looks
266 after these channels too */
267 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
269 struct parkeduser *pu, *cur;
270 int i,x,parking_range;
271 char exten[AST_MAX_EXTENSION];
272 struct ast_context *con;
274 if (!(pu = ast_calloc(1, sizeof(*pu)))) {
277 ast_mutex_lock(&parking_lock);
278 parking_range = parking_stop - parking_start+1;
279 for (i = 0; i < parking_range; i++) {
280 x = (i + parking_offset) % parking_range + parking_start;
283 if (cur->parkingnum == x)
291 if (!(i < parking_range)) {
292 ast_log(LOG_WARNING, "No more parking spaces\n");
294 ast_mutex_unlock(&parking_lock);
298 parking_offset = x - parking_start + 1;
299 chan->appl = "Parked Call";
303 /* Start music on hold */
305 ast_indicate(pu->chan, AST_CONTROL_HOLD);
306 ast_moh_start(pu->chan, NULL);
308 pu->start = ast_tvnow();
310 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
314 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
316 /* Remember what had been dialed, so that if the parking
317 expires, we try to come back to the same place */
318 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
319 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
320 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
321 pu->next = parkinglot;
323 /* If parking a channel directly, don't quiet yet get parking running on it */
326 ast_mutex_unlock(&parking_lock);
327 /* Wake up the (presumably select()ing) thread */
328 pthread_kill(parking_thread, SIGURG);
329 if (option_verbose > 1)
330 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));
332 manager_event(EVENT_FLAG_CALL, "ParkedCall",
338 "CallerIDName: %s\r\n",
339 pu->parkingnum, pu->chan->name, peer ? peer->name : "",
340 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
341 S_OR(pu->chan->cid.cid_num, "<unknown>"),
342 S_OR(pu->chan->cid.cid_name, "<unknown>")
346 if (adsipark && adsi_available(peer))
347 adsi_announce_park(peer, pu->parkingnum);
348 if (adsipark && adsi_available(peer))
349 adsi_unload_session(peer);
351 con = ast_context_find(parking_con);
353 con = ast_context_create(NULL, parking_con, registrar);
355 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
358 snprintf(exten, sizeof(exten), "%d", x);
359 ast_add_extension2(con, 1, exten, 1, NULL, NULL, parkedcall, strdup(exten), FREE, registrar);
362 ast_say_digits(peer, pu->parkingnum, "", peer->language);
363 if (pu->notquiteyet) {
364 /* Wake up parking thread if we're really done */
365 ast_moh_start(pu->chan, NULL);
367 pthread_kill(parking_thread, SIGURG);
372 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
374 struct ast_channel *chan;
377 /* Make a new, fake channel that we'll use to masquerade in the real one */
378 if ((chan = ast_channel_alloc(0))) {
379 /* Let us keep track of the channel name */
380 ast_string_field_build(chan, name, "Parked/%s",rchan->name);
382 /* Make formats okay */
383 chan->readformat = rchan->readformat;
384 chan->writeformat = rchan->writeformat;
385 ast_channel_masquerade(chan, rchan);
387 /* Setup the extensions and such */
388 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
390 /* Make the masq execute */
394 ast_park_call(chan, peer, timeout, extout);
396 ast_log(LOG_WARNING, "Unable to create parked channel\n");
403 #define FEATURE_RETURN_HANGUP -1
404 #define FEATURE_RETURN_SUCCESSBREAK 0
405 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
406 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
407 #define FEATURE_RETURN_PASSDIGITS 21
408 #define FEATURE_RETURN_STOREDIGITS 22
409 #define FEATURE_RETURN_SUCCESS 23
411 #define FEATURE_SENSE_CHAN (1 << 0)
412 #define FEATURE_SENSE_PEER (1 << 1)
415 * set caller and callee according to the direction
417 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
418 struct ast_channel *peer, struct ast_channel *chan, int sense)
420 if (sense == FEATURE_SENSE_PEER) {
429 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
431 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
434 struct ast_channel *caller_chan, *callee_chan;
437 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
441 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
443 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
447 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
449 if (!ast_strlen_zero(courtesytone)) {
450 if (ast_autoservice_start(callee_chan))
452 if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
453 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
454 ast_autoservice_stop(callee_chan);
457 if (ast_autoservice_stop(callee_chan))
461 if (callee_chan->monitor) {
462 if (option_verbose > 3)
463 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
464 ast_monitor_stop(callee_chan, 1);
465 return FEATURE_RETURN_SUCCESS;
468 if (caller_chan && callee_chan) {
469 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
470 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
473 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
476 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
479 len = strlen(touch_monitor) + 50;
481 touch_filename = alloca(len);
482 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
483 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
485 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
486 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
487 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
489 touch_filename = alloca(len);
490 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
491 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
494 for( x = 0; x < strlen(args); x++) {
499 if (option_verbose > 3)
500 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
502 pbx_exec(callee_chan, monitor_app, args);
503 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
504 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
506 return FEATURE_RETURN_SUCCESS;
509 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
513 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
515 if (option_verbose > 3)
516 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
517 return FEATURE_RETURN_HANGUP;
520 static int finishup(struct ast_channel *chan)
525 res = ast_autoservice_stop(chan);
526 ast_indicate(chan, AST_CONTROL_UNHOLD);
530 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
532 const char *s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
533 if (ast_strlen_zero(s))
534 s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
535 if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
536 s = transferer->macrocontext;
537 if (ast_strlen_zero(s))
538 s = transferer->context;
542 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
544 struct ast_channel *transferer;
545 struct ast_channel *transferee;
546 const char *transferer_real_context;
550 set_peers(&transferer, &transferee, peer, chan, sense);
551 transferer_real_context = real_ctx(transferer, transferee);
552 /* Start autoservice on chan while we talk to the originator */
553 ast_indicate(transferee, AST_CONTROL_HOLD);
554 ast_autoservice_start(transferee);
555 ast_moh_start(transferee, NULL);
557 memset(xferto, 0, sizeof(xferto));
560 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
562 finishup(transferee);
563 return -1; /* error ? */
565 if (res > 0) /* If they've typed a digit already, handle it */
566 xferto[0] = (char) res;
568 ast_stopstream(transferer);
569 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
570 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
571 finishup(transferee);
574 if (!strcmp(xferto, ast_parking_ext())) {
575 res = finishup(transferee);
578 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
579 /* We return non-zero, but tell the PBX not to hang the channel when
580 the thread dies -- We have to be careful now though. We are responsible for
581 hanging up the channel, else it will never be hung up! */
583 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
585 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
587 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
588 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
589 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
590 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
591 res=finishup(transferee);
592 if (!transferee->pbx) {
593 /* Doh! Use our handy async_goto functions */
594 if (option_verbose > 2)
595 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
596 ,transferee->name, xferto, transferer_real_context);
597 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
598 ast_log(LOG_WARNING, "Async goto failed :-(\n");
601 /* Set the channel's new extension, since it exists, using transferer context */
602 set_c_e_p(transferee, transferer_real_context, xferto, 0);
604 check_goto_on_transfer(transferer);
607 if (option_verbose > 2)
608 ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
610 if (ast_stream_and_wait(transferer, xferfailsound, transferee->language, AST_DIGIT_ANY) < 0 ) {
611 finishup(transferee);
614 ast_stopstream(transferer);
615 res = finishup(transferee);
617 if (option_verbose > 1)
618 ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
621 return FEATURE_RETURN_SUCCESS;
624 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
626 if (ast_channel_make_compatible(c, newchan) < 0) {
627 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
628 c->name, newchan->name);
635 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
637 struct ast_channel *transferer;
638 struct ast_channel *transferee;
639 const char *transferer_real_context;
643 struct ast_channel *newchan;
644 struct ast_channel *xferchan;
645 struct ast_bridge_thread_obj *tobj;
646 struct ast_bridge_config bconfig;
651 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
652 set_peers(&transferer, &transferee, peer, chan, sense);
653 transferer_real_context = real_ctx(transferer, transferee);
654 /* Start autoservice on chan while we talk to the originator */
655 ast_indicate(transferee, AST_CONTROL_HOLD);
656 ast_autoservice_start(transferee);
657 ast_moh_start(transferee, NULL);
658 memset(xferto, 0, sizeof(xferto));
660 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
662 finishup(transferee);
665 if (res > 0) /* If they've typed a digit already, handle it */
666 xferto[0] = (char) res;
668 /* this is specific of atxfer */
669 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
670 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
671 finishup(transferee);
675 ast_log(LOG_WARNING, "Did not read data.\n");
676 finishup(transferee);
677 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
679 return FEATURE_RETURN_SUCCESS;
682 /* valid extension, res == 1 */
683 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
684 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
685 finishup(transferee);
686 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
688 return FEATURE_RETURN_SUCCESS;
692 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
693 newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
694 xferto, 15000, &outstate, transferer->cid.cid_num, transferer->cid.cid_name);
695 ast_indicate(transferer, -1);
697 finishup(transferee);
698 /* any reason besides user requested cancel and busy triggers the failed sound */
699 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
700 ast_stream_and_wait(transferer, xferfailsound, transferer->language, ""))
702 return FEATURE_RETURN_SUCCESS;
705 if (check_compat(transferer, newchan))
707 memset(&bconfig,0,sizeof(struct ast_bridge_config));
708 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
709 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
710 res = ast_bridge_call(transferer, newchan, &bconfig);
711 if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
713 if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
714 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
715 finishup(transferee);
716 transferer->_softhangup = 0;
717 return FEATURE_RETURN_SUCCESS;
720 if (check_compat(transferee, newchan))
723 ast_moh_stop(transferee);
725 if ((ast_autoservice_stop(transferee) < 0)
726 || (ast_waitfordigit(transferee, 100) < 0)
727 || (ast_waitfordigit(newchan, 100) < 0)
728 || ast_check_hangup(transferee)
729 || ast_check_hangup(newchan)) {
734 xferchan = ast_channel_alloc(0);
739 ast_string_field_build(xferchan, name, "Transfered/%s", transferee->name);
740 /* Make formats okay */
741 xferchan->readformat = transferee->readformat;
742 xferchan->writeformat = transferee->writeformat;
743 ast_channel_masquerade(xferchan, transferee);
744 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
745 xferchan->_state = AST_STATE_UP;
746 ast_clear_flag(xferchan, AST_FLAGS_ALL);
747 xferchan->_softhangup = 0;
749 if ((f = ast_read(xferchan)))
752 newchan->_state = AST_STATE_UP;
753 ast_clear_flag(newchan, AST_FLAGS_ALL);
754 newchan->_softhangup = 0;
756 tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
758 ast_hangup(xferchan);
762 tobj->chan = xferchan;
763 tobj->peer = newchan;
764 tobj->bconfig = *config;
766 if (ast_stream_and_wait(newchan, xfersound, newchan->language, ""))
767 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
768 ast_bridge_call_thread_launch(tobj);
769 return -1; /* XXX meaning the channel is bridged ? */
773 /* add atxfer and automon as undefined so you can only use em if you configure them */
774 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
776 struct ast_call_feature builtin_features[] =
778 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF },
779 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF },
780 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF },
781 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF },
785 static AST_LIST_HEAD(feature_list,ast_call_feature) feature_list;
787 /*! \brief register new feature into feature_list*/
788 void ast_register_feature(struct ast_call_feature *feature)
791 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
795 AST_LIST_LOCK(&feature_list);
796 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
797 AST_LIST_UNLOCK(&feature_list);
799 if (option_verbose >= 2)
800 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
803 /*! \brief unregister feature from feature_list */
804 void ast_unregister_feature(struct ast_call_feature *feature)
809 AST_LIST_LOCK(&feature_list);
810 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
811 AST_LIST_UNLOCK(&feature_list);
815 static void ast_unregister_features(void)
817 struct ast_call_feature *feature;
819 AST_LIST_LOCK(&feature_list);
820 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
822 AST_LIST_UNLOCK(&feature_list);
825 /*! \brief find a feature by name */
826 static struct ast_call_feature *find_feature(char *name)
828 struct ast_call_feature *tmp;
830 AST_LIST_LOCK(&feature_list);
831 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
832 if (!strcasecmp(tmp->sname, name))
835 AST_LIST_UNLOCK(&feature_list);
840 /*! \brief exec an app by feature */
841 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
844 struct ast_call_feature *feature;
847 AST_LIST_LOCK(&feature_list);
848 AST_LIST_TRAVERSE(&feature_list,feature,feature_entry) {
849 if (!strcasecmp(feature->exten,code))
852 AST_LIST_UNLOCK(&feature_list);
854 if (!feature) { /* shouldn't ever happen! */
855 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
859 app = pbx_findapp(feature->app);
861 struct ast_channel *work = ast_test_flag(feature,AST_FEATURE_FLAG_CALLEE) ? peer : chan;
862 res = pbx_exec(work, app, feature->app_args);
866 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
870 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
873 static void unmap_features(void)
876 for (x = 0; x < FEATURES_COUNT; x++)
877 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
880 static int remap_feature(const char *name, const char *value)
884 for (x = 0; x < FEATURES_COUNT; x++) {
885 if (!strcasecmp(name, builtin_features[x].sname)) {
886 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
887 if (option_verbose > 1)
888 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);
890 } else if (!strcmp(value, builtin_features[x].exten))
891 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);
896 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
899 struct ast_flags features;
900 int res = FEATURE_RETURN_PASSDIGITS;
901 struct ast_call_feature *feature;
902 const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
904 if (sense == FEATURE_SENSE_CHAN)
905 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
907 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
908 if (option_debug > 2)
909 ast_log(LOG_DEBUG, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
911 for (x=0; x < FEATURES_COUNT; x++) {
912 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
913 !ast_strlen_zero(builtin_features[x].exten)) {
914 /* Feature is up for consideration */
915 if (!strcmp(builtin_features[x].exten, code)) {
916 res = builtin_features[x].operation(chan, peer, config, code, sense);
918 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
919 if (res == FEATURE_RETURN_PASSDIGITS)
920 res = FEATURE_RETURN_STOREDIGITS;
926 if (!ast_strlen_zero(dynamic_features)) {
927 char *tmp = ast_strdupa(dynamic_features);
930 while ((tok = strsep(&tmp, "#")) != NULL) {
931 feature = find_feature(tok);
934 /* Feature is up for consideration */
935 if (!strcmp(feature->exten, code)) {
936 if (option_verbose > 2)
937 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
938 res = feature->operation(chan, peer, config, code, sense);
940 } else if (!strncmp(feature->exten, code, strlen(code))) {
941 res = FEATURE_RETURN_STOREDIGITS;
950 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
954 ast_clear_flag(config, AST_FLAGS_ALL);
955 for (x = 0; x < FEATURES_COUNT; x++) {
956 if (ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF)) {
957 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
958 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
960 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
961 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
965 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
966 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
968 if (dynamic_features) {
969 char *tmp = ast_strdupa(dynamic_features);
971 struct ast_call_feature *feature;
973 /* while we have a feature */
974 while ((tok = strsep(&tmp, "#"))) {
975 if ((feature = find_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
976 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
977 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
978 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLEE))
979 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
986 /*! \todo XXX Check - this is very similar to the code in channel.c */
987 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)
992 struct ast_channel *chan;
993 struct ast_channel *monitor_chans[2];
994 struct ast_channel *active_channel;
995 int res = 0, ready = 0;
997 if ((chan = ast_request(type, format, data, &cause))) {
998 ast_set_callerid(chan, cid_num, cid_name, cid_num);
999 ast_channel_inherit_variables(caller, chan);
1000 if (!ast_call(chan, data, timeout)) {
1001 struct timeval started;
1003 char *disconnect_code = NULL, *dialed_code = NULL;
1005 ast_indicate(caller, AST_CONTROL_RINGING);
1006 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1007 for (x=0; x < FEATURES_COUNT; x++) {
1008 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1011 disconnect_code = builtin_features[x].exten;
1012 len = strlen(disconnect_code) + 1;
1013 dialed_code = alloca(len);
1014 memset(dialed_code, 0, len);
1018 started = ast_tvnow();
1020 while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
1021 struct ast_frame *f = NULL;
1023 monitor_chans[0] = caller;
1024 monitor_chans[1] = chan;
1025 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1027 /* see if the timeout has been violated */
1028 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1029 state = AST_CONTROL_UNHOLD;
1030 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1031 break; /*doh! timeout*/
1034 if (!active_channel)
1037 if (chan && (chan == active_channel)){
1039 if (f == NULL) { /*doh! where'd he go?*/
1040 state = AST_CONTROL_HANGUP;
1045 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1046 if (f->subclass == AST_CONTROL_RINGING) {
1047 state = f->subclass;
1048 if (option_verbose > 2)
1049 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
1050 ast_indicate(caller, AST_CONTROL_RINGING);
1051 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1052 state = f->subclass;
1053 if (option_verbose > 2)
1054 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
1055 ast_indicate(caller, AST_CONTROL_BUSY);
1059 } else if (f->subclass == AST_CONTROL_ANSWER) {
1060 /* This is what we are hoping for */
1061 state = f->subclass;
1067 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1069 /* else who cares */
1072 } else if (caller && (active_channel == caller)) {
1073 f = ast_read(caller);
1074 if (f == NULL) { /*doh! where'd he go?*/
1075 if (caller->_softhangup && !chan->_softhangup) {
1076 /* make this a blind transfer */
1080 state = AST_CONTROL_HANGUP;
1085 if (f->frametype == AST_FRAME_DTMF) {
1086 dialed_code[x++] = f->subclass;
1087 dialed_code[x] = '\0';
1088 if (strlen(dialed_code) == len) {
1090 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1092 dialed_code[x] = '\0';
1094 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1095 /* Caller Canceled the call */
1096 state = AST_CONTROL_UNHOLD;
1107 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1109 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1111 case AST_CAUSE_BUSY:
1112 state = AST_CONTROL_BUSY;
1114 case AST_CAUSE_CONGESTION:
1115 state = AST_CONTROL_CONGESTION;
1120 ast_indicate(caller, -1);
1121 if (chan && ready) {
1122 if (chan->_state == AST_STATE_UP)
1123 state = AST_CONTROL_ANSWER;
1136 if (chan && res <= 0) {
1137 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1139 ast_cdr_init(chan->cdr, chan);
1140 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1141 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1142 ast_cdr_update(chan);
1143 ast_cdr_start(chan->cdr);
1144 ast_cdr_end(chan->cdr);
1145 /* If the cause wasn't handled properly */
1146 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1147 ast_cdr_failed(chan->cdr);
1149 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1156 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1158 /* Copy voice back and forth between the two channels. Give the peer
1159 the ability to transfer calls with '#<extension' syntax. */
1160 struct ast_frame *f;
1161 struct ast_channel *who;
1162 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1163 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1168 struct ast_option_header *aoh;
1169 struct timeval start = { 0 , 0 };
1170 struct ast_bridge_config backup_config;
1172 memset(&backup_config, 0, sizeof(backup_config));
1174 config->start_time = ast_tvnow();
1177 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1178 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1180 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1183 const char *monitor_exec;
1184 struct ast_channel *src = NULL;
1186 if (!(monitor_app = pbx_findapp("Monitor")))
1189 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1191 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1193 if (monitor_app && src) {
1194 char *tmp = ast_strdupa(monitor_exec);
1195 pbx_exec(src, monitor_app, tmp);
1199 set_config_flags(chan, peer, config);
1200 config->firstpass = 1;
1202 /* Answer if need be */
1203 if (ast_answer(chan))
1205 peer->appl = "Bridged Call";
1206 peer->data = chan->name;
1208 /* copy the userfield from the B-leg to A-leg if applicable */
1209 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1211 if (!ast_strlen_zero(chan->cdr->userfield)) {
1212 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1213 ast_cdr_appenduserfield(chan, tmp);
1215 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1216 /* free the peer's cdr without ast_cdr_free complaining */
1221 struct ast_channel *other; /* used later */
1222 if (config->feature_timer)
1223 start = ast_tvnow();
1225 res = ast_channel_bridge(chan, peer, config, &f, &who);
1227 if (config->feature_timer) {
1228 /* Update time limit for next pass */
1229 diff = ast_tvdiff_ms(ast_tvnow(), start);
1230 config->feature_timer -= diff;
1232 /* Running on backup config, meaning a feature might be being
1233 activated, but that's no excuse to keep things going
1235 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1237 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
1238 config->feature_timer = 0;
1244 } else if (config->feature_timer <= 0) {
1245 /* Not *really* out of time, just out of time for
1246 digits to come in for features. */
1248 ast_log(LOG_DEBUG, "Timed out for feature!\n");
1249 if (!ast_strlen_zero(peer_featurecode)) {
1250 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
1251 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1253 if (!ast_strlen_zero(chan_featurecode)) {
1254 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
1255 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1259 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1261 /* Restore original (possibly time modified) bridge config */
1262 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1263 memset(&backup_config, 0, sizeof(backup_config));
1265 hadfeatures = hasfeatures;
1266 /* Continue as we were */
1270 if (config->feature_timer <=0) {
1271 /* We ran out of time */
1272 config->feature_timer = 0;
1282 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1286 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1287 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1288 f->subclass == AST_CONTROL_CONGESTION ) ) ) {
1292 /* many things should be sent to the 'other' channel */
1293 other = (who == chan) ? peer : chan;
1294 if (f->frametype == AST_FRAME_CONTROL) {
1295 if (f->subclass == AST_CONTROL_RINGING)
1296 ast_indicate(other, AST_CONTROL_RINGING);
1297 else if (f->subclass == -1)
1298 ast_indicate(other, -1);
1299 else if (f->subclass == AST_CONTROL_FLASH)
1300 ast_indicate(other, AST_CONTROL_FLASH);
1301 else if (f->subclass == AST_CONTROL_OPTION) {
1303 /* Forward option Requests */
1304 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST)
1305 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, f->datalen - sizeof(struct ast_option_header), 0);
1308 /* check for '*', if we find it it's time to disconnect */
1309 if (f->frametype == AST_FRAME_DTMF) {
1313 hadfeatures = hasfeatures;
1314 /* This cannot overrun because the longest feature is one shorter than our buffer */
1316 sense = FEATURE_SENSE_CHAN;
1317 featurecode = chan_featurecode;
1319 sense = FEATURE_SENSE_PEER;
1320 featurecode = peer_featurecode;
1322 /*! append the event to featurecode. we rely on the string being zero-filled, and
1323 * not overflowing it.
1324 * \todo XXX how do we guarantee the latter ?
1326 featurecode[strlen(featurecode)] = f->subclass;
1327 config->feature_timer = backup_config.feature_timer;
1328 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1330 case FEATURE_RETURN_PASSDIGITS:
1331 ast_dtmf_stream(other, who, featurecode, 0);
1333 case FEATURE_RETURN_SUCCESS:
1334 memset(featurecode, 0, sizeof(chan_featurecode));
1337 if (res >= FEATURE_RETURN_PASSDIGITS) {
1343 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1344 if (hadfeatures && !hasfeatures) {
1345 /* Restore backup */
1346 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1347 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1348 } else if (hasfeatures) {
1350 /* Backup configuration */
1351 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1352 /* Setup temporary config options */
1353 config->play_warning = 0;
1354 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1355 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1356 config->warning_freq = 0;
1357 config->warning_sound = NULL;
1358 config->end_sound = NULL;
1359 config->start_sound = NULL;
1360 config->firstpass = 0;
1362 config->feature_timer = featuredigittimeout;
1364 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
1373 static void post_manager_event(const char *s, int num, struct ast_channel *chan)
1375 manager_event(EVENT_FLAG_CALL, s,
1379 "CallerIDName: %s\r\n\r\n",
1381 S_OR(chan->cid.cid_num, "<unknown>"),
1382 S_OR(chan->cid.cid_name, "<unknown>")
1386 /*! \brief Take care of parked calls and unpark them if needed */
1387 static void *do_parking_thread(void *ignore)
1389 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
1394 struct parkeduser *pu, *pl, *pt = NULL;
1395 int ms = -1; /* select timeout, uninitialized */
1396 int max = -1; /* max fd, none there yet */
1397 fd_set nrfds, nefds; /* args for the next select */
1401 ast_mutex_lock(&parking_lock);
1404 /* navigate the list with prev-cur pointers to support removals */
1406 struct ast_channel *chan = pu->chan; /* shorthand */
1407 int tms; /* timeout for this item */
1408 int x; /* fd index in channel */
1409 struct ast_context *con;
1411 if (pu->notquiteyet) { /* Pretend this one isn't here yet */
1416 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
1417 if (tms > pu->parkingtime) {
1418 /* Stop music on hold */
1420 ast_indicate(chan, AST_CONTROL_UNHOLD);
1421 /* Get chan, exten from derived kludge */
1422 if (pu->peername[0]) {
1423 char *peername = ast_strdupa(pu->peername);
1424 char *cp = strrchr(peername, '-');
1427 con = ast_context_find(parking_con_dial);
1429 con = ast_context_create(NULL, parking_con_dial, registrar);
1431 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
1435 char returnexten[AST_MAX_EXTENSION];
1436 snprintf(returnexten, sizeof(returnexten), "%s||t", peername);
1437 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), FREE, registrar);
1439 set_c_e_p(chan, parking_con_dial, peername, 1);
1441 /* They've been waiting too long, send them back to where they came. Theoretically they
1442 should have their original extensions and such, but we copy to be on the safe side */
1443 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
1446 post_manager_event("ParkedCallTimeOut", pu->parkingnum, chan);
1448 if (option_verbose > 1)
1449 ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
1450 /* Start up the PBX, or hang them up */
1451 if (ast_pbx_start(chan)) {
1452 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
1455 /* And take them out of the parking lot */
1457 pl->next = pu->next;
1459 parkinglot = pu->next;
1462 con = ast_context_find(parking_con);
1464 char exten[AST_MAX_EXTENSION];
1465 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1466 if (ast_context_remove_extension2(con, exten, 1, NULL))
1467 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1469 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1471 } else { /* still within parking time, process descriptors */
1472 for (x = 0; x < AST_MAX_FDS; x++) {
1473 struct ast_frame *f;
1475 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
1476 continue; /* nothing on this descriptor */
1478 if (FD_ISSET(chan->fds[x], &efds))
1479 ast_set_flag(chan, AST_FLAG_EXCEPTION);
1481 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
1483 /* See if they need servicing */
1485 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
1488 post_manager_event("ParkedCallGiveUp", pu->parkingnum, chan);
1490 /* There's a problem, hang them up*/
1491 if (option_verbose > 1)
1492 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
1494 /* And take them out of the parking lot */
1496 pl->next = pu->next;
1498 parkinglot = pu->next;
1501 con = ast_context_find(parking_con);
1503 char exten[AST_MAX_EXTENSION];
1504 snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
1505 if (ast_context_remove_extension2(con, exten, 1, NULL))
1506 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1508 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1512 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
1514 if (pu->moh_trys < 3 && !chan->generatordata) {
1516 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
1517 ast_moh_start(chan, NULL);
1520 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
1524 if (x >= AST_MAX_FDS) {
1525 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
1526 if (chan->fds[x] > -1) {
1527 FD_SET(chan->fds[x], &nrfds);
1528 FD_SET(chan->fds[x], &nefds);
1529 if (chan->fds[x] > max)
1533 /* Keep track of our shortest wait */
1534 if (tms < ms || ms < 0)
1541 ast_mutex_unlock(&parking_lock);
1545 struct timeval tv = ast_samp2tv(ms, 1000);
1546 /* Wait for something to happen */
1547 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
1549 pthread_testcancel();
1551 return NULL; /* Never reached */
1554 static int park_call_exec(struct ast_channel *chan, void *data)
1556 /* Data is unused at the moment but could contain a parking
1557 lot context eventually */
1559 struct localuser *u;
1561 /* Setup the exten/priority to be s/1 since we don't know
1562 where this call should return */
1563 strcpy(chan->exten, "s");
1565 if (chan->_state != AST_STATE_UP)
1566 res = ast_answer(chan);
1568 res = ast_safe_sleep(chan, 1000);
1570 res = ast_park_call(chan, chan, 0, NULL);
1571 LOCAL_USER_REMOVE(u);
1573 res = AST_PBX_KEEPALIVE;
1577 static int park_exec(struct ast_channel *chan, void *data)
1580 struct localuser *u;
1581 struct ast_channel *peer=NULL;
1582 struct parkeduser *pu, *pl=NULL;
1583 struct ast_context *con;
1585 struct ast_bridge_config config;
1588 ast_log(LOG_WARNING, "Park requires an argument (extension number)\n");
1592 park = atoi((char *)data);
1593 ast_mutex_lock(&parking_lock);
1596 if (pu->parkingnum == park) {
1598 pl->next = pu->next;
1600 parkinglot = pu->next;
1606 ast_mutex_unlock(&parking_lock);
1609 con = ast_context_find(parking_con);
1611 char exten[AST_MAX_EXTENSION];
1612 snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
1613 if (ast_context_remove_extension2(con, exten, 1, NULL))
1614 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
1616 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
1618 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
1623 "CallerIDName: %s\r\n",
1624 pu->parkingnum, pu->chan->name, chan->name,
1625 S_OR(pu->chan->cid.cid_num, "<unknown>"),
1626 S_OR(pu->chan->cid.cid_name, "<unknown>")
1631 /* JK02: it helps to answer the channel if not already up */
1632 if (chan->_state != AST_STATE_UP)
1636 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
1638 if (!ast_strlen_zero(courtesytone)) {
1641 ast_indicate(peer, AST_CONTROL_UNHOLD);
1642 if (parkedplay == 0) {
1643 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
1644 } else if (parkedplay == 1) {
1645 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
1646 } else if (parkedplay == 2) {
1647 if (!ast_streamfile(chan, courtesytone, chan->language) &&
1648 !ast_streamfile(peer, courtesytone, chan->language)) {
1649 /*! \todo XXX we would like to wait on both! */
1650 res = ast_waitstream(chan, "");
1652 res = ast_waitstream(peer, "");
1658 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
1664 ast_indicate(peer, AST_CONTROL_UNHOLD);
1667 res = ast_channel_make_compatible(chan, peer);
1669 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
1673 /* This runs sorta backwards, since we give the incoming channel control, as if it
1674 were the person called. */
1675 if (option_verbose > 2)
1676 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
1678 memset(&config, 0, sizeof(struct ast_bridge_config));
1679 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1680 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1681 config.timelimit = 0;
1682 config.play_warning = 0;
1683 config.warning_freq = 0;
1684 config.warning_sound=NULL;
1685 res = ast_bridge_call(chan, peer, &config);
1687 /* Simulate the PBX hanging up */
1688 if (res != AST_PBX_NO_HANGUP_PEER)
1692 /*! \todo XXX Play a message XXX */
1693 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
1694 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
1695 if (option_verbose > 2)
1696 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
1699 LOCAL_USER_REMOVE(u);
1703 static int handle_showfeatures(int fd, int argc, char *argv[])
1707 struct ast_call_feature *feature;
1708 char format[] = "%-25s %-7s %-7s\n";
1710 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
1711 ast_cli(fd, format, "---------------", "-------", "-------");
1713 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
1715 fcount = sizeof(builtin_features) / sizeof(builtin_features[0]);
1717 for (i = 0; i < fcount; i++)
1719 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
1722 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
1723 ast_cli(fd, format, "---------------", "-------", "-------");
1724 if (AST_LIST_EMPTY(&feature_list)) {
1725 ast_cli(fd, "(none)\n");
1728 AST_LIST_LOCK(&feature_list);
1729 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1730 ast_cli(fd, format, feature->sname, "no def", feature->exten);
1732 AST_LIST_UNLOCK(&feature_list);
1734 ast_cli(fd, "\nCall parking\n");
1735 ast_cli(fd, "------------\n");
1736 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
1737 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
1738 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
1741 return RESULT_SUCCESS;
1744 static char showfeatures_help[] =
1745 "Usage: show features\n"
1746 " Lists currently configured features.\n";
1748 static struct ast_cli_entry showfeatures =
1749 { { "show", "features", NULL }, handle_showfeatures, "Lists configured features", showfeatures_help };
1751 static int handle_parkedcalls(int fd, int argc, char *argv[])
1753 struct parkeduser *cur;
1756 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
1757 , "Context", "Extension", "Pri", "Timeout");
1759 ast_mutex_lock(&parking_lock);
1761 for (cur = parkinglot; cur; cur = cur->next) {
1762 ast_cli(fd, "%4d %25s (%-15s %-12s %-4d) %6lds\n"
1763 ,cur->parkingnum, cur->chan->name, cur->context, cur->exten
1764 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
1768 ast_mutex_unlock(&parking_lock);
1769 ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
1772 return RESULT_SUCCESS;
1775 static char showparked_help[] =
1776 "Usage: show parkedcalls\n"
1777 " Lists currently parked calls.\n";
1779 static struct ast_cli_entry showparked =
1780 { { "show", "parkedcalls", NULL }, handle_parkedcalls, "Lists parked calls", showparked_help };
1782 /*! \brief Dump lot status */
1783 static int manager_parking_status( struct mansession *s, struct message *m )
1785 struct parkeduser *cur;
1786 char *id = astman_get_header(m,"ActionID");
1787 char idText[256] = "";
1789 if (!ast_strlen_zero(id))
1790 snprintf(idText,256,"ActionID: %s\r\n",id);
1792 astman_send_ack(s, m, "Parked calls will follow");
1794 ast_mutex_lock(&parking_lock);
1796 for (cur=parkinglot; cur; cur = cur->next) {
1797 astman_append(s, "Event: ParkedCall\r\n"
1803 "CallerIDName: %s\r\n"
1806 cur->parkingnum, cur->chan->name, cur->peername,
1807 (long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL),
1808 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
1809 S_OR(cur->chan->cid.cid_name, ""),
1814 "Event: ParkedCallsComplete\r\n"
1818 ast_mutex_unlock(&parking_lock);
1820 return RESULT_SUCCESS;
1823 static char mandescr_park[] =
1824 "Description: Park a channel.\n"
1825 "Variables: (Names marked with * are required)\n"
1826 " *Channel: Channel name to park\n"
1827 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
1828 " Timeout: Number of milliseconds to wait before callback.\n";
1830 static int manager_park(struct mansession *s, struct message *m)
1832 char *channel = astman_get_header(m, "Channel");
1833 char *channel2 = astman_get_header(m, "Channel2");
1834 char *timeout = astman_get_header(m, "Timeout");
1839 struct ast_channel *ch1, *ch2;
1841 if (ast_strlen_zero(channel)) {
1842 astman_send_error(s, m, "Channel not specified");
1846 if (ast_strlen_zero(channel2)) {
1847 astman_send_error(s, m, "Channel2 not specified");
1851 ch1 = ast_get_channel_by_name_locked(channel);
1853 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
1854 astman_send_error(s, m, buf);
1858 ch2 = ast_get_channel_by_name_locked(channel2);
1860 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
1861 astman_send_error(s, m, buf);
1862 ast_channel_unlock(ch1);
1866 if (!ast_strlen_zero(timeout)) {
1867 sscanf(timeout, "%d", &to);
1870 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
1872 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
1873 astman_send_ack(s, m, "Park successful");
1875 astman_send_error(s, m, "Park failure");
1878 ast_channel_unlock(ch1);
1879 ast_channel_unlock(ch2);
1885 int ast_pickup_call(struct ast_channel *chan)
1887 struct ast_channel *cur = NULL;
1890 while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
1893 (chan->pickupgroup & cur->callgroup) &&
1894 ((cur->_state == AST_STATE_RINGING) ||
1895 (cur->_state == AST_STATE_RING))) {
1898 ast_channel_unlock(cur);
1902 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
1903 res = ast_answer(chan);
1905 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
1906 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
1908 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
1909 res = ast_channel_masquerade(cur, chan);
1911 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
1912 ast_channel_unlock(cur);
1915 ast_log(LOG_DEBUG, "No call pickup possible...\n");
1920 static int load_config(void)
1922 int start = 0, end = 0;
1923 struct ast_context *con = NULL;
1924 struct ast_config *cfg = NULL;
1925 struct ast_variable *var = NULL;
1926 char old_parking_ext[AST_MAX_EXTENSION];
1927 char old_parking_con[AST_MAX_EXTENSION] = "";
1929 if (!ast_strlen_zero(parking_con)) {
1930 strcpy(old_parking_ext, parking_ext);
1931 strcpy(old_parking_con, parking_con);
1934 /* Reset to defaults */
1935 strcpy(parking_con, "parkedcalls");
1936 strcpy(parking_con_dial, "park-dial");
1937 strcpy(parking_ext, "700");
1938 strcpy(pickup_ext, "*8");
1939 courtesytone[0] = '\0';
1940 strcpy(xfersound, "beep");
1941 strcpy(xferfailsound, "pbx-invalid");
1942 parking_start = 701;
1947 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1948 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1950 cfg = ast_config_load("features.conf");
1952 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
1953 if (!strcasecmp(var->name, "parkext")) {
1954 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
1955 } else if (!strcasecmp(var->name, "context")) {
1956 ast_copy_string(parking_con, var->value, sizeof(parking_con));
1957 } else if (!strcasecmp(var->name, "parkingtime")) {
1958 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
1959 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
1960 parkingtime = DEFAULT_PARK_TIME;
1962 parkingtime = parkingtime * 1000;
1963 } else if (!strcasecmp(var->name, "parkpos")) {
1964 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
1965 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);
1967 parking_start = start;
1970 } else if (!strcasecmp(var->name, "findslot")) {
1971 parkfindnext = (!strcasecmp(var->value, "next"));
1972 } else if (!strcasecmp(var->name, "adsipark")) {
1973 adsipark = ast_true(var->value);
1974 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
1975 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
1976 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
1977 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
1979 transferdigittimeout = transferdigittimeout * 1000;
1980 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
1981 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
1982 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
1983 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
1985 } else if (!strcasecmp(var->name, "courtesytone")) {
1986 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
1987 } else if (!strcasecmp(var->name, "parkedplay")) {
1988 if (!strcasecmp(var->value, "both"))
1990 else if (!strcasecmp(var->value, "parked"))
1994 } else if (!strcasecmp(var->name, "xfersound")) {
1995 ast_copy_string(xfersound, var->value, sizeof(xfersound));
1996 } else if (!strcasecmp(var->name, "xferfailsound")) {
1997 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
1998 } else if (!strcasecmp(var->name, "pickupexten")) {
1999 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2004 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2005 if (remap_feature(var->name, var->value))
2006 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2009 /* Map a key combination to an application*/
2010 ast_unregister_features();
2011 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2012 char *tmp_val = ast_strdup(var->value);
2013 char *exten, *party=NULL, *app=NULL, *app_args=NULL;
2016 /*! \todo XXX No memory. We should probably break, but at least we do not
2017 * insist on this entry or we could be stuck in an
2023 /* strsep() sets the argument to NULL if match not found, and it
2024 * is safe to use it with a NULL argument, so we don't check
2027 exten = strsep(&tmp_val,",");
2028 party = strsep(&tmp_val,",");
2029 app = strsep(&tmp_val,",");
2030 app_args = strsep(&tmp_val,",");
2032 /*! \todo XXX var_name or app_args ? */
2033 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(party) || ast_strlen_zero(var->name)) {
2034 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);
2040 struct ast_call_feature *feature;
2043 if (!(feature = find_feature(var->name))) {
2046 if (!(feature = ast_calloc(1, sizeof(*feature)))) {
2052 ast_copy_string(feature->sname,var->name,FEATURE_SNAME_LEN);
2053 ast_copy_string(feature->app,app,FEATURE_APP_LEN);
2054 ast_copy_string(feature->exten, exten,FEATURE_EXTEN_LEN);
2058 ast_copy_string(feature->app_args,app_args,FEATURE_APP_ARGS_LEN);
2060 ast_copy_string(feature->exten, exten,sizeof(feature->exten));
2061 feature->operation=feature_exec_app;
2062 ast_set_flag(feature,AST_FEATURE_FLAG_NEEDSDTMF);
2064 if (!strcasecmp(party,"caller"))
2065 ast_set_flag(feature,AST_FEATURE_FLAG_CALLER);
2066 else if (!strcasecmp(party, "callee"))
2067 ast_set_flag(feature,AST_FEATURE_FLAG_CALLEE);
2069 ast_log(LOG_NOTICE, "Invalid party specification for feature '%s', must be caller, or callee\n", var->name);
2073 ast_register_feature(feature);
2074 /* XXX do we need to free it if mallocd ? */
2076 if (option_verbose >=1)
2077 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s' with code '%s'\n", var->name, app, exten);
2081 ast_config_destroy(cfg);
2083 /* Remove the old parking extension */
2084 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2085 ast_context_remove_extension2(con, old_parking_ext, 1, registrar);
2087 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2090 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
2091 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2094 return ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), FREE, registrar);
2097 static int reload(void *mod)
2099 return load_config();
2102 static int load_module(void *mod)
2107 AST_LIST_HEAD_INIT(&feature_list);
2108 memset(parking_ext, 0, sizeof(parking_ext));
2109 memset(parking_con, 0, sizeof(parking_con));
2111 if ((res = load_config()))
2113 ast_cli_register(&showparked);
2114 ast_cli_register(&showfeatures);
2115 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
2116 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
2118 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
2120 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
2121 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
2122 "Park a channel", mandescr_park);
2128 static int unload_module(void *mod)
2130 STANDARD_HANGUP_LOCALUSERS;
2132 ast_manager_unregister("ParkedCalls");
2133 ast_manager_unregister("Park");
2134 ast_cli_unregister(&showfeatures);
2135 ast_cli_unregister(&showparked);
2136 ast_unregister_application(parkcall);
2137 return ast_unregister_application(parkedcall);
2140 static const char *description(void)
2142 return "Call Features Resource";
2145 static const char *key(void)
2147 return ASTERISK_GPL_KEY;
2150 STD_MOD(MOD_0 | NO_UNLOAD, reload, NULL, NULL);