blob: fac462acebd6e66727cc1c7c5005306dded13e96 [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_reader.h"
6
7#include "net/third_party/quiche/src/quic/core/quic_packets.h"
8#include "net/third_party/quiche/src/quic/core/quic_utils.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
10#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
QUICHE team173c48f2019-11-19 16:34:44 -080011#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080012#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
13#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014
15namespace quic {
16
dmcardlecf0bfcf2019-12-13 08:08:21 -080017QuicDataReader::QuicDataReader(quiche::QuicheStringPiece data)
dmcardle2b64f502020-01-07 15:22:36 -080018 : quiche::QuicheDataReader(data) {}
nharper55fa6132019-05-07 19:37:21 -070019
QUICHE teama6ef0a62019-03-07 20:34:33 -050020QuicDataReader::QuicDataReader(const char* data, const size_t len)
QUICHE team173c48f2019-11-19 16:34:44 -080021 : QuicDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050022
23QuicDataReader::QuicDataReader(const char* data,
24 const size_t len,
QUICHE team173c48f2019-11-19 16:34:44 -080025 quiche::Endianness endianness)
dmcardle2b64f502020-01-07 15:22:36 -080026 : quiche::QuicheDataReader(data, len, endianness) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050027
28bool QuicDataReader::ReadUFloat16(uint64_t* result) {
29 uint16_t value;
30 if (!ReadUInt16(&value)) {
31 return false;
32 }
33
34 *result = value;
35 if (*result < (1 << kUFloat16MantissaEffectiveBits)) {
36 // Fast path: either the value is denormalized (no hidden bit), or
37 // normalized (hidden bit set, exponent offset by one) with exponent zero.
38 // Zero exponent offset by one sets the bit exactly where the hidden bit is.
39 // So in both cases the value encodes itself.
40 return true;
41 }
42
43 uint16_t exponent =
44 value >> kUFloat16MantissaBits; // No sign extend on uint!
45 // After the fast pass, the exponent is at least one (offset by one).
46 // Un-offset the exponent.
47 --exponent;
48 DCHECK_GE(exponent, 1);
49 DCHECK_LE(exponent, kUFloat16MaxExponent);
50 // Here we need to clear the exponent and set the hidden bit. We have already
51 // decremented the exponent, so when we subtract it, it leaves behind the
52 // hidden bit.
53 *result -= exponent << kUFloat16MantissaBits;
54 *result <<= exponent;
55 DCHECK_GE(*result,
56 static_cast<uint64_t>(1 << kUFloat16MantissaEffectiveBits));
57 DCHECK_LE(*result, kUFloat16MaxValue);
58 return true;
59}
60
QUICHE teama6ef0a62019-03-07 20:34:33 -050061bool QuicDataReader::ReadConnectionId(QuicConnectionId* connection_id,
62 uint8_t length) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 if (length == 0) {
64 connection_id->set_length(0);
65 return true;
66 }
67
dschinazib3241162019-06-10 17:59:37 -070068 if (BytesRemaining() < length) {
69 return false;
70 }
71
72 connection_id->set_length(length);
dschinazib953d022019-08-01 18:05:58 -070073 const bool ok =
74 ReadBytes(connection_id->mutable_data(), connection_id->length());
dschinazib3241162019-06-10 17:59:37 -070075 DCHECK(ok);
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 return ok;
77}
78
dschinazicf5b1e22019-07-17 18:35:17 -070079bool QuicDataReader::ReadLengthPrefixedConnectionId(
80 QuicConnectionId* connection_id) {
81 uint8_t connection_id_length;
82 if (!ReadUInt8(&connection_id_length)) {
83 return false;
84 }
dschinazicf5b1e22019-07-17 18:35:17 -070085 return ReadConnectionId(connection_id, connection_id_length);
86}
87
QUICHE teama6ef0a62019-03-07 20:34:33 -050088QuicVariableLengthIntegerLength QuicDataReader::PeekVarInt62Length() {
dmcardle2b64f502020-01-07 15:22:36 -080089 DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -050090 const unsigned char* next =
dmcardle2b64f502020-01-07 15:22:36 -080091 reinterpret_cast<const unsigned char*>(data() + pos());
QUICHE teama6ef0a62019-03-07 20:34:33 -050092 if (BytesRemaining() == 0) {
93 return VARIABLE_LENGTH_INTEGER_LENGTH_0;
94 }
95 return static_cast<QuicVariableLengthIntegerLength>(
96 1 << ((*next & 0b11000000) >> 6));
97}
98
QUICHE teama6ef0a62019-03-07 20:34:33 -050099// Read an IETF/QUIC formatted 62-bit Variable Length Integer.
100//
101// Performance notes
102//
103// Measurements and experiments showed that unrolling the four cases
104// like this and dereferencing next_ as we do (*(next_+n) --- and then
105// doing a single pos_+=x at the end) gains about 10% over making a
106// loop and dereferencing next_ such as *(next_++)
107//
108// Using a register for pos_ was not helpful.
109//
110// Branches are ordered to increase the likelihood of the first being
111// taken.
112//
113// Low-level optimization is useful here because this function will be
114// called frequently, leading to outsize benefits.
115bool QuicDataReader::ReadVarInt62(uint64_t* result) {
dmcardle2b64f502020-01-07 15:22:36 -0800116 DCHECK_EQ(endianness(), quiche::NETWORK_BYTE_ORDER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117
118 size_t remaining = BytesRemaining();
119 const unsigned char* next =
dmcardle2b64f502020-01-07 15:22:36 -0800120 reinterpret_cast<const unsigned char*>(data() + pos());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 if (remaining != 0) {
122 switch (*next & 0xc0) {
123 case 0xc0:
124 // Leading 0b11...... is 8 byte encoding
125 if (remaining >= 8) {
126 *result = (static_cast<uint64_t>((*(next)) & 0x3f) << 56) +
127 (static_cast<uint64_t>(*(next + 1)) << 48) +
128 (static_cast<uint64_t>(*(next + 2)) << 40) +
129 (static_cast<uint64_t>(*(next + 3)) << 32) +
130 (static_cast<uint64_t>(*(next + 4)) << 24) +
131 (static_cast<uint64_t>(*(next + 5)) << 16) +
132 (static_cast<uint64_t>(*(next + 6)) << 8) +
133 (static_cast<uint64_t>(*(next + 7)) << 0);
dmcardle2b64f502020-01-07 15:22:36 -0800134 AdvancePos(8);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 return true;
136 }
137 return false;
138
139 case 0x80:
140 // Leading 0b10...... is 4 byte encoding
141 if (remaining >= 4) {
142 *result = (((*(next)) & 0x3f) << 24) + (((*(next + 1)) << 16)) +
143 (((*(next + 2)) << 8)) + (((*(next + 3)) << 0));
dmcardle2b64f502020-01-07 15:22:36 -0800144 AdvancePos(4);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 return true;
146 }
147 return false;
148
149 case 0x40:
150 // Leading 0b01...... is 2 byte encoding
151 if (remaining >= 2) {
152 *result = (((*(next)) & 0x3f) << 8) + (*(next + 1));
dmcardle2b64f502020-01-07 15:22:36 -0800153 AdvancePos(2);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154 return true;
155 }
156 return false;
157
158 case 0x00:
159 // Leading 0b00...... is 1 byte encoding
160 *result = (*next) & 0x3f;
dmcardle2b64f502020-01-07 15:22:36 -0800161 AdvancePos(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162 return true;
163 }
164 }
165 return false;
166}
167
fkastenholz3c4eabf2019-04-22 07:49:59 -0700168bool QuicDataReader::ReadVarIntU32(uint32_t* result) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500169 uint64_t temp_uint64;
170 // TODO(fkastenholz): We should disambiguate read-errors from
171 // value errors.
172 if (!this->ReadVarInt62(&temp_uint64)) {
173 return false;
174 }
175 if (temp_uint64 > kMaxQuicStreamId) {
176 return false;
177 }
fkastenholz3c4eabf2019-04-22 07:49:59 -0700178 *result = static_cast<uint32_t>(temp_uint64);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179 return true;
180}
181
QUICHE teama6ef0a62019-03-07 20:34:33 -0500182#undef ENDPOINT // undef for jumbo builds
183} // namespace quic