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