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"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/quic/quic_sent_packet_manager.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_utils.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using std::min;
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using std::string;
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Reads the value corresponding to |name_| from |msg| into |out|. If the
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// to |default_value|.
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         QuicTag tag,
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         QuicConfigPresence presence,
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         uint32 default_value,
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         uint32* out,
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         string* error_details) {
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(error_details != NULL);
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  QuicErrorCode error = msg.GetUint32(tag, out);
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (error) {
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (presence == PRESENCE_REQUIRED) {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        *error_details = "Missing " + QuicUtils::TagToString(tag);
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error = QUIC_NO_ERROR;
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *out = default_value;
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case QUIC_NO_ERROR:
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *error_details = "Bad " + QuicUtils::TagToString(tag);
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return error;
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicConfigValue::QuicConfigValue(QuicTag tag,
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 QuicConfigPresence presence)
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : tag_(tag),
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      presence_(presence) {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicConfigValue::~QuicConfigValue() {}
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         QuicConfigPresence presence)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : QuicConfigValue(tag, presence),
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      negotiated_(false) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableValue::~QuicNegotiableValue() {}
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                           QuicConfigPresence presence)
670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    : QuicNegotiableValue(tag, presence),
680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      max_value_(0),
690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      default_value_(0) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableUint32::~QuicNegotiableUint32() {}
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_LE(default_value, max);
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_value_ = max;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  default_value_ = default_value;
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)uint32 QuicNegotiableUint32::GetUint32() const {
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return negotiated_value_;
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return default_value_;
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableUint32::ToHandshakeMessage(
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CryptoHandshakeMessage* out) const {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetValue(tag_, negotiated_value_);
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetValue(tag_, max_value_);
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
950529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!negotiated_);
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 value;
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicErrorCode error = ReadUint32(peer_hello,
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   tag_,
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   presence_,
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   default_value_,
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   &value,
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   error_details);
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return error;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (hello_type == SERVER && value > max_value_) {
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *error_details =
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        "Invalid value received for " + QuicUtils::TagToString(tag_);
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return QUIC_INVALID_NEGOTIATED_VALUE;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  negotiated_ = true;
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  negotiated_value_ = min(value, max_value_);
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QUIC_NO_ERROR;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : QuicNegotiableValue(tag, presence),
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      negotiated_tag_(0),
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default_value_(0) {
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicNegotiableTag::~QuicNegotiableTag() {}
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableTag::set(const QuicTagVector& possible,
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            QuicTag default_value) {
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(ContainsQuicTag(possible, default_value));
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  possible_values_ = possible;
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  default_value_ = default_value;
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicTag QuicNegotiableTag::GetTag() const {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return negotiated_tag_;
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return default_value_;
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (negotiated_) {
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Because of the way we serialize and parse handshake messages we can
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // serialize this as value and still parse it as a vector.
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetValue(tag_, negotiated_tag_);
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    out->SetVector(tag_, possible_values_);
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicErrorCode QuicNegotiableTag::ReadVector(
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const CryptoHandshakeMessage& msg,
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const QuicTag** out,
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_t* out_length,
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    string* error_details) const {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(error_details != NULL);
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (error) {
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (presence_ == PRESENCE_REQUIRED) {
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        *error_details = "Missing " + QuicUtils::TagToString(tag_);
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = QUIC_NO_ERROR;
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *out_length = 1;
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *out = &default_value_;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case QUIC_NO_ERROR:
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *error_details = "Bad " + QuicUtils::TagToString(tag_);
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return error;
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1800529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicNegotiableTag::ProcessPeerHello(
1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!negotiated_);
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const QuicTag* received_tags;
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t received_tags_length;
1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicErrorCode error = ReadVector(peer_hello, &received_tags,
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   &received_tags_length, error_details);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return error;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (hello_type == SERVER) {
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (received_tags_length != 1 ||
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        !ContainsQuicTag(possible_values_,  *received_tags)) {
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Invalid " + QuicUtils::TagToString(tag_);
1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return QUIC_INVALID_NEGOTIATED_VALUE;
1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    negotiated_tag_ = *received_tags;
2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } else {
2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    QuicTag negotiated_tag;
2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!QuicUtils::FindMutualTag(possible_values_,
2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  received_tags,
2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  received_tags_length,
2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  QuicUtils::LOCAL_PRIORITY,
2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  &negotiated_tag,
2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  NULL)) {
2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Unsupported " + QuicUtils::TagToString(tag_);
2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    negotiated_tag_ = negotiated_tag;
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  negotiated_ = true;
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QUIC_NO_ERROR;
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2190529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : QuicConfigValue(tag, presence),
2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_send_value_(false),
2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_(false) {
2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2240529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedUint32::~QuicFixedUint32() {}
2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedUint32::HasSendValue() const {
2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_send_value_;
2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedUint32::GetSendValue() const {
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG_IF(DFATAL, !has_send_value_)
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return send_value_;
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedUint32::SetSendValue(uint32 value) {
2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_send_value_ = true;
2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  send_value_ = value;
2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedUint32::HasReceivedValue() const {
2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_receive_value_;
2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedUint32::GetReceivedValue() const {
2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  LOG_IF(DFATAL, !has_receive_value_)
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return receive_value_;
2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedUint32::SetReceivedValue(uint32 value) {
2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_receive_value_ = true;
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  receive_value_ = value;
2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (has_send_value_) {
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    out->SetValue(tag_, send_value_);
2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2620529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicFixedUint32::ProcessPeerHello(
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  switch (error) {
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (presence_ == PRESENCE_OPTIONAL) {
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return QUIC_NO_ERROR;
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Missing " + QuicUtils::TagToString(tag_);
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_NO_ERROR:
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_ = true;
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    default:
2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Bad " + QuicUtils::TagToString(tag_);
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return error;
2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2850529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedTag::QuicFixedTag(QuicTag name,
2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                           QuicConfigPresence presence)
2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : QuicConfigValue(name, presence),
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_send_value_(false),
2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_(false) {
2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2920529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicFixedTag::~QuicFixedTag() {}
2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedTag::HasSendValue() const {
2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_send_value_;
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedTag::GetSendValue() const {
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG_IF(DFATAL, !has_send_value_)
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return send_value_;
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedTag::SetSendValue(uint32 value) {
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_send_value_ = true;
3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  send_value_ = value;
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicFixedTag::HasReceivedValue() const {
3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return has_receive_value_;
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicFixedTag::GetReceivedValue() const {
3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  LOG_IF(DFATAL, !has_receive_value_)
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return receive_value_;
3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedTag::SetReceivedValue(uint32 value) {
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  has_receive_value_ = true;
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  receive_value_ = value;
3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (has_send_value_) {
3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    out->SetValue(tag_, send_value_);
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3300529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicFixedTag::ProcessPeerHello(
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const CryptoHandshakeMessage& peer_hello,
3320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    string* error_details) {
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(error_details != NULL);
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
3360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  switch (error) {
3370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
33846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (presence_ == PRESENCE_OPTIONAL) {
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return QUIC_NO_ERROR;
3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Missing " + QuicUtils::TagToString(tag_);
3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    case QUIC_NO_ERROR:
3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      has_receive_value_ = true;
3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    default:
3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      *error_details = "Bad " + QuicUtils::TagToString(tag_);
3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return error;
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       QuicConfigPresence presence)
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : QuicConfigValue(name, presence),
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      has_send_values_(false),
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      has_receive_values_(false) {
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicFixedTagVector::~QuicFixedTagVector() {}
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool QuicFixedTagVector::HasSendValues() const {
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return has_send_values_;
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTagVector QuicFixedTagVector::GetSendValues() const {
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  LOG_IF(DFATAL, !has_send_values_)
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No send values to get for tag:" << QuicUtils::TagToString(tag_);
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return send_values_;
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  has_send_values_ = true;
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  send_values_ = values;
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool QuicFixedTagVector::HasReceivedValues() const {
37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return has_receive_values_;
37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  LOG_IF(DFATAL, !has_receive_values_)
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return receive_values_;
38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  has_receive_values_ = true;
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  receive_values_ = values;
39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (has_send_values_) {
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    out->SetVector(tag_, send_values_);
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const CryptoHandshakeMessage& peer_hello,
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    HelloType hello_type,
40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    string* error_details) {
40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(error_details != NULL);
40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const QuicTag* received_tags;
40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  size_t received_tags_length;
40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicErrorCode error =
40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (error) {
40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
40946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (presence_ == PRESENCE_OPTIONAL) {
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return QUIC_NO_ERROR;
41146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
41246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *error_details = "Missing " + QuicUtils::TagToString(tag_);
41346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      break;
41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case QUIC_NO_ERROR:
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),
42946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      congestion_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),
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // QUIC_VERSION_17.
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.
4456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL) {
44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicConfig::~QuicConfig() {}
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicConfig::set_congestion_feedback(
45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const QuicTagVector& congestion_feedback,
45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    QuicTag default_congestion_feedback) {
45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.set(congestion_feedback, default_congestion_feedback);
45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTag QuicConfig::congestion_feedback() const {
45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return congestion_feedback_.GetTag();
45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
46046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void QuicConfig::SetCongestionOptionsToSend(
46146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const QuicTagVector& congestion_options) {
46246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_options_.SetSendValues(congestion_options);
46346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
46446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
46546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool QuicConfig::HasReceivedCongestionOptions() const {
46646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return congestion_options_.HasReceivedValues();
46746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
46846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)QuicTagVector QuicConfig::ReceivedCongestionOptions() const {
47046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return congestion_options_.GetReceivedValues();
47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
4740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  loss_detection_.SetSendValue(loss_detection);
475e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
476e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
4770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedLossDetection() const {
4780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return loss_detection_.HasReceivedValue();
4790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4810529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicTag QuicConfig::ReceivedLossDetection() const {
4820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return loss_detection_.GetReceivedValue();
483e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
484e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::set_idle_connection_state_lifetime(
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    QuicTime::Delta max_idle_connection_state_lifetime,
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    QuicTime::Delta default_idle_conection_state_lifetime) {
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  idle_connection_state_lifetime_seconds_.set(
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      max_idle_connection_state_lifetime.ToSeconds(),
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      default_idle_conection_state_lifetime.ToSeconds());
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QuicTime::Delta::FromSeconds(
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      idle_connection_state_lifetime_seconds_.GetUint32());
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicTime::Delta QuicConfig::keepalive_timeout() const {
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return QuicTime::Delta::FromSeconds(
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      keepalive_timeout_seconds_.GetUint32());
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::set_max_streams_per_connection(size_t max_streams,
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                size_t default_streams) {
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_streams_per_connection_.set(max_streams, default_streams);
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)uint32 QuicConfig::max_streams_per_connection() const {
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return max_streams_per_connection_.GetUint32();
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void QuicConfig::set_max_time_before_crypto_handshake(
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    QuicTime::Delta max_time_before_crypto_handshake) {
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return max_time_before_crypto_handshake_;
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
5220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_congestion_window_.SetSendValue(initial_window);
5230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedInitialCongestionWindow() const {
5260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_congestion_window_.HasReceivedValue();
5270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicConfig::ReceivedInitialCongestionWindow() const {
5300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_congestion_window_.GetReceivedValue();
5310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
5320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
5340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_round_trip_time_us_.SetSendValue(rtt);
5350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_round_trip_time_us_.HasReceivedValue();
5390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
5420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_round_trip_time_us_.GetReceivedValue();
5430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes) {
546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (window_bytes < kDefaultFlowControlSendWindow) {
547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(DFATAL) << "Initial flow control receive window (" << window_bytes
548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                << ") cannot be set lower than default ("
549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                << kDefaultFlowControlSendWindow << ").";
550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    window_bytes = kDefaultFlowControlSendWindow;
551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
5520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_flow_control_window_bytes_.SetSendValue(window_bytes);
5530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return initial_flow_control_window_bytes_.GetSendValue();
557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return initial_flow_control_window_bytes_.HasReceivedValue();
561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochuint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
5640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return initial_flow_control_window_bytes_.GetReceivedValue();
565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
5686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (window_bytes < kDefaultFlowControlSendWindow) {
5696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    LOG(DFATAL) << "Initial stream flow control receive window ("
5706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << window_bytes << ") cannot be set lower than default ("
5716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << kDefaultFlowControlSendWindow << ").";
5726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    window_bytes = kDefaultFlowControlSendWindow;
5736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
5746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
5756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
5786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_stream_flow_control_window_bytes_.GetSendValue();
5796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
5826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_stream_flow_control_window_bytes_.HasReceivedValue();
5836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
5866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_stream_flow_control_window_bytes_.GetReceivedValue();
5876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
5906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (window_bytes < kDefaultFlowControlSendWindow) {
5916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    LOG(DFATAL) << "Initial session flow control receive window ("
5926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << window_bytes << ") cannot be set lower than default ("
5936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                << kDefaultFlowControlSendWindow << ").";
5946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    window_bytes = kDefaultFlowControlSendWindow;
5956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
5966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
5976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
5986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
6006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_session_flow_control_window_bytes_.GetSendValue();
6016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
6046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_session_flow_control_window_bytes_.HasReceivedValue();
6056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
6086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return initial_session_flow_control_window_bytes_.GetReceivedValue();
6096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
6106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool QuicConfig::negotiated() {
6120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // TODO(ianswett): Add the negotiated parameters once and iterate over all
6130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
6140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // ProcessServerHello.
61546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return congestion_feedback_.negotiated() &&
61690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      idle_connection_state_lifetime_seconds_.negotiated() &&
61790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      keepalive_timeout_seconds_.negotiated() &&
6180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      max_streams_per_connection_.negotiated();
61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::SetDefaults() {
62246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicTagVector congestion_feedback;
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (FLAGS_enable_quic_pacing) {
62446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    congestion_feedback.push_back(kPACE);
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
62646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback.push_back(kQBIC);
62746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.set(congestion_feedback, kQBIC);
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              kDefaultInitialTimeoutSecs);
63090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // kKATO is optional. Return 0 if not negotiated.
63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  keepalive_timeout_seconds_.set(0, 0);
63290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  kDefaultMaxStreamsPerConnection);
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      kDefaultMaxTimeForCryptoHandshakeSecs);
636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow);
6386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow);
6396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow);
64090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
64190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
642a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicConfig::EnablePacing(bool enable_pacing) {
64346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  QuicTagVector congestion_feedback;
644a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (enable_pacing) {
64546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    congestion_feedback.push_back(kPACE);
646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
64746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback.push_back(kQBIC);
64846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.set(congestion_feedback, kQBIC);
649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
650a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
65190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
65246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_feedback_.ToHandshakeMessage(out);
65390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
65490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  keepalive_timeout_seconds_.ToHandshakeMessage(out);
65590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  max_streams_per_connection_.ToHandshakeMessage(out);
6560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_congestion_window_.ToHandshakeMessage(out);
6570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  initial_round_trip_time_us_.ToHandshakeMessage(out);
658e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  loss_detection_.ToHandshakeMessage(out);
6590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  initial_flow_control_window_bytes_.ToHandshakeMessage(out);
6606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
6616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
66246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  congestion_options_.ToHandshakeMessage(out);
66390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
66490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6650529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochQuicErrorCode QuicConfig::ProcessPeerHello(
6660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CryptoHandshakeMessage& peer_hello,
6670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    HelloType hello_type,
66890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    string* error_details) {
66990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(error_details != NULL);
67090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
67190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  QuicErrorCode error = QUIC_NO_ERROR;
67290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
67346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    error = congestion_feedback_.ProcessPeerHello(
6740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello,  hello_type, error_details);
67590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
67690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
6780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
67990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
68090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = keepalive_timeout_seconds_.ProcessPeerHello(
6820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
68390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
68490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = max_streams_per_connection_.ProcessPeerHello(
6860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
68790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = initial_congestion_window_.ProcessPeerHello(
6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
6910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
6920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = initial_round_trip_time_us_.ProcessPeerHello(
6940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
6950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
696a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
6970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = initial_flow_control_window_bytes_.ProcessPeerHello(
6980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
699a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
700e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (error == QUIC_NO_ERROR) {
7016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
7026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        peer_hello, hello_type, error_details);
7036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
7046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
7066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        peer_hello, hello_type, error_details);
7076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
7086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (error == QUIC_NO_ERROR) {
7090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error = loss_detection_.ProcessPeerHello(
7100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        peer_hello, hello_type, error_details);
711e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
71246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (error == QUIC_NO_ERROR) {
71346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    error = congestion_options_.ProcessPeerHello(
71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        peer_hello, hello_type, error_details);
71546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
71690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return error;
71790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
71890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
720