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