xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/decoder/http2_frame_decoder.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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