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