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