Add connection option NSLC to always send connection close for idle timeout. Protected by gfe2_reloadable_flag_quic_no_silent_close_for_idle_timeout. PiperOrigin-RevId: 325443767 Change-Id: I681597b69c8bc256a9167c5dc0169217f41373e8
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h index ca972c1..8d907d8 100644 --- a/quic/core/crypto/crypto_protocol.h +++ b/quic/core/crypto/crypto_protocol.h
@@ -307,6 +307,9 @@ // has the highest priority. const QuicTag kRRWS = TAG('R', 'R', 'W', 'S'); // Round robin write scheduling. +const QuicTag kNSLC = TAG('N', 'S', 'L', 'C'); // Always send connection close + // for idle timeout. + // Proof types (i.e. certificate types) // NOTE: although it would be silly to do so, specifying both kX509 and kX59R // is allowed and is equivalent to specifying only kX509.
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index 5f645bd..f442b1b 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -519,6 +519,12 @@ idle_timeout_connection_close_behavior_ = ConnectionCloseBehavior:: SILENT_CLOSE_WITH_CONNECTION_CLOSE_PACKET_SERIALIZED; } + if (GetQuicReloadableFlag(quic_no_silent_close_for_idle_timeout) && + config.HasClientRequestedIndependentOption(kNSLC, perspective_)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_no_silent_close_for_idle_timeout); + idle_timeout_connection_close_behavior_ = + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET; + } if (!ValidateConfigConnectionIds(config)) { return; } @@ -4735,8 +4741,9 @@ return; } QuicErrorCode error_code = QUIC_NETWORK_IDLE_TIMEOUT; - if (GetQuicReloadableFlag(quic_add_silent_idle_timeout) && - perspective_ == Perspective::IS_SERVER) { + if (idle_timeout_connection_close_behavior_ == + ConnectionCloseBehavior:: + SILENT_CLOSE_WITH_CONNECTION_CLOSE_PACKET_SERIALIZED) { error_code = QUIC_SILENT_IDLE_TIMEOUT; } CloseConnection(error_code, error_details,
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index b39f606..c547d19 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -11617,6 +11617,42 @@ } } +TEST_P(QuicConnectionTest, NoSilentClose) { + set_perspective(Perspective::IS_SERVER); + QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false); + if (version().SupportsAntiAmplificationLimit()) { + QuicConnectionPeer::SetAddressValidated(&connection_); + } + + QuicConfig config; + QuicTagVector connection_options; + connection_options.push_back(kNSLC); + config.SetInitialReceivedConnectionOptions(connection_options); + QuicConfigPeer::SetNegotiated(&config, true); + if (connection_.version().AuthenticatesHandshakeConnectionIds()) { + QuicConfigPeer::SetReceivedOriginalConnectionId( + &config, connection_.connection_id()); + QuicConfigPeer::SetReceivedInitialSourceConnectionId(&config, + QuicConnectionId()); + } + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + connection_.SetFromConfig(config); + + EXPECT_TRUE(connection_.connected()); + EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet()); + + EXPECT_CALL(visitor_, + OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF)); + connection_.GetTimeoutAlarm()->Fire(); + if (GetQuicReloadableFlag(quic_no_silent_close_for_idle_timeout)) { + TestConnectionCloseQuicErrorCode(QUIC_NETWORK_IDLE_TIMEOUT); + } else { + // Verify no connection close packet is serialized. + EXPECT_EQ(nullptr, + QuicConnectionPeer::GetConnectionClosePacket(&connection_)); + } +} + } // namespace } // namespace test } // namespace quic