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