// 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.

#include "quiche/quic/core/quic_config.h"

#include <algorithm>
#include <cstring>
#include <limits>
#include <string>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/crypto_handshake_message.h"
#include "quiche/quic/core/crypto/crypto_protocol.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/core/quic_socket_address_coder.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_flag_utils.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_socket_address.h"

namespace quic {

// Reads the value corresponding to |name_| from |msg| into |out|. If the
// |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
// to |default_value|.
QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg, QuicTag tag,
                         QuicConfigPresence presence, uint32_t default_value,
                         uint32_t* out, std::string* error_details) {
  QUICHE_DCHECK(error_details != nullptr);
  QuicErrorCode error = msg.GetUint32(tag, out);
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence == PRESENCE_REQUIRED) {
        *error_details = "Missing " + QuicTagToString(tag);
        break;
      }
      error = QUIC_NO_ERROR;
      *out = default_value;
      break;
    case QUIC_NO_ERROR:
      break;
    default:
      *error_details = "Bad " + QuicTagToString(tag);
      break;
  }
  return error;
}

QuicConfigValue::QuicConfigValue(QuicTag tag, QuicConfigPresence presence)
    : tag_(tag), presence_(presence) {}
QuicConfigValue::~QuicConfigValue() {}

QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
    : QuicConfigValue(tag, presence),
      has_send_value_(false),
      has_receive_value_(false) {}
QuicFixedUint32::~QuicFixedUint32() {}

bool QuicFixedUint32::HasSendValue() const { return has_send_value_; }

uint32_t QuicFixedUint32::GetSendValue() const {
  QUIC_BUG_IF(quic_bug_12743_1, !has_send_value_)
      << "No send value to get for tag:" << QuicTagToString(tag_);
  return send_value_;
}

void QuicFixedUint32::SetSendValue(uint32_t value) {
  has_send_value_ = true;
  send_value_ = value;
}

bool QuicFixedUint32::HasReceivedValue() const { return has_receive_value_; }

uint32_t QuicFixedUint32::GetReceivedValue() const {
  QUIC_BUG_IF(quic_bug_12743_2, !has_receive_value_)
      << "No receive value to get for tag:" << QuicTagToString(tag_);
  return receive_value_;
}

void QuicFixedUint32::SetReceivedValue(uint32_t value) {
  has_receive_value_ = true;
  receive_value_ = value;
}

void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
  if (tag_ == 0) {
    QUIC_BUG(quic_bug_12743_3)
        << "This parameter does not support writing to CryptoHandshakeMessage";
    return;
  }
  if (has_send_value_) {
    out->SetValue(tag_, send_value_);
  }
}

QuicErrorCode QuicFixedUint32::ProcessPeerHello(
    const CryptoHandshakeMessage& peer_hello, HelloType /*hello_type*/,
    std::string* error_details) {
  QUICHE_DCHECK(error_details != nullptr);
  if (tag_ == 0) {
    *error_details =
        "This parameter does not support reading from CryptoHandshakeMessage";
    QUIC_BUG(quic_bug_10575_1) << *error_details;
    return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
  }
  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence_ == PRESENCE_OPTIONAL) {
        return QUIC_NO_ERROR;
      }
      *error_details = "Missing " + QuicTagToString(tag_);
      break;
    case QUIC_NO_ERROR:
      has_receive_value_ = true;
      break;
    default:
      *error_details = "Bad " + QuicTagToString(tag_);
      break;
  }
  return error;
}

QuicFixedUint62::QuicFixedUint62(QuicTag name, QuicConfigPresence presence)
    : QuicConfigValue(name, presence),
      has_send_value_(false),
      has_receive_value_(false) {}

QuicFixedUint62::~QuicFixedUint62() {}

bool QuicFixedUint62::HasSendValue() const { return has_send_value_; }

uint64_t QuicFixedUint62::GetSendValue() const {
  if (!has_send_value_) {
    QUIC_BUG(quic_bug_10575_2)
        << "No send value to get for tag:" << QuicTagToString(tag_);
    return 0;
  }
  return send_value_;
}

void QuicFixedUint62::SetSendValue(uint64_t value) {
  if (value > quiche::kVarInt62MaxValue) {
    QUIC_BUG(quic_bug_10575_3) << "QuicFixedUint62 invalid value " << value;
    value = quiche::kVarInt62MaxValue;
  }
  has_send_value_ = true;
  send_value_ = value;
}

bool QuicFixedUint62::HasReceivedValue() const { return has_receive_value_; }

uint64_t QuicFixedUint62::GetReceivedValue() const {
  if (!has_receive_value_) {
    QUIC_BUG(quic_bug_10575_4)
        << "No receive value to get for tag:" << QuicTagToString(tag_);
    return 0;
  }
  return receive_value_;
}

void QuicFixedUint62::SetReceivedValue(uint64_t value) {
  has_receive_value_ = true;
  receive_value_ = value;
}

void QuicFixedUint62::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
  if (!has_send_value_) {
    return;
  }
  uint32_t send_value32;
  if (send_value_ > std::numeric_limits<uint32_t>::max()) {
    QUIC_BUG(quic_bug_10575_5) << "Attempting to send " << send_value_
                               << " for tag:" << QuicTagToString(tag_);
    send_value32 = std::numeric_limits<uint32_t>::max();
  } else {
    send_value32 = static_cast<uint32_t>(send_value_);
  }
  out->SetValue(tag_, send_value32);
}

QuicErrorCode QuicFixedUint62::ProcessPeerHello(
    const CryptoHandshakeMessage& peer_hello, HelloType /*hello_type*/,
    std::string* error_details) {
  QUICHE_DCHECK(error_details != nullptr);
  uint32_t receive_value32;
  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value32);
  // GetUint32 is guaranteed to always initialize receive_value32.
  receive_value_ = receive_value32;
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence_ == PRESENCE_OPTIONAL) {
        return QUIC_NO_ERROR;
      }
      *error_details = "Missing " + QuicTagToString(tag_);
      break;
    case QUIC_NO_ERROR:
      has_receive_value_ = true;
      break;
    default:
      *error_details = "Bad " + QuicTagToString(tag_);
      break;
  }
  return error;
}

QuicFixedStatelessResetToken::QuicFixedStatelessResetToken(
    QuicTag tag, QuicConfigPresence presence)
    : QuicConfigValue(tag, presence),
      has_send_value_(false),
      has_receive_value_(false) {}
