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