Fix a bug in WriteGfeMemSliceSpanToStream().

The bug was that WriteGfeMemSliceSpanToStream() did not account for the fact that the DATA frame header is written by a separate write that could cause the stream to become write-blocked.

I manually verified this fixes test flakes described in b/191017151.

Protected by FLAGS_quic_restart_flag_quic_use_new_mem_slice_span2.

PiperOrigin-RevId: 379315449
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc
index 1e4b469..25f6200 100644
--- a/quic/core/http/http_encoder.cc
+++ b/quic/core/http/http_encoder.cc
@@ -34,13 +34,20 @@
 }  // namespace
 
 // static
+QuicByteCount HttpEncoder::GetDataFrameHeaderLength(
+    QuicByteCount payload_length) {
+  QUICHE_DCHECK_NE(0u, payload_length);
+  return QuicDataWriter::GetVarInt62Len(payload_length) +
+         QuicDataWriter::GetVarInt62Len(
+             static_cast<uint64_t>(HttpFrameType::DATA));
+}
+
+// static
 QuicBuffer HttpEncoder::SerializeDataFrameHeader(
     QuicByteCount payload_length,
     QuicBufferAllocator* allocator) {
   QUICHE_DCHECK_NE(0u, payload_length);
-  QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(payload_length) +
-                                QuicDataWriter::GetVarInt62Len(
-                                    static_cast<uint64_t>(HttpFrameType::DATA));
+  QuicByteCount header_length = GetDataFrameHeaderLength(payload_length);
 
   QuicBuffer header(allocator, header_length);
   QuicDataWriter writer(header.size(), header.data());
diff --git a/quic/core/http/http_encoder.h b/quic/core/http/http_encoder.h
index dc48bb0..585e739 100644
--- a/quic/core/http/http_encoder.h
+++ b/quic/core/http/http_encoder.h
@@ -22,6 +22,9 @@
  public:
   HttpEncoder() = delete;
 
+  // Returns the length of the header for a DATA frame.
+  static QuicByteCount GetDataFrameHeaderLength(QuicByteCount payload_length);
+
   // Serializes a DATA frame header into a QuicBuffer; returns said QuicBuffer
   // on success, empty buffer otherwise.
   static QuicBuffer SerializeDataFrameHeader(QuicByteCount payload_length,
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index 0c08938..e797dee 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -1250,6 +1250,16 @@
   return encoded_headers.size();
 }
 
+bool QuicSpdyStream::CanWriteNewBodyData(QuicByteCount write_size) const {
+  QUICHE_DCHECK_NE(0u, write_size);
+  if (!VersionUsesHttp3(transport_version())) {
+    return CanWriteNewData();
+  }
+
+  return CanWriteNewDataAfterData(
+      HttpEncoder::GetDataFrameHeaderLength(write_size));
+}
+
 void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() {
   if (!spdy_session_->SupportsWebTransport()) {
     return;
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h
index 4f962ce..74ae070 100644
--- a/quic/core/http/quic_spdy_stream.h
+++ b/quic/core/http/quic_spdy_stream.h
@@ -247,6 +247,10 @@
   // error, and returns false.
   bool AssertNotWebTransportDataStream(absl::string_view operation);
 
+  // Indicates whether a call to WriteBodySlices will be successful and not
+  // rejected due to buffer being full.  |write_size| must be non-zero.
+  bool CanWriteNewBodyData(QuicByteCount write_size) const;
+
  protected:
   // Called when the received headers are too large. By default this will
   // reset the stream.