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

Side by Side Diff: net/quic/crypto/crypto_framer.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months 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
« no previous file with comments | « net/quic/crypto/crypto_framer.h ('k') | net/quic/crypto/crypto_framer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/quic/crypto/crypto_framer.h"
6
7 #include <memory>
8
9 #include "base/strings/stringprintf.h"
10 #include "net/quic/crypto/crypto_protocol.h"
11 #include "net/quic/quic_data_reader.h"
12 #include "net/quic/quic_data_writer.h"
13
14 using base::StringPiece;
15 using std::pair;
16 using std::vector;
17
18 namespace net {
19
20 namespace {
21
22 const size_t kQuicTagSize = sizeof(uint32_t);
23 const size_t kCryptoEndOffsetSize = sizeof(uint32_t);
24 const size_t kNumEntriesSize = sizeof(uint16_t);
25
26 // OneShotVisitor is a framer visitor that records a single handshake message.
27 class OneShotVisitor : public CryptoFramerVisitorInterface {
28 public:
29 OneShotVisitor() : error_(false) {}
30
31 void OnError(CryptoFramer* framer) override { error_ = true; }
32
33 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
34 out_.reset(new CryptoHandshakeMessage(message));
35 }
36
37 bool error() const { return error_; }
38
39 CryptoHandshakeMessage* release() { return out_.release(); }
40
41 private:
42 std::unique_ptr<CryptoHandshakeMessage> out_;
43 bool error_;
44 };
45
46 } // namespace
47
48 CryptoFramer::CryptoFramer()
49 : visitor_(nullptr), error_detail_(""), num_entries_(0), values_len_(0) {
50 Clear();
51 }
52
53 CryptoFramer::~CryptoFramer() {}
54
55 // static
56 CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) {
57 OneShotVisitor visitor;
58 CryptoFramer framer;
59
60 framer.set_visitor(&visitor);
61 if (!framer.ProcessInput(in) || visitor.error() ||
62 framer.InputBytesRemaining()) {
63 return nullptr;
64 }
65
66 return visitor.release();
67 }
68
69 bool CryptoFramer::ProcessInput(StringPiece input) {
70 DCHECK_EQ(QUIC_NO_ERROR, error_);
71 if (error_ != QUIC_NO_ERROR) {
72 return false;
73 }
74 error_ = Process(input);
75 if (error_ != QUIC_NO_ERROR) {
76 DCHECK(!error_detail_.empty());
77 visitor_->OnError(this);
78 return false;
79 }
80
81 return true;
82 }
83
84 // static
85 QuicData* CryptoFramer::ConstructHandshakeMessage(
86 const CryptoHandshakeMessage& message) {
87 size_t num_entries = message.tag_value_map().size();
88 size_t pad_length = 0;
89 bool need_pad_tag = false;
90 bool need_pad_value = false;
91
92 size_t len = message.size();
93 if (len < message.minimum_size()) {
94 need_pad_tag = true;
95 need_pad_value = true;
96 num_entries++;
97
98 size_t delta = message.minimum_size() - len;
99 const size_t overhead = kQuicTagSize + kCryptoEndOffsetSize;
100 if (delta > overhead) {
101 pad_length = delta - overhead;
102 }
103 len += overhead + pad_length;
104 }
105
106 if (num_entries > kMaxEntries) {
107 return nullptr;
108 }
109
110 std::unique_ptr<char[]> buffer(new char[len]);
111 QuicDataWriter writer(len, buffer.get());
112 if (!writer.WriteUInt32(message.tag())) {
113 DCHECK(false) << "Failed to write message tag.";
114 return nullptr;
115 }
116 if (!writer.WriteUInt16(static_cast<uint16_t>(num_entries))) {
117 DCHECK(false) << "Failed to write size.";
118 return nullptr;
119 }
120 if (!writer.WriteUInt16(0)) {
121 DCHECK(false) << "Failed to write padding.";
122 return nullptr;
123 }
124
125 uint32_t end_offset = 0;
126 // Tags and offsets
127 for (QuicTagValueMap::const_iterator it = message.tag_value_map().begin();
128 it != message.tag_value_map().end(); ++it) {
129 if (it->first == kPAD && need_pad_tag) {
130 // Existing PAD tags are only checked when padding needs to be added
131 // because parts of the code may need to reserialize received messages
132 // and those messages may, legitimately include padding.
133 DCHECK(false) << "Message needed padding but already contained a PAD tag";
134 return nullptr;
135 }
136
137 if (it->first > kPAD && need_pad_tag) {
138 need_pad_tag = false;
139 if (!WritePadTag(&writer, pad_length, &end_offset)) {
140 return nullptr;
141 }
142 }
143
144 if (!writer.WriteUInt32(it->first)) {
145 DCHECK(false) << "Failed to write tag.";
146 return nullptr;
147 }
148 end_offset += it->second.length();
149 if (!writer.WriteUInt32(end_offset)) {
150 DCHECK(false) << "Failed to write end offset.";
151 return nullptr;
152 }
153 }
154
155 if (need_pad_tag) {
156 if (!WritePadTag(&writer, pad_length, &end_offset)) {
157 return nullptr;
158 }
159 }
160
161 // Values
162 for (QuicTagValueMap::const_iterator it = message.tag_value_map().begin();
163 it != message.tag_value_map().end(); ++it) {
164 if (it->first > kPAD && need_pad_value) {
165 need_pad_value = false;
166 if (!writer.WriteRepeatedByte('-', pad_length)) {
167 DCHECK(false) << "Failed to write padding.";
168 return nullptr;
169 }
170 }
171
172 if (!writer.WriteBytes(it->second.data(), it->second.length())) {
173 DCHECK(false) << "Failed to write value.";
174 return nullptr;
175 }
176 }
177
178 if (need_pad_value) {
179 if (!writer.WriteRepeatedByte('-', pad_length)) {
180 DCHECK(false) << "Failed to write padding.";
181 return nullptr;
182 }
183 }
184
185 return new QuicData(buffer.release(), len, true);
186 }
187
188 void CryptoFramer::Clear() {
189 message_.Clear();
190 tags_and_lengths_.clear();
191 error_ = QUIC_NO_ERROR;
192 error_detail_ = "";
193 state_ = STATE_READING_TAG;
194 }
195
196 QuicErrorCode CryptoFramer::Process(StringPiece input) {
197 // Add this data to the buffer.
198 buffer_.append(input.data(), input.length());
199 QuicDataReader reader(buffer_.data(), buffer_.length());
200
201 switch (state_) {
202 case STATE_READING_TAG:
203 if (reader.BytesRemaining() < kQuicTagSize) {
204 break;
205 }
206 QuicTag message_tag;
207 reader.ReadUInt32(&message_tag);
208 message_.set_tag(message_tag);
209 state_ = STATE_READING_NUM_ENTRIES;
210 case STATE_READING_NUM_ENTRIES:
211 if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16_t)) {
212 break;
213 }
214 reader.ReadUInt16(&num_entries_);
215 if (num_entries_ > kMaxEntries) {
216 error_detail_ = base::StringPrintf("%u entries", num_entries_);
217 return QUIC_CRYPTO_TOO_MANY_ENTRIES;
218 }
219 uint16_t padding;
220 reader.ReadUInt16(&padding);
221
222 tags_and_lengths_.reserve(num_entries_);
223 state_ = STATE_READING_TAGS_AND_LENGTHS;
224 values_len_ = 0;
225 case STATE_READING_TAGS_AND_LENGTHS: {
226 if (reader.BytesRemaining() <
227 num_entries_ * (kQuicTagSize + kCryptoEndOffsetSize)) {
228 break;
229 }
230
231 uint32_t last_end_offset = 0;
232 for (unsigned i = 0; i < num_entries_; ++i) {
233 QuicTag tag;
234 reader.ReadUInt32(&tag);
235 if (i > 0 && tag <= tags_and_lengths_[i - 1].first) {
236 if (tag == tags_and_lengths_[i - 1].first) {
237 error_detail_ = base::StringPrintf("Duplicate tag:%u", tag);
238 return QUIC_CRYPTO_DUPLICATE_TAG;
239 }
240 error_detail_ = base::StringPrintf("Tag %u out of order", tag);
241 return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
242 }
243
244 uint32_t end_offset;
245 reader.ReadUInt32(&end_offset);
246
247 if (end_offset < last_end_offset) {
248 error_detail_ = base::StringPrintf("End offset: %u vs %u", end_offset,
249 last_end_offset);
250 return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
251 }
252 tags_and_lengths_.push_back(std::make_pair(
253 tag, static_cast<size_t>(end_offset - last_end_offset)));
254 last_end_offset = end_offset;
255 }
256 values_len_ = last_end_offset;
257 state_ = STATE_READING_VALUES;
258 }
259 case STATE_READING_VALUES:
260 if (reader.BytesRemaining() < values_len_) {
261 break;
262 }
263 for (const pair<QuicTag, size_t>& item : tags_and_lengths_) {
264 StringPiece value;
265 reader.ReadStringPiece(&value, item.second);
266 message_.SetStringPiece(item.first, value);
267 }
268 visitor_->OnHandshakeMessage(message_);
269 Clear();
270 state_ = STATE_READING_TAG;
271 break;
272 }
273 // Save any remaining data.
274 buffer_ = reader.PeekRemainingPayload().as_string();
275 return QUIC_NO_ERROR;
276 }
277
278 // static
279 bool CryptoFramer::WritePadTag(QuicDataWriter* writer,
280 size_t pad_length,
281 uint32_t* end_offset) {
282 if (!writer->WriteUInt32(kPAD)) {
283 DCHECK(false) << "Failed to write tag.";
284 return false;
285 }
286 *end_offset += pad_length;
287 if (!writer->WriteUInt32(*end_offset)) {
288 DCHECK(false) << "Failed to write end offset.";
289 return false;
290 }
291 return true;
292 }
293
294 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_framer.h ('k') | net/quic/crypto/crypto_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698