QuicFixedStatelessResetToken::~QuicFixedStatelessResetToken() {}

bool QuicFixedStatelessResetToken::HasSendValue() const {
  return has_send_value_;
}

const StatelessResetToken& QuicFixedStatelessResetToken::GetSendValue() const {
  QUIC_BUG_IF(quic_bug_12743_4, !has_send_value_)
      << "No send value to get for tag:" << QuicTagToString(tag_);
  return send_value_;
}

void QuicFixedStatelessResetToken::SetSendValue(
    const StatelessResetToken& value) {
  has_send_value_ = true;
  send_value_ = value;
}

bool QuicFixedStatelessResetToken::HasReceivedValue() const {
  return has_receive_value_;
}

const StatelessResetToken& QuicFixedStatelessResetToken::GetReceivedValue()
    const {
  QUIC_BUG_IF(quic_bug_12743_5, !has_receive_value_)
      << "No receive value to get for tag:" << QuicTagToString(tag_);
  return receive_value_;
}

void QuicFixedStatelessResetToken::SetReceivedValue(
    const StatelessResetToken& value) {
  has_receive_value_ = true;
  receive_value_ = value;
}

void QuicFixedStatelessResetToken::ToHandshakeMessage(
    CryptoHandshakeMessage* out) const {
  if (has_send_value_) {
    out->SetValue(tag_, send_value_);
  }
}

QuicErrorCode QuicFixedStatelessResetToken::ProcessPeerHello(
    const CryptoHandshakeMessage& peer_hello, HelloType /*hello_type*/,
    std::string* error_details) {
  QUICHE_DCHECK(error_details != nullptr);
  QuicErrorCode error =
      peer_hello.GetStatelessResetToken(tag_, &receive_value_);
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence_ == PRESENCE_OPTIONAL) {
        return QUIC_NO_ERROR;
      }
      *error_details = "Missing " + QuicTagToString(tag_);
      break;
    case QUIC_NO_ERROR:
      has_receive_value_ = true;
      break;
    default:
      *error_details = "Bad " + QuicTagToString(tag_);
      break;
  }
  return error;
}

QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
                                       QuicConfigPresence presence)
    : QuicConfigValue(name, presence),
      has_send_values_(false),
      has_receive_values_(false) {}

QuicFixedTagVector::QuicFixedTagVector(const QuicFixedTagVector& other) =
    default;

QuicFixedTagVector::~QuicFixedTagVector() {}

bool QuicFixedTagVector::HasSendValues() const { return has_send_values_; }

const QuicTagVector& QuicFixedTagVector::GetSendValues() const {
  QUIC_BUG_IF(quic_bug_12743_6, !has_send_values_)
      << "No send values to get for tag:" << QuicTagToString(tag_);
  return send_values_;
}

void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
  has_send_values_ = true;
  send_values_ = values;
}

bool QuicFixedTagVector::HasReceivedValues() const {
  return has_receive_values_;
}

const QuicTagVector& QuicFixedTagVector::GetReceivedValues() const {
  QUIC_BUG_IF(quic_bug_12743_7, !has_receive_values_)
      << "No receive value to get for tag:" << QuicTagToString(tag_);
  return receive_values_;
}

void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
  has_receive_values_ = true;
  receive_values_ = values;
}

void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
  if (has_send_values_) {
    out->SetVector(tag_, send_values_);
  }
}

QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
    const CryptoHandshakeMessage& peer_hello, HelloType /*hello_type*/,
    std::string* error_details) {
  QUICHE_DCHECK(error_details != nullptr);
  QuicTagVector values;
  QuicErrorCode error = peer_hello.GetTaglist(tag_, &values);
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence_ == PRESENCE_OPTIONAL) {
        return QUIC_NO_ERROR;
      }
      *error_details = "Missing " + QuicTagToString(tag_);
      break;
    case QUIC_NO_ERROR:
      QUIC_DVLOG(1) << "Received Connection Option tags from receiver.";
      has_receive_values_ = true;
      receive_values_.insert(receive_values_.end(), values.begin(),
                             values.end());
      break;
    default:
      *error_details = "Bad " + QuicTagToString(tag_);
      break;
  }
  return error;
}

QuicFixedSocketAddress::QuicFixedSocketAddress(QuicTag tag,
                                               QuicConfigPresence presence)
    : QuicConfigValue(tag, presence),
      has_send_value_(false),
      has_receive_value_(false) {}

QuicFixedSocketAddress::~QuicFixedSocketAddress() {}

bool QuicFixedSocketAddress::HasSendValue() const { return has_send_value_; }

const QuicSocketAddress& QuicFixedSocketAddress::GetSendValue() const {
  QUIC_BUG_IF(quic_bug_12743_8, !has_send_value_)
      << "No send value to get for tag:" << QuicTagToString(tag_);
  return send_value_;
}

void QuicFixedSocketAddress::SetSendValue(const QuicSocketAddress& value) {
  has_send_value_ = true;
  send_value_ = value;
}

bool QuicFixedSocketAddress::HasReceivedValue() const {
  return has_receive_value_;
}

const QuicSocketAddress& QuicFixedSocketAddress::GetReceivedValue() const {
  QUIC_BUG_IF(quic_bug_12743_9, !has_receive_value_)
      << "No receive value to get for tag:" << QuicTagToString(tag_);
  return receive_value_;
}

void QuicFixedSocketAddress::SetReceivedValue(const QuicSocketAddress& value) {
  has_receive_value_ = true;
  receive_value_ = value;
}

void QuicFixedSocketAddress::ToHandshakeMessage(
    CryptoHandshakeMessage* out) const {
  if (has_send_value_) {
    QuicSocketAddressCoder address_coder(send_value_);
    out->SetStringPiece(tag_, address_coder.Encode());
  }
}

QuicErrorCode QuicFixedSocketAddress::ProcessPeerHello(
    const CryptoHandshakeMessage& peer_hello, HelloType /*hello_type*/,
    std::string* error_details) {
  absl::string_view address;
  if (!peer_hello.GetStringPiece(tag_, &address)) {
    if (presence_ == PRESENCE_REQUIRED) {
      *error_details = "Missing " + QuicTagToString(tag_);
      return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
    }
  } else {
    QuicSocketAddressCoder address_coder;
    if (address_coder.Decode(address.data(), address.length())) {
      SetReceivedValue(
          QuicSocketAddress(address_coder.ip(), address_coder.port()));
    }
  }
  return QUIC_NO_ERROR;
}

