blob: f20c752bcce2fd0f82f354d29bc3b1b7cea9f2a4 [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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "common/quiche_data_reader.h"
dmcardle2b64f502020-01-07 15:22:36 -08006
vasilvv0a09b8f2020-04-27 08:08:55 -07007#include <cstring>
8
vasilvv23846f32020-10-27 09:53:28 -07009#include "absl/strings/numbers.h"
vasilvv6950cd82020-12-03 15:33:04 -080010#include "absl/strings/str_cat.h"
vasilvv652cd422020-10-09 15:50:02 -070011#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050012#include "common/platform/api/quiche_logging.h"
QUICHE team5be974e2020-12-29 18:35:24 -050013#include "common/quiche_endian.h"
dmcardle2b64f502020-01-07 15:22:36 -080014
15namespace quiche {
16
vasilvv652cd422020-10-09 15:50:02 -070017QuicheDataReader::QuicheDataReader(absl::string_view data)
dmcardle2b64f502020-01-07 15:22:36 -080018 : 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
vasilvv652cd422020-10-09 15:50:02 -070080bool QuicheDataReader::ReadStringPiece16(absl::string_view* result) {
dmcardle2b64f502020-01-07 15:22:36 -080081 // 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
vasilvv652cd422020-10-09 15:50:02 -070091bool QuicheDataReader::ReadStringPiece8(absl::string_view* result) {
dschinazia0aeda52020-04-10 16:57:18 -070092 // 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
vasilvv652cd422020-10-09 15:50:02 -0700102bool QuicheDataReader::ReadStringPiece(absl::string_view* result, size_t size) {
dmcardle2b64f502020-01-07 15:22:36 -0800103 // Make sure that we have enough data to read.
104 if (!CanRead(size)) {
105 OnFailure();
106 return false;
107 }
108
109 // Set result.
vasilvv652cd422020-10-09 15:50:02 -0700110 *result = absl::string_view(data_ + pos_, size);
dmcardle2b64f502020-01-07 15:22:36 -0800111
112 // Iterate.
113 pos_ += size;
114
115 return true;
116}
117
118bool QuicheDataReader::ReadTag(uint32_t* tag) {
119 return ReadBytes(tag, sizeof(*tag));
120}
121
vasilvv52f24592020-06-02 17:32:16 -0700122bool QuicheDataReader::ReadDecimal64(size_t num_digits, uint64_t* result) {
vasilvv652cd422020-10-09 15:50:02 -0700123 absl::string_view digits;
vasilvv52f24592020-06-02 17:32:16 -0700124 if (!ReadStringPiece(&digits, num_digits)) {
125 return false;
126 }
127
vasilvv23846f32020-10-27 09:53:28 -0700128 return absl::SimpleAtoi(digits, result);
vasilvv52f24592020-06-02 17:32:16 -0700129}
130
vasilvv652cd422020-10-09 15:50:02 -0700131absl::string_view QuicheDataReader::ReadRemainingPayload() {
132 absl::string_view payload = PeekRemainingPayload();
dmcardle2b64f502020-01-07 15:22:36 -0800133 pos_ = len_;
134 return payload;
135}
136
vasilvv652cd422020-10-09 15:50:02 -0700137absl::string_view QuicheDataReader::PeekRemainingPayload() const {
138 return absl::string_view(data_ + pos_, len_ - pos_);
dmcardle2b64f502020-01-07 15:22:36 -0800139}
140
vasilvv652cd422020-10-09 15:50:02 -0700141absl::string_view QuicheDataReader::FullPayload() const {
142 return absl::string_view(data_, len_);
dmcardle2b64f502020-01-07 15:22:36 -0800143}
144
vasilvv652cd422020-10-09 15:50:02 -0700145absl::string_view QuicheDataReader::PreviouslyReadPayload() const {
146 return absl::string_view(data_, pos_);
dschinazi278efae2020-01-28 17:03:09 -0800147}
148
dmcardle2b64f502020-01-07 15:22:36 -0800149bool QuicheDataReader::ReadBytes(void* result, size_t size) {
150 // Make sure that we have enough data to read.
151 if (!CanRead(size)) {
152 OnFailure();
153 return false;
154 }
155
156 // Read into result.
157 memcpy(result, data_ + pos_, size);
158
159 // Iterate.
160 pos_ += size;
161
162 return true;
163}
164
165bool QuicheDataReader::Seek(size_t size) {
166 if (!CanRead(size)) {
167 OnFailure();
168 return false;
169 }
170 pos_ += size;
171 return true;
172}
173
174bool QuicheDataReader::IsDoneReading() const {
175 return len_ == pos_;
176}
177
178size_t QuicheDataReader::BytesRemaining() const {
179 return len_ - pos_;
180}
181
182bool QuicheDataReader::TruncateRemaining(size_t truncation_length) {
183 if (truncation_length > BytesRemaining()) {
184 return false;
185 }
186 len_ = pos_ + truncation_length;
187 return true;
188}
189
190bool QuicheDataReader::CanRead(size_t bytes) const {
191 return bytes <= (len_ - pos_);
192}
193
194void QuicheDataReader::OnFailure() {
195 // Set our iterator to the end of the buffer so that further reads fail
196 // immediately.
197 pos_ = len_;
198}
199
200uint8_t QuicheDataReader::PeekByte() const {
201 if (pos_ >= len_) {
202 QUICHE_LOG(FATAL)
203 << "Reading is done, cannot peek next byte. Tried to read pos = "
204 << pos_ << " buffer length = " << len_;
205 return 0;
206 }
207 return data_[pos_];
208}
209
210std::string QuicheDataReader::DebugString() const {
vasilvv6950cd82020-12-03 15:33:04 -0800211 return absl::StrCat(" { length: ", len_, ", position: ", pos_, " }");
dmcardle2b64f502020-01-07 15:22:36 -0800212}
213
214#undef ENDPOINT // undef for jumbo builds
215} // namespace quiche