xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_versions.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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_versions.h"
6 
7 #include <string>
8 
9 #include "absl/base/macros.h"
10 #include "absl/strings/numbers.h"
11 #include "absl/strings/str_cat.h"
12 #include "absl/strings/str_split.h"
13 #include "quiche/quic/core/crypto/quic_random.h"
14 #include "quiche/quic/core/quic_tag.h"
15 #include "quiche/quic/core/quic_types.h"
16 #include "quiche/quic/platform/api/quic_bug_tracker.h"
17 #include "quiche/quic/platform/api/quic_flag_utils.h"
18 #include "quiche/quic/platform/api/quic_flags.h"
19 #include "quiche/quic/platform/api/quic_logging.h"
20 #include "quiche/common/quiche_endian.h"
21 #include "quiche/common/quiche_text_utils.h"
22 
23 namespace quic {
24 namespace {
25 
CreateRandomVersionLabelForNegotiation()26 QuicVersionLabel CreateRandomVersionLabelForNegotiation() {
27   QuicVersionLabel result;
28   if (!GetQuicFlag(quic_disable_version_negotiation_grease_randomness)) {
29     QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
30   } else {
31     result = MakeVersionLabel(0xd1, 0x57, 0x38, 0x3f);
32   }
33   result &= 0xf0f0f0f0;
34   result |= 0x0a0a0a0a;
35   return result;
36 }
37 
SetVersionFlag(const ParsedQuicVersion & version,bool should_enable)38 void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) {
39   static_assert(SupportedVersions().size() == 4u,
40                 "Supported versions out of sync");
41   const bool enable = should_enable;
42   const bool disable = !should_enable;
43   if (version == ParsedQuicVersion::RFCv2()) {
44     SetQuicReloadableFlag(quic_enable_version_rfcv2, enable);
45   } else if (version == ParsedQuicVersion::RFCv1()) {
46     SetQuicReloadableFlag(quic_disable_version_rfcv1, disable);
47   } else if (version == ParsedQuicVersion::Draft29()) {
48     SetQuicReloadableFlag(quic_disable_version_draft_29, disable);
49   } else if (version == ParsedQuicVersion::Q046()) {
50     SetQuicReloadableFlag(quic_disable_version_q046, disable);
51   } else {
52     QUIC_BUG(quic_bug_10589_1)
53         << "Cannot " << (enable ? "en" : "dis") << "able version " << version;
54   }
55 }
56 
57 }  // namespace
58 
IsKnown() const59 bool ParsedQuicVersion::IsKnown() const {
60   QUICHE_DCHECK(ParsedQuicVersionIsValid(handshake_protocol, transport_version))
61       << QuicVersionToString(transport_version) << " "
62       << HandshakeProtocolToString(handshake_protocol);
63   return transport_version != QUIC_VERSION_UNSUPPORTED;
64 }
65 
KnowsWhichDecrypterToUse() const66 bool ParsedQuicVersion::KnowsWhichDecrypterToUse() const {
67   QUICHE_DCHECK(IsKnown());
68   return transport_version > QUIC_VERSION_46;
69 }
70 
UsesInitialObfuscators() const71 bool ParsedQuicVersion::UsesInitialObfuscators() const {
72   QUICHE_DCHECK(IsKnown());
73   // Initial obfuscators were added in version 50.
74   return transport_version > QUIC_VERSION_46;
75 }
76 
AllowsLowFlowControlLimits() const77 bool ParsedQuicVersion::AllowsLowFlowControlLimits() const {
78   QUICHE_DCHECK(IsKnown());
79   // Low flow-control limits are used for all IETF versions.
80   return UsesHttp3();
81 }
82 
HasHeaderProtection() const83 bool ParsedQuicVersion::HasHeaderProtection() const {
84   QUICHE_DCHECK(IsKnown());
85   // Header protection was added in version 50.
86   return transport_version > QUIC_VERSION_46;
87 }
88 
SupportsRetry() const89 bool ParsedQuicVersion::SupportsRetry() const {
90   QUICHE_DCHECK(IsKnown());
91   // Retry was added in version 47.
92   return transport_version > QUIC_VERSION_46;
93 }
94 
SendsVariableLengthPacketNumberInLongHeader() const95 bool ParsedQuicVersion::SendsVariableLengthPacketNumberInLongHeader() const {
96   QUICHE_DCHECK(IsKnown());
97   return transport_version > QUIC_VERSION_46;
98 }
99 
AllowsVariableLengthConnectionIds() const100 bool ParsedQuicVersion::AllowsVariableLengthConnectionIds() const {
101   QUICHE_DCHECK(IsKnown());
102   return VersionAllowsVariableLengthConnectionIds(transport_version);
103 }
104 
SupportsClientConnectionIds() const105 bool ParsedQuicVersion::SupportsClientConnectionIds() const {
106   QUICHE_DCHECK(IsKnown());
107   // Client connection IDs were added in version 49.
108   return transport_version > QUIC_VERSION_46;
109 }
110 
HasLengthPrefixedConnectionIds() const111 bool ParsedQuicVersion::HasLengthPrefixedConnectionIds() const {
112   QUICHE_DCHECK(IsKnown());
113   return VersionHasLengthPrefixedConnectionIds(transport_version);
114 }
115 
SupportsAntiAmplificationLimit() const116 bool ParsedQuicVersion::SupportsAntiAmplificationLimit() const {
117   QUICHE_DCHECK(IsKnown());
118   // The anti-amplification limit is used for all IETF versions.
119   return UsesHttp3();
120 }
121 
CanSendCoalescedPackets() const122 bool ParsedQuicVersion::CanSendCoalescedPackets() const {
123   QUICHE_DCHECK(IsKnown());
124   return HasLongHeaderLengths() && UsesTls();
125 }
126 
SupportsGoogleAltSvcFormat() const127 bool ParsedQuicVersion::SupportsGoogleAltSvcFormat() const {
128   QUICHE_DCHECK(IsKnown());
129   return VersionSupportsGoogleAltSvcFormat(transport_version);
130 }
131 
UsesHttp3() const132 bool ParsedQuicVersion::UsesHttp3() const {
133   QUICHE_DCHECK(IsKnown());
134   return VersionUsesHttp3(transport_version);
135 }
136 
HasLongHeaderLengths() const137 bool ParsedQuicVersion::HasLongHeaderLengths() const {
138   QUICHE_DCHECK(IsKnown());
139   return QuicVersionHasLongHeaderLengths(transport_version);
140 }
141 
UsesCryptoFrames() const142 bool ParsedQuicVersion::UsesCryptoFrames() const {
143   QUICHE_DCHECK(IsKnown());
144   return QuicVersionUsesCryptoFrames(transport_version);
145 }
146 
HasIetfQuicFrames() const147 bool ParsedQuicVersion::HasIetfQuicFrames() const {
148   QUICHE_DCHECK(IsKnown());
149   return VersionHasIetfQuicFrames(transport_version);
150 }
151 
UsesLegacyTlsExtension() const152 bool ParsedQuicVersion::UsesLegacyTlsExtension() const {
153   QUICHE_DCHECK(IsKnown());
154   return UsesTls() && transport_version <= QUIC_VERSION_IETF_DRAFT_29;
155 }
156 
UsesTls() const157 bool ParsedQuicVersion::UsesTls() const {
158   QUICHE_DCHECK(IsKnown());
159   return handshake_protocol == PROTOCOL_TLS1_3;
160 }
161 
UsesQuicCrypto() const162 bool ParsedQuicVersion::UsesQuicCrypto() const {
163   QUICHE_DCHECK(IsKnown());
164   return handshake_protocol == PROTOCOL_QUIC_CRYPTO;
165 }
166 
UsesV2PacketTypes() const167 bool ParsedQuicVersion::UsesV2PacketTypes() const {
168   QUICHE_DCHECK(IsKnown());
169   return transport_version == QUIC_VERSION_IETF_RFC_V2;
170 }
171 
AlpnDeferToRFCv1() const172 bool ParsedQuicVersion::AlpnDeferToRFCv1() const {
173   QUICHE_DCHECK(IsKnown());
174   return transport_version == QUIC_VERSION_IETF_RFC_V2;
175 }
176 
VersionHasLengthPrefixedConnectionIds(QuicTransportVersion transport_version)177 bool VersionHasLengthPrefixedConnectionIds(
178     QuicTransportVersion transport_version) {
179   QUICHE_DCHECK(transport_version != QUIC_VERSION_UNSUPPORTED);
180   // Length-prefixed connection IDs were added in version 49.
181   return transport_version > QUIC_VERSION_46;
182 }
183 
operator <<(std::ostream & os,const ParsedQuicVersion & version)184 std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
185   os << ParsedQuicVersionToString(version);
186   return os;
187 }
188 
operator <<(std::ostream & os,const ParsedQuicVersionVector & versions)189 std::ostream& operator<<(std::ostream& os,
190                          const ParsedQuicVersionVector& versions) {
191   os << ParsedQuicVersionVectorToString(versions);
192   return os;
193 }
194 
MakeVersionLabel(uint8_t a,uint8_t b,uint8_t c,uint8_t d)195 QuicVersionLabel MakeVersionLabel(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
196   return MakeQuicTag(d, c, b, a);
197 }
198 
operator <<(std::ostream & os,const QuicVersionLabelVector & version_labels)199 std::ostream& operator<<(std::ostream& os,
200                          const QuicVersionLabelVector& version_labels) {
201   os << QuicVersionLabelVectorToString(version_labels);
202   return os;
203 }
204 
operator <<(std::ostream & os,const QuicTransportVersionVector & transport_versions)205 std::ostream& operator<<(std::ostream& os,
206                          const QuicTransportVersionVector& transport_versions) {
207   os << QuicTransportVersionVectorToString(transport_versions);
208   return os;
209 }
210 
CreateQuicVersionLabel(ParsedQuicVersion parsed_version)211 QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
212   static_assert(SupportedVersions().size() == 4u,
213                 "Supported versions out of sync");
214   if (parsed_version == ParsedQuicVersion::RFCv2()) {
215     return MakeVersionLabel(0x6b, 0x33, 0x43, 0xcf);
216   } else if (parsed_version == ParsedQuicVersion::RFCv1()) {
217     return MakeVersionLabel(0x00, 0x00, 0x00, 0x01);
218   } else if (parsed_version == ParsedQuicVersion::Draft29()) {
219     return MakeVersionLabel(0xff, 0x00, 0x00, 29);
220   } else if (parsed_version == ParsedQuicVersion::Q046()) {
221     return MakeVersionLabel('Q', '0', '4', '6');
222   } else if (parsed_version == ParsedQuicVersion::ReservedForNegotiation()) {
223     return CreateRandomVersionLabelForNegotiation();
224   }
225   QUIC_BUG(quic_bug_10589_2)
226       << "Unsupported version "
227       << QuicVersionToString(parsed_version.transport_version) << " "
228       << HandshakeProtocolToString(parsed_version.handshake_protocol);
229   return 0;
230 }
231 
CreateQuicVersionLabelVector(const ParsedQuicVersionVector & versions)232 QuicVersionLabelVector CreateQuicVersionLabelVector(
233     const ParsedQuicVersionVector& versions) {
234   QuicVersionLabelVector out;
235   out.reserve(versions.size());
236   for (const auto& version : versions) {
237     out.push_back(CreateQuicVersionLabel(version));
238   }
239   return out;
240 }
241 
AllSupportedVersionsWithQuicCrypto()242 ParsedQuicVersionVector AllSupportedVersionsWithQuicCrypto() {
243   ParsedQuicVersionVector versions;
244   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
245     if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
246       versions.push_back(version);
247     }
248   }
249   QUIC_BUG_IF(quic_bug_10589_3, versions.empty())
250       << "No version with QUIC crypto found.";
251   return versions;
252 }
253 
CurrentSupportedVersionsWithQuicCrypto()254 ParsedQuicVersionVector CurrentSupportedVersionsWithQuicCrypto() {
255   ParsedQuicVersionVector versions;
256   for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
257     if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
258       versions.push_back(version);
259     }
260   }
261   QUIC_BUG_IF(quic_bug_10589_4, versions.empty())
262       << "No version with QUIC crypto found.";
263   return versions;
264 }
265 
AllSupportedVersionsWithTls()266 ParsedQuicVersionVector AllSupportedVersionsWithTls() {
267   ParsedQuicVersionVector versions;
268   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
269     if (version.UsesTls()) {
270       versions.push_back(version);
271     }
272   }
273   QUIC_BUG_IF(quic_bug_10589_5, versions.empty())
274       << "No version with TLS handshake found.";
275   return versions;
276 }
277 
CurrentSupportedVersionsWithTls()278 ParsedQuicVersionVector CurrentSupportedVersionsWithTls() {
279   ParsedQuicVersionVector versions;
280   for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
281     if (version.UsesTls()) {
282       versions.push_back(version);
283     }
284   }
285   QUIC_BUG_IF(quic_bug_10589_6, versions.empty())
286       << "No version with TLS handshake found.";
287   return versions;
288 }
289 
ObsoleteSupportedVersions()290 ParsedQuicVersionVector ObsoleteSupportedVersions() {
291   return ParsedQuicVersionVector{quic::ParsedQuicVersion::Q046(),
292                                  quic::ParsedQuicVersion::Draft29()};
293 }
294 
IsObsoleteSupportedVersion(ParsedQuicVersion version)295 bool IsObsoleteSupportedVersion(ParsedQuicVersion version) {
296   static const ParsedQuicVersionVector obsolete_versions =
297       ObsoleteSupportedVersions();
298   for (const ParsedQuicVersion& obsolete_version : obsolete_versions) {
299     if (version == obsolete_version) {
300       return true;
301     }
302   }
303   return false;
304 }
305 
CurrentSupportedVersionsForClients()306 ParsedQuicVersionVector CurrentSupportedVersionsForClients() {
307   ParsedQuicVersionVector versions;
308   for (const ParsedQuicVersion& version : CurrentSupportedVersionsWithTls()) {
309     QUICHE_DCHECK_EQ(version.handshake_protocol, PROTOCOL_TLS1_3);
310     if (version.transport_version >= QUIC_VERSION_IETF_RFC_V1) {
311       versions.push_back(version);
312     }
313   }
314   QUIC_BUG_IF(quic_bug_10589_8, versions.empty())
315       << "No supported client versions found.";
316   return versions;
317 }
318 
CurrentSupportedHttp3Versions()319 ParsedQuicVersionVector CurrentSupportedHttp3Versions() {
320   ParsedQuicVersionVector versions;
321   for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
322     if (version.UsesHttp3()) {
323       versions.push_back(version);
324     }
325   }
326   QUIC_BUG_IF(no_version_uses_http3, versions.empty())
327       << "No version speaking Http3 found.";
328   return versions;
329 }
330 
ParseQuicVersionLabel(QuicVersionLabel version_label)331 ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
332   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
333     if (version_label == CreateQuicVersionLabel(version)) {
334       return version;
335     }
336   }
337   // Reading from the client so this should not be considered an ERROR.
338   QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
339                   << QuicVersionLabelToString(version_label);
340   return UnsupportedQuicVersion();
341 }
342 
ParseQuicVersionLabelVector(const QuicVersionLabelVector & version_labels)343 ParsedQuicVersionVector ParseQuicVersionLabelVector(
344     const QuicVersionLabelVector& version_labels) {
345   ParsedQuicVersionVector parsed_versions;
346   for (const QuicVersionLabel& version_label : version_labels) {
347     ParsedQuicVersion parsed_version = ParseQuicVersionLabel(version_label);
348     if (parsed_version.IsKnown()) {
349       parsed_versions.push_back(parsed_version);
350     }
351   }
352   return parsed_versions;
353 }
354 
ParseQuicVersionString(absl::string_view version_string)355 ParsedQuicVersion ParseQuicVersionString(absl::string_view version_string) {
356   if (version_string.empty()) {
357     return UnsupportedQuicVersion();
358   }
359   const ParsedQuicVersionVector supported_versions = AllSupportedVersions();
360   for (const ParsedQuicVersion& version : supported_versions) {
361     if (version_string == ParsedQuicVersionToString(version) ||
362         (version_string == AlpnForVersion(version) &&
363          !version.AlpnDeferToRFCv1()) ||
364         (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO &&
365          version_string == QuicVersionToString(version.transport_version))) {
366       return version;
367     }
368   }
369   for (const ParsedQuicVersion& version : supported_versions) {
370     if (version.UsesHttp3() &&
371         version_string ==
372             QuicVersionLabelToString(CreateQuicVersionLabel(version))) {
373       return version;
374     }
375   }
376   int quic_version_number = 0;
377   if (absl::SimpleAtoi(version_string, &quic_version_number) &&
378       quic_version_number > 0) {
379     QuicTransportVersion transport_version =
380         static_cast<QuicTransportVersion>(quic_version_number);
381     if (!ParsedQuicVersionIsValid(PROTOCOL_QUIC_CRYPTO, transport_version)) {
382       return UnsupportedQuicVersion();
383     }
384     ParsedQuicVersion version(PROTOCOL_QUIC_CRYPTO, transport_version);
385     if (std::find(supported_versions.begin(), supported_versions.end(),
386                   version) != supported_versions.end()) {
387       return version;
388     }
389     return UnsupportedQuicVersion();
390   }
391   // Reading from the client so this should not be considered an ERROR.
392   QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string
393                   << "\".";
394   return UnsupportedQuicVersion();
395 }
396 
ParseQuicVersionVectorString(absl::string_view versions_string)397 ParsedQuicVersionVector ParseQuicVersionVectorString(
398     absl::string_view versions_string) {
399   ParsedQuicVersionVector versions;
400   std::vector<absl::string_view> version_strings =
401       absl::StrSplit(versions_string, ',');
402   for (absl::string_view version_string : version_strings) {
403     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
404         &version_string);
405     ParsedQuicVersion version = ParseQuicVersionString(version_string);
406     if (!version.IsKnown() || std::find(versions.begin(), versions.end(),
407                                         version) != versions.end()) {
408       continue;
409     }
410     versions.push_back(version);
411   }
412   return versions;
413 }
414 
AllSupportedTransportVersions()415 QuicTransportVersionVector AllSupportedTransportVersions() {
416   QuicTransportVersionVector transport_versions;
417   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
418     if (std::find(transport_versions.begin(), transport_versions.end(),
419                   version.transport_version) == transport_versions.end()) {
420       transport_versions.push_back(version.transport_version);
421     }
422   }
423   return transport_versions;
424 }
425 
AllSupportedVersions()426 ParsedQuicVersionVector AllSupportedVersions() {
427   constexpr auto supported_versions = SupportedVersions();
428   return ParsedQuicVersionVector(supported_versions.begin(),
429                                  supported_versions.end());
430 }
431 
CurrentSupportedVersions()432 ParsedQuicVersionVector CurrentSupportedVersions() {
433   return FilterSupportedVersions(AllSupportedVersions());
434 }
435 
FilterSupportedVersions(ParsedQuicVersionVector versions)436 ParsedQuicVersionVector FilterSupportedVersions(
437     ParsedQuicVersionVector versions) {
438   static_assert(SupportedVersions().size() == 4u,
439                 "Supported versions out of sync");
440   ParsedQuicVersionVector filtered_versions;
441   filtered_versions.reserve(versions.size());
442   for (const ParsedQuicVersion& version : versions) {
443     if (version == ParsedQuicVersion::RFCv2()) {
444       if (GetQuicReloadableFlag(quic_enable_version_rfcv2)) {
445         filtered_versions.push_back(version);
446       }
447     } else if (version == ParsedQuicVersion::RFCv1()) {
448       if (!GetQuicReloadableFlag(quic_disable_version_rfcv1)) {
449         filtered_versions.push_back(version);
450       }
451     } else if (version == ParsedQuicVersion::Draft29()) {
452       if (!GetQuicReloadableFlag(quic_disable_version_draft_29)) {
453         filtered_versions.push_back(version);
454       }
455     } else if (version == ParsedQuicVersion::Q046()) {
456       if (!GetQuicReloadableFlag(quic_disable_version_q046)) {
457         filtered_versions.push_back(version);
458       }
459     } else {
460       QUIC_BUG(quic_bug_10589_7)
461           << "QUIC version " << version << " has no flag protection";
462       filtered_versions.push_back(version);
463     }
464   }
465   return filtered_versions;
466 }
467 
ParsedVersionOfIndex(const ParsedQuicVersionVector & versions,int index)468 ParsedQuicVersionVector ParsedVersionOfIndex(
469     const ParsedQuicVersionVector& versions, int index) {
470   ParsedQuicVersionVector version;
471   int version_count = versions.size();
472   if (index >= 0 && index < version_count) {
473     version.push_back(versions[index]);
474   } else {
475     version.push_back(UnsupportedQuicVersion());
476   }
477   return version;
478 }
479 
QuicVersionLabelToString(QuicVersionLabel version_label)480 std::string QuicVersionLabelToString(QuicVersionLabel version_label) {
481   return QuicTagToString(quiche::QuicheEndian::HostToNet32(version_label));
482 }
483 
ParseQuicVersionLabelString(absl::string_view version_label_string)484 ParsedQuicVersion ParseQuicVersionLabelString(
485     absl::string_view version_label_string) {
486   const ParsedQuicVersionVector supported_versions = AllSupportedVersions();
487   for (const ParsedQuicVersion& version : supported_versions) {
488     if (version_label_string ==
489         QuicVersionLabelToString(CreateQuicVersionLabel(version))) {
490       return version;
491     }
492   }
493   return UnsupportedQuicVersion();
494 }
495 
QuicVersionLabelVectorToString(const QuicVersionLabelVector & version_labels,const std::string & separator,size_t skip_after_nth_version)496 std::string QuicVersionLabelVectorToString(
497     const QuicVersionLabelVector& version_labels, const std::string& separator,
498     size_t skip_after_nth_version) {
499   std::string result;
500   for (size_t i = 0; i < version_labels.size(); ++i) {
501     if (i != 0) {
502       result.append(separator);
503     }
504 
505     if (i > skip_after_nth_version) {
506       result.append("...");
507       break;
508     }
509     result.append(QuicVersionLabelToString(version_labels[i]));
510   }
511   return result;
512 }
513 
514 #define RETURN_STRING_LITERAL(x) \
515   case x:                        \
516     return #x
517 
QuicVersionToString(QuicTransportVersion transport_version)518 std::string QuicVersionToString(QuicTransportVersion transport_version) {
519   switch (transport_version) {
520     RETURN_STRING_LITERAL(QUIC_VERSION_46);
521     RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_29);
522     RETURN_STRING_LITERAL(QUIC_VERSION_IETF_RFC_V1);
523     RETURN_STRING_LITERAL(QUIC_VERSION_IETF_RFC_V2);
524     RETURN_STRING_LITERAL(QUIC_VERSION_UNSUPPORTED);
525     RETURN_STRING_LITERAL(QUIC_VERSION_RESERVED_FOR_NEGOTIATION);
526   }
527   return absl::StrCat("QUIC_VERSION_UNKNOWN(",
528                       static_cast<int>(transport_version), ")");
529 }
530 
HandshakeProtocolToString(HandshakeProtocol handshake_protocol)531 std::string HandshakeProtocolToString(HandshakeProtocol handshake_protocol) {
532   switch (handshake_protocol) {
533     RETURN_STRING_LITERAL(PROTOCOL_UNSUPPORTED);
534     RETURN_STRING_LITERAL(PROTOCOL_QUIC_CRYPTO);
535     RETURN_STRING_LITERAL(PROTOCOL_TLS1_3);
536   }
537   return absl::StrCat("PROTOCOL_UNKNOWN(", static_cast<int>(handshake_protocol),
538                       ")");
539 }
540 
ParsedQuicVersionToString(ParsedQuicVersion version)541 std::string ParsedQuicVersionToString(ParsedQuicVersion version) {
542   static_assert(SupportedVersions().size() == 4u,
543                 "Supported versions out of sync");
544   if (version == UnsupportedQuicVersion()) {
545     return "0";
546   } else if (version == ParsedQuicVersion::RFCv2()) {
547     QUICHE_DCHECK(version.UsesHttp3());
548     return "RFCv2";
549   } else if (version == ParsedQuicVersion::RFCv1()) {
550     QUICHE_DCHECK(version.UsesHttp3());
551     return "RFCv1";
552   } else if (version == ParsedQuicVersion::Draft29()) {
553     QUICHE_DCHECK(version.UsesHttp3());
554     return "draft29";
555   }
556 
557   return QuicVersionLabelToString(CreateQuicVersionLabel(version));
558 }
559 
QuicTransportVersionVectorToString(const QuicTransportVersionVector & versions)560 std::string QuicTransportVersionVectorToString(
561     const QuicTransportVersionVector& versions) {
562   std::string result = "";
563   for (size_t i = 0; i < versions.size(); ++i) {
564     if (i != 0) {
565       result.append(",");
566     }
567     result.append(QuicVersionToString(versions[i]));
568   }
569   return result;
570 }
571 
ParsedQuicVersionVectorToString(const ParsedQuicVersionVector & versions,const std::string & separator,size_t skip_after_nth_version)572 std::string ParsedQuicVersionVectorToString(
573     const ParsedQuicVersionVector& versions, const std::string& separator,
574     size_t skip_after_nth_version) {
575   std::string result;
576   for (size_t i = 0; i < versions.size(); ++i) {
577     if (i != 0) {
578       result.append(separator);
579     }
580     if (i > skip_after_nth_version) {
581       result.append("...");
582       break;
583     }
584     result.append(ParsedQuicVersionToString(versions[i]));
585   }
586   return result;
587 }
588 
VersionSupportsGoogleAltSvcFormat(QuicTransportVersion transport_version)589 bool VersionSupportsGoogleAltSvcFormat(QuicTransportVersion transport_version) {
590   return transport_version <= QUIC_VERSION_46;
591 }
592 
VersionAllowsVariableLengthConnectionIds(QuicTransportVersion transport_version)593 bool VersionAllowsVariableLengthConnectionIds(
594     QuicTransportVersion transport_version) {
595   QUICHE_DCHECK_NE(transport_version, QUIC_VERSION_UNSUPPORTED);
596   return transport_version > QUIC_VERSION_46;
597 }
598 
QuicVersionLabelUses4BitConnectionIdLength(QuicVersionLabel version_label)599 bool QuicVersionLabelUses4BitConnectionIdLength(
600     QuicVersionLabel version_label) {
601   // As we deprecate old versions, we still need the ability to send valid
602   // version negotiation packets for those versions. This function keeps track
603   // of the versions that ever supported the 4bit connection ID length encoding
604   // that we know about. Google QUIC 43 and earlier used a different encoding,
605   // and Google QUIC 49 and later use the new length prefixed encoding.
606   // Similarly, only IETF drafts 11 to 21 used this encoding.
607 
608   // Check Q043, Q044, Q045, Q046, Q047 and Q048.
609   for (uint8_t c = '3'; c <= '8'; ++c) {
610     if (version_label == MakeVersionLabel('Q', '0', '4', c)) {
611       return true;
612     }
613   }
614   // Check T048.
615   if (version_label == MakeVersionLabel('T', '0', '4', '8')) {
616     return true;
617   }
618   // Check IETF draft versions in [11,21].
619   for (uint8_t draft_number = 11; draft_number <= 21; ++draft_number) {
620     if (version_label == MakeVersionLabel(0xff, 0x00, 0x00, draft_number)) {
621       return true;
622     }
623   }
624   return false;
625 }
626 
UnsupportedQuicVersion()627 ParsedQuicVersion UnsupportedQuicVersion() {
628   return ParsedQuicVersion::Unsupported();
629 }
630 
QuicVersionReservedForNegotiation()631 ParsedQuicVersion QuicVersionReservedForNegotiation() {
632   return ParsedQuicVersion::ReservedForNegotiation();
633 }
634 
AlpnForVersion(ParsedQuicVersion parsed_version)635 std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
636   if (parsed_version == ParsedQuicVersion::RFCv2()) {
637     return "h3";
638   } else if (parsed_version == ParsedQuicVersion::RFCv1()) {
639     return "h3";
640   } else if (parsed_version == ParsedQuicVersion::Draft29()) {
641     return "h3-29";
642   }
643   return "h3-" + ParsedQuicVersionToString(parsed_version);
644 }
645 
QuicEnableVersion(const ParsedQuicVersion & version)646 void QuicEnableVersion(const ParsedQuicVersion& version) {
647   SetVersionFlag(version, /*should_enable=*/true);
648 }
649 
QuicDisableVersion(const ParsedQuicVersion & version)650 void QuicDisableVersion(const ParsedQuicVersion& version) {
651   SetVersionFlag(version, /*should_enable=*/false);
652 }
653 
QuicVersionIsEnabled(const ParsedQuicVersion & version)654 bool QuicVersionIsEnabled(const ParsedQuicVersion& version) {
655   ParsedQuicVersionVector current = CurrentSupportedVersions();
656   return std::find(current.begin(), current.end(), version) != current.end();
657 }
658 
659 #undef RETURN_STRING_LITERAL  // undef for jumbo builds
660 }  // namespace quic
661