blob: 2242fea6437b59f95ca44e1aa5d01eb2047242f4 [file] [log] [blame]
dmcardle2b64f502020-01-07 15:22:36 -08001// Copyright (c) 2020 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/common/quiche_data_reader.h"
6
vasilvv0a09b8f2020-04-27 08:08:55 -07007#include <cstring>
8
dmcardle2b64f502020-01-07 15:22:36 -08009#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
10#include "net/third_party/quiche/src/common/platform/api/quiche_logging.h"
11#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
12#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
vasilvv52f24592020-06-02 17:32:16 -070013#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
dmcardle2b64f502020-01-07 15:22:36 -080014
15namespace quiche {
16
17QuicheDataReader::QuicheDataReader(quiche::QuicheStringPiece data)
18 : QuicheDataReader(data.data(), data.length(), quiche::NETWORK_BYTE_ORDER) {
19}
20
21QuicheDataReader::QuicheDataReader(const char* data, const size_t len)
22 : QuicheDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
23
24QuicheDataReader::QuicheDataReader(const char* data,
25 const size_t len,
26 quiche::Endianness endianness)
27 : data_(data), len_(len), pos_(0), endianness_(endianness) {}
28
29bool QuicheDataReader::ReadUInt8(uint8_t* result) {
30 return ReadBytes(result, sizeof(*result));
31}
32
33bool QuicheDataReader::ReadUInt16(uint16_t* result) {
34 if (!ReadBytes(result, sizeof(*result))) {
35 return false;
36 }
37 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
38 *result = quiche::QuicheEndian::NetToHost16(*result);
39 }
40 return true;
41}
42
43bool QuicheDataReader::ReadUInt32(uint32_t* result) {
44 if (!ReadBytes(result, sizeof(*result))) {
45 return false;
46 }
47 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
48 *result = quiche::QuicheEndian::NetToHost32(*result);
49 }
50 return true;
51}
52
53bool QuicheDataReader::ReadUInt64(uint64_t* result) {
54 if (!ReadBytes(result, sizeof(*result))) {
55 return false;
56 }
57 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
58 *result = quiche::QuicheEndian::NetToHost64(*result);
59 }
60 return true;
61}
62
63bool QuicheDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
64 *result = 0u;
65 if (num_bytes > sizeof(*result)) {
66 return false;
67 }
68 if (endianness_ == quiche::HOST_BYTE_ORDER) {
69 return ReadBytes(result, num_bytes);
70 }
71
72 if (!ReadBytes(reinterpret_cast<char*>(result) + sizeof(*result) - num_bytes,
73 num_bytes)) {
74 return false;
75 }
76 *result = quiche::QuicheEndian::NetToHost64(*result);
77 return true;
78}
79
80bool QuicheDataReader::ReadStringPiece16(quiche::QuicheStringPiece* result) {
81 // Read resultant length.
82 uint16_t result_len;
83 if (!ReadUInt16(&result_len)) {
84 // OnFailure() already called.
85 return false;
86 }
87
88 return ReadStringPiece(result, result_len);
89}
90
dschinazia0aeda52020-04-10 16:57:18 -070091bool QuicheDataReader::ReadStringPiece8(quiche::QuicheStringPiece* result) {
92 // Read resultant length.
93 uint8_t result_len;
94 if (!ReadUInt8(&result_len)) {
95 // OnFailure() already called.
96 return false;
97 }
98
99 return ReadStringPiece(result, result_len);
100}
101
dmcardle2b64f502020-01-07 15:22:36 -0800102bool QuicheDataReader::ReadStringPiece(quiche::QuicheStringPiece* result,
103 size_t size) {
104 // Make sure that we have enough data to read.
105 if (!CanRead(size)) {
106 OnFailure();
107 return false;
108 }
109
110 // Set result.
111 *result = quiche::QuicheStringPiece(data_ + pos_, size);
112
113 // Iterate.
114 pos_ += size;
115
116 return true;
117}
118
119bool QuicheDataReader::ReadTag(uint32_t* tag) {
120 return ReadBytes(tag, sizeof(*tag));
121}
122
vasilvv52f24592020-06-02 17:32:16 -0700123bool QuicheDataReader::ReadDecimal64(size_t num_digits, uint64_t* result) {
124 quiche::QuicheStringPiece digits;
125 if (!ReadStringPiece(&digits, num_digits)) {
126 return false;
127 }
128
129 return QuicheTextUtils::StringToUint64(digits, result);
130}
131
dmcardle2b64f502020-01-07 15:22:36 -0800132quiche::QuicheStringPiece QuicheDataReader::ReadRemainingPayload() {
133 quiche::QuicheStringPiece payload = PeekRemainingPayload();
134 pos_ = len_;
135 return payload;
136}
137
138quiche::QuicheStringPiece QuicheDataReader::PeekRemainingPayload() const {
139 return quiche::QuicheStringPiece(data_ + pos_, len_ - pos_);
140}
141
142quiche::QuicheStringPiece QuicheDataReader::FullPayload() const {
143 return quiche::QuicheStringPiece(data_, len_);
144}
145
dschinazi278efae2020-01-28 17:03:09 -0800146quiche::QuicheStringPiece QuicheDataReader::PreviouslyReadPayload() const {
147 return quiche::QuicheStringPiece(data_, pos_);
148}
149
dmcardle2b64f502020-01-07 15:22:36 -0800150bool QuicheDataReader::ReadBytes(void* result, size_t size) {
151 // Make sure that we have enough data to read.
152 if (!CanRead(size)) {
153 OnFailure();
154 return false;
155 }
156
157 // Read into result.
158 memcpy(result, data_ + pos_, size);
159
160 // Iterate.
161 pos_ += size;
162
163 return true;
164}
165
166bool QuicheDataReader::Seek(size_t size) {
167 if (!CanRead(size)) {
168 OnFailure();
169 return false;
170 }
171 pos_ += size;
172 return true;
173}
174
175bool QuicheDataReader::IsDoneReading() const {
176 return len_ == pos_;
177}
178
179size_t QuicheDataReader::BytesRemaining() const {
180 return len_ - pos_;
181}
182
183bool QuicheDataReader::TruncateRemaining(size_t truncation_length) {
184 if (truncation_length > BytesRemaining()) {
185 return false;
186 }
187 len_ = pos_ + truncation_length;
188 return true;
189}
190
191bool QuicheDataReader::CanRead(size_t bytes) const {
192 return bytes <= (len_ - pos_);
193}
194
195void QuicheDataReader::OnFailure() {
196 // Set our iterator to the end of the buffer so that further reads fail
197 // immediately.
198 pos_ = len_;
199}
200
201uint8_t QuicheDataReader::PeekByte() const {
202 if (pos_ >= len_) {
203 QUICHE_LOG(FATAL)
204 << "Reading is done, cannot peek next byte. Tried to read pos = "
205 << pos_ << " buffer length = " << len_;
206 return 0;
207 }
208 return data_[pos_];
209}
210
211std::string QuicheDataReader::DebugString() const {
212 return quiche::QuicheStrCat(" { length: ", len_, ", position: ", pos_, " }");
213}
214
215#undef ENDPOINT // undef for jumbo builds
216} // namespace quiche