QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2012 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_QUIC_CORE_QUIC_DATA_WRITER_H_ |
| 6 | #define QUICHE_QUIC_CORE_QUIC_DATA_WRITER_H_ |
| 7 | |
| 8 | #include <cstddef> |
| 9 | #include <cstdint> |
| 10 | |
danzh | c89c799 | 2019-03-19 16:01:07 -0700 | [diff] [blame] | 11 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 12 | #include "net/third_party/quiche/src/quic/platform/api/quic_endian.h" |
| 13 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
| 14 | #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" |
| 15 | |
| 16 | namespace quic { |
| 17 | |
| 18 | class QuicRandom; |
| 19 | |
| 20 | // Maximum value that can be properly encoded using VarInt62 coding. |
| 21 | const uint64_t kVarInt62MaxValue = UINT64_C(0x3fffffffffffffff); |
| 22 | |
| 23 | // VarInt62 encoding masks |
| 24 | // If a uint64_t anded with a mask is not 0 then the value is encoded |
| 25 | // using that length (or is too big, in the case of kVarInt62ErrorMask). |
| 26 | // Values must be checked in order (error, 8-, 4-, and then 2- bytes) |
| 27 | // and if none are non-0, the value is encoded in 1 byte. |
| 28 | const uint64_t kVarInt62ErrorMask = UINT64_C(0xc000000000000000); |
| 29 | const uint64_t kVarInt62Mask8Bytes = UINT64_C(0x3fffffffc0000000); |
| 30 | const uint64_t kVarInt62Mask4Bytes = UINT64_C(0x000000003fffc000); |
| 31 | const uint64_t kVarInt62Mask2Bytes = UINT64_C(0x0000000000003fc0); |
| 32 | |
| 33 | // This class provides facilities for packing QUIC data. |
| 34 | // |
| 35 | // The QuicDataWriter supports appending primitive values (int, string, etc) |
| 36 | // to a frame instance. The internal memory buffer is exposed as the "data" |
| 37 | // of the QuicDataWriter. |
| 38 | class QUIC_EXPORT_PRIVATE QuicDataWriter { |
| 39 | public: |
| 40 | // Creates a QuicDataWriter where |buffer| is not owned |
| 41 | // using NETWORK_BYTE_ORDER endianness. |
| 42 | QuicDataWriter(size_t size, char* buffer); |
| 43 | // Creates a QuicDataWriter where |buffer| is not owned |
| 44 | // using the specified endianness. |
| 45 | QuicDataWriter(size_t size, char* buffer, Endianness endianness); |
| 46 | QuicDataWriter(const QuicDataWriter&) = delete; |
| 47 | QuicDataWriter& operator=(const QuicDataWriter&) = delete; |
| 48 | |
| 49 | ~QuicDataWriter(); |
| 50 | |
| 51 | // Returns the size of the QuicDataWriter's data. |
| 52 | size_t length() const { return length_; } |
| 53 | |
| 54 | // Retrieves the buffer from the QuicDataWriter without changing ownership. |
| 55 | char* data(); |
| 56 | |
| 57 | // Methods for adding to the payload. These values are appended to the end |
| 58 | // of the QuicDataWriter payload. |
| 59 | |
| 60 | // Writes 8/16/32/64-bit unsigned integers. |
| 61 | bool WriteUInt8(uint8_t value); |
| 62 | bool WriteUInt16(uint16_t value); |
| 63 | bool WriteUInt32(uint32_t value); |
| 64 | bool WriteUInt64(uint64_t value); |
| 65 | |
| 66 | // Write an unsigned-integer value per the IETF QUIC/Variable Length |
| 67 | // Integer encoding rules (see draft-ietf-quic-transport-08.txt). |
| 68 | // IETF Variable Length Integers have 62 significant bits, so the |
| 69 | // value to write must be in the range of 0...(2^62)-1. Returns |
| 70 | // false if the value is out of range or if there is no room in the |
| 71 | // buffer. |
| 72 | bool WriteVarInt62(uint64_t value); |
| 73 | |
| 74 | // Same as WriteVarInt62(uint64_t), but forces an encoding size to write to. |
| 75 | // This is not as optimized as WriteVarInt62(uint64_t). |
| 76 | // Returns false if the value does not fit in the specified write_length or if |
| 77 | // there is no room in the buffer. |
| 78 | bool WriteVarInt62(uint64_t value, |
| 79 | QuicVariableLengthIntegerLength write_length); |
| 80 | |
| 81 | // Writes a string piece as a consecutive length/content pair. The |
| 82 | // length is VarInt62 encoded. |
| 83 | bool WriteStringPieceVarInt62(const QuicStringPiece& string_piece); |
| 84 | |
| 85 | // Utility function to return the number of bytes needed to encode |
| 86 | // the given value using IETF VarInt62 encoding. Returns the number |
| 87 | // of bytes required to encode the given integer or 0 if the value |
| 88 | // is too large to encode. |
| 89 | static QuicVariableLengthIntegerLength GetVarInt62Len(uint64_t value); |
| 90 | |
| 91 | // Writes least significant |num_bytes| of a 64-bit unsigned integer in the |
| 92 | // correct byte order. |
| 93 | bool WriteBytesToUInt64(size_t num_bytes, uint64_t value); |
| 94 | |
| 95 | // Write unsigned floating point corresponding to the value. Large values are |
| 96 | // clamped to the maximum representable (kUFloat16MaxValue). Values that can |
| 97 | // not be represented directly are rounded down. |
| 98 | bool WriteUFloat16(uint64_t value); |
| 99 | bool WriteStringPiece(QuicStringPiece val); |
| 100 | bool WriteStringPiece16(QuicStringPiece val); |
| 101 | bool WriteBytes(const void* data, size_t data_len); |
| 102 | bool WriteRepeatedByte(uint8_t byte, size_t count); |
| 103 | // Fills the remaining buffer with null characters. |
| 104 | void WritePadding(); |
| 105 | // Write padding of |count| bytes. |
| 106 | bool WritePaddingBytes(size_t count); |
| 107 | |
| 108 | // Write connection ID to the payload. |
| 109 | bool WriteConnectionId(QuicConnectionId connection_id); |
| 110 | |
dschinazi | cf5b1e2 | 2019-07-17 18:35:17 -0700 | [diff] [blame] | 111 | // Write 8-bit length followed by connection ID to the payload. |
| 112 | bool WriteLengthPrefixedConnectionId(QuicConnectionId connection_id); |
| 113 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 114 | // Write tag as a 32-bit unsigned integer to the payload. As tags are already |
| 115 | // converted to big endian (e.g., CHLO is 'C','H','L','O') in memory by TAG or |
| 116 | // MakeQuicTag and tags are written in byte order, so tags on the wire are |
| 117 | // in big endian. |
| 118 | bool WriteTag(uint32_t tag); |
| 119 | |
| 120 | // Write |length| random bytes generated by |random|. |
| 121 | bool WriteRandomBytes(QuicRandom* random, size_t length); |
| 122 | |
nharper | 55fa613 | 2019-05-07 19:37:21 -0700 | [diff] [blame] | 123 | // Advance the writer's position for writing by |length| bytes without writing |
| 124 | // anything. This method only makes sense to be used on a buffer that has |
| 125 | // already been written to (and is having certain parts rewritten). |
| 126 | bool Seek(size_t length); |
| 127 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 128 | size_t capacity() const { return capacity_; } |
| 129 | |
| 130 | size_t remaining() const { return capacity_ - length_; } |
| 131 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 132 | std::string DebugString() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 133 | |
| 134 | private: |
| 135 | // Returns the location that the data should be written at, or nullptr if |
| 136 | // there is not enough room. Call EndWrite with the returned offset and the |
| 137 | // given length to pad out for the next write. |
| 138 | char* BeginWrite(size_t length); |
| 139 | |
| 140 | // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not |
| 141 | // char. |
| 142 | char* buffer_; |
| 143 | size_t capacity_; // Allocation size of payload (or -1 if buffer is const). |
| 144 | size_t length_; // Current length of the buffer. |
| 145 | |
| 146 | // The endianness to write integers and floating numbers. |
| 147 | Endianness endianness_; |
| 148 | }; |
| 149 | |
| 150 | } // namespace quic |
| 151 | |
| 152 | #endif // QUICHE_QUIC_CORE_QUIC_DATA_WRITER_H_ |