• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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