blob: ca6bdaee8e47e4d013ef695c8ff75bcc46ec5aaf [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 "net/third_party/quiche/src/quic/core/quic_versions.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/quic_tag.h"
10#include "net/third_party/quiche/src/quic/core/quic_types.h"
dschinazi8ae60012019-04-04 18:07:27 -070011#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
dschinazi8ae60012019-04-04 18:07:27 -070017#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050018
19namespace quic {
20namespace {
21
22// Constructs a version label from the 4 bytes such that the on-the-wire
23// order will be: d, c, b, a.
24QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) {
25 return MakeQuicTag(d, c, b, a);
26}
27
dschinazi35e749e2019-04-09 09:36:04 -070028// IETF draft version for ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99).
29// Overrides the version label and ALPN string for IETF interop events.
30int32_t kQuicT099IetfDraftVersion = 0;
dschinazi8ae60012019-04-04 18:07:27 -070031
QUICHE teama6ef0a62019-03-07 20:34:33 -050032} // namespace
33
34ParsedQuicVersion::ParsedQuicVersion(HandshakeProtocol handshake_protocol,
35 QuicTransportVersion transport_version)
36 : handshake_protocol(handshake_protocol),
37 transport_version(transport_version) {
38 if (handshake_protocol == PROTOCOL_TLS1_3 &&
39 !FLAGS_quic_supports_tls_handshake) {
40 QUIC_BUG << "TLS use attempted when not enabled";
41 }
42}
43
44std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
45 os << ParsedQuicVersionToString(version);
46 return os;
47}
48
49QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
50 char proto = 0;
51 switch (parsed_version.handshake_protocol) {
52 case PROTOCOL_QUIC_CRYPTO:
53 proto = 'Q';
54 break;
55 case PROTOCOL_TLS1_3:
56 proto = 'T';
57 break;
58 default:
59 QUIC_LOG(ERROR) << "Invalid HandshakeProtocol: "
60 << parsed_version.handshake_protocol;
61 return 0;
62 }
63 switch (parsed_version.transport_version) {
64 case QUIC_VERSION_39:
65 return MakeVersionLabel(proto, '0', '3', '9');
66 case QUIC_VERSION_43:
67 return MakeVersionLabel(proto, '0', '4', '3');
68 case QUIC_VERSION_44:
69 return MakeVersionLabel(proto, '0', '4', '4');
70 case QUIC_VERSION_46:
71 return MakeVersionLabel(proto, '0', '4', '6');
72 case QUIC_VERSION_47:
73 return MakeVersionLabel(proto, '0', '4', '7');
74 case QUIC_VERSION_99:
dschinazi8ae60012019-04-04 18:07:27 -070075 if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
dschinazi35e749e2019-04-09 09:36:04 -070076 kQuicT099IetfDraftVersion != 0) {
77 return 0xff000000 + kQuicT099IetfDraftVersion;
dschinazi8ae60012019-04-04 18:07:27 -070078 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 return MakeVersionLabel(proto, '0', '9', '9');
80 default:
81 // This shold be an ERROR because we should never attempt to convert an
82 // invalid QuicTransportVersion to be written to the wire.
83 QUIC_LOG(ERROR) << "Unsupported QuicTransportVersion: "
84 << parsed_version.transport_version;
85 return 0;
86 }
87}
88
89QuicVersionLabelVector CreateQuicVersionLabelVector(
90 const ParsedQuicVersionVector& versions) {
91 QuicVersionLabelVector out;
92 out.reserve(versions.size());
93 for (const auto& version : versions) {
94 out.push_back(CreateQuicVersionLabel(version));
95 }
96 return out;
97}
98
99ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
100 std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
101 if (FLAGS_quic_supports_tls_handshake) {
102 protocols.push_back(PROTOCOL_TLS1_3);
103 }
104 for (QuicTransportVersion version : kSupportedTransportVersions) {
105 for (HandshakeProtocol handshake : protocols) {
106 if (version_label ==
107 CreateQuicVersionLabel(ParsedQuicVersion(handshake, version))) {
108 return ParsedQuicVersion(handshake, version);
109 }
110 }
111 }
112 // Reading from the client so this should not be considered an ERROR.
113 QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
114 << QuicVersionLabelToString(version_label);
115 return UnsupportedQuicVersion();
116}
117
dschinazi8ae60012019-04-04 18:07:27 -0700118ParsedQuicVersion ParseQuicVersionString(std::string version_string) {
dschinazi35e749e2019-04-09 09:36:04 -0700119 if (version_string.empty()) {
dschinazi8ae60012019-04-04 18:07:27 -0700120 return UnsupportedQuicVersion();
121 }
122 int quic_version_number = 0;
123 if (QuicTextUtils::StringToInt(version_string, &quic_version_number) &&
124 quic_version_number > 0) {
125 return ParsedQuicVersion(
126 PROTOCOL_QUIC_CRYPTO,
127 static_cast<QuicTransportVersion>(quic_version_number));
128 }
129
130 std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
131 if (FLAGS_quic_supports_tls_handshake) {
132 protocols.push_back(PROTOCOL_TLS1_3);
133 }
134 for (QuicTransportVersion version : kSupportedTransportVersions) {
135 for (HandshakeProtocol handshake : protocols) {
136 const ParsedQuicVersion parsed_version =
137 ParsedQuicVersion(handshake, version);
138 if (version_string == ParsedQuicVersionToString(parsed_version)) {
139 return parsed_version;
140 }
141 }
142 }
dschinazi35e749e2019-04-09 09:36:04 -0700143 // Still recognize T099 even if kQuicT099IetfDraftVersion has been changed.
dschinazi8ae60012019-04-04 18:07:27 -0700144 if (FLAGS_quic_supports_tls_handshake && version_string == "T099") {
145 return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
146 }
147 // Reading from the client so this should not be considered an ERROR.
148 QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string
149 << "\".";
150 return UnsupportedQuicVersion();
151}
152
QUICHE teama6ef0a62019-03-07 20:34:33 -0500153QuicTransportVersionVector AllSupportedTransportVersions() {
154 QuicTransportVersionVector supported_versions;
155 for (QuicTransportVersion version : kSupportedTransportVersions) {
156 supported_versions.push_back(version);
157 }
158 return supported_versions;
159}
160
161ParsedQuicVersionVector AllSupportedVersions() {
162 ParsedQuicVersionVector supported_versions;
163 for (HandshakeProtocol protocol : kSupportedHandshakeProtocols) {
164 if (protocol == PROTOCOL_TLS1_3 && !FLAGS_quic_supports_tls_handshake) {
165 continue;
166 }
167 for (QuicTransportVersion version : kSupportedTransportVersions) {
QUICHE teamea740082019-03-11 17:58:43 -0700168 if (protocol == PROTOCOL_TLS1_3 &&
169 !QuicVersionUsesCryptoFrames(version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 // The TLS handshake is only deployable if CRYPTO frames are also used,
171 // which are added in v47.
172 continue;
173 }
174 supported_versions.push_back(ParsedQuicVersion(protocol, version));
175 }
176 }
177 return supported_versions;
178}
179
180// TODO(nharper): Remove this function when it is no longer in use.
181QuicTransportVersionVector CurrentSupportedTransportVersions() {
182 return FilterSupportedTransportVersions(AllSupportedTransportVersions());
183}
184
185ParsedQuicVersionVector CurrentSupportedVersions() {
186 return FilterSupportedVersions(AllSupportedVersions());
187}
188
189// TODO(nharper): Remove this function when it is no longer in use.
190QuicTransportVersionVector FilterSupportedTransportVersions(
191 QuicTransportVersionVector versions) {
192 ParsedQuicVersionVector parsed_versions;
193 for (QuicTransportVersion version : versions) {
194 parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
195 }
196 ParsedQuicVersionVector filtered_parsed_versions =
197 FilterSupportedVersions(parsed_versions);
198 QuicTransportVersionVector filtered_versions;
199 for (ParsedQuicVersion version : filtered_parsed_versions) {
200 filtered_versions.push_back(version.transport_version);
201 }
202 return filtered_versions;
203}
204
205ParsedQuicVersionVector FilterSupportedVersions(
206 ParsedQuicVersionVector versions) {
207 ParsedQuicVersionVector filtered_versions;
208 filtered_versions.reserve(versions.size());
209 for (ParsedQuicVersion version : versions) {
210 if (version.transport_version == QUIC_VERSION_99) {
211 if (GetQuicReloadableFlag(quic_enable_version_99) &&
212 GetQuicReloadableFlag(quic_enable_version_47) &&
213 GetQuicReloadableFlag(quic_enable_version_46) &&
214 GetQuicReloadableFlag(quic_enable_version_44) &&
215 GetQuicReloadableFlag(quic_enable_version_43)) {
216 filtered_versions.push_back(version);
217 }
218 } else if (version.transport_version == QUIC_VERSION_47) {
219 if (GetQuicReloadableFlag(quic_enable_version_47) &&
220 GetQuicReloadableFlag(quic_enable_version_46) &&
221 GetQuicReloadableFlag(quic_enable_version_44) &&
222 GetQuicReloadableFlag(quic_enable_version_43)) {
223 filtered_versions.push_back(version);
224 }
225 } else if (version.transport_version == QUIC_VERSION_46) {
226 if (GetQuicReloadableFlag(quic_enable_version_46) &&
227 GetQuicReloadableFlag(quic_enable_version_44) &&
228 GetQuicReloadableFlag(quic_enable_version_43)) {
229 filtered_versions.push_back(version);
230 }
231 } else if (version.transport_version == QUIC_VERSION_44) {
232 if (GetQuicReloadableFlag(quic_enable_version_44) &&
233 GetQuicReloadableFlag(quic_enable_version_43)) {
234 filtered_versions.push_back(version);
235 }
236 } else if (version.transport_version == QUIC_VERSION_43) {
237 if (GetQuicReloadableFlag(quic_enable_version_43)) {
238 filtered_versions.push_back(version);
239 }
240 } else if (version.transport_version == QUIC_VERSION_39) {
241 if (!GetQuicReloadableFlag(quic_disable_version_39)) {
242 filtered_versions.push_back(version);
243 }
244 } else {
245 filtered_versions.push_back(version);
246 }
247 }
248 return filtered_versions;
249}
250
251QuicTransportVersionVector VersionOfIndex(
252 const QuicTransportVersionVector& versions,
253 int index) {
254 QuicTransportVersionVector version;
255 int version_count = versions.size();
256 if (index >= 0 && index < version_count) {
257 version.push_back(versions[index]);
258 } else {
259 version.push_back(QUIC_VERSION_UNSUPPORTED);
260 }
261 return version;
262}
263
264ParsedQuicVersionVector ParsedVersionOfIndex(
265 const ParsedQuicVersionVector& versions,
266 int index) {
267 ParsedQuicVersionVector version;
268 int version_count = versions.size();
269 if (index >= 0 && index < version_count) {
270 version.push_back(versions[index]);
271 } else {
272 version.push_back(UnsupportedQuicVersion());
273 }
274 return version;
275}
276
277QuicTransportVersionVector ParsedVersionsToTransportVersions(
278 const ParsedQuicVersionVector& versions) {
279 QuicTransportVersionVector transport_versions;
280 transport_versions.resize(versions.size());
281 for (size_t i = 0; i < versions.size(); ++i) {
282 transport_versions[i] = versions[i].transport_version;
283 }
284 return transport_versions;
285}
286
287QuicVersionLabel QuicVersionToQuicVersionLabel(
288 QuicTransportVersion transport_version) {
289 return CreateQuicVersionLabel(
290 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version));
291}
292
vasilvvc48c8712019-03-11 13:38:16 -0700293std::string QuicVersionLabelToString(QuicVersionLabel version_label) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 return QuicTagToString(QuicEndian::HostToNet32(version_label));
295}
296
vasilvvc48c8712019-03-11 13:38:16 -0700297std::string QuicVersionLabelVectorToString(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500298 const QuicVersionLabelVector& version_labels,
vasilvvc48c8712019-03-11 13:38:16 -0700299 const std::string& separator,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500300 size_t skip_after_nth_version) {
vasilvvc48c8712019-03-11 13:38:16 -0700301 std::string result;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500302 for (size_t i = 0; i < version_labels.size(); ++i) {
303 if (i != 0) {
304 result.append(separator);
305 }
306
307 if (i > skip_after_nth_version) {
308 result.append("...");
309 break;
310 }
311 result.append(QuicVersionLabelToString(version_labels[i]));
312 }
313 return result;
314}
315
316QuicTransportVersion QuicVersionLabelToQuicVersion(
317 QuicVersionLabel version_label) {
318 return ParseQuicVersionLabel(version_label).transport_version;
319}
320
321HandshakeProtocol QuicVersionLabelToHandshakeProtocol(
322 QuicVersionLabel version_label) {
323 return ParseQuicVersionLabel(version_label).handshake_protocol;
324}
325
326#define RETURN_STRING_LITERAL(x) \
327 case x: \
328 return #x
329
vasilvvc48c8712019-03-11 13:38:16 -0700330std::string QuicVersionToString(QuicTransportVersion transport_version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500331 switch (transport_version) {
332 RETURN_STRING_LITERAL(QUIC_VERSION_39);
333 RETURN_STRING_LITERAL(QUIC_VERSION_43);
334 RETURN_STRING_LITERAL(QUIC_VERSION_44);
335 RETURN_STRING_LITERAL(QUIC_VERSION_46);
336 RETURN_STRING_LITERAL(QUIC_VERSION_47);
337 RETURN_STRING_LITERAL(QUIC_VERSION_99);
338 default:
339 return "QUIC_VERSION_UNSUPPORTED";
340 }
341}
342
vasilvvc48c8712019-03-11 13:38:16 -0700343std::string ParsedQuicVersionToString(ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500344 return QuicVersionLabelToString(CreateQuicVersionLabel(version));
345}
346
vasilvvc48c8712019-03-11 13:38:16 -0700347std::string QuicTransportVersionVectorToString(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348 const QuicTransportVersionVector& versions) {
vasilvvc48c8712019-03-11 13:38:16 -0700349 std::string result = "";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500350 for (size_t i = 0; i < versions.size(); ++i) {
351 if (i != 0) {
352 result.append(",");
353 }
354 result.append(QuicVersionToString(versions[i]));
355 }
356 return result;
357}
358
vasilvvc48c8712019-03-11 13:38:16 -0700359std::string ParsedQuicVersionVectorToString(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500360 const ParsedQuicVersionVector& versions,
vasilvvc48c8712019-03-11 13:38:16 -0700361 const std::string& separator,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500362 size_t skip_after_nth_version) {
vasilvvc48c8712019-03-11 13:38:16 -0700363 std::string result;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500364 for (size_t i = 0; i < versions.size(); ++i) {
365 if (i != 0) {
366 result.append(separator);
367 }
368 if (i > skip_after_nth_version) {
369 result.append("...");
370 break;
371 }
372 result.append(ParsedQuicVersionToString(versions[i]));
373 }
374 return result;
375}
376
377ParsedQuicVersion UnsupportedQuicVersion() {
378 return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
379}
380
dschinazi35e749e2019-04-09 09:36:04 -0700381std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
382 if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
383 parsed_version.transport_version == QUIC_VERSION_99 &&
384 kQuicT099IetfDraftVersion != 0) {
385 return "h3-" + QuicTextUtils::Uint64ToString(kQuicT099IetfDraftVersion);
386 }
387 return "h3-google-" + ParsedQuicVersionToString(parsed_version);
388}
389
dschinazi8ae60012019-04-04 18:07:27 -0700390void QuicVersionInitializeSupportForIetfDraft(int32_t draft_version) {
391 if (draft_version == 0) {
392 return;
393 }
394 if (draft_version < 0 || draft_version >= 256) {
395 LOG(FATAL) << "Invalid IETF draft version " << draft_version;
396 return;
397 }
398
dschinazi35e749e2019-04-09 09:36:04 -0700399 kQuicT099IetfDraftVersion = draft_version;
dschinazi8ae60012019-04-04 18:07:27 -0700400
401 // Enable necessary flags.
402 SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
403 SetQuicReloadableFlag(quic_deprecate_ack_bundling_mode, true);
404 SetQuicReloadableFlag(quic_rpm_decides_when_to_send_acks, true);
405 SetQuicReloadableFlag(quic_use_uber_loss_algorithm, true);
406 SetQuicReloadableFlag(quic_use_uber_received_packet_manager, true);
407 SetQuicReloadableFlag(quic_validate_packet_number_post_decryption, true);
408 SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
409}
410
411void QuicEnableVersion(ParsedQuicVersion parsed_version) {
412 if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
413 SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
414 }
415 static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
416 "Supported versions out of sync");
417 if (parsed_version.transport_version >= QUIC_VERSION_99) {
418 SetQuicReloadableFlag(quic_enable_version_99, true);
419 }
420 if (parsed_version.transport_version >= QUIC_VERSION_47) {
421 SetQuicReloadableFlag(quic_enable_version_47, true);
422 }
423 if (parsed_version.transport_version >= QUIC_VERSION_46) {
424 SetQuicReloadableFlag(quic_enable_version_46, true);
425 }
426 if (parsed_version.transport_version >= QUIC_VERSION_44) {
427 SetQuicReloadableFlag(quic_enable_version_44, true);
428 }
429 if (parsed_version.transport_version >= QUIC_VERSION_43) {
430 SetQuicReloadableFlag(quic_enable_version_43, true);
431 }
432}
433
QUICHE teama6ef0a62019-03-07 20:34:33 -0500434#undef RETURN_STRING_LITERAL // undef for jumbo builds
435} // namespace quic