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