summaryrefslogtreecommitdiff
path: root/main/features.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-02-23 20:14:54 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-02-23 20:14:54 +0000
commit235f88d12270b328ad466889189400666b3e56c1 (patch)
tree466f64dfe6d9a317c51602ca3271406ae4bccab6 /main/features.c
parentc078a1819cff61e8358deb4def8f9f488b592517 (diff)
Fix blind transfer parking issues if the dialed extension is not recognized as a parking extension.
Custom parking extensions may not be coded such that the first and only extension priority is the Park application. These custom parking extensions will not be recognized as parking extensions. When a call is blind transferred to an extension that is not recognized as a parking extension, the normal blind transfer code causes the transferred channel to start executing dialplan. Calls that get parked in this manner do not know the original channel name that parked the call so the original parker could never be called back if the parked call is not retrieved before the timeout time. The parking space is also announced to the call being parked as a side effect of not knowing the original parking channel. * Fix handling of BLINDTRANSFER channel variable for call parking. * Fixed SIP blind transfer using the wrong dialplan context variable to check for the parking extension. (closes issue ASTERISK-19322) Reported by: aragon Tested by: rmudgett, jparker Review: https://reviewboard.asterisk.org/r/1730/ JIRA AST-766 ........ Merged revisions 356521 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 356522 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@356523 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/features.c')
-rw-r--r--main/features.c74
1 files changed, 45 insertions, 29 deletions
diff --git a/main/features.c b/main/features.c
index d3c98a474..96f76d9cb 100644
--- a/main/features.c
+++ b/main/features.c
@@ -784,6 +784,7 @@ static struct ast_exten *get_parking_exten(const char *exten_str, struct ast_cha
struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
const char *app_at_exten;
+ ast_debug(4, "Checking if %s@%s is a parking exten\n", exten_str, context);
exten = pbx_find_extension(chan, NULL, &q, context, exten_str, 1, NULL, NULL,
E_MATCH);
if (!exten) {
@@ -1388,7 +1389,7 @@ static struct parkeduser *park_space_reserve(struct ast_channel *park_me, struct
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
{
struct parkeduser *pu = args->pu;
- const char *event_from;
+ const char *event_from; /*!< Channel name that is parking the call. */
char app_data[AST_MAX_EXTENSION + AST_MAX_CONTEXT];
if (pu == NULL) {
@@ -1407,10 +1408,10 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
if (chan != peer) {
if (ast_test_flag(args, AST_PARK_OPT_RINGING)) {
pu->hold_method = AST_CONTROL_RINGING;
- ast_indicate(pu->chan, AST_CONTROL_RINGING);
+ ast_indicate(chan, AST_CONTROL_RINGING);
} else {
pu->hold_method = AST_CONTROL_HOLD;
- ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
+ ast_indicate_data(chan, AST_CONTROL_HOLD,
S_OR(pu->parkinglot->cfg.mohclass, NULL),
!ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
}
@@ -1421,7 +1422,9 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
if (args->extout)
*(args->extout) = pu->parkingnum;
- if (peer) {
+ if (peer) {
+ event_from = S_OR(args->orig_chan_name, ast_channel_name(peer));
+
/*
* This is so ugly that it hurts, but implementing
* get_base_channel() on local channels could have ugly side
@@ -1436,7 +1439,7 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
char other_side[AST_CHANNEL_NAME];
char *c;
- ast_copy_string(other_side, S_OR(args->orig_chan_name, ast_channel_name(peer)), sizeof(other_side));
+ ast_copy_string(other_side, event_from, sizeof(other_side));
if ((c = strrchr(other_side, ';'))) {
*++c = '1';
}
@@ -1449,8 +1452,11 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
tmpchan = ast_channel_unref(tmpchan);
}
} else {
- ast_copy_string(pu->peername, S_OR(args->orig_chan_name, ast_channel_name(peer)), sizeof(pu->peername));
+ ast_copy_string(pu->peername, event_from, sizeof(pu->peername));
}
+ } else {
+ event_from = S_OR(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"),
+ ast_channel_name(chan));
}
/*
@@ -1486,18 +1492,12 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
/* Wake up the (presumably select()ing) thread */
pthread_kill(parking_thread, SIGURG);
ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n",
- ast_channel_name(pu->chan), pu->parkingnum, pu->parkinglot->name,
+ ast_channel_name(chan), pu->parkingnum, pu->parkinglot->name,
pu->context, pu->exten, pu->priority, (pu->parkingtime / 1000));
- ast_cel_report_event(pu->chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
+ ast_cel_report_event(chan, AST_CEL_PARK_START, NULL, pu->parkinglot->name, peer);
- if (peer) {
- event_from = ast_channel_name(peer);
- } else {
- event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
- }
-
- ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "ParkedCall",
"Exten: %s\r\n"
"Channel: %s\r\n"
"Parkinglot: %s\r\n"
@@ -1508,14 +1508,19 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
"ConnectedLineNum: %s\r\n"
"ConnectedLineName: %s\r\n"
"Uniqueid: %s\r\n",
- pu->parkingexten, ast_channel_name(pu->chan), pu->parkinglot->name, event_from ? event_from : "",
+ pu->parkingexten, ast_channel_name(chan), pu->parkinglot->name, event_from,
(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
- S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
- S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
- S_COR(pu->chan->connected.id.number.valid, pu->chan->connected.id.number.str, "<unknown>"),
- S_COR(pu->chan->connected.id.name.valid, pu->chan->connected.id.name.str, "<unknown>"),
- ast_channel_uniqueid(pu->chan)
+ S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"),
+ S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>"),
+ S_COR(chan->connected.id.number.valid, chan->connected.id.number.str, "<unknown>"),
+ S_COR(chan->connected.id.name.valid, chan->connected.id.name.str, "<unknown>"),
+ ast_channel_uniqueid(chan)
);
+ ast_debug(4, "peer: %s\n", peer ? ast_channel_name(peer) : "-No peer-");
+ ast_debug(4, "args->orig_chan_name: %s\n", args->orig_chan_name ? args->orig_chan_name : "-none-");
+ ast_debug(4, "pu->peername: %s\n", pu->peername);
+ ast_debug(4, "AMI ParkedCall Channel: %s\n", ast_channel_name(chan));
+ ast_debug(4, "AMI ParkedCall From: %s\n", event_from);
if (peer && adsipark && ast_adsi_available(peer)) {
adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
@@ -1550,7 +1555,7 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
if (peer == chan) { /* pu->notquiteyet = 1 */
/* Wake up parking thread if we're really done */
pu->hold_method = AST_CONTROL_HOLD;
- ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
+ ast_indicate_data(chan, AST_CONTROL_HOLD,
S_OR(pu->parkinglot->cfg.mohclass, NULL),
!ast_strlen_zero(pu->parkinglot->cfg.mohclass) ? strlen(pu->parkinglot->cfg.mohclass) + 1 : 0);
pu->notquiteyet = 0;
@@ -3877,6 +3882,10 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a
pbx_builtin_setvar_helper(chan, "BRIDGEPEER", ast_channel_name(peer));
pbx_builtin_setvar_helper(peer, "BRIDGEPEER", ast_channel_name(chan));
+ /* Clear any BLINDTRANSFER since the transfer has completed. */
+ pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
+ pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", NULL);
+
set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
add_features_datastores(chan, peer, config);
@@ -4920,13 +4929,7 @@ END_OPTIONS );
/*! \brief Park a call */
static int park_call_exec(struct ast_channel *chan, const char *data)
{
- /* Cache the original channel name in case we get masqueraded in the middle
- * of a park--it is still theoretically possible for a transfer to happen before
- * we get here, but it is _really_ unlikely */
- char *orig_chan_name = ast_strdupa(ast_channel_name(chan));
- struct ast_park_call_args args = {
- .orig_chan_name = orig_chan_name,
- };
+ struct ast_park_call_args args = { 0, };
struct ast_flags flags = { 0 };
char orig_exten[AST_MAX_EXTENSION];
int orig_priority;
@@ -4935,6 +4938,19 @@ static int park_call_exec(struct ast_channel *chan, const char *data)
char *parse;
struct park_app_args app_args;
+ /*
+ * Cache the original channel name because we are going to
+ * masquerade the channel. Prefer the BLINDTRANSFER channel
+ * name over this channel name. BLINDTRANSFER could be set if
+ * the parking access extension did not get detected and we are
+ * executing the Park application from the dialplan.
+ *
+ * The orig_chan_name is used to return the call to the
+ * originator on parking timeout.
+ */
+ args.orig_chan_name = ast_strdupa(S_OR(
+ pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), ast_channel_name(chan)));
+
/* Answer if call is not up */
if (ast_channel_state(chan) != AST_STATE_UP) {
if (ast_answer(chan)) {