QuicConfig::QuicConfig()
    : negotiated_(false),
      max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
      max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
      max_undecryptable_packets_(0),
      connection_options_(kCOPT, PRESENCE_OPTIONAL),
      client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
      max_idle_timeout_to_send_(QuicTime::Delta::Infinite()),
      max_bidirectional_streams_(kMIBS, PRESENCE_REQUIRED),
      max_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL),
      bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
      initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
      initial_max_stream_data_bytes_incoming_bidirectional_(0,
                                                            PRESENCE_OPTIONAL),
      initial_max_stream_data_bytes_outgoing_bidirectional_(0,
                                                            PRESENCE_OPTIONAL),
      initial_max_stream_data_bytes_unidirectional_(0, PRESENCE_OPTIONAL),
      initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
      initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
      connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
      alternate_server_address_ipv6_(kASAD, PRESENCE_OPTIONAL),
      alternate_server_address_ipv4_(kASAD, PRESENCE_OPTIONAL),
      stateless_reset_token_(kSRST, PRESENCE_OPTIONAL),
      max_ack_delay_ms_(kMAD, PRESENCE_OPTIONAL),
      min_ack_delay_ms_(0, PRESENCE_OPTIONAL),
      ack_delay_exponent_(kADE, PRESENCE_OPTIONAL),
      max_udp_payload_size_(0, PRESENCE_OPTIONAL),
      max_datagram_frame_size_(0, PRESENCE_OPTIONAL),
      active_connection_id_limit_(0, PRESENCE_OPTIONAL) {
  SetDefaults();
}

QuicConfig::QuicConfig(const QuicConfig& other) = default;

QuicConfig::~QuicConfig() {}

bool QuicConfig::SetInitialReceivedConnectionOptions(
    const QuicTagVector& tags) {
  if (HasReceivedConnectionOptions()) {
    // If we have already received connection options (via handshake or due to
    // a previous call), don't re-initialize.
    return false;
  }
  connection_options_.SetReceivedValues(tags);
  return true;
}

void QuicConfig::SetConnectionOptionsToSend(
    const QuicTagVector& connection_options) {
  connection_options_.SetSendValues(connection_options);
}

bool QuicConfig::HasReceivedConnectionOptions() const {
  return connection_options_.HasReceivedValues();
}

const QuicTagVector& QuicConfig::ReceivedConnectionOptions() const {
  return connection_options_.GetReceivedValues();
}

bool QuicConfig::HasSendConnectionOptions() const {
  return connection_options_.HasSendValues();
}

const QuicTagVector& QuicConfig::SendConnectionOptions() const {
  return connection_options_.GetSendValues();
}

bool QuicConfig::HasClientSentConnectionOption(QuicTag tag,
                                               Perspective perspective) const {
  if (perspective == Perspective::IS_SERVER) {
    if (HasReceivedConnectionOptions() &&
        ContainsQuicTag(ReceivedConnectionOptions(), tag)) {
      return true;
    }
  } else if (HasSendConnectionOptions() &&
             ContainsQuicTag(SendConnectionOptions(), tag)) {
    return true;
  }
  return false;
}

void QuicConfig::SetClientConnectionOptions(
    const QuicTagVector& client_connection_options) {
  client_connection_options_.SetSendValues(client_connection_options);
}

bool QuicConfig::HasClientRequestedIndependentOption(
    QuicTag tag, Perspective perspective) const {
  if (perspective == Perspective::IS_SERVER) {
    return (HasReceivedConnectionOptions() &&
            ContainsQuicTag(ReceivedConnectionOptions(), tag));
  }

  return (client_connection_options_.HasSendValues() &&
          ContainsQuicTag(client_connection_options_.GetSendValues(), tag));
}

const QuicTagVector& QuicConfig::ClientRequestedIndependentOptions(
    Perspective perspective) const {
  static const QuicTagVector* no_options = new QuicTagVector;
  if (perspective == Perspective::IS_SERVER) {
    return HasReceivedConnectionOptions() ? ReceivedConnectionOptions()
                                          : *no_options;
  }

  return client_connection_options_.HasSendValues()
             ? client_connection_options_.GetSendValues()
             : *no_options;
}

void QuicConfig::SetIdleNetworkTimeout(QuicTime::Delta idle_network_timeout) {
  if (idle_network_timeout.ToMicroseconds() <= 0) {
    QUIC_BUG(quic_bug_10575_6)
        << "Invalid idle network timeout " << idle_network_timeout;
    return;
  }
  max_idle_timeout_to_send_ = idle_network_timeout;
}

QuicTime::Delta QuicConfig::IdleNetworkTimeout() const {
  // TODO(b/152032210) add a QUIC_BUG to ensure that is not called before we've
  // received the peer's values. This is true in production code but not in all
  // of our tests that use a fake QuicConfig.
  if (!received_max_idle_timeout_.has_value()) {
    return max_idle_timeout_to_send_;
  }
  return received_max_idle_timeout_.value();
}

void QuicConfig::SetMaxBidirectionalStreamsToSend(uint32_t max_streams) {
  max_bidirectional_streams_.SetSendValue(max_streams);
}

uint32_t QuicConfig::GetMaxBidirectionalStreamsToSend() const {
  return max_bidirectional_streams_.GetSendValue();
}

bool QuicConfig::HasReceivedMaxBidirectionalStreams() const {
  return max_bidirectional_streams_.HasReceivedValue();
}

uint32_t QuicConfig::ReceivedMaxBidirectionalStreams() const {
  return max_bidirectional_streams_.GetReceivedValue();
}

void QuicConfig::SetMaxUnidirectionalStreamsToSend(uint32_t max_streams) {
  max_unidirectional_streams_.SetSendValue(max_streams);
}

uint32_t QuicConfig::GetMaxUnidirectionalStreamsToSend() const {
  return max_unidirectional_streams_.GetSendValue();
}

bool QuicConfig::HasReceivedMaxUnidirectionalStreams() const {
  return max_unidirectional_streams_.HasReceivedValue();
}

uint32_t QuicConfig::ReceivedMaxUnidirectionalStreams() const {
  return max_unidirectional_streams_.GetReceivedValue();
}

