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

Side by Side Diff: net/http2/decoder/payload_decoders/push_promise_payload_decoder.cc

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
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 #include "net/http2/decoder/payload_decoders/push_promise_payload_decoder.h"
6
7 #include <stddef.h>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "net/http2/decoder/decode_buffer.h"
12 #include "net/http2/decoder/http2_frame_decoder_listener.h"
13 #include "net/http2/http2_constants.h"
14 #include "net/http2/http2_structures.h"
15 #include "net/http2/tools/http2_bug_tracker.h"
16
17 namespace net {
18
19 std::ostream& operator<<(std::ostream& out,
20 PushPromisePayloadDecoder::PayloadState v) {
21 switch (v) {
22 case PushPromisePayloadDecoder::PayloadState::kReadPadLength:
23 return out << "kReadPadLength";
24 case PushPromisePayloadDecoder::PayloadState::
25 kStartDecodingPushPromiseFields:
26 return out << "kStartDecodingPushPromiseFields";
27 case PushPromisePayloadDecoder::PayloadState::kReadPayload:
28 return out << "kReadPayload";
29 case PushPromisePayloadDecoder::PayloadState::kSkipPadding:
30 return out << "kSkipPadding";
31 case PushPromisePayloadDecoder::PayloadState::
32 kResumeDecodingPushPromiseFields:
33 return out << "kResumeDecodingPushPromiseFields";
34 }
35 return out << static_cast<int>(v);
36 }
37
38 DecodeStatus PushPromisePayloadDecoder::StartDecodingPayload(
39 FrameDecoderState* state,
40 DecodeBuffer* db) {
41 const Http2FrameHeader& frame_header = state->frame_header();
42 const uint32_t total_length = frame_header.payload_length;
43
44 DVLOG(2) << "PushPromisePayloadDecoder::StartDecodingPayload: "
45 << frame_header;
46
47 DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type);
48 DCHECK_LE(db->Remaining(), total_length);
49 DCHECK_EQ(
50 0, frame_header.flags &
51 ~(Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED));
52
53 if (!frame_header.IsPadded()) {
54 // If it turns out that PUSH_PROMISE frames without padding are sufficiently
55 // common, and that they are usually short enough that they fit entirely
56 // into one DecodeBuffer, we can detect that here and implement a special
57 // case, avoiding the state machine in ResumeDecodingPayload.
58 payload_state_ = PayloadState::kStartDecodingPushPromiseFields;
59 } else {
60 payload_state_ = PayloadState::kReadPadLength;
61 }
62 state->InitializeRemainders();
63 return ResumeDecodingPayload(state, db);
64 }
65
66 DecodeStatus PushPromisePayloadDecoder::ResumeDecodingPayload(
67 FrameDecoderState* state,
68 DecodeBuffer* db) {
69 DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload"
70 << " remaining_payload=" << state->remaining_payload()
71 << " db->Remaining=" << db->Remaining();
72
73 const Http2FrameHeader& frame_header = state->frame_header();
74 DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type);
75 DCHECK_LE(state->remaining_payload(), frame_header.payload_length);
76 DCHECK_LE(db->Remaining(), frame_header.payload_length);
77
78 DecodeStatus status;
79 while (true) {
80 DVLOG(2)
81 << "PushPromisePayloadDecoder::ResumeDecodingPayload payload_state_="
82 << payload_state_;
83 switch (payload_state_) {
84 case PayloadState::kReadPadLength:
85 DCHECK_EQ(state->remaining_payload(), frame_header.payload_length);
86 // ReadPadLength handles the OnPadLength callback, and updating the
87 // remaining_payload and remaining_padding fields. If the amount of
88 // padding is too large to fit in the frame's payload, ReadPadLength
89 // instead calls OnPaddingTooLong and returns kDecodeError.
90 // Suppress the call to OnPadLength because we haven't yet called
91 // OnPushPromiseStart, which needs to wait until we've decoded the
92 // Promised Stream ID.
93 status = state->ReadPadLength(db, /*report_pad_length*/ false);
94 if (status != DecodeStatus::kDecodeDone) {
95 payload_state_ = PayloadState::kReadPadLength;
96 return status;
97 }
98 // FALLTHROUGH_INTENDED
99
100 case PayloadState::kStartDecodingPushPromiseFields:
101 status =
102 state->StartDecodingStructureInPayload(&push_promise_fields_, db);
103 if (status != DecodeStatus::kDecodeDone) {
104 payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
105 return status;
106 }
107 // Finished decoding the Promised Stream ID. Can now tell the listener
108 // that we're starting to decode a PUSH_PROMISE frame.
109 ReportPushPromise(state);
110 // FALLTHROUGH_INTENDED
111
112 case PayloadState::kReadPayload:
113 DCHECK_LT(state->remaining_payload(), frame_header.payload_length);
114 DCHECK_LE(state->remaining_payload(),
115 frame_header.payload_length -
116 Http2PushPromiseFields::EncodedSize());
117 DCHECK_LE(
118 state->remaining_payload(),
119 frame_header.payload_length -
120 Http2PushPromiseFields::EncodedSize() -
121 (frame_header.IsPadded() ? (1 + state->remaining_padding())
122 : 0));
123 {
124 size_t avail = state->AvailablePayload(db);
125 state->listener()->OnHpackFragment(db->cursor(), avail);
126 db->AdvanceCursor(avail);
127 state->ConsumePayload(avail);
128 }
129 if (state->remaining_payload() > 0) {
130 payload_state_ = PayloadState::kReadPayload;
131 return DecodeStatus::kDecodeInProgress;
132 }
133 // FALLTHROUGH_INTENDED
134
135 case PayloadState::kSkipPadding:
136 // SkipPadding handles the OnPadding callback.
137 if (state->SkipPadding(db)) {
138 state->listener()->OnPushPromiseEnd();
139 return DecodeStatus::kDecodeDone;
140 }
141 payload_state_ = PayloadState::kSkipPadding;
142 return DecodeStatus::kDecodeInProgress;
143
144 case PayloadState::kResumeDecodingPushPromiseFields:
145 status =
146 state->ResumeDecodingStructureInPayload(&push_promise_fields_, db);
147 if (status == DecodeStatus::kDecodeDone) {
148 // Finished decoding the Promised Stream ID. Can now tell the listener
149 // that we're starting to decode a PUSH_PROMISE frame.
150 ReportPushPromise(state);
151 payload_state_ = PayloadState::kReadPayload;
152 continue;
153 }
154 payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
155 return status;
156 }
157 HTTP2_BUG << "PayloadState: " << payload_state_;
158 }
159 }
160
161 void PushPromisePayloadDecoder::ReportPushPromise(FrameDecoderState* state) {
162 const Http2FrameHeader& frame_header = state->frame_header();
163 if (frame_header.IsPadded()) {
164 state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_,
165 1 + state->remaining_padding());
166 } else {
167 state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_,
168 0);
169 }
170 }
171
172 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698