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