void QuicConfig::SetMaxAckDelayToSendMs(uint32_t max_ack_delay_ms) {
  max_ack_delay_ms_.SetSendValue(max_ack_delay_ms);
}

uint32_t QuicConfig::GetMaxAckDelayToSendMs() const {
  return max_ack_delay_ms_.GetSendValue();
}

bool QuicConfig::HasReceivedMaxAckDelayMs() const {
  return max_ack_delay_ms_.HasReceivedValue();
}

uint32_t QuicConfig::ReceivedMaxAckDelayMs() const {
  return max_ack_delay_ms_.GetReceivedValue();
}

void QuicConfig::SetMinAckDelayMs(uint32_t min_ack_delay_ms) {
  min_ack_delay_ms_.SetSendValue(min_ack_delay_ms);
}

uint32_t QuicConfig::GetMinAckDelayToSendMs() const {
  return min_ack_delay_ms_.GetSendValue();
}

bool QuicConfig::HasReceivedMinAckDelayMs() const {
  return min_ack_delay_ms_.HasReceivedValue();
}

uint32_t QuicConfig::ReceivedMinAckDelayMs() const {
  return min_ack_delay_ms_.GetReceivedValue();
}

void QuicConfig::SetAckDelayExponentToSend(uint32_t exponent) {
  ack_delay_exponent_.SetSendValue(exponent);
}

uint32_t QuicConfig::GetAckDelayExponentToSend() const {
  return ack_delay_exponent_.GetSendValue();
}

bool QuicConfig::HasReceivedAckDelayExponent() const {
  return ack_delay_exponent_.HasReceivedValue();
}

uint32_t QuicConfig::ReceivedAckDelayExponent() const {
  return ack_delay_exponent_.GetReceivedValue();
}

void QuicConfig::SetMaxPacketSizeToSend(uint64_t max_udp_payload_size) {
  max_udp_payload_size_.SetSendValue(max_udp_payload_size);
}

uint64_t QuicConfig::GetMaxPacketSizeToSend() const {
  return max_udp_payload_size_.GetSendValue();
}

bool QuicConfig::HasReceivedMaxPacketSize() const {
  return max_udp_payload_size_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedMaxPacketSize() const {
  return max_udp_payload_size_.GetReceivedValue();
}

void QuicConfig::SetMaxDatagramFrameSizeToSend(
    uint64_t max_datagram_frame_size) {
  max_datagram_frame_size_.SetSendValue(max_datagram_frame_size);
}

uint64_t QuicConfig::GetMaxDatagramFrameSizeToSend() const {
  return max_datagram_frame_size_.GetSendValue();
}

bool QuicConfig::HasReceivedMaxDatagramFrameSize() const {
  return max_datagram_frame_size_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedMaxDatagramFrameSize() const {
  return max_datagram_frame_size_.GetReceivedValue();
}

void QuicConfig::SetActiveConnectionIdLimitToSend(
    uint64_t active_connection_id_limit) {
  active_connection_id_limit_.SetSendValue(active_connection_id_limit);
}

uint64_t QuicConfig::GetActiveConnectionIdLimitToSend() const {
  return active_connection_id_limit_.GetSendValue();
}

bool QuicConfig::HasReceivedActiveConnectionIdLimit() const {
  return active_connection_id_limit_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedActiveConnectionIdLimit() const {
  return active_connection_id_limit_.GetReceivedValue();
}

bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
  return bytes_for_connection_id_.HasSendValue();
}

void QuicConfig::SetBytesForConnectionIdToSend(uint32_t bytes) {
  bytes_for_connection_id_.SetSendValue(bytes);
}

bool QuicConfig::HasReceivedBytesForConnectionId() const {
  return bytes_for_connection_id_.HasReceivedValue();
}

uint32_t QuicConfig::ReceivedBytesForConnectionId() const {
  return bytes_for_connection_id_.GetReceivedValue();
}

void QuicConfig::SetInitialRoundTripTimeUsToSend(uint64_t rtt) {
  initial_round_trip_time_us_.SetSendValue(rtt);
}

bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
  return initial_round_trip_time_us_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedInitialRoundTripTimeUs() const {
  return initial_round_trip_time_us_.GetReceivedValue();
}

bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
  return initial_round_trip_time_us_.HasSendValue();
}

uint64_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
  return initial_round_trip_time_us_.GetSendValue();
}

void QuicConfig::SetInitialStreamFlowControlWindowToSend(
    uint64_t window_bytes) {
  if (window_bytes < kMinimumFlowControlSendWindow) {
    QUIC_BUG(quic_bug_10575_7)
        << "Initial stream flow control receive window (" << window_bytes
        << ") cannot be set lower than minimum ("
        << kMinimumFlowControlSendWindow << ").";
    window_bytes = kMinimumFlowControlSendWindow;
  }
  initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
}

uint64_t QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
  return initial_stream_flow_control_window_bytes_.GetSendValue();
}

bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
  return initial_stream_flow_control_window_bytes_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
  return initial_stream_flow_control_window_bytes_.GetReceivedValue();
}

void QuicConfig::SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
    uint64_t window_bytes) {
  initial_max_stream_data_bytes_incoming_bidirectional_.SetSendValue(
      window_bytes);
}

uint64_t QuicConfig::GetInitialMaxStreamDataBytesIncomingBidirectionalToSend()
    const {
  if (initial_max_stream_data_bytes_incoming_bidirectional_.HasSendValue()) {
    return initial_max_stream_data_bytes_incoming_bidirectional_.GetSendValue();
  }
  return initial_stream_flow_control_window_bytes_.GetSendValue();
}

bool QuicConfig::HasReceivedInitialMaxStreamDataBytesIncomingBidirectional()
    const {
  return initial_max_stream_data_bytes_incoming_bidirectional_
      .HasReceivedValue();
}

uint64_t QuicConfig::ReceivedInitialMaxStreamDataBytesIncomingBidirectional()
    const {
  return initial_max_stream_data_bytes_incoming_bidirectional_
      .GetReceivedValue();
}

void QuicConfig::SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
    uint64_t window_bytes) {
  initial_max_stream_data_bytes_outgoing_bidirectional_.SetSendValue(
      window_bytes);
}

uint64_t QuicConfig::GetInitialMaxStreamDataBytesOutgoingBidirectionalToSend()
    const {
  if (initial_max_stream_data_bytes_outgoing_bidirectional_.HasSendValue()) {
    return initial_max_stream_data_bytes_outgoing_bidirectional_.GetSendValue();
  }
  return initial_stream_flow_control_window_bytes_.GetSendValue();
}

