QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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 "net/third_party/quiche/src/quic/core/quic_versions.h" |
| 6 | |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 7 | #include <string> |
| 8 | |
dschinazi | 1ac22cc | 2019-06-25 11:47:50 -0700 | [diff] [blame] | 9 | #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 10 | #include "net/third_party/quiche/src/quic/core/quic_tag.h" |
| 11 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 12 | #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 13 | #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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" |
QUICHE team | 173c48f | 2019-11-19 16:34:44 -0800 | [diff] [blame] | 17 | #include "net/third_party/quiche/src/common/platform/api/quiche_endian.h" |
dmcardle | cf0bfcf | 2019-12-13 08:08:21 -0800 | [diff] [blame^] | 18 | #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 19 | |
| 20 | namespace quic { |
| 21 | namespace { |
| 22 | |
| 23 | // Constructs a version label from the 4 bytes such that the on-the-wire |
| 24 | // order will be: d, c, b, a. |
| 25 | QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) { |
| 26 | return MakeQuicTag(d, c, b, a); |
| 27 | } |
| 28 | |
dschinazi | 1ac22cc | 2019-06-25 11:47:50 -0700 | [diff] [blame] | 29 | QuicVersionLabel CreateRandomVersionLabelForNegotiation() { |
dschinazi | 1ac22cc | 2019-06-25 11:47:50 -0700 | [diff] [blame] | 30 | QuicVersionLabel result; |
| 31 | if (!GetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness)) { |
| 32 | QuicRandom::GetInstance()->RandBytes(&result, sizeof(result)); |
| 33 | } else { |
| 34 | result = MakeVersionLabel(0xd1, 0x57, 0x38, 0x3f); |
| 35 | } |
| 36 | result &= 0xf0f0f0f0; |
| 37 | result |= 0x0a0a0a0a; |
| 38 | return result; |
| 39 | } |
| 40 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 41 | } // namespace |
| 42 | |
zhongyi | 546cc45 | 2019-04-12 15:27:49 -0700 | [diff] [blame] | 43 | bool ParsedQuicVersion::KnowsWhichDecrypterToUse() const { |
dschinazi | 8b1c45a | 2019-10-17 08:48:13 -0700 | [diff] [blame] | 44 | return transport_version > QUIC_VERSION_46 || |
zhongyi | 546cc45 | 2019-04-12 15:27:49 -0700 | [diff] [blame] | 45 | handshake_protocol == PROTOCOL_TLS1_3; |
| 46 | } |
| 47 | |
nharper | c8d9e40 | 2019-09-12 18:30:14 -0700 | [diff] [blame] | 48 | bool ParsedQuicVersion::UsesInitialObfuscators() const { |
nharper | c32d8ab | 2019-10-09 11:09:06 -0700 | [diff] [blame] | 49 | return transport_version > QUIC_VERSION_49 || |
nharper | 965e592 | 2019-09-23 22:33:54 -0700 | [diff] [blame] | 50 | handshake_protocol == PROTOCOL_TLS1_3; |
nharper | c8d9e40 | 2019-09-12 18:30:14 -0700 | [diff] [blame] | 51 | } |
| 52 | |
dschinazi | c703612 | 2019-04-30 12:46:34 -0700 | [diff] [blame] | 53 | bool ParsedQuicVersion::AllowsLowFlowControlLimits() const { |
| 54 | return transport_version == QUIC_VERSION_99 && |
| 55 | handshake_protocol == PROTOCOL_TLS1_3; |
| 56 | } |
| 57 | |
nharper | cfafed7 | 2019-05-01 13:43:55 -0700 | [diff] [blame] | 58 | bool ParsedQuicVersion::HasHeaderProtection() const { |
nharper | c32d8ab | 2019-10-09 11:09:06 -0700 | [diff] [blame] | 59 | return transport_version > QUIC_VERSION_49; |
nharper | cfafed7 | 2019-05-01 13:43:55 -0700 | [diff] [blame] | 60 | } |
| 61 | |
dschinazi | 244f6dc | 2019-05-06 15:45:16 -0700 | [diff] [blame] | 62 | bool ParsedQuicVersion::SupportsRetry() const { |
dschinazi | 2431fa2 | 2019-05-09 13:05:19 -0700 | [diff] [blame] | 63 | return transport_version > QUIC_VERSION_46; |
dschinazi | 244f6dc | 2019-05-06 15:45:16 -0700 | [diff] [blame] | 64 | } |
| 65 | |
fayang | 3ac15c1 | 2019-06-14 14:04:51 -0700 | [diff] [blame] | 66 | bool ParsedQuicVersion::SendsVariableLengthPacketNumberInLongHeader() const { |
| 67 | return transport_version > QUIC_VERSION_46; |
| 68 | } |
| 69 | |
dschinazi | b417d60 | 2019-05-29 13:08:45 -0700 | [diff] [blame] | 70 | bool ParsedQuicVersion::SupportsClientConnectionIds() const { |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 71 | return transport_version > QUIC_VERSION_48; |
dschinazi | b417d60 | 2019-05-29 13:08:45 -0700 | [diff] [blame] | 72 | } |
| 73 | |
dschinazi | 48ac919 | 2019-07-31 00:07:26 -0700 | [diff] [blame] | 74 | bool ParsedQuicVersion::HasLengthPrefixedConnectionIds() const { |
| 75 | return VersionHasLengthPrefixedConnectionIds(transport_version); |
| 76 | } |
| 77 | |
fayang | 5f13505 | 2019-08-22 17:59:40 -0700 | [diff] [blame] | 78 | bool ParsedQuicVersion::SupportsAntiAmplificationLimit() const { |
fayang | d6db04a | 2019-10-02 14:21:42 -0700 | [diff] [blame] | 79 | return transport_version == QUIC_VERSION_99 && |
| 80 | handshake_protocol == PROTOCOL_TLS1_3; |
fayang | 5f13505 | 2019-08-22 17:59:40 -0700 | [diff] [blame] | 81 | } |
| 82 | |
fayang | 58f7107 | 2019-11-05 08:47:02 -0800 | [diff] [blame] | 83 | bool ParsedQuicVersion::CanSendCoalescedPackets() const { |
| 84 | return QuicVersionHasLongHeaderLengths(transport_version) && |
| 85 | handshake_protocol == PROTOCOL_TLS1_3; |
| 86 | } |
| 87 | |
dschinazi | 48ac919 | 2019-07-31 00:07:26 -0700 | [diff] [blame] | 88 | bool VersionHasLengthPrefixedConnectionIds( |
| 89 | QuicTransportVersion transport_version) { |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 90 | return transport_version > QUIC_VERSION_48; |
dschinazi | 48ac919 | 2019-07-31 00:07:26 -0700 | [diff] [blame] | 91 | } |
| 92 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 93 | std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) { |
| 94 | os << ParsedQuicVersionToString(version); |
| 95 | return os; |
| 96 | } |
| 97 | |
| 98 | QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) { |
| 99 | char proto = 0; |
| 100 | switch (parsed_version.handshake_protocol) { |
| 101 | case PROTOCOL_QUIC_CRYPTO: |
| 102 | proto = 'Q'; |
| 103 | break; |
| 104 | case PROTOCOL_TLS1_3: |
| 105 | proto = 'T'; |
| 106 | break; |
| 107 | default: |
nharper | 4fd1105 | 2019-06-04 14:23:22 -0700 | [diff] [blame] | 108 | QUIC_BUG << "Invalid HandshakeProtocol: " |
| 109 | << parsed_version.handshake_protocol; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 110 | return 0; |
| 111 | } |
dschinazi | 8b1c45a | 2019-10-17 08:48:13 -0700 | [diff] [blame] | 112 | static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u, |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 113 | "Supported versions out of sync"); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 114 | switch (parsed_version.transport_version) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 115 | case QUIC_VERSION_43: |
| 116 | return MakeVersionLabel(proto, '0', '4', '3'); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 117 | case QUIC_VERSION_46: |
| 118 | return MakeVersionLabel(proto, '0', '4', '6'); |
nharper | 107ba5f | 2019-07-02 21:33:39 -0700 | [diff] [blame] | 119 | case QUIC_VERSION_48: |
| 120 | return MakeVersionLabel(proto, '0', '4', '8'); |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 121 | case QUIC_VERSION_49: |
| 122 | return MakeVersionLabel(proto, '0', '4', '9'); |
nharper | c32d8ab | 2019-10-09 11:09:06 -0700 | [diff] [blame] | 123 | case QUIC_VERSION_50: |
| 124 | return MakeVersionLabel(proto, '0', '5', '0'); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 125 | case QUIC_VERSION_99: |
rch | a702be2 | 2019-08-30 15:20:12 -0700 | [diff] [blame] | 126 | if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) { |
| 127 | return MakeVersionLabel(0xff, 0x00, 0x00, kQuicIetfDraftVersion); |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 128 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 129 | return MakeVersionLabel(proto, '0', '9', '9'); |
dschinazi | 5a354c9 | 2019-05-09 12:18:53 -0700 | [diff] [blame] | 130 | case QUIC_VERSION_RESERVED_FOR_NEGOTIATION: |
dschinazi | 1ac22cc | 2019-06-25 11:47:50 -0700 | [diff] [blame] | 131 | return CreateRandomVersionLabelForNegotiation(); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 132 | default: |
nharper | 4fd1105 | 2019-06-04 14:23:22 -0700 | [diff] [blame] | 133 | // This is a bug because we should never attempt to convert an invalid |
| 134 | // QuicTransportVersion to be written to the wire. |
| 135 | QUIC_BUG << "Unsupported QuicTransportVersion: " |
| 136 | << parsed_version.transport_version; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 137 | return 0; |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | QuicVersionLabelVector CreateQuicVersionLabelVector( |
| 142 | const ParsedQuicVersionVector& versions) { |
| 143 | QuicVersionLabelVector out; |
| 144 | out.reserve(versions.size()); |
| 145 | for (const auto& version : versions) { |
| 146 | out.push_back(CreateQuicVersionLabel(version)); |
| 147 | } |
| 148 | return out; |
| 149 | } |
| 150 | |
| 151 | ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) { |
nharper | f5e6845 | 2019-05-29 17:24:18 -0700 | [diff] [blame] | 152 | std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO, |
| 153 | PROTOCOL_TLS1_3}; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 154 | for (QuicTransportVersion version : kSupportedTransportVersions) { |
| 155 | for (HandshakeProtocol handshake : protocols) { |
| 156 | if (version_label == |
| 157 | CreateQuicVersionLabel(ParsedQuicVersion(handshake, version))) { |
| 158 | return ParsedQuicVersion(handshake, version); |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | // Reading from the client so this should not be considered an ERROR. |
| 163 | QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: " |
| 164 | << QuicVersionLabelToString(version_label); |
| 165 | return UnsupportedQuicVersion(); |
| 166 | } |
| 167 | |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 168 | ParsedQuicVersion ParseQuicVersionString(std::string version_string) { |
dschinazi | 35e749e | 2019-04-09 09:36:04 -0700 | [diff] [blame] | 169 | if (version_string.empty()) { |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 170 | return UnsupportedQuicVersion(); |
| 171 | } |
| 172 | int quic_version_number = 0; |
dmcardle | cf0bfcf | 2019-12-13 08:08:21 -0800 | [diff] [blame^] | 173 | if (quiche::QuicheTextUtils::StringToInt(version_string, |
| 174 | &quic_version_number) && |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 175 | quic_version_number > 0) { |
| 176 | return ParsedQuicVersion( |
| 177 | PROTOCOL_QUIC_CRYPTO, |
| 178 | static_cast<QuicTransportVersion>(quic_version_number)); |
| 179 | } |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 180 | for (QuicTransportVersion version : kSupportedTransportVersions) { |
dschinazi | 76881f0 | 2019-12-09 14:56:14 -0800 | [diff] [blame] | 181 | for (HandshakeProtocol handshake : kSupportedHandshakeProtocols) { |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 182 | const ParsedQuicVersion parsed_version = |
| 183 | ParsedQuicVersion(handshake, version); |
| 184 | if (version_string == ParsedQuicVersionToString(parsed_version)) { |
| 185 | return parsed_version; |
| 186 | } |
| 187 | } |
| 188 | } |
dschinazi | 5262747 | 2019-04-09 16:20:20 -0700 | [diff] [blame] | 189 | // Still recognize T099 even if flag quic_ietf_draft_version has been changed. |
dschinazi | 76881f0 | 2019-12-09 14:56:14 -0800 | [diff] [blame] | 190 | if (GetQuicReloadableFlag(quic_enable_version_t099) && |
wub | eddb74b | 2019-05-01 10:26:55 -0700 | [diff] [blame] | 191 | version_string == "T099") { |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 192 | return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99); |
| 193 | } |
| 194 | // Reading from the client so this should not be considered an ERROR. |
| 195 | QUIC_DLOG(INFO) << "Unsupported QUIC version string: \"" << version_string |
| 196 | << "\"."; |
| 197 | return UnsupportedQuicVersion(); |
| 198 | } |
| 199 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 200 | QuicTransportVersionVector AllSupportedTransportVersions() { |
| 201 | QuicTransportVersionVector supported_versions; |
| 202 | for (QuicTransportVersion version : kSupportedTransportVersions) { |
| 203 | supported_versions.push_back(version); |
| 204 | } |
| 205 | return supported_versions; |
| 206 | } |
| 207 | |
| 208 | ParsedQuicVersionVector AllSupportedVersions() { |
| 209 | ParsedQuicVersionVector supported_versions; |
| 210 | for (HandshakeProtocol protocol : kSupportedHandshakeProtocols) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 211 | for (QuicTransportVersion version : kSupportedTransportVersions) { |
QUICHE team | ea74008 | 2019-03-11 17:58:43 -0700 | [diff] [blame] | 212 | if (protocol == PROTOCOL_TLS1_3 && |
dschinazi | 0ce303d | 2019-12-05 14:53:15 -0800 | [diff] [blame] | 213 | (!QuicVersionUsesCryptoFrames(version) || |
| 214 | version <= QUIC_VERSION_49)) { |
nharper | 107ba5f | 2019-07-02 21:33:39 -0700 | [diff] [blame] | 215 | // The TLS handshake is only deployable if CRYPTO frames are also used. |
dschinazi | 0ce303d | 2019-12-05 14:53:15 -0800 | [diff] [blame] | 216 | // We explicitly removed support for T048 and T049 to reduce test load. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 217 | continue; |
| 218 | } |
| 219 | supported_versions.push_back(ParsedQuicVersion(protocol, version)); |
| 220 | } |
| 221 | } |
| 222 | return supported_versions; |
| 223 | } |
| 224 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 225 | ParsedQuicVersionVector CurrentSupportedVersions() { |
| 226 | return FilterSupportedVersions(AllSupportedVersions()); |
| 227 | } |
| 228 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 229 | ParsedQuicVersionVector FilterSupportedVersions( |
| 230 | ParsedQuicVersionVector versions) { |
| 231 | ParsedQuicVersionVector filtered_versions; |
| 232 | filtered_versions.reserve(versions.size()); |
| 233 | for (ParsedQuicVersion version : versions) { |
| 234 | if (version.transport_version == QUIC_VERSION_99) { |
dschinazi | 76881f0 | 2019-12-09 14:56:14 -0800 | [diff] [blame] | 235 | if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) { |
| 236 | if (GetQuicReloadableFlag(quic_enable_version_q099)) { |
| 237 | filtered_versions.push_back(version); |
| 238 | } |
| 239 | } else { |
| 240 | if (GetQuicReloadableFlag(quic_enable_version_t099)) { |
| 241 | filtered_versions.push_back(version); |
| 242 | } |
| 243 | } |
| 244 | } else if (version.transport_version == QUIC_VERSION_50) { |
| 245 | if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) { |
| 246 | if (!GetQuicReloadableFlag(quic_disable_version_q050)) { |
| 247 | filtered_versions.push_back(version); |
| 248 | } |
| 249 | } else { |
| 250 | if (GetQuicReloadableFlag(quic_enable_version_t050)) { |
| 251 | filtered_versions.push_back(version); |
| 252 | } |
| 253 | } |
| 254 | } else if (version.transport_version == QUIC_VERSION_49) { |
| 255 | if (!GetQuicReloadableFlag(quic_disable_version_q049)) { |
| 256 | filtered_versions.push_back(version); |
| 257 | } |
| 258 | } else if (version.transport_version == QUIC_VERSION_48) { |
| 259 | if (!GetQuicReloadableFlag(quic_disable_version_q048)) { |
| 260 | filtered_versions.push_back(version); |
| 261 | } |
| 262 | } else if (version.transport_version == QUIC_VERSION_46) { |
| 263 | if (!GetQuicReloadableFlag(quic_disable_version_q046)) { |
| 264 | filtered_versions.push_back(version); |
| 265 | } |
| 266 | } else if (version.transport_version == QUIC_VERSION_43) { |
| 267 | if (!GetQuicReloadableFlag(quic_disable_version_q043)) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 268 | filtered_versions.push_back(version); |
| 269 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 270 | } else { |
| 271 | filtered_versions.push_back(version); |
| 272 | } |
| 273 | } |
| 274 | return filtered_versions; |
| 275 | } |
| 276 | |
| 277 | QuicTransportVersionVector VersionOfIndex( |
| 278 | const QuicTransportVersionVector& versions, |
| 279 | int index) { |
| 280 | QuicTransportVersionVector version; |
| 281 | int version_count = versions.size(); |
| 282 | if (index >= 0 && index < version_count) { |
| 283 | version.push_back(versions[index]); |
| 284 | } else { |
| 285 | version.push_back(QUIC_VERSION_UNSUPPORTED); |
| 286 | } |
| 287 | return version; |
| 288 | } |
| 289 | |
| 290 | ParsedQuicVersionVector ParsedVersionOfIndex( |
| 291 | const ParsedQuicVersionVector& versions, |
| 292 | int index) { |
| 293 | ParsedQuicVersionVector version; |
| 294 | int version_count = versions.size(); |
| 295 | if (index >= 0 && index < version_count) { |
| 296 | version.push_back(versions[index]); |
| 297 | } else { |
| 298 | version.push_back(UnsupportedQuicVersion()); |
| 299 | } |
| 300 | return version; |
| 301 | } |
| 302 | |
| 303 | QuicTransportVersionVector ParsedVersionsToTransportVersions( |
| 304 | const ParsedQuicVersionVector& versions) { |
| 305 | QuicTransportVersionVector transport_versions; |
| 306 | transport_versions.resize(versions.size()); |
| 307 | for (size_t i = 0; i < versions.size(); ++i) { |
| 308 | transport_versions[i] = versions[i].transport_version; |
| 309 | } |
| 310 | return transport_versions; |
| 311 | } |
| 312 | |
| 313 | QuicVersionLabel QuicVersionToQuicVersionLabel( |
| 314 | QuicTransportVersion transport_version) { |
| 315 | return CreateQuicVersionLabel( |
| 316 | ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version)); |
| 317 | } |
| 318 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 319 | std::string QuicVersionLabelToString(QuicVersionLabel version_label) { |
QUICHE team | 173c48f | 2019-11-19 16:34:44 -0800 | [diff] [blame] | 320 | return QuicTagToString(quiche::QuicheEndian::HostToNet32(version_label)); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 321 | } |
| 322 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 323 | std::string QuicVersionLabelVectorToString( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 324 | const QuicVersionLabelVector& version_labels, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 325 | const std::string& separator, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 326 | size_t skip_after_nth_version) { |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 327 | std::string result; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 328 | for (size_t i = 0; i < version_labels.size(); ++i) { |
| 329 | if (i != 0) { |
| 330 | result.append(separator); |
| 331 | } |
| 332 | |
| 333 | if (i > skip_after_nth_version) { |
| 334 | result.append("..."); |
| 335 | break; |
| 336 | } |
| 337 | result.append(QuicVersionLabelToString(version_labels[i])); |
| 338 | } |
| 339 | return result; |
| 340 | } |
| 341 | |
| 342 | QuicTransportVersion QuicVersionLabelToQuicVersion( |
| 343 | QuicVersionLabel version_label) { |
| 344 | return ParseQuicVersionLabel(version_label).transport_version; |
| 345 | } |
| 346 | |
| 347 | HandshakeProtocol QuicVersionLabelToHandshakeProtocol( |
| 348 | QuicVersionLabel version_label) { |
| 349 | return ParseQuicVersionLabel(version_label).handshake_protocol; |
| 350 | } |
| 351 | |
| 352 | #define RETURN_STRING_LITERAL(x) \ |
| 353 | case x: \ |
| 354 | return #x |
| 355 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 356 | std::string QuicVersionToString(QuicTransportVersion transport_version) { |
dschinazi | 8b1c45a | 2019-10-17 08:48:13 -0700 | [diff] [blame] | 357 | static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u, |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 358 | "Supported versions out of sync"); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 359 | switch (transport_version) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 360 | RETURN_STRING_LITERAL(QUIC_VERSION_43); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 361 | RETURN_STRING_LITERAL(QUIC_VERSION_46); |
nharper | 107ba5f | 2019-07-02 21:33:39 -0700 | [diff] [blame] | 362 | RETURN_STRING_LITERAL(QUIC_VERSION_48); |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 363 | RETURN_STRING_LITERAL(QUIC_VERSION_49); |
nharper | c32d8ab | 2019-10-09 11:09:06 -0700 | [diff] [blame] | 364 | RETURN_STRING_LITERAL(QUIC_VERSION_50); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 365 | RETURN_STRING_LITERAL(QUIC_VERSION_99); |
| 366 | default: |
| 367 | return "QUIC_VERSION_UNSUPPORTED"; |
| 368 | } |
| 369 | } |
| 370 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 371 | std::string ParsedQuicVersionToString(ParsedQuicVersion version) { |
nharper | 4fd1105 | 2019-06-04 14:23:22 -0700 | [diff] [blame] | 372 | if (version == UnsupportedQuicVersion()) { |
| 373 | return "0"; |
| 374 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 375 | return QuicVersionLabelToString(CreateQuicVersionLabel(version)); |
| 376 | } |
| 377 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 378 | std::string QuicTransportVersionVectorToString( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 379 | const QuicTransportVersionVector& versions) { |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 380 | std::string result = ""; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 381 | for (size_t i = 0; i < versions.size(); ++i) { |
| 382 | if (i != 0) { |
| 383 | result.append(","); |
| 384 | } |
| 385 | result.append(QuicVersionToString(versions[i])); |
| 386 | } |
| 387 | return result; |
| 388 | } |
| 389 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 390 | std::string ParsedQuicVersionVectorToString( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 391 | const ParsedQuicVersionVector& versions, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 392 | const std::string& separator, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 393 | size_t skip_after_nth_version) { |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 394 | std::string result; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 395 | for (size_t i = 0; i < versions.size(); ++i) { |
| 396 | if (i != 0) { |
| 397 | result.append(separator); |
| 398 | } |
| 399 | if (i > skip_after_nth_version) { |
| 400 | result.append("..."); |
| 401 | break; |
| 402 | } |
| 403 | result.append(ParsedQuicVersionToString(versions[i])); |
| 404 | } |
| 405 | return result; |
| 406 | } |
| 407 | |
rch | eb78dbb | 2019-10-26 08:37:15 -0700 | [diff] [blame] | 408 | bool VersionSupportsGoogleAltSvcFormat(QuicTransportVersion transport_version) { |
| 409 | return transport_version <= QUIC_VERSION_46; |
| 410 | } |
| 411 | |
dschinazi | 48ac919 | 2019-07-31 00:07:26 -0700 | [diff] [blame] | 412 | bool QuicVersionLabelUses4BitConnectionIdLength( |
| 413 | QuicVersionLabel version_label) { |
| 414 | // As we deprecate old versions, we still need the ability to send valid |
| 415 | // version negotiation packets for those versions. This function keeps track |
| 416 | // of the versions that ever supported the 4bit connection ID length encoding |
| 417 | // that we know about. Google QUIC 43 and earlier used a different encoding, |
dschinazi | c73506e | 2019-09-20 13:26:46 -0700 | [diff] [blame] | 418 | // and Google QUIC 49 and later use the new length prefixed encoding. |
dschinazi | 48ac919 | 2019-07-31 00:07:26 -0700 | [diff] [blame] | 419 | // Similarly, only IETF drafts 11 to 21 used this encoding. |
| 420 | |
| 421 | // Check Q044, Q045, Q046, Q047 and Q048. |
| 422 | for (uint8_t c = '4'; c <= '8'; ++c) { |
| 423 | if (version_label == MakeVersionLabel('Q', '0', '4', c)) { |
| 424 | return true; |
| 425 | } |
| 426 | } |
| 427 | // Check T048. |
| 428 | if (version_label == MakeVersionLabel('T', '0', '4', '8')) { |
| 429 | return true; |
| 430 | } |
| 431 | // Check IETF draft versions in [11,21]. |
| 432 | for (uint8_t draft_number = 11; draft_number <= 21; ++draft_number) { |
| 433 | if (version_label == MakeVersionLabel(0xff, 0x00, 0x00, draft_number)) { |
| 434 | return true; |
| 435 | } |
| 436 | } |
| 437 | return false; |
| 438 | } |
| 439 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 440 | ParsedQuicVersion UnsupportedQuicVersion() { |
| 441 | return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); |
| 442 | } |
| 443 | |
dschinazi | 5a354c9 | 2019-05-09 12:18:53 -0700 | [diff] [blame] | 444 | ParsedQuicVersion QuicVersionReservedForNegotiation() { |
| 445 | return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, |
| 446 | QUIC_VERSION_RESERVED_FOR_NEGOTIATION); |
| 447 | } |
| 448 | |
dschinazi | 35e749e | 2019-04-09 09:36:04 -0700 | [diff] [blame] | 449 | std::string AlpnForVersion(ParsedQuicVersion parsed_version) { |
| 450 | if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 && |
rch | a702be2 | 2019-08-30 15:20:12 -0700 | [diff] [blame] | 451 | parsed_version.transport_version == QUIC_VERSION_99) { |
dmcardle | cf0bfcf | 2019-12-13 08:08:21 -0800 | [diff] [blame^] | 452 | return "h3-" + |
| 453 | quiche::QuicheTextUtils::Uint64ToString(kQuicIetfDraftVersion); |
dschinazi | 35e749e | 2019-04-09 09:36:04 -0700 | [diff] [blame] | 454 | } |
rch | 5a2b3eb | 2019-08-23 11:49:33 -0700 | [diff] [blame] | 455 | return "h3-" + ParsedQuicVersionToString(parsed_version); |
dschinazi | 35e749e | 2019-04-09 09:36:04 -0700 | [diff] [blame] | 456 | } |
| 457 | |
rch | a702be2 | 2019-08-30 15:20:12 -0700 | [diff] [blame] | 458 | void QuicVersionInitializeSupportForIetfDraft() { |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 459 | // Enable necessary flags. |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 460 | } |
| 461 | |
| 462 | void QuicEnableVersion(ParsedQuicVersion parsed_version) { |
dschinazi | 8b1c45a | 2019-10-17 08:48:13 -0700 | [diff] [blame] | 463 | static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u, |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 464 | "Supported versions out of sync"); |
dschinazi | 6d2aea0 | 2019-06-26 02:59:06 -0700 | [diff] [blame] | 465 | if (parsed_version.transport_version == QUIC_VERSION_99) { |
dschinazi | 76881f0 | 2019-12-09 14:56:14 -0800 | [diff] [blame] | 466 | if (parsed_version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) { |
| 467 | SetQuicReloadableFlag(quic_enable_version_q099, true); |
| 468 | } else { |
| 469 | SetQuicReloadableFlag(quic_enable_version_t099, true); |
| 470 | } |
| 471 | } else if (parsed_version.transport_version == QUIC_VERSION_50) { |
| 472 | if (parsed_version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) { |
| 473 | SetQuicReloadableFlag(quic_disable_version_q050, false); |
| 474 | } else { |
| 475 | SetQuicReloadableFlag(quic_enable_version_t050, true); |
| 476 | } |
| 477 | } else if (parsed_version.transport_version == QUIC_VERSION_49) { |
| 478 | SetQuicReloadableFlag(quic_disable_version_q049, false); |
| 479 | } else if (parsed_version.transport_version == QUIC_VERSION_48) { |
| 480 | SetQuicReloadableFlag(quic_disable_version_q048, false); |
| 481 | } else if (parsed_version.transport_version == QUIC_VERSION_46) { |
| 482 | SetQuicReloadableFlag(quic_disable_version_q046, false); |
| 483 | } else if (parsed_version.transport_version == QUIC_VERSION_43) { |
| 484 | SetQuicReloadableFlag(quic_disable_version_q043, false); |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 485 | } |
dschinazi | 8ae6001 | 2019-04-04 18:07:27 -0700 | [diff] [blame] | 486 | } |
| 487 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 488 | #undef RETURN_STRING_LITERAL // undef for jumbo builds |
| 489 | } // namespace quic |