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