blob: ff6758c3729aed0734920df4cc5ab2f8c133bccf [file] [log] [blame]
bncbea13b82021-01-08 08:46:09 -08001// Copyright 2020 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 "http2/decoder/payload_decoders/priority_update_payload_decoder.h"
6
7#include <stddef.h>
8
bnc92d1f952022-01-11 10:52:05 -08009#include "absl/base/macros.h"
bncbea13b82021-01-08 08:46:09 -080010#include "http2/decoder/decode_buffer.h"
11#include "http2/decoder/http2_frame_decoder_listener.h"
12#include "http2/http2_constants.h"
13#include "http2/http2_structures.h"
14#include "http2/platform/api/http2_bug_tracker.h"
15#include "http2/platform/api/http2_logging.h"
bncbea13b82021-01-08 08:46:09 -080016
17namespace http2 {
18
19std::ostream& operator<<(std::ostream& out,
20 PriorityUpdatePayloadDecoder::PayloadState v) {
21 switch (v) {
22 case PriorityUpdatePayloadDecoder::PayloadState::kStartDecodingFixedFields:
23 return out << "kStartDecodingFixedFields";
24 case PriorityUpdatePayloadDecoder::PayloadState::kResumeDecodingFixedFields:
25 return out << "kResumeDecodingFixedFields";
26 case PriorityUpdatePayloadDecoder::PayloadState::kHandleFixedFieldsStatus:
27 return out << "kHandleFixedFieldsStatus";
28 case PriorityUpdatePayloadDecoder::PayloadState::kReadPriorityFieldValue:
29 return out << "kReadPriorityFieldValue";
30 }
31 // Since the value doesn't come over the wire, only a programming bug should
32 // result in reaching this point.
33 int unknown = static_cast<int>(v);
QUICHE team12823432021-03-17 16:01:01 -070034 HTTP2_BUG(http2_bug_173_1)
QUICHE team0ec81ca2021-03-11 09:29:06 -080035 << "Invalid PriorityUpdatePayloadDecoder::PayloadState: " << unknown;
bncbea13b82021-01-08 08:46:09 -080036 return out << "PriorityUpdatePayloadDecoder::PayloadState(" << unknown << ")";
37}
38
39DecodeStatus PriorityUpdatePayloadDecoder::StartDecodingPayload(
40 FrameDecoderState* state,
41 DecodeBuffer* db) {
42 HTTP2_DVLOG(2) << "PriorityUpdatePayloadDecoder::StartDecodingPayload: "
43 << state->frame_header();
vasilvvafcc3172021-02-02 12:01:07 -080044 QUICHE_DCHECK_EQ(Http2FrameType::PRIORITY_UPDATE, state->frame_header().type);
45 QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
46 QUICHE_DCHECK_EQ(0, state->frame_header().flags);
bncbea13b82021-01-08 08:46:09 -080047
48 state->InitializeRemainders();
49 payload_state_ = PayloadState::kStartDecodingFixedFields;
50 return ResumeDecodingPayload(state, db);
51}
52
53DecodeStatus PriorityUpdatePayloadDecoder::ResumeDecodingPayload(
54 FrameDecoderState* state,
55 DecodeBuffer* db) {
56 HTTP2_DVLOG(2) << "PriorityUpdatePayloadDecoder::ResumeDecodingPayload: "
57 "remaining_payload="
58 << state->remaining_payload()
59 << ", db->Remaining=" << db->Remaining();
60
61 const Http2FrameHeader& frame_header = state->frame_header();
vasilvvafcc3172021-02-02 12:01:07 -080062 QUICHE_DCHECK_EQ(Http2FrameType::PRIORITY_UPDATE, frame_header.type);
63 QUICHE_DCHECK_LE(db->Remaining(), frame_header.payload_length);
64 QUICHE_DCHECK_NE(PayloadState::kHandleFixedFieldsStatus, payload_state_);
bncbea13b82021-01-08 08:46:09 -080065
66 // |status| has to be initialized to some value to avoid compiler error in
67 // case PayloadState::kHandleFixedFieldsStatus below, but value does not
vasilvvafcc3172021-02-02 12:01:07 -080068 // matter, see QUICHE_DCHECK_NE above.
bncbea13b82021-01-08 08:46:09 -080069 DecodeStatus status = DecodeStatus::kDecodeError;
70 size_t avail;
71 while (true) {
72 HTTP2_DVLOG(2)
73 << "PriorityUpdatePayloadDecoder::ResumeDecodingPayload payload_state_="
74 << payload_state_;
75 switch (payload_state_) {
76 case PayloadState::kStartDecodingFixedFields:
77 status = state->StartDecodingStructureInPayload(
78 &priority_update_fields_, db);
bnc92d1f952022-01-11 10:52:05 -080079 ABSL_FALLTHROUGH_INTENDED;
bncbea13b82021-01-08 08:46:09 -080080
81 case PayloadState::kHandleFixedFieldsStatus:
82 if (status == DecodeStatus::kDecodeDone) {
83 state->listener()->OnPriorityUpdateStart(frame_header,
84 priority_update_fields_);
85 } else {
86 // Not done decoding the structure. Either we've got more payload
87 // to decode, or we've run out because the payload is too short,
88 // in which case OnFrameSizeError will have already been called.
vasilvvafcc3172021-02-02 12:01:07 -080089 QUICHE_DCHECK((status == DecodeStatus::kDecodeInProgress &&
90 state->remaining_payload() > 0) ||
91 (status == DecodeStatus::kDecodeError &&
92 state->remaining_payload() == 0))
bncbea13b82021-01-08 08:46:09 -080093 << "\n status=" << status
94 << "; remaining_payload=" << state->remaining_payload();
95 payload_state_ = PayloadState::kResumeDecodingFixedFields;
96 return status;
97 }
bnc92d1f952022-01-11 10:52:05 -080098 ABSL_FALLTHROUGH_INTENDED;
bncbea13b82021-01-08 08:46:09 -080099
100 case PayloadState::kReadPriorityFieldValue:
101 // Anything left in the decode buffer is the Priority Field Value.
102 avail = db->Remaining();
103 if (avail > 0) {
104 state->listener()->OnPriorityUpdatePayload(db->cursor(), avail);
105 db->AdvanceCursor(avail);
106 state->ConsumePayload(avail);
107 }
108 if (state->remaining_payload() > 0) {
109 payload_state_ = PayloadState::kReadPriorityFieldValue;
110 return DecodeStatus::kDecodeInProgress;
111 }
112 state->listener()->OnPriorityUpdateEnd();
113 return DecodeStatus::kDecodeDone;
114
115 case PayloadState::kResumeDecodingFixedFields:
116 status = state->ResumeDecodingStructureInPayload(
117 &priority_update_fields_, db);
118 payload_state_ = PayloadState::kHandleFixedFieldsStatus;
119 continue;
120 }
QUICHE team12823432021-03-17 16:01:01 -0700121 HTTP2_BUG(http2_bug_173_2) << "PayloadState: " << payload_state_;
bncbea13b82021-01-08 08:46:09 -0800122 }
123}
124
125} // namespace http2