In QUIC, instead of looking up QuicConnection states, consult the session on whether the connection should be closed on STATELESS_RESET. The new approach allows Chrome's connectivity probing manager to make decisions, which is consistent with other path determination logic for probing. Client side change only. not protected. PiperOrigin-RevId: 312556190 Change-Id: I0a295b84312b7c53bdf14c4c7940ce1f60609b09
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index 1ef3cf7..0190967 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -1596,9 +1596,9 @@ // debug_visitor_. DCHECK(VersionHasIetfInvariantHeader(transport_version())); DCHECK_EQ(perspective_, Perspective::IS_CLIENT); - if (last_packet_destination_address_ != self_address()) { + if (!visitor_->ValidateStatelessReset(last_packet_destination_address_, + last_packet_source_address_)) { // This packet is received on a probing path. Do not close connection. - visitor_->OnStatelessResetForProbing(); return; }
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index c1e95f3..9339fb0 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -131,8 +131,11 @@ // bandwidth. Returns true if data was sent, false otherwise. virtual bool SendProbingData() = 0; - // Called when stateless reset packet is received but is on a different path. - virtual void OnStatelessResetForProbing() = 0; + // Called when stateless reset packet is received. Returns true if the + // connection needs to be closed. + virtual bool ValidateStatelessReset( + const quic::QuicSocketAddress& self_address, + const quic::QuicSocketAddress& peer_address) = 0; // Called when the connection experiences a change in congestion window. virtual void OnCongestionWindowChange(QuicTime now) = 0;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index fe94fcf..bb61130 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -7418,6 +7418,7 @@ kTestStatelessResetToken)); std::unique_ptr<QuicReceivedPacket> received( ConstructReceivedPacket(*packet, QuicTime::Zero())); + EXPECT_CALL(visitor_, ValidateStatelessReset(_, _)).WillOnce(Return(true)); EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_PEER)) .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame)); connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received); @@ -7426,33 +7427,6 @@ IsError(QUIC_PUBLIC_RESET)); } -TEST_P(QuicConnectionTest, IetfStatelessResetOnProbingPath) { - if (!VersionHasIetfInvariantHeader(GetParam().version.transport_version)) { - return; - } - const QuicUint128 kTestStatelessResetToken = 1010101; - QuicConfig config; - QuicConfigPeer::SetReceivedStatelessResetToken(&config, - kTestStatelessResetToken); - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - connection_.SetFromConfig(config); - - // Process a normal packet first to set the self address. - QuicReceivedPacket encrypted(nullptr, 0, QuicTime::Zero()); - connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, encrypted); - - std::unique_ptr<QuicEncryptedPacket> packet( - QuicFramer::BuildIetfStatelessResetPacket(connection_id_, - kTestStatelessResetToken)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*packet, QuicTime::Zero())); - EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0); - EXPECT_CALL(visitor_, OnStatelessResetForProbing()); - auto host = kSelfAddress.host(); - QuicSocketAddress alternate_address(host, 80); - connection_.ProcessUdpPacket(alternate_address, kPeerAddress, *received); -} - TEST_P(QuicConnectionTest, GoAway) { if (VersionHasIetfQuicFrames(GetParam().version.transport_version)) { // GoAway is not available in version 99.
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index 0aa3ae4..ae41efc 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -110,7 +110,11 @@ bool is_connectivity_probe) override; void OnCanWrite() override; bool SendProbingData() override; - void OnStatelessResetForProbing() override {} + bool ValidateStatelessReset( + const quic::QuicSocketAddress& /*self_address*/, + const quic::QuicSocketAddress& /*peer_address*/) override { + return true; + } void OnCongestionWindowChange(QuicTime /*now*/) override {} void OnConnectionMigration(AddressChangeType /*type*/) override {} // Adds a connection level WINDOW_UPDATE frame.
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index 491b828..3c311a1 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -499,7 +499,10 @@ MOCK_METHOD(void, OnWriteBlocked, (), (override)); MOCK_METHOD(void, OnCanWrite, (), (override)); MOCK_METHOD(bool, SendProbingData, (), (override)); - MOCK_METHOD(void, OnStatelessResetForProbing, (), (override)); + MOCK_METHOD(bool, + ValidateStatelessReset, + (const quic::QuicSocketAddress&, const quic::QuicSocketAddress&), + (override)); MOCK_METHOD(void, OnCongestionWindowChange, (QuicTime now), (override)); MOCK_METHOD(void, OnConnectionMigration,
diff --git a/quic/test_tools/simulator/quic_endpoint.h b/quic/test_tools/simulator/quic_endpoint.h index 9a3277b..dfc74ee 100644 --- a/quic/test_tools/simulator/quic_endpoint.h +++ b/quic/test_tools/simulator/quic_endpoint.h
@@ -51,7 +51,11 @@ void OnCryptoFrame(const QuicCryptoFrame& frame) override; void OnCanWrite() override; bool SendProbingData() override; - void OnStatelessResetForProbing() override {} + bool ValidateStatelessReset( + const quic::QuicSocketAddress& /*self_address*/, + const quic::QuicSocketAddress& /*peer_address*/) override { + return true; + } bool WillingAndAbleToWrite() const override; bool ShouldKeepConnectionAlive() const override;