blob: ee3c861ee8cd378021e4850c86a91675756195f0 [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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/core/quic_data_writer.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
7#include <algorithm>
8#include <limits>
9
vasilvvc872ee42020-10-07 19:50:22 -070010#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050011#include "quic/core/crypto/quic_random.h"
12#include "quic/core/quic_constants.h"
13#include "quic/platform/api/quic_bug_tracker.h"
14#include "quic/platform/api/quic_flags.h"
QUICHE team5be974e2020-12-29 18:35:24 -050015#include "common/quiche_endian.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016
17namespace quic {
18
19QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
dmcardle2b64f502020-01-07 15:22:36 -080020 : quiche::QuicheDataWriter(size, buffer) {}
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)
dmcardle2b64f502020-01-07 15:22:36 -080025 : quiche::QuicheDataWriter(size, buffer, endianness) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050026
27QuicDataWriter::~QuicDataWriter() {}
28
QUICHE teama6ef0a62019-03-07 20:34:33 -050029bool QuicDataWriter::WriteUFloat16(uint64_t value) {
30 uint16_t result;
31 if (value < (UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
32 // Fast path: either the value is denormalized, or has exponent zero.
33 // Both cases are represented by the value itself.
34 result = static_cast<uint16_t>(value);
35 } else if (value >= kUFloat16MaxValue) {
36 // Value is out of range; clamp it to the maximum representable.
37 result = std::numeric_limits<uint16_t>::max();
38 } else {
39 // The highest bit is between position 13 and 42 (zero-based), which
40 // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10,
41 // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11
42 // and count the shifts.
43 uint16_t exponent = 0;
44 for (uint16_t offset = 16; offset > 0; offset /= 2) {
45 // Right-shift the value until the highest bit is in position 11.
46 // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30),
47 // shift if the bit is at or above 11 + offset.
48 if (value >= (UINT64_C(1) << (kUFloat16MantissaBits + offset))) {
49 exponent += offset;
50 value >>= offset;
51 }
52 }
53
vasilvvf8035162021-02-01 14:49:14 -080054 QUICHE_DCHECK_GE(exponent, 1);
55 QUICHE_DCHECK_LE(exponent, kUFloat16MaxExponent);
56 QUICHE_DCHECK_GE(value, UINT64_C(1) << kUFloat16MantissaBits);
57 QUICHE_DCHECK_LT(value, UINT64_C(1) << kUFloat16MantissaEffectiveBits);
QUICHE teama6ef0a62019-03-07 20:34:33 -050058
59 // Hidden bit (position 11) is set. We should remove it and increment the
60 // exponent. Equivalently, we just add it to the exponent.
61 // This hides the bit.
62 result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits));
63 }
64
dmcardle2b64f502020-01-07 15:22:36 -080065 if (endianness() == quiche::NETWORK_BYTE_ORDER) {
QUICHE team173c48f2019-11-19 16:34:44 -080066 result = quiche::QuicheEndian::HostToNet16(result);
QUICHE teama6ef0a62019-03-07 20:34:33 -050067 }
68 return WriteBytes(&result, sizeof(result));
69}
70
QUICHE teama6ef0a62019-03-07 20:34:33 -050071bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id) {
72 if (connection_id.IsEmpty()) {
73 return true;
74 }
75 return WriteBytes(connection_id.data(), connection_id.length());
76}
77
dschinazicf5b1e22019-07-17 18:35:17 -070078bool QuicDataWriter::WriteLengthPrefixedConnectionId(
79 QuicConnectionId connection_id) {
80 return WriteUInt8(connection_id.length()) && WriteConnectionId(connection_id);
81}
82
QUICHE teama6ef0a62019-03-07 20:34:33 -050083bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
84 char* dest = BeginWrite(length);
85 if (!dest) {
86 return false;
87 }
88
89 random->RandBytes(dest, length);
dmcardle2b64f502020-01-07 15:22:36 -080090 IncreaseLength(length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050091 return true;
92}
93
dschinazi9a5d7c02021-02-22 13:05:47 -080094bool QuicDataWriter::WriteInsecureRandomBytes(QuicRandom* random,
95 size_t length) {
96 char* dest = BeginWrite(length);
97 if (!dest) {
98 return false;
99 }
100
101 random->InsecureRandBytes(dest, length);
102 IncreaseLength(length);
103 return true;
104}
nharper55fa6132019-05-07 19:37:21 -0700105
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106// Converts a uint64_t into an IETF/Quic formatted Variable Length
107// Integer. IETF Variable Length Integers have 62 significant bits, so
108// the value to write must be in the range of 0..(2^62)-1.
109//
110// Performance notes
111//
112// Measurements and experiments showed that unrolling the four cases
113// like this and dereferencing next_ as we do (*(next_+n)) gains about
114// 10% over making a loop and dereferencing it as *(next_++)
115//
116// Using a register for next didn't help.
117//
118// Branches are ordered to increase the likelihood of the first being
119// taken.
120//
121// Low-level optimization is useful here because this function will be
122// called frequently, leading to outsize benefits.
123bool QuicDataWriter::WriteVarInt62(uint64_t value) {
vasilvvf8035162021-02-01 14:49:14 -0800124 QUICHE_DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125
dmcardle2b64f502020-01-07 15:22:36 -0800126 size_t remaining_bytes = remaining();
127 char* next = buffer() + length();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128
129 if ((value & kVarInt62ErrorMask) == 0) {
130 // We know the high 2 bits are 0 so |value| is legal.
131 // We can do the encoding.
132 if ((value & kVarInt62Mask8Bytes) != 0) {
133 // Someplace in the high-4 bytes is a 1-bit. Do an 8-byte
134 // encoding.
dmcardle2b64f502020-01-07 15:22:36 -0800135 if (remaining_bytes >= 8) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500136 *(next + 0) = ((value >> 56) & 0x3f) + 0xc0;
137 *(next + 1) = (value >> 48) & 0xff;
138 *(next + 2) = (value >> 40) & 0xff;
139 *(next + 3) = (value >> 32) & 0xff;
140 *(next + 4) = (value >> 24) & 0xff;
141 *(next + 5) = (value >> 16) & 0xff;
142 *(next + 6) = (value >> 8) & 0xff;
143 *(next + 7) = value & 0xff;
dmcardle2b64f502020-01-07 15:22:36 -0800144 IncreaseLength(8);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 return true;
146 }
147 return false;
148 }
149 // The high-order-4 bytes are all 0, check for a 1, 2, or 4-byte
150 // encoding
151 if ((value & kVarInt62Mask4Bytes) != 0) {
152 // The encoding will not fit into 2 bytes, Do a 4-byte
153 // encoding.
dmcardle2b64f502020-01-07 15:22:36 -0800154 if (remaining_bytes >= 4) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155 *(next + 0) = ((value >> 24) & 0x3f) + 0x80;
156 *(next + 1) = (value >> 16) & 0xff;
157 *(next + 2) = (value >> 8) & 0xff;
158 *(next + 3) = value & 0xff;
dmcardle2b64f502020-01-07 15:22:36 -0800159 IncreaseLength(4);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 return true;
161 }
162 return false;
163 }
164 // The high-order bits are all 0. Check to see if the number
165 // can be encoded as one or two bytes. One byte encoding has
166 // only 6 significant bits (bits 0xffffffff ffffffc0 are all 0).
167 // Two byte encoding has more than 6, but 14 or less significant
168 // bits (bits 0xffffffff ffffc000 are 0 and 0x00000000 00003fc0
169 // are not 0)
170 if ((value & kVarInt62Mask2Bytes) != 0) {
171 // Do 2-byte encoding
dmcardle2b64f502020-01-07 15:22:36 -0800172 if (remaining_bytes >= 2) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 *(next + 0) = ((value >> 8) & 0x3f) + 0x40;
174 *(next + 1) = (value)&0xff;
dmcardle2b64f502020-01-07 15:22:36 -0800175 IncreaseLength(2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500176 return true;
177 }
178 return false;
179 }
dmcardle2b64f502020-01-07 15:22:36 -0800180 if (remaining_bytes >= 1) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181 // Do 1-byte encoding
182 *next = (value & 0x3f);
dmcardle2b64f502020-01-07 15:22:36 -0800183 IncreaseLength(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500184 return true;
185 }
186 return false;
187 }
188 // Can not encode, high 2 bits not 0
189 return false;
190}
191
192bool QuicDataWriter::WriteVarInt62(
193 uint64_t value,
194 QuicVariableLengthIntegerLength write_length) {
vasilvvf8035162021-02-01 14:49:14 -0800195 QUICHE_DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500196
dmcardle2b64f502020-01-07 15:22:36 -0800197 size_t remaining_bytes = remaining();
198 if (remaining_bytes < write_length) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 return false;
200 }
201
202 const QuicVariableLengthIntegerLength min_length = GetVarInt62Len(value);
203 if (write_length < min_length) {
QUICHE team60aff822021-03-16 15:21:02 -0700204 QUIC_BUG(quic_bug_10347_1) << "Cannot write value " << value
205 << " with write_length " << write_length;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500206 return false;
207 }
208 if (write_length == min_length) {
209 return WriteVarInt62(value);
210 }
211
212 if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_2) {
213 return WriteUInt8(0b01000000) && WriteUInt8(value);
214 }
215 if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_4) {
216 return WriteUInt8(0b10000000) && WriteUInt8(0) && WriteUInt16(value);
217 }
218 if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_8) {
219 return WriteUInt8(0b11000000) && WriteUInt8(0) && WriteUInt16(0) &&
220 WriteUInt32(value);
221 }
222
QUICHE team60aff822021-03-16 15:21:02 -0700223 QUIC_BUG(quic_bug_10347_2)
QUICHE teamb89112a2021-03-09 16:02:46 -0800224 << "Invalid write_length " << static_cast<int>(write_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225 return false;
226}
227
228// static
229QuicVariableLengthIntegerLength QuicDataWriter::GetVarInt62Len(uint64_t value) {
230 if ((value & kVarInt62ErrorMask) != 0) {
QUICHE team60aff822021-03-16 15:21:02 -0700231 QUIC_BUG(quic_bug_10347_3) << "Attempted to encode a value, " << value
232 << ", that is too big for VarInt62";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500233 return VARIABLE_LENGTH_INTEGER_LENGTH_0;
234 }
235 if ((value & kVarInt62Mask8Bytes) != 0) {
236 return VARIABLE_LENGTH_INTEGER_LENGTH_8;
237 }
238 if ((value & kVarInt62Mask4Bytes) != 0) {
239 return VARIABLE_LENGTH_INTEGER_LENGTH_4;
240 }
241 if ((value & kVarInt62Mask2Bytes) != 0) {
242 return VARIABLE_LENGTH_INTEGER_LENGTH_2;
243 }
244 return VARIABLE_LENGTH_INTEGER_LENGTH_1;
245}
246
247bool QuicDataWriter::WriteStringPieceVarInt62(
vasilvvc872ee42020-10-07 19:50:22 -0700248 const absl::string_view& string_piece) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500249 if (!WriteVarInt62(string_piece.size())) {
250 return false;
251 }
252 if (!string_piece.empty()) {
253 if (!WriteBytes(string_piece.data(), string_piece.size())) {
254 return false;
255 }
256 }
257 return true;
258}
259
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260} // namespace quic