Internal change

PiperOrigin-RevId: 429370483
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 3deafcc..0702707 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -429,6 +429,7 @@
 const QuicTag kSRWP = TAG('S', 'R', 'W', 'P');   // Enable retransmittable on
                                                  // wire PING (ROWP) on the
                                                  // server side.
+const QuicTag kGSR0 = TAG('G', 'S', 'R', '0');   // Selective Resumption
 
 // Client Hints triggers.
 const QuicTag kGWCH = TAG('G', 'W', 'C', 'H');
diff --git a/quic/core/crypto/tls_connection.cc b/quic/core/crypto/tls_connection.cc
index 901ae66..e534f7d 100644
--- a/quic/core/crypto/tls_connection.cc
+++ b/quic/core/crypto/tls_connection.cc
@@ -120,6 +120,11 @@
       });
 }
 
+void TlsConnection::DisableTicketSupport() {
+  ssl_config_.disable_ticket_support = true;
+  SSL_set_options(ssl(), SSL_OP_NO_TICKET);
+}
+
 // static
 bssl::UniquePtr<SSL_CTX> TlsConnection::CreateSslCtx() {
   CRYPTO_library_init();
diff --git a/quic/core/crypto/tls_connection.h b/quic/core/crypto/tls_connection.h
index a7a869a..5e80185 100644
--- a/quic/core/crypto/tls_connection.h
+++ b/quic/core/crypto/tls_connection.h
@@ -90,6 +90,11 @@
   // Configure the SSL such that delegate_->InfoCallback will be called.
   void EnableInfoCallback();
 
+  // Configure the SSL to disable session ticket support. Note that, this
+  // function simply sets the |SSL_OP_NO_TICKET| option on the SSL object, it
+  // does not check whether it is too late to do so.
+  void DisableTicketSupport();
+
   // Functions to convert between BoringSSL's enum ssl_encryption_level_t and
   // QUIC's EncryptionLevel.
   static EncryptionLevel QuicEncryptionLevel(enum ssl_encryption_level_t level);
diff --git a/quic/core/http/quic_server_session_base.h b/quic/core/http/quic_server_session_base.h
index 5903de6..e6afc19 100644
--- a/quic/core/http/quic_server_session_base.h
+++ b/quic/core/http/quic_server_session_base.h
@@ -68,6 +68,8 @@
     serving_region_ = serving_region;
   }
 
+  const std::string& serving_region() const { return serving_region_; }
+
   QuicSSLConfig GetSSLConfig() const override;
 
  protected:
diff --git a/quic/core/quic_crypto_server_stream.cc b/quic/core/quic_crypto_server_stream.cc
index 55b7bf1..1f8b026 100644
--- a/quic/core/quic_crypto_server_stream.cc
+++ b/quic/core/quic_crypto_server_stream.cc
@@ -309,6 +309,11 @@
   ++num_server_config_update_messages_sent_;
 }
 
+bool QuicCryptoServerStream::DisableResumption() {
+  QUICHE_DCHECK(false) << "Not supported for QUIC crypto.";
+  return false;
+}
+
 bool QuicCryptoServerStream::IsZeroRtt() const {
   return num_handshake_messages_ == 1 &&
          num_handshake_messages_with_server_nonces_ == 0;
@@ -332,6 +337,11 @@
   return zero_rtt_attempted_;
 }
 
