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>
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38 #include <sys/signal.h>
39 #include <netinet/in.h>
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/devicestate.h"
60 #include "asterisk/monitor.h"
62 #define DEFAULT_PARK_TIME 45000
63 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
64 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
65 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
66 #define DEFAULT_ATXFER_DROP_CALL 0
67 #define DEFAULT_ATXFER_LOOP_DELAY 10000
68 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
70 #define AST_MAX_WATCHERS 256
73 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
74 AST_FEATURE_FLAG_ONPEER = (1 << 1),
75 AST_FEATURE_FLAG_ONSELF = (1 << 2),
76 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
77 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
78 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
81 struct feature_group_exten {
82 AST_LIST_ENTRY(feature_group_exten) entry;
83 AST_DECLARE_STRING_FIELDS(
84 AST_STRING_FIELD(exten);
86 struct ast_call_feature *feature;
89 struct feature_group {
90 AST_LIST_ENTRY(feature_group) entry;
91 AST_DECLARE_STRING_FIELDS(
92 AST_STRING_FIELD(gname);
94 AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
97 static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
99 static char *parkedcall = "ParkedCall";
101 static int parkaddhints = 0; /*!< Add parking hints automatically */
102 static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
103 static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
104 static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
105 static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
106 static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
107 static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
108 static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
109 static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
110 static int parking_start; /*!< First available extension for parking */
111 static int parking_stop; /*!< Last available extension for parking */
113 static char courtesytone[256]; /*!< Courtesy tone */
114 static int parkedplay = 0; /*!< Who to play the courtesy tone to */
115 static char xfersound[256]; /*!< Call transfer sound */
116 static char xferfailsound[256]; /*!< Call transfer failure sound */
118 static int parking_offset;
119 static int parkfindnext;
123 static int transferdigittimeout;
124 static int featuredigittimeout;
125 static int comebacktoorigin = 1;
127 static int atxfernoanswertimeout;
128 static unsigned int atxferdropcall;
129 static unsigned int atxferloopdelay;
130 static unsigned int atxfercallbackretries;
132 static char *registrar = "res_features"; /*!< Registrar for operations */
134 /* module and CLI command definitions */
135 static char *synopsis = "Answer a parked call";
137 static char *descrip = "ParkedCall(exten):"
138 "Used to connect to a parked call. This application is always\n"
139 "registered internally and does not need to be explicitly added\n"
140 "into the dialplan, although you should include the 'parkedcalls'\n"
143 static char *parkcall = "Park";
145 static char *synopsis2 = "Park yourself";
147 static char *descrip2 = "Park():"
148 "Used to park yourself (typically in combination with a supervised\n"
149 "transfer to know the parking space). This application is always\n"
150 "registered internally and does not need to be explicitly added\n"
151 "into the dialplan, although you should include the 'parkedcalls'\n"
152 "context (or the context specified in features.conf).\n\n"
153 "If you set the PARKINGEXTEN variable to an extension in your\n"
154 "parking context, park() will park the call on that extension, unless\n"
155 "it already exists. In that case, execution will continue at next\n"
158 static struct ast_app *monitor_app = NULL;
159 static int monitor_ok = 1;
162 struct ast_channel *chan; /*!< Parking channel */
163 struct timeval start; /*!< Time the parking started */
164 int parkingnum; /*!< Parking lot */
165 char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
166 char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
167 char exten[AST_MAX_EXTENSION];
169 int parkingtime; /*!< Maximum length in parking lot before return */
172 unsigned char moh_trys;
173 AST_LIST_ENTRY(parkeduser) list;
176 static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
178 static pthread_t parking_thread;
180 const char *ast_parking_ext(void)
185 const char *ast_pickup_ext(void)
190 struct ast_bridge_thread_obj
192 struct ast_bridge_config bconfig;
193 struct ast_channel *chan;
194 struct ast_channel *peer;
195 unsigned int return_to_pbx:1;
201 * \brief store context, extension and priority
202 * \param chan, context, ext, pri
204 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
206 ast_copy_string(chan->context, context, sizeof(chan->context));
207 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
208 chan->priority = pri;
212 * \brief Check goto on transfer
214 * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
215 * When found make sure the types are compatible. Check if channel is valid
216 * if so start the new channel else hangup the call.
218 static void check_goto_on_transfer(struct ast_channel *chan)
220 struct ast_channel *xferchan;
221 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
222 char *x, *goto_on_transfer;
225 if (ast_strlen_zero(val))
228 goto_on_transfer = ast_strdupa(val);
230 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
233 for (x = goto_on_transfer; x && *x; x++) {
237 /* Make formats okay */
238 xferchan->readformat = chan->readformat;
239 xferchan->writeformat = chan->writeformat;
240 ast_channel_masquerade(xferchan, chan);
241 ast_parseable_goto(xferchan, goto_on_transfer);
242 xferchan->_state = AST_STATE_UP;
243 ast_clear_flag(xferchan, AST_FLAGS_ALL);
244 xferchan->_softhangup = 0;
245 if ((f = ast_read(xferchan))) {
248 ast_pbx_start(xferchan);
250 ast_hangup(xferchan);
254 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);
257 * \brief bridge the call
258 * \param data thread bridge
259 * Set Last Data for respective channels, reset cdr for channels
260 * bridge call, check if we're going back to dialplan
261 * if not hangup both legs of the call
263 static void *ast_bridge_call_thread(void *data)
265 struct ast_bridge_thread_obj *tobj = data;
268 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
269 tobj->chan->data = tobj->peer->name;
270 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
271 tobj->peer->data = tobj->chan->name;
273 if (tobj->chan->cdr) {
274 ast_cdr_reset(tobj->chan->cdr, NULL);
275 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
277 if (tobj->peer->cdr) {
278 ast_cdr_reset(tobj->peer->cdr, NULL);
279 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
282 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
284 if (tobj->return_to_pbx) {
285 if (!ast_check_hangup(tobj->peer)) {
286 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
287 res = ast_pbx_start(tobj->peer);
288 if (res != AST_PBX_SUCCESS)
289 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
291 ast_hangup(tobj->peer);
292 if (!ast_check_hangup(tobj->chan)) {
293 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
294 res = ast_pbx_start(tobj->chan);
295 if (res != AST_PBX_SUCCESS)
296 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
298 ast_hangup(tobj->chan);
300 ast_hangup(tobj->chan);
301 ast_hangup(tobj->peer);
310 * \brief create thread for the parked call
312 * Create thread and attributes, call ast_bridge_call_thread
314 static void ast_bridge_call_thread_launch(void *data)
318 struct sched_param sched;
320 pthread_attr_init(&attr);
321 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
322 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
323 pthread_attr_destroy(&attr);
324 memset(&sched, 0, sizeof(sched));
325 pthread_setschedparam(thread, SCHED_RR, &sched);
329 * \brief Announce call parking by ADSI
331 * \param parkingexten
332 * Create message to show for ADSI, display message.
333 * \retval 0 on success.
334 * \retval -1 on failure.
336 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
339 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
341 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
343 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
345 res = ast_adsi_load_session(chan, NULL, 0, 1);
348 return ast_adsi_print(chan, message, justify, 1);
351 /*! \brief Notify metermaids that we've changed an extension */
352 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
354 ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
355 exten, context, devstate2str(state));
357 ast_devstate_changed(state, "park:%s@%s", exten, context);
360 /*! \brief metermaids callback from devicestate.c */
361 static enum ast_device_state metermaidstate(const char *data)
366 context = ast_strdupa(data);
368 exten = strsep(&context, "@");
370 return AST_DEVICE_INVALID;
372 ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
374 if (!ast_exists_extension(NULL, context, exten, 1, NULL))
375 return AST_DEVICE_NOT_INUSE;
377 return AST_DEVICE_INUSE;
381 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
383 struct parkeduser *pu, *cur;
384 int i, x = -1, parking_range;
385 struct ast_context *con;
386 const char *parkingexten;
388 /* Allocate memory for parking data */
389 if (!(pu = ast_calloc(1, sizeof(*pu))))
392 /* Lock parking lot */
393 AST_LIST_LOCK(&parkinglot);
394 /* Check for channel variable PARKINGEXTEN */
395 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
396 if (!ast_strlen_zero(parkingexten)) {
397 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
398 AST_LIST_UNLOCK(&parkinglot);
400 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
401 return -1; /* We failed to park this call, plain and simple so we need to error out */
403 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
404 x = atoi(parkingexten);
406 /* Select parking space within range */
407 parking_range = parking_stop - parking_start+1;
408 for (i = 0; i < parking_range; i++) {
409 x = (i + parking_offset) % parking_range + parking_start;
410 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
411 if (cur->parkingnum == x)
418 if (!(i < parking_range)) {
419 ast_log(LOG_WARNING, "No more parking spaces\n");
421 AST_LIST_UNLOCK(&parkinglot);
424 /* Set pointer for next parking */
426 parking_offset = x - parking_start + 1;
429 chan->appl = "Parked Call";
434 /* Put the parked channel on hold if we have two different channels */
436 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
437 S_OR(parkmohclass, NULL),
438 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
441 pu->start = ast_tvnow();
443 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
448 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
450 /* Remember what had been dialed, so that if the parking
451 expires, we try to come back to the same place */
452 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
453 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
454 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
455 AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
457 /* If parking a channel directly, don't quiet yet get parking running on it */
460 AST_LIST_UNLOCK(&parkinglot);
461 /* Wake up the (presumably select()ing) thread */
462 pthread_kill(parking_thread, SIGURG);
463 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));
465 if (pu->parkingnum != -1)
466 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
467 manager_event(EVENT_FLAG_CALL, "ParkedCall",
472 "CallerIDNum: %s\r\n"
473 "CallerIDName: %s\r\n",
474 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
475 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
476 S_OR(pu->chan->cid.cid_num, "<unknown>"),
477 S_OR(pu->chan->cid.cid_name, "<unknown>")
480 if (peer && adsipark && ast_adsi_available(peer)) {
481 adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
482 ast_adsi_unload_session(peer);
485 con = ast_context_find(parking_con);
487 con = ast_context_create(NULL, parking_con, registrar);
488 if (!con) /* Still no context? Bad */
489 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
490 /* Tell the peer channel the number of the parking space */
491 if (peer && pu->parkingnum != -1) /* Only say number if it's a number */
492 ast_say_digits(peer, pu->parkingnum, "", peer->language);
494 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free, registrar))
495 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
497 if (pu->notquiteyet) {
498 /* Wake up parking thread if we're really done */
499 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
500 S_OR(parkmohclass, NULL),
501 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
503 pthread_kill(parking_thread, SIGURG);
508 /* Park call via masquraded channel */
509 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
511 struct ast_channel *chan;
514 /* Make a new, fake channel that we'll use to masquerade in the real one */
515 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
516 ast_log(LOG_WARNING, "Unable to create parked channel\n");
520 /* Make formats okay */
521 chan->readformat = rchan->readformat;
522 chan->writeformat = rchan->writeformat;
523 ast_channel_masquerade(chan, rchan);
525 /* Setup the extensions and such */
526 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
528 /* Make the masq execute */
533 ast_park_call(chan, peer, timeout, extout);
538 #define FEATURE_RETURN_HANGUP -1
539 #define FEATURE_RETURN_SUCCESSBREAK 0
540 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
541 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
542 #define FEATURE_RETURN_PASSDIGITS 21
543 #define FEATURE_RETURN_STOREDIGITS 22
544 #define FEATURE_RETURN_SUCCESS 23
546 #define FEATURE_SENSE_CHAN (1 << 0)
547 #define FEATURE_SENSE_PEER (1 << 1)
550 * \brief set caller and callee according to the direction
551 * \param caller, callee, peer, chan, sense
552 * Detect who triggered feature and set callee/caller variables accordingly
554 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
555 struct ast_channel *peer, struct ast_channel *chan, int sense)
557 if (sense == FEATURE_SENSE_PEER) {
567 * \brief support routing for one touch call parking
568 * \param chan channel parking call
569 * \param peer channel to be parked
570 * \param config unsed
572 * \param sense feature options
573 * Setup channel, set return exten,priority to 's,1'
574 * answer chan, sleep chan, park call
576 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
578 struct ast_channel *parker;
579 struct ast_channel *parkee;
581 struct ast_module_user *u;
583 u = ast_module_user_add(chan);
585 set_peers(&parker, &parkee, peer, chan, sense);
586 /* Setup the exten/priority to be s/1 since we don't know
587 where this call should return */
588 strcpy(chan->exten, "s");
590 if (chan->_state != AST_STATE_UP)
591 res = ast_answer(chan);
593 res = ast_safe_sleep(chan, 1000);
595 res = ast_park_call(parkee, parker, 0, NULL);
597 ast_module_user_remove(u);
600 if (sense == FEATURE_SENSE_CHAN)
601 res = AST_PBX_NO_HANGUP_PEER;
603 res = AST_PBX_KEEPALIVE;
610 * \brief Monitor a channel by DTMF
611 * \param chan channel requesting monitor
612 * \param peer channel to be monitored
616 * Check monitor app enabled, setup channels, both caller/callee chans not null
617 * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
618 * \retval FEATURE_RETURN_SUCCESS on success.
619 * \retval -1 on error.
621 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
623 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
626 struct ast_channel *caller_chan, *callee_chan;
629 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
633 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
635 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
639 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
641 if (!ast_strlen_zero(courtesytone)) {
642 if (ast_autoservice_start(callee_chan))
644 if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
645 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
646 ast_autoservice_stop(callee_chan);
649 if (ast_autoservice_stop(callee_chan))
653 if (callee_chan->monitor) {
654 ast_verb(4, "User hit '%s' to stop recording call.\n", code);
655 ast_monitor_stop(callee_chan, 1);
656 return FEATURE_RETURN_SUCCESS;
659 if (caller_chan && callee_chan) {
660 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
661 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
664 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
667 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
670 len = strlen(touch_monitor) + 50;
672 touch_filename = alloca(len);
673 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
674 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
676 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
677 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
678 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
680 touch_filename = alloca(len);
681 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
682 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
685 for(x = 0; x < strlen(args); x++) {
690 ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
692 pbx_exec(callee_chan, monitor_app, args);
693 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
694 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
696 return FEATURE_RETURN_SUCCESS;
699 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
703 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
705 ast_verb(4, "User hit '%s' to disconnect call.\n", code);
706 return FEATURE_RETURN_HANGUP;
709 static int finishup(struct ast_channel *chan)
711 ast_indicate(chan, AST_CONTROL_UNHOLD);
713 return ast_autoservice_stop(chan);
717 * \brief Find the context for the transfer
720 * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
721 * \return a context string
723 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
725 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
726 if (ast_strlen_zero(s))
727 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
728 if (ast_strlen_zero(s)) /* Use the non-macro context to transfer the call XXX ? */
729 s = transferer->macrocontext;
730 if (ast_strlen_zero(s))
731 s = transferer->context;
736 * \brief Blind transfer user to another extension
737 * \param chan channel initiated blind transfer
738 * \param peer channel to be transfered
742 * Place peer on hold, check if tranfered to parkinglot extension,
743 * otherwise check extension exists and transfer caller.
744 * \retval FEATURE_RETURN_SUCCESS.
745 * \retval -1 on failure.
747 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
749 struct ast_channel *transferer;
750 struct ast_channel *transferee;
751 const char *transferer_real_context;
755 set_peers(&transferer, &transferee, peer, chan, sense);
756 transferer_real_context = real_ctx(transferer, transferee);
757 /* Start autoservice on chan while we talk to the originator */
758 ast_autoservice_start(transferee);
759 ast_indicate(transferee, AST_CONTROL_HOLD);
761 memset(xferto, 0, sizeof(xferto));
764 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
766 finishup(transferee);
767 return -1; /* error ? */
769 if (res > 0) /* If they've typed a digit already, handle it */
770 xferto[0] = (char) res;
772 ast_stopstream(transferer);
773 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
774 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
775 finishup(transferee);
778 if (!strcmp(xferto, ast_parking_ext())) {
779 res = finishup(transferee);
782 else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
783 /* We return non-zero, but tell the PBX not to hang the channel when
784 the thread dies -- We have to be careful now though. We are responsible for
785 hanging up the channel, else it will never be hung up! */
787 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
789 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
791 /*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
792 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
793 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
794 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
795 res=finishup(transferee);
796 if (!transferer->cdr) {
797 transferer->cdr=ast_cdr_alloc();
799 ast_cdr_init(transferer->cdr, transferer); /* initilize our channel's cdr */
800 ast_cdr_start(transferer->cdr);
803 if (transferer->cdr) {
804 ast_cdr_setdestchan(transferer->cdr, transferee->name);
805 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
807 if (!transferee->pbx) {
808 /* Doh! Use our handy async_goto functions */
809 if (option_verbose > 2)
810 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
811 ,transferee->name, xferto, transferer_real_context);
812 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
813 ast_log(LOG_WARNING, "Async goto failed :-(\n");
815 /* Set the channel's new extension, since it exists, using transferer context */
816 set_c_e_p(transferee, transferer_real_context, xferto, 0);
818 check_goto_on_transfer(transferer);
821 ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
823 if (ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
824 finishup(transferee);
827 ast_stopstream(transferer);
828 res = finishup(transferee);
830 ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
833 return FEATURE_RETURN_SUCCESS;
837 * \brief make channels compatible
840 * \retval 0 on success.
841 * \retval -1 on failure.
843 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
845 if (ast_channel_make_compatible(c, newchan) < 0) {
846 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
847 c->name, newchan->name);
855 * \brief Attended transfer
861 * Get extension to transfer to, if you cannot generate channel (or find extension)
862 * return to host channel. After called channel answered wait for hangup of transferer,
863 * bridge call between transfer peer (taking them off hold) to attended transfer channel.
864 * \return -1 means what failure/success both?
866 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
868 struct ast_channel *transferer;
869 struct ast_channel *transferee;
870 const char *transferer_real_context;
871 char xferto[256] = "";
872 char callbackto[256] = "";
875 struct ast_channel *newchan;
876 struct ast_channel *xferchan;
877 struct ast_bridge_thread_obj *tobj;
878 struct ast_bridge_config bconfig;
882 ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
883 set_peers(&transferer, &transferee, peer, chan, sense);
884 transferer_real_context = real_ctx(transferer, transferee);
885 /* Start autoservice on chan while we talk to the originator */
886 ast_autoservice_start(transferee);
887 ast_indicate(transferee, AST_CONTROL_HOLD);
890 res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
892 finishup(transferee);
895 if (res > 0) /* If they've typed a digit already, handle it */
896 xferto[0] = (char) res;
898 /* this is specific of atxfer */
899 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
900 if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
901 finishup(transferee);
905 ast_log(LOG_WARNING, "Did not read data.\n");
906 finishup(transferee);
907 if (ast_stream_and_wait(transferer, "beeperr", ""))
909 return FEATURE_RETURN_SUCCESS;
912 /* valid extension, res == 1 */
913 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
914 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
915 finishup(transferee);
916 if (ast_stream_and_wait(transferer, "beeperr", ""))
918 return FEATURE_RETURN_SUCCESS;
922 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
923 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
924 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
926 if (!ast_check_hangup(transferer)) {
927 /* Transferer is up - old behaviour */
928 ast_indicate(transferer, -1);
930 finishup(transferee);
931 /* any reason besides user requested cancel and busy triggers the failed sound */
932 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
933 ast_stream_and_wait(transferer, xferfailsound, ""))
935 if (ast_stream_and_wait(transferer, xfersound, ""))
936 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
937 return FEATURE_RETURN_SUCCESS;
940 if (check_compat(transferer, newchan))
942 memset(&bconfig,0,sizeof(struct ast_bridge_config));
943 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
944 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
945 res = ast_bridge_call(transferer, newchan, &bconfig);
946 if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
948 if (ast_stream_and_wait(transferer, xfersound, ""))
949 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
950 finishup(transferee);
951 transferer->_softhangup = 0;
952 return FEATURE_RETURN_SUCCESS;
954 if (check_compat(transferee, newchan))
956 ast_indicate(transferee, AST_CONTROL_UNHOLD);
958 if ((ast_autoservice_stop(transferee) < 0)
959 || (ast_waitfordigit(transferee, 100) < 0)
960 || (ast_waitfordigit(newchan, 100) < 0)
961 || ast_check_hangup(transferee)
962 || ast_check_hangup(newchan)) {
966 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
971 /* Make formats okay */
972 xferchan->readformat = transferee->readformat;
973 xferchan->writeformat = transferee->writeformat;
974 ast_channel_masquerade(xferchan, transferee);
975 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
976 xferchan->_state = AST_STATE_UP;
977 ast_clear_flag(xferchan, AST_FLAGS_ALL);
978 xferchan->_softhangup = 0;
979 if ((f = ast_read(xferchan)))
981 newchan->_state = AST_STATE_UP;
982 ast_clear_flag(newchan, AST_FLAGS_ALL);
983 newchan->_softhangup = 0;
984 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
985 ast_hangup(xferchan);
989 tobj->chan = xferchan;
990 tobj->peer = newchan;
991 tobj->bconfig = *config;
993 if (ast_stream_and_wait(newchan, xfersound, ""))
994 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
995 ast_bridge_call_thread_launch(tobj);
996 return -1; /* XXX meaning the channel is bridged ? */
997 } else if (!ast_check_hangup(transferee)) {
998 /* act as blind transfer */
999 if (ast_autoservice_stop(transferee) < 0) {
1000 ast_hangup(newchan);
1005 unsigned int tries = 0;
1007 /* newchan wasn't created - we should callback to transferer */
1008 if (!ast_exists_extension(transferer, transferer_real_context, transferer->cid.cid_num, 1, transferee->cid.cid_num)) {
1009 ast_log(LOG_WARNING, "Extension %s does not exist in context %s - callback failed\n",transferer->cid.cid_num,transferer_real_context);
1010 if (ast_stream_and_wait(transferee, "beeperr", ""))
1012 return FEATURE_RETURN_SUCCESS;
1014 snprintf(callbackto, sizeof(callbackto), "%s@%s/n", transferer->cid.cid_num, transferer_real_context); /* append context */
1016 newchan = ast_feature_request_and_dial(transferee, NULL, "Local", ast_best_codec(transferee->nativeformats),
1017 callbackto, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
1018 while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
1019 /* Trying to transfer again */
1020 ast_autoservice_start(transferee);
1021 ast_indicate(transferee, AST_CONTROL_HOLD);
1023 newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
1024 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1);
1025 if (ast_autoservice_stop(transferee) < 0) {
1026 ast_hangup(newchan);
1030 /* Transfer failed, sleeping */
1031 ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
1032 ast_safe_sleep(transferee, atxferloopdelay);
1033 ast_debug(1, "Trying to callback...\n");
1034 newchan = ast_feature_request_and_dial(transferee, NULL, "Local", ast_best_codec(transferee->nativeformats),
1035 callbackto, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0);
1043 /* newchan is up, we should prepare transferee and bridge them */
1044 if (check_compat(transferee, newchan))
1046 ast_indicate(transferee, AST_CONTROL_UNHOLD);
1048 if ((ast_waitfordigit(transferee, 100) < 0)
1049 || (ast_waitfordigit(newchan, 100) < 0)
1050 || ast_check_hangup(transferee)
1051 || ast_check_hangup(newchan)) {
1052 ast_hangup(newchan);
1056 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
1058 ast_hangup(newchan);
1061 /* Make formats okay */
1062 xferchan->readformat = transferee->readformat;
1063 xferchan->writeformat = transferee->writeformat;
1064 ast_channel_masquerade(xferchan, transferee);
1065 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
1066 xferchan->_state = AST_STATE_UP;
1067 ast_clear_flag(xferchan, AST_FLAGS_ALL);
1068 xferchan->_softhangup = 0;
1069 if ((f = ast_read(xferchan)))
1071 newchan->_state = AST_STATE_UP;
1072 ast_clear_flag(newchan, AST_FLAGS_ALL);
1073 newchan->_softhangup = 0;
1074 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
1075 ast_hangup(xferchan);
1076 ast_hangup(newchan);
1079 tobj->chan = xferchan;
1080 tobj->peer = newchan;
1081 tobj->bconfig = *config;
1083 if (ast_stream_and_wait(newchan, xfersound, ""))
1084 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
1085 ast_bridge_call_thread_launch(tobj);
1086 return -1; /* XXX meaning the channel is bridged ? */
1088 /* Transferee hung up */
1089 finishup(transferee);
1094 /* add atxfer and automon as undefined so you can only use em if you configure them */
1095 #define FEATURES_COUNT ARRAY_LEN(builtin_features)
1097 AST_RWLOCK_DEFINE_STATIC(features_lock);
1099 static struct ast_call_feature builtin_features[] =
1101 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1102 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1103 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1104 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1105 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
1109 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
1111 /*! \brief register new feature into feature_list*/
1112 void ast_register_feature(struct ast_call_feature *feature)
1115 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
1119 AST_LIST_LOCK(&feature_list);
1120 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
1121 AST_LIST_UNLOCK(&feature_list);
1123 ast_verb(2, "Registered Feature '%s'\n",feature->sname);
1127 * \brief Add new feature group
1128 * \param fgname feature group name
1129 * Add new feature group to the feature group list insert at head of list.
1130 * \note This function MUST be called while feature_groups is locked.
1132 static struct feature_group* register_group(const char *fgname)
1134 struct feature_group *fg;
1137 ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
1141 if (!(fg = ast_calloc(1, sizeof(*fg))))
1144 if (ast_string_field_init(fg, 128)) {
1149 ast_string_field_set(fg, gname, fgname);
1151 AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
1153 ast_verb(2, "Registered group '%s'\n", fg->gname);
1159 * \brief Add feature to group
1160 * \param fg feature group
1162 * \param feature feature to add
1163 * Check fg and feature specified, add feature to list
1164 * \note This function MUST be called while feature_groups is locked.
1166 static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
1168 struct feature_group_exten *fge;
1170 if (!(fge = ast_calloc(1, sizeof(*fge))))
1173 if (ast_string_field_init(fge, 128)) {
1179 ast_log(LOG_NOTICE, "You didn't pass a group!\n");
1184 ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
1188 ast_string_field_set(fge, exten, (ast_strlen_zero(exten) ? feature->exten : exten));
1190 fge->feature = feature;
1192 AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
1194 ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
1195 feature->sname, fg->gname, exten);
1198 void ast_unregister_feature(struct ast_call_feature *feature)
1203 AST_LIST_LOCK(&feature_list);
1204 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
1205 AST_LIST_UNLOCK(&feature_list);
1209 /*! \brief Remove all features in the list */
1210 static void ast_unregister_features(void)
1212 struct ast_call_feature *feature;
1214 AST_LIST_LOCK(&feature_list);
1215 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
1217 AST_LIST_UNLOCK(&feature_list);
1220 /*! \brief find a call feature by name */
1221 static struct ast_call_feature *find_dynamic_feature(const char *name)
1223 struct ast_call_feature *tmp;
1225 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
1226 if (!strcasecmp(tmp->sname, name))
1233 /*! \brief Remove all feature groups in the list */
1234 static void ast_unregister_groups(void)
1236 struct feature_group *fg;
1237 struct feature_group_exten *fge;
1239 AST_RWLIST_WRLOCK(&feature_groups);
1240 while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
1241 while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
1242 ast_string_field_free_all(fge);
1246 ast_string_field_free_all(fg);
1249 AST_RWLIST_UNLOCK(&feature_groups);
1253 * \brief Find a group by name
1254 * \param name feature name
1255 * \retval feature group on success.
1256 * \retval NULL on failure.
1258 static struct feature_group *find_group(const char *name) {
1259 struct feature_group *fg = NULL;
1261 AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
1262 if (!strcasecmp(fg->gname, name))
1270 * \brief Find a feature extension
1272 * \retval feature group extension on success.
1273 * \retval NULL on failure.
1275 static struct feature_group_exten *find_group_exten(struct feature_group *fg, const char *code) {
1276 struct feature_group_exten *fge = NULL;
1278 AST_LIST_TRAVERSE(&fg->features, fge, entry) {
1279 if(!strcasecmp(fge->exten, code))
1286 void ast_rdlock_call_features(void)
1288 ast_rwlock_rdlock(&features_lock);
1291 void ast_unlock_call_features(void)
1293 ast_rwlock_unlock(&features_lock);
1296 struct ast_call_feature *ast_find_call_feature(const char *name)
1299 for (x = 0; x < FEATURES_COUNT; x++) {
1300 if (!strcasecmp(name, builtin_features[x].sname))
1301 return &builtin_features[x];
1307 * \brief exec an app by feature
1308 * \param chan,peer,config,code,sense
1309 * Find a feature, determine which channel activated
1310 * \retval FEATURE_RETURN_PBX_KEEPALIVE,FEATURE_RETURN_NO_HANGUP_PEER
1312 * \retval -2 when an application cannot be found.
1314 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1316 struct ast_app *app;
1317 struct ast_call_feature *feature;
1318 struct ast_channel *work, *idle;
1321 AST_LIST_LOCK(&feature_list);
1322 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry) {
1323 if (!strcasecmp(feature->exten, code))
1326 AST_LIST_UNLOCK(&feature_list);
1328 if (!feature) { /* shouldn't ever happen! */
1329 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
1333 if (sense == FEATURE_SENSE_CHAN) {
1334 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1335 return FEATURE_RETURN_PASSDIGITS;
1336 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1344 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1345 return FEATURE_RETURN_PASSDIGITS;
1346 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
1355 if (!(app = pbx_findapp(feature->app))) {
1356 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
1360 ast_autoservice_start(idle);
1362 if (!ast_strlen_zero(feature->moh_class))
1363 ast_moh_start(idle, feature->moh_class, NULL);
1365 res = pbx_exec(work, app, feature->app_args);
1367 if (!ast_strlen_zero(feature->moh_class))
1370 ast_autoservice_stop(idle);
1372 if (res == AST_PBX_KEEPALIVE)
1373 return FEATURE_RETURN_PBX_KEEPALIVE;
1374 else if (res == AST_PBX_NO_HANGUP_PEER)
1375 return FEATURE_RETURN_NO_HANGUP_PEER;
1377 return FEATURE_RETURN_SUCCESSBREAK;
1379 return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
1382 static void unmap_features(void)
1386 ast_rwlock_wrlock(&features_lock);
1387 for (x = 0; x < FEATURES_COUNT; x++)
1388 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
1389 ast_rwlock_unlock(&features_lock);
1392 static int remap_feature(const char *name, const char *value)
1396 ast_rwlock_wrlock(&features_lock);
1397 for (x = 0; x < FEATURES_COUNT; x++) {
1398 if (strcasecmp(builtin_features[x].sname, name))
1401 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
1405 ast_rwlock_unlock(&features_lock);
1411 * \brief Check the dynamic features
1412 * \param chan,peer,config,code,sense
1413 * Lock features list, browse for code, unlock list
1414 * \retval res on success.
1415 * \retval -1 on failure.
1417 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
1420 struct ast_flags features;
1421 int res = FEATURE_RETURN_PASSDIGITS;
1422 struct ast_call_feature *feature;
1423 struct feature_group *fg = NULL;
1424 struct feature_group_exten *fge;
1425 const char *dynamic_features=pbx_builtin_getvar_helper(chan,"DYNAMIC_FEATURES");
1428 if (sense == FEATURE_SENSE_CHAN)
1429 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
1431 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
1432 ast_debug(3, "Feature interpret: chan=%s, peer=%s, sense=%d, features=%d\n", chan->name, peer->name, sense, features.flags);
1434 ast_rwlock_rdlock(&features_lock);
1435 for (x = 0; x < FEATURES_COUNT; x++) {
1436 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
1437 !ast_strlen_zero(builtin_features[x].exten)) {
1438 /* Feature is up for consideration */
1439 if (!strcmp(builtin_features[x].exten, code)) {
1440 res = builtin_features[x].operation(chan, peer, config, code, sense);
1442 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
1443 if (res == FEATURE_RETURN_PASSDIGITS)
1444 res = FEATURE_RETURN_STOREDIGITS;
1448 ast_rwlock_unlock(&features_lock);
1450 if (ast_strlen_zero(dynamic_features))
1453 tmp = ast_strdupa(dynamic_features);
1455 while ((tok = strsep(&tmp, "#"))) {
1456 AST_RWLIST_RDLOCK(&feature_groups);
1458 fg = find_group(tok);
1460 if (fg && (fge = find_group_exten(fg, code))) {
1461 res = fge->feature->operation(chan, peer, config, code, sense);
1462 AST_RWLIST_UNLOCK(&feature_groups);
1466 AST_RWLIST_UNLOCK(&feature_groups);
1467 AST_LIST_LOCK(&feature_list);
1469 if(!(feature = find_dynamic_feature(tok))) {
1470 AST_LIST_UNLOCK(&feature_list);
1474 /* Feature is up for consideration */
1475 if (!strcmp(feature->exten, code)) {
1476 ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
1477 res = feature->operation(chan, peer, config, code, sense);
1478 AST_LIST_UNLOCK(&feature_list);
1480 } else if (!strncmp(feature->exten, code, strlen(code)))
1481 res = FEATURE_RETURN_STOREDIGITS;
1483 AST_LIST_UNLOCK(&feature_list);
1489 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
1493 ast_clear_flag(config, AST_FLAGS_ALL);
1495 ast_rwlock_rdlock(&features_lock);
1496 for (x = 0; x < FEATURES_COUNT; x++) {
1497 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
1500 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
1501 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1503 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
1504 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1506 ast_rwlock_unlock(&features_lock);
1508 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
1509 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
1511 if (dynamic_features) {
1512 char *tmp = ast_strdupa(dynamic_features);
1514 struct ast_call_feature *feature;
1516 /* while we have a feature */
1517 while ((tok = strsep(&tmp, "#"))) {
1518 AST_LIST_LOCK(&feature_list);
1519 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
1520 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
1521 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
1522 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
1523 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
1525 AST_LIST_UNLOCK(&feature_list);
1533 * \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
1534 * Request channel, set channel variables, initiate call,check if they want to disconnect
1535 * go into loop, check if timeout has elapsed, check if person to be transfered hung up,
1536 * check for answer break loop, set cdr return channel.
1537 * \todo XXX Check - this is very similar to the code in channel.c
1538 * \return always a channel
1540 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)
1545 struct ast_channel *chan;
1546 struct ast_channel *monitor_chans[2];
1547 struct ast_channel *active_channel;
1548 int res = 0, ready = 0;
1550 if ((chan = ast_request(type, format, data, &cause))) {
1551 ast_set_callerid(chan, cid_num, cid_name, cid_num);
1552 ast_channel_inherit_variables(caller, chan);
1553 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
1555 chan->cdr=ast_cdr_alloc();
1557 ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
1558 ast_cdr_start(chan->cdr);
1562 if (!ast_call(chan, data, timeout)) {
1563 struct timeval started;
1565 char *disconnect_code = NULL, *dialed_code = NULL;
1567 ast_indicate(caller, AST_CONTROL_RINGING);
1568 /* support dialing of the featuremap disconnect code while performing an attended tranfer */
1569 ast_rwlock_rdlock(&features_lock);
1570 for (x = 0; x < FEATURES_COUNT; x++) {
1571 if (strcasecmp(builtin_features[x].sname, "disconnect"))
1574 disconnect_code = builtin_features[x].exten;
1575 len = strlen(disconnect_code) + 1;
1576 dialed_code = alloca(len);
1577 memset(dialed_code, 0, len);
1580 ast_rwlock_unlock(&features_lock);
1582 started = ast_tvnow();
1584 while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
1585 struct ast_frame *f = NULL;
1587 monitor_chans[0] = caller;
1588 monitor_chans[1] = chan;
1589 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
1591 /* see if the timeout has been violated */
1592 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
1593 state = AST_CONTROL_UNHOLD;
1594 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
1595 break; /*doh! timeout*/
1598 if (!active_channel)
1601 if (chan && (chan == active_channel)){
1603 if (f == NULL) { /*doh! where'd he go?*/
1604 state = AST_CONTROL_HANGUP;
1609 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
1610 if (f->subclass == AST_CONTROL_RINGING) {
1611 state = f->subclass;
1612 ast_verb(3, "%s is ringing\n", chan->name);
1613 ast_indicate(caller, AST_CONTROL_RINGING);
1614 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
1615 state = f->subclass;
1616 ast_verb(3, "%s is busy\n", chan->name);
1617 ast_indicate(caller, AST_CONTROL_BUSY);
1621 } else if (f->subclass == AST_CONTROL_ANSWER) {
1622 /* This is what we are hoping for */
1623 state = f->subclass;
1629 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
1631 /* else who cares */
1634 } else if (caller && (active_channel == caller)) {
1635 f = ast_read(caller);
1636 if (f == NULL) { /*doh! where'd he go?*/
1637 if (!igncallerstate) {
1638 if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
1639 /* make this a blind transfer */
1643 state = AST_CONTROL_HANGUP;
1649 if (f->frametype == AST_FRAME_DTMF) {
1650 dialed_code[x++] = f->subclass;
1651 dialed_code[x] = '\0';
1652 if (strlen(dialed_code) == len) {
1654 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
1656 dialed_code[x] = '\0';
1658 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
1659 /* Caller Canceled the call */
1660 state = AST_CONTROL_UNHOLD;
1672 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
1674 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
1676 case AST_CAUSE_BUSY:
1677 state = AST_CONTROL_BUSY;
1679 case AST_CAUSE_CONGESTION:
1680 state = AST_CONTROL_CONGESTION;
1685 ast_indicate(caller, -1);
1686 if (chan && ready) {
1687 if (chan->_state == AST_STATE_UP)
1688 state = AST_CONTROL_ANSWER;
1701 if (chan && res <= 0) {
1702 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
1704 ast_cdr_init(chan->cdr, chan);
1705 snprintf(tmp, 256, "%s/%s", type, (char *)data);
1706 ast_cdr_setapp(chan->cdr,"Dial",tmp);
1707 ast_cdr_update(chan);
1708 ast_cdr_start(chan->cdr);
1709 ast_cdr_end(chan->cdr);
1710 /* If the cause wasn't handled properly */
1711 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
1712 ast_cdr_failed(chan->cdr);
1714 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
1722 * \brief bridge the call and set CDR
1723 * \param chan,peer,config
1724 * Set start time, check for two channels,check if monitor on
1725 * check for feature activation, create new CDR
1726 * \retval res on success.
1727 * \retval -1 on failure to bridge.
1729 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
1731 /* Copy voice back and forth between the two channels. Give the peer
1732 the ability to transfer calls with '#<extension' syntax. */
1733 struct ast_frame *f;
1734 struct ast_channel *who;
1735 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
1736 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
1741 struct ast_option_header *aoh;
1742 struct ast_bridge_config backup_config;
1743 struct ast_cdr *bridge_cdr;
1745 memset(&backup_config, 0, sizeof(backup_config));
1747 config->start_time = ast_tvnow();
1750 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
1751 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
1753 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
1756 const char *monitor_exec;
1757 struct ast_channel *src = NULL;
1759 if (!(monitor_app = pbx_findapp("Monitor")))
1762 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
1764 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
1766 if (monitor_app && src) {
1767 char *tmp = ast_strdupa(monitor_exec);
1768 pbx_exec(src, monitor_app, tmp);
1772 set_config_flags(chan, peer, config);
1773 config->firstpass = 1;
1775 /* Answer if need be */
1776 if (ast_answer(chan))
1778 peer->appl = "Bridged Call";
1779 peer->data = chan->name;
1781 /* copy the userfield from the B-leg to A-leg if applicable */
1782 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
1784 if (!ast_strlen_zero(chan->cdr->userfield)) {
1785 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
1786 ast_cdr_appenduserfield(chan, tmp);
1788 ast_cdr_setuserfield(chan, peer->cdr->userfield);
1789 /* free the peer's cdr without ast_cdr_free complaining */
1790 ast_free(peer->cdr);
1795 struct ast_channel *other; /* used later */
1797 res = ast_channel_bridge(chan, peer, config, &f, &who);
1799 if (config->feature_timer) {
1800 /* Update time limit for next pass */
1801 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
1802 config->feature_timer -= diff;
1804 /* Running on backup config, meaning a feature might be being
1805 activated, but that's no excuse to keep things going
1807 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
1808 ast_debug(1, "Timed out, realtime this time!\n");
1809 config->feature_timer = 0;
1815 } else if (config->feature_timer <= 0) {
1816 /* Not *really* out of time, just out of time for
1817 digits to come in for features. */
1818 ast_debug(1, "Timed out for feature!\n");
1819 if (!ast_strlen_zero(peer_featurecode)) {
1820 ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
1821 memset(peer_featurecode, 0, sizeof(peer_featurecode));
1823 if (!ast_strlen_zero(chan_featurecode)) {
1824 ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
1825 memset(chan_featurecode, 0, sizeof(chan_featurecode));
1829 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1831 /* Restore original (possibly time modified) bridge config */
1832 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1833 memset(&backup_config, 0, sizeof(backup_config));
1835 hadfeatures = hasfeatures;
1836 /* Continue as we were */
1839 /* The bridge returned without a frame and there is a feature in progress.
1840 * However, we don't think the feature has quite yet timed out, so just
1841 * go back into the bridge. */
1845 if (config->feature_timer <=0) {
1846 /* We ran out of time */
1847 config->feature_timer = 0;
1857 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
1861 if (!f || (f->frametype == AST_FRAME_CONTROL &&
1862 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
1863 f->subclass == AST_CONTROL_CONGESTION))) {
1867 /* many things should be sent to the 'other' channel */
1868 other = (who == chan) ? peer : chan;
1869 if (f->frametype == AST_FRAME_CONTROL) {
1870 switch (f->subclass) {
1871 case AST_CONTROL_RINGING:
1872 case AST_CONTROL_FLASH:
1874 ast_indicate(other, f->subclass);
1876 case AST_CONTROL_HOLD:
1877 case AST_CONTROL_UNHOLD:
1878 ast_indicate_data(other, f->subclass, f->data, f->datalen);
1880 case AST_CONTROL_OPTION:
1882 /* Forward option Requests */
1883 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
1884 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
1885 f->datalen - sizeof(struct ast_option_header), 0);
1889 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
1891 } else if (f->frametype == AST_FRAME_DTMF) {
1895 hadfeatures = hasfeatures;
1896 /* This cannot overrun because the longest feature is one shorter than our buffer */
1898 sense = FEATURE_SENSE_CHAN;
1899 featurecode = chan_featurecode;
1901 sense = FEATURE_SENSE_PEER;
1902 featurecode = peer_featurecode;
1904 /*! append the event to featurecode. we rely on the string being zero-filled, and
1905 * not overflowing it.
1906 * \todo XXX how do we guarantee the latter ?
1908 featurecode[strlen(featurecode)] = f->subclass;
1909 /* Get rid of the frame before we start doing "stuff" with the channels */
1912 config->feature_timer = backup_config.feature_timer;
1913 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
1915 case FEATURE_RETURN_PASSDIGITS:
1916 ast_dtmf_stream(other, who, featurecode, 0, 0);
1918 case FEATURE_RETURN_SUCCESS:
1919 memset(featurecode, 0, sizeof(chan_featurecode));
1922 if (res >= FEATURE_RETURN_PASSDIGITS) {
1926 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
1927 if (hadfeatures && !hasfeatures) {
1928 /* Restore backup */
1929 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
1930 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
1931 } else if (hasfeatures) {
1933 /* Backup configuration */
1934 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
1935 /* Setup temporary config options */
1936 config->play_warning = 0;
1937 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
1938 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
1939 config->warning_freq = 0;
1940 config->warning_sound = NULL;
1941 config->end_sound = NULL;
1942 config->start_sound = NULL;
1943 config->firstpass = 0;
1945 config->start_time = ast_tvnow();
1946 config->feature_timer = featuredigittimeout;
1947 ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
1954 /* arrange the cdrs */
1955 bridge_cdr = ast_cdr_alloc();
1957 if (chan->cdr && peer->cdr) { /* both of them? merge */
1958 ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
1959 ast_cdr_start(bridge_cdr); /* now is the time to start */
1961 /* absorb the channel cdr */
1962 ast_cdr_merge(bridge_cdr, chan->cdr);
1963 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
1964 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1966 /* absorb the peer cdr */
1967 ast_cdr_merge(bridge_cdr, peer->cdr);
1968 if (ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
1969 ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
1972 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1973 } else if (chan->cdr) {
1974 /* take the cdr from the channel - literally */
1975 ast_cdr_init(bridge_cdr,chan);
1976 /* absorb this data */
1977 ast_cdr_merge(bridge_cdr, chan->cdr);
1978 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
1979 ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1980 chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1981 } else if (peer->cdr) {
1982 /* take the cdr from the peer - literally */
1983 ast_cdr_init(bridge_cdr,peer);
1984 /* absorb this data */
1985 ast_cdr_merge(bridge_cdr, peer->cdr);
1986 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
1987 ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
1989 peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
1991 /* make up a new cdr */
1992 ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
1993 chan->cdr = bridge_cdr; /* */
1995 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
1996 if (strcmp(bridge_cdr->channel, peer->name) != 0)
1997 ast_cdr_setdestchan(bridge_cdr, peer->name);
1999 ast_cdr_setdestchan(bridge_cdr, chan->name);
2005 /*! \brief Output parking event to manager */
2006 static void post_manager_event(const char *s, struct parkeduser *pu)
2008 manager_event(EVENT_FLAG_CALL, s,
2011 "CallerIDNum: %s\r\n"
2012 "CallerIDName: %s\r\n\r\n",
2015 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2016 S_OR(pu->chan->cid.cid_name, "<unknown>")
2021 * \brief Take care of parked calls and unpark them if needed
2022 * \param ignore unused var
2023 * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
2024 * if so, remove channel from parking lot and return it to the extension that parked it.
2025 * Check if parked channel decided to hangup, wait until next FD via select().
2027 static void *do_parking_thread(void *ignore)
2029 char parkingslot[AST_MAX_EXTENSION];
2030 fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
2036 struct parkeduser *pu;
2037 int ms = -1; /* select timeout, uninitialized */
2038 int max = -1; /* max fd, none there yet */
2039 fd_set nrfds, nefds; /* args for the next select */
2043 AST_LIST_LOCK(&parkinglot);
2044 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2045 struct ast_channel *chan = pu->chan; /* shorthand */
2046 int tms; /* timeout for this item */
2047 int x; /* fd index in channel */
2048 struct ast_context *con;
2050 if (pu->notquiteyet) /* Pretend this one isn't here yet */
2052 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
2053 if (tms > pu->parkingtime) {
2054 ast_indicate(chan, AST_CONTROL_UNHOLD);
2055 /* Get chan, exten from derived kludge */
2056 if (pu->peername[0]) {
2057 char *peername = ast_strdupa(pu->peername);
2058 char *cp = strrchr(peername, '-');
2061 con = ast_context_find(parking_con_dial);
2063 con = ast_context_create(NULL, parking_con_dial, registrar);
2065 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
2068 char returnexten[AST_MAX_EXTENSION];
2069 snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
2070 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free, registrar);
2072 if (comebacktoorigin) {
2073 set_c_e_p(chan, parking_con_dial, peername, 1);
2075 ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
2076 snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
2077 pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
2078 set_c_e_p(chan, "parkedcallstimeout", peername, 1);
2081 /* They've been waiting too long, send them back to where they came. Theoretically they
2082 should have their original extensions and such, but we copy to be on the safe side */
2083 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
2086 post_manager_event("ParkedCallTimeOut", pu);
2088 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);
2089 /* Start up the PBX, or hang them up */
2090 if (ast_pbx_start(chan)) {
2091 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
2094 /* And take them out of the parking lot */
2095 AST_LIST_REMOVE_CURRENT(&parkinglot, list);
2096 con = ast_context_find(parking_con);
2098 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2099 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2101 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2103 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2105 } else { /* still within parking time, process descriptors */
2106 for (x = 0; x < AST_MAX_FDS; x++) {
2107 struct ast_frame *f;
2109 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
2110 continue; /* nothing on this descriptor */
2112 if (FD_ISSET(chan->fds[x], &efds))
2113 ast_set_flag(chan, AST_FLAG_EXCEPTION);
2115 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
2118 /* See if they need servicing */
2120 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
2123 post_manager_event("ParkedCallGiveUp", pu);
2125 /* There's a problem, hang them up*/
2126 ast_verb(2, "%s got tired of being parked\n", chan->name);
2128 /* And take them out of the parking lot */
2129 AST_LIST_REMOVE_CURRENT(&parkinglot, list);
2130 con = ast_context_find(parking_con);
2132 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2133 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2135 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2137 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2141 /*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
2143 if (pu->moh_trys < 3 && !chan->generatordata) {
2144 ast_debug(1, "MOH on parked call stopped by outside source. Restarting.\n");
2145 ast_indicate_data(chan, AST_CONTROL_HOLD,
2146 S_OR(parkmohclass, NULL),
2147 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
2150 goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
2154 if (x >= AST_MAX_FDS) {
2155 std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
2156 if (chan->fds[x] > -1) {
2157 FD_SET(chan->fds[x], &nrfds);
2158 FD_SET(chan->fds[x], &nefds);
2159 if (chan->fds[x] > max)
2163 /* Keep track of our shortest wait */
2164 if (tms < ms || ms < 0)
2169 AST_LIST_TRAVERSE_SAFE_END
2170 AST_LIST_UNLOCK(&parkinglot);
2174 struct timeval tv = ast_samp2tv(ms, 1000);
2175 /* Wait for something to happen */
2176 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
2178 pthread_testcancel();
2180 return NULL; /* Never reached */
2183 /*! \brief Park a call */
2184 static int park_call_exec(struct ast_channel *chan, void *data)
2186 /* Data is unused at the moment but could contain a parking
2187 lot context eventually */
2189 struct ast_module_user *u;
2191 u = ast_module_user_add(chan);
2193 /* Setup the exten/priority to be s/1 since we don't know
2194 where this call should return */
2195 strcpy(chan->exten, "s");
2197 /* Answer if call is not up */
2198 if (chan->_state != AST_STATE_UP)
2199 res = ast_answer(chan);
2200 /* Sleep to allow VoIP streams to settle down */
2202 res = ast_safe_sleep(chan, 1000);
2205 res = ast_park_call(chan, chan, 0, NULL);
2207 ast_module_user_remove(u);
2209 return !res ? AST_PBX_KEEPALIVE : res;
2212 /*! \brief Pickup parked call */
2213 static int park_exec(struct ast_channel *chan, void *data)
2216 struct ast_module_user *u;
2217 struct ast_channel *peer=NULL;
2218 struct parkeduser *pu;
2219 struct ast_context *con;
2222 struct ast_bridge_config config;
2225 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
2229 u = ast_module_user_add(chan);
2231 park = atoi((char *)data);
2233 AST_LIST_LOCK(&parkinglot);
2234 AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
2235 if (pu->parkingnum == park) {
2236 AST_LIST_REMOVE_CURRENT(&parkinglot, list);
2240 AST_LIST_TRAVERSE_SAFE_END
2241 AST_LIST_UNLOCK(&parkinglot);
2245 con = ast_context_find(parking_con);
2247 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
2248 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
2250 notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
2252 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
2254 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
2258 "CallerIDNum: %s\r\n"
2259 "CallerIDName: %s\r\n",
2260 pu->parkingexten, pu->chan->name, chan->name,
2261 S_OR(pu->chan->cid.cid_num, "<unknown>"),
2262 S_OR(pu->chan->cid.cid_name, "<unknown>")
2267 /* JK02: it helps to answer the channel if not already up */
2268 if (chan->_state != AST_STATE_UP)
2272 /* Play a courtesy to the source(s) configured to prefix the bridge connecting */
2274 if (!ast_strlen_zero(courtesytone)) {
2276 ast_indicate(peer, AST_CONTROL_UNHOLD);
2277 if (parkedplay == 0) {
2278 error = ast_stream_and_wait(chan, courtesytone, "");
2279 } else if (parkedplay == 1) {
2280 error = ast_stream_and_wait(peer, courtesytone, "");
2281 } else if (parkedplay == 2) {
2282 if (!ast_streamfile(chan, courtesytone, chan->language) &&
2283 !ast_streamfile(peer, courtesytone, chan->language)) {
2284 /*! \todo XXX we would like to wait on both! */
2285 res = ast_waitstream(chan, "");
2287 res = ast_waitstream(peer, "");
2293 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
2298 ast_indicate(peer, AST_CONTROL_UNHOLD);
2300 res = ast_channel_make_compatible(chan, peer);
2302 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
2306 /* This runs sorta backwards, since we give the incoming channel control, as if it
2307 were the person called. */
2308 ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
2310 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2311 ast_cdr_setdestchan(chan->cdr, peer->name);
2312 memset(&config, 0, sizeof(struct ast_bridge_config));
2313 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2314 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
2315 if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
2316 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
2317 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2318 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
2319 if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
2320 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
2321 res = ast_bridge_call(chan, peer, &config);
2323 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
2324 ast_cdr_setdestchan(chan->cdr, peer->name);
2326 /* Simulate the PBX hanging up */
2327 if (res != AST_PBX_NO_HANGUP_PEER)
2331 /*! \todo XXX Play a message XXX */
2332 if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
2333 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
2334 ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
2338 ast_module_user_remove(u);
2343 static int handle_showfeatures(int fd, int argc, char *argv[])
2346 struct ast_call_feature *feature;
2347 char format[] = "%-25s %-7s %-7s\n";
2349 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
2350 ast_cli(fd, format, "---------------", "-------", "-------");
2352 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
2354 ast_rwlock_rdlock(&features_lock);
2355 for (i = 0; i < FEATURES_COUNT; i++)
2356 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
2357 ast_rwlock_unlock(&features_lock);
2360 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
2361 ast_cli(fd, format, "---------------", "-------", "-------");
2362 if (AST_LIST_EMPTY(&feature_list))
2363 ast_cli(fd, "(none)\n");
2365 AST_LIST_LOCK(&feature_list);
2366 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
2367 ast_cli(fd, format, feature->sname, "no def", feature->exten);
2368 AST_LIST_UNLOCK(&feature_list);
2370 ast_cli(fd, "\nCall parking\n");
2371 ast_cli(fd, "------------\n");
2372 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
2373 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
2374 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
2377 return RESULT_SUCCESS;
2380 static char mandescr_bridge[] =
2381 "Description: Bridge together two channels already in the PBX\n"
2382 "Variables: ( Headers marked with * are required )\n"
2383 " *Channel1: Channel to Bridge to Channel2\n"
2384 " *Channel2: Channel to Bridge to Channel1\n"
2385 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
2389 * \brief Actual bridge
2392 * Stop hold music, lock both channels, masq channels,
2393 * after bridge return channel to next priority.
2395 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
2398 ast_mutex_lock(&chan->lock);
2399 ast_setstate(tmpchan, chan->_state);
2400 tmpchan->readformat = chan->readformat;
2401 tmpchan->writeformat = chan->writeformat;
2402 ast_channel_masquerade(tmpchan, chan);
2403 ast_mutex_lock(&tmpchan->lock);
2404 ast_do_masquerade(tmpchan);
2405 /* when returning from bridge, the channel will continue at the next priority */
2406 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
2407 ast_mutex_unlock(&tmpchan->lock);
2408 ast_mutex_unlock(&chan->lock);
2412 * \brief Bridge channels together
2415 * Make sure valid channels were specified,
2416 * send errors if any of the channels could not be found/locked, answer channels if needed,
2417 * create the placeholder channels and grab the other channels
2418 * make the channels compatible, send error if we fail doing so
2419 * setup the bridge thread object and start the bridge.
2420 * \retval 0 on success or on incorrect use.
2421 * \retval 1 on failure to bridge channels.
2423 static int action_bridge(struct mansession *s, const struct message *m)
2425 const char *channela = astman_get_header(m, "Channel1");
2426 const char *channelb = astman_get_header(m, "Channel2");
2427 const char *playtone = astman_get_header(m, "Tone");
2428 struct ast_channel *chana = NULL, *chanb = NULL;
2429 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
2430 struct ast_bridge_thread_obj *tobj = NULL;
2432 /* make sure valid channels were specified */
2433 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
2434 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
2435 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
2437 ast_mutex_unlock(&chana->lock);
2439 ast_mutex_unlock(&chanb->lock);
2441 /* send errors if any of the channels could not be found/locked */
2444 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
2445 astman_send_error(s, m, buf);
2450 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
2451 astman_send_error(s, m, buf);
2455 astman_send_error(s, m, "Missing channel parameter in request");
2459 /* Answer the channels if needed */
2460 if (chana->_state != AST_STATE_UP)
2462 if (chanb->_state != AST_STATE_UP)
2465 /* create the placeholder channels and grab the other channels */
2466 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2467 NULL, NULL, 0, "Bridge/%s", chana->name))) {
2468 astman_send_error(s, m, "Unable to create temporary channel!");
2472 if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
2473 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
2474 astman_send_error(s, m, "Unable to create temporary channels!");
2475 ast_channel_free(tmpchana);
2479 do_bridge_masquerade(chana, tmpchana);
2480 do_bridge_masquerade(chanb, tmpchanb);
2482 /* make the channels compatible, send error if we fail doing so */
2483 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
2484 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
2485 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
2486 ast_hangup(tmpchana);
2487 ast_hangup(tmpchanb);
2491 /* setup the bridge thread object and start the bridge */
2492 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
2493 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
2494 astman_send_error(s, m, "Unable to spawn a new bridge thread");
2495 ast_hangup(tmpchana);
2496 ast_hangup(tmpchanb);
2500 tobj->chan = tmpchana;
2501 tobj->peer = tmpchanb;
2502 tobj->return_to_pbx = 1;
2504 if (ast_true(playtone)) {
2505 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
2506 if (ast_waitstream(tmpchanb, "") < 0)
2507 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
2511 ast_bridge_call_thread_launch(tobj);
2513 astman_send_ack(s, m, "Launched bridge thread with success");
2518 static char showfeatures_help[] =
2519 "Usage: feature list\n"
2520 " Lists currently configured features.\n";
2523 * \brief CLI command to list parked calls
2527 * Check right usage, lock parking lot, display parked calls, unlock parking lot list.
2528 * \retval CLI_SUCCESS on success.
2529 * \retval CLI_SHOWUSAGE on incorrect number of arguements.
2530 * \retval NULL when tab completion is used.
2532 static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2534 struct parkeduser *cur;
2539 e->command = "parkedcalls show";
2541 "Usage: parkedcalls show\n"
2542 " List currently parked calls\n";
2548 if (a->argc > e->args)
2549 return CLI_SHOWUSAGE;
2551 ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
2552 , "Context", "Extension", "Pri", "Timeout");
2554 AST_LIST_LOCK(&parkinglot);
2555 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
2556 ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
2557 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
2558 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
2562 AST_LIST_UNLOCK(&parkinglot);
2563 ast_cli(a->fd, "%d parked call%s.\n", numparked, ESS(numparked));
2569 static char *handle_parkedcalls_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2571 char *res = handle_parkedcalls(e, cmd, a);
2572 if (cmd == CLI_INIT)
2573 e->command = "show parkedcalls";
2577 static struct ast_cli_entry cli_show_parkedcalls_deprecated = NEW_CLI(handle_parkedcalls_deprecated, "List currently parked calls.");
2579 static struct ast_cli_entry cli_features[] = {
2580 { { "feature", "show", NULL },
2581 handle_showfeatures, "Lists configured features",
2582 showfeatures_help },
2584 NEW_CLI(handle_parkedcalls, "List currently parked calls", .deprecate_cmd = &cli_show_parkedcalls_deprecated),
2588 * \brief Dump parking lot status
2591 * Lock parking lot, iterate list and append parked calls status, unlock parking lot.
2592 * \return Always RESULT_SUCCESS
2594 static int manager_parking_status(struct mansession *s, const struct message *m)
2596 struct parkeduser *cur;
2597 const char *id = astman_get_header(m, "ActionID");
2598 char idText[256] = "";
2600 if (!ast_strlen_zero(id))
2601 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2603 astman_send_ack(s, m, "Parked calls will follow");
2605 AST_LIST_LOCK(&parkinglot);
2607 AST_LIST_TRAVERSE(&parkinglot, cur, list) {
2608 astman_append(s, "Event: ParkedCall\r\n"
2613 "CallerIDNum: %s\r\n"
2614 "CallerIDName: %s\r\n"
2617 cur->parkingnum, cur->chan->name, cur->peername,
2618 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
2619 S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
2620 S_OR(cur->chan->cid.cid_name, ""),
2625 "Event: ParkedCallsComplete\r\n"
2629 AST_LIST_UNLOCK(&parkinglot);
2631 return RESULT_SUCCESS;
2634 static char mandescr_park[] =
2635 "Description: Park a channel.\n"
2636 "Variables: (Names marked with * are required)\n"
2637 " *Channel: Channel name to park\n"
2638 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
2639 " Timeout: Number of milliseconds to wait before callback.\n";
2642 * \brief Create manager event for parked calls
2645 * Get channels involved in park, create event.
2648 static int manager_park(struct mansession *s, const struct message *m)
2650 const char *channel = astman_get_header(m, "Channel");
2651 const char *channel2 = astman_get_header(m, "Channel2");
2652 const char *timeout = astman_get_header(m, "Timeout");
2657 struct ast_channel *ch1, *ch2;
2659 if (ast_strlen_zero(channel)) {
2660 astman_send_error(s, m, "Channel not specified");
2664 if (ast_strlen_zero(channel2)) {
2665 astman_send_error(s, m, "Channel2 not specified");
2669 ch1 = ast_get_channel_by_name_locked(channel);
2671 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
2672 astman_send_error(s, m, buf);
2676 ch2 = ast_get_channel_by_name_locked(channel2);
2678 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
2679 astman_send_error(s, m, buf);
2680 ast_channel_unlock(ch1);
2684 if (!ast_strlen_zero(timeout)) {
2685 sscanf(timeout, "%d", &to);
2688 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
2690 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
2691 astman_send_ack(s, m, "Park successful");
2693 astman_send_error(s, m, "Park failure");
2696 ast_channel_unlock(ch1);
2697 ast_channel_unlock(ch2);
2703 * \brief Pickup a call
2704 * \param chan channel that initiated pickup
2705 * Walk list of channels, checking it is not itself, channel is pbx one,
2706 * check that the callgroup for both channels are the same and the channel is ringing.
2707 * Answer calling channel, flag channel as answered on queue, masq channels together.
2709 int ast_pickup_call(struct ast_channel *chan)
2711 struct ast_channel *cur = NULL;
2714 while ((cur = ast_channel_walk_locked(cur)) != NULL) {
2717 (chan->pickupgroup & cur->callgroup) &&
2718 ((cur->_state == AST_STATE_RINGING) ||
2719 (cur->_state == AST_STATE_RING))) {
2722 ast_channel_unlock(cur);
2725 ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
2726 res = ast_answer(chan);
2728 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
2729 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
2731 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
2732 res = ast_channel_masquerade(cur, chan);
2734 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
2735 ast_channel_unlock(cur);
2737 ast_debug(1, "No call pickup possible...\n");
2743 * \brief Add parking hints for all defined parking lots
2745 * \param start starting parkinglot number
2746 * \param stop ending parkinglot number
2748 static void park_add_hints(char *context, int start, int stop)
2751 char device[AST_MAX_EXTENSION];
2754 for (numext = start; numext <= stop; numext++) {
2755 snprintf(exten, sizeof(exten), "%d", numext);
2756 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
2757 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
2762 static int load_config(void)
2764 int start = 0, end = 0;
2767 struct ast_context *con = NULL;
2768 struct ast_config *cfg = NULL;
2769 struct ast_variable *var = NULL;
2770 struct feature_group *fg = NULL;
2771 struct ast_flags config_flags = { 0 };
2772 char old_parking_ext[AST_MAX_EXTENSION];
2773 char old_parking_con[AST_MAX_EXTENSION] = "";
2775 static const char *categories[] = {
2776 /* Categories in features.conf that are not
2777 * to be parsed as group categories
2784 if (!ast_strlen_zero(parking_con)) {
2785 strcpy(old_parking_ext, parking_ext);
2786 strcpy(old_parking_con, parking_con);
2789 /* Reset to defaults */
2790 strcpy(parking_con, "parkedcalls");
2791 strcpy(parking_con_dial, "park-dial");
2792 strcpy(parking_ext, "700");
2793 strcpy(pickup_ext, "*8");
2794 strcpy(parkmohclass, "default");
2795 courtesytone[0] = '\0';
2796 strcpy(xfersound, "beep");
2797 strcpy(xferfailsound, "pbx-invalid");
2798 parking_start = 701;
2802 comebacktoorigin = 1;
2804 parkedcalltransfers = 0;
2805 parkedcallreparking = 0;
2807 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2808 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2809 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2810 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2811 atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
2812 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2814 cfg = ast_config_load("features.conf", config_flags);
2816 ast_log(LOG_WARNING,"Could not load features.conf\n");
2817 return AST_MODULE_LOAD_DECLINE;
2819 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
2820 if (!strcasecmp(var->name, "parkext")) {
2821 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
2822 } else if (!strcasecmp(var->name, "context")) {
2823 ast_copy_string(parking_con, var->value, sizeof(parking_con));
2824 } else if (!strcasecmp(var->name, "parkingtime")) {
2825 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
2826 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
2827 parkingtime = DEFAULT_PARK_TIME;
2829 parkingtime = parkingtime * 1000;
2830 } else if (!strcasecmp(var->name, "parkpos")) {
2831 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
2832 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);
2834 parking_start = start;
2837 } else if (!strcasecmp(var->name, "findslot")) {
2838 parkfindnext = (!strcasecmp(var->value, "next"));
2839 } else if (!strcasecmp(var->name, "parkinghints")) {
2840 parkaddhints = ast_true(var->value);
2841 } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
2842 if (!strcasecmp(var->value, "both"))
2843 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2844 else if (!strcasecmp(var->value, "caller"))
2845 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2846 else if (!strcasecmp(var->value, "callee"))
2847 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2848 } else if (!strcasecmp(var->name, "parkedcallreparking")) {
2849 if (!strcasecmp(var->value, "both"))
2850 parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
2851 else if (!strcasecmp(var->value, "caller"))
2852 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
2853 else if (!strcasecmp(var->value, "callee"))
2854 parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
2855 } else if (!strcasecmp(var->name, "adsipark")) {
2856 adsipark = ast_true(var->value);
2857 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
2858 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
2859 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
2860 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
2862 transferdigittimeout = transferdigittimeout * 1000;
2863 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
2864 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
2865 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
2866 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
2868 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
2869 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
2870 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
2871 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
2873 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
2874 } else if (!strcasecmp(var->name, "atxferloopdelay")) {
2875 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2876 ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
2877 atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
2879 atxferloopdelay *= 1000;
2880 } else if (!strcasecmp(var->name, "atxferdropcall")) {
2881 atxferdropcall = ast_true(var->value);
2882 } else if (!strcasecmp(var->name, "atxfercallbackretries")) {
2883 if ((sscanf(var->value, "%u", &atxferloopdelay) != 1)) {
2884 ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
2885 atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
2887 } else if (!strcasecmp(var->name, "courtesytone")) {
2888 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
2889 } else if (!strcasecmp(var->name, "parkedplay")) {
2890 if (!strcasecmp(var->value, "both"))
2892 else if (!strcasecmp(var->value, "parked"))
2896 } else if (!strcasecmp(var->name, "xfersound")) {
2897 ast_copy_string(xfersound, var->value, sizeof(xfersound));
2898 } else if (!strcasecmp(var->name, "xferfailsound")) {
2899 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
2900 } else if (!strcasecmp(var->name, "pickupexten")) {
2901 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
2902 } else if (!strcasecmp(var->name, "comebacktoorigin")) {
2903 comebacktoorigin = ast_true(var->value);
2904 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
2905 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
2910 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
2911 if (remap_feature(var->name, var->value))
2912 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
2915 /* Map a key combination to an application*/
2916 ast_unregister_features();
2917 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
2918 char *tmp_val = ast_strdupa(var->value);
2919 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
2920 struct ast_call_feature *feature;
2922 /* strsep() sets the argument to NULL if match not found, and it
2923 * is safe to use it with a NULL argument, so we don't check
2926 exten = strsep(&tmp_val,",");
2927 activatedby = strsep(&tmp_val,",");
2928 app = strsep(&tmp_val,",");
2929 app_args = strsep(&tmp_val,",");
2930 moh_class = strsep(&tmp_val,",");
2932 activateon = strsep(&activatedby, "/");
2934 /*! \todo XXX var_name or app_args ? */
2935 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
2936 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
2937 app, exten, activateon, var->name);
2941 AST_LIST_LOCK(&feature_list);
2942 if ((feature = find_dynamic_feature(var->name))) {
2943 AST_LIST_UNLOCK(&feature_list);
2944 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
2947 AST_LIST_UNLOCK(&feature_list);
2949 if (!(feature = ast_calloc(1, sizeof(*feature))))
2952 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
2953 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
2954 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
2957 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
2960 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
2962 ast_copy_string(feature->exten, ex