Add HttpDecoder::IsBufferedFrame().
This will allow clearer state transitions in an upcoming CL.
PiperOrigin-RevId: 386285509
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index 5a07c3f..cc253be 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -228,6 +228,10 @@
}
if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
+ // MaxFrameLength() returns numeric_limits::max()
+ // if IsFrameBuffered() is false.
+ QUICHE_DCHECK(IsFrameBuffered());
+
RaiseError(QUIC_HTTP_FRAME_TOO_LARGE, "Frame is too large.");
return false;
}
@@ -278,6 +282,24 @@
return continue_processing;
}
+bool HttpDecoder::IsFrameBuffered() {
+ switch (current_frame_type_) {
+ case static_cast<uint64_t>(HttpFrameType::SETTINGS):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::GOAWAY):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::ACCEPT_CH):
+ return true;
+ }
+
+ // Other defined frame types as well as unknown frames are not buffered.
+ return false;
+}
+
bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
QUICHE_DCHECK_NE(0u, reader->BytesRemaining());
QUICHE_DCHECK_NE(0u, remaining_frame_length_);
@@ -341,6 +363,17 @@
}
}
+ if (IsFrameBuffered()) {
+ if (state_ != STATE_READING_FRAME_PAYLOAD) {
+ // BufferOrParsePayload() has advanced |state_|.
+ // TODO(bnc): Simplify state transitions.
+ QUICHE_DCHECK_EQ(STATE_READING_FRAME_TYPE, state_);
+ QUICHE_DCHECK_EQ(0u, remaining_frame_length_);
+ }
+ } else {
+ QUICHE_DCHECK(state_ == STATE_READING_FRAME_PAYLOAD);
+ }
+
// BufferOrParsePayload() may have advanced |state_|.
if (state_ == STATE_READING_FRAME_PAYLOAD && remaining_frame_length_ == 0) {
state_ = STATE_FINISH_PARSING;
@@ -423,6 +456,7 @@
}
bool HttpDecoder::BufferOrParsePayload(QuicDataReader* reader) {
+ QUICHE_DCHECK(IsFrameBuffered());
QUICHE_DCHECK_EQ(current_frame_length_,
buffer_.size() + remaining_frame_length_);
@@ -468,6 +502,7 @@
}
bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) {
+ QUICHE_DCHECK(IsFrameBuffered());
QUICHE_DCHECK_EQ(current_frame_length_, reader->BytesRemaining());
QUICHE_DCHECK_EQ(0u, remaining_frame_length_);
diff --git a/quic/core/http/http_decoder.h b/quic/core/http/http_decoder.h
index 3743788..002ff68 100644
--- a/quic/core/http/http_decoder.h
+++ b/quic/core/http/http_decoder.h
@@ -171,16 +171,23 @@
// if there are any errors. Returns whether processing should continue.
bool ReadFrameLength(QuicDataReader* reader);
- // Depending on the frame type, reads and processes the payload of the current
- // frame from |reader| and calls visitor methods, or calls
- // BufferOrParsePayload(). Returns whether processing should continue.
+ // Returns whether the current frame is of a buffered type.
+ // The payload of buffered frames is buffered by HttpDecoder, and parsed by
+ // HttpDecoder after the entire frame has been received. (Copying to the
+ // buffer is skipped if the ProcessInput() call covers the entire payload.)
+ // Frames that are not buffered have every payload fragment synchronously
+ // passed to the Visitor without buffering.
+ bool IsFrameBuffered();
+
+ // For buffered frame types, calls BufferOrParsePayload(). For other frame
+ // types, reads the payload of the current frame from |reader| and calls
+ // visitor methods. Returns whether processing should continue.
bool ReadFramePayload(QuicDataReader* reader);
- // For frame types parsed by BufferOrParsePayload(), this method is only
- // called if frame payload is empty, at it calls BufferOrParsePayload(). For
- // other frame types, this method directly calls visitor methods to signal
- // that frame had been parsed completely. Returns whether processing should
- // continue.
+ // For buffered frame types, this method is only called if frame payload is
+ // empty, and it calls BufferOrParsePayload(). For other frame types, this
+ // method directly calls visitor methods to signal that frame had been
+ // received completely. Returns whether processing should continue.
bool FinishParsing(QuicDataReader* reader);
// Read payload of unknown frame from |reader| and call
@@ -190,13 +197,15 @@
// Buffers any remaining frame payload from |*reader| into |buffer_| if
// necessary. Parses the frame payload if complete. Parses out of |*reader|
- // without unnecessary copy if |*reader| has entire payload.
+ // without unnecessary copy if |*reader| contains entire payload.
// Returns whether processing should continue.
+ // Must only be called when current frame type is buffered.
bool BufferOrParsePayload(QuicDataReader* reader);
// Parses the entire payload of certain kinds of frames that are parsed in a
// single pass. |reader| must have at least |current_frame_length_| bytes.
// Returns whether processing should continue.
+ // Must only be called when current frame type is buffered.
bool ParseEntirePayload(QuicDataReader* reader);
// Buffers any remaining frame length field from |reader| into