xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/decoder/frame_decoder_state.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/frame_decoder_state.h"
6 
7 namespace http2 {
8 
ReadPadLength(DecodeBuffer * db,bool report_pad_length)9 DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db,
10                                               bool report_pad_length) {
11   QUICHE_DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining()
12                   << "; payload_length=" << frame_header().payload_length;
13   QUICHE_DCHECK(IsPaddable());
14   QUICHE_DCHECK(frame_header().IsPadded());
15 
16   // Pad Length is always at the start of the frame, so remaining_payload_
17   // should equal payload_length at this point.
18   const uint32_t total_payload = frame_header().payload_length;
19   QUICHE_DCHECK_EQ(total_payload, remaining_payload_);
20   QUICHE_DCHECK_EQ(0u, remaining_padding_);
21 
22   if (db->HasData()) {
23     const uint32_t pad_length = db->DecodeUInt8();
24     const uint32_t total_padding = pad_length + 1;
25     if (total_padding <= total_payload) {
26       remaining_padding_ = pad_length;
27       remaining_payload_ = total_payload - total_padding;
28       if (report_pad_length) {
29         listener()->OnPadLength(pad_length);
30       }
31       return DecodeStatus::kDecodeDone;
32     }
33     const uint32_t missing_length = total_padding - total_payload;
34     // To allow for the possibility of recovery, record the number of
35     // remaining bytes of the frame's payload (invalid though it is)
36     // in remaining_payload_.
37     remaining_payload_ = total_payload - 1;  // 1 for sizeof(Pad Length).
38     remaining_padding_ = 0;
39     listener()->OnPaddingTooLong(frame_header(), missing_length);
40     return DecodeStatus::kDecodeError;
41   }
42 
43   if (total_payload == 0) {
44     remaining_payload_ = 0;
45     remaining_padding_ = 0;
46     listener()->OnPaddingTooLong(frame_header(), 1);
47     return DecodeStatus::kDecodeError;
48   }
49   // Need to wait for another buffer.
50   return DecodeStatus::kDecodeInProgress;
51 }
52 
SkipPadding(DecodeBuffer * db)53 bool FrameDecoderState::SkipPadding(DecodeBuffer* db) {
54   QUICHE_DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_
55                   << ", db->Remaining=" << db->Remaining()
56                   << ", header: " << frame_header();
57   QUICHE_DCHECK_EQ(remaining_payload_, 0u);
58   QUICHE_DCHECK(IsPaddable()) << "header: " << frame_header();
59   QUICHE_DCHECK(remaining_padding_ == 0 || frame_header().IsPadded())
60       << "remaining_padding_=" << remaining_padding_
61       << ", header: " << frame_header();
62   const size_t avail = AvailablePadding(db);
63   if (avail > 0) {
64     listener()->OnPadding(db->cursor(), avail);
65     db->AdvanceCursor(avail);
66     remaining_padding_ -= avail;
67   }
68   return remaining_padding_ == 0;
69 }
70 
ReportFrameSizeError()71 DecodeStatus FrameDecoderState::ReportFrameSizeError() {
72   QUICHE_DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: "
73                   << " remaining_payload_=" << remaining_payload_
74                   << "; remaining_padding_=" << remaining_padding_
75                   << ", header: " << frame_header();
76   listener()->OnFrameSizeError(frame_header());
77   return DecodeStatus::kDecodeError;
78 }
79 
80 }  // namespace http2
81