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;