blob: d2d71133fe78620c50fbe7c81f3c342d9966dab9 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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/third_party/quiche/src/quic/core/quic_data_writer.h"
6
7#include <algorithm>
8#include <limits>
9
10#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
danzh4fbea5d2019-03-20 10:31:44 -070011#include "net/third_party/quiche/src/quic/core/quic_constants.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE team173c48f2019-11-19 16:34:44 -080015#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016
17namespace quic {
18
19QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
QUICHE team173c48f2019-11-19 16:34:44 -080020 : QuicDataWriter(size, buffer, quiche::NETWORK_BYTE_ORDER) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050021
QUICHE team173c48f2019-11-19 16:34:44 -080022QuicDataWriter::QuicDataWriter(size_t size,
23 char* buffer,
24 quiche::Endianness endianness)
QUICHE teama6ef0a62019-03-07 20:34:33 -050025 : buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
26
27QuicDataWriter::~QuicDataWriter() {}
28
29char* QuicDataWriter::data() {
30 return buffer_;
31}
32
33bool QuicDataWriter::WriteUInt8(uint8_t value) {
34 return WriteBytes(&value, sizeof(value));
35}
36
37bool QuicDataWriter::WriteUInt16(uint16_t value) {
QUICHE team173c48f2019-11-19 16:34:44 -080038 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
39 value = quiche::QuicheEndian::HostToNet16(value);
QUICHE teama6ef0a62019-03-07 20:34:33 -050040 }
41 return WriteBytes(&value, sizeof(value));
42}
43
44bool QuicDataWriter::WriteUInt32(uint32_t value) {
QUICHE team173c48f2019-11-19 16:34:44 -080045 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
46 value = quiche::QuicheEndian::HostToNet32(value);
QUICHE teama6ef0a62019-03-07 20:34:33 -050047 }
48 return WriteBytes(&value, sizeof(value));
49}
50
51bool QuicDataWriter::WriteUInt64(uint64_t value) {
QUICHE team173c48f2019-11-19 16:34:44 -080052 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
53 value = quiche::QuicheEndian::HostToNet64(value);
QUICHE teama6ef0a62019-03-07 20:34:33 -050054 }
55 return WriteBytes(&value, sizeof(value));
56}
57
58bool QuicDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) {
59 if (num_bytes > sizeof(value)) {
60 return false;
61 }
QUICHE team173c48f2019-11-19 16:34:44 -080062 if (endianness_ == quiche::HOST_BYTE_ORDER) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 return WriteBytes(&value, num_bytes);
64 }
65
QUICHE team173c48f2019-11-19 16:34:44 -080066 value = quiche::QuicheEndian::HostToNet64(value);
QUICHE teama6ef0a62019-03-07 20:34:33 -050067 return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes,
68 num_bytes);
69}
70
71bool QuicDataWriter::WriteUFloat16(uint64_t value) {
72 uint16_t result;
73 if (value < (UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
74 // Fast path: either the value is denormalized, or has exponent zero.
75 // Both cases are represented by the value itself.
76 result = static_cast<uint16_t>(value);
77 } else if (value >= kUFloat16MaxValue) {
78 // Value is out of range; clamp it to the maximum representable.
79 result = std::numeric_limits<uint16_t>::max();
80 } else {
81 // The highest bit is between position 13 and 42 (zero-based), which
82 // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10,
83 // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11
84 // and count the shifts.
85 uint16_t exponent = 0;
86 for (uint16_t offset = 16; offset > 0; offset /= 2) {
87 // Right-shift the value until the highest bit is in position 11.
88 // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30),
89 // shift if the bit is at or above 11 + offset.
90 if (value >= (UINT64_C(1) << (kUFloat16MantissaBits + offset))) {
91 exponent += offset;
92 value >>= offset;
93 }
94 }
95
96 DCHECK_GE(exponent, 1);
97 DCHECK_LE(exponent, kUFloat16MaxExponent);
98 DCHECK_GE(value, UINT64_C(1) << kUFloat16MantissaBits);
99 DCHECK_LT(value, UINT64_C(1) << kUFloat16MantissaEffectiveBits);
100
101 // Hidden bit (position 11) is set. We should remove it and increment the
102 // exponent. Equivalently, we just add it to the exponent.
103 // This hides the bit.
104 result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits));
105 }
106
QUICHE team173c48f2019-11-19 16:34:44 -0800107 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
108 result = quiche::QuicheEndian::HostToNet16(result);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500109 }
110 return WriteBytes(&result, sizeof(result));
111}
112
113bool QuicDataWriter::WriteStringPiece16(QuicStringPiece val) {
114 if (val.size() > std::numeric_limits<uint16_t>::max()) {
115 return false;
116 }
117 if (!WriteUInt16(static_cast<uint16_t>(val.size()))) {
118 return false;
119 }
120 return WriteBytes(val.data(), val.size());
121}
122
123bool QuicDataWriter::WriteStringPiece(QuicStringPiece val) {
124 return WriteBytes(val.data(), val.size());
125}
126
127char* QuicDataWriter::BeginWrite(size_t length) {
128 if (length_ > capacity_) {
129 return nullptr;
130 }
131
132 if (capacity_ - length_ < length) {
133 return nullptr;
134 }
135
136#ifdef ARCH_CPU_64_BITS
137 DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
138#endif
139
140 return buffer_ + length_;
141}
142
143bool QuicDataWriter::WriteBytes(const void* data, size_t data_len) {
144 char* dest = BeginWrite(data_len);
145 if (!dest) {
146 return false;
147 }
148
149 memcpy(dest, data, data_len);
150
151 length_ += data_len;
152 return true;
153}
154
155bool QuicDataWriter::WriteRepeatedByte(uint8_t byte, size_t count) {
156 char* dest = BeginWrite(count);
157 if (!dest) {
158 return false;
159 }
160
161 memset(dest, byte, count);
162
163 length_ += count;
164 return true;
165}
166
167void QuicDataWriter::WritePadding() {
168 DCHECK_LE(length_, capacity_);
169 if (length_ > capacity_) {
170 return;
171 }
172 memset(buffer_ + length_, 0x00, capacity_ - length_);
173 length_ = capacity_;
174}
175
176bool QuicDataWriter::WritePaddingBytes(size_t count) {
177 return WriteRepeatedByte(0x00, count);
178}
179
180bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id) {
181 if (connection_id.IsEmpty()) {
182 return true;
183 }
184 return WriteBytes(connection_id.data(), connection_id.length());
185}
186
dschinazicf5b1e22019-07-17 18:35:17 -0700187bool QuicDataWriter::WriteLengthPrefixedConnectionId(
188 QuicConnectionId connection_id) {
189 return WriteUInt8(connection_id.length()) && WriteConnectionId(connection_id);
190}
191
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192bool QuicDataWriter::WriteTag(uint32_t tag) {
193 return WriteBytes(&tag, sizeof(tag));
194}
195
196bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
197 char* dest = BeginWrite(length);
198 if (!dest) {
199 return false;
200 }
201
202 random->RandBytes(dest, length);
203 length_ += length;
204 return true;
205}
206
nharper55fa6132019-05-07 19:37:21 -0700207bool QuicDataWriter::Seek(size_t length) {
208 if (!BeginWrite(length)) {
209 return false;
210 }
211 length_ += length;
212 return true;
213}
214
QUICHE teama6ef0a62019-03-07 20:34:33 -0500215// Converts a uint64_t into an IETF/Quic formatted Variable Length
216// Integer. IETF Variable Length Integers have 62 significant bits, so
217// the value to write must be in the range of 0..(2^62)-1.
218//
219// Performance notes
220//
221// Measurements and experiments showed that unrolling the four cases
222// like this and dereferencing next_ as we do (*(next_+n)) gains about
223// 10% over making a loop and dereferencing it as *(next_++)
224//
225// Using a register for next didn't help.
226//
227// Branches are ordered to increase the likelihood of the first being
228// taken.
229//
230// Low-level optimization is useful here because this function will be
231// called frequently, leading to outsize benefits.
232bool QuicDataWriter::WriteVarInt62(uint64_t value) {
QUICHE team173c48f2019-11-19 16:34:44 -0800233 DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234
235 size_t remaining = capacity_ - length_;
236 char* next = buffer_ + length_;
237
238 if ((value & kVarInt62ErrorMask) == 0) {
239 // We know the high 2 bits are 0 so |value| is legal.
240 // We can do the encoding.
241 if ((value & kVarInt62Mask8Bytes) != 0) {
242 // Someplace in the high-4 bytes is a 1-bit. Do an 8-byte
243 // encoding.
244 if (remaining >= 8) {
245 *(next + 0) = ((value >> 56) & 0x3f) + 0xc0;
246 *(next + 1) = (value >> 48) & 0xff;
247 *(next + 2) = (value >> 40) & 0xff;
248 *(next + 3) = (value >> 32) & 0xff;
249 *(next + 4) = (value >> 24) & 0xff;
250 *(next + 5) = (value >> 16) & 0xff;
251 *(next + 6) = (value >> 8) & 0xff;
252 *(next + 7) = value & 0xff;
253 length_ += 8;
254 return true;
255 }
256 return false;
257 }
258 // The high-order-4 bytes are all 0, check for a 1, 2, or 4-byte
259 // encoding
260 if ((value & kVarInt62Mask4Bytes) != 0) {
261 // The encoding will not fit into 2 bytes, Do a 4-byte
262 // encoding.
263 if (remaining >= 4) {
264 *(next + 0) = ((value >> 24) & 0x3f) + 0x80;
265 *(next + 1) = (value >> 16) & 0xff;
266 *(next + 2) = (value >> 8) & 0xff;
267 *(next + 3) = value & 0xff;
268 length_ += 4;
269 return true;
270 }
271 return false;
272 }
273 // The high-order bits are all 0. Check to see if the number
274 // can be encoded as one or two bytes. One byte encoding has
275 // only 6 significant bits (bits 0xffffffff ffffffc0 are all 0).
276 // Two byte encoding has more than 6, but 14 or less significant
277 // bits (bits 0xffffffff ffffc000 are 0 and 0x00000000 00003fc0
278 // are not 0)
279 if ((value & kVarInt62Mask2Bytes) != 0) {
280 // Do 2-byte encoding
281 if (remaining >= 2) {
282 *(next + 0) = ((value >> 8) & 0x3f) + 0x40;
283 *(next + 1) = (value)&0xff;
284 length_ += 2;
285 return true;
286 }
287 return false;
288 }
289 if (remaining >= 1) {
290 // Do 1-byte encoding
291 *next = (value & 0x3f);
292 length_ += 1;
293 return true;
294 }
295 return false;
296 }
297 // Can not encode, high 2 bits not 0
298 return false;
299}
300
301bool QuicDataWriter::WriteVarInt62(
302 uint64_t value,
303 QuicVariableLengthIntegerLength write_length) {
QUICHE team173c48f2019-11-19 16:34:44 -0800304 DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305
306 size_t remaining = capacity_ - length_;
307 if (remaining < write_length) {
308 return false;
309 }
310
311 const QuicVariableLengthIntegerLength min_length = GetVarInt62Len(value);
312 if (write_length < min_length) {
313 QUIC_BUG << "Cannot write value " << value << " with write_length "
314 << write_length;
315 return false;
316 }
317 if (write_length == min_length) {
318 return WriteVarInt62(value);
319 }
320
321 if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_2) {
322 return WriteUInt8(0b01000000) && WriteUInt8(value);
323 }
324 if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_4) {
325 return WriteUInt8(0b10000000) && WriteUInt8(0) && WriteUInt16(value);
326 }
327 if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_8) {
328 return WriteUInt8(0b11000000) && WriteUInt8(0) && WriteUInt16(0) &&
329 WriteUInt32(value);
330 }
331
332 QUIC_BUG << "Invalid write_length " << static_cast<int>(write_length);
333 return false;
334}
335
336// static
337QuicVariableLengthIntegerLength QuicDataWriter::GetVarInt62Len(uint64_t value) {
338 if ((value & kVarInt62ErrorMask) != 0) {
339 QUIC_BUG << "Attempted to encode a value, " << value
340 << ", that is too big for VarInt62";
341 return VARIABLE_LENGTH_INTEGER_LENGTH_0;
342 }
343 if ((value & kVarInt62Mask8Bytes) != 0) {
344 return VARIABLE_LENGTH_INTEGER_LENGTH_8;
345 }
346 if ((value & kVarInt62Mask4Bytes) != 0) {
347 return VARIABLE_LENGTH_INTEGER_LENGTH_4;
348 }
349 if ((value & kVarInt62Mask2Bytes) != 0) {
350 return VARIABLE_LENGTH_INTEGER_LENGTH_2;
351 }
352 return VARIABLE_LENGTH_INTEGER_LENGTH_1;
353}
354
355bool QuicDataWriter::WriteStringPieceVarInt62(
356 const QuicStringPiece& string_piece) {
357 if (!WriteVarInt62(string_piece.size())) {
358 return false;
359 }
360 if (!string_piece.empty()) {
361 if (!WriteBytes(string_piece.data(), string_piece.size())) {
362 return false;
363 }
364 }
365 return true;
366}
367
vasilvvc48c8712019-03-11 13:38:16 -0700368std::string QuicDataWriter::DebugString() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369 return QuicStrCat(" { capacity: ", capacity_, ", length: ", length_, " }");
370}
371
372} // namespace quic