Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/quic_config.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/logging.h"
     10 #include "net/quic/crypto/crypto_handshake_message.h"
     11 #include "net/quic/crypto/crypto_protocol.h"
     12 #include "net/quic/quic_flags.h"
     13 #include "net/quic/quic_utils.h"
     14 
     15 using std::min;
     16 using std::string;
     17 
     18 namespace net {
     19 
     20 // Reads the value corresponding to |name_| from |msg| into |out|. If the
     21 // |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
     22 // to |default_value|.
     23 QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
     24                          QuicTag tag,
     25                          QuicConfigPresence presence,
     26                          uint32 default_value,
     27                          uint32* out,
     28                          string* error_details) {
     29   DCHECK(error_details != NULL);
     30   QuicErrorCode error = msg.GetUint32(tag, out);
     31   switch (error) {
     32     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
     33       if (presence == PRESENCE_REQUIRED) {
     34         *error_details = "Missing " + QuicUtils::TagToString(tag);
     35         break;
     36       }
     37       error = QUIC_NO_ERROR;
     38       *out = default_value;
     39       break;
     40     case QUIC_NO_ERROR:
     41       break;
     42     default:
     43       *error_details = "Bad " + QuicUtils::TagToString(tag);
     44       break;
     45   }
     46   return error;
     47 }
     48 
     49 
     50 QuicConfigValue::QuicConfigValue(QuicTag tag,
     51                                  QuicConfigPresence presence)
     52     : tag_(tag),
     53       presence_(presence) {
     54 }
     55 QuicConfigValue::~QuicConfigValue() {}
     56 
     57 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
     58                                          QuicConfigPresence presence)
     59     : QuicConfigValue(tag, presence),
     60       negotiated_(false) {
     61 }
     62 QuicNegotiableValue::~QuicNegotiableValue() {}
     63 
     64 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
     65                                            QuicConfigPresence presence)
     66     : QuicNegotiableValue(tag, presence),
     67       max_value_(0),
     68       default_value_(0) {
     69 }
     70 QuicNegotiableUint32::~QuicNegotiableUint32() {}
     71 
     72 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
     73   DCHECK_LE(default_value, max);
     74   max_value_ = max;
     75   default_value_ = default_value;
     76 }
     77 
     78 uint32 QuicNegotiableUint32::GetUint32() const {
     79   if (negotiated_) {
     80     return negotiated_value_;
     81   }
     82   return default_value_;
     83 }
     84 
     85 void QuicNegotiableUint32::ToHandshakeMessage(
     86     CryptoHandshakeMessage* out) const {
     87   if (negotiated_) {
     88     out->SetValue(tag_, negotiated_value_);
     89   } else {
     90     out->SetValue(tag_, max_value_);
     91   }
     92 }
     93 
     94 QuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
     95     const CryptoHandshakeMessage& peer_hello,
     96     HelloType hello_type,
     97     string* error_details) {
     98   DCHECK(!negotiated_);
     99   DCHECK(error_details != NULL);
    100   uint32 value;
    101   QuicErrorCode error = ReadUint32(peer_hello,
    102                                    tag_,
    103                                    presence_,
    104                                    default_value_,
    105                                    &value,
    106                                    error_details);
    107   if (error != QUIC_NO_ERROR) {
    108     return error;
    109   }
    110   if (hello_type == SERVER && value > max_value_) {
    111     *error_details =
    112         "Invalid value received for " + QuicUtils::TagToString(tag_);
    113     return QUIC_INVALID_NEGOTIATED_VALUE;
    114   }
    115 
    116   negotiated_ = true;
    117   negotiated_value_ = min(value, max_value_);
    118   return QUIC_NO_ERROR;
    119 }
    120 
    121 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
    122     : QuicNegotiableValue(tag, presence),
    123       negotiated_tag_(0),
    124       default_value_(0) {
    125 }
    126 
    127 QuicNegotiableTag::~QuicNegotiableTag() {}
    128 
    129 void QuicNegotiableTag::set(const QuicTagVector& possible,
    130                             QuicTag default_value) {
    131   DCHECK(ContainsQuicTag(possible, default_value));
    132   possible_values_ = possible;
    133   default_value_ = default_value;
    134 }
    135 
    136 QuicTag QuicNegotiableTag::GetTag() const {
    137   if (negotiated_) {
    138     return negotiated_tag_;
    139   }
    140   return default_value_;
    141 }
    142 
    143 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
    144   if (negotiated_) {
    145     // Because of the way we serialize and parse handshake messages we can
    146     // serialize this as value and still parse it as a vector.
    147     out->SetValue(tag_, negotiated_tag_);
    148   } else {
    149     out->SetVector(tag_, possible_values_);
    150   }
    151 }
    152 
    153 QuicErrorCode QuicNegotiableTag::ReadVector(
    154     const CryptoHandshakeMessage& msg,
    155     const QuicTag** out,
    156     size_t* out_length,
    157     string* error_details) const {
    158   DCHECK(error_details != NULL);
    159   QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
    160   switch (error) {
    161     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
    162       if (presence_ == PRESENCE_REQUIRED) {
    163         *error_details = "Missing " + QuicUtils::TagToString(tag_);
    164         break;
    165       }
    166       error = QUIC_NO_ERROR;
    167       *out_length = 1;
    168       *out = &default_value_;
    169 
    170     case QUIC_NO_ERROR:
    171       break;
    172     default:
    173       *error_details = "Bad " + QuicUtils::TagToString(tag_);
    174       break;
    175   }
    176   return error;
    177 }
    178 
    179 QuicErrorCode QuicNegotiableTag::ProcessPeerHello(
    180     const CryptoHandshakeMessage& peer_hello,
    181     HelloType hello_type,
    182     string* error_details) {
    183   DCHECK(!negotiated_);
    184   DCHECK(error_details != NULL);
    185   const QuicTag* received_tags;
    186   size_t received_tags_length;
    187   QuicErrorCode error = ReadVector(peer_hello, &received_tags,
    188                                    &received_tags_length, error_details);
    189   if (error != QUIC_NO_ERROR) {
    190     return error;
    191   }
    192 
    193   if (hello_type == SERVER) {
    194     if (received_tags_length != 1 ||
    195         !ContainsQuicTag(possible_values_,  *received_tags)) {
    196       *error_details = "Invalid " + QuicUtils::TagToString(tag_);
    197       return QUIC_INVALID_NEGOTIATED_VALUE;
    198     }
    199     negotiated_tag_ = *received_tags;
    200   } else {
    201     QuicTag negotiated_tag;
    202     if (!QuicUtils::FindMutualTag(possible_values_,
    203                                   received_tags,
    204                                   received_tags_length,
    205                                   QuicUtils::LOCAL_PRIORITY,
    206                                   &negotiated_tag,
    207                                   NULL)) {
    208       *error_details = "Unsupported " + QuicUtils::TagToString(tag_);
    209       return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
    210     }
    211     negotiated_tag_ = negotiated_tag;
    212   }
    213 
    214   negotiated_ = true;
    215   return QUIC_NO_ERROR;
    216 }
    217 
    218 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
    219     : QuicConfigValue(tag, presence),
    220       has_send_value_(false),
    221       has_receive_value_(false) {
    222 }
    223 QuicFixedUint32::~QuicFixedUint32() {}
    224 
    225 bool QuicFixedUint32::HasSendValue() const {
    226   return has_send_value_;
    227 }
    228 
    229 uint32 QuicFixedUint32::GetSendValue() const {
    230   LOG_IF(DFATAL, !has_send_value_)
    231       << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
    232   return send_value_;
    233 }
    234 
    235 void QuicFixedUint32::SetSendValue(uint32 value) {
    236   has_send_value_ = true;
    237   send_value_ = value;
    238 }
    239 
    240 bool QuicFixedUint32::HasReceivedValue() const {
    241   return has_receive_value_;
    242 }
    243 
    244 uint32 QuicFixedUint32::GetReceivedValue() const {
    245   LOG_IF(DFATAL, !has_receive_value_)
    246       << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
    247   return receive_value_;
    248 }
    249 
    250 void QuicFixedUint32::SetReceivedValue(uint32 value) {
    251   has_receive_value_ = true;
    252   receive_value_ = value;
    253 }
    254 
    255 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
    256   if (has_send_value_) {
    257     out->SetValue(tag_, send_value_);
    258   }
    259 }
    260 
    261 QuicErrorCode QuicFixedUint32::ProcessPeerHello(
    262     const CryptoHandshakeMessage& peer_hello,
    263     HelloType hello_type,
    264     string* error_details) {
    265   DCHECK(error_details != NULL);
    266   QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
    267   switch (error) {
    268     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
    269       if (presence_ == PRESENCE_OPTIONAL) {
    270         return QUIC_NO_ERROR;
    271       }
    272       *error_details = "Missing " + QuicUtils::TagToString(tag_);
    273       break;
    274     case QUIC_NO_ERROR:
    275       has_receive_value_ = true;
    276       break;
    277     default:
    278       *error_details = "Bad " + QuicUtils::TagToString(tag_);
    279       break;
    280   }
    281   return error;
    282 }
    283 
    284 QuicFixedTag::QuicFixedTag(QuicTag name,
    285                            QuicConfigPresence presence)
    286     : QuicConfigValue(name, presence),
    287       has_send_value_(false),
    288       has_receive_value_(false) {
    289 }
    290 
    291 QuicFixedTag::~QuicFixedTag() {}
    292 
    293 bool QuicFixedTag::HasSendValue() const {
    294   return has_send_value_;
    295 }
    296 
    297 uint32 QuicFixedTag::GetSendValue() const {
    298   LOG_IF(DFATAL, !has_send_value_)
    299       << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
    300   return send_value_;
    301 }
    302 
    303 void QuicFixedTag::SetSendValue(uint32 value) {
    304   has_send_value_ = true;
    305   send_value_ = value;
    306 }
    307 
    308 bool QuicFixedTag::HasReceivedValue() const {
    309   return has_receive_value_;
    310 }
    311 
    312 uint32 QuicFixedTag::GetReceivedValue() const {
    313   LOG_IF(DFATAL, !has_receive_value_)
    314       << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
    315   return receive_value_;
    316 }
    317 
    318 void QuicFixedTag::SetReceivedValue(uint32 value) {
    319   has_receive_value_ = true;
    320   receive_value_ = value;
    321 }
    322 
    323 void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
    324   if (has_send_value_) {
    325     out->SetValue(tag_, send_value_);
    326   }
    327 }
    328 
    329 QuicErrorCode QuicFixedTag::ProcessPeerHello(
    330     const CryptoHandshakeMessage& peer_hello,
    331     HelloType hello_type,
    332     string* error_details) {
    333   DCHECK(error_details != NULL);
    334   QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
    335   switch (error) {
    336     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
    337       if (presence_ == PRESENCE_OPTIONAL) {
    338         return QUIC_NO_ERROR;
    339       }
    340       *error_details = "Missing " + QuicUtils::TagToString(tag_);
    341       break;
    342     case QUIC_NO_ERROR:
    343       has_receive_value_ = true;
    344       break;
    345     default:
    346       *error_details = "Bad " + QuicUtils::TagToString(tag_);
    347       break;
    348   }
    349   return error;
    350 }
    351 
    352 QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
    353                                        QuicConfigPresence presence)
    354     : QuicConfigValue(name, presence),
    355       has_send_values_(false),
    356       has_receive_values_(false) {
    357 }
    358 
    359 QuicFixedTagVector::~QuicFixedTagVector() {}
    360 
    361 bool QuicFixedTagVector::HasSendValues() const {
    362   return has_send_values_;
    363 }
    364 
    365 QuicTagVector QuicFixedTagVector::GetSendValues() const {
    366   LOG_IF(DFATAL, !has_send_values_)
    367       << "No send values to get for tag:" << QuicUtils::TagToString(tag_);
    368   return send_values_;
    369 }
    370 
    371 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
    372   has_send_values_ = true;
    373   send_values_ = values;
    374 }
    375 
    376 bool QuicFixedTagVector::HasReceivedValues() const {
    377   return has_receive_values_;
    378 }
    379 
    380 QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
    381   LOG_IF(DFATAL, !has_receive_values_)
    382       << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
    383   return receive_values_;
    384 }
    385 
    386 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
    387   has_receive_values_ = true;
    388   receive_values_ = values;
    389 }
    390 
    391 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
    392   if (has_send_values_) {
    393     out->SetVector(tag_, send_values_);
    394   }
    395 }
    396 
    397 QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
    398     const CryptoHandshakeMessage& peer_hello,
    399     HelloType hello_type,
    400     string* error_details) {
    401   DCHECK(error_details != NULL);
    402   const QuicTag* received_tags;
    403   size_t received_tags_length;
    404   QuicErrorCode error =
    405       peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
    406   switch (error) {
    407     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
    408       if (presence_ == PRESENCE_OPTIONAL) {
    409         return QUIC_NO_ERROR;
    410       }
    411       *error_details = "Missing " + QuicUtils::TagToString(tag_);
    412       break;
    413     case QUIC_NO_ERROR:
    414       DVLOG(1) << "Received Connection Option tags from receiver.";
    415       has_receive_values_ = true;
    416       for (size_t i = 0; i < received_tags_length; ++i) {
    417         receive_values_.push_back(received_tags[i]);
    418       }
    419       break;
    420     default:
    421       *error_details = "Bad " + QuicUtils::TagToString(tag_);
    422       break;
    423   }
    424   return error;
    425 }
    426 
    427 QuicConfig::QuicConfig()
    428     : congestion_feedback_(kCGST, PRESENCE_REQUIRED),
    429       connection_options_(kCOPT, PRESENCE_OPTIONAL),
    430       loss_detection_(kLOSS, PRESENCE_OPTIONAL),
    431       idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
    432       keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL),
    433       max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED),
    434       max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
    435       initial_congestion_window_(kSWND, PRESENCE_OPTIONAL),
    436       initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
    437       // TODO(rjshade): Make this PRESENCE_REQUIRED when QUIC_VERSION_16 is
    438       // retired.
    439       initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL),
    440       // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
    441       // QUIC_VERSION_19.
    442       initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
    443       // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
    444       // QUIC_VERSION_19.
    445       initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
    446       socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL) {
    447 }
    448 
    449 QuicConfig::~QuicConfig() {}
    450 
    451 void QuicConfig::set_congestion_feedback(
    452     const QuicTagVector& congestion_feedback,
    453     QuicTag default_congestion_feedback) {
    454   congestion_feedback_.set(congestion_feedback, default_congestion_feedback);
    455 }
    456 
    457 QuicTag QuicConfig::congestion_feedback() const {
    458   return congestion_feedback_.GetTag();
    459 }
    460 
    461 void QuicConfig::SetConnectionOptionsToSend(
    462     const QuicTagVector& connection_options) {
    463   connection_options_.SetSendValues(connection_options);
    464 }
    465 
    466 bool QuicConfig::HasReceivedConnectionOptions() const {
    467   return connection_options_.HasReceivedValues();
    468 }
    469 
    470 QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
    471   return connection_options_.GetReceivedValues();
    472 }
    473 
    474 bool QuicConfig::HasSendConnectionOptions() const {
    475   return connection_options_.HasSendValues();
    476 }
    477 
    478 QuicTagVector QuicConfig::SendConnectionOptions() const {
    479   return connection_options_.GetSendValues();
    480 }
    481 
    482 void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
    483   loss_detection_.SetSendValue(loss_detection);
    484 }
    485 
    486 bool QuicConfig::HasReceivedLossDetection() const {
    487   return loss_detection_.HasReceivedValue();
    488 }
    489 
    490 QuicTag QuicConfig::ReceivedLossDetection() const {
    491   return loss_detection_.GetReceivedValue();
    492 }
    493 
    494 void QuicConfig::set_idle_connection_state_lifetime(
    495     QuicTime::Delta max_idle_connection_state_lifetime,
    496     QuicTime::Delta default_idle_conection_state_lifetime) {
    497   idle_connection_state_lifetime_seconds_.set(
    498       max_idle_connection_state_lifetime.ToSeconds(),
    499       default_idle_conection_state_lifetime.ToSeconds());
    500 }
    501 
    502 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
    503   return QuicTime::Delta::FromSeconds(
    504       idle_connection_state_lifetime_seconds_.GetUint32());
    505 }
    506 
    507 QuicTime::Delta QuicConfig::keepalive_timeout() const {
    508   return QuicTime::Delta::FromSeconds(
    509       keepalive_timeout_seconds_.GetUint32());
    510 }
    511 
    512 void QuicConfig::set_max_streams_per_connection(size_t max_streams,
    513                                                 size_t default_streams) {
    514   max_streams_per_connection_.set(max_streams, default_streams);
    515 }
    516 
    517 uint32 QuicConfig::max_streams_per_connection() const {
    518   return max_streams_per_connection_.GetUint32();
    519 }
    520 
    521 void QuicConfig::set_max_time_before_crypto_handshake(
    522     QuicTime::Delta max_time_before_crypto_handshake) {
    523   max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
    524 }
    525 
    526 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
    527   return max_time_before_crypto_handshake_;
    528 }
    529 
    530 void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
    531   initial_congestion_window_.SetSendValue(initial_window);
    532 }
    533 
    534 bool QuicConfig::HasReceivedInitialCongestionWindow() const {
    535   return initial_congestion_window_.HasReceivedValue();
    536 }
    537 
    538 uint32 QuicConfig::ReceivedInitialCongestionWindow() const {
    539   return initial_congestion_window_.GetReceivedValue();
    540 }
    541 
    542 void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
    543   initial_round_trip_time_us_.SetSendValue(rtt);
    544 }
    545 
    546 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
    547   return initial_round_trip_time_us_.HasReceivedValue();
    548 }
    549 
    550 uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
    551   return initial_round_trip_time_us_.GetReceivedValue();
    552 }
    553 
    554 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
    555   return initial_round_trip_time_us_.HasSendValue();
    556 }
    557 
    558 uint32 QuicConfig::GetInitialRoundTripTimeUsToSend() const {
    559   return initial_round_trip_time_us_.GetSendValue();
    560 }
    561 
    562 void QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes) {
    563   if (window_bytes < kDefaultFlowControlSendWindow) {
    564     LOG(DFATAL) << "Initial flow control receive window (" << window_bytes
    565                 << ") cannot be set lower than default ("
    566                 << kDefaultFlowControlSendWindow << ").";
    567     window_bytes = kDefaultFlowControlSendWindow;
    568   }
    569   initial_flow_control_window_bytes_.SetSendValue(window_bytes);
    570 }
    571 
    572 uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
    573   return initial_flow_control_window_bytes_.GetSendValue();
    574 }
    575 
    576 bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
    577   return initial_flow_control_window_bytes_.HasReceivedValue();
    578 }
    579 
    580 uint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
    581   return initial_flow_control_window_bytes_.GetReceivedValue();
    582 }
    583 
    584 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
    585   if (window_bytes < kDefaultFlowControlSendWindow) {
    586     LOG(DFATAL) << "Initial stream flow control receive window ("
    587                 << window_bytes << ") cannot be set lower than default ("
    588                 << kDefaultFlowControlSendWindow << ").";
    589     window_bytes = kDefaultFlowControlSendWindow;
    590   }
    591   initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
    592 }
    593 
    594 uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
    595   return initial_stream_flow_control_window_bytes_.GetSendValue();
    596 }
    597 
    598 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
    599   return initial_stream_flow_control_window_bytes_.HasReceivedValue();
    600 }
    601 
    602 uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
    603   return initial_stream_flow_control_window_bytes_.GetReceivedValue();
    604 }
    605 
    606 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
    607   if (window_bytes < kDefaultFlowControlSendWindow) {
    608     LOG(DFATAL) << "Initial session flow control receive window ("
    609                 << window_bytes << ") cannot be set lower than default ("
    610                 << kDefaultFlowControlSendWindow << ").";
    611     window_bytes = kDefaultFlowControlSendWindow;
    612   }
    613   initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
    614 }
    615 
    616 uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
    617   return initial_session_flow_control_window_bytes_.GetSendValue();
    618 }
    619 
    620 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
    621   return initial_session_flow_control_window_bytes_.HasReceivedValue();
    622 }
    623 
    624 uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
    625   return initial_session_flow_control_window_bytes_.GetReceivedValue();
    626 }
    627 
    628 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window) {
    629   socket_receive_buffer_.SetSendValue(tcp_receive_window);
    630 }
    631 
    632 uint32 QuicConfig::GetSocketReceiveBufferToSend() const {
    633   return socket_receive_buffer_.GetSendValue();
    634 }
    635 
    636 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
    637   return socket_receive_buffer_.HasReceivedValue();
    638 }
    639 
    640 uint32 QuicConfig::ReceivedSocketReceiveBuffer() const {
    641   return socket_receive_buffer_.GetReceivedValue();
    642 }
    643 
    644 bool QuicConfig::negotiated() {
    645   // TODO(ianswett): Add the negotiated parameters once and iterate over all
    646   // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
    647   // ProcessServerHello.
    648   return congestion_feedback_.negotiated() &&
    649       idle_connection_state_lifetime_seconds_.negotiated() &&
    650       keepalive_timeout_seconds_.negotiated() &&
    651       max_streams_per_connection_.negotiated();
    652 }
    653 
    654 void QuicConfig::SetDefaults() {
    655   QuicTagVector congestion_feedback;
    656   congestion_feedback.push_back(kQBIC);
    657   congestion_feedback_.set(congestion_feedback, kQBIC);
    658   idle_connection_state_lifetime_seconds_.set(kMaximumIdleTimeoutSecs,
    659                                               kDefaultInitialTimeoutSecs);
    660   // kKATO is optional. Return 0 if not negotiated.
    661   keepalive_timeout_seconds_.set(0, 0);
    662   set_max_streams_per_connection(kDefaultMaxStreamsPerConnection,
    663                                  kDefaultMaxStreamsPerConnection);
    664   max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
    665       kDefaultMaxTimeForCryptoHandshakeSecs);
    666 
    667   SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow);
    668   SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow);
    669   SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow);
    670 }
    671 
    672 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
    673   congestion_feedback_.ToHandshakeMessage(out);
    674   idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
    675   keepalive_timeout_seconds_.ToHandshakeMessage(out);
    676   max_streams_per_connection_.ToHandshakeMessage(out);
    677   initial_congestion_window_.ToHandshakeMessage(out);
    678   initial_round_trip_time_us_.ToHandshakeMessage(out);
    679   loss_detection_.ToHandshakeMessage(out);
    680   initial_flow_control_window_bytes_.ToHandshakeMessage(out);
    681   initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
    682   initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
    683   socket_receive_buffer_.ToHandshakeMessage(out);
    684   connection_options_.ToHandshakeMessage(out);
    685 }
    686 
    687 QuicErrorCode QuicConfig::ProcessPeerHello(
    688     const CryptoHandshakeMessage& peer_hello,
    689     HelloType hello_type,
    690     string* error_details) {
    691   DCHECK(error_details != NULL);
    692 
    693   QuicErrorCode error = QUIC_NO_ERROR;
    694   if (error == QUIC_NO_ERROR) {
    695     error = congestion_feedback_.ProcessPeerHello(
    696         peer_hello,  hello_type, error_details);
    697   }
    698   if (error == QUIC_NO_ERROR) {
    699     error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
    700         peer_hello, hello_type, error_details);
    701   }
    702   if (error == QUIC_NO_ERROR) {
    703     error = keepalive_timeout_seconds_.ProcessPeerHello(
    704         peer_hello, hello_type, error_details);
    705   }
    706   if (error == QUIC_NO_ERROR) {
    707     error = max_streams_per_connection_.ProcessPeerHello(
    708         peer_hello, hello_type, error_details);
    709   }
    710   if (error == QUIC_NO_ERROR) {
    711     error = initial_congestion_window_.ProcessPeerHello(
    712         peer_hello, hello_type, error_details);
    713   }
    714   if (error == QUIC_NO_ERROR) {
    715     error = initial_round_trip_time_us_.ProcessPeerHello(
    716         peer_hello, hello_type, error_details);
    717   }
    718   if (error == QUIC_NO_ERROR) {
    719     error = initial_flow_control_window_bytes_.ProcessPeerHello(
    720         peer_hello, hello_type, error_details);
    721   }
    722   if (error == QUIC_NO_ERROR) {
    723     error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
    724         peer_hello, hello_type, error_details);
    725   }
    726   if (error == QUIC_NO_ERROR) {
    727     error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
    728         peer_hello, hello_type, error_details);
    729   }
    730   if (error == QUIC_NO_ERROR) {
    731     error = socket_receive_buffer_.ProcessPeerHello(
    732         peer_hello, hello_type, error_details);
    733   }
    734   if (error == QUIC_NO_ERROR) {
    735     error = loss_detection_.ProcessPeerHello(
    736         peer_hello, hello_type, error_details);
    737   }
    738   if (error == QUIC_NO_ERROR) {
    739     error = connection_options_.ProcessPeerHello(
    740         peer_hello, hello_type, error_details);
    741   }
    742   return error;
    743 }
    744 
    745 }  // namespace net
    746