// 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 "net/quic/quic_config.h"

#include <algorithm>

#include "base/logging.h"
#include "net/quic/quic_sent_packet_manager.h"

using std::string;

namespace net {

QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
    : tag_(tag),
      presence_(presence),
      negotiated_(false) {
}

QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
    : QuicNegotiableValue(tag, presence),
      max_value_(0),
      default_value_(0) {
}

void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
  DCHECK_LE(default_value, max);
  max_value_ = max;
  default_value_ = default_value;
}

uint32 QuicNegotiableUint32::GetUint32() const {
  if (negotiated_) {
    return negotiated_value_;
  }
  return default_value_;
}

void QuicNegotiableUint32::ToHandshakeMessage(
    CryptoHandshakeMessage* out) const {
  if (negotiated_) {
    out->SetValue(tag_, negotiated_value_);
  } else {
    out->SetValue(tag_, max_value_);
  }
}

QuicErrorCode QuicNegotiableUint32::ReadUint32(
    const CryptoHandshakeMessage& msg,
    uint32* out,
    string* error_details) const {
  DCHECK(error_details != NULL);
  QuicErrorCode error = msg.GetUint32(tag_, out);
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) {
        *error_details = "Missing " + QuicUtils::TagToString(tag_);
        break;
      }
      error = QUIC_NO_ERROR;
      *out = default_value_;

    case QUIC_NO_ERROR:
      break;
    default:
      *error_details = "Bad " + QuicUtils::TagToString(tag_);
      break;
  }
  return error;
}

QuicErrorCode QuicNegotiableUint32::ProcessClientHello(
    const CryptoHandshakeMessage& client_hello,
    string* error_details) {
  DCHECK(!negotiated_);
  DCHECK(error_details != NULL);
  uint32 value;
  QuicErrorCode error = ReadUint32(client_hello, &value, error_details);
  if (error != QUIC_NO_ERROR) {
    return error;
  }

  negotiated_ = true;
  negotiated_value_ = std::min(value, max_value_);

  return QUIC_NO_ERROR;
}

QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
    const CryptoHandshakeMessage& server_hello,
    string* error_details) {
  DCHECK(!negotiated_);
  DCHECK(error_details != NULL);
  uint32 value;
  QuicErrorCode error = ReadUint32(server_hello, &value, error_details);
  if (error != QUIC_NO_ERROR) {
    return error;
  }

  if (value > max_value_) {
    *error_details = "Invalid value received for " +
        QuicUtils::TagToString(tag_);
    return QUIC_INVALID_NEGOTIATED_VALUE;
  }

  negotiated_ = true;
  negotiated_value_ = value;
  return QUIC_NO_ERROR;
}

QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
    : QuicNegotiableValue(tag, presence),
      negotiated_tag_(0),
      default_value_(0) {
}

QuicNegotiableTag::~QuicNegotiableTag() {}

void QuicNegotiableTag::set(const QuicTagVector& possible,
                            QuicTag default_value) {
  DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
            possible.end());
  possible_values_ = possible;
  default_value_ = default_value;
}

QuicTag QuicNegotiableTag::GetTag() const {
  if (negotiated_) {
    return negotiated_tag_;
  }
  return default_value_;
}

void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
  if (negotiated_) {
    // Because of the way we serialize and parse handshake messages we can
    // serialize this as value and still parse it as a vector.
    out->SetValue(tag_, negotiated_tag_);
  } else {
    out->SetVector(tag_, possible_values_);
  }
}

QuicErrorCode QuicNegotiableTag::ReadVector(
    const CryptoHandshakeMessage& msg,
    const QuicTag** out,
    size_t* out_length,
    string* error_details) const {
  DCHECK(error_details != NULL);
  QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
  switch (error) {
    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
      if (presence_ == PRESENCE_REQUIRED) {
        *error_details = "Missing " + QuicUtils::TagToString(tag_);
        break;
      }
      error = QUIC_NO_ERROR;
      *out_length = 1;
      *out = &default_value_;

    case QUIC_NO_ERROR:
      break;
    default:
      *error_details = "Bad " + QuicUtils::TagToString(tag_);
      break;
  }
  return error;
}

