2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2008, 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>
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include "asterisk/_private.h"
34 #include <sys/signal.h>
35 #include <netinet/in.h>
37 #include "asterisk/lock.h"
38 #include "asterisk/file.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/causes.h"
42 #include "asterisk/module.h"
43 #include "asterisk/translate.h"
44 #include "asterisk/app.h"
45 #include "asterisk/say.h"
46 #include "asterisk/features.h"
47 #include "asterisk/musiconhold.h"
48 #include "asterisk/config.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/manager.h"
51 #include "asterisk/utils.h"
52 #include "asterisk/adsi.h"
53 #include "asterisk/devicestate.h"
54 #include "asterisk/monitor.h"
55 #include "asterisk/audiohook.h"
56 #include "asterisk/global_datastores.h"
58 #define DEFAULT_PARK_TIME 45000
59 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
60 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
61 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
62 #define DEFAULT_ATXFER_DROP_CALL 0
63 #define DEFAULT_ATXFER_LOOP_DELAY 10000
64 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
66 #define AST_MAX_WATCHERS 256
69 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
70 AST_FEATURE_FLAG_ONPEER = (1 << 1),
71 AST_FEATURE_FLAG_ONSELF = (1 << 2),
72 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
73 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
74 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
77 struct feature_group_exten {
78 AST_LIST_ENTRY(feature_group_exten) entry;
79 AST_DECLARE_STRING_FIELDS(
80 AST_STRING_FIELD(exten);
82 struct ast_call_feature *feature;
85 struct feature_group {
86 AST_LIST_ENTRY(feature_group) entry;
87 AST_DECLARE_STRING_FIELDS(
88 AST_STRING_FIELD(gname);
90 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
93 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
95 static char *parkedcall = "ParkedCall";
97 static int parkaddhints = 0; /*!< Add parking hints automatically */
98 static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
99 static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
100 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
101 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
102 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
103 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
104 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
105 static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
106 static int parking_start; /*!< First available extension for parking */
107 static int parking_stop; /*!< Last available extension for parking */
109 static char courtesytone[256]; /*!< Courtesy tone */
110 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
111 static char xfersound[256]; /*!< Call transfer sound */
112 static char xferfailsound[256]; /*!< Call transfer failure sound */
114 static int parking_offset;
115 static int parkfindnext;
119 static int transferdigittimeout;
120 static int featuredigittimeout;
121 static int comebacktoorigin = 1;
123 static int atxfernoanswertimeout;
124 static unsigned int atxferdropcall;
125 static unsigned int atxferloopdelay;
126 static unsigned int atxfercallbackretries;
128 static char *registrar = "features"; /*!< Registrar for operations */
130 /* module and CLI command definitions */
131 static char *synopsis = "Answer a parked call";
133 static char *descrip = "ParkedCall(exten): "
134 "Used to connect to a parked call. This application is always\n"
135 "registered internally and does not need to be explicitly added\n"
136 "into the dialplan, although you should include the 'parkedcalls'\n"
137 "context. If no extension is provided, then the first available\n"
138 "parked call will be acquired.\n";
140 static char *parkcall = "Park";
142 static char *synopsis2 = "Park yourself";
144 static char *descrip2 = "Park(): "
145 "Used to park yourself (typically in combination with a supervised\n"
146 "transfer to know the parking space). This application is always\n"
147 "registered internally and does not need to be explicitly added\n"
148 "into the dialplan, although you should include the 'parkedcalls'\n"
149 "context (or the context specified in features.conf).\n\n"
150 "If you set the PARKINGEXTEN variable to an extension in your\n"
151 "parking context, Park() will park the call on that extension, unless\n"
152 "it already exists. In that case, execution will continue at next\n"
155 static struct ast_app *monitor_app = NULL;
156 static int monitor_ok = 1;
158 static struct ast_app *mixmonitor_app = NULL;
159 static int mixmonitor_ok = 1;
161 static struct ast_app *stopmixmonitor_app = NULL;
162 static int stopmixmonitor_ok = 1;
165 struct ast_channel *chan; /*!< Parking channel */
166 struct timeval start; /*!< Time the parking started */
167 int parkingnum; /*!< Parking lot */
168 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
169 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
170 char exten[AST_MAX_EXTENSION];
172 int parkingtime; /*!< Maximum length in parking lot before return */
175 unsigned char moh_trys;
176 AST_LIST_ENTRY(parkeduser) list;
179 static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
181 static pthread_t parking_thread;
183 const char *ast_parking_ext(void)
188 const char *ast_pickup_ext(void)
193 struct ast_bridge_thread_obj
195 struct ast_bridge_config bconfig;
196 struct ast_channel *chan;
197 struct ast_channel *peer;
198 unsigned int return_to_pbx:1;
204 * \brief store context, extension and priority
205 * \param chan, context, ext, pri
207 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
209 ast_copy_string(chan->context, context, sizeof(chan->context));
210 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
211 chan->priority = pri;
215 * \brief Check goto on transfer
218 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
219 * When found make sure the types are compatible. Check if channel is valid
220 * if so start the new channel else hangup the call.
222 static void check_goto_on_transfer(struct ast_channel *chan)
224 struct ast_channel *xferchan;
225 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
226 char *x, *goto_on_transfer;
229 if (ast_strlen_zero(val))
232 goto_on_transfer = ast_strdupa(val);
234 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
237 for (x = goto_on_transfer; x && *x; x++) {
241 /* Make formats okay */
242 xferchan->readformat = chan->readformat;
243 xferchan->writeformat = chan->writeformat;
244 ast_channel_masquerade(xferchan, chan);
245 ast_parseable_goto(xferchan, goto_on_transfer);
246 xferchan->_state = AST_STATE_UP;
247 ast_clear_flag(xferchan, AST_FLAGS_ALL);
248 xferchan->_softhangup = 0;
249 if ((f = ast_read(xferchan))) {
252 ast_pbx_start(xferchan);
254 ast_hangup(xferchan);
258 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language);
261 * \brief bridge the call
262 * \param data thread bridge.
264 * Set Last Data for respective channels, reset cdr for channels
265 * bridge call, check if we're going back to dialplan
266 * if not hangup both legs of the call
268 static void *ast_bridge_call_thread(void *data)
270 struct ast_bridge_thread_obj *tobj = data;
273 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
274 tobj->chan->data = tobj->peer->name;
275 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
276 tobj->peer->data = tobj->chan->name;
278 if (tobj->chan->cdr) {
279 ast_cdr_reset(tobj->chan->cdr, NULL);
280 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
282 if (tobj->peer->cdr) {
283 ast_cdr_reset(tobj->peer->cdr, NULL);
284 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
287 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
289 if (tobj->return_to_pbx) {
290 if (!ast_check_hangup(tobj->peer)) {
291 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
292 res = ast_pbx_start(tobj->peer);
293 if (res != AST_PBX_SUCCESS)
294 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
296 ast_hangup(tobj->peer);
297 if (!ast_check_hangup(tobj->chan)) {
298 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
299 res = ast_pbx_start(tobj->chan);
300 if (res != AST_PBX_SUCCESS)
301 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
303 ast_hangup(tobj->chan);
305 ast_hangup(tobj->chan);
306 ast_hangup(tobj->peer);
315 * \brief create thread for the parked call
318 * Create thread and attributes, call ast_bridge_call_thread
320 static void ast_bridge_call_thread_launch(void *data)
324 struct sched_param sched;
326 pthread_attr_init(&attr);
327 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
328 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
329 pthread_attr_destroy(&attr);
330 memset(&sched, 0, sizeof(sched));
331 pthread_setschedparam(thread, SCHED_RR, &sched);
335 * \brief Announce call parking by ADSI
337 * \param parkingexten .
338 * Create message to show for ADSI, display message.
339 * \retval 0 on success.
340 * \retval -1 on failure.
342 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
345 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
347 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
349 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
351 res = ast_adsi_load_session(chan, NULL, 0, 1);
354 return ast_adsi_print(chan, message, justify, 1);
357 /*! \brief Notify metermaids that we've changed an extension */
358 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
360 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
361 exten, context, devstate2str(state));
363 ast_devstate_changed(state, "park:%s@%s", exten, context);
366 /*! \brief metermaids callback from devicestate.c */
367 static enum ast_device_state metermaidstate(const char *data)
372 context = ast_strdupa(data);
374 exten = strsep(&context, "@");
376 return AST_DEVICE_INVALID;
378 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
380 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
381 return AST_DEVICE_NOT_INUSE;
383 return AST_DEVICE_INUSE;
387 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name)
389 struct parkeduser *pu, *cur;
390 int i, x = -1, parking_range;
391 struct ast_context *con;
392 const char *parkingexten;
394 /* Allocate memory for parking data */
395 if (!(pu = ast_calloc(1, sizeof(*pu))))
398 /* Lock parking lot */
399 AST_LIST_LOCK(&parkinglot);
400 /* Check for channel variable PARKINGEXTEN */
401 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
402 if (!ast_strlen_zero(parkingexten)) {
403 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
404 AST_LIST_UNLOCK(&parkinglot);
406 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
407 return 1; /* Continue execution if possible */
409 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
410 x = atoi(parkingexten);
412 /* Select parking space within range */
413 parking_range = parking_stop - parking_start+1;
414 for (i = 0; i < parking_range; i++) {
415 x = (i + parking_offset) % parking_range + parking_start;
416 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
417 if (cur->parkingnum == x)
424 if (!(i < parking_range)) {
425 ast_log(LOG_WARNING, "No more parking spaces\n");
427 AST_LIST_UNLOCK(&parkinglot);
430 /* Set pointer for next parking */
432 parking_offset = x - parking_start + 1;
435 chan->appl = "Parked Call";
440 /* Put the parked channel on hold if we have two different channels */
442 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
443 S_OR(parkmohclass, NULL),
444 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
447 pu->start = ast_tvnow();
449 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
454 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
456 /* Remember what had been dialed, so that if the parking
457 expires, we try to come back to the same place */
458 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
459 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
460 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
461 AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
463 /* If parking a channel directly, don't quiet yet get parking running on it */
466 AST_LIST_UNLOCK(&parkinglot);
467 /* Wake up the (presumably select()ing) thread */
468 pthread_kill(parking_thread, SIGURG);
469 ast_verb(2, "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
471 if (pu->parkingnum != -1)
472 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
473 manager_event(EVENT_FLAG_CALL, "ParkedCall",
478 "CallerIDNum: %s\r\n"
479 "CallerIDName: %s\r\n",
480 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
481 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
482 S_OR(pu->chan->cid.cid_num, "<unknown>"),
483 S_OR(pu->chan->cid.cid_name, "<unknown>")
486 if (peer && adsipark && ast_adsi_available(peer)) {
487 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
488 ast_adsi_unload_session(peer);
491 con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
492 if (!con) /* Still no context? Bad */
493 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
494 /* Tell the peer channel the number of the parking space */
495 if (peer && ((pu->parkingnum != -1 && ast_strlen_zero(orig_chan_name)) || !strcasecmp(peer->name, orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
496 /* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
497 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
498 ast_say_digits(peer, pu->parkingnum, "", peer->language);
499 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
502 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
503 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
505 if (pu->notquiteyet) {
506 /* Wake up parking thread if we're really done */
507 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
508 S_OR(parkmohclass, NULL),
509 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
511 pthread_kill(parking_thread, SIGURG);
516 /*! \brief Park a call */
517 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
519 return park_call_full(chan, peer, timeout, extout, NULL);
522 /* Park call via masquraded channel */
523 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
525 struct ast_channel *chan;
527 char *orig_chan_name = NULL;
529 /* Make a new, fake channel that we'll use to masquerade in the real one */
530 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
531 ast_log(LOG_WARNING, "Unable to create parked channel\n");
535 /* Make formats okay */
536 chan->readformat = rchan->readformat;
537 chan->writeformat = rchan->writeformat;
538 ast_channel_masquerade(chan, rchan);
540 /* Setup the extensions and such */
541 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
543 /* Make the masq execute */
544 if ((f = ast_read(chan)))
547 orig_chan_name = ast_strdupa(chan->name);
549 park_call_full(chan, peer, timeout, extout, orig_chan_name);
555 #define FEATURE_RETURN_HANGUP -1
556 #define FEATURE_RETURN_SUCCESSBREAK 0
557 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
558 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
559 #define FEATURE_RETURN_PASSDIGITS 21
560 #define FEATURE_RETURN_STOREDIGITS 22
561 #define FEATURE_RETURN_SUCCESS 23
562 #define FEATURE_RETURN_KEEPTRYING 24
564 #define FEATURE_SENSE_CHAN (1 << 0)
565 #define FEATURE_SENSE_PEER (1 << 1)
568 * \brief set caller and callee according to the direction
569 * \param caller, callee, peer, chan, sense
571 * Detect who triggered feature and set callee/caller variables accordingly
573 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
574 struct ast_channel *peer, struct ast_channel *chan, int sense)
576 if (sense == FEATURE_SENSE_PEER) {
586 * \brief support routing for one touch call parking
587 * \param chan channel parking call
588 * \param peer channel to be parked
589 * \param config unsed
591 * \param sense feature options
594 * Setup channel, set return exten,priority to 's,1'
595 * answer chan, sleep chan, park call
597 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
599 struct ast_channel *parker;
600 struct ast_channel *parkee;
603 set_peers(&parker, &parkee, peer, chan, sense);
604 /* Setup the exten/priority to be s/1 since we don't know
605 where this call should return */
606 strcpy(chan->exten, "s");
608 if (chan->_state != AST_STATE_UP)
609 res = ast_answer(chan);
611 res = ast_safe_sleep(chan, 1000);
613 res = ast_park_call(parkee, parker, 0, NULL);
616 if (sense == FEATURE_SENSE_CHAN)
617 res = AST_PBX_NO_HANGUP_PEER;
619 res = AST_PBX_KEEPALIVE;
626 * \brief Monitor a channel by DTMF
627 * \param chan channel requesting monitor
628 * \param peer channel to be monitored
631 * \param sense feature options
634 * Check monitor app enabled, setup channels, both caller/callee chans not null
635 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
636 * \retval FEATURE_RETURN_SUCCESS on success.
637 * \retval -1 on error.
639 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
641 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
644 struct ast_channel *caller_chan, *callee_chan;
647 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
651 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
653 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
657 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
659 if (!ast_strlen_zero(courtesytone)) {
660 if (ast_autoservice_start(callee_chan))
662 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
663 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
664 ast_autoservice_stop(callee_chan);
667 if (ast_autoservice_stop(callee_chan))
671 if (callee_chan->monitor) {
672 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
673 callee_chan->monitor->stop(callee_chan, 1);
674 return FEATURE_RETURN_SUCCESS;
677 if (caller_chan && callee_chan) {
678 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
679 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
680 const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
683 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
686 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
688 if (!touch_monitor_prefix)
689 touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
692 len = strlen(touch_monitor) + 50;
694 touch_filename = alloca(len);
695 snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
696 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
698 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
699 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
700 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
702 touch_filename = alloca(len);
703 snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
704 snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
707 for(x = 0; x < strlen(args); x++) {
712 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
714 pbx_exec(callee_chan, monitor_app, args);
715 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
716 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
718 return FEATURE_RETURN_SUCCESS;
721 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
725 static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
727 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
730 struct ast_channel *caller_chan, *callee_chan;
731 const char *mixmonitor_spy_type = "MixMonitor";
734 if (!mixmonitor_ok) {
735 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
739 if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
741 ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
745 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
747 if (!ast_strlen_zero(courtesytone)) {
748 if (ast_autoservice_start(callee_chan))
750 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
751 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
752 ast_autoservice_stop(callee_chan);
755 if (ast_autoservice_stop(callee_chan))
759 ast_channel_lock(callee_chan);
760 count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
761 ast_channel_unlock(callee_chan);
763 // This means a mixmonitor is attached to the channel, running or not is unknown.
766 ast_verb(3, "User hit '%s' to stop recording call.\n", code);
768 //Make sure they are running
769 ast_channel_lock(callee_chan);
770 count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
771 ast_channel_unlock(callee_chan);
773 if (!stopmixmonitor_ok) {
774 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
777 if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
778 stopmixmonitor_ok = 0;
779 ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
782 pbx_exec(callee_chan, stopmixmonitor_app, "");
783 return FEATURE_RETURN_SUCCESS;
787 ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
790 if (caller_chan && callee_chan) {
791 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
792 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
795 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
798 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
801 len = strlen(touch_monitor) + 50;
803 touch_filename = alloca(len);
804 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
805 snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
807 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
808 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
809 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
811 touch_filename = alloca(len);
812 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
813 snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
816 for( x = 0; x < strlen(args); x++) {
821 ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
823 pbx_exec(callee_chan, mixmonitor_app, args);
824 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
825 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
826 return FEATURE_RETURN_SUCCESS;
830 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
835 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
837 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
838 return FEATURE_RETURN_HANGUP;
841 static int finishup(struct ast_channel *chan)
843 ast_indicate(chan, AST_CONTROL_UNHOLD);
845 return ast_autoservice_stop(chan);
849 * \brief Find the context for the transfer
853 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
854 * \return a context string
856 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
858 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
859 if (ast_strlen_zero(s)) {
860 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
862 if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
863 s = transferer->macrocontext;
865 if (ast_strlen_zero(s)) {
866 s = transferer->context;
872 * \brief Blind transfer user to another extension
873 * \param chan channel to be transfered
874 * \param peer channel initiated blind transfer
878 * \param sense feature options
880 * Place chan on hold, check if transferred to parkinglot extension,
881 * otherwise check extension exists and transfer caller.
882 * \retval FEATURE_RETURN_SUCCESS.
883 * \retval -1 on failure.
885 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
887 struct ast_channel *transferer;
888 struct ast_channel *transferee;
889 const char *transferer_real_context;
893 set_peers(&transferer, &transferee, peer, chan, sense);
894 transferer_real_context = real_ctx(transferer, transferee);
895 /* Start autoservice on chan while we talk to the originator */
896 ast_autoservice_start(transferee);
897 ast_indicate(transferee, AST_CONTROL_HOLD);
899 memset(xferto, 0, sizeof(xferto));
902 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
904 finishup(transferee);
905 return -1; /* error ? */
907 if (res > 0) /* If they've typed a digit already, handle it */
908 xferto[0] = (char) res;
910 ast_stopstream(transferer);
911 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
912 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
913 finishup(transferee);
916 if (!strcmp(xferto, ast_parking_ext())) {
917 res = finishup(transferee);
920 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
921 /* We return non-zero, but tell the PBX not to hang the channel when
922 the thread dies -- We have to be careful now though. We are responsible for
923 hanging up the channel, else it will never be hung up! */
925 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
927 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
929 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
930 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
931 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
932 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
933 res=finishup(transferee);
934 if (!transferer->cdr) {
935 transferer->cdr=ast_cdr_alloc();
937 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
938 ast_cdr_start(transferer->cdr);
941 if (transferer->cdr) {
942 ast_cdr_setdestchan(transferer->cdr, transferee->name);
943 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
945 if (!transferee->pbx) {
946 /* Doh! Use our handy async_goto functions */
947 ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
948 ,transferee->name, xferto, transferer_real_context);
949 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
950 ast_log(LOG_WARNING, "Async goto failed :-(\n");
952 /* Set the channel's new extension, since it exists, using transferer context */
953 set_c_e_p(transferee, transferer_real_context, xferto, 0);
955 check_goto_on_transfer(transferer);
958 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
960 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
961 finishup(transferee);
964 ast_stopstream(transferer);
965 res = finishup(transferee);
967 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
970 return FEATURE_RETURN_SUCCESS;
974 * \brief make channels compatible
977 * \retval 0 on success.
978 * \retval -1 on failure.
980 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
982 if (ast_channel_make_compatible(c, newchan) < 0) {
983 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
984 c->name, newchan->name);
992 * \brief Attended transfer
993 * \param chan transfered user
994 * \param peer person transfering call
997 * \param sense feature options
1000 * Get extension to transfer to, if you cannot generate channel (or find extension)
1001 * return to host channel. After called channel answered wait for hangup of transferer,
1002 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
1004 * \return -1 on failure
1006 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1008 struct ast_channel *transferer;
1009 struct ast_channel *transferee;
1010 const char *transferer_real_context;
1011 char xferto[256] = "";
1014 struct ast_channel *newchan;
1015 struct ast_channel *xferchan;
1016 struct ast_bridge_thread_obj *tobj;
1017 struct ast_bridge_config bconfig;
1018 struct ast_frame *f;
1021 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
1022 set_peers(&transferer, &transferee, peer, chan, sense);
1023 transferer_real_context = real_ctx(transferer, transferee);
1024 /* Start autoservice on chan while we talk to the originator */
1025 ast_autoservice_start(transferee);
1026 ast_indicate(transferee, AST_CONTROL_HOLD);
1029 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
1031 finishup(transferee);
1034 if (res > 0) /* If they've typed a digit already, handle it */
1035 xferto[0] = (char) res;
1037 /* this is specific of atxfer */
1038 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
1039 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
1040 finishup(transferee);
1044 ast_log(LOG_WARNING, "Did not read data.\n");
1045 finishup(transferee);
1046 if (ast_stream_and_wait(transferer, "beeperr", ""))
1048 return FEATURE_RETURN_SUCCESS;
1051 /* valid extension, res == 1 */
1052 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
1053 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
1054 finishup(transferee);
1055 if (ast_stream_and_wait(transferer, "beeperr", ""))
1057 return FEATURE_RETURN_SUCCESS;
1061 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
1062 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1063 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1065 if (!ast_check_hangup(transferer)) {
1066 /* Transferer is up - old behaviour */
1067 ast_indicate(transferer, -1);
1069 finishup(transferee);
1070 /* any reason besides user requested cancel and busy triggers the failed sound */
1071 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
1072 ast_stream_and_wait(transferer, xferfailsound, ""))
1074 if (ast_stream_and_wait(transferer, xfersound, ""))
1075 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1076 return FEATURE_RETURN_SUCCESS;
1079 if (check_compat(transferer, newchan)) {
1080 /* we do mean transferee here, NOT transferer */
1081 finishup(transferee);
1084 memset(&bconfig,0,sizeof(struct ast_bridge_config));
1085 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
1086 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
1087 res = ast_bridge_call(transferer, newchan, &bconfig);
1088 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
1089 ast_hangup(newchan);
1090 if (ast_stream_and_wait(transferer, xfersound, ""))
1091 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1092 finishup(transferee);
1093 transferer->_softhangup = 0;
1094 return FEATURE_RETURN_SUCCESS;
1096 if (check_compat(transferee, newchan)) {
1097 finishup(transferee);
1100 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1102 if ((ast_autoservice_stop(transferee) < 0)
1103 || (ast_waitfordigit(transferee, 100) < 0)
1104 || (ast_waitfordigit(newchan, 100) < 0)
1105 || ast_check_hangup(transferee)
1106 || ast_check_hangup(newchan)) {
1107 ast_hangup(newchan);
1110 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1112 ast_hangup(newchan);
1115 /* Make formats okay */
1116 xferchan->visible_indication = transferer->visible_indication;
1117 xferchan->readformat = transferee->readformat;
1118 xferchan->writeformat = transferee->writeformat;
1119 ast_channel_masquerade(xferchan, transferee);
1120 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1121 xferchan->_state = AST_STATE_UP;
1122 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1123 xferchan->_softhangup = 0;
1124 if ((f = ast_read(xferchan)))
1126 newchan->_state = AST_STATE_UP;
1127 ast_clear_flag(newchan, AST_FLAGS_ALL);
1128 newchan->_softhangup = 0;
1129 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1130 ast_hangup(xferchan);
1131 ast_hangup(newchan);
1134 tobj->chan = newchan;
1135 tobj->peer = xferchan;
1136 tobj->bconfig = *config;
1138 if (ast_stream_and_wait(newchan, xfersound, ""))
1139 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1140 ast_bridge_call_thread_launch(tobj);
1141 return -1; /* XXX meaning the channel is bridged ? */
1142 } else if (!ast_check_hangup(transferee)) {
1143 /* act as blind transfer */
1144 if (ast_autoservice_stop(transferee) < 0) {
1145 ast_hangup(newchan);
1150 unsigned int tries = 0;
1151 char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
1153 transferer_tech = strsep(&transferer_name, "/");
1154 transferer_name = strsep(&transferer_name, "-");
1156 if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
1157 ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
1158 if (ast_stream_and_wait(transferee, "beeperr", ""))
1160 return FEATURE_RETURN_SUCCESS;
1163 ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
1164 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1165 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1166 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1167 /* Trying to transfer again */
1168 ast_autoservice_start(transferee);
1169 ast_indicate(transferee, AST_CONTROL_HOLD);
1171 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1172 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
1173 if (ast_autoservice_stop(transferee) < 0) {
1175 ast_hangup(newchan);
1179 /* Transfer failed, sleeping */
1180 ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1181 ast_safe_sleep(transferee, atxferloopdelay);
1182 ast_debug(1, "Trying to callback...\n");
1183 newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
1184 transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
1192 /* newchan is up, we should prepare transferee and bridge them */
1193 if (check_compat(transferee, newchan)) {
1194 finishup(transferee);
1197 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1199 if ((ast_waitfordigit(transferee, 100) < 0)
1200 || (ast_waitfordigit(newchan, 100) < 0)
1201 || ast_check_hangup(transferee)
1202 || ast_check_hangup(newchan)) {
1203 ast_hangup(newchan);
1207 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1209 ast_hangup(newchan);
1212 /* Make formats okay */
1213 xferchan->visible_indication = transferer->visible_indication;
1214 xferchan->readformat = transferee->readformat;
1215 xferchan->writeformat = transferee->writeformat;
1216 ast_channel_masquerade(xferchan, transferee);
1217 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1218 xferchan->_state = AST_STATE_UP;
1219 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1220 xferchan->_softhangup = 0;
1221 if ((f = ast_read(xferchan)))
1223 newchan->_state = AST_STATE_UP;
1224 ast_clear_flag(newchan, AST_FLAGS_ALL);
1225 newchan->_softhangup = 0;
1226 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1227 ast_hangup(xferchan);
1228 ast_hangup(newchan);
1231 tobj->chan = newchan;
1232 tobj->peer = xferchan;
1233 tobj->bconfig = *config;
1235 if (ast_stream_and_wait(newchan, xfersound, ""))
1236 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1237 ast_bridge_call_thread_launch(tobj);
1238 return -1; /* XXX meaning the channel is bridged ? */
1240 /* Transferee hung up */
1241 finishup(transferee);
1246 /* add atxfer and automon as undefined so you can only use em if you configure them */
1247 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1249 AST_RWLOCK_DEFINE_STATIC(features_lock);
1251 static struct ast_call_feature builtin_features[] =
1253 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1254 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1255 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1256 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1257 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1258 { AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1262 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1264 /*! \brief register new feature into feature_list*/
1265 void ast_register_feature(struct ast_call_feature *feature)
1268 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1272 AST_LIST_LOCK(&feature_list);
1273 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1274 AST_LIST_UNLOCK(&feature_list);
1276 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1280 * \brief Add new feature group
1281 * \param fgname feature group name.
1283 * Add new feature group to the feature group list insert at head of list.
1284 * \note This function MUST be called while feature_groups is locked.
1286 static struct feature_group* register_group(const char *fgname)
1288 struct feature_group *fg;
1291 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1295 if (!(fg = ast_calloc(1, sizeof(*fg))))
1298 if (ast_string_field_init(fg, 128)) {
1303 ast_string_field_set(fg, gname, fgname);
1305 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1307 ast_verb(2, "Registered group '%s'\n", fg->gname);
1313 * \brief Add feature to group
1314 * \param fg feature group
1316 * \param feature feature to add.
1318 * Check fg and feature specified, add feature to list
1319 * \note This function MUST be called while feature_groups is locked.
1321 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
1323 struct feature_group_exten *fge;
1325 if (!(fge = ast_calloc(1, sizeof(*fge))))
1328 if (ast_string_field_init(fge, 128)) {
1334 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1339 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1343 ast_string_field_set(fge, exten, (ast_strlen_zero(exten) ? feature->exten : exten));
1345 fge->feature = feature;
1347 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
1349 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1350 feature->sname, fg->gname, exten);
1353 void ast_unregister_feature(struct ast_call_feature *feature)
1358 AST_LIST_LOCK(&feature_list);
1359 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1360 AST_LIST_UNLOCK(&feature_list);
1364 /*! \brief Remove all features in the list */
1365 static void ast_unregister_features(void)
1367 struct ast_call_feature *feature;
1369 AST_LIST_LOCK(&feature_list);
1370 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1372 AST_LIST_UNLOCK(&feature_list);
1375 /*! \brief find a call feature by name */
1376 static struct ast_call_feature *find_dynamic_feature(const char *name)
1378 struct ast_call_feature *tmp;
1380 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1381 if (!strcasecmp(tmp->sname, name))
1388 /*! \brief Remove all feature groups in the list */
1389 static void ast_unregister_groups(void)
1391 struct feature_group *fg;
1392 struct feature_group_exten *fge;
1394 AST_RWLIST_WRLOCK(&feature_groups);
1395 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1396 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1397 ast_string_field_free_memory(fge);
1401 ast_string_field_free_memory(fg);
1404 AST_RWLIST_UNLOCK(&feature_groups);
1408 * \brief Find a group by name
1409 * \param name feature name
1410 * \retval feature group on success.
1411 * \retval NULL on failure.
1413 static struct feature_group *find_group(const char *name) {
1414 struct feature_group *fg = NULL;
1416 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1417 if (!strcasecmp(fg->gname, name))
1424 void ast_rdlock_call_features(void)
1426 ast_rwlock_rdlock(&features_lock);
1429 void ast_unlock_call_features(void)
1431 ast_rwlock_unlock(&features_lock);
1434 struct ast_call_feature *ast_find_call_feature(const char *name)
1437 for (x = 0; x < FEATURES_COUNT; x++) {
1438 if (!strcasecmp(name, builtin_features[x].sname))
1439 return &builtin_features[x];
1445 * \brief exec an app by feature
1446 * \param chan,peer,config,code,sense,data
1448 * Find a feature, determine which channel activated
1449 * \retval FEATURE_RETURN_PBX_KEEPALIVE,FEATURE_RETURN_NO_HANGUP_PEER
1451 * \retval -2 when an application cannot be found.
1453 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
1455 struct ast_app *app;
1456 struct ast_call_feature *feature = data;
1457 struct ast_channel *work, *idle;
1460 if (!feature) { /* shouldn't ever happen! */
1461 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1465 if (sense == FEATURE_SENSE_CHAN) {
1466 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1467 return FEATURE_RETURN_KEEPTRYING;
1468 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1476 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1477 return FEATURE_RETURN_KEEPTRYING;
1478 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1487 if (!(app = pbx_findapp(feature->app))) {
1488 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1492 ast_autoservice_start(idle);
1494 if (!ast_strlen_zero(feature->moh_class))
1495 ast_moh_start(idle, feature->moh_class, NULL);
1497 res = pbx_exec(work, app, feature->app_args);
1499 if (!ast_strlen_zero(feature->moh_class))
1502 ast_autoservice_stop(idle);
1504 if (res == AST_PBX_KEEPALIVE)
1505 return FEATURE_RETURN_PBX_KEEPALIVE;
1506 else if (res == AST_PBX_NO_HANGUP_PEER)
1507 return FEATURE_RETURN_NO_HANGUP_PEER;
1509 return FEATURE_RETURN_SUCCESSBREAK;
1511 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1514 static void unmap_features(void)
1518 ast_rwlock_wrlock(&features_lock);
1519 for (x = 0; x < FEATURES_COUNT; x++)
1520 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1521 ast_rwlock_unlock(&features_lock);
1524 static int remap_feature(const char *name, const char *value)
1528 ast_rwlock_wrlock(&features_lock);
1529 for (x = 0; x < FEATURES_COUNT; x++) {
1530 if (strcasecmp(builtin_features[x].sname, name))
1533 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1537 ast_rwlock_unlock(&features_lock);
1543 * \brief Check the dynamic features
1544 * \param chan,peer,config,code,sense
1546 * Lock features list, browse for code, unlock list
1547 * \retval res on success.
1548 * \retval -1 on failure.
1550 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1553 struct ast_flags features;
1554 int res = FEATURE_RETURN_PASSDIGITS;
1555 struct ast_call_feature *feature;
1556 struct feature_group *fg = NULL;
1557 struct feature_group_exten *fge;
1558 const char *dynamic_features;
1561 if (sense == FEATURE_SENSE_CHAN) {
1562 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1563 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1566 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1567 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
1569 ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
1571 ast_rwlock_rdlock(&features_lock);
1572 for (x = 0; x < FEATURES_COUNT; x++) {
1573 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1574 !ast_strlen_zero(builtin_features[x].exten)) {
1575 /* Feature is up for consideration */
1576 if (!strcmp(builtin_features[x].exten, code)) {
1577 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
1579 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1580 if (res == FEATURE_RETURN_PASSDIGITS)
1581 res = FEATURE_RETURN_STOREDIGITS;
1585 ast_rwlock_unlock(&features_lock);
1587 if (ast_strlen_zero(dynamic_features))
1590 tmp = ast_strdupa(dynamic_features);
1592 while ((tok = strsep(&tmp, "#"))) {
1593 AST_RWLIST_RDLOCK(&feature_groups);
1595 fg = find_group(tok);
1598 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1599 if (strcasecmp(fge->exten, code))
1602 res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
1603 if (res != FEATURE_RETURN_KEEPTRYING) {
1604 AST_RWLIST_UNLOCK(&feature_groups);
1607 res = FEATURE_RETURN_PASSDIGITS;
1613 AST_RWLIST_UNLOCK(&feature_groups);
1614 AST_LIST_LOCK(&feature_list);
1616 if(!(feature = find_dynamic_feature(tok))) {
1617 AST_LIST_UNLOCK(&feature_list);
1621 /* Feature is up for consideration */
1622 if (!strcmp(feature->exten, code)) {
1623 ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1624 res = feature->operation(chan, peer, config, code, sense, feature);
1625 if (res != FEATURE_RETURN_KEEPTRYING) {
1626 AST_LIST_UNLOCK(&feature_list);
1629 res = FEATURE_RETURN_PASSDIGITS;
1630 } else if (!strncmp(feature->exten, code, strlen(code)))
1631 res = FEATURE_RETURN_STOREDIGITS;
1633 AST_LIST_UNLOCK(&feature_list);
1639 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1643 ast_clear_flag(config, AST_FLAGS_ALL);
1645 ast_rwlock_rdlock(&features_lock);
1646 for (x = 0; x < FEATURES_COUNT; x++) {
1647 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1650 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1651 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1653 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1654 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1656 ast_rwlock_unlock(&features_lock);
1658 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1659 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1661 if (dynamic_features) {
1662 char *tmp = ast_strdupa(dynamic_features);
1664 struct ast_call_feature *feature;
1666 /* while we have a feature */
1667 while ((tok = strsep(&tmp, "#"))) {
1668 AST_LIST_LOCK(&feature_list);
1669 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1670 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1671 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1672 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1673 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1675 AST_LIST_UNLOCK(&feature_list);
1682 * \brief Get feature and dial
1683 * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1685 * Request channel, set channel variables, initiate call,check if they want to disconnect
1686 * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1687 * check for answer break loop, set cdr return channel.
1689 * \todo XXX Check - this is very similar to the code in channel.c
1690 * \return always a channel
1692 static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language)
1697 struct ast_channel *chan;
1698 struct ast_channel *monitor_chans[2];
1699 struct ast_channel *active_channel;
1700 int res = 0, ready = 0;
1702 if ((chan = ast_request(type, format, data, &cause))) {
1703 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1704 ast_string_field_set(chan, language, language);
1705 ast_channel_inherit_variables(caller, chan);
1706 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1708 chan->cdr=ast_cdr_alloc();
1710 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1711 ast_cdr_start(chan->cdr);
1715 if (!ast_call(chan, data, timeout)) {
1716 struct timeval started;
1718 char *disconnect_code = NULL, *dialed_code = NULL;
1720 ast_indicate(caller, AST_CONTROL_RINGING);
1721 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1722 ast_rwlock_rdlock(&features_lock);
1723 for (x = 0; x < FEATURES_COUNT; x++) {
1724 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1727 disconnect_code = builtin_features[x].exten;
1728 len = strlen(disconnect_code) + 1;
1729 dialed_code = alloca(len);
1730 memset(dialed_code, 0, len);
1733 ast_rwlock_unlock(&features_lock);
1735 started = ast_tvnow();
1738 ast_poll_channel_add(caller, chan);
1740 while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1741 struct ast_frame *f = NULL;
1743 monitor_chans[0] = caller;
1744 monitor_chans[1] = chan;
1745 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1747 /* see if the timeout has been violated */
1748 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1749 state = AST_CONTROL_UNHOLD;
1750 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1751 break; /*doh! timeout*/
1754 if (!active_channel)
1757 if (chan && (chan == active_channel)){
1759 if (f == NULL) { /*doh! where'd he go?*/
1760 state = AST_CONTROL_HANGUP;
1765 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1766 if (f->subclass == AST_CONTROL_RINGING) {
1767 state = f->subclass;
1768 ast_verb(3, "%s is ringing\n", chan->name);
1769 ast_indicate(caller, AST_CONTROL_RINGING);
1770 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1771 state = f->subclass;
1772 ast_verb(3, "%s is busy\n", chan->name);
1773 ast_indicate(caller, AST_CONTROL_BUSY);
1777 } else if (f->subclass == AST_CONTROL_ANSWER) {
1778 /* This is what we are hoping for */
1779 state = f->subclass;
1784 } else if (f->subclass != -1) {
1785 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1787 /* else who cares */
1790 } else if (caller && (active_channel == caller)) {
1791 f = ast_read(caller);
1792 if (f == NULL) { /*doh! where'd he go?*/
1793 if (!igncallerstate) {
1794 if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
1795 /* make this a blind transfer */
1799 state = AST_CONTROL_HANGUP;
1805 if (f->frametype == AST_FRAME_DTMF) {
1806 dialed_code[x++] = f->subclass;
1807 dialed_code[x] = '\0';
1808 if (strlen(dialed_code) == len) {
1810 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1812 dialed_code[x] = '\0';
1814 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1815 /* Caller Canceled the call */
1816 state = AST_CONTROL_UNHOLD;
1828 ast_poll_channel_del(caller, chan);
1831 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1833 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1835 case AST_CAUSE_BUSY:
1836 state = AST_CONTROL_BUSY;
1838 case AST_CAUSE_CONGESTION:
1839 state = AST_CONTROL_CONGESTION;
1844 ast_indicate(caller, -1);
1845 if (chan && ready) {
1846 if (chan->_state == AST_STATE_UP)
1847 state = AST_CONTROL_ANSWER;
1860 if (chan && res <= 0) {
1861 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1863 ast_cdr_init(chan->cdr, chan);
1864 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1865 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1866 ast_cdr_update(chan);
1867 ast_cdr_start(chan->cdr);
1868 ast_cdr_end(chan->cdr);
1869 /* If the cause wasn't handled properly */
1870 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1871 ast_cdr_failed(chan->cdr);
1873 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1881 * \brief bridge the call and set CDR
1882 * \param chan,peer,config
1884 * Set start time, check for two channels,check if monitor on
1885 * check for feature activation, create new CDR
1886 * \retval res on success.
1887 * \retval -1 on failure to bridge.
1889 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1891 /* Copy voice back and forth between the two channels. Give the peer
1892 the ability to transfer calls with '#<extension' syntax. */
1893 struct ast_frame *f;
1894 struct ast_channel *who;
1895 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1896 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1901 struct ast_option_header *aoh;
1902 struct ast_bridge_config backup_config;
1903 struct ast_cdr *bridge_cdr;
1905 memset(&backup_config, 0, sizeof(backup_config));
1907 config->start_time = ast_tvnow();
1910 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1911 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1913 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1916 const char *monitor_exec;
1917 struct ast_channel *src = NULL;
1919 if (!(monitor_app = pbx_findapp("Monitor")))
1922 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1924 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1926 if (monitor_app && src) {
1927 char *tmp = ast_strdupa(monitor_exec);
1928 pbx_exec(src, monitor_app, tmp);
1932 set_config_flags(chan, peer, config);
1933 config->firstpass = 1;
1935 /* Answer if need be */
1936 if (ast_answer(chan))
1938 peer->appl = "Bridged Call";
1939 peer->data = chan->name;
1941 /* copy the userfield from the B-leg to A-leg if applicable */
1942 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1944 if (!ast_strlen_zero(chan->cdr->userfield)) {
1945 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1946 ast_cdr_appenduserfield(chan, tmp);
1948 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1949 /* free the peer's cdr without ast_cdr_free complaining */
1950 ast_free(peer->cdr);
1955 struct ast_channel *other; /* used later */
1957 res = ast_channel_bridge(chan, peer, config, &f, &who);
1959 if (config->feature_timer) {
1960 /* Update time limit for next pass */
1961 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1962 config->feature_timer -= diff;
1964 /* Running on backup config, meaning a feature might be being
1965 activated, but that's no excuse to keep things going
1967 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1968 ast_debug(1, "Timed out, realtime this time!\n");
1969 config->feature_timer = 0;
1975 } else if (config->feature_timer <= 0) {
1976 /* Not *really* out of time, just out of time for
1977 digits to come in for features. */
1978 ast_debug(1, "Timed out for feature!\n");
1979 if (!ast_strlen_zero(peer_featurecode)) {
1980 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
1981 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1983 if (!ast_strlen_zero(chan_featurecode)) {
1984 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
1985 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1989 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1991 /* Restore original (possibly time modified) bridge config */
1992 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1993 memset(&backup_config, 0, sizeof(backup_config));
1995 hadfeatures = hasfeatures;
1996 /* Continue as we were */
1999 /* The bridge returned without a frame and there is a feature in progress.
2000 * However, we don't think the feature has quite yet timed out, so just
2001 * go back into the bridge. */
2005 if (config->feature_timer <=0) {
2006 /* We ran out of time */
2007 config->feature_timer = 0;
2017 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
2018 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
2022 if (!f || (f->frametype == AST_FRAME_CONTROL &&
2023 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
2024 f->subclass == AST_CONTROL_CONGESTION))) {
2028 /* many things should be sent to the 'other' channel */
2029 other = (who == chan) ? peer : chan;
2030 if (f->frametype == AST_FRAME_CONTROL) {
2031 switch (f->subclass) {
2032 case AST_CONTROL_RINGING:
2033 case AST_CONTROL_FLASH:
2035 ast_indicate(other, f->subclass);
2037 case AST_CONTROL_HOLD:
2038 case AST_CONTROL_UNHOLD:
2039 ast_indicate_data(other, f->subclass, f->data, f->datalen);
2041 case AST_CONTROL_OPTION:
2043 /* Forward option Requests */
2044 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
2045 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
2046 f->datalen - sizeof(struct ast_option_header), 0);
2050 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
2052 } else if (f->frametype == AST_FRAME_DTMF) {
2056 hadfeatures = hasfeatures;
2057 /* This cannot overrun because the longest feature is one shorter than our buffer */
2059 sense = FEATURE_SENSE_CHAN;
2060 featurecode = chan_featurecode;
2062 sense = FEATURE_SENSE_PEER;
2063 featurecode = peer_featurecode;
2065 /*! append the event to featurecode. we rely on the string being zero-filled, and
2066 * not overflowing it.
2067 * \todo XXX how do we guarantee the latter ?
2069 featurecode[strlen(featurecode)] = f->subclass;
2070 /* Get rid of the frame before we start doing "stuff" with the channels */
2073 config->feature_timer = backup_config.feature_timer;
2074 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
2076 case FEATURE_RETURN_PASSDIGITS:
2077 ast_dtmf_stream(other, who, featurecode, 0, 0);
2079 case FEATURE_RETURN_SUCCESS:
2080 memset(featurecode, 0, sizeof(chan_featurecode));
2083 if (res >= FEATURE_RETURN_PASSDIGITS) {
2087 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
2088 if (hadfeatures && !hasfeatures) {
2089 /* Restore backup */
2090 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
2091 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
2092 } else if (hasfeatures) {
2094 /* Backup configuration */
2095 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
2096 /* Setup temporary config options */
2097 config->play_warning = 0;
2098 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
2099 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
2100 config->warning_freq = 0;
2101 config->warning_sound = NULL;
2102 config->end_sound = NULL;
2103 config->start_sound = NULL;
2104 config->firstpass = 0;
2106 config->start_time = ast_tvnow();
2107 config->feature_timer = featuredigittimeout;
2108 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
2115 /* arrange the cdrs */
2116 bridge_cdr = ast_cdr_alloc();
2118 if (chan->cdr && peer->cdr) { /* both of them? merge */
2119 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
2120 ast_cdr_start(bridge_cdr); /* now is the time to start */
2122 /* absorb the channel cdr */
2123 ast_cdr_merge(bridge_cdr, chan->cdr);
2124 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
2125 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2127 /* absorb the peer cdr */
2128 ast_cdr_merge(bridge_cdr, peer->cdr);
2129 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
2130 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
2133 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2134 } else if (chan->cdr) {
2135 /* take the cdr from the channel - literally */
2136 ast_cdr_init(bridge_cdr,chan);
2137 /* absorb this data */
2138 ast_cdr_merge(bridge_cdr, chan->cdr);
2139 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
2140 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2141 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2142 } else if (peer->cdr) {
2143 /* take the cdr from the peer - literally */
2144 ast_cdr_init(bridge_cdr,peer);
2145 /* absorb this data */
2146 ast_cdr_merge(bridge_cdr, peer->cdr);
2147 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
2148 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
2150 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
2152 /* make up a new cdr */
2153 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
2154 chan->cdr = bridge_cdr; /* */
2156 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
2157 if (strcmp(bridge_cdr->channel, peer->name) != 0)
2158 ast_cdr_setdestchan(bridge_cdr, peer->name);
2160 ast_cdr_setdestchan(bridge_cdr, chan->name);
2166 /*! \brief Output parking event to manager */
2167 static void post_manager_event(const char *s, struct parkeduser *pu)
2169 manager_event(EVENT_FLAG_CALL, s,
2172 "CallerIDNum: %s\r\n"
2173 "CallerIDName: %s\r\n\r\n",
2176 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2177 S_OR(pu->chan->cid.cid_name, "<unknown>")
2182 * \brief Take care of parked calls and unpark them if needed
2183 * \param ignore unused var.
2185 * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2186 * if so, remove channel from parking lot and return it to the extension that parked it.
2187 * Check if parked channel decided to hangup, wait until next FD via select().
2189 static void *do_parking_thread(void *ignore)
2191 char parkingslot[AST_MAX_EXTENSION];
2192 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
2198 struct parkeduser *pu;
2199 int ms = -1; /* select timeout, uninitialized */
2200 int max = -1; /* max fd, none there yet */
2201 fd_set nrfds, nefds; /* args for the next select */
2205 AST_LIST_LOCK(&parkinglot);
2206 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2207 struct ast_channel *chan = pu->chan; /* shorthand */
2208 int tms; /* timeout for this item */
2209 int x; /* fd index in channel */
2210 struct ast_context *con;
2212 if (pu->notquiteyet) /* Pretend this one isn't here yet */
2214 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2215 if (tms > pu->parkingtime) {
2216 ast_indicate(chan, AST_CONTROL_UNHOLD);
2217 /* Get chan, exten from derived kludge */
2218 if (pu->peername[0]) {
2219 char *peername = ast_strdupa(pu->peername);
2220 char *cp = strrchr(peername, '-');
2221 char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
2226 ast_copy_string(peername_flat,peername,sizeof(peername_flat));
2227 for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
2228 if (peername_flat[i] == '/')
2229 peername_flat[i]= '0';
2231 con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
2233 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
2235 char returnexten[AST_MAX_EXTENSION];
2236 struct ast_datastore *features_datastore;
2237 struct ast_dial_features *dialfeatures = NULL;
2239 ast_channel_lock(chan);
2241 if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
2242 dialfeatures = features_datastore->data;
2244 ast_channel_unlock(chan);
2247 snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
2248 else /* Existing default */
2249 snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
2251 ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
2253 if (comebacktoorigin) {
2254 set_c_e_p(chan, parking_con_dial, peername_flat, 1);
2256 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2257 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2258 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
2259 set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
2262 /* They've been waiting too long, send them back to where they came. Theoretically they
2263 should have their original extensions and such, but we copy to be on the safe side */
2264 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2267 post_manager_event("ParkedCallTimeOut", pu);
2269 ast_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
2270 /* Start up the PBX, or hang them up */
2271 if (ast_pbx_start(chan)) {
2272 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
2275 /* And take them out of the parking lot */
2276 AST_LIST_REMOVE_CURRENT(list);
2277 con = ast_context_find(parking_con);
2279 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2280 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2282 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2284 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2286 } else { /* still within parking time, process descriptors */
2287 for (x = 0; x < AST_MAX_FDS; x++) {
2288 struct ast_frame *f;
2290 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
2291 continue; /* nothing on this descriptor */
2293 if (FD_ISSET(chan->fds[x], &efds))
2294 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2296 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2299 /* See if they need servicing */
2301 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
2304 post_manager_event("ParkedCallGiveUp", pu);
2306 /* There's a problem, hang them up*/
2307 ast_verb(2, "%s got tired of being parked\n", chan->name);
2309 /* And take them out of the parking lot */
2310 AST_LIST_REMOVE_CURRENT(list);
2311 con = ast_context_find(parking_con);
2313 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2314 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2316 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2318 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2322 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2324 if (pu->moh_trys < 3 && !chan->generatordata) {
2325 ast_debug(1, "MOH on parked call stopped by outside source. Restarting.\n");
2326 ast_indicate_data(chan, AST_CONTROL_HOLD,
2327 S_OR(parkmohclass, NULL),
2328 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
2331 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
2335 if (x >= AST_MAX_FDS) {
2336 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2337 if (chan->fds[x] > -1) {
2338 FD_SET(chan->fds[x], &nrfds);
2339 FD_SET(chan->fds[x], &nefds);
2340 if (chan->fds[x] > max)
2344 /* Keep track of our shortest wait */
2345 if (tms < ms || ms < 0)
2350 AST_LIST_TRAVERSE_SAFE_END
2351 AST_LIST_UNLOCK(&parkinglot);
2355 struct timeval tv = ast_samp2tv(ms, 1000);
2356 /* Wait for something to happen */
2357 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2359 pthread_testcancel();
2361 return NULL; /* Never reached */
2364 /*! \brief Park a call */
2365 static int park_call_exec(struct ast_channel *chan, void *data)
2367 /* Cache the original channel name in case we get masqueraded in the middle
2368 * of a park--it is still theoretically possible for a transfer to happen before
2369 * we get here, but it is _really_ unlikely */
2370 char *orig_chan_name = ast_strdupa(chan->name);
2371 char orig_exten[AST_MAX_EXTENSION];
2372 int orig_priority = chan->priority;
2374 /* Data is unused at the moment but could contain a parking
2375 lot context eventually */
2378 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
2380 /* Setup the exten/priority to be s/1 since we don't know
2381 where this call should return */
2382 strcpy(chan->exten, "s");
2384 /* Answer if call is not up */
2385 if (chan->_state != AST_STATE_UP)
2386 res = ast_answer(chan);
2387 /* Sleep to allow VoIP streams to settle down */
2389 res = ast_safe_sleep(chan, 1000);
2392 res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
2393 /* Continue on in the dialplan */
2395 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
2396 chan->priority = orig_priority;
2399 res = AST_PBX_KEEPALIVE;
2405 /*! \brief Pickup parked call */
2406 static int park_exec(struct ast_channel *chan, void *data)
2409 struct ast_channel *peer=NULL;
2410 struct parkeduser *pu;
2411 struct ast_context *con;
2413 struct ast_bridge_config config;
2416 park = atoi((char *)data);
2418 AST_LIST_LOCK(&parkinglot);
2419 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2420 if (!data || pu->parkingnum == park) {
2421 AST_LIST_REMOVE_CURRENT(list);
2425 AST_LIST_TRAVERSE_SAFE_END
2426 AST_LIST_UNLOCK(&parkinglot);
2430 con = ast_context_find(parking_con);
2432 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2433 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2435 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2437 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2439 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2443 "CallerIDNum: %s\r\n"
2444 "CallerIDName: %s\r\n",
2445 pu->parkingexten, pu->chan->name, chan->name,
2446 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2447 S_OR(pu->chan->cid.cid_name, "<unknown>")
2452 /* JK02: it helps to answer the channel if not already up */
2453 if (chan->_state != AST_STATE_UP)
2457 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2459 if (!ast_strlen_zero(courtesytone)) {
2461 ast_indicate(peer, AST_CONTROL_UNHOLD);
2462 if (parkedplay == 0) {
2463 error = ast_stream_and_wait(chan, courtesytone, "");
2464 } else if (parkedplay == 1) {
2465 error = ast_stream_and_wait(peer, courtesytone, "");
2466 } else if (parkedplay == 2) {
2467 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2468 !ast_streamfile(peer, courtesytone, chan->language)) {
2469 /*! \todo XXX we would like to wait on both! */
2470 res = ast_waitstream(chan, "");
2472 res = ast_waitstream(peer, "");
2478 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2483 ast_indicate(peer, AST_CONTROL_UNHOLD);
2485 res = ast_channel_make_compatible(chan, peer);
2487 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2491 /* This runs sorta backwards, since we give the incoming channel control, as if it
2492 were the person called. */
2493 ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
2495 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2496 ast_cdr_setdestchan(chan->cdr, peer->name);
2497 memset(&config, 0, sizeof(struct ast_bridge_config));
2498 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2499 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2500 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2501 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2502 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2503 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2504 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2505 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2506 res = ast_bridge_call(chan, peer, &config);
2508 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2509 ast_cdr_setdestchan(chan->cdr, peer->name);
2511 /* Simulate the PBX hanging up */
2512 if (res != AST_PBX_NO_HANGUP_PEER)
2516 /*! \todo XXX Play a message XXX */
2517 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2518 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2519 ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2527 * \brief Add parking hints for all defined parking lots
2529 * \param start starting parkinglot number
2530 * \param stop ending parkinglot number
2532 static void park_add_hints(char *context, int start, int stop)
2535 char device[AST_MAX_EXTENSION];
2538 for (numext = start; numext <= stop; numext++) {
2539 snprintf(exten, sizeof(exten), "%d", numext);
2540 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2541 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2545 static int load_config(void)
2547 int start = 0, end = 0;
2550 struct ast_context *con = NULL;
2551 struct ast_config *cfg = NULL;
2552 struct ast_variable *var = NULL;
2553 struct feature_group *fg = NULL;
2554 struct ast_flags config_flags = { 0 };
2555 char old_parking_ext[AST_MAX_EXTENSION];
2556 char old_parking_con[AST_MAX_EXTENSION] = "";
2558 static const char *categories[] = {
2559 /* Categories in features.conf that are not
2560 * to be parsed as group categories
2567 if (!ast_strlen_zero(parking_con)) {
2568 strcpy(old_parking_ext, parking_ext);
2569 strcpy(old_parking_con, parking_con);
2572 /* Reset to defaults */
2573 strcpy(parking_con, "parkedcalls");
2574 strcpy(parking_con_dial, "park-dial");
2575 strcpy(parking_ext, "700");
2576 strcpy(pickup_ext, "*8");
2577 strcpy(parkmohclass, "default");
2578 courtesytone[0] = '\0';
2579 strcpy(xfersound, "beep");
2580 strcpy(xferfailsound, "pbx-invalid");
2581 parking_start = 701;
2585 comebacktoorigin = 1;
2587 parkedcalltransfers = 0;
2588 parkedcallreparking = 0;
2590 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2591 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2592 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2593 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2594 atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2595 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2597 cfg = ast_config_load("features.conf", config_flags);
2599 ast_log(LOG_WARNING,"Could not load features.conf\n");
2602 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2603 if (!strcasecmp(var->name, "parkext")) {
2604 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2605 } else if (!strcasecmp(var->name, "context")) {
2606 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2607 } else if (!strcasecmp(var->name, "parkingtime")) {
2608 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2609 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2610 parkingtime = DEFAULT_PARK_TIME;
2612 parkingtime = parkingtime * 1000;
2613 } else if (!strcasecmp(var->name, "parkpos")) {
2614 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2615 ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
2617 parking_start = start;
2620 } else if (!strcasecmp(var->name, "findslot")) {
2621 parkfindnext = (!strcasecmp(var->value, "next"));
2622 } else if (!strcasecmp(var->name, "parkinghints")) {
2623 parkaddhints = ast_true(var->value);
2624 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2625 if (!strcasecmp(var->value, "both"))
2626 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2627 else if (!strcasecmp(var->value, "caller"))
2628 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2629 else if (!strcasecmp(var->value, "callee"))
2630 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2631 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2632 if (!strcasecmp(var->value, "both"))
2633 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2634 else if (!strcasecmp(var->value, "caller"))
2635 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2636 else if (!strcasecmp(var->value, "callee"))
2637 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2638 } else if (!strcasecmp(var->name, "adsipark")) {
2639 adsipark = ast_true(var->value);
2640 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2641 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2642 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2643 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2645 transferdigittimeout = transferdigittimeout * 1000;
2646 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2647 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2648 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2649 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2651 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2652 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2653 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2654 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2656 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2657 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2658 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2659 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2660 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2662 atxferloopdelay *= 1000;
2663 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2664 atxferdropcall = ast_true(var->value);
2665 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2666 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2667 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2668 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2670 } else if (!strcasecmp(var->name, "courtesytone")) {
2671 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2672 } else if (!strcasecmp(var->name, "parkedplay")) {
2673 if (!strcasecmp(var->value, "both"))
2675 else if (!strcasecmp(var->value, "parked"))
2679 } else if (!strcasecmp(var->name, "xfersound")) {
2680 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2681 } else if (!strcasecmp(var->name, "xferfailsound")) {
2682 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2683 } else if (!strcasecmp(var->name, "pickupexten")) {
2684 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2685 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2686 comebacktoorigin = ast_true(var->value);
2687 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2688 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2693 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2694 if (remap_feature(var->name, var->value))
2695 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2698 /* Map a key combination to an application*/
2699 ast_unregister_features();
2700 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2701 char *tmp_val = ast_strdupa(var->value);
2702 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2703 struct ast_call_feature *feature;
2705 /* strsep() sets the argument to NULL if match not found, and it
2706 * is safe to use it with a NULL argument, so we don't check
2709 exten = strsep(&tmp_val,",");
2710 activatedby = strsep(&tmp_val,",");
2711 app = strsep(&tmp_val,",");
2712 app_args = strsep(&tmp_val,",");
2713 moh_class = strsep(&tmp_val,",");
2715 activateon = strsep(&activatedby, "/");
2717 /*! \todo XXX var_name or app_args ? */
2718 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2719 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2720 app, exten, activateon, var->name);
2724 AST_LIST_LOCK(&feature_list);
2725 if ((feature = find_dynamic_feature(var->name))) {
2726 AST_LIST_UNLOCK(&feature_list);
2727 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2730 AST_LIST_UNLOCK(&feature_list);
2732 if (!(feature = ast_calloc(1, sizeof(*feature))))
2735 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2736 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2737 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2740 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2743 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2745 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
2746 feature->operation = feature_exec_app;
2747 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
2749 /* Allow caller and calle to be specified for backwards compatability */
2750 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
2751 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
2752 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
2753 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
2755 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
2756 " must be 'self', or 'peer'\n", var->name);
2760 if (ast_strlen_zero(activatedby))
2761 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2762 else if (!strcasecmp(activatedby, "caller"))
2763 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
2764 else if (!strcasecmp(activatedby, "callee"))
2765 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
2766 else if (!strcasecmp(activatedby, "both"))
2767 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
2769 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
2770 " must be 'caller', or 'callee', or 'both'\n", var->name);
2774 ast_register_feature(feature);
2776 ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
2779 ast_unregister_groups();
2780 AST_RWLIST_WRLOCK(&feature_groups);
2783 while ((ctg = ast_category_browse(cfg, ctg))) {
2784 for (i = 0; i < ARRAY_LEN(categories); i++) {
2785 if (!strcasecmp(categories[i], ctg))
2789 if (i < ARRAY_LEN(categories))
2792 if (!(fg = register_group(ctg)))
2795 for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
2796 struct ast_call_feature *feature;
2798 AST_LIST_LOCK(&feature_list);
2799 if(!(feature = find_dynamic_feature(var->name)) &&
2800 !(feature = ast_find_call_feature(var->name))) {
2801 AST_LIST_UNLOCK(&feature_list);
2802 ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
2805 AST_LIST_UNLOCK(&feature_list);
2807 register_group_feature(fg, var->value, feature);
2811 AST_RWLIST_UNLOCK(&feature_groups);
2813 ast_config_destroy(cfg);
2815 /* Remove the old parking extension */
2816 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
2817 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
2818 notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
2819 ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
2822 if (!(con = ast_context_find_or_create(NULL, NULL, parking_con, registrar))) {
2823 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
2826 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
2828 park_add_hints(parking_con, parking_start, parking_stop);
2830 notify_metermaids(ast_parking_ext(), parking_con, AST_DEVICE_INUSE);
2836 * \brief CLI command to list configured features
2841 * \retval CLI_SUCCESS on success.
2842 * \retval NULL when tab completion is used.
2844 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2847 struct ast_call_feature *feature;
2848 char format[] = "%-25s %-7s %-7s\n";
2853 e->command = "features show";
2855 "Usage: features show\n"
2856 " Lists configured features\n";
2862 ast_cli(a->fd, format, "Builtin Feature", "Default", "Current");
2863 ast_cli(a->fd, format, "---------------", "-------", "-------");
2865 ast_cli(a->fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2867 ast_rwlock_rdlock(&features_lock);
2868 for (i = 0; i < FEATURES_COUNT; i++)
2869 ast_cli(a->fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2870 ast_rwlock_unlock(&features_lock);
2872 ast_cli(a->fd, "\n");
2873 ast_cli(a->fd, format, "Dynamic Feature", "Default", "Current");
2874 ast_cli(a->fd, format, "---------------", "-------", "-------");
2875 if (AST_LIST_EMPTY(&feature_list))
2876 ast_cli(a->fd, "(none)\n");
2878 AST_LIST_LOCK(&feature_list);
2879 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2880 ast_cli(a->fd, format, feature->sname, "no def", feature->exten);
2881 AST_LIST_UNLOCK(&feature_list);
2883 ast_cli(a->fd, "\nCall parking\n");
2884 ast_cli(a->fd, "------------\n");
2885 ast_cli(a->fd,"%-20s: %s\n", "Parking extension", parking_ext);
2886 ast_cli(a->fd,"%-20s: %s\n", "Parking context", parking_con);
2887 ast_cli(a->fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2888 ast_cli(a->fd,"\n");
2893 int ast_features_reload(void)
2897 return RESULT_SUCCESS;
2900 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2904 e->command = "features reload";
2906 "Usage: features reload\n"
2907 " Reloads configured call features from features.conf\n";
2917 static char mandescr_bridge[] =
2918 "Description: Bridge together two channels already in the PBX\n"
2919 "Variables: ( Headers marked with * are required )\n"
2920 " *Channel1: Channel to Bridge to Channel2\n"
2921 " *Channel2: Channel to Bridge to Channel1\n"
2922 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2926 * \brief Actual bridge
2930 * Stop hold music, lock both channels, masq channels,
2931 * after bridge return channel to next priority.
2933 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2936 ast_channel_lock(chan);
2937 ast_setstate(tmpchan, chan->_state);
2938 tmpchan->readformat = chan->readformat;
2939 tmpchan->writeformat = chan->writeformat;
2940 ast_channel_masquerade(tmpchan, chan);
2941 ast_channel_lock(tmpchan);
2942 ast_do_masquerade(tmpchan);
2943 /* when returning from bridge, the channel will continue at the next priority */
2944 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2945 ast_channel_unlock(tmpchan);
2946 ast_channel_unlock(chan);
2950 * \brief Bridge channels together