Internal QUICHE change

PiperOrigin-RevId: 368856207
Change-Id: Ifce2e70ab38d3cfc7e52de2f07a4571abcb0e404
diff --git a/quic/core/handshaker_delegate_interface.h b/quic/core/handshaker_delegate_interface.h
index ae291b7..1e47d16 100644
--- a/quic/core/handshaker_delegate_interface.h
+++ b/quic/core/handshaker_delegate_interface.h
@@ -74,6 +74,9 @@
 
   // Called at the end of an handshake operation callback.
   virtual void OnHandshakeCallbackDone() = 0;
+
+  // Whether a packet flusher is currently attached.
+  virtual bool PacketFlusherAttached() const = 0;
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 099043c..6362f9a 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -7,6 +7,7 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_reset, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_accept_empty_stream_frame_with_no_fin, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ack_delay_alarm_granularity, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_packet_flusher_on_async_op_done, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allocate_stream_sequencer_buffer_blocks_on_demand, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, false)
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 52eaf57..871e326 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -1775,6 +1775,11 @@
   }
 }
 
+bool QuicSession::PacketFlusherAttached() const {
+  QUICHE_DCHECK(connection_->connected());
+  return connection()->packet_creator().PacketFlusherAttached();
+}
+
 void QuicSession::OnCryptoHandshakeMessageSent(
     const CryptoHandshakeMessage& /*message*/) {}
 
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index cc1d6eb..40f2d18 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -302,6 +302,7 @@
                                            bool is_resumption,
                                            std::string* error_details) override;
   void OnHandshakeCallbackDone() override;
+  bool PacketFlusherAttached() const override;
 
   // Implement StreamDelegateInterface.
   void OnStreamError(QuicErrorCode error_code,
diff --git a/quic/core/tls_handshaker.cc b/quic/core/tls_handshaker.cc
index 56110c7..cbc1998 100644
--- a/quic/core/tls_handshaker.cc
+++ b/quic/core/tls_handshaker.cc
@@ -93,6 +93,13 @@
     return;
   }
 
+  QUICHE_BUG_IF(quic_tls_server_async_done_no_flusher,
+                SSL_is_server(ssl()) && add_packet_flusher_on_async_op_done_ &&
+                    !handshaker_delegate_->PacketFlusherAttached())
+      << "is_server:" << SSL_is_server(ssl())
+      << ", add_packet_flusher_on_async_op_done_:"
+      << add_packet_flusher_on_async_op_done_;
+
   QUIC_VLOG(1) << "TlsHandshaker: continuing handshake";
   int rv = SSL_do_handshake(ssl());
   if (rv == 1) {
diff --git a/quic/core/tls_handshaker.h b/quic/core/tls_handshaker.h
index 4f8bf47..0b9c7f6 100644
--- a/quic/core/tls_handshaker.h
+++ b/quic/core/tls_handshaker.h
@@ -16,6 +16,7 @@
 #include "quic/core/crypto/tls_connection.h"
 #include "quic/core/quic_session.h"
 #include "quic/platform/api/quic_export.h"
+#include "quic/platform/api/quic_flags.h"
 
 namespace quic {
 
@@ -155,6 +156,9 @@
   // error code corresponding to the TLS alert description |desc|.
   void SendAlert(EncryptionLevel level, uint8_t desc) override;
 
+  const bool add_packet_flusher_on_async_op_done_ =
+      GetQuicReloadableFlag(quic_add_packet_flusher_on_async_op_done);
+
  private:
   // ProofVerifierCallbackImpl handles the result of an asynchronous certificate
   // verification operation.
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index cc536e7..fd9cc55 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -384,6 +384,19 @@
 void TlsServerHandshaker::OverrideQuicConfigDefaults(QuicConfig* /*config*/) {}
 
 void TlsServerHandshaker::AdvanceHandshakeFromCallback() {
+  std::unique_ptr<QuicConnection::ScopedPacketFlusher> flusher;
+  if (add_packet_flusher_on_async_op_done_) {
+    if (session()->PacketFlusherAttached()) {
+      QUIC_RELOADABLE_FLAG_COUNT_N(quic_add_packet_flusher_on_async_op_done, 1,
+                                   2);
+    } else {
+      QUIC_RELOADABLE_FLAG_COUNT_N(quic_add_packet_flusher_on_async_op_done, 2,
+                                   2);
+    }
+    flusher = std::make_unique<QuicConnection::ScopedPacketFlusher>(
+        session()->connection());
+  }
+
   AdvanceHandshake();
   if (!is_connection_closed()) {
     handshaker_delegate()->OnHandshakeCallbackDone();
diff --git a/quic/core/tls_server_handshaker_test.cc b/quic/core/tls_server_handshaker_test.cc
index fbec255..2c7d415 100644
--- a/quic/core/tls_server_handshaker_test.cc
+++ b/quic/core/tls_server_handshaker_test.cc
@@ -601,6 +601,15 @@
       1,        // HandshakeType client_hello
       0, 0, 0,  // uint24 length
   };
+
+  // Install a packet flusher such that the packets generated by
+  // |server_connection_| in response to this handshake message are more likely
+  // to be coalesced and/or batched in the writer.
+  //
+  // This is required by TlsServerHandshaker because without the flusher, it
+  // tends to generate many small, uncoalesced packets, one per
+  // TlsHandshaker::WriteMessage.
+  QuicConnection::ScopedPacketFlusher flusher(server_connection_);
   server_stream()->crypto_message_parser()->ProcessInput(
       absl::string_view(bogus_handshake_message,
                         ABSL_ARRAYSIZE(bogus_handshake_message)),