1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_config.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <algorithm>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/crypto/crypto_handshake_message.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/crypto/crypto_protocol.h"
12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "net/quic/quic_flags.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_utils.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using std::min;
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using std::string;
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Reads the value corresponding to |name_| from |msg| into |out|. If the
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// to |default_value|.
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         QuicTag tag,
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         QuicConfigPresence presence,
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         uint32 default_value,
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         uint32* out,
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         string* error_details) {
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(error_details != NULL);
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  QuicErrorCode error = msg.GetUint32(tag, out);
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (error) {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (presence == PRESENCE_REQUIRED) {
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        *error_details = "Missing " + QuicUtils::TagToString(tag);
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error = QUIC_NO_ERROR;
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *out = default_value;
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case QUIC_NO_ERROR:
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *error_details = "Bad " + QuicUtils::TagToString(tag);
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return error;
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicConfigValue::QuicConfigValue(QuicTag tag,
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 QuicConfigPresence presence)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : tag_(tag),
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      presence_(presence) {
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicConfigValue::~QuicConfigValue() {}
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         QuicConfigPresence presence)
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : QuicConfigValue(tag, presence),
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      negotiated_(false) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableValue::~QuicNegotiableValue() {}
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           QuicConfigPresence presence)
660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    : QuicNegotiableValue(tag, presence),
670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      max_value_(0),
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      default_value_(0) {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableUint32::~QuicNegotiableUint32() {}
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_LE(default_value, max);
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_value_ = max;
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  default_value_ = default_value;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)uint32 QuicNegotiableUint32::GetUint32() const {
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return negotiated_value_;
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return default_value_;
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableUint32::ToHandshakeMessage(
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CryptoHandshakeMessage* out) const {
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetValue(tag_, negotiated_value_);
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetValue(tag_, max_value_);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
940529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!negotiated_);
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 value;
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicErrorCode error = ReadUint32(peer_hello,
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   tag_,
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   presence_,
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   default_value_,
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   &value,
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   error_details);
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return error;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (hello_type == SERVER && value > max_value_) {
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *error_details =
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        "Invalid value received for " + QuicUtils::TagToString(tag_);
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return QUIC_INVALID_NEGOTIATED_VALUE;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  negotiated_ = true;
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  negotiated_value_ = min(value, max_value_);
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QUIC_NO_ERROR;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : QuicNegotiableValue(tag, presence),
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      negotiated_tag_(0),
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default_value_(0) {
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicNegotiableTag::~QuicNegotiableTag() {}
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableTag::set(const QuicTagVector& possible,
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            QuicTag default_value) {
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(ContainsQuicTag(possible, default_value));
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  possible_values_ = possible;
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  default_value_ = default_value;
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicTag QuicNegotiableTag::GetTag() const {
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return negotiated_tag_;
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return default_value_;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Because of the way we serialize and parse handshake messages we can
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // serialize this as value and still parse it as a vector.
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetValue(tag_, negotiated_tag_);
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetVector(tag_, possible_values_);
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicErrorCode QuicNegotiableTag::ReadVector(
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const CryptoHandshakeMessage& msg,
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const QuicTag** out,
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_t* out_length,
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    string* error_details) const {
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(error_details != NULL);
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (error) {
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (presence_ == PRESENCE_REQUIRED) {
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        *error_details = "Missing " + QuicUtils::TagToString(tag_);
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = QUIC_NO_ERROR;
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *out_length = 1;
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *out = &default_value_;
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case QUIC_NO_ERROR:
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *error_details = "Bad " + QuicUtils::TagToString(tag_);
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return error;
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1790529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicNegotiableTag::ProcessPeerHello(
1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!negotiated_);
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const QuicTag* received_tags;
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t received_tags_length;
1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicErrorCode error = ReadVector(peer_hello, &received_tags,
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   &received_tags_length, error_details);
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return error;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (hello_type == SERVER) {
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (received_tags_length != 1 ||
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        !ContainsQuicTag(possible_values_,  *received_tags)) {
1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Invalid " + QuicUtils::TagToString(tag_);
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return QUIC_INVALID_NEGOTIATED_VALUE;
1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    negotiated_tag_ = *received_tags;
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } else {
2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    QuicTag negotiated_tag;
2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!QuicUtils::FindMutualTag(possible_values_,
2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  received_tags,
2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  received_tags_length,
2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  QuicUtils::LOCAL_PRIORITY,
2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  &negotiated_tag,
2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  NULL)) {
2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Unsupported " + QuicUtils::TagToString(tag_);
2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    negotiated_tag_ = negotiated_tag;
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  negotiated_ = true;
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QUIC_NO_ERROR;
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2180529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : QuicConfigValue(tag, presence),
2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_send_value_(false),
2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_(false) {
2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2230529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedUint32::~QuicFixedUint32() {}
2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedUint32::HasSendValue() const {
2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_send_value_;
2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedUint32::GetSendValue() const {
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG_IF(DFATAL, !has_send_value_)
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return send_value_;
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedUint32::SetSendValue(uint32 value) {
2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_send_value_ = true;
2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  send_value_ = value;
2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedUint32::HasReceivedValue() const {
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_receive_value_;
2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedUint32::GetReceivedValue() const {
2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  LOG_IF(DFATAL, !has_receive_value_)
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return receive_value_;
2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedUint32::SetReceivedValue(uint32 value) {
2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_receive_value_ = true;
2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  receive_value_ = value;
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (has_send_value_) {
2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    out->SetValue(tag_, send_value_);
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2610529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicFixedUint32::ProcessPeerHello(
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  switch (error) {
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (presence_ == PRESENCE_OPTIONAL) {
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return QUIC_NO_ERROR;
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Missing " + QuicUtils::TagToString(tag_);
2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_NO_ERROR:
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_ = true;
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    default:
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Bad " + QuicUtils::TagToString(tag_);
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return error;
2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2840529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedTag::QuicFixedTag(QuicTag name,
2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                           QuicConfigPresence presence)
2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : QuicConfigValue(name, presence),
2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_send_value_(false),
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_(false) {
2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2910529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedTag::~QuicFixedTag() {}
2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedTag::HasSendValue() const {
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_send_value_;
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedTag::GetSendValue() const {
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG_IF(DFATAL, !has_send_value_)
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return send_value_;
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedTag::SetSendValue(uint32 value) {
3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_send_value_ = true;
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  send_value_ = value;
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedTag::HasReceivedValue() const {
3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_receive_value_;
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedTag::GetReceivedValue() const {
3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  LOG_IF(DFATAL, !has_receive_value_)
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return receive_value_;
3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedTag::SetReceivedValue(uint32 value) {
3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_receive_value_ = true;
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  receive_value_ = value;
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (has_send_value_) {
3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    out->SetValue(tag_, send_value_);
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3290529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicFixedTag::ProcessPeerHello(
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const CryptoHandshakeMessage& peer_hello,
3310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    string* error_details) {
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(error_details != NULL);
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  switch (error) {
3360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
33746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (presence_ == PRESENCE_OPTIONAL) {
33846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return QUIC_NO_ERROR;
3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Missing " + QuicUtils::TagToString(tag_);
3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_NO_ERROR:
3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_ = true;
3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    default:
3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Bad " + QuicUtils::TagToString(tag_);
3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return error;
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       QuicConfigPresence presence)
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : QuicConfigValue(name, presence),
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      has_send_values_(false),
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      has_receive_values_(false) {
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicFixedTagVector::~QuicFixedTagVector() {}
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool QuicFixedTagVector::HasSendValues() const {
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return has_send_values_;
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTagVector QuicFixedTagVector::GetSendValues() const {
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG_IF(DFATAL, !has_send_values_)
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No send values to get for tag:" << QuicUtils::TagToString(tag_);
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return send_values_;
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  has_send_values_ = true;
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  send_values_ = values;
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool QuicFixedTagVector::HasReceivedValues() const {
37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return has_receive_values_;
37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  LOG_IF(DFATAL, !has_receive_values_)
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return receive_values_;
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  has_receive_values_ = true;
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  receive_values_ = values;
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (has_send_values_) {
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out->SetVector(tag_, send_values_);
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const CryptoHandshakeMessage& peer_hello,
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    HelloType hello_type,
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    string* error_details) {
40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(error_details != NULL);
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const QuicTag* received_tags;
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  size_t received_tags_length;
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicErrorCode error =
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (error) {
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (presence_ == PRESENCE_OPTIONAL) {
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return QUIC_NO_ERROR;
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Missing " + QuicUtils::TagToString(tag_);
41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
41346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case QUIC_NO_ERROR:
414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DVLOG(1) << "Received Connection Option tags from receiver.";
41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      has_receive_values_ = true;
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      for (size_t i = 0; i < received_tags_length; ++i) {
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        receive_values_.push_back(received_tags[i]);
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    default:
42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Bad " + QuicUtils::TagToString(tag_);
42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
42346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return error;
42546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicConfig::QuicConfig()
42846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : congestion_feedback_(kCGST, PRESENCE_REQUIRED),
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      connection_options_(kCOPT, PRESENCE_OPTIONAL),
430e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      loss_detection_(kLOSS, PRESENCE_OPTIONAL),
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL),
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED),
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      initial_congestion_window_(kSWND, PRESENCE_OPTIONAL),
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // TODO(rjshade): Make this PRESENCE_REQUIRED when QUIC_VERSION_16 is
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // retired.
4396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL),
4406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
4416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // QUIC_VERSION_19.
4426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
4436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
4446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      // QUIC_VERSION_19.
4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
4466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL) {
44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig::~QuicConfig() {}
45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicConfig::set_congestion_feedback(
45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const QuicTagVector& congestion_feedback,
45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    QuicTag default_congestion_feedback) {
45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.set(congestion_feedback, default_congestion_feedback);
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTag QuicConfig::congestion_feedback() const {
45846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return congestion_feedback_.GetTag();
45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
461116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid QuicConfig::SetConnectionOptionsToSend(
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const QuicTagVector& connection_options) {
463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  connection_options_.SetSendValues(connection_options);
464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool QuicConfig::HasReceivedConnectionOptions() const {
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return connection_options_.HasReceivedValues();
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
470116680a4aac90f2aa7413d9095a592090648e557Ben MurdochQuicTagVector QuicConfig::ReceivedConnectionOptions() const {
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return connection_options_.GetReceivedValues();
47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
47346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool QuicConfig::HasSendConnectionOptions() const {
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return connection_options_.HasSendValues();
47646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
47746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
478116680a4aac90f2aa7413d9095a592090648e557Ben MurdochQuicTagVector QuicConfig::SendConnectionOptions() const {
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return connection_options_.GetSendValues();
48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
4830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  loss_detection_.SetSendValue(loss_detection);
484e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
485e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
4860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedLossDetection() const {
4870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return loss_detection_.HasReceivedValue();
4880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
4890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4900529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicTag QuicConfig::ReceivedLossDetection() const {
4910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return loss_detection_.GetReceivedValue();
492e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
493e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::set_idle_connection_state_lifetime(
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    QuicTime::Delta max_idle_connection_state_lifetime,
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    QuicTime::Delta default_idle_conection_state_lifetime) {
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  idle_connection_state_lifetime_seconds_.set(
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      max_idle_connection_state_lifetime.ToSeconds(),
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      default_idle_conection_state_lifetime.ToSeconds());
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QuicTime::Delta::FromSeconds(
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      idle_connection_state_lifetime_seconds_.GetUint32());
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicTime::Delta QuicConfig::keepalive_timeout() const {
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QuicTime::Delta::FromSeconds(
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      keepalive_timeout_seconds_.GetUint32());
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::set_max_streams_per_connection(size_t max_streams,
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                size_t default_streams) {
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_streams_per_connection_.set(max_streams, default_streams);
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)uint32 QuicConfig::max_streams_per_connection() const {
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return max_streams_per_connection_.GetUint32();
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void QuicConfig::set_max_time_before_crypto_handshake(
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    QuicTime::Delta max_time_before_crypto_handshake) {
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return max_time_before_crypto_handshake_;
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
5310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_congestion_window_.SetSendValue(initial_window);
5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedInitialCongestionWindow() const {
5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_congestion_window_.HasReceivedValue();
5360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicConfig::ReceivedInitialCongestionWindow() const {
5390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_congestion_window_.GetReceivedValue();
5400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
5430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_round_trip_time_us_.SetSendValue(rtt);
5440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
5470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_round_trip_time_us_.HasReceivedValue();
5480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
5510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_round_trip_time_us_.GetReceivedValue();
5520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return initial_round_trip_time_us_.HasSendValue();
5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciuint32 QuicConfig::GetInitialRoundTripTimeUsToSend() const {
5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return initial_round_trip_time_us_.GetSendValue();
5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes) {
563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (window_bytes < kDefaultFlowControlSendWindow) {
564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(DFATAL) << "Initial flow control receive window (" << window_bytes
565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                << ") cannot be set lower than default ("
566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                << kDefaultFlowControlSendWindow << ").";
567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    window_bytes = kDefaultFlowControlSendWindow;
568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
5690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_flow_control_window_bytes_.SetSendValue(window_bytes);
5700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return initial_flow_control_window_bytes_.GetSendValue();
574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return initial_flow_control_window_bytes_.HasReceivedValue();
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_flow_control_window_bytes_.GetReceivedValue();
582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
583a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
5856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (window_bytes < kDefaultFlowControlSendWindow) {
5866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    LOG(DFATAL) << "Initial stream flow control receive window ("
5876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << window_bytes << ") cannot be set lower than default ("
5886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << kDefaultFlowControlSendWindow << ").";
5896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    window_bytes = kDefaultFlowControlSendWindow;
5906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
5916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
5926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
5956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_stream_flow_control_window_bytes_.GetSendValue();
5966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
5996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_stream_flow_control_window_bytes_.HasReceivedValue();
6006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
6036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_stream_flow_control_window_bytes_.GetReceivedValue();
6046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
6076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (window_bytes < kDefaultFlowControlSendWindow) {
6086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    LOG(DFATAL) << "Initial session flow control receive window ("
6096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << window_bytes << ") cannot be set lower than default ("
6106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << kDefaultFlowControlSendWindow << ").";
6116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    window_bytes = kDefaultFlowControlSendWindow;
6126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
6136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
6146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
6176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_session_flow_control_window_bytes_.GetSendValue();
6186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
6216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_session_flow_control_window_bytes_.HasReceivedValue();
6226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
6256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_session_flow_control_window_bytes_.GetReceivedValue();
6266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window) {
6296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  socket_receive_buffer_.SetSendValue(tcp_receive_window);
6306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)uint32 QuicConfig::GetSocketReceiveBufferToSend() const {
6336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return socket_receive_buffer_.GetSendValue();
6346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
6376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return socket_receive_buffer_.HasReceivedValue();
6386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)uint32 QuicConfig::ReceivedSocketReceiveBuffer() const {
6416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return socket_receive_buffer_.GetReceivedValue();
6426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
64490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool QuicConfig::negotiated() {
6450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // TODO(ianswett): Add the negotiated parameters once and iterate over all
6460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
6470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // ProcessServerHello.
64846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return congestion_feedback_.negotiated() &&
64990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      idle_connection_state_lifetime_seconds_.negotiated() &&
65090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      keepalive_timeout_seconds_.negotiated() &&
6510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      max_streams_per_connection_.negotiated();
65290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
65390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
65490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::SetDefaults() {
65546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicTagVector congestion_feedback;
65646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback.push_back(kQBIC);
65746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.set(congestion_feedback, kQBIC);
6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  idle_connection_state_lifetime_seconds_.set(kMaximumIdleTimeoutSecs,
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              kDefaultInitialTimeoutSecs);
66090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // kKATO is optional. Return 0 if not negotiated.
66190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  keepalive_timeout_seconds_.set(0, 0);
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_max_streams_per_connection(kDefaultMaxStreamsPerConnection,
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 kDefaultMaxStreamsPerConnection);
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      kDefaultMaxTimeForCryptoHandshakeSecs);
666f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
667f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow);
6686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow);
6696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow);
67090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
67190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
67290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
67346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.ToHandshakeMessage(out);
67490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
67590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  keepalive_timeout_seconds_.ToHandshakeMessage(out);
67690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_streams_per_connection_.ToHandshakeMessage(out);
6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_congestion_window_.ToHandshakeMessage(out);
6780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  initial_round_trip_time_us_.ToHandshakeMessage(out);
679e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  loss_detection_.ToHandshakeMessage(out);
6800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_flow_control_window_bytes_.ToHandshakeMessage(out);
6816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
6826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
6836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  socket_receive_buffer_.ToHandshakeMessage(out);
684116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  connection_options_.ToHandshakeMessage(out);
68590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
68690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6870529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicConfig::ProcessPeerHello(
6880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
69090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
69190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
69290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
69390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  QuicErrorCode error = QUIC_NO_ERROR;
69490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
69546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    error = congestion_feedback_.ProcessPeerHello(
6960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello,  hello_type, error_details);
69790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
69890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
7000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
70190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
70290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = keepalive_timeout_seconds_.ProcessPeerHello(
7040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
70590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
70690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = max_streams_per_connection_.ProcessPeerHello(
7080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
70990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
7100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = initial_congestion_window_.ProcessPeerHello(
7120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
7130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
7140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = initial_round_trip_time_us_.ProcessPeerHello(
7160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
7170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = initial_flow_control_window_bytes_.ProcessPeerHello(
7200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
722e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (error == QUIC_NO_ERROR) {
7236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
7246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        peer_hello, hello_type, error_details);
7256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
7266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
7286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        peer_hello, hello_type, error_details);
7296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
7306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    error = socket_receive_buffer_.ProcessPeerHello(
7326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        peer_hello, hello_type, error_details);
7336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
7346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = loss_detection_.ProcessPeerHello(
7360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
737e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
73846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
739116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    error = connection_options_.ProcessPeerHello(
74046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        peer_hello, hello_type, error_details);
74146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
74290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return error;
74390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
74490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
746