Add explicit signal of coalscing done to QuicConnection.

Protected by FLAGS_quic_reloadable_flag_quic_fix_out_of_order_sending2.

PiperOrigin-RevId: 333530471
Change-Id: I23318531bae11486f7ccab1e8187293e8ad14cd4
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index c834d7b..50b7904 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -200,7 +200,7 @@
     AddToCache("/bar", 200, kBarResponseBody);
     // Enable fixes for bugs found in tests and prod.
     SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
-    SetQuicReloadableFlag(quic_fix_out_of_order_sending, true);
+    SetQuicReloadableFlag(quic_fix_out_of_order_sending2, true);
   }
 
   ~EndToEndTest() override { QuicRecyclePort(server_address_.port()); }
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index bb7dd47..876e997 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -2717,6 +2717,7 @@
       return true;
     case COALESCE:
       QUIC_BUG_IF(!version().CanSendCoalescedPackets());
+      QUIC_BUG_IF(fix_out_of_order_sending_ && coalescing_done_);
       if (!coalesced_packet_.MaybeCoalescePacket(
               *packet, self_address(), send_to_address,
               helper_->GetStreamSendBufferAllocator(),
@@ -2764,6 +2765,10 @@
       buffered_packets_.emplace_back(*packet, self_address(), send_to_address);
       break;
     case SEND_TO_WRITER:
+      if (fix_out_of_order_sending_ && !coalescing_done_) {
+        // Stop using coalsecer from now on.
+        coalescing_done_ = true;
+      }
       // At this point, packet->release_encrypted_buffer is either nullptr,
       // meaning |packet->encrypted_buffer| is a stack buffer, or not-nullptr,
       /// meaning it's a writer-allocated buffer. Note that connectivity probing
@@ -3097,7 +3102,14 @@
 }
 
 QuicPacketBuffer QuicConnection::GetPacketBuffer() {
-  if (version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
+  if (fix_out_of_order_sending_) {
+    if (version().CanSendCoalescedPackets() && !coalescing_done_) {
+      // Do not use writer's packet buffer for coalesced packets which may
+      // contain
+      // multiple QUIC packets.
+      return {nullptr, nullptr};
+    }
+  } else if (version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
     // Do not use writer's packet buffer for coalesced packets which may contain
     // multiple QUIC packets.
     return {nullptr, nullptr};
@@ -4806,14 +4818,15 @@
     DCHECK(!is_mtu_discovery);
     return LEGACY_VERSION_ENCAPSULATE;
   }
-  if (version().CanSendCoalescedPackets() && !is_mtu_discovery) {
+  if (version().CanSendCoalescedPackets() && !coalescing_done_ &&
+      !is_mtu_discovery) {
     if (!IsHandshakeConfirmed()) {
       // Before receiving ACK for any 1-RTT packets, always try to coalesce
       // packet (except MTU discovery packet).
       return COALESCE;
     }
-    if (GetQuicReloadableFlag(quic_fix_out_of_order_sending)) {
-      QUIC_RELOADABLE_FLAG_COUNT(quic_fix_out_of_order_sending);
+    if (fix_out_of_order_sending_) {
+      QUIC_RELOADABLE_FLAG_COUNT(quic_fix_out_of_order_sending2);
       if (coalesced_packet_.length() > 0) {
         // If the coalescer is not empty, let this packet go through coalescer
         // to avoid potential out of order sending.
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 994a8df..3eec673 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -1783,8 +1783,14 @@
   // True if AckFrequencyFrame is supported.
   bool can_receive_ack_frequency_frame_ = false;
 
+  // Indicate whether coalescing is done.
+  bool coalescing_done_ = false;
+
   const bool fix_missing_initial_keys_ =
       GetQuicReloadableFlag(quic_fix_missing_initial_keys);
+
+  const bool fix_out_of_order_sending_ =
+      GetQuicReloadableFlag(quic_fix_out_of_order_sending2);
 };
 
 }  // namespace quic