bool QuicConfig::HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional()
    const {
  return initial_max_stream_data_bytes_outgoing_bidirectional_
      .HasReceivedValue();
}

uint64_t QuicConfig::ReceivedInitialMaxStreamDataBytesOutgoingBidirectional()
    const {
  return initial_max_stream_data_bytes_outgoing_bidirectional_
      .GetReceivedValue();
}

void QuicConfig::SetInitialMaxStreamDataBytesUnidirectionalToSend(
    uint64_t window_bytes) {
  initial_max_stream_data_bytes_unidirectional_.SetSendValue(window_bytes);
}

uint64_t QuicConfig::GetInitialMaxStreamDataBytesUnidirectionalToSend() const {
  if (initial_max_stream_data_bytes_unidirectional_.HasSendValue()) {
    return initial_max_stream_data_bytes_unidirectional_.GetSendValue();
  }
  return initial_stream_flow_control_window_bytes_.GetSendValue();
}

bool QuicConfig::HasReceivedInitialMaxStreamDataBytesUnidirectional() const {
  return initial_max_stream_data_bytes_unidirectional_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedInitialMaxStreamDataBytesUnidirectional() const {
  return initial_max_stream_data_bytes_unidirectional_.GetReceivedValue();
}

void QuicConfig::SetInitialSessionFlowControlWindowToSend(
    uint64_t window_bytes) {
  if (window_bytes < kMinimumFlowControlSendWindow) {
    QUIC_BUG(quic_bug_10575_8)
        << "Initial session flow control receive window (" << window_bytes
        << ") cannot be set lower than default ("
        << kMinimumFlowControlSendWindow << ").";
    window_bytes = kMinimumFlowControlSendWindow;
  }
  initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
}

uint64_t QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
  return initial_session_flow_control_window_bytes_.GetSendValue();
}

bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
  return initial_session_flow_control_window_bytes_.HasReceivedValue();
}

uint64_t QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
  return initial_session_flow_control_window_bytes_.GetReceivedValue();
}

void QuicConfig::SetDisableConnectionMigration() {
  connection_migration_disabled_.SetSendValue(1);
}

bool QuicConfig::DisableConnectionMigration() const {
  return connection_migration_disabled_.HasReceivedValue();
}

void QuicConfig::SetIPv6AlternateServerAddressToSend(
    const QuicSocketAddress& alternate_server_address_ipv6) {
  if (!alternate_server_address_ipv6.host().IsIPv6()) {
    QUIC_BUG(quic_bug_10575_9)
        << "Cannot use SetIPv6AlternateServerAddressToSend with "
        << alternate_server_address_ipv6;
    return;
  }
  alternate_server_address_ipv6_.SetSendValue(alternate_server_address_ipv6);
}

void QuicConfig::SetIPv6AlternateServerAddressToSend(
    const QuicSocketAddress& alternate_server_address_ipv6,
    const QuicConnectionId& connection_id,
    const StatelessResetToken& stateless_reset_token) {
  if (!alternate_server_address_ipv6.host().IsIPv6()) {
    QUIC_BUG(quic_bug_10575_10)
        << "Cannot use SetIPv6AlternateServerAddressToSend with "
        << alternate_server_address_ipv6;
    return;
  }
  alternate_server_address_ipv6_.SetSendValue(alternate_server_address_ipv6);
  preferred_address_connection_id_and_token_ =
      std::make_pair(connection_id, stateless_reset_token);
}

bool QuicConfig::HasReceivedIPv6AlternateServerAddress() const {
  return alternate_server_address_ipv6_.HasReceivedValue();
}

const QuicSocketAddress& QuicConfig::ReceivedIPv6AlternateServerAddress()
    const {
  return alternate_server_address_ipv6_.GetReceivedValue();
}

void QuicConfig::SetIPv4AlternateServerAddressToSend(
    const QuicSocketAddress& alternate_server_address_ipv4) {
  if (!alternate_server_address_ipv4.host().IsIPv4()) {
    QUIC_BUG(quic_bug_10575_11)
        << "Cannot use SetIPv4AlternateServerAddressToSend with "
        << alternate_server_address_ipv4;
    return;
  }
  alternate_server_address_ipv4_.SetSendValue(alternate_server_address_ipv4);
}

void QuicConfig::SetIPv4AlternateServerAddressToSend(
    const QuicSocketAddress& alternate_server_address_ipv4,
    const QuicConnectionId& connection_id,
    const StatelessResetToken& stateless_reset_token) {
  if (!alternate_server_address_ipv4.host().IsIPv4()) {
    QUIC_BUG(quic_bug_10575_12)
        << "Cannot use SetIPv4AlternateServerAddressToSend with "
        << alternate_server_address_ipv4;
    return;
  }
  alternate_server_address_ipv4_.SetSendValue(alternate_server_address_ipv4);
  preferred_address_connection_id_and_token_ =
      std::make_pair(connection_id, stateless_reset_token);
}

bool QuicConfig::HasReceivedIPv4AlternateServerAddress() const {
  return alternate_server_address_ipv4_.HasReceivedValue();
}

const QuicSocketAddress& QuicConfig::ReceivedIPv4AlternateServerAddress()
    const {
  return alternate_server_address_ipv4_.GetReceivedValue();
}

bool QuicConfig::HasReceivedPreferredAddressConnectionIdAndToken() const {
  return (HasReceivedIPv6AlternateServerAddress() ||
          HasReceivedIPv4AlternateServerAddress()) &&
         preferred_address_connection_id_and_token_.has_value();
}

const std::pair<QuicConnectionId, StatelessResetToken>&
QuicConfig::ReceivedPreferredAddressConnectionIdAndToken() const {
  QUICHE_DCHECK(HasReceivedPreferredAddressConnectionIdAndToken());
  return *preferred_address_connection_id_and_token_;
}

void QuicConfig::SetOriginalConnectionIdToSend(
    const QuicConnectionId& original_destination_connection_id) {
  original_destination_connection_id_to_send_ =
      original_destination_connection_id;
}

bool QuicConfig::HasReceivedOriginalConnectionId() const {
  return received_original_destination_connection_id_.has_value();
}

