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.