QuicErrorCode QuicNegotiableTag::ProcessClientHello(
    const CryptoHandshakeMessage& client_hello,
    string* error_details) {
  DCHECK(!negotiated_);
  DCHECK(error_details != NULL);
  const QuicTag* received_tags;
  size_t received_tags_length;
  QuicErrorCode error = ReadVector(client_hello, &received_tags,
                                   &received_tags_length, error_details);
  if (error != QUIC_NO_ERROR) {
    return error;
  }

  QuicTag negotiated_tag;
  if (!QuicUtils::FindMutualTag(possible_values_,
                                received_tags,
                                received_tags_length,
                                QuicUtils::LOCAL_PRIORITY,
                                &negotiated_tag,
                                NULL)) {
    *error_details = "Unsuported " + QuicUtils::TagToString(tag_);
    return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
  }

  negotiated_ = true;
  negotiated_tag_ = negotiated_tag;
  return QUIC_NO_ERROR;
}

QuicErrorCode QuicNegotiableTag::ProcessServerHello(
    const CryptoHandshakeMessage& server_hello,
    string* error_details) {
  DCHECK(!negotiated_);
  DCHECK(error_details != NULL);
  const QuicTag* received_tags;
  size_t received_tags_length;
  QuicErrorCode error = ReadVector(server_hello, &received_tags,
                                   &received_tags_length, error_details);
  if (error != QUIC_NO_ERROR) {
    return error;
  }

  if (received_tags_length != 1 ||
      std::find(possible_values_.begin(), possible_values_.end(),
                *received_tags) == possible_values_.end()) {
    *error_details = "Invalid " + QuicUtils::TagToString(tag_);
    return QUIC_INVALID_NEGOTIATED_VALUE;
  }

  negotiated_ = true;
  negotiated_tag_ = *received_tags;
  return QUIC_NO_ERROR;
}

QuicConfig::QuicConfig() :
    congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED),
    idle_connection_state_lifetime_seconds_(
        kICSL, QuicNegotiableValue::PRESENCE_REQUIRED),
    keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL),
    max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED),
    max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
    server_initial_congestion_window_(
        kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL),
    initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) {
  // All optional non-zero parameters should be initialized here.
  server_initial_congestion_window_.set(kMaxInitialWindow,
                                        kDefaultInitialWindow);
}

QuicConfig::~QuicConfig() {}

void QuicConfig::set_congestion_control(
    const QuicTagVector& congestion_control,
    QuicTag default_congestion_control) {
  congestion_control_.set(congestion_control, default_congestion_control);
}

QuicTag QuicConfig::congestion_control() const {
  return congestion_control_.GetTag();
}

void QuicConfig::set_idle_connection_state_lifetime(
    QuicTime::Delta max_idle_connection_state_lifetime,
    QuicTime::Delta default_idle_conection_state_lifetime) {
  idle_connection_state_lifetime_seconds_.set(
      max_idle_connection_state_lifetime.ToSeconds(),
      default_idle_conection_state_lifetime.ToSeconds());
}

QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
  return QuicTime::Delta::FromSeconds(
      idle_connection_state_lifetime_seconds_.GetUint32());
}

QuicTime::Delta QuicConfig::keepalive_timeout() const {
  return QuicTime::Delta::FromSeconds(
      keepalive_timeout_seconds_.GetUint32());
}

void QuicConfig::set_max_streams_per_connection(size_t max_streams,
                                                size_t default_streams) {
  max_streams_per_connection_.set(max_streams, default_streams);
}

uint32 QuicConfig::max_streams_per_connection() const {
  return max_streams_per_connection_.GetUint32();
}

