Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_config.h b/quic/core/quic_config.h
new file mode 100644
index 0000000..affc7b9
--- /dev/null
+++ b/quic/core/quic_config.h
@@ -0,0 +1,491 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_CONFIG_H_
+#define QUICHE_QUIC_CORE_QUIC_CONFIG_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+
+namespace quic {
+
+namespace test {
+class QuicConfigPeer;
+} // namespace test
+
+class CryptoHandshakeMessage;
+
+// Describes whether or not a given QuicTag is required or optional in the
+// handshake message.
+enum QuicConfigPresence {
+ // This negotiable value can be absent from the handshake message. Default
+ // value is selected as the negotiated value in such a case.
+ PRESENCE_OPTIONAL,
+ // This negotiable value is required in the handshake message otherwise the
+ // Process*Hello function returns an error.
+ PRESENCE_REQUIRED,
+};
+
+// Whether the CryptoHandshakeMessage is from the client or server.
+enum HelloType {
+ CLIENT,
+ SERVER,
+};
+
+// An abstract base class that stores a value that can be sent in CHLO/SHLO
+// message. These values can be OPTIONAL or REQUIRED, depending on |presence_|.
+class QUIC_EXPORT_PRIVATE QuicConfigValue {
+ public:
+ QuicConfigValue(QuicTag tag, QuicConfigPresence presence);
+ virtual ~QuicConfigValue();
+
+ // Serialises tag name and value(s) to |out|.
+ virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const = 0;
+
+ // Selects a mutually acceptable value from those offered in |peer_hello|
+ // and those defined in the subclass.
+ virtual QuicErrorCode ProcessPeerHello(
+ const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details) = 0;
+
+ protected:
+ const QuicTag tag_;
+ const QuicConfigPresence presence_;
+};
+
+class QUIC_EXPORT_PRIVATE QuicNegotiableValue : public QuicConfigValue {
+ public:
+ QuicNegotiableValue(QuicTag tag, QuicConfigPresence presence);
+ ~QuicNegotiableValue() override;
+
+ bool negotiated() const { return negotiated_; }
+
+ protected:
+ void set_negotiated(bool negotiated) { negotiated_ = negotiated; }
+
+ private:
+ bool negotiated_;
+};
+
+class QUIC_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
+ // TODO(fayang): some negotiated values use uint32 as bool (e.g., silent
+ // close). Consider adding a QuicNegotiableBool type.
+ public:
+ // Default and max values default to 0.
+ QuicNegotiableUint32(QuicTag name, QuicConfigPresence presence);
+ ~QuicNegotiableUint32() override;
+
+ // Sets the maximum possible value that can be achieved after negotiation and
+ // also the default values to be assumed if PRESENCE_OPTIONAL and the *HLO msg
+ // doesn't contain a value corresponding to |name_|. |max| is serialised via
+ // ToHandshakeMessage call if |negotiated_| is false.
+ void set(uint32_t max, uint32_t default_value);
+
+ // Returns the value negotiated if |negotiated_| is true, otherwise returns
+ // default_value_ (used to set default values before negotiation finishes).
+ uint32_t GetUint32() const;
+
+ // Returns the maximum value negotiable.
+ uint32_t GetMax() const;
+
+ // Serialises |name_| and value to |out|. If |negotiated_| is true then
+ // |negotiated_value_| is serialised, otherwise |max_value_| is serialised.
+ void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
+
+ // Processes the corresponding value from |peer_hello| and if present calls
+ // ReceiveValue with it. If the corresponding value is missing and
+ // PRESENCE_OPTIONAL then |negotiated_value_| is set to |default_value_|.
+ QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details) override;
+
+ // Takes a value |value| parsed from a handshake message (whether a TLS
+ // ClientHello/ServerHello or a CryptoHandshakeMessage) whose sender was
+ // |hello_type|, and sets |negotiated_value_| to the minimum of |value| and
+ // |max_value_|. On success this function returns QUIC_NO_ERROR; if there is
+ // an error, details are put in |*error_details|.
+ QuicErrorCode ReceiveValue(uint32_t value,
+ HelloType hello_type,
+ QuicString* error_details);
+
+ private:
+ uint32_t max_value_;
+ uint32_t default_value_;
+ uint32_t negotiated_value_;
+};
+
+// Stores uint32_t from CHLO or SHLO messages that are not negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue {
+ public:
+ QuicFixedUint32(QuicTag name, QuicConfigPresence presence);
+ ~QuicFixedUint32() override;
+
+ bool HasSendValue() const;
+
+ uint32_t GetSendValue() const;
+
+ void SetSendValue(uint32_t value);
+
+ bool HasReceivedValue() const;
+
+ uint32_t GetReceivedValue() const;
+
+ void SetReceivedValue(uint32_t value);
+
+ // If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
+ void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
+
+ // Sets |value_| to the corresponding value from |peer_hello_| if it exists.
+ QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details) override;
+
+ private:
+ uint32_t send_value_;
+ bool has_send_value_;
+ uint32_t receive_value_;
+ bool has_receive_value_;
+};
+
+// Stores uint128 from CHLO or SHLO messages that are not negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedUint128 : public QuicConfigValue {
+ public:
+ QuicFixedUint128(QuicTag tag, QuicConfigPresence presence);
+ ~QuicFixedUint128() override;
+
+ bool HasSendValue() const;
+
+ QuicUint128 GetSendValue() const;
+
+ void SetSendValue(QuicUint128 value);
+
+ bool HasReceivedValue() const;
+
+ QuicUint128 GetReceivedValue() const;
+
+ void SetReceivedValue(QuicUint128 value);
+
+ // If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
+ void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
+
+ // Sets |value_| to the corresponding value from |peer_hello_| if it exists.
+ QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details) override;
+
+ private:
+ QuicUint128 send_value_;
+ bool has_send_value_;
+ QuicUint128 receive_value_;
+ bool has_receive_value_;
+};
+
+// Stores tag from CHLO or SHLO messages that are not negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
+ public:
+ QuicFixedTagVector(QuicTag name, QuicConfigPresence presence);
+ QuicFixedTagVector(const QuicFixedTagVector& other);
+ ~QuicFixedTagVector() override;
+
+ bool HasSendValues() const;
+
+ QuicTagVector GetSendValues() const;
+
+ void SetSendValues(const QuicTagVector& values);
+
+ bool HasReceivedValues() const;
+
+ QuicTagVector GetReceivedValues() const;
+
+ void SetReceivedValues(const QuicTagVector& values);
+
+ // If has_send_value is true, serialises |tag_vector_| and |send_value_| to
+ // |out|.
+ void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
+
+ // Sets |receive_values_| to the corresponding value from |client_hello_| if
+ // it exists.
+ QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details) override;
+
+ private:
+ QuicTagVector send_values_;
+ bool has_send_values_;
+ QuicTagVector receive_values_;
+ bool has_receive_values_;
+};
+
+// Stores QuicSocketAddress from CHLO or SHLO messages that are not negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedSocketAddress : public QuicConfigValue {
+ public:
+ QuicFixedSocketAddress(QuicTag tag, QuicConfigPresence presence);
+ ~QuicFixedSocketAddress() override;
+
+ bool HasSendValue() const;
+
+ const QuicSocketAddress& GetSendValue() const;
+
+ void SetSendValue(const QuicSocketAddress& value);
+
+ bool HasReceivedValue() const;
+
+ const QuicSocketAddress& GetReceivedValue() const;
+
+ void SetReceivedValue(const QuicSocketAddress& value);
+
+ void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
+
+ QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details) override;
+
+ private:
+ QuicSocketAddress send_value_;
+ bool has_send_value_;
+ QuicSocketAddress receive_value_;
+ bool has_receive_value_;
+};
+
+// QuicConfig contains non-crypto configuration options that are negotiated in
+// the crypto handshake.
+class QUIC_EXPORT_PRIVATE QuicConfig {
+ public:
+ QuicConfig();
+ QuicConfig(const QuicConfig& other);
+ ~QuicConfig();
+
+ void SetConnectionOptionsToSend(const QuicTagVector& connection_options);
+
+ bool HasReceivedConnectionOptions() const;
+
+ // Sets initial received connection options. All received connection options
+ // will be initialized with these fields. Initial received options may only be
+ // set once per config, prior to the setting of any other options. If options
+ // have already been set (either by previous calls or via handshake), this
+ // function does nothing and returns false.
+ bool SetInitialReceivedConnectionOptions(const QuicTagVector& tags);
+
+ QuicTagVector ReceivedConnectionOptions() const;
+
+ bool HasSendConnectionOptions() const;
+
+ QuicTagVector SendConnectionOptions() const;
+
+ // Returns true if the client is sending or the server has received a
+ // connection option.
+ // TODO(ianswett): Rename to HasClientRequestedSharedOption
+ bool HasClientSentConnectionOption(QuicTag tag,
+ Perspective perspective) const;
+
+ void SetClientConnectionOptions(
+ const QuicTagVector& client_connection_options);
+
+ // Returns true if the client has requested the specified connection option.
+ // Checks the client connection options if the |perspective| is client and
+ // connection options if the |perspective| is the server.
+ bool HasClientRequestedIndependentOption(QuicTag tag,
+ Perspective perspective) const;
+
+ void SetIdleNetworkTimeout(QuicTime::Delta max_idle_network_timeout,
+ QuicTime::Delta default_idle_network_timeout);
+
+ QuicTime::Delta IdleNetworkTimeout() const;
+
+ void SetSilentClose(bool silent_close);
+
+ bool SilentClose() const;
+
+ void SetMaxIncomingDynamicStreamsToSend(
+ uint32_t max_incoming_dynamic_streams);
+
+ uint32_t GetMaxIncomingDynamicStreamsToSend();
+
+ bool HasReceivedMaxIncomingDynamicStreams();
+
+ uint32_t ReceivedMaxIncomingDynamicStreams();
+
+ void set_max_time_before_crypto_handshake(
+ QuicTime::Delta max_time_before_crypto_handshake) {
+ max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
+ }
+
+ QuicTime::Delta max_time_before_crypto_handshake() const {
+ return max_time_before_crypto_handshake_;
+ }
+
+ void set_max_idle_time_before_crypto_handshake(
+ QuicTime::Delta max_idle_time_before_crypto_handshake) {
+ max_idle_time_before_crypto_handshake_ =
+ max_idle_time_before_crypto_handshake;
+ }
+
+ QuicTime::Delta max_idle_time_before_crypto_handshake() const {
+ return max_idle_time_before_crypto_handshake_;
+ }
+
+ QuicNegotiableUint32 idle_network_timeout_seconds() const {
+ return idle_network_timeout_seconds_;
+ }
+
+ void set_max_undecryptable_packets(size_t max_undecryptable_packets) {
+ max_undecryptable_packets_ = max_undecryptable_packets;
+ }
+
+ size_t max_undecryptable_packets() const {
+ return max_undecryptable_packets_;
+ }
+
+ bool HasSetBytesForConnectionIdToSend() const;
+
+ // Sets the peer's connection id length, in bytes.
+ void SetBytesForConnectionIdToSend(uint32_t bytes);
+
+ bool HasReceivedBytesForConnectionId() const;
+
+ uint32_t ReceivedBytesForConnectionId() const;
+
+ // Sets an estimated initial round trip time in us.
+ void SetInitialRoundTripTimeUsToSend(uint32_t rtt_us);
+
+ bool HasReceivedInitialRoundTripTimeUs() const;
+
+ uint32_t ReceivedInitialRoundTripTimeUs() const;
+
+ bool HasInitialRoundTripTimeUsToSend() const;
+
+ uint32_t GetInitialRoundTripTimeUsToSend() const;
+
+ // Sets an initial stream flow control window size to transmit to the peer.
+ void SetInitialStreamFlowControlWindowToSend(uint32_t window_bytes);
+
+ uint32_t GetInitialStreamFlowControlWindowToSend() const;
+
+ bool HasReceivedInitialStreamFlowControlWindowBytes() const;
+
+ uint32_t ReceivedInitialStreamFlowControlWindowBytes() const;
+
+ // Sets an initial session flow control window size to transmit to the peer.
+ void SetInitialSessionFlowControlWindowToSend(uint32_t window_bytes);
+
+ uint32_t GetInitialSessionFlowControlWindowToSend() const;
+
+ bool HasReceivedInitialSessionFlowControlWindowBytes() const;
+
+ uint32_t ReceivedInitialSessionFlowControlWindowBytes() const;
+
+ void SetDisableConnectionMigration();
+
+ bool DisableConnectionMigration() const;
+
+ void SetAlternateServerAddressToSend(
+ const QuicSocketAddress& alternate_server_address);
+
+ bool HasReceivedAlternateServerAddress() const;
+
+ const QuicSocketAddress& ReceivedAlternateServerAddress() const;
+
+ void SetSupportMaxHeaderListSize();
+
+ bool SupportMaxHeaderListSize() const;
+
+ void SetStatelessResetTokenToSend(QuicUint128 stateless_reset_token);
+
+ bool HasReceivedStatelessResetToken() const;
+
+ QuicUint128 ReceivedStatelessResetToken() const;
+
+ bool negotiated() const;
+
+ void SetCreateSessionTagIndicators(QuicTagVector tags);
+
+ const QuicTagVector& create_session_tag_indicators() const;
+
+ // ToHandshakeMessage serialises the settings in this object as a series of
+ // tags /value pairs and adds them to |out|.
+ void ToHandshakeMessage(CryptoHandshakeMessage* out) const;
+
+ // Calls ProcessPeerHello on each negotiable parameter. On failure returns
+ // the corresponding QuicErrorCode and sets detailed error in |error_details|.
+ QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
+ HelloType hello_type,
+ QuicString* error_details);
+
+ // FillTransportParameters writes the values to send for ICSL, MIDS, CFCW, and
+ // SFCW to |*params|, returning true if the values could be written and false
+ // if something prevents them from being written (e.g. a value is too large).
+ bool FillTransportParameters(TransportParameters* params) const;
+
+ // ProcessTransportParameters reads from |params| which was received from a
+ // peer operating as a |hello_type|. It processes values for ICSL, MIDS, CFCW,
+ // and SFCW and sets the corresponding members of this QuicConfig. On failure,
+ // it returns a QuicErrorCode and puts a detailed error in |*error_details|.
+ QuicErrorCode ProcessTransportParameters(const TransportParameters& params,
+ HelloType hello_type,
+ QuicString* error_details);
+
+ private:
+ friend class test::QuicConfigPeer;
+
+ // SetDefaults sets the members to sensible, default values.
+ void SetDefaults();
+
+ // Configurations options that are not negotiated.
+ // Maximum time the session can be alive before crypto handshake is finished.
+ QuicTime::Delta max_time_before_crypto_handshake_;
+ // Maximum idle time before the crypto handshake has completed.
+ QuicTime::Delta max_idle_time_before_crypto_handshake_;
+ // Maximum number of undecryptable packets stored before CHLO/SHLO.
+ size_t max_undecryptable_packets_;
+
+ // Connection options which affect the server side. May also affect the
+ // client side in cases when identical behavior is desirable.
+ QuicFixedTagVector connection_options_;
+ // Connection options which only affect the client side.
+ QuicFixedTagVector client_connection_options_;
+ // Idle network timeout in seconds.
+ QuicNegotiableUint32 idle_network_timeout_seconds_;
+ // Whether to use silent close. Defaults to 0 (false) and is otherwise true.
+ QuicNegotiableUint32 silent_close_;
+ // Maximum number of incoming dynamic streams that the connection can support.
+ QuicFixedUint32 max_incoming_dynamic_streams_;
+ // The number of bytes required for the connection ID.
+ QuicFixedUint32 bytes_for_connection_id_;
+ // Initial round trip time estimate in microseconds.
+ QuicFixedUint32 initial_round_trip_time_us_;
+
+ // Initial stream flow control receive window in bytes.
+ QuicFixedUint32 initial_stream_flow_control_window_bytes_;
+ // Initial session flow control receive window in bytes.
+ QuicFixedUint32 initial_session_flow_control_window_bytes_;
+
+ // Whether tell peer not to attempt connection migration.
+ QuicFixedUint32 connection_migration_disabled_;
+
+ // An alternate server address the client could connect to.
+ QuicFixedSocketAddress alternate_server_address_;
+
+ // Whether support HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
+ QuicFixedUint32 support_max_header_list_size_;
+
+ // Stateless reset token used in IETF public reset packet.
+ QuicFixedUint128 stateless_reset_token_;
+
+ // List of QuicTags whose presence immediately causes the session to
+ // be created. This allows for CHLOs that are larger than a single
+ // packet to be processed.
+ QuicTagVector create_session_tag_indicators_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_CONFIG_H_