Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: net/http2/decoder/frame_decoder_state.h

Issue 2554683003: Revert of Add new HTTP/2 and HPACK decoder in net/http2/. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/http2/decoder/decode_status.cc ('k') | net/http2/decoder/frame_decoder_state.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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 NET_HTTP2_DECODER_FRAME_DECODER_STATE_H_
6 #define NET_HTTP2_DECODER_FRAME_DECODER_STATE_H_
7
8 // FrameDecoderState provides state and behaviors in support of decoding
9 // the common frame header and the payload of all frame types.
10 // It is an input to all of the payload decoders.
11
12 // TODO(jamessynge): Since FrameDecoderState has far more than state in it,
13 // rename to FrameDecoderHelper, or similar.
14
15 #include <stddef.h>
16
17 #include "base/logging.h"
18 #include "net/base/net_export.h"
19 #include "net/http2/decoder/decode_buffer.h"
20 #include "net/http2/decoder/decode_status.h"
21 #include "net/http2/decoder/http2_frame_decoder_listener.h"
22 #include "net/http2/decoder/http2_structure_decoder.h"
23 #include "net/http2/http2_constants.h"
24 #include "net/http2/http2_structures.h"
25
26 namespace net {
27 namespace test {
28 class FrameDecoderStatePeer;
29 } // namespace test
30
31 class NET_EXPORT_PRIVATE FrameDecoderState {
32 public:
33 FrameDecoderState() {}
34
35 // Sets the listener which the decoders should call as they decode HTTP/2
36 // frames. The listener can be changed at any time, which allows for replacing
37 // it with a no-op listener when an error is detected, either by the payload
38 // decoder (OnPaddingTooLong or OnFrameSizeError) or by the "real" listener.
39 // That in turn allows us to define Http2FrameDecoderListener such that all
40 // methods have return type void, with no direct way to indicate whether the
41 // decoder should stop, and to eliminate from the decoder all checks of the
42 // return value. Instead the listener/caller can simply replace the current
43 // listener with a no-op listener implementation.
44 // TODO(jamessynge): Make set_listener private as only Http2FrameDecoder
45 // and tests need to set it, so it doesn't need to be public.
46 void set_listener(Http2FrameDecoderListener* listener) {
47 listener_ = listener;
48 }
49 Http2FrameDecoderListener* listener() const { return listener_; }
50
51 // The most recently decoded frame header.
52 const Http2FrameHeader& frame_header() const { return frame_header_; }
53
54 // Decode a structure in the payload, adjusting remaining_payload_ to account
55 // for the consumed portion of the payload. Returns kDecodeDone when fully
56 // decoded, kDecodeError if it ran out of payload before decoding completed,
57 // and kDecodeInProgress if the decode buffer didn't have enough of the
58 // remaining payload.
59 template <class S>
60 DecodeStatus StartDecodingStructureInPayload(S* out, DecodeBuffer* db) {
61 DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining()
62 << "\n\tremaining_payload_=" << remaining_payload_
63 << "\n\tneed=" << S::EncodedSize();
64 DecodeStatus status =
65 structure_decoder_.Start(out, db, &remaining_payload_);
66 if (status != DecodeStatus::kDecodeError) {
67 return status;
68 }
69 DVLOG(2) << "StartDecodingStructureInPayload: detected frame size error";
70 return ReportFrameSizeError();
71 }
72
73 // Resume decoding of a structure that has been split across buffers,
74 // adjusting remaining_payload_ to account for the consumed portion of
75 // the payload. Returns values are as for StartDecodingStructureInPayload.
76 template <class S>
77 DecodeStatus ResumeDecodingStructureInPayload(S* out, DecodeBuffer* db) {
78 DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining()
79 << "\n\tremaining_payload_=" << remaining_payload_;
80 if (structure_decoder_.Resume(out, db, &remaining_payload_)) {
81 return DecodeStatus::kDecodeDone;
82 } else if (remaining_payload_ > 0) {
83 return DecodeStatus::kDecodeInProgress;
84 } else {
85 DVLOG(2) << "ResumeDecodingStructureInPayload: detected frame size error";
86 return ReportFrameSizeError();
87 }
88 }
89
90 // Initializes the two remaining* fields, which is needed if the frame's
91 // payload is split across buffers, or the decoder calls ReadPadLength or
92 // StartDecodingStructureInPayload, and of course the methods below which
93 // read those fields, as their names imply.
94 void InitializeRemainders() {
95 remaining_payload_ = frame_header().payload_length;
96 // Note that remaining_total_payload() relies on remaining_padding_ being
97 // zero for frames that have no padding.
98 remaining_padding_ = 0;
99 }
100
101 // Returns the number of bytes of the frame's payload that remain to be
102 // decoded, including any trailing padding. This method must only be called
103 // after the variables have been initialized, which in practice means once a
104 // payload decoder has called InitializeRemainders and/or ReadPadLength.
105 size_t remaining_total_payload() const {
106 DCHECK(IsPaddable() || remaining_padding_ == 0) << frame_header();
107 return remaining_payload_ + remaining_padding_;
108 }
109
110 // Returns the number of bytes of the frame's payload that remain to be
111 // decoded, excluding any trailing padding. This method must only be called
112 // after the variable has been initialized, which in practice means once a
113 // payload decoder has called InitializeRemainders; ReadPadLength will deduct
114 // the total number of padding bytes from remaining_payload_, including the
115 // size of the Pad Length field itself (1 byte).
116 size_t remaining_payload() const { return remaining_payload_; }
117
118 // Returns the number of bytes of the frame's payload that remain to be
119 // decoded, including any trailing padding. This method must only be called if
120 // the frame type allows padding, and after the variable has been initialized,
121 // which in practice means once a payload decoder has called
122 // InitializeRemainders and/or ReadPadLength.
123 size_t remaining_payload_and_padding() const {
124 DCHECK(IsPaddable()) << frame_header();
125 return remaining_payload_ + remaining_padding_;
126 }
127
128 // Returns the number of bytes of trailing padding after the payload that
129 // remain to be decoded. This method must only be called if the frame type
130 // allows padding, and after the variable has been initialized, which in
131 // practice means once a payload decoder has called InitializeRemainders,
132 // and isn't set to a non-zero value until ReadPadLength has been called.
133 uint32_t remaining_padding() const {
134 DCHECK(IsPaddable()) << frame_header();
135 return remaining_padding_;
136 }
137
138 // Returns the amount of trailing padding after the payload that remains to be
139 // decoded.
140 uint32_t remaining_padding_for_test() const { return remaining_padding_; }
141
142 // How many bytes of the remaining payload are in db?
143 size_t AvailablePayload(DecodeBuffer* db) const {
144 return db->MinLengthRemaining(remaining_payload_);
145 }
146
147 // How many bytes of the remaining payload and padding are in db?
148 // Call only for frames whose type is paddable.
149 size_t AvailablePayloadAndPadding(DecodeBuffer* db) const {
150 DCHECK(IsPaddable()) << frame_header();
151 return db->MinLengthRemaining(remaining_payload_ + remaining_padding_);
152 }
153
154 // How many bytes of the padding that have not yet been skipped are in db?
155 // Call only after remaining_padding_ has been set (for padded frames), or
156 // been cleared (for unpadded frames); and after all of the non-padding
157 // payload has been decoded.
158 size_t AvailablePadding(DecodeBuffer* db) const {
159 DCHECK(IsPaddable()) << frame_header();
160 DCHECK_EQ(remaining_payload_, 0u);
161 return db->MinLengthRemaining(remaining_padding_);
162 }
163
164 // Reduces remaining_payload_ by amount. To be called by a payload decoder
165 // after it has passed a variable length portion of the payload to the
166 // listener; remaining_payload_ will be automatically reduced when fixed
167 // size structures and padding, including the Pad Length field, are decoded.
168 void ConsumePayload(size_t amount) {
169 DCHECK_LE(amount, remaining_payload_);
170 remaining_payload_ -= amount;
171 }
172
173 // Reads the Pad Length field into remaining_padding_, and appropriately sets
174 // remaining_payload_. When present, the Pad Length field is always the first
175 // field in the payload, which this method relies on so that the caller need
176 // not set remaining_payload_ before calling this method.
177 // If report_pad_length is true, calls the listener's OnPadLength method when
178 // it decodes the Pad Length field.
179 // Returns kDecodeDone if the decode buffer was not empty (i.e. because the
180 // field is only a single byte long, it can always be decoded if the buffer is
181 // not empty).
182 // Returns kDecodeError if the buffer is empty because the frame has no
183 // payload (i.e. payload_length() == 0).
184 // Returns kDecodeInProgress if the buffer is empty but the frame has a
185 // payload.
186 DecodeStatus ReadPadLength(DecodeBuffer* db, bool report_pad_length);
187
188 // Skip the trailing padding bytes; only call once remaining_payload_==0.
189 // Returns true when the padding has been skipped.
190 // Does NOT check that the padding is all zeroes.
191 bool SkipPadding(DecodeBuffer* db);
192
193 // Calls the listener's OnFrameSizeError method and returns kDecodeError.
194 DecodeStatus ReportFrameSizeError();
195
196 private:
197 friend class Http2FrameDecoder;
198 friend class test::FrameDecoderStatePeer;
199
200 // Starts the decoding of a common frame header. Returns true if completed the
201 // decoding, false if the decode buffer didn't have enough data in it, in
202 // which case the decode buffer will have been drained and the caller should
203 // call ResumeDecodingFrameHeader when more data is available. This is called
204 // from Http2FrameDecoder, a friend class.
205 bool StartDecodingFrameHeader(DecodeBuffer* db) {
206 return structure_decoder_.Start(&frame_header_, db);
207 }
208
209 // Resumes decoding the common frame header after the preceding call to
210 // StartDecodingFrameHeader returned false, as did any subsequent calls to
211 // ResumeDecodingFrameHeader. This is called from Http2FrameDecoder,
212 // a friend class.
213 bool ResumeDecodingFrameHeader(DecodeBuffer* db) {
214 return structure_decoder_.Resume(&frame_header_, db);
215 }
216
217 // Clear any of the flags in the frame header that aren't set in valid_flags.
218 void RetainFlags(uint8_t valid_flags) {
219 frame_header_.RetainFlags(valid_flags);
220 }
221
222 // Clear all of the flags in the frame header; for use with frame types that
223 // don't define any flags, such as WINDOW_UPDATE.
224 void ClearFlags() { frame_header_.flags = Http2FrameFlag(); }
225
226 // Returns true if the type of frame being decoded can have padding.
227 bool IsPaddable() const {
228 return frame_header().type == Http2FrameType::DATA ||
229 frame_header().type == Http2FrameType::HEADERS ||
230 frame_header().type == Http2FrameType::PUSH_PROMISE;
231 }
232
233 Http2FrameDecoderListener* listener_ = nullptr;
234 Http2FrameHeader frame_header_;
235
236 // Number of bytes remaining to be decoded, if set; does not include the
237 // trailing padding once the length of padding has been determined.
238 // See ReadPadLength.
239 uint32_t remaining_payload_;
240
241 // The amount of trailing padding after the payload that remains to be
242 // decoded. See ReadPadLength.
243 uint32_t remaining_padding_;
244
245 // Generic decoder of structures, which takes care of buffering the needed
246 // bytes if the encoded structure is split across decode buffers.
247 Http2StructureDecoder structure_decoder_;
248 };
249
250 } // namespace net
251
252 #endif // NET_HTTP2_DECODER_FRAME_DECODER_STATE_H_
OLDNEW
« no previous file with comments | « net/http2/decoder/decode_status.cc ('k') | net/http2/decoder/frame_decoder_state.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698