void QuicConfig::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 QuicConfig::max_time_before_crypto_handshake() const {
  return max_time_before_crypto_handshake_;
}

void QuicConfig::set_server_initial_congestion_window(size_t max_initial_window,
                                               size_t default_initial_window) {
  server_initial_congestion_window_.set(max_initial_window,
                                        default_initial_window);
}

uint32 QuicConfig::server_initial_congestion_window() const {
  return server_initial_congestion_window_.GetUint32();
}

void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt,
                                                size_t default_rtt) {
  initial_round_trip_time_us_.set(max_rtt, default_rtt);
}

uint32 QuicConfig::initial_round_trip_time_us() const {
  return initial_round_trip_time_us_.GetUint32();
}

bool QuicConfig::negotiated() {
  // TODO(ianswett): Add the negotiated parameters once and iterate over all
  // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
  // ProcessServerHello.
  return congestion_control_.negotiated() &&
      idle_connection_state_lifetime_seconds_.negotiated() &&
      keepalive_timeout_seconds_.negotiated() &&
      max_streams_per_connection_.negotiated() &&
      server_initial_congestion_window_.negotiated() &&
      initial_round_trip_time_us_.negotiated();
}

void QuicConfig::SetDefaults() {
  QuicTagVector congestion_control;
  if (FLAGS_enable_quic_pacing) {
    congestion_control.push_back(kPACE);
  }
  congestion_control.push_back(kQBIC);
  congestion_control_.set(congestion_control, kQBIC);
  idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
                                              kDefaultInitialTimeoutSecs);
  // kKATO is optional. Return 0 if not negotiated.
  keepalive_timeout_seconds_.set(0, 0);
  max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
                                  kDefaultMaxStreamsPerConnection);
  max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
      kDefaultMaxTimeForCryptoHandshakeSecs);
  server_initial_congestion_window_.set(kDefaultInitialWindow,
                                        kDefaultInitialWindow);
}

void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
  congestion_control_.ToHandshakeMessage(out);
  idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
  keepalive_timeout_seconds_.ToHandshakeMessage(out);
  max_streams_per_connection_.ToHandshakeMessage(out);
  server_initial_congestion_window_.ToHandshakeMessage(out);
  // TODO(ianswett): Don't transmit parameters which are optional and not set.
  initial_round_trip_time_us_.ToHandshakeMessage(out);
}

QuicErrorCode QuicConfig::ProcessClientHello(
    const CryptoHandshakeMessage& client_hello,
    string* error_details) {
  DCHECK(error_details != NULL);

  QuicErrorCode error = QUIC_NO_ERROR;
  if (error == QUIC_NO_ERROR) {
    error = congestion_control_.ProcessClientHello(client_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = idle_connection_state_lifetime_seconds_.ProcessClientHello(
        client_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = keepalive_timeout_seconds_.ProcessClientHello(
        client_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = max_streams_per_connection_.ProcessClientHello(
        client_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = server_initial_congestion_window_.ProcessClientHello(
        client_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = initial_round_trip_time_us_.ProcessClientHello(
        client_hello, error_details);
  }
  return error;
}

QuicErrorCode QuicConfig::ProcessServerHello(
    const CryptoHandshakeMessage& server_hello,
    string* error_details) {
  DCHECK(error_details != NULL);

  QuicErrorCode error = QUIC_NO_ERROR;
  if (error == QUIC_NO_ERROR) {
    error = congestion_control_.ProcessServerHello(server_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = idle_connection_state_lifetime_seconds_.ProcessServerHello(
        server_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = keepalive_timeout_seconds_.ProcessServerHello(
        server_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = max_streams_per_connection_.ProcessServerHello(
        server_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = server_initial_congestion_window_.ProcessServerHello(
        server_hello, error_details);
  }
  if (error == QUIC_NO_ERROR) {
    error = initial_round_trip_time_us_.ProcessServerHello(
        server_hello, error_details);
  }
  return error;
}

}  // namespace net
