In QuicConnection, cancel the previous path validation request before starting a new one. Protected by FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator. PiperOrigin-RevId: 351886493 Change-Id: If1ff60fc9cc423780a64edd8382232182c7df8cf
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index ac8b22d..86872de 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -5561,6 +5561,10 @@ most_recent_alternative_path_ = AlternativePathState(context->self_address(), context->peer_address()); } + if (path_validator_.HasPendingPathValidation()) { + // Cancel and fail any earlier validation. + path_validator_.CancelPathValidation(); + } path_validator_.StartPathValidation(std::move(context), std::move(result_delegate)); }
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index 8ad4214..29ad505 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -11316,6 +11316,55 @@ EXPECT_TRUE(success); } +TEST_P(QuicConnectionTest, NewPathValidationCancelsPreviousOne) { + if (!VersionHasIetfQuicFrames(connection_.version().transport_version) || + !connection_.use_path_validator()) { + return; + } + PathProbeTestInit(Perspective::IS_CLIENT); + const QuicSocketAddress kNewSelfAddress(QuicIpAddress::Any4(), 12345); + EXPECT_NE(kNewSelfAddress, connection_.self_address()); + TestPacketWriter new_writer(version(), &clock_, Perspective::IS_CLIENT); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) + .Times(AtLeast(1u)) + .WillOnce(Invoke([&]() { + EXPECT_EQ(1u, new_writer.packets_write_attempts()); + EXPECT_EQ(1u, new_writer.path_challenge_frames().size()); + EXPECT_EQ(1u, new_writer.padding_frames().size()); + EXPECT_EQ(kNewSelfAddress.host(), + new_writer.last_write_source_address()); + })); + bool success = true; + connection_.ValidatePath( + std::make_unique<TestQuicPathValidationContext>( + kNewSelfAddress, connection_.peer_address(), &new_writer), + std::make_unique<TestValidationResultDelegate>( + kNewSelfAddress, connection_.peer_address(), &success)); + EXPECT_EQ(0u, writer_->packets_write_attempts()); + + // Start another path validation request. + const QuicSocketAddress kNewSelfAddress2(QuicIpAddress::Any4(), 12346); + EXPECT_NE(kNewSelfAddress2, connection_.self_address()); + TestPacketWriter new_writer2(version(), &clock_, Perspective::IS_CLIENT); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)) + .Times(AtLeast(1u)) + .WillOnce(Invoke([&]() { + EXPECT_EQ(1u, new_writer2.packets_write_attempts()); + EXPECT_EQ(1u, new_writer2.path_challenge_frames().size()); + EXPECT_EQ(1u, new_writer2.padding_frames().size()); + EXPECT_EQ(kNewSelfAddress2.host(), + new_writer2.last_write_source_address()); + })); + bool success2 = false; + connection_.ValidatePath( + std::make_unique<TestQuicPathValidationContext>( + kNewSelfAddress2, connection_.peer_address(), &new_writer2), + std::make_unique<TestValidationResultDelegate>( + kNewSelfAddress2, connection_.peer_address(), &success2)); + EXPECT_FALSE(success); + EXPECT_TRUE(connection_.HasPendingPathValidation()); +} + TEST_P(QuicConnectionTest, PathValidationReceivesStatelessReset) { if (!VersionHasIetfQuicFrames(connection_.version().transport_version) || !connection_.use_path_validator()) {