quic_config.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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
16using std::min;
17using std::string;
18
19namespace 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|.
24QuicErrorCode 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
51QuicConfigValue::QuicConfigValue(QuicTag tag,
52                                 QuicConfigPresence presence)
53    : tag_(tag),
54      presence_(presence) {
55}
56QuicConfigValue::~QuicConfigValue() {}
57
58QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
59                                         QuicConfigPresence presence)
60    : QuicConfigValue(tag, presence),
61      negotiated_(false) {
62}
63QuicNegotiableValue::~QuicNegotiableValue() {}
64
65QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
66                                           QuicConfigPresence presence)
67    : QuicNegotiableValue(tag, presence),
68      max_value_(0),
69      default_value_(0) {
70}
71QuicNegotiableUint32::~QuicNegotiableUint32() {}
72
73void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
74  DCHECK_LE(default_value, max);
75  max_value_ = max;
76  default_value_ = default_value;
77}
78
79uint32 QuicNegotiableUint32::GetUint32() const {
80  if (negotiated_) {
81    return negotiated_value_;
82  }
83  return default_value_;
84}
85
86void 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
95QuicErrorCode 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
122QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
123    : QuicNegotiableValue(tag, presence),
124      negotiated_tag_(0),
125      default_value_(0) {
126}
127
128QuicNegotiableTag::~QuicNegotiableTag() {}
129
130void 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
137QuicTag QuicNegotiableTag::GetTag() const {
138  if (negotiated_) {
139    return negotiated_tag_;
140  }
141  return default_value_;
142}
143
144void 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
154QuicErrorCode 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
180QuicErrorCode 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
219QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
220    : QuicConfigValue(tag, presence),
221      has_send_value_(false),
222      has_receive_value_(false) {
223}
224QuicFixedUint32::~QuicFixedUint32() {}
225
226bool QuicFixedUint32::HasSendValue() const {
227  return has_send_value_;
228}
229
230uint32 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
236void QuicFixedUint32::SetSendValue(uint32 value) {
237  has_send_value_ = true;
238  send_value_ = value;
239}
240
241bool QuicFixedUint32::HasReceivedValue() const {
242  return has_receive_value_;
243}
244
245uint32 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
251void QuicFixedUint32::SetReceivedValue(uint32 value) {
252  has_receive_value_ = true;
253  receive_value_ = value;
254}
255
256void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
257  if (has_send_value_) {
258    out->SetValue(tag_, send_value_);
259  }
260}
261
262QuicErrorCode 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
285QuicFixedTag::QuicFixedTag(QuicTag name,
286                           QuicConfigPresence presence)
287    : QuicConfigValue(name, presence),
288      has_send_value_(false),
289      has_receive_value_(false) {
290}
291
292QuicFixedTag::~QuicFixedTag() {}
293
294bool QuicFixedTag::HasSendValue() const {
295  return has_send_value_;
296}
297
298uint32 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
304void QuicFixedTag::SetSendValue(uint32 value) {
305  has_send_value_ = true;
306  send_value_ = value;
307}
308
309bool QuicFixedTag::HasReceivedValue() const {
310  return has_receive_value_;
311}
312
313uint32 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
319void QuicFixedTag::SetReceivedValue(uint32 value) {
320  has_receive_value_ = true;
321  receive_value_ = value;
322}
323
324void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
325  if (has_send_value_) {
326    out->SetValue(tag_, send_value_);
327  }
328}
329
330QuicErrorCode 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
353QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
354                                       QuicConfigPresence presence)
355    : QuicConfigValue(name, presence),
356      has_send_values_(false),
357      has_receive_values_(false) {
358}
359
360QuicFixedTagVector::~QuicFixedTagVector() {}
361
362bool QuicFixedTagVector::HasSendValues() const {
363  return has_send_values_;
364}
365
366QuicTagVector 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
372void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
373  has_send_values_ = true;
374  send_values_ = values;
375}
376
377bool QuicFixedTagVector::HasReceivedValues() const {
378  return has_receive_values_;
379}
380
381QuicTagVector 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
387void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
388  has_receive_values_ = true;
389  receive_values_ = values;
390}
391
392void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
393  if (has_send_values_) {
394    out->SetVector(tag_, send_values_);
395  }
396}
397
398QuicErrorCode 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      DVLOG(1) << "Received Connection Option tags from receiver.";
416      has_receive_values_ = true;
417      for (size_t i = 0; i < received_tags_length; ++i) {
418        receive_values_.push_back(received_tags[i]);
419      }
420      break;
421    default:
422      *error_details = "Bad " + QuicUtils::TagToString(tag_);
423      break;
424  }
425  return error;
426}
427
428QuicConfig::QuicConfig()
429    : congestion_feedback_(kCGST, PRESENCE_REQUIRED),
430      connection_options_(kCOPT, PRESENCE_OPTIONAL),
431      loss_detection_(kLOSS, PRESENCE_OPTIONAL),
432      idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
433      keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL),
434      max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED),
435      max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
436      initial_congestion_window_(kSWND, PRESENCE_OPTIONAL),
437      initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
438      // TODO(rjshade): Make this PRESENCE_REQUIRED when QUIC_VERSION_16 is
439      // retired.
440      initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL),
441      // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
442      // QUIC_VERSION_19.
443      initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
444      // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
445      // QUIC_VERSION_19.
446      initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL) {
447}
448
449QuicConfig::~QuicConfig() {}
450
451void 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
457QuicTag QuicConfig::congestion_feedback() const {
458  return congestion_feedback_.GetTag();
459}
460
461void QuicConfig::SetConnectionOptionsToSend(
462    const QuicTagVector& connection_options) {
463  connection_options_.SetSendValues(connection_options);
464}
465
466bool QuicConfig::HasReceivedConnectionOptions() const {
467  return connection_options_.HasReceivedValues();
468}
469
470QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
471  return connection_options_.GetReceivedValues();
472}
473
474bool QuicConfig::HasSendConnectionOptions() const {
475  return connection_options_.HasSendValues();
476}
477
478QuicTagVector QuicConfig::SendConnectionOptions() const {
479  return connection_options_.GetSendValues();
480}
481
482void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
483  loss_detection_.SetSendValue(loss_detection);
484}
485
486bool QuicConfig::HasReceivedLossDetection() const {
487  return loss_detection_.HasReceivedValue();
488}
489
490QuicTag QuicConfig::ReceivedLossDetection() const {
491  return loss_detection_.GetReceivedValue();
492}
493
494void 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
502QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
503  return QuicTime::Delta::FromSeconds(
504      idle_connection_state_lifetime_seconds_.GetUint32());
505}
506
507QuicTime::Delta QuicConfig::keepalive_timeout() const {
508  return QuicTime::Delta::FromSeconds(
509      keepalive_timeout_seconds_.GetUint32());
510}
511
512void 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
517uint32 QuicConfig::max_streams_per_connection() const {
518  return max_streams_per_connection_.GetUint32();
519}
520
521void 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
526QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
527  return max_time_before_crypto_handshake_;
528}
529
530void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
531  initial_congestion_window_.SetSendValue(initial_window);
532}
533
534bool QuicConfig::HasReceivedInitialCongestionWindow() const {
535  return initial_congestion_window_.HasReceivedValue();
536}
537
538uint32 QuicConfig::ReceivedInitialCongestionWindow() const {
539  return initial_congestion_window_.GetReceivedValue();
540}
541
542void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
543  initial_round_trip_time_us_.SetSendValue(rtt);
544}
545
546bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
547  return initial_round_trip_time_us_.HasReceivedValue();
548}
549
550uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
551  return initial_round_trip_time_us_.GetReceivedValue();
552}
553
554void QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes) {
555  if (window_bytes < kDefaultFlowControlSendWindow) {
556    LOG(DFATAL) << "Initial flow control receive window (" << window_bytes
557                << ") cannot be set lower than default ("
558                << kDefaultFlowControlSendWindow << ").";
559    window_bytes = kDefaultFlowControlSendWindow;
560  }
561  initial_flow_control_window_bytes_.SetSendValue(window_bytes);
562}
563
564uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
565  return initial_flow_control_window_bytes_.GetSendValue();
566}
567
568bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
569  return initial_flow_control_window_bytes_.HasReceivedValue();
570}
571
572uint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
573  return initial_flow_control_window_bytes_.GetReceivedValue();
574}
575
576void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
577  if (window_bytes < kDefaultFlowControlSendWindow) {
578    LOG(DFATAL) << "Initial stream flow control receive window ("
579                << window_bytes << ") cannot be set lower than default ("
580                << kDefaultFlowControlSendWindow << ").";
581    window_bytes = kDefaultFlowControlSendWindow;
582  }
583  initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
584}
585
586uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
587  return initial_stream_flow_control_window_bytes_.GetSendValue();
588}
589
590bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
591  return initial_stream_flow_control_window_bytes_.HasReceivedValue();
592}
593
594uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
595  return initial_stream_flow_control_window_bytes_.GetReceivedValue();
596}
597
598void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
599  if (window_bytes < kDefaultFlowControlSendWindow) {
600    LOG(DFATAL) << "Initial session flow control receive window ("
601                << window_bytes << ") cannot be set lower than default ("
602                << kDefaultFlowControlSendWindow << ").";
603    window_bytes = kDefaultFlowControlSendWindow;
604  }
605  initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
606}
607
608uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
609  return initial_session_flow_control_window_bytes_.GetSendValue();
610}
611
612bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
613  return initial_session_flow_control_window_bytes_.HasReceivedValue();
614}
615
616uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
617  return initial_session_flow_control_window_bytes_.GetReceivedValue();
618}
619
620bool QuicConfig::negotiated() {
621  // TODO(ianswett): Add the negotiated parameters once and iterate over all
622  // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
623  // ProcessServerHello.
624  return congestion_feedback_.negotiated() &&
625      idle_connection_state_lifetime_seconds_.negotiated() &&
626      keepalive_timeout_seconds_.negotiated() &&
627      max_streams_per_connection_.negotiated();
628}
629
630void QuicConfig::SetDefaults() {
631  QuicTagVector congestion_feedback;
632  if (FLAGS_enable_quic_pacing) {
633    congestion_feedback.push_back(kPACE);
634  }
635  congestion_feedback.push_back(kQBIC);
636  congestion_feedback_.set(congestion_feedback, kQBIC);
637  idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
638                                              kDefaultInitialTimeoutSecs);
639  // kKATO is optional. Return 0 if not negotiated.
640  keepalive_timeout_seconds_.set(0, 0);
641  max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
642                                  kDefaultMaxStreamsPerConnection);
643  max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
644      kDefaultMaxTimeForCryptoHandshakeSecs);
645
646  SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow);
647  SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow);
648  SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow);
649}
650
651void QuicConfig::EnablePacing(bool enable_pacing) {
652  QuicTagVector congestion_feedback;
653  if (enable_pacing) {
654    congestion_feedback.push_back(kPACE);
655  }
656  congestion_feedback.push_back(kQBIC);
657  congestion_feedback_.set(congestion_feedback, kQBIC);
658}
659
660void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
661  congestion_feedback_.ToHandshakeMessage(out);
662  idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
663  keepalive_timeout_seconds_.ToHandshakeMessage(out);
664  max_streams_per_connection_.ToHandshakeMessage(out);
665  initial_congestion_window_.ToHandshakeMessage(out);
666  initial_round_trip_time_us_.ToHandshakeMessage(out);
667  loss_detection_.ToHandshakeMessage(out);
668  initial_flow_control_window_bytes_.ToHandshakeMessage(out);
669  initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
670  initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
671  connection_options_.ToHandshakeMessage(out);
672}
673
674QuicErrorCode QuicConfig::ProcessPeerHello(
675    const CryptoHandshakeMessage& peer_hello,
676    HelloType hello_type,
677    string* error_details) {
678  DCHECK(error_details != NULL);
679
680  QuicErrorCode error = QUIC_NO_ERROR;
681  if (error == QUIC_NO_ERROR) {
682    error = congestion_feedback_.ProcessPeerHello(
683        peer_hello,  hello_type, error_details);
684  }
685  if (error == QUIC_NO_ERROR) {
686    error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
687        peer_hello, hello_type, error_details);
688  }
689  if (error == QUIC_NO_ERROR) {
690    error = keepalive_timeout_seconds_.ProcessPeerHello(
691        peer_hello, hello_type, error_details);
692  }
693  if (error == QUIC_NO_ERROR) {
694    error = max_streams_per_connection_.ProcessPeerHello(
695        peer_hello, hello_type, error_details);
696  }
697  if (error == QUIC_NO_ERROR) {
698    error = initial_congestion_window_.ProcessPeerHello(
699        peer_hello, hello_type, error_details);
700  }
701  if (error == QUIC_NO_ERROR) {
702    error = initial_round_trip_time_us_.ProcessPeerHello(
703        peer_hello, hello_type, error_details);
704  }
705  if (error == QUIC_NO_ERROR) {
706    error = initial_flow_control_window_bytes_.ProcessPeerHello(
707        peer_hello, hello_type, error_details);
708  }
709  if (error == QUIC_NO_ERROR) {
710    error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
711        peer_hello, hello_type, error_details);
712  }
713  if (error == QUIC_NO_ERROR) {
714    error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
715        peer_hello, hello_type, error_details);
716  }
717  if (error == QUIC_NO_ERROR) {
718    error = loss_detection_.ProcessPeerHello(
719        peer_hello, hello_type, error_details);
720  }
721  if (error == QUIC_NO_ERROR) {
722    error = connection_options_.ProcessPeerHello(
723        peer_hello, hello_type, error_details);
724  }
725  return error;
726}
727
728}  // namespace net
729