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