• 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 #include "quiche/quic/core/quic_utils.h"
6 
7 #include <algorithm>
8 #include <cstdint>
9 #include <cstring>
10 #include <limits>
11 #include <string>
12 
13 #include "absl/base/macros.h"
14 #include "absl/base/optimization.h"
15 #include "absl/numeric/int128.h"
16 #include "absl/strings/string_view.h"
17 #include "openssl/sha.h"
18 #include "quiche/quic/core/quic_connection_id.h"
19 #include "quiche/quic/core/quic_constants.h"
20 #include "quiche/quic/core/quic_types.h"
21 #include "quiche/quic/core/quic_versions.h"
22 #include "quiche/quic/platform/api/quic_bug_tracker.h"
23 #include "quiche/quic/platform/api/quic_flag_utils.h"
24 #include "quiche/quic/platform/api/quic_flags.h"
25 #include "quiche/common/platform/api/quiche_logging.h"
26 #include "quiche/common/platform/api/quiche_mem_slice.h"
27 #include "quiche/common/quiche_endian.h"
28 
29 namespace quic {
30 namespace {
31 
32 // We know that >= GCC 4.8 and Clang have a __uint128_t intrinsic. Other
33 // compilers don't necessarily, notably MSVC.
34 #if defined(__x86_64__) &&                                         \
35     ((defined(__GNUC__) &&                                         \
36       (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \
37      defined(__clang__))
38 #define QUIC_UTIL_HAS_UINT128 1
39 #endif
40 
41 #ifdef QUIC_UTIL_HAS_UINT128
IncrementalHashFast(absl::uint128 uhash,absl::string_view data)42 absl::uint128 IncrementalHashFast(absl::uint128 uhash, absl::string_view data) {
43   // This code ends up faster than the naive implementation for 2 reasons:
44   // 1. absl::uint128 is sufficiently complicated that the compiler
45   //    cannot transform the multiplication by kPrime into a shift-multiply-add;
46   //    it has go through all of the instructions for a 128-bit multiply.
47   // 2. Because there are so fewer instructions (around 13), the hot loop fits
48   //    nicely in the instruction queue of many Intel CPUs.
49   // kPrime = 309485009821345068724781371
50   static const absl::uint128 kPrime =
51       (static_cast<absl::uint128>(16777216) << 64) + 315;
52   auto hi = absl::Uint128High64(uhash);
53   auto lo = absl::Uint128Low64(uhash);
54   absl::uint128 xhash = (static_cast<absl::uint128>(hi) << 64) + lo;
55   const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
56   for (size_t i = 0; i < data.length(); ++i) {
57     xhash = (xhash ^ static_cast<uint32_t>(octets[i])) * kPrime;
58   }
59   return absl::MakeUint128(absl::Uint128High64(xhash),
60                            absl::Uint128Low64(xhash));
61 }
62 #endif
63 
64 #ifndef QUIC_UTIL_HAS_UINT128
65 // Slow implementation of IncrementalHash. In practice, only used by Chromium.
IncrementalHashSlow(absl::uint128 hash,absl::string_view data)66 absl::uint128 IncrementalHashSlow(absl::uint128 hash, absl::string_view data) {
67   // kPrime = 309485009821345068724781371
68   static const absl::uint128 kPrime = absl::MakeUint128(16777216, 315);
69   const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
70   for (size_t i = 0; i < data.length(); ++i) {
71     hash = hash ^ absl::MakeUint128(0, octets[i]);
72     hash = hash * kPrime;
73   }
74   return hash;
75 }
76 #endif
77 
IncrementalHash(absl::uint128 hash,absl::string_view data)78 absl::uint128 IncrementalHash(absl::uint128 hash, absl::string_view data) {
79 #ifdef QUIC_UTIL_HAS_UINT128
80   return IncrementalHashFast(hash, data);
81 #else
82   return IncrementalHashSlow(hash, data);
83 #endif
84 }
85 
86 }  // namespace
87 
88 // static
FNV1a_64_Hash(absl::string_view data)89 uint64_t QuicUtils::FNV1a_64_Hash(absl::string_view data) {
90   static const uint64_t kOffset = UINT64_C(14695981039346656037);
91   static const uint64_t kPrime = UINT64_C(1099511628211);
92 
93   const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
94 
95   uint64_t hash = kOffset;
96 
97   for (size_t i = 0; i < data.length(); ++i) {
98     hash = hash ^ octets[i];
99     hash = hash * kPrime;
100   }
101 
102   return hash;
103 }
104 
105 // static
FNV1a_128_Hash(absl::string_view data)106 absl::uint128 QuicUtils::FNV1a_128_Hash(absl::string_view data) {
107   return FNV1a_128_Hash_Three(data, absl::string_view(), absl::string_view());
108 }
109 
110 // static
FNV1a_128_Hash_Two(absl::string_view data1,absl::string_view data2)111 absl::uint128 QuicUtils::FNV1a_128_Hash_Two(absl::string_view data1,
112                                             absl::string_view data2) {
113   return FNV1a_128_Hash_Three(data1, data2, absl::string_view());
114 }
115 
116 // static
FNV1a_128_Hash_Three(absl::string_view data1,absl::string_view data2,absl::string_view data3)117 absl::uint128 QuicUtils::FNV1a_128_Hash_Three(absl::string_view data1,
118                                               absl::string_view data2,
119                                               absl::string_view data3) {
120   // The two constants are defined as part of the hash algorithm.
121   // see http://www.isthe.com/chongo/tech/comp/fnv/
122   // kOffset = 144066263297769815596495629667062367629
123   const absl::uint128 kOffset = absl::MakeUint128(
124       UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
125 
126   absl::uint128 hash = IncrementalHash(kOffset, data1);
127   if (data2.empty()) {
128     return hash;
129   }
130 
131   hash = IncrementalHash(hash, data2);
132   if (data3.empty()) {
133     return hash;
134   }
135   return IncrementalHash(hash, data3);
136 }
137 
138 // static
SerializeUint128Short(absl::uint128 v,uint8_t * out)139 void QuicUtils::SerializeUint128Short(absl::uint128 v, uint8_t* out) {
140   const uint64_t lo = absl::Uint128Low64(v);
141   const uint64_t hi = absl::Uint128High64(v);
142   // This assumes that the system is little-endian.
143   memcpy(out, &lo, sizeof(lo));
144   memcpy(out + sizeof(lo), &hi, sizeof(hi) / 2);
145 }
146 
147 #define RETURN_STRING_LITERAL(x) \
148   case x:                        \
149     return #x;
150 
AddressChangeTypeToString(AddressChangeType type)151 std::string QuicUtils::AddressChangeTypeToString(AddressChangeType type) {
152   switch (type) {
153     RETURN_STRING_LITERAL(NO_CHANGE);
154     RETURN_STRING_LITERAL(PORT_CHANGE);
155     RETURN_STRING_LITERAL(IPV4_SUBNET_CHANGE);
156     RETURN_STRING_LITERAL(IPV4_TO_IPV6_CHANGE);
157     RETURN_STRING_LITERAL(IPV6_TO_IPV4_CHANGE);
158     RETURN_STRING_LITERAL(IPV6_TO_IPV6_CHANGE);
159     RETURN_STRING_LITERAL(IPV4_TO_IPV4_CHANGE);
160   }
161   return "INVALID_ADDRESS_CHANGE_TYPE";
162 }
163 
SentPacketStateToString(SentPacketState state)164 const char* QuicUtils::SentPacketStateToString(SentPacketState state) {
165   switch (state) {
166     RETURN_STRING_LITERAL(OUTSTANDING);
167     RETURN_STRING_LITERAL(NEVER_SENT);
168     RETURN_STRING_LITERAL(ACKED);
169     RETURN_STRING_LITERAL(UNACKABLE);
170     RETURN_STRING_LITERAL(NEUTERED);
171     RETURN_STRING_LITERAL(HANDSHAKE_RETRANSMITTED);
172     RETURN_STRING_LITERAL(LOST);
173     RETURN_STRING_LITERAL(PTO_RETRANSMITTED);
174     RETURN_STRING_LITERAL(NOT_CONTRIBUTING_RTT);
175   }
176   return "INVALID_SENT_PACKET_STATE";
177 }
178 
179 // static
QuicLongHeaderTypetoString(QuicLongHeaderType type)180 const char* QuicUtils::QuicLongHeaderTypetoString(QuicLongHeaderType type) {
181   switch (type) {
182     RETURN_STRING_LITERAL(VERSION_NEGOTIATION);
183     RETURN_STRING_LITERAL(INITIAL);
184     RETURN_STRING_LITERAL(RETRY);
185     RETURN_STRING_LITERAL(HANDSHAKE);
186     RETURN_STRING_LITERAL(ZERO_RTT_PROTECTED);
187     default:
188       return "INVALID_PACKET_TYPE";
189   }
190 }
191 
192 // static
AckResultToString(AckResult result)193 const char* QuicUtils::AckResultToString(AckResult result) {
194   switch (result) {
195     RETURN_STRING_LITERAL(PACKETS_NEWLY_ACKED);
196     RETURN_STRING_LITERAL(NO_PACKETS_NEWLY_ACKED);
197     RETURN_STRING_LITERAL(UNSENT_PACKETS_ACKED);
198     RETURN_STRING_LITERAL(UNACKABLE_PACKETS_ACKED);
199     RETURN_STRING_LITERAL(PACKETS_ACKED_IN_WRONG_PACKET_NUMBER_SPACE);
200   }
201   return "INVALID_ACK_RESULT";
202 }
203 
204 // static
DetermineAddressChangeType(const QuicSocketAddress & old_address,const QuicSocketAddress & new_address)205 AddressChangeType QuicUtils::DetermineAddressChangeType(
206     const QuicSocketAddress& old_address,
207     const QuicSocketAddress& new_address) {
208   if (!old_address.IsInitialized() || !new_address.IsInitialized() ||
209       old_address == new_address) {
210     return NO_CHANGE;
211   }
212 
213   if (old_address.host() == new_address.host()) {
214     return PORT_CHANGE;
215   }
216 
217   bool old_ip_is_ipv4 = old_address.host().IsIPv4() ? true : false;
218   bool migrating_ip_is_ipv4 = new_address.host().IsIPv4() ? true : false;
219   if (old_ip_is_ipv4 && !migrating_ip_is_ipv4) {
220     return IPV4_TO_IPV6_CHANGE;
221   }
222 
223   if (!old_ip_is_ipv4) {
224     return migrating_ip_is_ipv4 ? IPV6_TO_IPV4_CHANGE : IPV6_TO_IPV6_CHANGE;
225   }
226 
227   const int kSubnetMaskLength = 24;
228   if (old_address.host().InSameSubnet(new_address.host(), kSubnetMaskLength)) {
229     // Subnet part does not change (here, we use /24), which is considered to be
230     // caused by NATs.
231     return IPV4_SUBNET_CHANGE;
232   }
233 
234   return IPV4_TO_IPV4_CHANGE;
235 }
236 
237 // static
IsAckable(SentPacketState state)238 bool QuicUtils::IsAckable(SentPacketState state) {
239   return state != NEVER_SENT && state != ACKED && state != UNACKABLE;
240 }
241 
242 // static
IsRetransmittableFrame(QuicFrameType type)243 bool QuicUtils::IsRetransmittableFrame(QuicFrameType type) {
244   switch (type) {
245     case ACK_FRAME:
246     case PADDING_FRAME:
247     case STOP_WAITING_FRAME:
248     case MTU_DISCOVERY_FRAME:
249     case PATH_CHALLENGE_FRAME:
250     case PATH_RESPONSE_FRAME:
251       return false;
252     default:
253       return true;
254   }
255 }
256 
257 // static
IsHandshakeFrame(const QuicFrame & frame,QuicTransportVersion transport_version)258 bool QuicUtils::IsHandshakeFrame(const QuicFrame& frame,
259                                  QuicTransportVersion transport_version) {
260   if (!QuicVersionUsesCryptoFrames(transport_version)) {
261     return frame.type == STREAM_FRAME &&
262            frame.stream_frame.stream_id == GetCryptoStreamId(transport_version);
263   } else {
264     return frame.type == CRYPTO_FRAME;
265   }
266 }
267 
268 // static
ContainsFrameType(const QuicFrames & frames,QuicFrameType type)269 bool QuicUtils::ContainsFrameType(const QuicFrames& frames,
270                                   QuicFrameType type) {
271   for (const QuicFrame& frame : frames) {
272     if (frame.type == type) {
273       return true;
274     }
275   }
276   return false;
277 }
278 
279 // static
RetransmissionTypeToPacketState(TransmissionType retransmission_type)280 SentPacketState QuicUtils::RetransmissionTypeToPacketState(
281     TransmissionType retransmission_type) {
282   switch (retransmission_type) {
283     case ALL_ZERO_RTT_RETRANSMISSION:
284       return UNACKABLE;
285     case HANDSHAKE_RETRANSMISSION:
286       return HANDSHAKE_RETRANSMITTED;
287     case LOSS_RETRANSMISSION:
288       return LOST;
289     case PTO_RETRANSMISSION:
290       return PTO_RETRANSMITTED;
291     case PATH_RETRANSMISSION:
292       return NOT_CONTRIBUTING_RTT;
293     case ALL_INITIAL_RETRANSMISSION:
294       return UNACKABLE;
295     default:
296       QUIC_BUG(quic_bug_10839_2)
297           << retransmission_type << " is not a retransmission_type";
298       return UNACKABLE;
299   }
300 }
301 
302 // static
IsIetfPacketHeader(uint8_t first_byte)303 bool QuicUtils::IsIetfPacketHeader(uint8_t first_byte) {
304   return (first_byte & FLAGS_LONG_HEADER) || (first_byte & FLAGS_FIXED_BIT) ||
305          !(first_byte & FLAGS_DEMULTIPLEXING_BIT);
306 }
307 
308 // static
IsIetfPacketShortHeader(uint8_t first_byte)309 bool QuicUtils::IsIetfPacketShortHeader(uint8_t first_byte) {
310   return IsIetfPacketHeader(first_byte) && !(first_byte & FLAGS_LONG_HEADER);
311 }
312 
313 // static
GetInvalidStreamId(QuicTransportVersion version)314 QuicStreamId QuicUtils::GetInvalidStreamId(QuicTransportVersion version) {
315   return VersionHasIetfQuicFrames(version)
316              ? std::numeric_limits<QuicStreamId>::max()
317              : 0;
318 }
319 
320 // static
GetCryptoStreamId(QuicTransportVersion version)321 QuicStreamId QuicUtils::GetCryptoStreamId(QuicTransportVersion version) {
322   QUIC_BUG_IF(quic_bug_12982_1, QuicVersionUsesCryptoFrames(version))
323       << "CRYPTO data aren't in stream frames; they have no stream ID.";
324   return QuicVersionUsesCryptoFrames(version) ? GetInvalidStreamId(version) : 1;
325 }
326 
327 // static
IsCryptoStreamId(QuicTransportVersion version,QuicStreamId stream_id)328 bool QuicUtils::IsCryptoStreamId(QuicTransportVersion version,
329                                  QuicStreamId stream_id) {
330   if (QuicVersionUsesCryptoFrames(version)) {
331     return false;
332   }
333   return stream_id == GetCryptoStreamId(version);
334 }
335 
336 // static
GetHeadersStreamId(QuicTransportVersion version)337 QuicStreamId QuicUtils::GetHeadersStreamId(QuicTransportVersion version) {
338   QUICHE_DCHECK(!VersionUsesHttp3(version));
339   return GetFirstBidirectionalStreamId(version, Perspective::IS_CLIENT);
340 }
341 
342 // static
IsClientInitiatedStreamId(QuicTransportVersion version,QuicStreamId id)343 bool QuicUtils::IsClientInitiatedStreamId(QuicTransportVersion version,
344                                           QuicStreamId id) {
345   if (id == GetInvalidStreamId(version)) {
346     return false;
347   }
348   return VersionHasIetfQuicFrames(version) ? id % 2 == 0 : id % 2 != 0;
349 }
350 
351 // static
IsServerInitiatedStreamId(QuicTransportVersion version,QuicStreamId id)352 bool QuicUtils::IsServerInitiatedStreamId(QuicTransportVersion version,
353                                           QuicStreamId id) {
354   if (id == GetInvalidStreamId(version)) {
355     return false;
356   }
357   return VersionHasIetfQuicFrames(version) ? id % 2 != 0 : id % 2 == 0;
358 }
359 
360 // static
IsOutgoingStreamId(ParsedQuicVersion version,QuicStreamId id,Perspective perspective)361 bool QuicUtils::IsOutgoingStreamId(ParsedQuicVersion version, QuicStreamId id,
362                                    Perspective perspective) {
363   // Streams are outgoing streams, iff:
364   // - we are the server and the stream is server-initiated
365   // - we are the client and the stream is client-initiated.
366   const bool perspective_is_server = perspective == Perspective::IS_SERVER;
367   const bool stream_is_server =
368       QuicUtils::IsServerInitiatedStreamId(version.transport_version, id);
369   return perspective_is_server == stream_is_server;
370 }
371 
372 // static
IsBidirectionalStreamId(QuicStreamId id,ParsedQuicVersion version)373 bool QuicUtils::IsBidirectionalStreamId(QuicStreamId id,
374                                         ParsedQuicVersion version) {
375   QUICHE_DCHECK(version.HasIetfQuicFrames());
376   return id % 4 < 2;
377 }
378 
379 // static
GetStreamType(QuicStreamId id,Perspective perspective,bool peer_initiated,ParsedQuicVersion version)380 StreamType QuicUtils::GetStreamType(QuicStreamId id, Perspective perspective,
381                                     bool peer_initiated,
382                                     ParsedQuicVersion version) {
383   QUICHE_DCHECK(version.HasIetfQuicFrames());
384   if (IsBidirectionalStreamId(id, version)) {
385     return BIDIRECTIONAL;
386   }
387 
388   if (peer_initiated) {
389     if (perspective == Perspective::IS_SERVER) {
390       QUICHE_DCHECK_EQ(2u, id % 4);
391     } else {
392       QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective);
393       QUICHE_DCHECK_EQ(3u, id % 4);
394     }
395     return READ_UNIDIRECTIONAL;
396   }
397 
398   if (perspective == Perspective::IS_SERVER) {
399     QUICHE_DCHECK_EQ(3u, id % 4);
400   } else {
401     QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective);
402     QUICHE_DCHECK_EQ(2u, id % 4);
403   }
404   return WRITE_UNIDIRECTIONAL;
405 }
406 
407 // static
StreamIdDelta(QuicTransportVersion version)408 QuicStreamId QuicUtils::StreamIdDelta(QuicTransportVersion version) {
409   return VersionHasIetfQuicFrames(version) ? 4 : 2;
410 }
411 
412 // static
GetFirstBidirectionalStreamId(QuicTransportVersion version,Perspective perspective)413 QuicStreamId QuicUtils::GetFirstBidirectionalStreamId(
414     QuicTransportVersion version, Perspective perspective) {
415   if (VersionHasIetfQuicFrames(version)) {
416     return perspective == Perspective::IS_CLIENT ? 0 : 1;
417   } else if (QuicVersionUsesCryptoFrames(version)) {
418     return perspective == Perspective::IS_CLIENT ? 1 : 2;
419   }
420   return perspective == Perspective::IS_CLIENT ? 3 : 2;
421 }
422 
423 // static
GetFirstUnidirectionalStreamId(QuicTransportVersion version,Perspective perspective)424 QuicStreamId QuicUtils::GetFirstUnidirectionalStreamId(
425     QuicTransportVersion version, Perspective perspective) {
426   if (VersionHasIetfQuicFrames(version)) {
427     return perspective == Perspective::IS_CLIENT ? 2 : 3;
428   } else if (QuicVersionUsesCryptoFrames(version)) {
429     return perspective == Perspective::IS_CLIENT ? 1 : 2;
430   }
431   return perspective == Perspective::IS_CLIENT ? 3 : 2;
432 }
433 
434 // static
GetMaxClientInitiatedBidirectionalStreamId(QuicTransportVersion version)435 QuicStreamId QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
436     QuicTransportVersion version) {
437   if (VersionHasIetfQuicFrames(version)) {
438     // Client initiated bidirectional streams have stream IDs divisible by 4.
439     return std::numeric_limits<QuicStreamId>::max() - 3;
440   }
441 
442   // Client initiated bidirectional streams have odd stream IDs.
443   return std::numeric_limits<QuicStreamId>::max();
444 }
445 
446 // static
CreateRandomConnectionId()447 QuicConnectionId QuicUtils::CreateRandomConnectionId() {
448   return CreateRandomConnectionId(kQuicDefaultConnectionIdLength,
449                                   QuicRandom::GetInstance());
450 }
451 
452 // static
CreateRandomConnectionId(QuicRandom * random)453 QuicConnectionId QuicUtils::CreateRandomConnectionId(QuicRandom* random) {
454   return CreateRandomConnectionId(kQuicDefaultConnectionIdLength, random);
455 }
456 // static
CreateRandomConnectionId(uint8_t connection_id_length)457 QuicConnectionId QuicUtils::CreateRandomConnectionId(
458     uint8_t connection_id_length) {
459   return CreateRandomConnectionId(connection_id_length,
460                                   QuicRandom::GetInstance());
461 }
462 
463 // static
CreateRandomConnectionId(uint8_t connection_id_length,QuicRandom * random)464 QuicConnectionId QuicUtils::CreateRandomConnectionId(
465     uint8_t connection_id_length, QuicRandom* random) {
466   QuicConnectionId connection_id;
467   connection_id.set_length(connection_id_length);
468   if (connection_id.length() > 0) {
469     random->RandBytes(connection_id.mutable_data(), connection_id.length());
470   }
471   return connection_id;
472 }
473 
474 // static
CreateZeroConnectionId(QuicTransportVersion version)475 QuicConnectionId QuicUtils::CreateZeroConnectionId(
476     QuicTransportVersion version) {
477   if (!VersionAllowsVariableLengthConnectionIds(version)) {
478     char connection_id_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
479     return QuicConnectionId(static_cast<char*>(connection_id_bytes),
480                             ABSL_ARRAYSIZE(connection_id_bytes));
481   }
482   return EmptyQuicConnectionId();
483 }
484 
485 // static
IsConnectionIdLengthValidForVersion(size_t connection_id_length,QuicTransportVersion transport_version)486 bool QuicUtils::IsConnectionIdLengthValidForVersion(
487     size_t connection_id_length, QuicTransportVersion transport_version) {
488   // No version of QUIC can support lengths that do not fit in an uint8_t.
489   if (connection_id_length >
490       static_cast<size_t>(std::numeric_limits<uint8_t>::max())) {
491     return false;
492   }
493 
494   if (transport_version == QUIC_VERSION_UNSUPPORTED ||
495       transport_version == QUIC_VERSION_RESERVED_FOR_NEGOTIATION) {
496     // Unknown versions could allow connection ID lengths up to 255.
497     return true;
498   }
499 
500   const uint8_t connection_id_length8 =
501       static_cast<uint8_t>(connection_id_length);
502   // Versions that do not support variable lengths only support length 8.
503   if (!VersionAllowsVariableLengthConnectionIds(transport_version)) {
504     return connection_id_length8 == kQuicDefaultConnectionIdLength;
505   }
506   return connection_id_length8 <= kQuicMaxConnectionIdWithLengthPrefixLength;
507 }
508 
509 // static
IsConnectionIdValidForVersion(QuicConnectionId connection_id,QuicTransportVersion transport_version)510 bool QuicUtils::IsConnectionIdValidForVersion(
511     QuicConnectionId connection_id, QuicTransportVersion transport_version) {
512   return IsConnectionIdLengthValidForVersion(connection_id.length(),
513                                              transport_version);
514 }
515 
GenerateStatelessResetToken(QuicConnectionId connection_id)516 StatelessResetToken QuicUtils::GenerateStatelessResetToken(
517     QuicConnectionId connection_id) {
518   static_assert(sizeof(absl::uint128) == sizeof(StatelessResetToken),
519                 "bad size");
520   static_assert(alignof(absl::uint128) >= alignof(StatelessResetToken),
521                 "bad alignment");
522   absl::uint128 hash = FNV1a_128_Hash(
523       absl::string_view(connection_id.data(), connection_id.length()));
524   return *reinterpret_cast<StatelessResetToken*>(&hash);
525 }
526 
527 // static
GetMaxStreamCount()528 QuicStreamCount QuicUtils::GetMaxStreamCount() {
529   return (kMaxQuicStreamCount >> 2) + 1;
530 }
531 
532 // static
GetPacketNumberSpace(EncryptionLevel encryption_level)533 PacketNumberSpace QuicUtils::GetPacketNumberSpace(
534     EncryptionLevel encryption_level) {
535   switch (encryption_level) {
536     case ENCRYPTION_INITIAL:
537       return INITIAL_DATA;
538     case ENCRYPTION_HANDSHAKE:
539       return HANDSHAKE_DATA;
540     case ENCRYPTION_ZERO_RTT:
541     case ENCRYPTION_FORWARD_SECURE:
542       return APPLICATION_DATA;
543     default:
544       QUIC_BUG(quic_bug_10839_3)
545           << "Try to get packet number space of encryption level: "
546           << encryption_level;
547       return NUM_PACKET_NUMBER_SPACES;
548   }
549 }
550 
551 // static
GetEncryptionLevelToSendAckofSpace(PacketNumberSpace packet_number_space)552 EncryptionLevel QuicUtils::GetEncryptionLevelToSendAckofSpace(
553     PacketNumberSpace packet_number_space) {
554   switch (packet_number_space) {
555     case INITIAL_DATA:
556       return ENCRYPTION_INITIAL;
557     case HANDSHAKE_DATA:
558       return ENCRYPTION_HANDSHAKE;
559     case APPLICATION_DATA:
560       return ENCRYPTION_FORWARD_SECURE;
561     default:
562       QUICHE_DCHECK(false);
563       return NUM_ENCRYPTION_LEVELS;
564   }
565 }
566 
567 // static
IsProbingFrame(QuicFrameType type)568 bool QuicUtils::IsProbingFrame(QuicFrameType type) {
569   switch (type) {
570     case PATH_CHALLENGE_FRAME:
571     case PATH_RESPONSE_FRAME:
572     case NEW_CONNECTION_ID_FRAME:
573     case PADDING_FRAME:
574       return true;
575     default:
576       return false;
577   }
578 }
579 
580 // static
IsAckElicitingFrame(QuicFrameType type)581 bool QuicUtils::IsAckElicitingFrame(QuicFrameType type) {
582   switch (type) {
583     case PADDING_FRAME:
584     case STOP_WAITING_FRAME:
585     case ACK_FRAME:
586     case CONNECTION_CLOSE_FRAME:
587       return false;
588     default:
589       return true;
590   }
591 }
592 
593 // static
AreStatelessResetTokensEqual(const StatelessResetToken & token1,const StatelessResetToken & token2)594 bool QuicUtils::AreStatelessResetTokensEqual(
595     const StatelessResetToken& token1, const StatelessResetToken& token2) {
596   char byte = 0;
597   for (size_t i = 0; i < kStatelessResetTokenLength; i++) {
598     // This avoids compiler optimizations that could make us stop comparing
599     // after we find a byte that doesn't match.
600     byte |= (token1[i] ^ token2[i]);
601   }
602   return byte == 0;
603 }
604 
IsValidWebTransportSessionId(WebTransportSessionId id,ParsedQuicVersion version)605 bool IsValidWebTransportSessionId(WebTransportSessionId id,
606                                   ParsedQuicVersion version) {
607   QUICHE_DCHECK(version.UsesHttp3());
608   return (id <= std::numeric_limits<QuicStreamId>::max()) &&
609          QuicUtils::IsBidirectionalStreamId(id, version) &&
610          QuicUtils::IsClientInitiatedStreamId(version.transport_version, id);
611 }
612 
MemSliceSpanTotalSize(absl::Span<quiche::QuicheMemSlice> span)613 QuicByteCount MemSliceSpanTotalSize(absl::Span<quiche::QuicheMemSlice> span) {
614   QuicByteCount total = 0;
615   for (const quiche::QuicheMemSlice& slice : span) {
616     total += slice.length();
617   }
618   return total;
619 }
620 
RawSha256(absl::string_view input)621 std::string RawSha256(absl::string_view input) {
622   std::string raw_hash;
623   raw_hash.resize(SHA256_DIGEST_LENGTH);
624   SHA256(reinterpret_cast<const uint8_t*>(input.data()), input.size(),
625          reinterpret_cast<uint8_t*>(&raw_hash[0]));
626   return raw_hash;
627 }
628 
629 #undef RETURN_STRING_LITERAL  // undef for jumbo builds
630 }  // namespace quic
631