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 | // Definitions and utility functions related to handling of QUIC versions. |
| 6 | // |
| 7 | // QUIC version is a four-byte tag that can be represented in memory as a |
| 8 | // QuicVersionLabel type (which is an alias to uint32_t). In actuality, all |
| 9 | // versions supported by this implementation have the following format: |
| 10 | // [QT]0\d\d |
| 11 | // e.g. Q046. Q or T distinguishes the type of handshake used (Q for QUIC |
| 12 | // Crypto handshake, T for TLS-based handshake), and the two digits at the end |
| 13 | // is the actual numeric value of transport version used by the code. |
| 14 | |
| 15 | #ifndef QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ |
| 16 | #define QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ |
| 17 | |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 18 | #include <string> |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 19 | #include <vector> |
| 20 | |
| 21 | #include "net/third_party/quiche/src/quic/core/quic_tag.h" |
| 22 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
| 23 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 24 | |
| 25 | namespace quic { |
| 26 | |
| 27 | // The available versions of QUIC. The numeric value of the enum is guaranteed |
| 28 | // to match the number in the name. The versions not currently supported are |
| 29 | // documented in comments. |
| 30 | // |
| 31 | // See go/new-quic-version for more details on how to roll out new versions. |
| 32 | enum QuicTransportVersion { |
| 33 | // Special case to indicate unknown/unsupported QUIC version. |
| 34 | QUIC_VERSION_UNSUPPORTED = 0, |
| 35 | |
| 36 | // Version 1 was the first version of QUIC that supported versioning. |
| 37 | // Version 2 decoupled versioning of non-cryptographic parameters from the |
| 38 | // SCFG. |
| 39 | // Version 3 moved public flags into the beginning of the packet. |
| 40 | // Version 4 added support for variable-length connection IDs. |
| 41 | // Version 5 made specifying FEC groups optional. |
| 42 | // Version 6 introduced variable-length packet numbers. |
| 43 | // Version 7 introduced a lower-overhead encoding for stream frames. |
| 44 | // Version 8 made salt length equal to digest length for the RSA-PSS |
| 45 | // signatures. |
| 46 | // Version 9 added stream priority. |
| 47 | // Version 10 redid the frame type numbering. |
| 48 | // Version 11 reduced the length of null encryption authentication tag |
| 49 | // from 16 to 12 bytes. |
| 50 | // Version 12 made the sequence numbers in the ACK frames variable-sized. |
| 51 | // Version 13 added the dedicated header stream. |
| 52 | // Version 14 added byte_offset to RST_STREAM frame. |
| 53 | // Version 15 added a list of packets recovered using FEC to the ACK frame. |
| 54 | // Version 16 added STOP_WAITING frame. |
| 55 | // Version 17 added per-stream flow control. |
| 56 | // Version 18 added PING frame. |
| 57 | // Version 19 added connection-level flow control |
| 58 | // Version 20 allowed to set stream- and connection-level flow control windows |
| 59 | // to different values. |
| 60 | // Version 21 made header and crypto streams flow-controlled. |
| 61 | // Version 22 added support for SCUP (server config update) messages. |
| 62 | // Version 23 added timestamps into the ACK frame. |
| 63 | // Version 24 added SPDY/4 header compression. |
| 64 | // Version 25 added support for SPDY/4 header keys and removed error_details |
| 65 | // from RST_STREAM frame. |
| 66 | // Version 26 added XLCT (expected leaf certificate) tag into CHLO. |
| 67 | // Version 27 added a nonce into SHLO. |
| 68 | // Version 28 allowed receiver to refuse creating a requested stream. |
| 69 | // Version 29 added support for QUIC_STREAM_NO_ERROR. |
| 70 | // Version 30 added server-side support for certificate transparency. |
| 71 | // Version 31 incorporated the hash of CHLO into the crypto proof supplied by |
| 72 | // the server. |
| 73 | // Version 32 removed FEC-related fields from wire format. |
| 74 | // Version 33 added diversification nonces. |
| 75 | // Version 34 removed entropy bits from packets and ACK frames, removed |
| 76 | // private flag from packet header and changed the ACK format to |
| 77 | // specify ranges of packets acknowledged rather than missing |
| 78 | // ranges. |
| 79 | // Version 35 allows endpoints to independently set stream limit. |
| 80 | // Version 36 added support for forced head-of-line blocking experiments. |
| 81 | // Version 37 added perspective into null encryption. |
| 82 | // Version 38 switched to IETF padding frame format and support for NSTP (no |
| 83 | // stop waiting frame) connection option. |
| 84 | |
| 85 | QUIC_VERSION_39 = 39, // Integers and floating numbers are written in big |
| 86 | // endian. Dot not ack acks. Send a connection level |
| 87 | // WINDOW_UPDATE every 20 sent packets which do not |
| 88 | // contain retransmittable frames. |
| 89 | |
| 90 | // Version 40 was an attempt to convert QUIC to IETF frame format; it was |
| 91 | // never shipped due to a bug. |
| 92 | // Version 41 was a bugfix for version 40. The working group changed the wire |
| 93 | // format before it shipped, which caused it to be never shipped |
| 94 | // and all the changes from it to be reverted. No changes from v40 |
| 95 | // or v41 are present in subsequent versions. |
| 96 | // Version 42 allowed receiving overlapping stream data. |
| 97 | |
| 98 | QUIC_VERSION_43 = 43, // PRIORITY frames are sent by client and accepted by |
| 99 | // server. |
| 100 | QUIC_VERSION_44 = 44, // Use IETF header format. |
| 101 | |
| 102 | // Version 45 added MESSAGE frame. |
| 103 | |
| 104 | QUIC_VERSION_46 = 46, // Use IETF draft-17 header format with demultiplexing |
| 105 | // bit. |
QUICHE team | 9b41c97 | 2019-03-21 11:22:48 -0700 | [diff] [blame] | 106 | QUIC_VERSION_47 = 47, // Allow variable-length QUIC connection IDs. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 107 | QUIC_VERSION_99 = 99, // Dumping ground for IETF QUIC changes which are not |
| 108 | // yet ready for production. |
| 109 | }; |
| 110 | |
| 111 | // The crypto handshake protocols that can be used with QUIC. |
| 112 | enum HandshakeProtocol { |
| 113 | PROTOCOL_UNSUPPORTED, |
| 114 | PROTOCOL_QUIC_CRYPTO, |
| 115 | PROTOCOL_TLS1_3, |
| 116 | }; |
| 117 | |
| 118 | // A parsed QUIC version label which determines that handshake protocol |
| 119 | // and the transport version. |
| 120 | struct QUIC_EXPORT_PRIVATE ParsedQuicVersion { |
| 121 | HandshakeProtocol handshake_protocol; |
| 122 | QuicTransportVersion transport_version; |
| 123 | |
| 124 | ParsedQuicVersion(HandshakeProtocol handshake_protocol, |
| 125 | QuicTransportVersion transport_version); |
| 126 | |
| 127 | ParsedQuicVersion(const ParsedQuicVersion& other) |
| 128 | : handshake_protocol(other.handshake_protocol), |
| 129 | transport_version(other.transport_version) {} |
| 130 | |
| 131 | ParsedQuicVersion& operator=(const ParsedQuicVersion& other) { |
| 132 | if (this != &other) { |
| 133 | handshake_protocol = other.handshake_protocol; |
| 134 | transport_version = other.transport_version; |
| 135 | } |
| 136 | return *this; |
| 137 | } |
| 138 | |
| 139 | bool operator==(const ParsedQuicVersion& other) const { |
| 140 | return handshake_protocol == other.handshake_protocol && |
| 141 | transport_version == other.transport_version; |
| 142 | } |
| 143 | |
| 144 | bool operator!=(const ParsedQuicVersion& other) const { |
| 145 | return handshake_protocol != other.handshake_protocol || |
| 146 | transport_version != other.transport_version; |
| 147 | } |
| 148 | }; |
| 149 | |
| 150 | QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion(); |
| 151 | |
| 152 | QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, |
| 153 | const ParsedQuicVersion& version); |
| 154 | |
| 155 | using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>; |
| 156 | |
| 157 | // Representation of the on-the-wire QUIC version number. Will be written/read |
| 158 | // to the wire in network-byte-order. |
| 159 | using QuicVersionLabel = uint32_t; |
| 160 | using QuicVersionLabelVector = std::vector<QuicVersionLabel>; |
| 161 | |
| 162 | // This vector contains QUIC versions which we currently support. |
| 163 | // This should be ordered such that the highest supported version is the first |
| 164 | // element, with subsequent elements in descending order (versions can be |
| 165 | // skipped as necessary). |
| 166 | // |
| 167 | // See go/new-quic-version for more details on how to roll out new versions. |
| 168 | static const QuicTransportVersion kSupportedTransportVersions[] = { |
| 169 | QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, |
| 170 | QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, |
| 171 | }; |
| 172 | |
| 173 | // This vector contains all crypto handshake protocols that are supported. |
| 174 | static const HandshakeProtocol kSupportedHandshakeProtocols[] = { |
| 175 | PROTOCOL_QUIC_CRYPTO, PROTOCOL_TLS1_3}; |
| 176 | |
| 177 | typedef std::vector<QuicTransportVersion> QuicTransportVersionVector; |
| 178 | |
| 179 | // Returns a vector of QUIC versions in kSupportedTransportVersions. |
| 180 | QUIC_EXPORT_PRIVATE QuicTransportVersionVector AllSupportedTransportVersions(); |
| 181 | |
| 182 | // Returns a vector of QUIC versions that is the cartesian product of |
| 183 | // kSupportedTransportVersions and kSupportedHandshakeProtocols. |
| 184 | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions(); |
| 185 | |
| 186 | // Returns a vector of QUIC versions from kSupportedTransportVersions which |
| 187 | // exclude any versions which are disabled by flags. |
| 188 | QUIC_EXPORT_PRIVATE QuicTransportVersionVector |
| 189 | CurrentSupportedTransportVersions(); |
| 190 | |
| 191 | // Returns a vector of QUIC versions that is the cartesian product of |
| 192 | // kSupportedTransportVersions and kSupportedHandshakeProtocols, with any |
| 193 | // versions disabled by flags excluded. |
| 194 | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersions(); |
| 195 | |
| 196 | // Returns a vector of QUIC versions from |versions| which exclude any versions |
| 197 | // which are disabled by flags. |
| 198 | QUIC_EXPORT_PRIVATE QuicTransportVersionVector |
| 199 | FilterSupportedTransportVersions(QuicTransportVersionVector versions); |
| 200 | |
| 201 | // Returns a vector of QUIC versions from |versions| which exclude any versions |
| 202 | // which are disabled by flags. |
| 203 | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector |
| 204 | FilterSupportedVersions(ParsedQuicVersionVector versions); |
| 205 | |
| 206 | // Returns QUIC version of |index| in result of |versions|. Returns |
| 207 | // QUIC_VERSION_UNSUPPORTED if |index| is out of bounds. |
| 208 | QUIC_EXPORT_PRIVATE QuicTransportVersionVector |
| 209 | VersionOfIndex(const QuicTransportVersionVector& versions, int index); |
| 210 | |
| 211 | // Returns QUIC version of |index| in result of |versions|. Returns |
| 212 | // UnsupportedQuicVersion() if |index| is out of bounds. |
| 213 | QUIC_EXPORT_PRIVATE ParsedQuicVersionVector |
| 214 | ParsedVersionOfIndex(const ParsedQuicVersionVector& versions, int index); |
| 215 | |
| 216 | // Returns a vector of QuicTransportVersions corresponding to just the transport |
| 217 | // versions in |versions|. If the input vector contains multiple parsed versions |
| 218 | // with different handshake protocols (but the same transport version), that |
| 219 | // transport version will appear in the resulting vector multiple times. |
| 220 | QUIC_EXPORT_PRIVATE QuicTransportVersionVector |
| 221 | ParsedVersionsToTransportVersions(const ParsedQuicVersionVector& versions); |
| 222 | |
| 223 | // QuicVersionLabel is written to and read from the wire, but we prefer to use |
| 224 | // the more readable ParsedQuicVersion at other levels. |
| 225 | // Helper function which translates from a QuicVersionLabel to a |
| 226 | // ParsedQuicVersion. |
| 227 | QUIC_EXPORT_PRIVATE ParsedQuicVersion |
| 228 | ParseQuicVersionLabel(QuicVersionLabel version_label); |
| 229 | |
| 230 | // Constructs a QuicVersionLabel from the provided ParsedQuicVersion. |
| 231 | QUIC_EXPORT_PRIVATE QuicVersionLabel |
| 232 | CreateQuicVersionLabel(ParsedQuicVersion parsed_version); |
| 233 | |
| 234 | // Constructs a QuicVersionLabelVector from the provided |
| 235 | // ParsedQuicVersionVector. |
| 236 | QUIC_EXPORT_PRIVATE QuicVersionLabelVector |
| 237 | CreateQuicVersionLabelVector(const ParsedQuicVersionVector& versions); |
| 238 | |
| 239 | // QuicVersionLabel is written to and read from the wire, but we prefer to use |
| 240 | // the more readable QuicTransportVersion at other levels. |
| 241 | // Helper function which translates from a QuicTransportVersion to a |
| 242 | // QuicVersionLabel. Returns 0 if |version| is unsupported. |
| 243 | QUIC_EXPORT_PRIVATE QuicVersionLabel |
| 244 | QuicVersionToQuicVersionLabel(QuicTransportVersion transport_version); |
| 245 | |
| 246 | // Helper function which translates from a QuicVersionLabel to a string. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 247 | QUIC_EXPORT_PRIVATE std::string QuicVersionLabelToString( |
| 248 | QuicVersionLabel version_label); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 249 | |
| 250 | // Returns |separator|-separated list of string representations of |
| 251 | // QuicVersionLabel values in the supplied |version_labels| vector. The values |
| 252 | // after the (0-based) |skip_after_nth_version|'th are skipped. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 253 | QUIC_EXPORT_PRIVATE std::string QuicVersionLabelVectorToString( |
| 254 | const QuicVersionLabelVector& version_labels, |
| 255 | const std::string& separator, |
| 256 | size_t skip_after_nth_version); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 257 | |
| 258 | // Returns comma separated list of string representations of QuicVersionLabel |
| 259 | // values in the supplied |version_labels| vector. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 260 | QUIC_EXPORT_PRIVATE inline std::string QuicVersionLabelVectorToString( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 261 | const QuicVersionLabelVector& version_labels) { |
| 262 | return QuicVersionLabelVectorToString(version_labels, ",", |
| 263 | std::numeric_limits<size_t>::max()); |
| 264 | } |
| 265 | |
| 266 | // Returns appropriate QuicTransportVersion from a QuicVersionLabel. |
| 267 | // Returns QUIC_VERSION_UNSUPPORTED if |version_label| cannot be understood. |
| 268 | QUIC_EXPORT_PRIVATE QuicTransportVersion |
| 269 | QuicVersionLabelToQuicVersion(QuicVersionLabel version_label); |
| 270 | |
| 271 | // Returns the HandshakeProtocol used with the given |version_label|, returning |
| 272 | // PROTOCOL_UNSUPPORTED if it is unknown. |
| 273 | QUIC_EXPORT_PRIVATE HandshakeProtocol |
| 274 | QuicVersionLabelToHandshakeProtocol(QuicVersionLabel version_label); |
| 275 | |
| 276 | // Helper function which translates from a QuicTransportVersion to a string. |
| 277 | // Returns strings corresponding to enum names (e.g. QUIC_VERSION_6). |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 278 | QUIC_EXPORT_PRIVATE std::string QuicVersionToString( |
| 279 | QuicTransportVersion transport_version); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 280 | |
| 281 | // Helper function which translates from a ParsedQuicVersion to a string. |
| 282 | // Returns strings corresponding to the on-the-wire tag. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 283 | QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionToString( |
| 284 | ParsedQuicVersion version); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 285 | |
| 286 | // Returns comma separated list of string representations of |
| 287 | // QuicTransportVersion enum values in the supplied |versions| vector. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 288 | QUIC_EXPORT_PRIVATE std::string QuicTransportVersionVectorToString( |
| 289 | const QuicTransportVersionVector& versions); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 290 | |
| 291 | // Returns comma separated list of string representations of ParsedQuicVersion |
| 292 | // values in the supplied |versions| vector. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 293 | QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( |
| 294 | const ParsedQuicVersionVector& versions); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 295 | |
| 296 | // Returns |separator|-separated list of string representations of |
| 297 | // ParsedQuicVersion values in the supplied |versions| vector. The values after |
| 298 | // the (0-based) |skip_after_nth_version|'th are skipped. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 299 | QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( |
| 300 | const ParsedQuicVersionVector& versions, |
| 301 | const std::string& separator, |
| 302 | size_t skip_after_nth_version); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 303 | |
| 304 | // Returns comma separated list of string representations of ParsedQuicVersion |
| 305 | // values in the supplied |versions| vector. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 306 | QUIC_EXPORT_PRIVATE inline std::string ParsedQuicVersionVectorToString( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 307 | const ParsedQuicVersionVector& versions) { |
| 308 | return ParsedQuicVersionVectorToString(versions, ",", |
| 309 | std::numeric_limits<size_t>::max()); |
| 310 | } |
| 311 | |
| 312 | // Returns true if QuicSpdyStream encodes body using HTTP/3 specification and |
| 313 | // sends data frame header along with body. |
| 314 | QUIC_EXPORT_PRIVATE inline bool VersionHasDataFrameHeader( |
| 315 | QuicTransportVersion transport_version) { |
| 316 | return transport_version == QUIC_VERSION_99; |
| 317 | } |
| 318 | |
| 319 | // Returns true if QuicSpdySession instantiates a QPACK encoder and decoder. |
| 320 | // TODO(123528590): Implement the following features and gate them on this |
| 321 | // function as well, optionally renaming this function as appropriate. |
| 322 | // Send HEADERS on the request/response stream instead of the headers stream. |
| 323 | // Send PUSH_PROMISE on the request/response stream instead of headers stream. |
| 324 | // Send PRIORITY on the request/response stream instead of the headers stream. |
| 325 | // Do not instantiate the headers stream object. |
| 326 | QUIC_EXPORT_PRIVATE inline bool VersionUsesQpack( |
| 327 | QuicTransportVersion transport_version) { |
| 328 | const bool uses_qpack = (transport_version == QUIC_VERSION_99); |
| 329 | if (uses_qpack) { |
| 330 | DCHECK(VersionHasDataFrameHeader(transport_version)); |
| 331 | } |
| 332 | return uses_qpack; |
| 333 | } |
| 334 | |
| 335 | // Returns whether the transport_version supports the variable length integer |
| 336 | // length field as defined by IETF QUIC draft-13 and later. |
| 337 | QUIC_EXPORT_PRIVATE inline bool QuicVersionHasLongHeaderLengths( |
| 338 | QuicTransportVersion transport_version) { |
| 339 | // TODO(dschinazi) if we enable long header lengths before v99, we need to |
| 340 | // add support for fixing up lengths in QuicFramer::BuildDataPacket. |
| 341 | return transport_version == QUIC_VERSION_99; |
| 342 | } |
| 343 | |
QUICHE team | ea74008 | 2019-03-11 17:58:43 -0700 | [diff] [blame] | 344 | // Returns whether |transport_version| uses CRYPTO frames for the handshake |
| 345 | // instead of stream 1. |
| 346 | QUIC_EXPORT_PRIVATE inline bool QuicVersionUsesCryptoFrames( |
| 347 | QuicTransportVersion transport_version) { |
QUICHE team | 9b41c97 | 2019-03-21 11:22:48 -0700 | [diff] [blame] | 348 | return transport_version == QUIC_VERSION_99; |
QUICHE team | ea74008 | 2019-03-11 17:58:43 -0700 | [diff] [blame] | 349 | } |
| 350 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 351 | } // namespace quic |
| 352 | |
| 353 | #endif // QUICHE_QUIC_CORE_QUIC_VERSIONS_H_ |