blob: 0b089b4bad617f60accf86cfeb5563ab59ba9d7a [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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>
wubcfddec82020-01-13 07:45:27 -080010#include <sstream>
vasilvv872e7a32019-03-12 16:42:44 -070011#include <string>
wubcfddec82020-01-13 07:45:27 -080012#include <type_traits>
QUICHE teama6ef0a62019-03-07 20:34:33 -050013
bncc7556a02021-04-06 05:10:45 -070014#include "absl/numeric/int128.h"
vasilvvc872ee42020-10-07 19:50:22 -070015#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050016#include "quic/core/crypto/quic_random.h"
17#include "quic/core/frames/quic_frame.h"
18#include "quic/core/quic_connection_id.h"
19#include "quic/core/quic_error_codes.h"
20#include "quic/core/quic_types.h"
21#include "quic/core/quic_versions.h"
22#include "quic/platform/api/quic_export.h"
23#include "quic/platform/api/quic_iovec.h"
24#include "quic/platform/api/quic_socket_address.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050025
26namespace quic {
27
28class QUIC_EXPORT_PRIVATE QuicUtils {
29 public:
30 QuicUtils() = delete;
31
32 // Returns the 64 bit FNV1a hash of the data. See
33 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
vasilvvc872ee42020-10-07 19:50:22 -070034 static uint64_t FNV1a_64_Hash(absl::string_view data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050035
36 // Returns the 128 bit FNV1a hash of the data. See
37 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
bncc7556a02021-04-06 05:10:45 -070038 static absl::uint128 FNV1a_128_Hash(absl::string_view data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050039
40 // Returns the 128 bit FNV1a hash of the two sequences of data. See
41 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
bncc7556a02021-04-06 05:10:45 -070042 static absl::uint128 FNV1a_128_Hash_Two(absl::string_view data1,
43 absl::string_view data2);
QUICHE teama6ef0a62019-03-07 20:34:33 -050044
45 // Returns the 128 bit FNV1a hash of the three sequences of data. See
46 // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
bncc7556a02021-04-06 05:10:45 -070047 static absl::uint128 FNV1a_128_Hash_Three(absl::string_view data1,
48 absl::string_view data2,
49 absl::string_view data3);
QUICHE teama6ef0a62019-03-07 20:34:33 -050050
51 // SerializeUint128 writes the first 96 bits of |v| in little-endian form
52 // to |out|.
bncc7556a02021-04-06 05:10:45 -070053 static void SerializeUint128Short(absl::uint128 v, uint8_t* out);
QUICHE teama6ef0a62019-03-07 20:34:33 -050054
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 // Returns AddressChangeType as a string.
vasilvvc48c8712019-03-11 13:38:16 -070056 static std::string AddressChangeTypeToString(AddressChangeType type);
QUICHE teama6ef0a62019-03-07 20:34:33 -050057
58 // Returns SentPacketState as a char*.
59 static const char* SentPacketStateToString(SentPacketState state);
60
61 // Returns QuicLongHeaderType as a char*.
62 static const char* QuicLongHeaderTypetoString(QuicLongHeaderType type);
63
fayang3eb82212019-04-16 12:05:46 -070064 // Returns AckResult as a char*.
65 static const char* AckResultToString(AckResult result);
66
QUICHE teama6ef0a62019-03-07 20:34:33 -050067 // Determines and returns change type of address change from |old_address| to
68 // |new_address|.
69 static AddressChangeType DetermineAddressChangeType(
70 const QuicSocketAddress& old_address,
71 const QuicSocketAddress& new_address);
72
73 // Copies |buffer_length| bytes from iov starting at offset |iov_offset| into
74 // buffer. |iov| must be at least iov_offset+length total length and buffer
75 // must be at least |length| long.
76 static void CopyToBuffer(const struct iovec* iov,
77 int iov_count,
78 size_t iov_offset,
79 size_t buffer_length,
80 char* buffer);
81
82 // Creates an iovec pointing to the same data as |data|.
vasilvvc872ee42020-10-07 19:50:22 -070083 static struct iovec MakeIovec(absl::string_view data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050084
nharper4eba09b2019-06-26 20:17:25 -070085 // Returns the opposite Perspective of the |perspective| passed in.
86 static constexpr Perspective InvertPerspective(Perspective perspective) {
87 return perspective == Perspective::IS_CLIENT ? Perspective::IS_SERVER
88 : Perspective::IS_CLIENT;
89 }
90
QUICHE teama6ef0a62019-03-07 20:34:33 -050091 // Returns true if a packet is ackable. A packet is unackable if it can never
92 // be acked. Occurs when a packet is never sent, after it is acknowledged
93 // once, or if it's a crypto packet we never expect to receive an ack for.
94 static bool IsAckable(SentPacketState state);
95
96 // Returns true if frame with |type| is retransmittable. A retransmittable
97 // frame should be retransmitted if it is detected as lost.
98 static bool IsRetransmittableFrame(QuicFrameType type);
99
100 // Returns true if |frame| is a handshake frame in version |version|.
101 static bool IsHandshakeFrame(const QuicFrame& frame,
102 QuicTransportVersion transport_version);
103
wubf6ed10e2020-01-31 13:22:02 -0800104 // Return true if any frame in |frames| is of |type|.
105 static bool ContainsFrameType(const QuicFrames& frames, QuicFrameType type);
106
QUICHE teama6ef0a62019-03-07 20:34:33 -0500107 // Returns packet state corresponding to |retransmission_type|.
108 static SentPacketState RetransmissionTypeToPacketState(
109 TransmissionType retransmission_type);
110
111 // Returns true if header with |first_byte| is considered as an IETF QUIC
dschinazi48ac9192019-07-31 00:07:26 -0700112 // packet header. This only works on the server.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500113 static bool IsIetfPacketHeader(uint8_t first_byte);
114
115 // Returns true if header with |first_byte| is considered as an IETF QUIC
116 // short packet header.
117 static bool IsIetfPacketShortHeader(uint8_t first_byte);
118
119 // Returns ID to denote an invalid stream of |version|.
120 static QuicStreamId GetInvalidStreamId(QuicTransportVersion version);
121
122 // Returns crypto stream ID of |version|.
123 static QuicStreamId GetCryptoStreamId(QuicTransportVersion version);
124
nharper46833c32019-05-15 21:33:05 -0700125 // Returns whether |id| is the stream ID for the crypto stream. If |version|
126 // is a version where crypto data doesn't go over stream frames, this function
127 // will always return false.
128 static bool IsCryptoStreamId(QuicTransportVersion version, QuicStreamId id);
129
QUICHE teama6ef0a62019-03-07 20:34:33 -0500130 // Returns headers stream ID of |version|.
131 static QuicStreamId GetHeadersStreamId(QuicTransportVersion version);
132
133 // Returns true if |id| is considered as client initiated stream ID.
134 static bool IsClientInitiatedStreamId(QuicTransportVersion version,
135 QuicStreamId id);
136
137 // Returns true if |id| is considered as server initiated stream ID.
138 static bool IsServerInitiatedStreamId(QuicTransportVersion version,
139 QuicStreamId id);
140
dschinazi18cdf132019-10-09 16:08:18 -0700141 // Returns true if the stream ID represents a stream initiated by the
142 // provided perspective.
143 static bool IsOutgoingStreamId(ParsedQuicVersion version,
144 QuicStreamId id,
145 Perspective perspective);
146
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 // Returns true if |id| is considered as bidirectional stream ID. Only used in
148 // v99.
renjietangd262e252020-06-19 15:11:24 -0700149 static bool IsBidirectionalStreamId(QuicStreamId id,
150 ParsedQuicVersion version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500151
152 // Returns stream type. Either |perspective| or |peer_initiated| would be
153 // enough together with |id|. This method enforces that the three parameters
154 // are consistent. Only used in v99.
155 static StreamType GetStreamType(QuicStreamId id,
156 Perspective perspective,
renjietangd262e252020-06-19 15:11:24 -0700157 bool peer_initiated,
158 ParsedQuicVersion version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500159
160 // Returns the delta between consecutive stream IDs of the same type.
161 static QuicStreamId StreamIdDelta(QuicTransportVersion version);
162
163 // Returns the first initiated bidirectional stream ID of |perspective|.
164 static QuicStreamId GetFirstBidirectionalStreamId(
165 QuicTransportVersion version,
166 Perspective perspective);
167
168 // Returns the first initiated unidirectional stream ID of |perspective|.
169 static QuicStreamId GetFirstUnidirectionalStreamId(
170 QuicTransportVersion version,
171 Perspective perspective);
172
bnc01aa36e2020-11-11 08:26:27 -0800173 // Returns the largest possible client initiated bidirectional stream ID.
174 static QuicStreamId GetMaxClientInitiatedBidirectionalStreamId(
175 QuicTransportVersion version);
176
dschinazi8963f602020-05-15 13:14:16 -0700177 // Generates a connection ID of length |expected_connection_id_length|
178 // derived from |connection_id|.
dschinaziadc75072019-08-19 10:54:45 -0700179 // This is guaranteed to be deterministic (calling this method with two
180 // connection IDs that are equal is guaranteed to produce the same result).
181 static QuicConnectionId CreateReplacementConnectionId(
dschinazi8963f602020-05-15 13:14:16 -0700182 const QuicConnectionId& connection_id,
183 uint8_t expected_connection_id_length);
184
185 // Generates a 64bit connection ID derived from |connection_id|.
186 // This is guaranteed to be deterministic (calling this method with two
187 // connection IDs that are equal is guaranteed to produce the same result).
188 static QuicConnectionId CreateReplacementConnectionId(
189 const QuicConnectionId& connection_id);
dschinaziadc75072019-08-19 10:54:45 -0700190
QUICHE teama6ef0a62019-03-07 20:34:33 -0500191 // Generates a random 64bit connection ID.
192 static QuicConnectionId CreateRandomConnectionId();
193
194 // Generates a random 64bit connection ID using the provided QuicRandom.
195 static QuicConnectionId CreateRandomConnectionId(QuicRandom* random);
196
QUICHE teamc65d1d12019-03-19 20:58:04 -0700197 // Generates a random connection ID of the given length.
198 static QuicConnectionId CreateRandomConnectionId(
199 uint8_t connection_id_length);
200
201 // Generates a random connection ID of the given length using the provided
202 // QuicRandom.
203 static QuicConnectionId CreateRandomConnectionId(uint8_t connection_id_length,
204 QuicRandom* random);
205
dschinazi6c84c142019-07-31 09:11:49 -0700206 // Returns true if the connection ID length is valid for this QUIC version.
207 static bool IsConnectionIdLengthValidForVersion(
208 size_t connection_id_length,
209 QuicTransportVersion transport_version);
210
QUICHE teama6ef0a62019-03-07 20:34:33 -0500211 // Returns true if the connection ID is valid for this QUIC version.
dschinazi6c84c142019-07-31 09:11:49 -0700212 static bool IsConnectionIdValidForVersion(
213 QuicConnectionId connection_id,
214 QuicTransportVersion transport_version);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500215
216 // Returns a connection ID suitable for QUIC use-cases that do not need the
217 // connection ID for multiplexing. If the version allows variable lengths,
218 // a connection of length zero is returned, otherwise 64bits set to zero.
219 static QuicConnectionId CreateZeroConnectionId(QuicTransportVersion version);
220
221 // Generates a 128bit stateless reset token based on a connection ID.
bnc1ccd0bc2021-04-07 10:20:17 -0700222 static StatelessResetToken GenerateStatelessResetToken(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500223 QuicConnectionId connection_id);
QUICHE team10b22a12019-03-21 15:31:42 -0700224
225 // Determines packet number space from |encryption_level|.
226 static PacketNumberSpace GetPacketNumberSpace(
227 EncryptionLevel encryption_level);
QUICHE team1dfa46b2019-03-22 10:39:10 -0700228
229 // Determines encryption level to send packets in |packet_number_space|.
230 static EncryptionLevel GetEncryptionLevel(
231 PacketNumberSpace packet_number_space);
fkastenholz3c4eabf2019-04-22 07:49:59 -0700232
233 // Get the maximum value for a V99/IETF QUIC stream count. If a count
234 // exceeds this value, it will result in a stream ID that exceeds the
235 // implementation limit on stream ID size.
renjietangb885a122020-03-20 08:24:16 -0700236 static QuicStreamCount GetMaxStreamCount();
danzh623f6ef2020-08-25 16:44:37 -0700237
238 // Return true if this frame is an IETF probing frame.
239 static bool IsProbingFrame(QuicFrameType type);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240};
241
vasilvv2a2cecc2021-03-12 15:38:24 -0800242// Returns true if the specific ID is a valid WebTransport session ID that our
243// implementation can process.
244bool IsValidWebTransportSessionId(WebTransportSessionId id,
245 ParsedQuicVersion transport_version);
246
wubcfddec82020-01-13 07:45:27 -0800247template <typename Mask>
248class QUIC_EXPORT_PRIVATE BitMask {
249 public:
250 // explicit to prevent (incorrect) usage like "BitMask bitmask = 0;".
251 template <typename... Bits>
252 explicit BitMask(Bits... bits) {
253 mask_ = MakeMask(bits...);
254 }
255
256 BitMask() = default;
257 BitMask(const BitMask& other) = default;
258 BitMask& operator=(const BitMask& other) = default;
259
260 template <typename... Bits>
261 void Set(Bits... bits) {
262 mask_ |= MakeMask(bits...);
263 }
264
265 template <typename Bit>
266 bool IsSet(Bit bit) const {
267 return (MakeMask(bit) & mask_) != 0;
268 }
269
wub1dc01cf2020-01-27 13:04:14 -0800270 void ClearAll() { mask_ = 0; }
271
wubcfddec82020-01-13 07:45:27 -0800272 static constexpr size_t NumBits() { return 8 * sizeof(Mask); }
273
274 friend bool operator==(const BitMask& lhs, const BitMask& rhs) {
275 return lhs.mask_ == rhs.mask_;
276 }
277
278 std::string DebugString() const {
279 std::ostringstream oss;
280 oss << "0x" << std::hex << mask_;
281 return oss.str();
282 }
283
284 private:
285 template <typename Bit>
286 static std::enable_if_t<std::is_enum<Bit>::value, Mask> MakeMask(Bit bit) {
287 using IntType = typename std::underlying_type<Bit>::type;
288 return Mask(1) << static_cast<IntType>(bit);
289 }
290
291 template <typename Bit>
292 static std::enable_if_t<!std::is_enum<Bit>::value, Mask> MakeMask(Bit bit) {
293 return Mask(1) << bit;
294 }
295
296 template <typename Bit, typename... Bits>
297 static Mask MakeMask(Bit first_bit, Bits... other_bits) {
298 return MakeMask(first_bit) | MakeMask(other_bits...);
299 }
300
301 Mask mask_ = 0;
302};
303
304using BitMask64 = BitMask<uint64_t>;
305
QUICHE teama6ef0a62019-03-07 20:34:33 -0500306} // namespace quic
307
308#endif // QUICHE_QUIC_CORE_QUIC_UTILS_H_