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