QuicConnectionId QuicConfig::ReceivedOriginalConnectionId() const {
  if (!HasReceivedOriginalConnectionId()) {
    QUIC_BUG(quic_bug_10575_13) << "No received original connection ID";
    return EmptyQuicConnectionId();
  }
  return received_original_destination_connection_id_.value();
}

void QuicConfig::SetInitialSourceConnectionIdToSend(
    const QuicConnectionId& initial_source_connection_id) {
  initial_source_connection_id_to_send_ = initial_source_connection_id;
}

bool QuicConfig::HasReceivedInitialSourceConnectionId() const {
  return received_initial_source_connection_id_.has_value();
}

QuicConnectionId QuicConfig::ReceivedInitialSourceConnectionId() const {
  if (!HasReceivedInitialSourceConnectionId()) {
    QUIC_BUG(quic_bug_10575_14) << "No received initial source connection ID";
    return EmptyQuicConnectionId();
  }
  return received_initial_source_connection_id_.value();
}

void QuicConfig::SetRetrySourceConnectionIdToSend(
    const QuicConnectionId& retry_source_connection_id) {
  retry_source_connection_id_to_send_ = retry_source_connection_id;
}

bool QuicConfig::HasReceivedRetrySourceConnectionId() const {
  return received_retry_source_connection_id_.has_value();
}

QuicConnectionId QuicConfig::ReceivedRetrySourceConnectionId() const {
  if (!HasReceivedRetrySourceConnectionId()) {
    QUIC_BUG(quic_bug_10575_15) << "No received retry source connection ID";
    return EmptyQuicConnectionId();
  }
  return received_retry_source_connection_id_.value();
}

void QuicConfig::SetStatelessResetTokenToSend(
    const StatelessResetToken& stateless_reset_token) {
  stateless_reset_token_.SetSendValue(stateless_reset_token);
}

bool QuicConfig::HasReceivedStatelessResetToken() const {
  return stateless_reset_token_.HasReceivedValue();
}

const StatelessResetToken& QuicConfig::ReceivedStatelessResetToken() const {
  return stateless_reset_token_.GetReceivedValue();
}

bool QuicConfig::negotiated() const { return negotiated_; }

void QuicConfig::SetCreateSessionTagIndicators(QuicTagVector tags) {
  create_session_tag_indicators_ = std::move(tags);
}

const QuicTagVector& QuicConfig::create_session_tag_indicators() const {
  return create_session_tag_indicators_;
}

void QuicConfig::SetDefaults() {
  SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs));
  SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
  SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
  max_time_before_crypto_handshake_ =
      QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
  max_idle_time_before_crypto_handshake_ =
      QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs);
  max_undecryptable_packets_ = kDefaultMaxUndecryptablePackets;

  SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
  SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
  SetMaxAckDelayToSendMs(kDefaultDelayedAckTimeMs);
  SetAckDelayExponentToSend(kDefaultAckDelayExponent);
  SetMaxPacketSizeToSend(kMaxIncomingPacketSize);
  SetMaxDatagramFrameSizeToSend(kMaxAcceptedDatagramFrameSize);
}

void QuicConfig::ToHandshakeMessage(
    CryptoHandshakeMessage* out, QuicTransportVersion transport_version) const {
  // Idle timeout has custom rules that are different from other values.
  // We configure ourselves with the minumum value between the one sent and
  // the one received. Additionally, when QUIC_CRYPTO is used, the server
  // MUST send an idle timeout no greater than the idle timeout it received
  // from the client. We therefore send the received value if it is lower.
  QuicFixedUint32 max_idle_timeout_seconds(kICSL, PRESENCE_REQUIRED);
  uint32_t max_idle_timeout_to_send_seconds =
      max_idle_timeout_to_send_.ToSeconds();
  if (received_max_idle_timeout_.has_value() &&
      received_max_idle_timeout_->ToSeconds() <
          max_idle_timeout_to_send_seconds) {
    max_idle_timeout_to_send_seconds = received_max_idle_timeout_->ToSeconds();
  }
  max_idle_timeout_seconds.SetSendValue(max_idle_timeout_to_send_seconds);
  max_idle_timeout_seconds.ToHandshakeMessage(out);

  // Do not need a version check here, max...bi... will encode
  // as "MIDS" -- the max initial dynamic streams tag -- if
  // doing some version other than IETF QUIC.
  max_bidirectional_streams_.ToHandshakeMessage(out);
  if (VersionHasIetfQuicFrames(transport_version)) {
    max_unidirectional_streams_.ToHandshakeMessage(out);
    ack_delay_exponent_.ToHandshakeMessage(out);
  }
  if (max_ack_delay_ms_.GetSendValue() != kDefaultDelayedAckTimeMs) {
    // Only send max ack delay if it is using a non-default value, because
    // the default value is used by QuicSentPacketManager if it is not
    // sent during the handshake, and we want to save bytes.
    max_ack_delay_ms_.ToHandshakeMessage(out);
  }
  bytes_for_connection_id_.ToHandshakeMessage(out);
  initial_round_trip_time_us_.ToHandshakeMessage(out);
  initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
  initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
  connection_migration_disabled_.ToHandshakeMessage(out);
  connection_options_.ToHandshakeMessage(out);
  if (alternate_server_address_ipv6_.HasSendValue()) {
    alternate_server_address_ipv6_.ToHandshakeMessage(out);
  } else {
    alternate_server_address_ipv4_.ToHandshakeMessage(out);
  }
  stateless_reset_token_.ToHandshakeMessage(out);
}

