Set up session config from 0-rtt transport parameters.
Protected by gfe2_reloadable_flag_quic_zero_rtt
PiperOrigin-RevId: 310435641
Change-Id: Ib9dd3e4563b2a53729b3a75554479b8f80538357
diff --git a/quic/core/crypto/tls_server_connection.cc b/quic/core/crypto/tls_server_connection.cc
index 7e5b366..54db545 100644
--- a/quic/core/crypto/tls_server_connection.cc
+++ b/quic/core/crypto/tls_server_connection.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
@@ -27,6 +28,9 @@
proof_source->GetTicketCrypter()) {
SSL_CTX_set_ticket_aead_method(ssl_ctx.get(),
&TlsServerConnection::kSessionTicketMethod);
+ if (GetQuicReloadableFlag(quic_enable_zero_rtt_for_tls)) {
+ SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
+ }
} else {
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_NO_TICKET);
}
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc
index 71604e6..45e90ad 100644
--- a/quic/core/http/quic_spdy_client_session_test.cc
+++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -11,9 +11,11 @@
#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_constants.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_constants.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"
@@ -170,6 +172,7 @@
config.SetMaxBidirectionalStreamsToSend(server_max_incoming_streams);
}
SetQuicReloadableFlag(quic_enable_tls_resumption, true);
+ SetQuicReloadableFlag(quic_enable_zero_rtt_for_tls, true);
std::unique_ptr<QuicCryptoServerConfig> crypto_config =
crypto_test_utils::CryptoServerConfigForTesting();
crypto_test_utils::HandshakeWithFakeServer(
@@ -177,6 +180,19 @@
stream, AlpnForVersion(connection_->version()));
}
+ void CreateConnection() {
+ connection_ = new PacketSavingConnection(&helper_, &alarm_factory_,
+ Perspective::IS_CLIENT,
+ SupportedVersions(GetParam()));
+ // Advance the time, because timers do not like uninitialized times.
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ session_ = std::make_unique<TestQuicSpdyClientSession>(
+ DefaultQuicConfig(), SupportedVersions(GetParam()), connection_,
+ QuicServerId(kServerHostname, kPort, false), crypto_config_.get(),
+ &push_promise_index_);
+ session_->Initialize();
+ }
+
std::unique_ptr<QuicCryptoClientConfig> crypto_config_;
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
@@ -966,6 +982,67 @@
->application_state);
}
+TEST_P(QuicSpdyClientSessionTest, IetfZeroRttSetup) {
+ // This feature is HTTP/3 only
+ if (!VersionUsesHttp3(session_->transport_version())) {
+ return;
+ }
+ CompleteCryptoHandshake();
+ EXPECT_FALSE(session_->GetCryptoStream()->IsResumption());
+ SettingsFrame settings;
+ settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 2;
+ settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
+ settings.values[256] = 4; // unknown setting
+ session_->OnSettingsFrame(settings);
+
+ CreateConnection();
+ EXPECT_EQ(0u, session_->flow_controller()->send_window_offset());
+ session_->CryptoConnect();
+
+ // The client session should have a basic setup ready before the handshake
+ // succeeds.
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest,
+ session_->flow_controller()->send_window_offset());
+ auto* id_manager = QuicSessionPeer::v99_streamid_manager(session_.get());
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection,
+ id_manager->max_outgoing_bidirectional_streams());
+ EXPECT_EQ(
+ kDefaultMaxStreamsPerConnection + kHttp3StaticUnidirectionalStreamCount,
+ id_manager->max_outgoing_unidirectional_streams());
+ auto* control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_EQ(kInitialStreamFlowControlWindowForTest,
+ control_stream->flow_controller()->send_window_offset());
+
+ // Complete the handshake with a different config.
+ QuicCryptoClientStream* stream =
+ static_cast<QuicCryptoClientStream*>(session_->GetMutableCryptoStream());
+ QuicConfig config = DefaultQuicConfig();
+ config.SetInitialMaxStreamDataBytesUnidirectionalToSend(
+ kInitialStreamFlowControlWindowForTest + 1);
+ config.SetInitialSessionFlowControlWindowToSend(
+ kInitialSessionFlowControlWindowForTest + 1);
+ config.SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection + 1);
+ config.SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection + 1);
+ SetQuicReloadableFlag(quic_enable_tls_resumption, true);
+ std::unique_ptr<QuicCryptoServerConfig> crypto_config =
+ crypto_test_utils::CryptoServerConfigForTesting();
+ crypto_test_utils::HandshakeWithFakeServer(
+ &config, crypto_config.get(), &helper_, &alarm_factory_, connection_,
+ stream, AlpnForVersion(connection_->version()));
+
+ EXPECT_TRUE(session_->GetCryptoStream()->IsResumption());
+ EXPECT_EQ(kInitialSessionFlowControlWindowForTest + 1,
+ session_->flow_controller()->send_window_offset());
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection + 1,
+ id_manager->max_outgoing_bidirectional_streams());
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection +
+ kHttp3StaticUnidirectionalStreamCount + 1,
+ id_manager->max_outgoing_unidirectional_streams());
+ EXPECT_EQ(kInitialStreamFlowControlWindowForTest + 1,
+ control_stream->flow_controller()->send_window_offset());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc
index c638040..a6aee11 100644
--- a/quic/core/tls_client_handshaker.cc
+++ b/quic/core/tls_client_handshaker.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
@@ -118,6 +119,20 @@
session_cache_->Lookup(server_id_, SSL_get_SSL_CTX(ssl()));
if (cached_state) {
SSL_set_session(ssl(), cached_state->tls_session.get());
+ if (GetQuicReloadableFlag(quic_enable_zero_rtt_for_tls) &&
+ VersionHasIetfQuicFrames(session()->transport_version()) &&
+ SSL_SESSION_early_data_capable(cached_state->tls_session.get())) {
+ std::string error_details;
+ if (session()->config()->ProcessTransportParameters(
+ *(cached_state->transport_params), SERVER,
+ /*is_resumption = */ true, &error_details) != QUIC_NO_ERROR) {
+ QUIC_BUG << "Cached transport parameters failed to be parsed";
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ "Client failed to parse cached Transport Parameters");
+ return false;
+ }
+ session()->OnConfigNegotiated();
+ }
}
}
@@ -378,6 +393,7 @@
int ssl_error = SSL_get_error(ssl(), rv);
bool should_close = true;
switch (state_) {
+ // TODO(b/153726130): handle the case where the server rejects early data.
case STATE_HANDSHAKE_RUNNING:
should_close = ssl_error != SSL_ERROR_WANT_READ;
break;