blob: 30ebadc49efbed1ce5d0cfb2c2515972949be565 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
renjietang857362b2019-08-09 09:52:35 -07008#include <cstdint>
9
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include "net/third_party/quiche/src/quic/core/http/http_frames.h"
11#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
renjietang857362b2019-08-09 09:52:35 -070012#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
bnc4f6d01a2019-06-25 06:03:54 -070014#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050015
16namespace quic {
17
bnc62c32b42019-06-24 16:06:41 -070018namespace test {
19
20class HttpDecoderPeer;
21
22} // namespace test
23
QUICHE teama6ef0a62019-03-07 20:34:33 -050024class QuicDataReader;
25
QUICHE teama6ef0a62019-03-07 20:34:33 -050026// A class for decoding the HTTP frames that are exchanged in an HTTP over QUIC
27// session.
28class QUIC_EXPORT_PRIVATE HttpDecoder {
29 public:
30 class QUIC_EXPORT_PRIVATE Visitor {
31 public:
32 virtual ~Visitor() {}
33
34 // Called if an error is detected.
35 virtual void OnError(HttpDecoder* decoder) = 0;
36
bncb9d07d92019-06-25 17:43:49 -070037 // All the following methods return true to continue decoding,
38 // and false to pause it.
bnce5f9c032019-07-25 11:30:40 -070039 // On*FrameStart() methods are called after the frame header is completely
40 // processed. At that point it is safe to consume
41 // |frame_length.header_length| bytes.
bncb9d07d92019-06-25 17:43:49 -070042
renjietang7d4f9132019-06-20 15:04:34 -070043 // Called when a PRIORITY frame has been received.
44 // |frame_length| contains PRIORITY frame length and payload length.
bnca2b13be2019-07-31 12:04:20 -070045 virtual bool OnPriorityFrameStart(QuicByteCount header_length) = 0;
renjietang7d4f9132019-06-20 15:04:34 -070046
QUICHE teama6ef0a62019-03-07 20:34:33 -050047 // Called when a PRIORITY frame has been successfully parsed.
renjietang546a6282019-06-03 10:21:21 -070048 virtual bool OnPriorityFrame(const PriorityFrame& frame) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050049
50 // Called when a CANCEL_PUSH frame has been successfully parsed.
renjietang546a6282019-06-03 10:21:21 -070051 virtual bool OnCancelPushFrame(const CancelPushFrame& frame) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050052
53 // Called when a MAX_PUSH_ID frame has been successfully parsed.
renjietang546a6282019-06-03 10:21:21 -070054 virtual bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050055
56 // Called when a GOAWAY frame has been successfully parsed.
renjietang546a6282019-06-03 10:21:21 -070057 virtual bool OnGoAwayFrame(const GoAwayFrame& frame) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050058
renjietangf41bf642019-04-02 11:45:34 -070059 // Called when a SETTINGS frame has been received.
bnca2b13be2019-07-31 12:04:20 -070060 virtual bool OnSettingsFrameStart(QuicByteCount header_length) = 0;
renjietangf41bf642019-04-02 11:45:34 -070061
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 // Called when a SETTINGS frame has been successfully parsed.
renjietang546a6282019-06-03 10:21:21 -070063 virtual bool OnSettingsFrame(const SettingsFrame& frame) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050064
65 // Called when a DUPLICATE_PUSH frame has been successfully parsed.
renjietang546a6282019-06-03 10:21:21 -070066 virtual bool OnDuplicatePushFrame(const DuplicatePushFrame& frame) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050067
bnc62446bc2019-03-14 06:11:25 -070068 // Called when a DATA frame has been received.
69 // |frame_length| contains DATA frame length and payload length.
bnca2b13be2019-07-31 12:04:20 -070070 virtual bool OnDataFrameStart(QuicByteCount header_length) = 0;
bnc70914262019-03-16 12:49:50 -070071 // Called when part of the payload of a DATA frame has been read. May be
72 // called multiple times for a single frame. |payload| is guaranteed to be
73 // non-empty.
renjietang546a6282019-06-03 10:21:21 -070074 virtual bool OnDataFramePayload(QuicStringPiece payload) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 // Called when a DATA frame has been completely processed.
renjietang546a6282019-06-03 10:21:21 -070076 virtual bool OnDataFrameEnd() = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050077
bnce433f532019-04-16 13:05:27 -070078 // Called when a HEADERS frame has been received.
bnc62446bc2019-03-14 06:11:25 -070079 // |frame_length| contains HEADERS frame length and payload length.
bnca2b13be2019-07-31 12:04:20 -070080 virtual bool OnHeadersFrameStart(QuicByteCount header_length) = 0;
bnc70914262019-03-16 12:49:50 -070081 // Called when part of the payload of a HEADERS frame has been read. May be
82 // called multiple times for a single frame. |payload| is guaranteed to be
83 // non-empty.
renjietang546a6282019-06-03 10:21:21 -070084 virtual bool OnHeadersFramePayload(QuicStringPiece payload) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050085 // Called when a HEADERS frame has been completely processed.
86 // |frame_len| is the length of the HEADERS frame payload.
renjietang546a6282019-06-03 10:21:21 -070087 virtual bool OnHeadersFrameEnd() = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050088
bnce433f532019-04-16 13:05:27 -070089 // Called when a PUSH_PROMISE frame has been received for |push_id|.
renjietangf4f47122019-07-22 12:08:53 -070090 virtual bool OnPushPromiseFrameStart(PushId push_id,
bnca2b13be2019-07-31 12:04:20 -070091 QuicByteCount header_length,
renjietang3c3dfb72019-07-26 11:55:52 -070092 QuicByteCount push_id_length) = 0;
bnc70914262019-03-16 12:49:50 -070093 // Called when part of the payload of a PUSH_PROMISE frame has been read.
94 // May be called multiple times for a single frame. |payload| is guaranteed
95 // to be non-empty.
renjietang546a6282019-06-03 10:21:21 -070096 virtual bool OnPushPromiseFramePayload(QuicStringPiece payload) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050097 // Called when a PUSH_PROMISE frame has been completely processed.
renjietang546a6282019-06-03 10:21:21 -070098 virtual bool OnPushPromiseFrameEnd() = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -050099
bncbf3dbe52019-07-17 05:17:41 -0700100 // 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 // |frame_length| contains frame length and payload length.
103 virtual bool OnUnknownFrameStart(uint64_t frame_type,
bnca2b13be2019-07-31 12:04:20 -0700104 QuicByteCount header_length) = 0;
bncbf3dbe52019-07-17 05:17:41 -0700105 // Called when part of the payload of the unknown frame has been read. May
106 // be called multiple times for a single frame. |payload| is guaranteed to
107 // be non-empty.
108 virtual bool OnUnknownFramePayload(QuicStringPiece payload) = 0;
109 // Called when the unknown frame has been completely processed.
110 virtual bool OnUnknownFrameEnd() = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500111 };
112
bnca9bb4692019-07-09 17:29:48 -0700113 // |visitor| must be non-null, and must outlive HttpDecoder.
114 explicit HttpDecoder(Visitor* visitor);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115
116 ~HttpDecoder();
117
bncb9d07d92019-06-25 17:43:49 -0700118 // Processes the input and invokes the appropriate visitor methods, until a
119 // visitor method returns false or an error occurs. Returns the number of
120 // bytes processed. Does not process any input if called after an error.
121 // Paused processing can be resumed by calling ProcessInput() again with the
bnc620095a2019-06-26 05:31:05 -0700122 // unprocessed portion of data. Must not be called after an error has
123 // occurred.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124 QuicByteCount ProcessInput(const char* data, QuicByteCount len);
125
bnc620095a2019-06-26 05:31:05 -0700126 // Returns an error code other than QUIC_NO_ERROR if and only if
127 // Visitor::OnError() has been called.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 QuicErrorCode error() const { return error_; }
bnc620095a2019-06-26 05:31:05 -0700129
vasilvvc48c8712019-03-11 13:38:16 -0700130 const std::string& error_detail() const { return error_detail_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131
132 private:
bnc62c32b42019-06-24 16:06:41 -0700133 friend test::HttpDecoderPeer;
134
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 // Represents the current state of the parsing state machine.
136 enum HttpDecoderState {
137 STATE_READING_FRAME_LENGTH,
138 STATE_READING_FRAME_TYPE,
139 STATE_READING_FRAME_PAYLOAD,
bnc70914262019-03-16 12:49:50 -0700140 STATE_FINISH_PARSING,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 STATE_ERROR
142 };
143
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144 // Reads the type of a frame from |reader|. Sets error_ and error_detail_
bnc70914262019-03-16 12:49:50 -0700145 // if there are any errors. Also calls OnDataFrameStart() or
146 // OnHeadersFrameStart() for appropriate frame types.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 void ReadFrameType(QuicDataReader* reader);
148
renjietangfcd91c02019-04-22 10:40:35 -0700149 // Reads the length of a frame from |reader|. Sets error_ and error_detail_
bncb9d07d92019-06-25 17:43:49 -0700150 // if there are any errors. Returns whether processing should continue.
151 bool ReadFrameLength(QuicDataReader* reader);
renjietangfcd91c02019-04-22 10:40:35 -0700152
QUICHE teama6ef0a62019-03-07 20:34:33 -0500153 // Reads the payload of the current frame from |reader| and processes it,
bncb9d07d92019-06-25 17:43:49 -0700154 // possibly buffering the data or invoking the visitor. Returns whether
155 // processing should continue.
156 bool ReadFramePayload(QuicDataReader* reader);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157
bnc70914262019-03-16 12:49:50 -0700158 // Optionally parses buffered data; calls visitor method to signal that frame
bncb9d07d92019-06-25 17:43:49 -0700159 // had been parsed completely. Returns whether processing should continue.
160 bool FinishParsing();
bnc70914262019-03-16 12:49:50 -0700161
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162 // Discards any remaining frame payload from |reader|.
163 void DiscardFramePayload(QuicDataReader* reader);
164
165 // Buffers any remaining frame payload from |reader| into |buffer_|.
166 void BufferFramePayload(QuicDataReader* reader);
167
168 // Buffers any remaining frame length field from |reader| into
renjietang2d475cf2019-04-18 17:03:37 -0700169 // |length_buffer_|.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 void BufferFrameLength(QuicDataReader* reader);
171
renjietang2d475cf2019-04-18 17:03:37 -0700172 // Buffers any remaining frame type field from |reader| into |type_buffer_|.
173 void BufferFrameType(QuicDataReader* reader);
174
renjietang857362b2019-08-09 09:52:35 -0700175 // Buffers at most |remaining_push_id_length_| from |reader| to
176 // |push_id_buffer_|.
177 void BufferPushId(QuicDataReader* reader);
178
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179 // Sets |error_| and |error_detail_| accordingly.
vasilvvc48c8712019-03-11 13:38:16 -0700180 void RaiseError(QuicErrorCode error, std::string error_detail);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181
182 // Parses the payload of a PRIORITY frame from |reader| into |frame|.
183 bool ParsePriorityFrame(QuicDataReader* reader, PriorityFrame* frame);
184
185 // Parses the payload of a SETTINGS frame from |reader| into |frame|.
186 bool ParseSettingsFrame(QuicDataReader* reader, SettingsFrame* frame);
187
renjietang4ab9d9f2019-04-10 14:30:26 -0700188 // Returns the max frame size of a given |frame_type|.
bnc95fb6b62019-07-21 11:20:47 -0700189 QuicByteCount MaxFrameLength(uint64_t frame_type);
renjietang4ab9d9f2019-04-10 14:30:26 -0700190
QUICHE teama6ef0a62019-03-07 20:34:33 -0500191 // Visitor to invoke when messages are parsed.
bnca9bb4692019-07-09 17:29:48 -0700192 Visitor* const visitor_; // Unowned.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 // Current state of the parsing.
194 HttpDecoderState state_;
195 // Type of the frame currently being parsed.
renjietang2d475cf2019-04-18 17:03:37 -0700196 uint64_t current_frame_type_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500197 // Size of the frame's length field.
renjietangbb98cbc2019-04-23 13:13:56 -0700198 QuicByteCount current_length_field_length_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 // Remaining length that's needed for the frame's length field.
200 QuicByteCount remaining_length_field_length_;
201 // Length of the payload of the frame currently being parsed.
202 QuicByteCount current_frame_length_;
203 // Remaining payload bytes to be parsed.
204 QuicByteCount remaining_frame_length_;
renjietang2d475cf2019-04-18 17:03:37 -0700205 // Length of the frame's type field.
206 QuicByteCount current_type_field_length_;
207 // Remaining length that's needed for the frame's type field.
208 QuicByteCount remaining_type_field_length_;
renjietang857362b2019-08-09 09:52:35 -0700209 // Length of PUSH_PROMISE frame's push id.
210 QuicByteCount current_push_id_length_;
211 // Remaining length that's needed for PUSH_PROMISE frame's push id field.
212 QuicByteCount remaining_push_id_length_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213 // Last error.
214 QuicErrorCode error_;
215 // The issue which caused |error_|
vasilvvc48c8712019-03-11 13:38:16 -0700216 std::string error_detail_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500217 // Remaining unparsed data.
vasilvvc48c8712019-03-11 13:38:16 -0700218 std::string buffer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219 // Remaining unparsed length field data.
renjietangbb98cbc2019-04-23 13:13:56 -0700220 std::array<char, sizeof(uint64_t)> length_buffer_;
renjietang2d475cf2019-04-18 17:03:37 -0700221 // Remaining unparsed type field data.
222 std::array<char, sizeof(uint64_t)> type_buffer_;
renjietang857362b2019-08-09 09:52:35 -0700223 // Remaining unparsed push id data.
224 std::array<char, sizeof(uint64_t)> push_id_buffer_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225};
226
227} // namespace quic
228
229#endif // QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_