blob: cee8ec9a30d9410af719695140411658b12b3949 [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// Copyright 2016 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_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_
6#define QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_
7
8// Http2FrameDecoder decodes the available input until it reaches the end of
9// the input or it reaches the end of the first frame in the input.
10// Note that Http2FrameDecoder does only minimal validation; for example,
11// stream ids are not checked, nor is the sequence of frames such as
12// CONTINUATION frame placement.
13//
14// Http2FrameDecoder enters state kError once it has called the listener's
15// OnFrameSizeError or OnPaddingTooLong methods, and at this time has no
16// provision for leaving that state. While the HTTP/2 spec (RFC7540) allows
17// for some such errors to be considered as just stream errors in some cases,
18// this implementation treats them all as connection errors.
19
20#include <stddef.h>
21
22#include <cstdint>
23
QUICHE teamfd50a402018-12-07 22:54:05 -050024#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
25#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
26#include "net/third_party/quiche/src/http2/decoder/frame_decoder_state.h"
27#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h"
28#include "net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.h"
29#include "net/third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.h"
30#include "net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.h"
31#include "net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.h"
32#include "net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.h"
33#include "net/third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.h"
34#include "net/third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.h"
35#include "net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.h"
36#include "net/third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h"
37#include "net/third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.h"
38#include "net/third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.h"
39#include "net/third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.h"
40#include "net/third_party/quiche/src/http2/http2_structures.h"
QUICHE team61940b42019-03-07 23:32:27 -050041#include "net/third_party/quiche/src/http2/platform/api/http2_logging.h"
bnc641ace72020-01-21 12:24:57 -080042#include "net/third_party/quiche/src/common/platform/api/quiche_export.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050043
44namespace http2 {
45namespace test {
46class Http2FrameDecoderPeer;
47} // namespace test
48
bnc641ace72020-01-21 12:24:57 -080049class QUICHE_EXPORT_PRIVATE Http2FrameDecoder {
QUICHE teamfd50a402018-12-07 22:54:05 -050050 public:
51 explicit Http2FrameDecoder(Http2FrameDecoderListener* listener);
52 Http2FrameDecoder() : Http2FrameDecoder(nullptr) {}
53
54 Http2FrameDecoder(const Http2FrameDecoder&) = delete;
55 Http2FrameDecoder& operator=(const Http2FrameDecoder&) = delete;
56
57 // The decoder will call the listener's methods as it decodes a frame.
58 void set_listener(Http2FrameDecoderListener* listener);
59 Http2FrameDecoderListener* listener() const;
60
61 // The decoder will reject frame's whose payload
62 // length field exceeds the maximum payload size.
63 void set_maximum_payload_size(size_t v) { maximum_payload_size_ = v; }
64 size_t maximum_payload_size() const { return maximum_payload_size_; }
65
66 // Decodes the input up to the next frame boundary (i.e. at most one frame).
67 //
68 // Returns kDecodeDone if it decodes the final byte of a frame, OR if there
69 // is no input and it is awaiting the start of a new frame (e.g. if this
70 // is the first call to DecodeFrame, or if the previous call returned
71 // kDecodeDone).
72 //
73 // Returns kDecodeInProgress if it decodes all of the decode buffer, but has
74 // not reached the end of the frame.
75 //
76 // Returns kDecodeError if the frame's padding or length wasn't valid (i.e. if
77 // the decoder called either the listener's OnPaddingTooLong or
78 // OnFrameSizeError method).
79 DecodeStatus DecodeFrame(DecodeBuffer* db);
80
81 //////////////////////////////////////////////////////////////////////////////
82 // Methods that support Http2FrameDecoderAdapter.
83
84 // Is the remainder of the frame's payload being discarded?
85 bool IsDiscardingPayload() const { return state_ == State::kDiscardPayload; }
86
87 // Returns the number of bytes of the frame's payload that remain to be
88 // decoded, excluding any trailing padding. This method must only be called
89 // after the frame header has been decoded AND DecodeFrame has returned
90 // kDecodeInProgress.
91 size_t remaining_payload() const;
92
93 // Returns the number of bytes of trailing padding after the payload that
94 // remain to be decoded. This method must only be called if the frame type
95 // allows padding, and after the frame header has been decoded AND
96 // DecodeFrame has returned. Will return 0 if the Pad Length field has not
97 // yet been decoded.
98 uint32_t remaining_padding() const;
99
100 private:
101 enum class State {
102 // Ready to start decoding a new frame's header.
103 kStartDecodingHeader,
104 // Was in state kStartDecodingHeader, but unable to read the entire frame
105 // header, so needs more input to complete decoding the header.
106 kResumeDecodingHeader,
107
108 // Have decoded the frame header, and started decoding the available bytes
109 // of the frame's payload, but need more bytes to finish the job.
110 kResumeDecodingPayload,
111
112 // Decoding of the most recently started frame resulted in an error:
113 // OnPaddingTooLong or OnFrameSizeError was called to indicate that the
114 // decoder detected a problem, or OnFrameHeader returned false, indicating
115 // that the listener detected a problem. Regardless of which, the decoder
116 // will stay in state kDiscardPayload until it has been passed the rest
117 // of the bytes of the frame's payload that it hasn't yet seen, after
118 // which it will be ready to decode another frame.
119 kDiscardPayload,
120 };
121
122 friend class test::Http2FrameDecoderPeer;
123 friend std::ostream& operator<<(std::ostream& out, State v);
124
125 DecodeStatus StartDecodingPayload(DecodeBuffer* db);
126 DecodeStatus ResumeDecodingPayload(DecodeBuffer* db);
127 DecodeStatus DiscardPayload(DecodeBuffer* db);
128
129 const Http2FrameHeader& frame_header() const {
130 return frame_decoder_state_.frame_header();
131 }
132
133 // Clear any of the flags in the frame header that aren't set in valid_flags.
134 void RetainFlags(uint8_t valid_flags);
135
136 // Clear all of the flags in the frame header; for use with frame types that
137 // don't define any flags, such as WINDOW_UPDATE.
138 void ClearFlags();
139
140 // These methods call the StartDecodingPayload() method of the frame type's
141 // payload decoder, after first clearing invalid flags in the header. The
142 // caller must ensure that the decode buffer does not extend beyond the
143 // end of the payload (handled by Http2FrameDecoder::StartDecodingPayload).
144 DecodeStatus StartDecodingAltSvcPayload(DecodeBuffer* db);
145 DecodeStatus StartDecodingContinuationPayload(DecodeBuffer* db);
146 DecodeStatus StartDecodingDataPayload(DecodeBuffer* db);
147 DecodeStatus StartDecodingGoAwayPayload(DecodeBuffer* db);
148 DecodeStatus StartDecodingHeadersPayload(DecodeBuffer* db);
149 DecodeStatus StartDecodingPingPayload(DecodeBuffer* db);
150 DecodeStatus StartDecodingPriorityPayload(DecodeBuffer* db);
151 DecodeStatus StartDecodingPushPromisePayload(DecodeBuffer* db);
152 DecodeStatus StartDecodingRstStreamPayload(DecodeBuffer* db);
153 DecodeStatus StartDecodingSettingsPayload(DecodeBuffer* db);
154 DecodeStatus StartDecodingUnknownPayload(DecodeBuffer* db);
155 DecodeStatus StartDecodingWindowUpdatePayload(DecodeBuffer* db);
156
157 // These methods call the ResumeDecodingPayload() method of the frame type's
158 // payload decoder; they are called only if the preceding call to the
159 // corresponding Start method (above) returned kDecodeInProgress, as did any
160 // subsequent calls to the resume method.
161 // Unlike the Start methods, the decode buffer may extend beyond the
162 // end of the payload, so the method will create a DecodeBufferSubset
163 // before calling the ResumeDecodingPayload method of the frame type's
164 // payload decoder.
165 DecodeStatus ResumeDecodingAltSvcPayload(DecodeBuffer* db);
166 DecodeStatus ResumeDecodingContinuationPayload(DecodeBuffer* db);
167 DecodeStatus ResumeDecodingDataPayload(DecodeBuffer* db);
168 DecodeStatus ResumeDecodingGoAwayPayload(DecodeBuffer* db);
169 DecodeStatus ResumeDecodingHeadersPayload(DecodeBuffer* db);
170 DecodeStatus ResumeDecodingPingPayload(DecodeBuffer* db);
171 DecodeStatus ResumeDecodingPriorityPayload(DecodeBuffer* db);
172 DecodeStatus ResumeDecodingPushPromisePayload(DecodeBuffer* db);
173 DecodeStatus ResumeDecodingRstStreamPayload(DecodeBuffer* db);
174 DecodeStatus ResumeDecodingSettingsPayload(DecodeBuffer* db);
175 DecodeStatus ResumeDecodingUnknownPayload(DecodeBuffer* db);
176 DecodeStatus ResumeDecodingWindowUpdatePayload(DecodeBuffer* db);
177
178 FrameDecoderState frame_decoder_state_;
179
180 // We only need one payload decoder at a time, so they share the same storage.
181 union {
182 AltSvcPayloadDecoder altsvc_payload_decoder_;
183 ContinuationPayloadDecoder continuation_payload_decoder_;
184 DataPayloadDecoder data_payload_decoder_;
185 GoAwayPayloadDecoder goaway_payload_decoder_;
186 HeadersPayloadDecoder headers_payload_decoder_;
187 PingPayloadDecoder ping_payload_decoder_;
188 PriorityPayloadDecoder priority_payload_decoder_;
189 PushPromisePayloadDecoder push_promise_payload_decoder_;
190 RstStreamPayloadDecoder rst_stream_payload_decoder_;
191 SettingsPayloadDecoder settings_payload_decoder_;
192 UnknownPayloadDecoder unknown_payload_decoder_;
193 WindowUpdatePayloadDecoder window_update_payload_decoder_;
194 };
195
196 State state_;
197 size_t maximum_payload_size_;
198
199 // Listener used whenever caller passes nullptr to set_listener.
200 Http2FrameDecoderNoOpListener no_op_listener_;
201};
202
203} // namespace http2
204
205#endif // QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_