From 077a1b171ccd66e40d74b06d65021467bb57a627 Mon Sep 17 00:00:00 2001
From: George Joseph <gjoseph@sangoma.com>
Date: Fri, 12 Jan 2024 05:47:58 -0700
Subject: [PATCH] Revert "core & res_pjsip: Improve topology change handling."

This reverts commit 315eb551dbd18ecd424a2f32179d4c1f6f6edd26.

Over the past year, we've had several reports of "topology storms"
occurring where 2 external facing channels connected by one or more
local channels and bridges will get themselves in a state where
they continually send each other topology change requests.  This
usually manifests itself in no-audio calls and a flood of
"Exceptionally long queue length" messages.  It appears that this
commit is the cause so we're reverting it for now until we can
determine a more appropriate solution.

Resolves: #530
(cherry picked from commit c31cd32b8296c675f66be7a4d39e89b45c3aec2c)
---
 main/channel.c          |  9 +++++++++
 res/res_pjsip_session.c | 17 ++++++++++-------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/main/channel.c b/main/channel.c
index d7bd42f283..6fda5128c9 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -10970,6 +10970,15 @@ int ast_channel_request_stream_topology_change(struct ast_channel *chan,
 		return -1;
 	}
 
+	if (ast_stream_topology_equal(ast_channel_get_stream_topology(chan), topology)) {
+		ast_debug(2, "%s: Topologies already match. Current: %s  Requested: %s\n",
+				ast_channel_name(chan),
+				ast_str_tmp(256, ast_stream_topology_to_str(ast_channel_get_stream_topology(chan), &STR_TMP)),
+				ast_str_tmp(256, ast_stream_topology_to_str(topology, &STR_TMP)));
+		ast_channel_unlock(chan);
+		return 0;
+	}
+
 	ast_channel_internal_set_stream_topology_change_source(chan, change_source);
 
 	res = ast_channel_tech(chan)->indicate(chan, AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, topology, sizeof(topology));
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index b5a8b3f54c..b1d2dbdf17 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1935,7 +1935,15 @@ static struct ast_sip_session_media_state *resolve_refresh_media_states(
 				/* All the same state, no need to update. */
 				SCOPE_EXIT_EXPR(continue, "%s: All in the same state so nothing to do\n", session_name);
 			}
-			if (dp_state != ca_state) {
+			if (da_state != ca_state) {
+				/*
+				 * Something set the CA state between the time this request was queued
+				 * and now.  The CA state wins so we don't do anything.
+				 */
+				SCOPE_EXIT_EXPR(continue, "%s: Ignoring request to change state from %s to %s\n",
+					session_name, ast_stream_state2str(ca_state), ast_stream_state2str(dp_state));
+			}
+			if (dp_state != da_state) {
 				/* DP needs to update the state */
 				ast_stream_set_state(np_stream, dp_state);
 				SCOPE_EXIT_EXPR(continue, "%s: Changed NP stream state from %s to %s\n",
@@ -5945,7 +5953,6 @@ AST_TEST_DEFINE(test_resolve_refresh_media_states)
 
 	test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
-	test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	CHECKER();
 
@@ -5984,9 +5991,8 @@ AST_TEST_DEFINE(test_resolve_refresh_media_states)
 
 	test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
-	test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
-	test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
+	test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	CHECKER();
 
 	RESET_STATE(7);
@@ -6032,7 +6038,6 @@ AST_TEST_DEFINE(test_resolve_refresh_media_states)
 
 	test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
-	test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	CHECKER();
@@ -6053,8 +6058,6 @@ AST_TEST_DEFINE(test_resolve_refresh_media_states)
 	test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
 
 	test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
-	test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
-	test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
 	CHECKER();
-- 
GitLab