1 // 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 #ifndef QUICHE_COMMON_QUICHE_DATA_READER_H_ 6 #define QUICHE_COMMON_QUICHE_DATA_READER_H_ 7 8 #include <cstddef> 9 #include <cstdint> 10 #include <limits> 11 #include <string> 12 13 #include "absl/strings/string_view.h" 14 #include "quiche/common/platform/api/quiche_export.h" 15 #include "quiche/common/platform/api/quiche_logging.h" 16 #include "quiche/common/quiche_endian.h" 17 18 namespace quiche { 19 20 // To use, simply construct a QuicheDataReader using the underlying buffer that 21 // you'd like to read fields from, then call one of the Read*() methods to 22 // actually do some reading. 23 // 24 // This class keeps an internal iterator to keep track of what's already been 25 // read and each successive Read*() call automatically increments said iterator 26 // on success. On failure, internal state of the QuicheDataReader should not be 27 // trusted and it is up to the caller to throw away the failed instance and 28 // handle the error as appropriate. None of the Read*() methods should ever be 29 // called after failure, as they will also fail immediately. 30 class QUICHE_EXPORT QuicheDataReader { 31 public: 32 // Constructs a reader using NETWORK_BYTE_ORDER endianness. 33 // Caller must provide an underlying buffer to work on. 34 explicit QuicheDataReader(absl::string_view data); 35 // Constructs a reader using NETWORK_BYTE_ORDER endianness. 36 // Caller must provide an underlying buffer to work on. 37 QuicheDataReader(const char* data, const size_t len); 38 // Constructs a reader using the specified endianness. 39 // Caller must provide an underlying buffer to work on. 40 QuicheDataReader(const char* data, const size_t len, 41 quiche::Endianness endianness); 42 QuicheDataReader(const QuicheDataReader&) = delete; 43 QuicheDataReader& operator=(const QuicheDataReader&) = delete; 44 45 // Empty destructor. ~QuicheDataReader()46 ~QuicheDataReader() {} 47 48 // Reads an 8/16/24/32/64-bit unsigned integer into the given output 49 // parameter. Forwards the internal iterator on success. Returns true on 50 // success, false otherwise. 51 bool ReadUInt8(uint8_t* result); 52 bool ReadUInt16(uint16_t* result); 53 bool ReadUInt24(uint32_t* result); 54 bool ReadUInt32(uint32_t* result); 55 bool ReadUInt64(uint64_t* result); 56 57 // Set |result| to 0, then read |num_bytes| bytes in the correct byte order 58 // into least significant bytes of |result|. 59 bool ReadBytesToUInt64(size_t num_bytes, uint64_t* result); 60 61 // Reads a string prefixed with 16-bit length into the given output parameter. 62 // 63 // NOTE: Does not copy but rather references strings in the underlying buffer. 64 // This should be kept in mind when handling memory management! 65 // 66 // Forwards the internal iterator on success. 67 // Returns true on success, false otherwise. 68 bool ReadStringPiece16(absl::string_view* result); 69 70 // Reads a string prefixed with 8-bit length into the given output parameter. 71 // 72 // NOTE: Does not copy but rather references strings in the underlying buffer. 73 // This should be kept in mind when handling memory management! 74 // 75 // Forwards the internal iterator on success. 76 // Returns true on success, false otherwise. 77 bool ReadStringPiece8(absl::string_view* result); 78 79 // Reads a given number of bytes into the given buffer. The buffer 80 // must be of adequate size. 81 // Forwards the internal iterator on success. 82 // Returns true on success, false otherwise. 83 bool ReadStringPiece(absl::string_view* result, size_t size); 84 85 // Reads tag represented as 32-bit unsigned integer into given output 86 // parameter. Tags are in big endian on the wire (e.g., CHLO is 87 // 'C','H','L','O') and are read in byte order, so tags in memory are in big 88 // endian. 89 bool ReadTag(uint32_t* tag); 90 91 // Reads a sequence of a fixed number of decimal digits, parses them as an 92 // unsigned integer and returns them as a uint64_t. Forwards internal 93 // iterator on success, may forward it even in case of failure. 94 bool ReadDecimal64(size_t num_digits, uint64_t* result); 95 96 // Returns the length in bytes of a variable length integer based on the next 97 // two bits available. Returns 1, 2, 4, or 8 on success, and 0 on failure. 98 QuicheVariableLengthIntegerLength PeekVarInt62Length(); 99 100 // Read an RFC 9000 62-bit Variable Length Integer and place the result in 101 // |*result|. Returns false if there is not enough space in the buffer to read 102 // the number, true otherwise. If false is returned, |*result| is not altered. 103 bool ReadVarInt62(uint64_t* result); 104 105 // Reads a string prefixed with a RFC 9000 62-bit variable Length integer 106 // length into the given output parameter. 107 // 108 // NOTE: Does not copy but rather references strings in the underlying buffer. 109 // This should be kept in mind when handling memory management! 110 // 111 // Returns false if there is not enough space in the buffer to read 112 // the number and subsequent string, true otherwise. 113 bool ReadStringPieceVarInt62(absl::string_view* result); 114 115 // Reads a string prefixed with a RFC 9000 varint length prefix, and copies it 116 // into the provided string. 117 // 118 // Returns false if there is not enough space in the buffer to read 119 // the number and subsequent string, true otherwise. 120 bool ReadStringVarInt62(std::string& result); 121 122 // Returns the remaining payload as a absl::string_view. 123 // 124 // NOTE: Does not copy but rather references strings in the underlying buffer. 125 // This should be kept in mind when handling memory management! 126 // 127 // Forwards the internal iterator. 128 absl::string_view ReadRemainingPayload(); 129 130 // Returns the remaining payload as a absl::string_view. 131 // 132 // NOTE: Does not copy but rather references strings in the underlying buffer. 133 // This should be kept in mind when handling memory management! 134 // 135 // DOES NOT forward the internal iterator. 136 absl::string_view PeekRemainingPayload() const; 137 138 // Returns the entire payload as a absl::string_view. 139 // 140 // NOTE: Does not copy but rather references strings in the underlying buffer. 141 // This should be kept in mind when handling memory management! 142 // 143 // DOES NOT forward the internal iterator. 144 absl::string_view FullPayload() const; 145 146 // Returns the part of the payload that has been already read as a 147 // absl::string_view. 148 // 149 // NOTE: Does not copy but rather references strings in the underlying buffer. 150 // This should be kept in mind when handling memory management! 151 // 152 // DOES NOT forward the internal iterator. 153 absl::string_view PreviouslyReadPayload() const; 154 155 // Reads a given number of bytes into the given buffer. The buffer 156 // must be of adequate size. 157 // Forwards the internal iterator on success. 158 // Returns true on success, false otherwise. 159 bool ReadBytes(void* result, size_t size); 160 161 // Skips over |size| bytes from the buffer and forwards the internal iterator. 162 // Returns true if there are at least |size| bytes remaining to read, false 163 // otherwise. 164 bool Seek(size_t size); 165 166 // Returns true if the entirety of the underlying buffer has been read via 167 // Read*() calls. 168 bool IsDoneReading() const; 169 170 // Returns the number of bytes remaining to be read. 171 size_t BytesRemaining() const; 172 173 // Truncates the reader down by reducing its internal length. 174 // If called immediately after calling this, BytesRemaining will 175 // return |truncation_length|. If truncation_length is less than the 176 // current value of BytesRemaining, this does nothing and returns false. 177 bool TruncateRemaining(size_t truncation_length); 178 179 // Returns the next byte that to be read. Must not be called when there are no 180 // bytes to be read. 181 // 182 // DOES NOT forward the internal iterator. 183 uint8_t PeekByte() const; 184 185 std::string DebugString() const; 186 187 protected: 188 // Returns true if the underlying buffer has enough room to read the given 189 // amount of bytes. 190 bool CanRead(size_t bytes) const; 191 192 // To be called when a read fails for any reason. 193 void OnFailure(); 194 data()195 const char* data() const { return data_; } 196 pos()197 size_t pos() const { return pos_; } 198 AdvancePos(size_t amount)199 void AdvancePos(size_t amount) { 200 QUICHE_DCHECK_LE(pos_, std::numeric_limits<size_t>::max() - amount); 201 QUICHE_DCHECK_LE(pos_, len_ - amount); 202 pos_ += amount; 203 } 204 endianness()205 quiche::Endianness endianness() const { return endianness_; } 206 207 private: 208 // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not 209 // char. The data buffer that we're reading from. 210 const char* data_; 211 212 // The length of the data buffer that we're reading from. 213 size_t len_; 214 215 // The location of the next read from our data buffer. 216 size_t pos_; 217 218 // The endianness to read integers and floating numbers. 219 quiche::Endianness endianness_; 220 }; 221 222 } // namespace quiche 223 224 #endif // QUICHE_COMMON_QUICHE_DATA_READER_H_ 225