1 // Copyright (c) 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_ 6 #define QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_ 7 8 #include <cstdint> 9 10 #include "absl/strings/string_view.h" 11 #include "quiche/quic/core/http/http_frames.h" 12 #include "quiche/quic/core/quic_error_codes.h" 13 #include "quiche/quic/core/quic_types.h" 14 #include "quiche/quic/platform/api/quic_export.h" 15 16 namespace quic { 17 18 namespace test { 19 20 class HttpDecoderPeer; 21 22 } // namespace test 23 24 class QuicDataReader; 25 26 // A class for decoding the HTTP frames that are exchanged in an HTTP over QUIC 27 // session. 28 class QUICHE_EXPORT HttpDecoder { 29 public: 30 class QUICHE_EXPORT Visitor { 31 public: ~Visitor()32 virtual ~Visitor() {} 33 34 // Called if an error is detected. 35 virtual void OnError(HttpDecoder* decoder) = 0; 36 37 // All the following methods return true to continue decoding, 38 // and false to pause it. 39 // On*FrameStart() methods are called after the frame header is completely 40 // processed. At that point it is safe to consume |header_length| bytes. 41 42 // Called when a MAX_PUSH_ID frame has been successfully parsed. 43 virtual bool OnMaxPushIdFrame() = 0; 44 45 // Called when a GOAWAY frame has been successfully parsed. 46 virtual bool OnGoAwayFrame(const GoAwayFrame& frame) = 0; 47 48 // Called when a SETTINGS frame has been received. 49 virtual bool OnSettingsFrameStart(QuicByteCount header_length) = 0; 50 51 // Called when a SETTINGS frame has been successfully parsed. 52 virtual bool OnSettingsFrame(const SettingsFrame& frame) = 0; 53 54 // Called when a DATA frame has been received. 55 // |header_length| and |payload_length| are the length of DATA frame header 56 // and payload, respectively. 57 virtual bool OnDataFrameStart(QuicByteCount header_length, 58 QuicByteCount payload_length) = 0; 59 // Called when part of the payload of a DATA frame has been read. May be 60 // called multiple times for a single frame. |payload| is guaranteed to be 61 // non-empty. 62 virtual bool OnDataFramePayload(absl::string_view payload) = 0; 63 // Called when a DATA frame has been completely processed. 64 virtual bool OnDataFrameEnd() = 0; 65 66 // Called when a HEADERS frame has been received. 67 // |header_length| and |payload_length| are the length of HEADERS frame 68 // header and payload, respectively. 69 virtual bool OnHeadersFrameStart(QuicByteCount header_length, 70 QuicByteCount payload_length) = 0; 71 // Called when part of the payload of a HEADERS frame has been read. May be 72 // called multiple times for a single frame. |payload| is guaranteed to be 73 // non-empty. 74 virtual bool OnHeadersFramePayload(absl::string_view payload) = 0; 75 // Called when a HEADERS frame has been completely processed. 76 virtual bool OnHeadersFrameEnd() = 0; 77 78 // Called when a PRIORITY_UPDATE frame has been received. 79 // |header_length| contains PRIORITY_UPDATE frame length and payload length. 80 virtual bool OnPriorityUpdateFrameStart(QuicByteCount header_length) = 0; 81 82 // Called when a PRIORITY_UPDATE frame has been successfully parsed. 83 virtual bool OnPriorityUpdateFrame(const PriorityUpdateFrame& frame) = 0; 84 85 // Called when an ACCEPT_CH frame has been received. 86 // |header_length| contains ACCEPT_CH frame length and payload length. 87 virtual bool OnAcceptChFrameStart(QuicByteCount header_length) = 0; 88 89 // Called when an ACCEPT_CH frame has been successfully parsed. 90 virtual bool OnAcceptChFrame(const AcceptChFrame& frame) = 0; 91 92 // Called when a WEBTRANSPORT_STREAM frame type and the session ID varint 93 // immediately following it has been received. Any further parsing should 94 // be done by the stream itself, and not the parser. Note that this does not 95 // return bool, because WEBTRANSPORT_STREAM always causes the parsing 96 // process to cease. 97 virtual void OnWebTransportStreamFrameType( 98 QuicByteCount header_length, WebTransportSessionId session_id) = 0; 99 100 // Called when a frame of unknown type |frame_type| has been received. 101 // Frame type might be reserved, Visitor must make sure to ignore. 102 // |header_length| and |payload_length| are the length of the frame header 103 // and payload, respectively. 104 virtual bool OnUnknownFrameStart(uint64_t frame_type, 105 QuicByteCount header_length, 106 QuicByteCount payload_length) = 0; 107 // Called when part of the payload of the unknown frame has been read. May 108 // be called multiple times for a single frame. |payload| is guaranteed to 109 // be non-empty. 110 virtual bool OnUnknownFramePayload(absl::string_view payload) = 0; 111 // Called when the unknown frame has been completely processed. 112 virtual bool OnUnknownFrameEnd() = 0; 113 }; 114 115 // |visitor| must be non-null, and must outlive HttpDecoder. 116 explicit HttpDecoder(Visitor* visitor); 117 118 ~HttpDecoder(); 119 120 // Processes the input and invokes the appropriate visitor methods, until a 121 // visitor method returns false or an error occurs. Returns the number of 122 // bytes processed. Does not process any input if called after an error. 123 // Paused processing can be resumed by calling ProcessInput() again with the 124 // unprocessed portion of data. Must not be called after an error has 125 // occurred. 126 QuicByteCount ProcessInput(const char* data, QuicByteCount len); 127 128 // Decode settings frame from |data|. 129 // Upon successful decoding, |frame| will be populated, and returns true. 130 // This method is not used for regular processing of incoming data. 131 static bool DecodeSettings(const char* data, QuicByteCount len, 132 SettingsFrame* frame); 133 134 // Returns an error code other than QUIC_NO_ERROR if and only if 135 // Visitor::OnError() has been called. error()136 QuicErrorCode error() const { return error_; } 137 error_detail()138 const std::string& error_detail() const { return error_detail_; } 139 140 // Returns true if input data processed so far ends on a frame boundary. AtFrameBoundary()141 bool AtFrameBoundary() const { return state_ == STATE_READING_FRAME_TYPE; } 142 143 // Indicates that WEBTRANSPORT_STREAM should be parsed. EnableWebTransportStreamParsing()144 void EnableWebTransportStreamParsing() { allow_web_transport_stream_ = true; } 145 146 std::string DebugString() const; 147 148 private: 149 friend test::HttpDecoderPeer; 150 151 // Represents the current state of the parsing state machine. 152 enum HttpDecoderState { 153 STATE_READING_FRAME_LENGTH, 154 STATE_READING_FRAME_TYPE, 155 156 // States used for buffered frame types 157 STATE_BUFFER_OR_PARSE_PAYLOAD, 158 159 // States used for non-buffered frame types 160 STATE_READING_FRAME_PAYLOAD, 161 STATE_FINISH_PARSING, 162 163 STATE_PARSING_NO_LONGER_POSSIBLE, 164 STATE_ERROR 165 }; 166 167 // Reads the type of a frame from |reader|. Sets error_ and error_detail_ 168 // if there are any errors. Also calls OnDataFrameStart() or 169 // OnHeadersFrameStart() for appropriate frame types. Returns whether the 170 // processing should continue. 171 bool ReadFrameType(QuicDataReader* reader); 172 173 // Reads the length of a frame from |reader|. Sets error_ and error_detail_ 174 // if there are any errors. Returns whether processing should continue. 175 bool ReadFrameLength(QuicDataReader* reader); 176 177 // Returns whether the current frame is of a buffered type. 178 // The payload of buffered frames is buffered by HttpDecoder, and parsed by 179 // HttpDecoder after the entire frame has been received. (Copying to the 180 // buffer is skipped if the ProcessInput() call covers the entire payload.) 181 // Frames that are not buffered have every payload fragment synchronously 182 // passed to the Visitor without buffering. 183 bool IsFrameBuffered(); 184 185 // For buffered frame types, calls BufferOrParsePayload(). For other frame 186 // types, reads the payload of the current frame from |reader| and calls 187 // visitor methods. Returns whether processing should continue. 188 bool ReadFramePayload(QuicDataReader* reader); 189 190 // For buffered frame types, this method is only called if frame payload is 191 // empty, and it calls BufferOrParsePayload(). For other frame types, this 192 // method directly calls visitor methods to signal that frame had been 193 // received completely. Returns whether processing should continue. 194 bool FinishParsing(); 195 196 // Reset internal fields to prepare for reading next frame. 197 void ResetForNextFrame(); 198 199 // Read payload of unknown frame from |reader| and call 200 // Visitor::OnUnknownFramePayload(). Returns true decoding should continue, 201 // false if it should be paused. 202 bool HandleUnknownFramePayload(QuicDataReader* reader); 203 204 // Buffers any remaining frame payload from |*reader| into |buffer_| if 205 // necessary. Parses the frame payload if complete. Parses out of |*reader| 206 // without unnecessary copy if |*reader| contains entire payload. 207 // Returns whether processing should continue. 208 // Must only be called when current frame type is buffered. 209 bool BufferOrParsePayload(QuicDataReader* reader); 210 211 // Parses the entire payload of certain kinds of frames that are parsed in a 212 // single pass. |reader| must have at least |current_frame_length_| bytes. 213 // Returns whether processing should continue. 214 // Must only be called when current frame type is buffered. 215 bool ParseEntirePayload(QuicDataReader* reader); 216 217 // Buffers any remaining frame length field from |reader| into 218 // |length_buffer_|. 219 void BufferFrameLength(QuicDataReader* reader); 220 221 // Buffers any remaining frame type field from |reader| into |type_buffer_|. 222 void BufferFrameType(QuicDataReader* reader); 223 224 // Sets |error_| and |error_detail_| accordingly. 225 void RaiseError(QuicErrorCode error, std::string error_detail); 226 227 // Parses the payload of a SETTINGS frame from |reader| into |frame|. 228 bool ParseSettingsFrame(QuicDataReader* reader, SettingsFrame* frame); 229 230 // Parses the payload of a PRIORITY_UPDATE frame (draft-02, type 0xf0700) 231 // from |reader| into |frame|. 232 bool ParsePriorityUpdateFrame(QuicDataReader* reader, 233 PriorityUpdateFrame* frame); 234 235 // Parses the payload of an ACCEPT_CH frame from |reader| into |frame|. 236 bool ParseAcceptChFrame(QuicDataReader* reader, AcceptChFrame* frame); 237 238 // Returns the max frame size of a given |frame_type|. 239 QuicByteCount MaxFrameLength(uint64_t frame_type); 240 241 // Visitor to invoke when messages are parsed. 242 Visitor* const visitor_; // Unowned. 243 // Whether WEBTRANSPORT_STREAM should be parsed. 244 bool allow_web_transport_stream_; 245 // Current state of the parsing. 246 HttpDecoderState state_; 247 // Type of the frame currently being parsed. 248 uint64_t current_frame_type_; 249 // Size of the frame's length field. 250 QuicByteCount current_length_field_length_; 251 // Remaining length that's needed for the frame's length field. 252 QuicByteCount remaining_length_field_length_; 253 // Length of the payload of the frame currently being parsed. 254 QuicByteCount current_frame_length_; 255 // Remaining payload bytes to be parsed. 256 QuicByteCount remaining_frame_length_; 257 // Length of the frame's type field. 258 QuicByteCount current_type_field_length_; 259 // Remaining length that's needed for the frame's type field. 260 QuicByteCount remaining_type_field_length_; 261 // Last error. 262 QuicErrorCode error_; 263 // The issue which caused |error_| 264 std::string error_detail_; 265 // Remaining unparsed data. 266 std::string buffer_; 267 // Remaining unparsed length field data. 268 std::array<char, sizeof(uint64_t)> length_buffer_; 269 // Remaining unparsed type field data. 270 std::array<char, sizeof(uint64_t)> type_buffer_; 271 }; 272 273 } // namespace quic 274 275 #endif // QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_ 276