Make the QuicSession actually delete the QuicConfig after the handshake compelete, and save various members into local state. Protected by quic_reloadable_flag_quic_delete_config. PiperOrigin-RevId: 838907991
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h index cabd955..a34aa63 100755 --- a/quiche/common/quiche_feature_flags_list.h +++ b/quiche/common/quiche_feature_flags_list.h
@@ -25,6 +25,7 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_to_bbr, true, false, "When true, defaults to BBR congestion control instead of Cubic.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_to_bbr_v2, false, false, "If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_delay_connection_close_on_invalid_sni, true, true, "Delay closing the connection on invalid SNI in client hello till after the transport parameters are parsed.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_delete_config, false, false, "If true, the QuicSession will delete the QuicConfig after the handshake completes.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_deliver_stop_sending_to_zombie_streams, true, true, "If true, deliver STOP_SENDING to zombie streams.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_batch_write, false, false, "If true, round-robin stream writes instead of batching in QuicWriteBlockedList.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_server_blackhole_detection, false, false, "If true, disable blackhole detection on server side.")
diff --git a/quiche/quic/core/quic_session.cc b/quiche/quic/core/quic_session.cc index 841c020..d0a766a 100644 --- a/quiche/quic/core/quic_session.cc +++ b/quiche/quic/core/quic_session.cc
@@ -101,6 +101,58 @@ } // namespace +void QuicSession::SavedConfig::DeleteConfig(ParsedQuicVersion version) { + if (!delete_config_) { + config_deleted_ = true; + return; + } + + if (version.IsIetfQuic()) { + QUIC_BUG_IF(no_config_in_delete_config, config_ == nullptr); + } else if (config_ == nullptr) { + return; + } + + if (config_->HasReceivedInitialStreamFlowControlWindowBytes()) { + has_received_initial_stream_flow_control_window_bytes_ = true; + received_initial_stream_flow_control_window_bytes_ = + config_->ReceivedInitialStreamFlowControlWindowBytes(); + } + if (config_->HasReceivedInitialMaxStreamDataBytesUnidirectional()) { + has_received_initial_max_stream_data_bytes_unidirectional_ = true; + received_initial_max_stream_data_bytes_unidirectional_ = + config_->ReceivedInitialMaxStreamDataBytesUnidirectional(); + } + if (config_->HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional()) { + has_received_initial_max_stream_data_bytes_outgoing_bidirectional_ = true; + received_initial_max_stream_data_bytes_outgoing_bidirectional_ = + config_->ReceivedInitialMaxStreamDataBytesOutgoingBidirectional(); + } + if (config_->HasReceivedInitialMaxStreamDataBytesIncomingBidirectional()) { + has_received_initial_max_stream_data_bytes_incoming_bidirectional_ = true; + received_initial_max_stream_data_bytes_incoming_bidirectional_ = + config_->ReceivedInitialMaxStreamDataBytesIncomingBidirectional(); + } + if (config_->HasReceivedMaxBidirectionalStreams()) { + has_received_max_bidirectional_streams_ = true; + received_max_bidirectional_streams_ = + config_->ReceivedMaxBidirectionalStreams(); + } + + get_initial_stream_flow_control_window_to_send_ = + config_->GetInitialStreamFlowControlWindowToSend(); + get_initial_max_stream_data_bytes_unidirectional_to_send_ = + config_->GetInitialMaxStreamDataBytesUnidirectionalToSend(); + get_initial_max_stream_data_bytes_outgoing_bidirectional_to_send_ = + config_->GetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(); + get_initial_max_stream_data_bytes_incoming_bidirectional_to_send_ = + config_->GetInitialMaxStreamDataBytesIncomingBidirectionalToSend(); + received_max_bidirectional_streams_ = + config_->ReceivedMaxBidirectionalStreams(); + idle_network_timeout_ = config_->IdleNetworkTimeout(); + config_.reset(); +} + #define ENDPOINT \ (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ") @@ -1970,7 +2022,7 @@ GetMutableCryptoStream()->NeuterStreamDataOfEncryptionLevel( ENCRYPTION_HANDSHAKE); connection()->OnHandshakeComplete(); - saved_config_.DeleteConfig(); + saved_config_.DeleteConfig(version()); } void QuicSession::OnZeroRttRejected(int reason) {
diff --git a/quiche/quic/core/quic_session.h b/quiche/quic/core/quic_session.h index ca0d23c..562b2db 100644 --- a/quiche/quic/core/quic_session.h +++ b/quiche/quic/core/quic_session.h
@@ -120,86 +120,149 @@ class QUICHE_EXPORT SavedConfig { public: // Creates a new `SavedConfig` which stores a copy of `config`. - SavedConfig(const QuicConfig& config) : config_(config) {} + explicit SavedConfig(const QuicConfig& config) + : config_(std::make_unique<QuicConfig>(config)) {} // Returns the underlying `QuicConfig`. Must not be called after the config // is deleted. QuicConfig* RawConfig() { QUIC_BUG_IF(no_config, config_deleted_); - return &config_; + QUIC_BUG_IF(no_config, delete_config_ && config_ == nullptr); + return config_.get(); } - // Marks the config deleted but does not actually delete it. - // TODO(b/461482627): Store `config_` in a unique_ptr and reset it. - void DeleteConfig() { config_deleted_ = true; } + void DeleteConfig(ParsedQuicVersion version); bool HasReceivedInitialStreamFlowControlWindowBytes() const { - return config_.HasReceivedInitialStreamFlowControlWindowBytes(); + if (delete_config_ && config_ == nullptr) { + return has_received_initial_stream_flow_control_window_bytes_; + } + return config_->HasReceivedInitialStreamFlowControlWindowBytes(); } bool HasReceivedInitialMaxStreamDataBytesUnidirectional() const { - return config_.HasReceivedInitialMaxStreamDataBytesUnidirectional(); + if (delete_config_ && config_ == nullptr) { + return has_received_initial_max_stream_data_bytes_unidirectional_; + } + return config_->HasReceivedInitialMaxStreamDataBytesUnidirectional(); } bool HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional() const { + if (delete_config_ && config_ == nullptr) { + return has_received_initial_max_stream_data_bytes_outgoing_bidirectional_; // NOLINT + } return config_ - .HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional(); + ->HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional(); } bool HasReceivedInitialMaxStreamDataBytesIncomingBidirectional() const { + if (delete_config_ && config_ == nullptr) { + return has_received_initial_max_stream_data_bytes_incoming_bidirectional_; // NOLINT + } return config_ - .HasReceivedInitialMaxStreamDataBytesIncomingBidirectional(); + ->HasReceivedInitialMaxStreamDataBytesIncomingBidirectional(); } bool HasReceivedMaxBidirectionalStreams() const { - return config_.HasReceivedMaxBidirectionalStreams(); + if (delete_config_ && config_ == nullptr) { + return has_received_max_bidirectional_streams_; + } + return config_->HasReceivedMaxBidirectionalStreams(); } uint64_t ReceivedInitialStreamFlowControlWindowBytes() const { - return config_.ReceivedInitialStreamFlowControlWindowBytes(); + if (delete_config_ && config_ == nullptr) { + return received_initial_stream_flow_control_window_bytes_; + } + return config_->ReceivedInitialStreamFlowControlWindowBytes(); } uint64_t ReceivedInitialMaxStreamDataBytesUnidirectional() const { - return config_.ReceivedInitialMaxStreamDataBytesUnidirectional(); + if (delete_config_ && config_ == nullptr) { + return received_initial_max_stream_data_bytes_unidirectional_; + } + return config_->ReceivedInitialMaxStreamDataBytesUnidirectional(); } uint64_t ReceivedInitialMaxStreamDataBytesOutgoingBidirectional() const { - return config_.ReceivedInitialMaxStreamDataBytesOutgoingBidirectional(); + if (delete_config_ && config_ == nullptr) { + return received_initial_max_stream_data_bytes_outgoing_bidirectional_; + } + return config_->ReceivedInitialMaxStreamDataBytesOutgoingBidirectional(); } uint64_t ReceivedInitialMaxStreamDataBytesIncomingBidirectional() const { - return config_.ReceivedInitialMaxStreamDataBytesIncomingBidirectional(); + if (delete_config_ && config_ == nullptr) { + return received_initial_max_stream_data_bytes_incoming_bidirectional_; + } + return config_->ReceivedInitialMaxStreamDataBytesIncomingBidirectional(); } uint64_t GetInitialStreamFlowControlWindowToSend() const { - return config_.GetInitialStreamFlowControlWindowToSend(); + if (delete_config_ && config_ == nullptr) { + return get_initial_stream_flow_control_window_to_send_; + } + return config_->GetInitialStreamFlowControlWindowToSend(); } uint64_t GetInitialMaxStreamDataBytesUnidirectionalToSend() const { - return config_.GetInitialMaxStreamDataBytesUnidirectionalToSend(); + if (delete_config_ && config_ == nullptr) { + return get_initial_max_stream_data_bytes_unidirectional_to_send_; + } + return config_->GetInitialMaxStreamDataBytesUnidirectionalToSend(); } uint64_t GetInitialMaxStreamDataBytesOutgoingBidirectionalToSend() const { - return config_.GetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(); + if (delete_config_ && config_ == nullptr) { + return get_initial_max_stream_data_bytes_outgoing_bidirectional_to_send_; // NOLINT + } + return config_->GetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(); } uint64_t GetInitialMaxStreamDataBytesIncomingBidirectionalToSend() const { - return config_.GetInitialMaxStreamDataBytesIncomingBidirectionalToSend(); + if (delete_config_ && config_ == nullptr) { + return get_initial_max_stream_data_bytes_incoming_bidirectional_to_send_; // NOLINT + } + return config_->GetInitialMaxStreamDataBytesIncomingBidirectionalToSend(); } uint64_t ReceivedMaxBidirectionalStreams() const { - return config_.ReceivedMaxBidirectionalStreams(); + if (delete_config_ && config_ == nullptr) { + return received_max_bidirectional_streams_; + } + return config_->ReceivedMaxBidirectionalStreams(); } QuicTime::Delta IdleNetworkTimeout() const { - return config_.IdleNetworkTimeout(); + if (delete_config_ && config_ == nullptr) { + return idle_network_timeout_; + } + return config_->IdleNetworkTimeout(); } private: - // TODO(b/461482627): Store `config_` in a unique_ptr and reset it in - // `DeleteConfig()`. - QuicConfig config_; + std::unique_ptr<QuicConfig> config_; + // TODO(b/461482627): Delete this when retiring the flag. bool config_deleted_ = false; + const bool delete_config_ = GetQuicReloadableFlag(quic_delete_config); + + bool has_received_initial_stream_flow_control_window_bytes_ = false; + bool has_received_initial_max_stream_data_bytes_unidirectional_ = false; + bool has_received_initial_max_stream_data_bytes_outgoing_bidirectional_ = + false; + bool has_received_initial_max_stream_data_bytes_incoming_bidirectional_ = + false; + bool has_received_max_bidirectional_streams_ = false; + uint64_t received_initial_stream_flow_control_window_bytes_; + uint64_t received_initial_max_stream_data_bytes_unidirectional_; + uint64_t received_initial_max_stream_data_bytes_outgoing_bidirectional_; + uint64_t received_initial_max_stream_data_bytes_incoming_bidirectional_; + uint64_t get_initial_stream_flow_control_window_to_send_; + uint64_t get_initial_max_stream_data_bytes_unidirectional_to_send_; + uint64_t get_initial_max_stream_data_bytes_outgoing_bidirectional_to_send_; + uint64_t get_initial_max_stream_data_bytes_incoming_bidirectional_to_send_; + uint64_t received_max_bidirectional_streams_; + QuicTime::Delta idle_network_timeout_ = QuicTime::Delta::Zero(); }; // Does not take ownership of |connection| or |visitor|.