+bool QuicCryptoServerStream::EarlyDataAttempted() const {
+  QUICHE_DCHECK(false) << "Not supported for QUIC crypto.";
+  return zero_rtt_attempted_;
+}
+
 void QuicCryptoServerStream::SetPreviousCachedNetworkParams(
     CachedNetworkParameters cached_network_params) {
   previous_cached_network_params_.reset(
diff --git a/quic/core/quic_crypto_server_stream.h b/quic/core/quic_crypto_server_stream.h
index aca9e9a..05f68e6 100644
--- a/quic/core/quic_crypto_server_stream.h
+++ b/quic/core/quic_crypto_server_stream.h
@@ -34,9 +34,11 @@
   bool GetBase64SHA256ClientChannelID(std::string* output) const override;
   void SendServerConfigUpdate(
       const CachedNetworkParameters* cached_network_params) override;
+  bool DisableResumption() override;
   bool IsZeroRtt() const override;
   bool IsResumption() const override;
   bool ResumptionAttempted() const override;
+  bool EarlyDataAttempted() const override;
   int NumServerConfigUpdateMessagesSent() const override;
   const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
   void SetPreviousCachedNetworkParams(
diff --git a/quic/core/quic_crypto_server_stream_base.h b/quic/core/quic_crypto_server_stream_base.h
index 0a2a63e..dcefdfb 100644
--- a/quic/core/quic_crypto_server_stream_base.h
+++ b/quic/core/quic_crypto_server_stream_base.h
@@ -62,6 +62,11 @@
   virtual void SendServerConfigUpdate(
       const CachedNetworkParameters* cached_network_params) = 0;
 
+  // Disables TLS resumption, should be called as early as possible.
+  // Return true if resumption is disabled.
+  // Return false if nothing happened, typically it means it is called too late.
+  virtual bool DisableResumption() = 0;
+
   // Returns true if the connection was a successful 0-RTT resumption.
   virtual bool IsZeroRtt() const = 0;
 
@@ -73,6 +78,10 @@
   // the resumption actually occurred.
   virtual bool ResumptionAttempted() const = 0;
 
+  // Returns true if the client attempted to use early data, as indicated by the
+  // "early_data" TLS extension. TLS only.
+  virtual bool EarlyDataAttempted() const = 0;
+
   // NOTE: Indicating that the Expect-CT header should be sent here presents
   // a layering violation to some extent. The Expect-CT header only applies to
   // HTTP connections, while this class can be used for non-HTTP applications.
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index a16e729..dc4b39a 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -278,6 +278,14 @@
   // SCUP messages aren't supported when using the TLS handshake.
 }
 
+bool TlsServerHandshaker::DisableResumption() {
+  if (!can_disable_resumption_ || !session()->connection()->connected()) {
+    return false;
+  }
+  tls_connection_.DisableTicketSupport();
+  return true;
+}
+
 bool TlsServerHandshaker::IsZeroRtt() const {
   return SSL_early_data_accepted(ssl());
 }
@@ -290,6 +298,14 @@
   return ticket_received_;
 }
 
+bool TlsServerHandshaker::EarlyDataAttempted() const {
+  QUIC_BUG_IF(quic_tls_early_data_attempted_too_early,
+              !select_cert_status_.has_value())
+      << "EarlyDataAttempted must be called after EarlySelectCertCallback is "
+         "started";
+  return early_data_attempted_;
+}
+
 int TlsServerHandshaker::NumServerConfigUpdateMessagesSent() const {
   // SCUP messages aren't supported when using the TLS handshake.
   return 0;
@@ -881,6 +897,10 @@
     ticket_received_ = SSL_early_callback_ctx_extension_get(
         client_hello, TLSEXT_TYPE_pre_shared_key, &unused_extension_bytes,
         &unused_extension_len);
+
+    early_data_attempted_ = SSL_early_callback_ctx_extension_get(
+        client_hello, TLSEXT_TYPE_early_data, &unused_extension_bytes,
+        &unused_extension_len);
   }
 
   // This callback is called very early by Boring SSL, most of the SSL_get_foo
@@ -950,6 +970,7 @@
     return ssl_select_cert_error;
   }
 
+  can_disable_resumption_ = false;
   const QuicAsyncStatus status = proof_source_handle_->SelectCertificate(
       session()->connection()->self_address().Normalized(),
       session()->connection()->peer_address().Normalized(),
diff --git a/quic/core/tls_server_handshaker.h b/quic/core/tls_server_handshaker.h
index d2f37b0..c2ea44b 100644
--- a/quic/core/tls_server_handshaker.h
+++ b/quic/core/tls_server_handshaker.h
@@ -45,9 +45,12 @@
   bool GetBase64SHA256ClientChannelID(std::string* output) const override;
   void SendServerConfigUpdate(
       const CachedNetworkParameters* cached_network_params) override;
+  bool DisableResumption() override;
   bool IsZeroRtt() const override;
   bool IsResumption() const override;
   bool ResumptionAttempted() const override;
+  // Must be called after EarlySelectCertCallback is started.
+  bool EarlyDataAttempted() const override;
   int NumServerConfigUpdateMessagesSent() const override;
   const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
   void SetPreviousCachedNetworkParams(
@@ -344,6 +347,9 @@
   // indicates that the client attempted a resumption.
   bool ticket_received_ = false;
 
+  // True if the "early_data" extension is in the client hello.
+  bool early_data_attempted_ = false;
+
   // Force SessionTicketOpen to return ssl_ticket_aead_ignore_ticket if called.
   bool ignore_ticket_open_ = false;
 
@@ -367,6 +373,7 @@
   HandshakeState state_ = HANDSHAKE_START;
   bool encryption_established_ = false;
   bool valid_alpn_received_ = false;
+  bool can_disable_resumption_ = true;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
       crypto_negotiated_params_;
   TlsServerConnection tls_connection_;