Deprecate --gfe2_reloadable_flag_quic_session_map_consistency_check
PiperOrigin-RevId: 477725360
diff --git a/quiche/quic/core/quic_dispatcher.cc b/quiche/quic/core/quic_dispatcher.cc
index be05103..acce420 100644
--- a/quiche/quic/core/quic_dispatcher.cc
+++ b/quiche/quic/core/quic_dispatcher.cc
@@ -1099,10 +1099,38 @@
}
closed_session_list_.push_back(std::move(it->second));
CleanUpSession(it->first, connection, error, error_details, source);
+ bool session_removed = false;
for (const QuicConnectionId& cid :
connection->GetActiveServerConnectionIds()) {
- reference_counted_session_map_.erase(cid);
+ auto it1 = reference_counted_session_map_.find(cid);
+ if (it1 != reference_counted_session_map_.end()) {
+ const QuicSession* session2 = it1->second.get();
+ // For cid == server_connection_id, session2 is a nullptr (and hence
+ // session2 != session) now since we have std::move the session into
+ // closed_session_list_ above.
+ if (session2 == session || cid == server_connection_id) {
+ reference_counted_session_map_.erase(it1);
+ session_removed = true;
+ } else {
+ // Leave this session in the map.
+ QUIC_BUG(quic_dispatcher_session_mismatch)
+ << "Session is mismatched in the map. server_connection_id: "
+ << server_connection_id << ". Current cid: " << cid
+ << ". Cid of the other session "
+ << (session2 == nullptr
+ ? "null"
+ : session2->connection()->connection_id().ToString());
+ }
+ } else {
+ // GetActiveServerConnectionIds might return the original destination
+ // ID, which is not contained in the session map.
+ QUIC_BUG_IF(quic_dispatcher_session_not_found,
+ cid != connection->GetOriginalDestinationConnectionId())
+ << "Missing session for cid " << cid
+ << ". server_connection_id: " << server_connection_id;
+ }
}
+ QUIC_BUG_IF(quic_session_is_not_removed, !session_removed);
--num_sessions_in_session_map_;
}
diff --git a/quiche/quic/core/quic_dispatcher_test.cc b/quiche/quic/core/quic_dispatcher_test.cc
index 8d14a8c..0382fdb 100644
--- a/quiche/quic/core/quic_dispatcher_test.cc
+++ b/quiche/quic/core/quic_dispatcher_test.cc
@@ -2281,6 +2281,82 @@
}
TEST_P(QuicDispatcherSupportMultipleConnectionIdPerConnectionTest,
+ TryAddNewConnectionIdWithCollision) {
+ AddConnection1();
+ AddConnection2();
+ ASSERT_EQ(dispatcher_->NumSessions(), 2u);
+ ASSERT_THAT(session1_, testing::NotNull());
+ ASSERT_THAT(session2_, testing::NotNull());
+ MockServerConnection* mock_server_connection1 =
+ reinterpret_cast<MockServerConnection*>(connection1());
+ MockServerConnection* mock_server_connection2 =
+ reinterpret_cast<MockServerConnection*>(connection2());
+
+ {
+ // TestConnectionId(2) is already claimed by connection2 but connection1
+ // still thinks it owns it.
+ mock_server_connection1->UnconditionallyAddNewConnectionIdForTest(
+ TestConnectionId(2));
+ EXPECT_EQ(dispatcher_->NumSessions(), 2u);
+ auto* session =
+ QuicDispatcherPeer::FindSession(dispatcher_.get(), TestConnectionId(2));
+ ASSERT_EQ(session, session2_);
+ EXPECT_THAT(mock_server_connection1->GetActiveServerConnectionIds(),
+ testing::ElementsAre(TestConnectionId(1), TestConnectionId(2)));
+ }
+
+ {
+ mock_server_connection2->AddNewConnectionId(TestConnectionId(3));
+ EXPECT_EQ(dispatcher_->NumSessions(), 2u);
+ auto* session =
+ QuicDispatcherPeer::FindSession(dispatcher_.get(), TestConnectionId(3));
+ ASSERT_EQ(session, session2_);
+ EXPECT_THAT(mock_server_connection2->GetActiveServerConnectionIds(),
+ testing::ElementsAre(TestConnectionId(2), TestConnectionId(3)));
+ }
+
+ // Connection2 removes both TestConnectionId(2) & TestConnectionId(3) from the
+ // session map.
+ dispatcher_->OnConnectionClosed(TestConnectionId(2),
+ QuicErrorCode::QUIC_NO_ERROR, "detail",
+ quic::ConnectionCloseSource::FROM_SELF);
+ // QUICHE_BUG fires when connection1 tries to remove TestConnectionId(2)
+ // again from the session_map.
+ EXPECT_QUICHE_BUG(dispatcher_->OnConnectionClosed(
+ TestConnectionId(1), QuicErrorCode::QUIC_NO_ERROR,
+ "detail", quic::ConnectionCloseSource::FROM_SELF),
+ "Missing session for cid");
+}
+
+TEST_P(QuicDispatcherSupportMultipleConnectionIdPerConnectionTest,
+ MismatchedSessionAfterAddingCollidedConnectionId) {
+ AddConnection1();
+ AddConnection2();
+ MockServerConnection* mock_server_connection1 =
+ reinterpret_cast<MockServerConnection*>(connection1());
+
+ {
+ // TestConnectionId(2) is already claimed by connection2 but connection1
+ // still thinks it owns it.
+ mock_server_connection1->UnconditionallyAddNewConnectionIdForTest(
+ TestConnectionId(2));
+ EXPECT_EQ(dispatcher_->NumSessions(), 2u);
+ auto* session =
+ QuicDispatcherPeer::FindSession(dispatcher_.get(), TestConnectionId(2));
+ ASSERT_EQ(session, session2_);
+ EXPECT_THAT(mock_server_connection1->GetActiveServerConnectionIds(),
+ testing::ElementsAre(TestConnectionId(1), TestConnectionId(2)));
+ }
+
+ // Connection1 tries to remove both Cid1 & Cid2, but they point to different
+ // sessions.
+ EXPECT_QUIC_BUG(dispatcher_->OnConnectionClosed(
+ TestConnectionId(1), QuicErrorCode::QUIC_NO_ERROR,
+ "detail", quic::ConnectionCloseSource::FROM_SELF),
+ "Session is mismatched in the map");
+}
+
+TEST_P(QuicDispatcherSupportMultipleConnectionIdPerConnectionTest,
RetireConnectionIdFromSingleConnection) {
AddConnection1();
ASSERT_EQ(dispatcher_->NumSessions(), 1u);