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