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_UTILS_H_ 6 #define QUICHE_QUIC_CORE_QUIC_UTILS_H_ 7 8 #include <cstddef> 9 #include <cstdint> 10 #include <sstream> 11 #include <string> 12 #include <type_traits> 13 14 #include "absl/numeric/int128.h" 15 #include "absl/strings/string_view.h" 16 #include "absl/types/span.h" 17 #include "quiche/quic/core/crypto/quic_random.h" 18 #include "quiche/quic/core/frames/quic_frame.h" 19 #include "quiche/quic/core/quic_connection_id.h" 20 #include "quiche/quic/core/quic_error_codes.h" 21 #include "quiche/quic/core/quic_types.h" 22 #include "quiche/quic/core/quic_versions.h" 23 #include "quiche/quic/platform/api/quic_export.h" 24 #include "quiche/quic/platform/api/quic_socket_address.h" 25 #include "quiche/common/platform/api/quiche_mem_slice.h" 26 27 namespace quic { 28 29 class QUIC_EXPORT_PRIVATE QuicUtils { 30 public: 31 QuicUtils() = delete; 32 33 // Returns the 64 bit FNV1a hash of the data. See 34 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param 35 static uint64_t FNV1a_64_Hash(absl::string_view data); 36 37 // Returns the 128 bit FNV1a hash of the data. See 38 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param 39 static absl::uint128 FNV1a_128_Hash(absl::string_view data); 40 41 // Returns the 128 bit FNV1a hash of the two sequences of data. See 42 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param 43 static absl::uint128 FNV1a_128_Hash_Two(absl::string_view data1, 44 absl::string_view data2); 45 46 // Returns the 128 bit FNV1a hash of the three sequences of data. See 47 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param 48 static absl::uint128 FNV1a_128_Hash_Three(absl::string_view data1, 49 absl::string_view data2, 50 absl::string_view data3); 51 52 // SerializeUint128 writes the first 96 bits of |v| in little-endian form 53 // to |out|. 54 static void SerializeUint128Short(absl::uint128 v, uint8_t* out); 55 56 // Returns AddressChangeType as a string. 57 static std::string AddressChangeTypeToString(AddressChangeType type); 58 59 // Returns SentPacketState as a char*. 60 static const char* SentPacketStateToString(SentPacketState state); 61 62 // Returns QuicLongHeaderType as a char*. 63 static const char* QuicLongHeaderTypetoString(QuicLongHeaderType type); 64 65 // Returns AckResult as a char*. 66 static const char* AckResultToString(AckResult result); 67 68 // Determines and returns change type of address change from |old_address| to 69 // |new_address|. 70 static AddressChangeType DetermineAddressChangeType( 71 const QuicSocketAddress& old_address, 72 const QuicSocketAddress& new_address); 73 74 // Returns the opposite Perspective of the |perspective| passed in. InvertPerspective(Perspective perspective)75 static constexpr Perspective InvertPerspective(Perspective perspective) { 76 return perspective == Perspective::IS_CLIENT ? Perspective::IS_SERVER 77 : Perspective::IS_CLIENT; 78 } 79 80 // Returns true if a packet is ackable. A packet is unackable if it can never 81 // be acked. Occurs when a packet is never sent, after it is acknowledged 82 // once, or if it's a crypto packet we never expect to receive an ack for. 83 static bool IsAckable(SentPacketState state); 84 85 // Returns true if frame with |type| is retransmittable. A retransmittable 86 // frame should be retransmitted if it is detected as lost. 87 static bool IsRetransmittableFrame(QuicFrameType type); 88 89 // Returns true if |frame| is a handshake frame in version |version|. 90 static bool IsHandshakeFrame(const QuicFrame& frame, 91 QuicTransportVersion transport_version); 92 93 // Return true if any frame in |frames| is of |type|. 94 static bool ContainsFrameType(const QuicFrames& frames, QuicFrameType type); 95 96 // Returns packet state corresponding to |retransmission_type|. 97 static SentPacketState RetransmissionTypeToPacketState( 98 TransmissionType retransmission_type); 99 100 // Returns true if header with |first_byte| is considered as an IETF QUIC 101 // packet header. This only works on the server. 102 static bool IsIetfPacketHeader(uint8_t first_byte); 103 104 // Returns true if header with |first_byte| is considered as an IETF QUIC 105 // short packet header. 106 static bool IsIetfPacketShortHeader(uint8_t first_byte); 107 108 // Returns ID to denote an invalid stream of |version|. 109 static QuicStreamId GetInvalidStreamId(QuicTransportVersion version); 110 111 // Returns crypto stream ID of |version|. 112 static QuicStreamId GetCryptoStreamId(QuicTransportVersion version); 113 114 // Returns whether |id| is the stream ID for the crypto stream. If |version| 115 // is a version where crypto data doesn't go over stream frames, this function 116 // will always return false. 117 static bool IsCryptoStreamId(QuicTransportVersion version, QuicStreamId id); 118 119 // Returns headers stream ID of |version|. 120 static QuicStreamId GetHeadersStreamId(QuicTransportVersion version); 121 122 // Returns true if |id| is considered as client initiated stream ID. 123 static bool IsClientInitiatedStreamId(QuicTransportVersion version, 124 QuicStreamId id); 125 126 // Returns true if |id| is considered as server initiated stream ID. 127 static bool IsServerInitiatedStreamId(QuicTransportVersion version, 128 QuicStreamId id); 129 130 // Returns true if the stream ID represents a stream initiated by the 131 // provided perspective. 132 static bool IsOutgoingStreamId(ParsedQuicVersion version, QuicStreamId id, 133 Perspective perspective); 134 135 // Returns true if |id| is considered as bidirectional stream ID. Only used in 136 // v99. 137 static bool IsBidirectionalStreamId(QuicStreamId id, 138 ParsedQuicVersion version); 139 140 // Returns stream type. Either |perspective| or |peer_initiated| would be 141 // enough together with |id|. This method enforces that the three parameters 142 // are consistent. Only used in v99. 143 static StreamType GetStreamType(QuicStreamId id, Perspective perspective, 144 bool peer_initiated, 145 ParsedQuicVersion version); 146 147 // Returns the delta between consecutive stream IDs of the same type. 148 static QuicStreamId StreamIdDelta(QuicTransportVersion version); 149 150 // Returns the first initiated bidirectional stream ID of |perspective|. 151 static QuicStreamId GetFirstBidirectionalStreamId( 152 QuicTransportVersion version, Perspective perspective); 153 154 // Returns the first initiated unidirectional stream ID of |perspective|. 155 static QuicStreamId GetFirstUnidirectionalStreamId( 156 QuicTransportVersion version, Perspective perspective); 157 158 // Returns the largest possible client initiated bidirectional stream ID. 159 static QuicStreamId GetMaxClientInitiatedBidirectionalStreamId( 160 QuicTransportVersion version); 161 162 // Generates a random 64bit connection ID. 163 static QuicConnectionId CreateRandomConnectionId(); 164 165 // Generates a random 64bit connection ID using the provided QuicRandom. 166 static QuicConnectionId CreateRandomConnectionId(QuicRandom* random); 167 168 // Generates a random connection ID of the given length. 169 static QuicConnectionId CreateRandomConnectionId( 170 uint8_t connection_id_length); 171 172 // Generates a random connection ID of the given length using the provided 173 // QuicRandom. 174 static QuicConnectionId CreateRandomConnectionId(uint8_t connection_id_length, 175 QuicRandom* random); 176 177 // Returns true if the connection ID length is valid for this QUIC version. 178 static bool IsConnectionIdLengthValidForVersion( 179 size_t connection_id_length, QuicTransportVersion transport_version); 180 181 // Returns true if the connection ID is valid for this QUIC version. 182 static bool IsConnectionIdValidForVersion( 183 QuicConnectionId connection_id, QuicTransportVersion transport_version); 184 185 // Returns a connection ID suitable for QUIC use-cases that do not need the 186 // connection ID for multiplexing. If the version allows variable lengths, 187 // a connection of length zero is returned, otherwise 64bits set to zero. 188 static QuicConnectionId CreateZeroConnectionId(QuicTransportVersion version); 189 190 // Generates a 128bit stateless reset token based on a connection ID. 191 static StatelessResetToken GenerateStatelessResetToken( 192 QuicConnectionId connection_id); 193 194 // Determines packet number space from |encryption_level|. 195 static PacketNumberSpace GetPacketNumberSpace( 196 EncryptionLevel encryption_level); 197 198 // Determines encryption level to send ACK in |packet_number_space|. 199 static EncryptionLevel GetEncryptionLevelToSendAckofSpace( 200 PacketNumberSpace packet_number_space); 201 202 // Get the maximum value for a V99/IETF QUIC stream count. If a count 203 // exceeds this value, it will result in a stream ID that exceeds the 204 // implementation limit on stream ID size. 205 static QuicStreamCount GetMaxStreamCount(); 206 207 // Return true if this frame is an IETF probing frame. 208 static bool IsProbingFrame(QuicFrameType type); 209 210 // Return true if the two stateless reset tokens are equal. Performs the 211 // comparison in constant time. 212 static bool AreStatelessResetTokensEqual(const StatelessResetToken& token1, 213 const StatelessResetToken& token2); 214 215 // Return ture if this frame is an ack-eliciting frame. 216 static bool IsAckElicitingFrame(QuicFrameType type); 217 }; 218 219 // Returns true if the specific ID is a valid WebTransport session ID that our 220 // implementation can process. 221 bool IsValidWebTransportSessionId(WebTransportSessionId id, 222 ParsedQuicVersion transport_version); 223 224 QuicByteCount MemSliceSpanTotalSize(absl::Span<quiche::QuicheMemSlice> span); 225 226 // Computes a SHA-256 hash and returns the raw bytes of the hash. 227 QUIC_EXPORT_PRIVATE std::string RawSha256(absl::string_view input); 228 229 template <typename Mask> 230 class QUIC_EXPORT_PRIVATE BitMask { 231 public: 232 // explicit to prevent (incorrect) usage like "BitMask bitmask = 0;". 233 template <typename... Bits> BitMask(Bits...bits)234 explicit BitMask(Bits... bits) { 235 mask_ = MakeMask(bits...); 236 } 237 238 BitMask() = default; 239 BitMask(const BitMask& other) = default; 240 BitMask& operator=(const BitMask& other) = default; 241 242 template <typename... Bits> Set(Bits...bits)243 void Set(Bits... bits) { 244 mask_ |= MakeMask(bits...); 245 } 246 247 template <typename Bit> IsSet(Bit bit)248 bool IsSet(Bit bit) const { 249 return (MakeMask(bit) & mask_) != 0; 250 } 251 ClearAll()252 void ClearAll() { mask_ = 0; } 253 NumBits()254 static constexpr size_t NumBits() { return 8 * sizeof(Mask); } 255 256 friend bool operator==(const BitMask& lhs, const BitMask& rhs) { 257 return lhs.mask_ == rhs.mask_; 258 } 259 DebugString()260 std::string DebugString() const { 261 std::ostringstream oss; 262 oss << "0x" << std::hex << mask_; 263 return oss.str(); 264 } 265 266 private: 267 template <typename Bit> MakeMask(Bit bit)268 static std::enable_if_t<std::is_enum<Bit>::value, Mask> MakeMask(Bit bit) { 269 using IntType = typename std::underlying_type<Bit>::type; 270 return Mask(1) << static_cast<IntType>(bit); 271 } 272 273 template <typename Bit> MakeMask(Bit bit)274 static std::enable_if_t<!std::is_enum<Bit>::value, Mask> MakeMask(Bit bit) { 275 return Mask(1) << bit; 276 } 277 278 template <typename Bit, typename... Bits> MakeMask(Bit first_bit,Bits...other_bits)279 static Mask MakeMask(Bit first_bit, Bits... other_bits) { 280 return MakeMask(first_bit) | MakeMask(other_bits...); 281 } 282 283 Mask mask_ = 0; 284 }; 285 286 using BitMask64 = BitMask<uint64_t>; 287 288 } // namespace quic 289 290 #endif // QUICHE_QUIC_CORE_QUIC_UTILS_H_ 291