More plumbing for fallback configs This CL adds a 'fallback_config_' member to QuicCryptoServerConfig along with plumbing for setting it and passing it around. Nobody sets it to anything other than nullptr yet - a subsequent flag-protected change will modify GFE to set it. gfe-relnote: More no-op-refactoring, not flag-protected. PiperOrigin-RevId: 239831495 Change-Id: I1ff7b119b23c78f18aae64c70d62b2752ae2e97b
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc index 253fb0e..da84c24 100644 --- a/quic/core/crypto/quic_crypto_server_config.cc +++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -394,7 +394,8 @@ return nullptr; } - QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf)); + QuicReferenceCountedPointer<Config> config = + ParseConfigProtobuf(protobuf, /* is_fallback = */ false); if (!config.get()) { QUIC_LOG(WARNING) << "Failed to parse server config message"; return nullptr; @@ -428,10 +429,12 @@ bool QuicCryptoServerConfig::SetConfigs( const std::vector<QuicServerConfigProtobuf>& protobufs, + const QuicServerConfigProtobuf* fallback_protobuf, const QuicWallTime now) { std::vector<QuicReferenceCountedPointer<Config>> parsed_configs; for (auto& protobuf : protobufs) { - QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf)); + QuicReferenceCountedPointer<Config> config = + ParseConfigProtobuf(protobuf, /* is_fallback = */ false); if (!config) { QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors"; return false; @@ -440,6 +443,21 @@ parsed_configs.push_back(config); } + QuicReferenceCountedPointer<Config> fallback_config; + if (fallback_protobuf != nullptr) { + fallback_config = + ParseConfigProtobuf(*fallback_protobuf, /* is_fallback = */ true); + if (!fallback_config) { + QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors"; + return false; + } + QUIC_LOG(INFO) << "Fallback config has scid " + << QuicTextUtils::HexEncode(fallback_config->id); + parsed_configs.push_back(fallback_config); + } else { + QUIC_LOG(INFO) << "No fallback config provided"; + } + if (parsed_configs.empty()) { QUIC_LOG(WARNING) << "Rejecting QUIC configs because new config list is empty."; @@ -482,6 +500,7 @@ } configs_ = std::move(new_configs); + fallback_config_ = fallback_config; SelectNewPrimaryConfig(now); DCHECK(primary_config_.get()); DCHECK_EQ(configs_.find(primary_config_->id)->second.get(), @@ -593,9 +612,9 @@ private: const QuicCryptoServerConfig* config_; std::unique_ptr<ProofSource::Details> proof_source_details_; - QuicTag key_exchange_type_; + const QuicTag key_exchange_type_; std::unique_ptr<CryptoHandshakeMessage> out_; - std::string public_value_; + const std::string public_value_; std::unique_ptr<ProcessClientHelloContext> context_; const Configs configs_; }; @@ -1007,6 +1026,7 @@ configs->primary = primary_config_; } configs->requested = GetConfigWithScid(requested_scid); + configs->fallback = fallback_config_; return true; } @@ -1492,7 +1512,8 @@ QuicReferenceCountedPointer<QuicCryptoServerConfig::Config> QuicCryptoServerConfig::ParseConfigProtobuf( - const QuicServerConfigProtobuf& protobuf) { + const QuicServerConfigProtobuf& protobuf, + bool is_fallback) const { std::unique_ptr<CryptoHandshakeMessage> msg = CryptoFramer::ParseMessage(protobuf.config()); @@ -1585,8 +1606,8 @@ } } - std::unique_ptr<AsynchronousKeyExchange> ka = key_exchange_source_->Create( - config->id, /* is_fallback = */ false, tag, private_key); + std::unique_ptr<AsynchronousKeyExchange> ka = + key_exchange_source_->Create(config->id, is_fallback, tag, private_key); if (!ka) { return nullptr; }
diff --git a/quic/core/crypto/quic_crypto_server_config.h b/quic/core/crypto/quic_crypto_server_config.h index 651195b..91fe60d 100644 --- a/quic/core/crypto/quic_crypto_server_config.h +++ b/quic/core/crypto/quic_crypto_server_config.h
@@ -258,6 +258,7 @@ // currently the primary config. SetConfigs returns false if any errors were // encountered and no changes to the QuicCryptoServerConfig will occur. bool SetConfigs(const std::vector<QuicServerConfigProtobuf>& protobufs, + const QuicServerConfigProtobuf* fallback_protobuf, QuicWallTime now); // SetSourceAddressTokenKeys sets the keys to be tried, in order, when @@ -519,6 +520,7 @@ struct Configs { QuicReferenceCountedPointer<Config> requested; QuicReferenceCountedPointer<Config> primary; + QuicReferenceCountedPointer<Config> fallback; }; // Get a snapshot of the current configs associated with a handshake. If this @@ -724,7 +726,8 @@ // QuicReferenceCountedPointer<Config> if successful. The caller adopts the // reference to the Config. On error, ParseConfigProtobuf returns nullptr. QuicReferenceCountedPointer<Config> ParseConfigProtobuf( - const QuicServerConfigProtobuf& protobuf); + const QuicServerConfigProtobuf& protobuf, + bool is_fallback) const; // NewSourceAddressToken returns a fresh source address token for the given // IP address. |cached_network_params| is optional, and can be nullptr. @@ -867,6 +870,14 @@ mutable QuicReferenceCountedPointer<Config> primary_config_ GUARDED_BY(configs_lock_); + // fallback_config_ points to a Config (which is also in |configs_|) which is + // the fallback config, which will be used if the other configs are unuseable + // for some reason. + // + // TODO(b/112548056): This is currently always nullptr. + QuicReferenceCountedPointer<Config> fallback_config_ + GUARDED_BY(configs_lock_); + // next_config_promotion_time_ contains the nearest, future time when an // active config will be promoted to primary. mutable QuicWallTime next_config_promotion_time_ GUARDED_BY(configs_lock_);
diff --git a/quic/core/crypto/quic_crypto_server_config_test.cc b/quic/core/crypto/quic_crypto_server_config_test.cc index 61f8006..cedd249 100644 --- a/quic/core/crypto/quic_crypto_server_config_test.cc +++ b/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -355,7 +355,8 @@ } ASSERT_EQ(!has_invalid && !configs.empty(), - config_.SetConfigs(protobufs, clock_.WallNow())); + config_.SetConfigs(protobufs, /* fallback_protobuf = */ nullptr, + clock_.WallNow())); } protected: