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 #include "quiche/http2/decoder/http2_frame_decoder.h"
6
7 #include "quiche/http2/decoder/decode_status.h"
8 #include "quiche/http2/hpack/varint/hpack_varint_decoder.h"
9 #include "quiche/http2/http2_constants.h"
10 #include "quiche/common/platform/api/quiche_bug_tracker.h"
11 #include "quiche/common/platform/api/quiche_logging.h"
12
13 namespace http2 {
14
operator <<(std::ostream & out,Http2FrameDecoder::State v)15 std::ostream& operator<<(std::ostream& out, Http2FrameDecoder::State v) {
16 switch (v) {
17 case Http2FrameDecoder::State::kStartDecodingHeader:
18 return out << "kStartDecodingHeader";
19 case Http2FrameDecoder::State::kResumeDecodingHeader:
20 return out << "kResumeDecodingHeader";
21 case Http2FrameDecoder::State::kResumeDecodingPayload:
22 return out << "kResumeDecodingPayload";
23 case Http2FrameDecoder::State::kDiscardPayload:
24 return out << "kDiscardPayload";
25 }
26 // Since the value doesn't come over the wire, only a programming bug should
27 // result in reaching this point.
28 int unknown = static_cast<int>(v);
29 QUICHE_BUG(http2_bug_155_1) << "Http2FrameDecoder::State " << unknown;
30 return out << "Http2FrameDecoder::State(" << unknown << ")";
31 }
32
Http2FrameDecoder(Http2FrameDecoderListener * listener)33 Http2FrameDecoder::Http2FrameDecoder(Http2FrameDecoderListener* listener)
34 : state_(State::kStartDecodingHeader),
35 maximum_payload_size_(Http2SettingsInfo::DefaultMaxFrameSize()) {
36 set_listener(listener);
37 }
38
set_listener(Http2FrameDecoderListener * listener)39 void Http2FrameDecoder::set_listener(Http2FrameDecoderListener* listener) {
40 if (listener == nullptr) {
41 listener = &no_op_listener_;
42 }
43 frame_decoder_state_.set_listener(listener);
44 }
45
listener() const46 Http2FrameDecoderListener* Http2FrameDecoder::listener() const {
47 return frame_decoder_state_.listener();
48 }
49
DecodeFrame(DecodeBuffer * db)50 DecodeStatus Http2FrameDecoder::DecodeFrame(DecodeBuffer* db) {
51 QUICHE_DVLOG(2) << "Http2FrameDecoder::DecodeFrame state=" << state_;
52 switch (state_) {
53 case State::kStartDecodingHeader:
54 if (frame_decoder_state_.StartDecodingFrameHeader(db)) {
55 return StartDecodingPayload(db);
56 }
57 state_ = State::kResumeDecodingHeader;
58 return DecodeStatus::kDecodeInProgress;
59
60 case State::kResumeDecodingHeader:
61 if (frame_decoder_state_.ResumeDecodingFrameHeader(db)) {
62 return StartDecodingPayload(db);
63 }
64 return DecodeStatus::kDecodeInProgress;
65
66 case State::kResumeDecodingPayload:
67 return ResumeDecodingPayload(db);
68
69 case State::kDiscardPayload:
70 return DiscardPayload(db);
71 }
72
73 QUICHE_NOTREACHED();
74 return DecodeStatus::kDecodeError;
75 }
76
remaining_payload() const77 size_t Http2FrameDecoder::remaining_payload() const {
78 return frame_decoder_state_.remaining_payload();
79 }
80
remaining_padding() const81 uint32_t Http2FrameDecoder::remaining_padding() const {
82 return frame_decoder_state_.remaining_padding();
83 }
84
StartDecodingPayload(DecodeBuffer * db)85 DecodeStatus Http2FrameDecoder::StartDecodingPayload(DecodeBuffer* db) {
86 const Http2FrameHeader& header = frame_header();
87
88 // TODO(jamessynge): Remove OnFrameHeader once done with supporting
89 // SpdyFramer's exact states.
90 if (!listener()->OnFrameHeader(header)) {
91 QUICHE_DVLOG(2)
92 << "OnFrameHeader rejected the frame, will discard; header: " << header;
93 state_ = State::kDiscardPayload;
94 frame_decoder_state_.InitializeRemainders();
95 return DecodeStatus::kDecodeError;
96 }
97
98 if (header.payload_length > maximum_payload_size_) {
99 QUICHE_DVLOG(2) << "Payload length is greater than allowed: "
100 << header.payload_length << " > " << maximum_payload_size_
101 << "\n header: " << header;
102 state_ = State::kDiscardPayload;
103 frame_decoder_state_.InitializeRemainders();
104 listener()->OnFrameSizeError(header);
105 return DecodeStatus::kDecodeError;
106 }
107
108 // The decode buffer can extend across many frames. Make sure that the
109 // buffer we pass to the start method that is specific to the frame type
110 // does not exend beyond this frame.
111 DecodeBufferSubset subset(db, header.payload_length);
112 DecodeStatus status;
113 switch (header.type) {
114 case Http2FrameType::DATA:
115 status = StartDecodingDataPayload(&subset);
116 break;
117
118 case Http2FrameType::HEADERS:
119 status = StartDecodingHeadersPayload(&subset);
120 break;
121
122 case Http2FrameType::PRIORITY:
123 status = StartDecodingPriorityPayload(&subset);
124 break;
125
126 case Http2FrameType::RST_STREAM:
127 status = StartDecodingRstStreamPayload(&subset);
128 break;
129
130 case Http2FrameType::SETTINGS:
131 status = StartDecodingSettingsPayload(&subset);
132 break;
133
134 case Http2FrameType::PUSH_PROMISE:
135 status = StartDecodingPushPromisePayload(&subset);
136 break;
137
138 case Http2FrameType::PING:
139 status = StartDecodingPingPayload(&subset);
140 break;
141
142 case Http2FrameType::GOAWAY:
143 status = StartDecodingGoAwayPayload(&subset);
144 break;
145
146 case Http2FrameType::WINDOW_UPDATE:
147 status = StartDecodingWindowUpdatePayload(&subset);
148 break;
149
150 case Http2FrameType::CONTINUATION:
151 status = StartDecodingContinuationPayload(&subset);
152 break;
153
154 case Http2FrameType::ALTSVC:
155 status = StartDecodingAltSvcPayload(&subset);
156 break;
157
158 case Http2FrameType::PRIORITY_UPDATE:
159 status = StartDecodingPriorityUpdatePayload(&subset);
160 break;
161
162 default:
163 status = StartDecodingUnknownPayload(&subset);
164 break;
165 }
166
167 if (status == DecodeStatus::kDecodeDone) {
168 state_ = State::kStartDecodingHeader;
169 return status;
170 } else if (status == DecodeStatus::kDecodeInProgress) {
171 state_ = State::kResumeDecodingPayload;
172 return status;
173 } else {
174 state_ = State::kDiscardPayload;
175 return status;
176 }
177 }
178
ResumeDecodingPayload(DecodeBuffer * db)179 DecodeStatus Http2FrameDecoder::ResumeDecodingPayload(DecodeBuffer* db) {
180 // The decode buffer can extend across many frames. Make sure that the
181 // buffer we pass to the start method that is specific to the frame type
182 // does not exend beyond this frame.
183 size_t remaining = frame_decoder_state_.remaining_total_payload();
184 QUICHE_DCHECK_LE(remaining, frame_header().payload_length);
185 DecodeBufferSubset subset(db, remaining);
186 DecodeStatus status;
187 switch (frame_header().type) {
188 case Http2FrameType::DATA:
189 status = ResumeDecodingDataPayload(&subset);
190 break;
191
192 case Http2FrameType::HEADERS:
193 status = ResumeDecodingHeadersPayload(&subset);
194 break;
195
196 case Http2FrameType::PRIORITY:
197 status = ResumeDecodingPriorityPayload(&subset);
198 break;
199
200 case Http2FrameType::RST_STREAM:
201 status = ResumeDecodingRstStreamPayload(&subset);
202 break;
203
204 case Http2FrameType::SETTINGS:
205 status = ResumeDecodingSettingsPayload(&subset);
206 break;
207
208 case Http2FrameType::PUSH_PROMISE:
209 status = ResumeDecodingPushPromisePayload(&subset);
210 break;
211
212 case Http2FrameType::PING:
213 status = ResumeDecodingPingPayload(&subset);
214 break;
215
216 case Http2FrameType::GOAWAY:
217 status = ResumeDecodingGoAwayPayload(&subset);
218 break;
219
220 case Http2FrameType::WINDOW_UPDATE:
221 status = ResumeDecodingWindowUpdatePayload(&subset);
222 break;
223
224 case Http2FrameType::CONTINUATION:
225 status = ResumeDecodingContinuationPayload(&subset);
226 break;
227
228 case Http2FrameType::ALTSVC:
229 status = ResumeDecodingAltSvcPayload(&subset);
230 break;
231
232 case Http2FrameType::PRIORITY_UPDATE:
233 status = ResumeDecodingPriorityUpdatePayload(&subset);
234 break;
235
236 default:
237 status = ResumeDecodingUnknownPayload(&subset);
238 break;
239 }
240
241 if (status == DecodeStatus::kDecodeDone) {
242 state_ = State::kStartDecodingHeader;
243 return status;
244 } else if (status == DecodeStatus::kDecodeInProgress) {
245 return status;
246 } else {
247 state_ = State::kDiscardPayload;
248 return status;
249 }
250 }
251
252 // Clear any of the flags in the frame header that aren't set in valid_flags.
RetainFlags(uint8_t valid_flags)253 void Http2FrameDecoder::RetainFlags(uint8_t valid_flags) {
254 frame_decoder_state_.RetainFlags(valid_flags);
255 }
256
257 // Clear all of the flags in the frame header; for use with frame types that
258 // don't define any flags, such as WINDOW_UPDATE.
ClearFlags()259 void Http2FrameDecoder::ClearFlags() { frame_decoder_state_.ClearFlags(); }
260
StartDecodingAltSvcPayload(DecodeBuffer * db)261 DecodeStatus Http2FrameDecoder::StartDecodingAltSvcPayload(DecodeBuffer* db) {
262 ClearFlags();
263 return altsvc_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
264 db);
265 }
ResumeDecodingAltSvcPayload(DecodeBuffer * db)266 DecodeStatus Http2FrameDecoder::ResumeDecodingAltSvcPayload(DecodeBuffer* db) {
267 // The frame is not paddable.
268 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
269 frame_decoder_state_.remaining_payload());
270 return altsvc_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
271 db);
272 }
273
StartDecodingContinuationPayload(DecodeBuffer * db)274 DecodeStatus Http2FrameDecoder::StartDecodingContinuationPayload(
275 DecodeBuffer* db) {
276 RetainFlags(Http2FrameFlag::END_HEADERS);
277 return continuation_payload_decoder_.StartDecodingPayload(
278 &frame_decoder_state_, db);
279 }
ResumeDecodingContinuationPayload(DecodeBuffer * db)280 DecodeStatus Http2FrameDecoder::ResumeDecodingContinuationPayload(
281 DecodeBuffer* db) {
282 // The frame is not paddable.
283 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
284 frame_decoder_state_.remaining_payload());
285 return continuation_payload_decoder_.ResumeDecodingPayload(
286 &frame_decoder_state_, db);
287 }
288
StartDecodingDataPayload(DecodeBuffer * db)289 DecodeStatus Http2FrameDecoder::StartDecodingDataPayload(DecodeBuffer* db) {
290 RetainFlags(Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED);
291 return data_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db);
292 }
ResumeDecodingDataPayload(DecodeBuffer * db)293 DecodeStatus Http2FrameDecoder::ResumeDecodingDataPayload(DecodeBuffer* db) {
294 return data_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db);
295 }
296
StartDecodingGoAwayPayload(DecodeBuffer * db)297 DecodeStatus Http2FrameDecoder::StartDecodingGoAwayPayload(DecodeBuffer* db) {
298 ClearFlags();
299 return goaway_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
300 db);
301 }
ResumeDecodingGoAwayPayload(DecodeBuffer * db)302 DecodeStatus Http2FrameDecoder::ResumeDecodingGoAwayPayload(DecodeBuffer* db) {
303 // The frame is not paddable.
304 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
305 frame_decoder_state_.remaining_payload());
306 return goaway_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
307 db);
308 }
309
StartDecodingHeadersPayload(DecodeBuffer * db)310 DecodeStatus Http2FrameDecoder::StartDecodingHeadersPayload(DecodeBuffer* db) {
311 RetainFlags(Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS |
312 Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY);
313 return headers_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
314 db);
315 }
ResumeDecodingHeadersPayload(DecodeBuffer * db)316 DecodeStatus Http2FrameDecoder::ResumeDecodingHeadersPayload(DecodeBuffer* db) {
317 QUICHE_DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(),
318 frame_header().payload_length);
319 return headers_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
320 db);
321 }
322
StartDecodingPingPayload(DecodeBuffer * db)323 DecodeStatus Http2FrameDecoder::StartDecodingPingPayload(DecodeBuffer* db) {
324 RetainFlags(Http2FrameFlag::ACK);
325 return ping_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db);
326 }
ResumeDecodingPingPayload(DecodeBuffer * db)327 DecodeStatus Http2FrameDecoder::ResumeDecodingPingPayload(DecodeBuffer* db) {
328 // The frame is not paddable.
329 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
330 frame_decoder_state_.remaining_payload());
331 return ping_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db);
332 }
333
StartDecodingPriorityPayload(DecodeBuffer * db)334 DecodeStatus Http2FrameDecoder::StartDecodingPriorityPayload(DecodeBuffer* db) {
335 ClearFlags();
336 return priority_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
337 db);
338 }
ResumeDecodingPriorityPayload(DecodeBuffer * db)339 DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityPayload(
340 DecodeBuffer* db) {
341 // The frame is not paddable.
342 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
343 frame_decoder_state_.remaining_payload());
344 return priority_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
345 db);
346 }
347
StartDecodingPriorityUpdatePayload(DecodeBuffer * db)348 DecodeStatus Http2FrameDecoder::StartDecodingPriorityUpdatePayload(
349 DecodeBuffer* db) {
350 ClearFlags();
351 return priority_payload_update_decoder_.StartDecodingPayload(
352 &frame_decoder_state_, db);
353 }
ResumeDecodingPriorityUpdatePayload(DecodeBuffer * db)354 DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityUpdatePayload(
355 DecodeBuffer* db) {
356 // The frame is not paddable.
357 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
358 frame_decoder_state_.remaining_payload());
359 return priority_payload_update_decoder_.ResumeDecodingPayload(
360 &frame_decoder_state_, db);
361 }
362
StartDecodingPushPromisePayload(DecodeBuffer * db)363 DecodeStatus Http2FrameDecoder::StartDecodingPushPromisePayload(
364 DecodeBuffer* db) {
365 RetainFlags(Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED);
366 return push_promise_payload_decoder_.StartDecodingPayload(
367 &frame_decoder_state_, db);
368 }
ResumeDecodingPushPromisePayload(DecodeBuffer * db)369 DecodeStatus Http2FrameDecoder::ResumeDecodingPushPromisePayload(
370 DecodeBuffer* db) {
371 QUICHE_DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(),
372 frame_header().payload_length);
373 return push_promise_payload_decoder_.ResumeDecodingPayload(
374 &frame_decoder_state_, db);
375 }
376
StartDecodingRstStreamPayload(DecodeBuffer * db)377 DecodeStatus Http2FrameDecoder::StartDecodingRstStreamPayload(
378 DecodeBuffer* db) {
379 ClearFlags();
380 return rst_stream_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
381 db);
382 }
ResumeDecodingRstStreamPayload(DecodeBuffer * db)383 DecodeStatus Http2FrameDecoder::ResumeDecodingRstStreamPayload(
384 DecodeBuffer* db) {
385 // The frame is not paddable.
386 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
387 frame_decoder_state_.remaining_payload());
388 return rst_stream_payload_decoder_.ResumeDecodingPayload(
389 &frame_decoder_state_, db);
390 }
391
StartDecodingSettingsPayload(DecodeBuffer * db)392 DecodeStatus Http2FrameDecoder::StartDecodingSettingsPayload(DecodeBuffer* db) {
393 RetainFlags(Http2FrameFlag::ACK);
394 return settings_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
395 db);
396 }
ResumeDecodingSettingsPayload(DecodeBuffer * db)397 DecodeStatus Http2FrameDecoder::ResumeDecodingSettingsPayload(
398 DecodeBuffer* db) {
399 // The frame is not paddable.
400 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
401 frame_decoder_state_.remaining_payload());
402 return settings_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
403 db);
404 }
405
StartDecodingUnknownPayload(DecodeBuffer * db)406 DecodeStatus Http2FrameDecoder::StartDecodingUnknownPayload(DecodeBuffer* db) {
407 // We don't known what type of frame this is, so we don't know which flags
408 // are valid, so we don't touch them.
409 return unknown_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
410 db);
411 }
ResumeDecodingUnknownPayload(DecodeBuffer * db)412 DecodeStatus Http2FrameDecoder::ResumeDecodingUnknownPayload(DecodeBuffer* db) {
413 // We don't known what type of frame this is, so we treat it as not paddable.
414 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
415 frame_decoder_state_.remaining_payload());
416 return unknown_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
417 db);
418 }
419
StartDecodingWindowUpdatePayload(DecodeBuffer * db)420 DecodeStatus Http2FrameDecoder::StartDecodingWindowUpdatePayload(
421 DecodeBuffer* db) {
422 ClearFlags();
423 return window_update_payload_decoder_.StartDecodingPayload(
424 &frame_decoder_state_, db);
425 }
ResumeDecodingWindowUpdatePayload(DecodeBuffer * db)426 DecodeStatus Http2FrameDecoder::ResumeDecodingWindowUpdatePayload(
427 DecodeBuffer* db) {
428 // The frame is not paddable.
429 QUICHE_DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
430 frame_decoder_state_.remaining_payload());
431 return window_update_payload_decoder_.ResumeDecodingPayload(
432 &frame_decoder_state_, db);
433 }
434
DiscardPayload(DecodeBuffer * db)435 DecodeStatus Http2FrameDecoder::DiscardPayload(DecodeBuffer* db) {
436 QUICHE_DVLOG(2) << "remaining_payload="
437 << frame_decoder_state_.remaining_payload_
438 << "; remaining_padding="
439 << frame_decoder_state_.remaining_padding_;
440 frame_decoder_state_.remaining_payload_ +=
441 frame_decoder_state_.remaining_padding_;
442 frame_decoder_state_.remaining_padding_ = 0;
443 const size_t avail = frame_decoder_state_.AvailablePayload(db);
444 QUICHE_DVLOG(2) << "avail=" << avail;
445 if (avail > 0) {
446 frame_decoder_state_.ConsumePayload(avail);
447 db->AdvanceCursor(avail);
448 }
449 if (frame_decoder_state_.remaining_payload_ == 0) {
450 state_ = State::kStartDecodingHeader;
451 return DecodeStatus::kDecodeDone;
452 }
453 return DecodeStatus::kDecodeInProgress;
454 }
455
456 } // namespace http2
457