In TlsHandshaker::AdvanceHandshake, retry SSL_do_handshake once if it "succeeded" when entering early data.

Protected by FLAGS_quic_reloadable_flag_quic_tls_retry_handshake_on_early_data.

PiperOrigin-RevId: 371358037
Change-Id: I8bc9d39d4f455e5d01bea392c27e9423bf552a1f
diff --git a/quic/core/tls_handshaker.h b/quic/core/tls_handshaker.h
index 0b9c7f6..0b5ddc3 100644
--- a/quic/core/tls_handshaker.h
+++ b/quic/core/tls_handshaker.h
@@ -74,8 +74,20 @@
   // finished. Note that due to 0-RTT, the handshake may "finish" twice;
   // |SSL_in_early_data| can be used to determine whether the handshake is truly
   // done.
+  // TODO(wub): When --quic_tls_retry_handshake_on_early_data is true, this
+  // function will only be called once when the handshake actually finishes.
+  // Update comment when deprecating the flag.
   virtual void FinishHandshake() = 0;
 
+  // Called when |SSL_do_handshake| returns 1 and the connection is in early
+  // data. In that case, |AdvanceHandshake| will call |OnEnterEarlyData| and
+  // retry |SSL_do_handshake| once.
+  virtual void OnEnterEarlyData() {
+    // By default, do nothing but check the preconditions.
+    QUICHE_DCHECK(retry_handshake_on_early_data_);
+    QUICHE_DCHECK(SSL_in_early_data(ssl()));
+  }
+
   // Called when a handshake message is received after the handshake is
   // complete.
   virtual void ProcessPostHandshakeMessage() = 0;
@@ -159,6 +171,9 @@
   const bool add_packet_flusher_on_async_op_done_ =
       GetQuicReloadableFlag(quic_add_packet_flusher_on_async_op_done);
 
+  const bool retry_handshake_on_early_data_ =
+      GetQuicReloadableFlag(quic_tls_retry_handshake_on_early_data);
+
  private:
   // ProofVerifierCallbackImpl handles the result of an asynchronous certificate
   // verification operation.