summaryrefslogtreecommitdiff
path: root/main/bridge_channel.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2016-02-19 19:06:14 -0600
committerRichard Mudgett <rmudgett@digium.com>2016-02-29 12:50:43 -0600
commit86f7336c91bb3fcd0704143ed93d41275080b2e4 (patch)
tree1c17d9f843d6a92e20f86b08d421e03c6461cd3c /main/bridge_channel.c
parent128c96456ce0fc794867317c6a47fb41795c33d5 (diff)
bridge_channel: Don't settle owed events on an optimization.
Local channel optimization could cause DTMF digits to be duplicated. Pending DTMF end events would be posted to a bridge when the local channel optimizes out and is replaced by the channel further down the chain. When the real digit ends, the channel would get another DTMF end posted to the bridge. A -- LocalA;1/n -- LocalA;2/n -- LocalB;1 -- LocalB;2 -- B 1) LocalA has the /n flag to prevent optimization. 2) B is sending DTMF to A through the local channel chain. 3) When LocalB optimizes out it can move B to the position of LocalB;1 4) Without this patch, when B swaps with LocalB;1 then LocalB;1 would settle an owed DTMF end to the bridge toward LocalA;2. 5) When B finally ends its DTMF it sends the DTMF end down the chain. 6) Without this patch, A would hear the DTMF digit end when LocalB optimizes out and when B ends the original digit. ASTERISK-25582 Change-Id: I1bbd28b8b399c0fb54985a5747f330a4cd2aa251
Diffstat (limited to 'main/bridge_channel.c')
-rw-r--r--main/bridge_channel.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index f3483e440..3f141452e 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -675,6 +675,22 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel,
return 0;
}
+/*!
+ * \internal
+ * \brief Cancel owed events by the channel to the bridge.
+ * \since 13.8.0
+ *
+ * \param bridge_channel Channel that owes events to the bridge.
+ *
+ * \note On entry, the bridge_channel->bridge is already locked.
+ *
+ * \return Nothing
+ */
+static void bridge_channel_cancel_owed_events(struct ast_bridge_channel *bridge_channel)
+{
+ bridge_channel->owed.dtmf_digit = '\0';
+}
+
void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct ast_bridge_channel *bridge_channel)
{
if (bridge_channel->owed.dtmf_digit) {
@@ -2037,7 +2053,7 @@ void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel)
ast_bridge_publish_leave(bridge, bridge_channel->chan);
}
-int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
+int bridge_channel_internal_push_full(struct ast_bridge_channel *bridge_channel, int optimized)
{
struct ast_bridge *bridge = bridge_channel->bridge;
struct ast_bridge_channel *swap;
@@ -2073,6 +2089,9 @@ int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
/* This flag is cleared so the act of this channel leaving does not cause it to dissolve if need be */
ast_clear_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_EMPTY);
+ if (optimized) {
+ bridge_channel_cancel_owed_events(swap);
+ }
ast_bridge_channel_leave_bridge(swap, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, 0);
bridge_channel_internal_pull(swap);
@@ -2112,6 +2131,11 @@ int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
return 0;
}
+int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
+{
+ return bridge_channel_internal_push_full(bridge_channel, 0);
+}
+
/*!
* \internal
* \brief Handle bridge channel control frame action.