Upon receiving SETTINGS for a QuicSpdyClientSession, serialize the frame and cache it in tls_client_handshaker. gfe-relnote: unused code. not protected. PiperOrigin-RevId: 306897017 Change-Id: I94fbf706b7c9846befb80b1363a79dc022e95828
diff --git a/quic/core/crypto/quic_crypto_client_config.h b/quic/core/crypto/quic_crypto_client_config.h index 3ae19dd..b4675de 100644 --- a/quic/core/crypto/quic_crypto_client_config.h +++ b/quic/core/crypto/quic_crypto_client_config.h
@@ -71,7 +71,7 @@ virtual void Insert(const QuicServerId& server_id, bssl::UniquePtr<SSL_SESSION> session, TransportParameters* params, - std::vector<uint8_t>* application_states) = 0; + ApplicationState* application_states) = 0; // Lookup is called once at the beginning of each TLS handshake to potentially // provide the saved state both for the TLS handshake and for sending 0-RTT
diff --git a/quic/core/http/quic_spdy_client_session_base.cc b/quic/core/http/quic_spdy_client_session_base.cc index a0c70dd..2655259 100644 --- a/quic/core/http/quic_spdy_client_session_base.cc +++ b/quic/core/http/quic_spdy_client_session_base.cc
@@ -222,4 +222,15 @@ return !HasActiveRequestStreams() && promised_by_id_.empty(); } +void QuicSpdyClientSessionBase::OnSettingsFrame(const SettingsFrame& frame) { + QuicSpdySession::OnSettingsFrame(frame); + std::unique_ptr<char[]> buffer; + QuicByteCount frame_length = + HttpEncoder::SerializeSettingsFrame(frame, &buffer); + auto serialized_data = std::make_unique<ApplicationState>( + buffer.get(), buffer.get() + frame_length); + static_cast<QuicCryptoClientStreamBase*>(GetMutableCryptoStream()) + ->OnApplicationState(std::move(serialized_data)); +} + } // namespace quic
diff --git a/quic/core/http/quic_spdy_client_session_base.h b/quic/core/http/quic_spdy_client_session_base.h index 7d4ba01..9d702e3 100644 --- a/quic/core/http/quic_spdy_client_session_base.h +++ b/quic/core/http/quic_spdy_client_session_base.h
@@ -117,6 +117,9 @@ return push_promise_index_; } + // Override to serialize the settings and pass it down to the handshaker. + void OnSettingsFrame(const SettingsFrame& frame) override; + private: // For QuicSpdyClientStream to detect that a response corresponds to a // promise.
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc index f702671..65dd43a 100644 --- a/quic/core/http/quic_spdy_client_session_test.cc +++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -11,9 +11,12 @@ #include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h" #include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" +#include "net/third_party/quiche/src/quic/core/http/http_frames.h" #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h" #include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" +#include "net/third_party/quiche/src/quic/core/quic_versions.h" +#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" @@ -27,6 +30,7 @@ #include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" +#include "net/third_party/quiche/src/quic/test_tools/simple_session_cache.h" #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h" #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" @@ -81,11 +85,14 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> { protected: QuicSpdyClientSessionTest() - : crypto_config_(crypto_test_utils::ProofVerifierForTesting()), - promised_stream_id_( + : promised_stream_id_( QuicUtils::GetInvalidStreamId(GetParam().transport_version)), associated_stream_id_( QuicUtils::GetInvalidStreamId(GetParam().transport_version)) { + auto client_cache = std::make_unique<test::SimpleSessionCache>(); + client_session_cache_ = client_cache.get(); + crypto_config_ = std::make_unique<QuicCryptoClientConfig>( + crypto_test_utils::ProofVerifierForTesting(), std::move(client_cache)); Initialize(); // Advance the time, because timers do not like uninitialized times. connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); @@ -103,7 +110,7 @@ SupportedVersions(GetParam())); session_ = std::make_unique<TestQuicSpdyClientSession>( DefaultQuicConfig(), SupportedVersions(GetParam()), connection_, - QuicServerId(kServerHostname, kPort, false), &crypto_config_, + QuicServerId(kServerHostname, kPort, false), crypto_config_.get(), &push_promise_index_); session_->Initialize(); push_promise_[":path"] = "/bar"; @@ -171,7 +178,7 @@ stream, AlpnForVersion(connection_->version())); } - QuicCryptoClientConfig crypto_config_; + std::unique_ptr<QuicCryptoClientConfig> crypto_config_; MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; PacketSavingConnection* connection_; @@ -181,6 +188,7 @@ std::string promise_url_; QuicStreamId promised_stream_id_; QuicStreamId associated_stream_id_; + test::SimpleSessionCache* client_session_cache_; }; INSTANTIATE_TEST_SUITE_P(Tests, @@ -940,6 +948,43 @@ } } +// Test that upon receiving HTTP/3 SETTINGS, the settings are serialized and +// stored into client session cache. +TEST_P(QuicSpdyClientSessionTest, OnSettingsFrame) { + // This feature is HTTP/3 only + if (!VersionUsesHttp3(session_->transport_version())) { + return; + } + CompleteCryptoHandshake(); + SettingsFrame settings; + settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 2; + settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5; + settings.values[256] = 4; // unknown setting + char application_state[] = {// type (SETTINGS) + 0x04, + // length + 0x07, + // identifier (SETTINGS_QPACK_MAX_TABLE_CAPACITY) + 0x01, + // content + 0x02, + // identifier (SETTINGS_MAX_HEADER_LIST_SIZE) + 0x06, + // content + 0x05, + // identifier (256 in variable length integer) + 0x40 + 0x01, 0x00, + // content + 0x04}; + ApplicationState expected(std::begin(application_state), + std::end(application_state)); + session_->OnSettingsFrame(settings); + EXPECT_EQ(expected, + *client_session_cache_ + ->Lookup(QuicServerId(kServerHostname, kPort, false), nullptr) + ->application_state); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index f6dd0a7..2ab8637 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -873,6 +873,7 @@ } void QuicSpdySession::OnSettingsFrame(const SettingsFrame& frame) { + DCHECK(VersionUsesHttp3(transport_version())); if (debug_visitor_ != nullptr) { debug_visitor_->OnSettingsFrameReceived(frame); }
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h index 29eca32..d641d51 100644 --- a/quic/core/http/quic_spdy_session.h +++ b/quic/core/http/quic_spdy_session.h
@@ -247,7 +247,7 @@ bool server_push_enabled() const; // Called when the control stream receives HTTP/3 SETTINGS. - void OnSettingsFrame(const SettingsFrame& frame); + virtual void OnSettingsFrame(const SettingsFrame& frame); // Called when a setting is parsed from an incoming SETTINGS frame. void OnSetting(uint64_t id, uint64_t value);
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc index baac324..9e9e214 100644 --- a/quic/core/tls_client_handshaker.cc +++ b/quic/core/tls_client_handshaker.cc
@@ -520,6 +520,11 @@ void TlsClientHandshaker::OnApplicationState( std::unique_ptr<ApplicationState> application_state) { received_application_state_ = std::move(application_state); + if (session_cache_ != nullptr) { + // TODO(renjietang): cache the TLS session ticket and insert them together. + session_cache_->Insert(server_id_, nullptr, nullptr, + received_application_state_.get()); + } } } // namespace quic
diff --git a/quic/test_tools/simple_session_cache.cc b/quic/test_tools/simple_session_cache.cc index 32f8436..bbb5f28 100644 --- a/quic/test_tools/simple_session_cache.cc +++ b/quic/test_tools/simple_session_cache.cc
@@ -11,11 +11,22 @@ void SimpleSessionCache::Insert(const QuicServerId& server_id, bssl::UniquePtr<SSL_SESSION> session, - TransportParameters* /*params*/, - std::vector<uint8_t>* /*application_states*/) { - auto state = std::make_unique<QuicResumptionState>(); - state->tls_session = std::move(session); - cache_entries_.insert(std::make_pair(server_id, std::move(state))); + TransportParameters* params, + ApplicationState* application_state) { + auto it = cache_entries_.find(server_id); + if (it == cache_entries_.end()) { + it = cache_entries_.insert(std::make_pair(server_id, Entry())).first; + } + if (session != nullptr) { + it->second.session = std::move(session); + } + if (application_state != nullptr) { + it->second.application_state = + std::make_unique<ApplicationState>(*application_state); + } + if (params != nullptr) { + it->second.params = std::make_unique<TransportParameters>(*params); + } } std::unique_ptr<QuicResumptionState> SimpleSessionCache::Lookup( @@ -25,8 +36,10 @@ if (it == cache_entries_.end()) { return nullptr; } - std::unique_ptr<QuicResumptionState> state = std::move(it->second); - cache_entries_.erase(it); + auto state = std::make_unique<QuicResumptionState>(); + state->tls_session = std::move(it->second.session); + state->application_state = it->second.application_state.get(); + state->transport_params = it->second.params.get(); return state; }
diff --git a/quic/test_tools/simple_session_cache.h b/quic/test_tools/simple_session_cache.h index 62dbd6f..0bb23e0 100644 --- a/quic/test_tools/simple_session_cache.h +++ b/quic/test_tools/simple_session_cache.h
@@ -5,7 +5,9 @@ #ifndef QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_CACHE_H_ #define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_CACHE_H_ +#include <memory> #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" +#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h" namespace quic { namespace test { @@ -23,12 +25,17 @@ void Insert(const QuicServerId& server_id, bssl::UniquePtr<SSL_SESSION> session, TransportParameters* params, - std::vector<uint8_t>* application_states) override; + ApplicationState* application_state) override; std::unique_ptr<QuicResumptionState> Lookup(const QuicServerId& server_id, const SSL_CTX* ctx) override; private: - std::map<QuicServerId, std::unique_ptr<QuicResumptionState>> cache_entries_; + struct Entry { + bssl::UniquePtr<SSL_SESSION> session; + std::unique_ptr<TransportParameters> params; + std::unique_ptr<ApplicationState> application_state; + }; + std::map<QuicServerId, Entry> cache_entries_; }; } // namespace test