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

Side by Side Diff: net/http2/hpack/decoder/hpack_entry_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/hpack/decoder/hpack_entry_decoder.h"
6
7 #include <stddef.h>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11
12 namespace net {
13 namespace {
14 // Converts calls from HpackStringDecoder when decoding a header name into the
15 // appropriate HpackEntryDecoderListener::OnName* calls.
16 class NameDecoderListener {
17 public:
18 explicit NameDecoderListener(HpackEntryDecoderListener* listener)
19 : listener_(listener) {}
20 bool OnStringStart(bool huffman_encoded, size_t len) {
21 listener_->OnNameStart(huffman_encoded, len);
22 return true;
23 }
24 void OnStringData(const char* data, size_t len) {
25 listener_->OnNameData(data, len);
26 }
27 void OnStringEnd() { listener_->OnNameEnd(); }
28
29 private:
30 HpackEntryDecoderListener* listener_;
31 };
32
33 // Converts calls from HpackStringDecoder when decoding a header value into
34 // the appropriate HpackEntryDecoderListener::OnValue* calls.
35 class ValueDecoderListener {
36 public:
37 explicit ValueDecoderListener(HpackEntryDecoderListener* listener)
38 : listener_(listener) {}
39 bool OnStringStart(bool huffman_encoded, size_t len) {
40 listener_->OnValueStart(huffman_encoded, len);
41 return true;
42 }
43 void OnStringData(const char* data, size_t len) {
44 listener_->OnValueData(data, len);
45 }
46 void OnStringEnd() { listener_->OnValueEnd(); }
47
48 private:
49 HpackEntryDecoderListener* listener_;
50 };
51 } // namespace
52
53 // Only call Resume if the previous call (Start or Resume) returned
54 // kDecodeInProgress; Resume is also called from Start when it has succeeded
55 // in decoding the entry type and its varint.
56 DecodeStatus HpackEntryDecoder::Resume(DecodeBuffer* db,
57 HpackEntryDecoderListener* listener) {
58 DCHECK(db != nullptr);
59 DCHECK(listener != nullptr);
60
61 DecodeStatus status;
62
63 do {
64 switch (state_) {
65 case EntryDecoderState::kResumeDecodingType:
66 // entry_type_decoder_ returned kDecodeInProgress when last called.
67 DVLOG(1) << "kResumeDecodingType: db->Remaining=" << db->Remaining();
68 status = entry_type_decoder_.Resume(db);
69 if (status != DecodeStatus::kDecodeDone) {
70 return status;
71 }
72 state_ = EntryDecoderState::kDecodedType;
73 // FALLTHROUGH_INTENDED
74
75 case EntryDecoderState::kDecodedType:
76 // entry_type_decoder_ returned kDecodeDone, now need to decide how
77 // to proceed.
78 DVLOG(1) << "kDecodedType: db->Remaining=" << db->Remaining();
79 if (DispatchOnType(listener)) {
80 // All done.
81 return DecodeStatus::kDecodeDone;
82 }
83 continue;
84
85 case EntryDecoderState::kStartDecodingName:
86 DVLOG(1) << "kStartDecodingName: db->Remaining=" << db->Remaining();
87 {
88 NameDecoderListener ncb(listener);
89 status = string_decoder_.Start(db, &ncb);
90 }
91 if (status != DecodeStatus::kDecodeDone) {
92 // On the assumption that the status is kDecodeInProgress, set
93 // state_ accordingly; unnecessary if status is kDecodeError, but
94 // that will only happen if the varint encoding the name's length
95 // is too long.
96 state_ = EntryDecoderState::kResumeDecodingName;
97 return status;
98 }
99 state_ = EntryDecoderState::kStartDecodingValue;
100 // FALLTHROUGH_INTENDED
101
102 case EntryDecoderState::kStartDecodingValue:
103 DVLOG(1) << "kStartDecodingValue: db->Remaining=" << db->Remaining();
104 {
105 ValueDecoderListener vcb(listener);
106 status = string_decoder_.Start(db, &vcb);
107 }
108 if (status == DecodeStatus::kDecodeDone) {
109 // Done with decoding the literal value, so we've reached the
110 // end of the header entry.
111 return status;
112 }
113 // On the assumption that the status is kDecodeInProgress, set
114 // state_ accordingly; unnecessary if status is kDecodeError, but
115 // that will only happen if the varint encoding the value's length
116 // is too long.
117 state_ = EntryDecoderState::kResumeDecodingValue;
118 return status;
119
120 case EntryDecoderState::kResumeDecodingName:
121 // The literal name was split across decode buffers.
122 DVLOG(1) << "kResumeDecodingName: db->Remaining=" << db->Remaining();
123 {
124 NameDecoderListener ncb(listener);
125 status = string_decoder_.Resume(db, &ncb);
126 }
127 if (status != DecodeStatus::kDecodeDone) {
128 // On the assumption that the status is kDecodeInProgress, set
129 // state_ accordingly; unnecessary if status is kDecodeError, but
130 // that will only happen if the varint encoding the name's length
131 // is too long.
132 state_ = EntryDecoderState::kResumeDecodingName;
133 return status;
134 }
135 state_ = EntryDecoderState::kStartDecodingValue;
136 break;
137
138 case EntryDecoderState::kResumeDecodingValue:
139 // The literal value was split across decode buffers.
140 DVLOG(1) << "kResumeDecodingValue: db->Remaining=" << db->Remaining();
141 {
142 ValueDecoderListener vcb(listener);
143 status = string_decoder_.Resume(db, &vcb);
144 }
145 if (status == DecodeStatus::kDecodeDone) {
146 // Done with decoding the value, therefore the entry as a whole.
147 return status;
148 }
149 // On the assumption that the status is kDecodeInProgress, set
150 // state_ accordingly; unnecessary if status is kDecodeError, but
151 // that will only happen if the varint encoding the value's length
152 // is too long.
153 state_ = EntryDecoderState::kResumeDecodingValue;
154 return status;
155 }
156 } while (true);
157 }
158
159 bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) {
160 const HpackEntryType entry_type = entry_type_decoder_.entry_type();
161 const uint32_t varint = entry_type_decoder_.varint();
162 switch (entry_type) {
163 case HpackEntryType::kIndexedHeader:
164 // The entry consists solely of the entry type and varint. See:
165 // http://httpwg.org/specs/rfc7541.html#indexed.header.representation
166 listener->OnIndexedHeader(varint);
167 return true;
168
169 case HpackEntryType::kIndexedLiteralHeader:
170 case HpackEntryType::kUnindexedLiteralHeader:
171 case HpackEntryType::kNeverIndexedLiteralHeader:
172 // The entry has a literal value, and if the varint is zero also has a
173 // literal name preceding the value. See:
174 // http://httpwg.org/specs/rfc7541.html#literal.header.representation
175 listener->OnStartLiteralHeader(entry_type, varint);
176 if (varint == 0) {
177 state_ = EntryDecoderState::kStartDecodingName;
178 } else {
179 state_ = EntryDecoderState::kStartDecodingValue;
180 }
181 return false;
182
183 case HpackEntryType::kDynamicTableSizeUpdate:
184 // The entry consists solely of the entry type and varint. FWIW, I've
185 // never seen this type of entry in production (primarily browser
186 // traffic) so if you're designing an HPACK successor someday, consider
187 // dropping it or giving it a much longer prefix. See:
188 // http://httpwg.org/specs/rfc7541.html#encoding.context.update
189 listener->OnDynamicTableSizeUpdate(varint);
190 return true;
191 }
192
193 NOTREACHED();
194 return true;
195 }
196
197 void HpackEntryDecoder::OutputDebugString(std::ostream& out) const {
198 out << "HpackEntryDecoder(state=" << state_ << ", " << entry_type_decoder_
199 << ", " << string_decoder_ << ")";
200 }
201
202 std::string HpackEntryDecoder::DebugString() const {
203 std::stringstream s;
204 s << *this;
205 return s.str();
206 }
207
208 std::ostream& operator<<(std::ostream& out, const HpackEntryDecoder& v) {
209 v.OutputDebugString(out);
210 return out;
211 }
212
213 std::ostream& operator<<(std::ostream& out,
214 HpackEntryDecoder::EntryDecoderState state) {
215 typedef HpackEntryDecoder::EntryDecoderState EntryDecoderState;
216 switch (state) {
217 case EntryDecoderState::kResumeDecodingType:
218 return out << "kResumeDecodingType";
219 case EntryDecoderState::kDecodedType:
220 return out << "kDecodedType";
221 case EntryDecoderState::kStartDecodingName:
222 return out << "kStartDecodingName";
223 case EntryDecoderState::kResumeDecodingName:
224 return out << "kResumeDecodingName";
225 case EntryDecoderState::kStartDecodingValue:
226 return out << "kStartDecodingValue";
227 case EntryDecoderState::kResumeDecodingValue:
228 return out << "kResumeDecodingValue";
229 }
230 return out << static_cast<int>(state);
231 }
232
233 } // namespace net
OLDNEW
« no previous file with comments | « net/http2/hpack/decoder/hpack_entry_decoder.h ('k') | net/http2/hpack/decoder/hpack_entry_decoder_listener.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698