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