QuicErrorCode QuicConfig::ProcessPeerHello(
    const CryptoHandshakeMessage& peer_hello, HelloType hello_type,
    std::string* error_details) {
  QUICHE_DCHECK(error_details != nullptr);

  QuicErrorCode error = QUIC_NO_ERROR;
  if (error == QUIC_NO_ERROR) {
    // Idle timeout has custom rules that are different from other values.
    // We configure ourselves with the minumum value between the one sent and
    // the one received. Additionally, when QUIC_CRYPTO is used, the server
    // MUST send an idle timeout no greater than the idle timeout it received
    // from the client.
    QuicFixedUint32 max_idle_timeout_seconds(kICSL, PRESENCE_REQUIRED);
    error = max_idle_timeout_seconds.ProcessPeerHello(peer_hello, hello_type,
                                                      error_details);
    if (error == QUIC_NO_ERROR) {
      if (max_idle_timeout_seconds.GetReceivedValue() >
          max_idle_timeout_to_send_.ToSeconds()) {
        // The received value is higher than ours, ignore it if from the client
        // and raise an error if from the server.
        if (hello_type == SERVER) {
          error = QUIC_INVALID_NEGOTIATED_VALUE;
          *error_details =
              "Invalid value received for " + QuicTagToString(kICSL);
        }
      } else {
        received_max_idle_timeout_ = QuicTime::Delta::FromSeconds(
            max_idle_timeout_seconds.GetReceivedValue());
      }
    }
  }
  if (error == QUIC_NO_ERROR) {
    error = max_bidirectional_streams_.ProcessPeerHello(peer_hello, hello_type,
                                                        error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = max_unidirectional_streams_.ProcessPeerHello(peer_hello, hello_type,
                                                         error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = bytes_for_connection_id_.ProcessPeerHello(peer_hello, hello_type,
                                                      error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = initial_round_trip_time_us_.ProcessPeerHello(peer_hello, hello_type,
                                                         error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
        peer_hello, hello_type, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
        peer_hello, hello_type, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = connection_migration_disabled_.ProcessPeerHello(
        peer_hello, hello_type, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = connection_options_.ProcessPeerHello(peer_hello, hello_type,
                                                 error_details);
  }
  if (error == QUIC_NO_ERROR) {
    QuicFixedSocketAddress alternate_server_address(kASAD, PRESENCE_OPTIONAL);
    error = alternate_server_address.ProcessPeerHello(peer_hello, hello_type,
                                                      error_details);
    if (error == QUIC_NO_ERROR && alternate_server_address.HasReceivedValue()) {
      const QuicSocketAddress& received_address =
          alternate_server_address.GetReceivedValue();
      if (received_address.host().IsIPv6()) {
        alternate_server_address_ipv6_.SetReceivedValue(received_address);
      } else if (received_address.host().IsIPv4()) {
        alternate_server_address_ipv4_.SetReceivedValue(received_address);
      }
    }
  }
  if (error == QUIC_NO_ERROR) {
    error = stateless_reset_token_.ProcessPeerHello(peer_hello, hello_type,
                                                    error_details);
  }

  if (error == QUIC_NO_ERROR) {
    error = max_ack_delay_ms_.ProcessPeerHello(peer_hello, hello_type,
                                               error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = ack_delay_exponent_.ProcessPeerHello(peer_hello, hello_type,
                                                 error_details);
  }
  if (error == QUIC_NO_ERROR) {
    negotiated_ = true;
  }
  return error;
}

bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
  if (original_destination_connection_id_to_send_.has_value()) {
    params->original_destination_connection_id =
        original_destination_connection_id_to_send_.value();
  }

  params->max_idle_timeout_ms.set_value(
      max_idle_timeout_to_send_.ToMilliseconds());

  if (stateless_reset_token_.HasSendValue()) {
    StatelessResetToken stateless_reset_token =
        stateless_reset_token_.GetSendValue();
    params->stateless_reset_token.assign(
        reinterpret_cast<const char*>(&stateless_reset_token),
        reinterpret_cast<const char*>(&stateless_reset_token) +
            sizeof(stateless_reset_token));
  }

  params->max_udp_payload_size.set_value(GetMaxPacketSizeToSend());
  params->max_datagram_frame_size.set_value(GetMaxDatagramFrameSizeToSend());
  params->initial_max_data.set_value(
      GetInitialSessionFlowControlWindowToSend());
  // The max stream data bidirectional transport parameters can be either local
  // or remote. A stream is local iff it is initiated by the endpoint that sent
  // the transport parameter (see the Transport Parameter Definitions section of
  // draft-ietf-quic-transport). In this function we are sending transport
  // parameters, so a local stream is one we initiated, which means an outgoing
  // stream.
  params->initial_max_stream_data_bidi_local.set_value(
      GetInitialMaxStreamDataBytesOutgoingBidirectionalToSend());
  params->initial_max_stream_data_bidi_remote.set_value(
      GetInitialMaxStreamDataBytesIncomingBidirectionalToSend());
  params->initial_max_stream_data_uni.set_value(
      GetInitialMaxStreamDataBytesUnidirectionalToSend());
  params->initial_max_streams_bidi.set_value(
      GetMaxBidirectionalStreamsToSend());
  params->initial_max_streams_uni.set_value(
      GetMaxUnidirectionalStreamsToSend());
  params->max_ack_delay.set_value(GetMaxAckDelayToSendMs());
  if (min_ack_delay_ms_.HasSendValue()) {
    params->min_ack_delay_us.set_value(min_ack_delay_ms_.GetSendValue() *
                                       kNumMicrosPerMilli);
  }
  params->ack_delay_exponent.set_value(GetAckDelayExponentToSend());
  params->disable_active_migration =
      connection_migration_disabled_.HasSendValue() &&
      connection_migration_disabled_.GetSendValue() != 0;

  if (alternate_server_address_ipv6_.HasSendValue() ||
      alternate_server_address_ipv4_.HasSendValue()) {
    TransportParameters::PreferredAddress preferred_address;
    if (alternate_server_address_ipv6_.HasSendValue()) {
      preferred_address.ipv6_socket_address =
          alternate_server_address_ipv6_.GetSendValue();
    }
    if (alternate_server_address_ipv4_.HasSendValue()) {
      preferred_address.ipv4_socket_address =
          alternate_server_address_ipv4_.GetSendValue();
    }
    if (preferred_address_connection_id_and_token_) {
      preferred_address.connection_id =
          preferred_address_connection_id_and_token_->first;
      auto* begin = reinterpret_cast<const char*>(
          &preferred_address_connection_id_and_token_->second);
      auto* end =
          begin + sizeof(preferred_address_connection_id_and_token_->second);
      preferred_address.stateless_reset_token.assign(begin, end);
    }
    params->preferred_address =
        std::make_unique<TransportParameters::PreferredAddress>(
            preferred_address);
  }

  if (active_connection_id_limit_.HasSendValue()) {
    params->active_connection_id_limit.set_value(
        active_connection_id_limit_.GetSendValue());
  }

  if (initial_source_connection_id_to_send_.has_value()) {
    params->initial_source_connection_id =
        initial_source_connection_id_to_send_.value();
  }

  if (retry_source_connection_id_to_send_.has_value()) {
    params->retry_source_connection_id =
        retry_source_connection_id_to_send_.value();
  }

  if (initial_round_trip_time_us_.HasSendValue()) {
    params->initial_round_trip_time_us.set_value(
        initial_round_trip_time_us_.GetSendValue());
  }
  if (connection_options_.HasSendValues() &&
      !connection_options_.GetSendValues().empty()) {
    params->google_connection_options = connection_options_.GetSendValues();
  }

  params->custom_parameters = custom_transport_parameters_to_send_;

  return true;
}

QuicErrorCode QuicConfig::ProcessTransportParameters(
    const TransportParameters& params, bool is_resumption,
    std::string* error_details) {
  if (!is_resumption && params.original_destination_connection_id.has_value()) {
    received_original_destination_connection_id_ =
        params.original_destination_connection_id.value();
  }

  if (params.max_idle_timeout_ms.value() > 0 &&
      params.max_idle_timeout_ms.value() <
          static_cast<uint64_t>(max_idle_timeout_to_send_.ToMilliseconds())) {
    // An idle timeout of zero indicates it is disabled.
    // We also ignore values higher than ours which will cause us to use the
    // smallest value between ours and our peer's.
    received_max_idle_timeout_ =
        QuicTime::Delta::FromMilliseconds(params.max_idle_timeout_ms.value());
  }

  if (!is_resumption && !params.stateless_reset_token.empty()) {
    StatelessResetToken stateless_reset_token;
    if (params.stateless_reset_token.size() != sizeof(stateless_reset_token)) {
      QUIC_BUG(quic_bug_10575_16) << "Bad stateless reset token length "
                                  << params.stateless_reset_token.size();
      *error_details = "Bad stateless reset token length";
      return QUIC_INTERNAL_ERROR;
    }
    memcpy(&stateless_reset_token, params.stateless_reset_token.data(),
           params.stateless_reset_token.size());
    stateless_reset_token_.SetReceivedValue(stateless_reset_token);
  }

  if (params.max_udp_payload_size.IsValid()) {
    max_udp_payload_size_.SetReceivedValue(params.max_udp_payload_size.value());
  }

  if (params.max_datagram_frame_size.IsValid()) {
    max_datagram_frame_size_.SetReceivedValue(
        params.max_datagram_frame_size.value());
  }

  initial_session_flow_control_window_bytes_.SetReceivedValue(
      params.initial_max_data.value());

  // IETF QUIC specifies stream IDs and stream counts as 62-bit integers but
  // our implementation uses uint32_t to represent them to save memory.
  max_bidirectional_streams_.SetReceivedValue(
      std::min<uint64_t>(params.initial_max_streams_bidi.value(),
                         std::numeric_limits<uint32_t>::max()));
  max_unidirectional_streams_.SetReceivedValue(
      std::min<uint64_t>(params.initial_max_streams_uni.value(),
                         std::numeric_limits<uint32_t>::max()));

  // The max stream data bidirectional transport parameters can be either local
  // or remote. A stream is local iff it is initiated by the endpoint that sent
  // the transport parameter (see the Transport Parameter Definitions section of
  // draft-ietf-quic-transport). However in this function we are processing
  // received transport parameters, so a local stream is one initiated by our
  // peer, which means an incoming stream.
  initial_max_stream_data_bytes_incoming_bidirectional_.SetReceivedValue(
      params.initial_max_stream_data_bidi_local.value());
  initial_max_stream_data_bytes_outgoing_bidirectional_.SetReceivedValue(
      params.initial_max_stream_data_bidi_remote.value());
  initial_max_stream_data_bytes_unidirectional_.SetReceivedValue(
      params.initial_max_stream_data_uni.value());

  if (!is_resumption) {
    max_ack_delay_ms_.SetReceivedValue(params.max_ack_delay.value());
    if (params.ack_delay_exponent.IsValid()) {
      ack_delay_exponent_.SetReceivedValue(params.ack_delay_exponent.value());
    }
    if (params.preferred_address != nullptr) {
      if (params.preferred_address->ipv6_socket_address.port() != 0) {
        alternate_server_address_ipv6_.SetReceivedValue(
            params.preferred_address->ipv6_socket_address);
      }
      if (params.preferred_address->ipv4_socket_address.port() != 0) {
        alternate_server_address_ipv4_.SetReceivedValue(
            params.preferred_address->ipv4_socket_address);
      }
      // TODO(haoyuewang) Treat 0 length connection ID sent in preferred_address
      // as a connection error of type TRANSPORT_PARAMETER_ERROR when server
      // fully supports it.
      if (!params.preferred_address->connection_id.IsEmpty()) {
        preferred_address_connection_id_and_token_ = std::make_pair(
            params.preferred_address->connection_id,
            *reinterpret_cast<const StatelessResetToken*>(
                &params.preferred_address->stateless_reset_token.front()));
      }
    }
    if (params.min_ack_delay_us.value() != 0) {
      if (params.min_ack_delay_us.value() >
          params.max_ack_delay.value() * kNumMicrosPerMilli) {
        *error_details = "MinAckDelay is greater than MaxAckDelay.";
        return IETF_QUIC_PROTOCOL_VIOLATION;
      }
      min_ack_delay_ms_.SetReceivedValue(params.min_ack_delay_us.value() /
                                         kNumMicrosPerMilli);
    }
  }

  if (params.disable_active_migration) {
    connection_migration_disabled_.SetReceivedValue(1u);
  }

  active_connection_id_limit_.SetReceivedValue(
      params.active_connection_id_limit.value());

  if (!is_resumption) {
    if (params.initial_source_connection_id.has_value()) {
      received_initial_source_connection_id_ =
          params.initial_source_connection_id.value();
    }
    if (params.retry_source_connection_id.has_value()) {
      received_retry_source_connection_id_ =
          params.retry_source_connection_id.value();
    }
  }

  if (params.initial_round_trip_time_us.value() > 0) {
    initial_round_trip_time_us_.SetReceivedValue(
        params.initial_round_trip_time_us.value());
  }
  if (params.google_connection_options.has_value()) {
    connection_options_.SetReceivedValues(
        params.google_connection_options.value());
  }

  received_custom_transport_parameters_ = params.custom_parameters;

  if (!is_resumption) {
    negotiated_ = true;
  }
  *error_details = "";
  return QUIC_NO_ERROR;
}

}  // namespace quic
