// 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 NET_QUIC_QUIC_CONFIG_H_
#define NET_QUIC_QUIC_CONFIG_H_

#include <string>

#include "base/basictypes.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
#include "net/quic/quic_utils.h"

namespace net {

class NET_EXPORT_PRIVATE QuicNegotiableValue {
 public:
  enum Presence {
    // 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,
  };

  QuicNegotiableValue(QuicTag tag, Presence presence);

  bool negotiated() const {
    return negotiated_;
  }

 protected:
  const QuicTag tag_;
  const Presence presence_;
  bool negotiated_;
};

class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
 public:
  QuicNegotiableUint32(QuicTag name, Presence presence);

  // 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 max, uint32 default_value);

  // Returns the value negotiated if |negotiated_| is true, otherwise returns
  // default_value_ (used to set default values before negotiation finishes).
  uint32 GetUint32() 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;

  // Sets |negotiated_value_| to the minimum of |max_value_| and the
  // corresponding value from |client_hello|. If the corresponding value is
  // missing and PRESENCE_OPTIONAL then |negotiated_value_| is set to
  // |default_value_|.
  QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
                                   std::string* error_details);

  // Sets the |negotiated_value_| to the corresponding value from
  // |server_hello|. Returns error if the value received in |server_hello| is
  // greater than |max_value_|. If the corresponding value is missing and
  // PRESENCE_OPTIONAL then |negotiated_value_| is set to |0|,
  QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello,
                                   std::string* error_details);

 private:
  // 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 |max_value_|.
  QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
                           uint32* out,
                           std::string* error_details) const;

  uint32 max_value_;
  uint32 default_value_;
  uint32 negotiated_value_;
};

class NET_EXPORT_PRIVATE QuicNegotiableTag : public QuicNegotiableValue {
 public:
  QuicNegotiableTag(QuicTag name, Presence presence);
  ~QuicNegotiableTag();

  // Sets the possible values that |negotiated_tag_| can take after negotiation
  // and the default value that |negotiated_tag_| takes if OPTIONAL and *HLO
  // msg doesn't contain tag |name_|.
  void set(const QuicTagVector& possible_values, QuicTag default_value);

  // Returns the negotiated tag if |negotiated_| is true, otherwise returns
  // |default_value_| (used to set default values before negotiation finishes).
  QuicTag GetTag() const;

  // Serialises |name_| and vector (either possible or negotiated) to |out|. If
  // |negotiated_| is true then |negotiated_tag_| is serialised, otherwise
  // |possible_values_| is serialised.
  void ToHandshakeMessage(CryptoHandshakeMessage* out) const;

  // Selects the tag common to both tags in |client_hello| for |name_| and
  // |possible_values_| with preference to tag in |possible_values_|. The
  // selected tag is set as |negotiated_tag_|.
  QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
                                   std::string* error_details);

  // Sets the value for |name_| tag in |server_hello| as |negotiated_value_|.
  // Returns error if the value received in |server_hello| isn't present in
  // |possible_values_|.
  QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello,
                                   std::string* error_details);

 private:
  // Reads the vector corresponding to |name_| from |msg| into |out|. If the
  // |name_| is absent in |msg| and |presence_| is set to OPTIONAL |out| is set
  // to |possible_values_|.
  QuicErrorCode ReadVector(const CryptoHandshakeMessage& msg,
                           const QuicTag** out,
                           size_t* out_length,
                           std::string* error_details) const;

  QuicTag negotiated_tag_;
  QuicTagVector possible_values_;
  QuicTag default_value_;
};

// QuicConfig contains non-crypto configuration options that are negotiated in
// the crypto handshake.
class NET_EXPORT_PRIVATE QuicConfig {
 public:
  QuicConfig();
  ~QuicConfig();

  void set_congestion_control(const QuicTagVector& congestion_control,
                              QuicTag default_congestion_control);

  QuicTag congestion_control() const;

  void set_idle_connection_state_lifetime(
      QuicTime::Delta max_idle_connection_state_lifetime,
      QuicTime::Delta default_idle_conection_state_lifetime);

  QuicTime::Delta idle_connection_state_lifetime() const;

  QuicTime::Delta keepalive_timeout() const;

  void set_max_streams_per_connection(size_t max_streams,
                                      size_t default_streams);

  uint32 max_streams_per_connection() const;

  void set_max_time_before_crypto_handshake(
      QuicTime::Delta max_time_before_crypto_handshake);

  QuicTime::Delta max_time_before_crypto_handshake() const;

  bool negotiated();

  // SetDefaults sets the members to sensible, default values.
  void SetDefaults();

  // ToHandshakeMessage serializes the settings in this object as a series of
  // tags /value pairs and adds them to |out|.
  void ToHandshakeMessage(CryptoHandshakeMessage* out) const;

  // Calls ProcessClientHello on each negotiable parameter. On failure returns
  // the corresponding QuicErrorCode and sets detailed error in |error_details|.
  QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
                                   std::string* error_details);

  // Calls ProcessServerHello on each negotiable parameter. On failure returns
  // the corresponding QuicErrorCode and sets detailed error in |error_details|.
  QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello,
                                   std::string* error_details);

 private:
  // Congestion control feedback type.
  QuicNegotiableTag congestion_control_;
  // Idle connection state lifetime
  QuicNegotiableUint32 idle_connection_state_lifetime_seconds_;
  // Keepalive timeout, or 0 to turn off keepalive probes
  QuicNegotiableUint32 keepalive_timeout_seconds_;
  // Maximum number of streams that the connection can support.
  QuicNegotiableUint32 max_streams_per_connection_;
  // Maximum time till the session can be alive before crypto handshake is
  // finished. (Not negotiated).
  QuicTime::Delta max_time_before_crypto_handshake_;
};

}  // namespace net

#endif  // NET_QUIC_QUIC_CONFIG_H_
