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.