• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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|.
ReadUint32(const CryptoHandshakeMessage & msg,QuicTag tag,QuicConfigPresence presence,uint32 default_value,uint32 * out,string * error_details)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 
QuicConfigValue(QuicTag tag,QuicConfigPresence presence)51 QuicConfigValue::QuicConfigValue(QuicTag tag,
52                                  QuicConfigPresence presence)
53     : tag_(tag),
54       presence_(presence) {
55 }
~QuicConfigValue()56 QuicConfigValue::~QuicConfigValue() {}
57 
QuicNegotiableValue(QuicTag tag,QuicConfigPresence presence)58 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
59                                          QuicConfigPresence presence)
60     : QuicConfigValue(tag, presence),
61       negotiated_(false) {
62 }
~QuicNegotiableValue()63 QuicNegotiableValue::~QuicNegotiableValue() {}
64 
QuicNegotiableUint32(QuicTag tag,QuicConfigPresence presence)65 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
66                                            QuicConfigPresence presence)
67     : QuicNegotiableValue(tag, presence),
68       max_value_(0),
69       default_value_(0) {
70 }
~QuicNegotiableUint32()71 QuicNegotiableUint32::~QuicNegotiableUint32() {}
72 
set(uint32 max,uint32 default_value)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 
GetUint32() const79 uint32 QuicNegotiableUint32::GetUint32() const {
80   if (negotiated_) {
81     return negotiated_value_;
82   }
83   return default_value_;
84 }
85 
ToHandshakeMessage(CryptoHandshakeMessage * out) const86 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 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicNegotiableTag(QuicTag tag,QuicConfigPresence presence)122 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
123     : QuicNegotiableValue(tag, presence),
124       negotiated_tag_(0),
125       default_value_(0) {
126 }
127 
~QuicNegotiableTag()128 QuicNegotiableTag::~QuicNegotiableTag() {}
129 
set(const QuicTagVector & possible,QuicTag default_value)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 
GetTag() const137 QuicTag QuicNegotiableTag::GetTag() const {
138   if (negotiated_) {
139     return negotiated_tag_;
140   }
141   return default_value_;
142 }
143 
ToHandshakeMessage(CryptoHandshakeMessage * out) const144 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 
ReadVector(const CryptoHandshakeMessage & msg,const QuicTag ** out,size_t * out_length,string * error_details) const154 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 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicFixedUint32(QuicTag tag,QuicConfigPresence presence)219 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
220     : QuicConfigValue(tag, presence),
221       has_send_value_(false),
222       has_receive_value_(false) {
223 }
~QuicFixedUint32()224 QuicFixedUint32::~QuicFixedUint32() {}
225 
HasSendValue() const226 bool QuicFixedUint32::HasSendValue() const {
227   return has_send_value_;
228 }
229 
GetSendValue() const230 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 
SetSendValue(uint32 value)236 void QuicFixedUint32::SetSendValue(uint32 value) {
237   has_send_value_ = true;
238   send_value_ = value;
239 }
240 
HasReceivedValue() const241 bool QuicFixedUint32::HasReceivedValue() const {
242   return has_receive_value_;
243 }
244 
GetReceivedValue() const245 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 
SetReceivedValue(uint32 value)251 void QuicFixedUint32::SetReceivedValue(uint32 value) {
252   has_receive_value_ = true;
253   receive_value_ = value;
254 }
255 
ToHandshakeMessage(CryptoHandshakeMessage * out) const256 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
257   if (has_send_value_) {
258     out->SetValue(tag_, send_value_);
259   }
260 }
261 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicFixedTag(QuicTag name,QuicConfigPresence presence)285 QuicFixedTag::QuicFixedTag(QuicTag name,
286                            QuicConfigPresence presence)
287     : QuicConfigValue(name, presence),
288       has_send_value_(false),
289       has_receive_value_(false) {
290 }
291 
~QuicFixedTag()292 QuicFixedTag::~QuicFixedTag() {}
293 
HasSendValue() const294 bool QuicFixedTag::HasSendValue() const {
295   return has_send_value_;
296 }
297 
GetSendValue() const298 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 
SetSendValue(uint32 value)304 void QuicFixedTag::SetSendValue(uint32 value) {
305   has_send_value_ = true;
306   send_value_ = value;
307 }
308 
HasReceivedValue() const309 bool QuicFixedTag::HasReceivedValue() const {
310   return has_receive_value_;
311 }
312 
GetReceivedValue() const313 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 
SetReceivedValue(uint32 value)319 void QuicFixedTag::SetReceivedValue(uint32 value) {
320   has_receive_value_ = true;
321   receive_value_ = value;
322 }
323 
ToHandshakeMessage(CryptoHandshakeMessage * out) const324 void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
325   if (has_send_value_) {
326     out->SetValue(tag_, send_value_);
327   }
328 }
329 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicFixedTagVector(QuicTag name,QuicConfigPresence presence)353 QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
354                                        QuicConfigPresence presence)
355     : QuicConfigValue(name, presence),
356       has_send_values_(false),
357       has_receive_values_(false) {
358 }
359 
~QuicFixedTagVector()360 QuicFixedTagVector::~QuicFixedTagVector() {}
361 
HasSendValues() const362 bool QuicFixedTagVector::HasSendValues() const {
363   return has_send_values_;
364 }
365 
GetSendValues() const366 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 
SetSendValues(const QuicTagVector & values)372 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
373   has_send_values_ = true;
374   send_values_ = values;
375 }
376 
HasReceivedValues() const377 bool QuicFixedTagVector::HasReceivedValues() const {
378   return has_receive_values_;
379 }
380 
GetReceivedValues() const381 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 
SetReceivedValues(const QuicTagVector & values)387 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
388   has_receive_values_ = true;
389   receive_values_ = values;
390 }
391 
ToHandshakeMessage(CryptoHandshakeMessage * out) const392 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
393   if (has_send_values_) {
394     out->SetVector(tag_, send_values_);
395   }
396 }
397 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicConfig()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 
~QuicConfig()448 QuicConfig::~QuicConfig() {}
449 
set_congestion_feedback(const QuicTagVector & congestion_feedback,QuicTag default_congestion_feedback)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 
congestion_feedback() const456 QuicTag QuicConfig::congestion_feedback() const {
457   return congestion_feedback_.GetTag();
458 }
459 
SetCongestionOptionsToSend(const QuicTagVector & congestion_options)460 void QuicConfig::SetCongestionOptionsToSend(
461     const QuicTagVector& congestion_options) {
462   congestion_options_.SetSendValues(congestion_options);
463 }
464 
HasReceivedCongestionOptions() const465 bool QuicConfig::HasReceivedCongestionOptions() const {
466   return congestion_options_.HasReceivedValues();
467 }
468 
ReceivedCongestionOptions() const469 QuicTagVector QuicConfig::ReceivedCongestionOptions() const {
470   return congestion_options_.GetReceivedValues();
471 }
472 
SetLossDetectionToSend(QuicTag loss_detection)473 void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
474   loss_detection_.SetSendValue(loss_detection);
475 }
476 
HasReceivedLossDetection() const477 bool QuicConfig::HasReceivedLossDetection() const {
478   return loss_detection_.HasReceivedValue();
479 }
480 
ReceivedLossDetection() const481 QuicTag QuicConfig::ReceivedLossDetection() const {
482   return loss_detection_.GetReceivedValue();
483 }
484 
set_idle_connection_state_lifetime(QuicTime::Delta max_idle_connection_state_lifetime,QuicTime::Delta default_idle_conection_state_lifetime)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 
idle_connection_state_lifetime() const493 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
494   return QuicTime::Delta::FromSeconds(
495       idle_connection_state_lifetime_seconds_.GetUint32());
496 }
497 
keepalive_timeout() const498 QuicTime::Delta QuicConfig::keepalive_timeout() const {
499   return QuicTime::Delta::FromSeconds(
500       keepalive_timeout_seconds_.GetUint32());
501 }
502 
set_max_streams_per_connection(size_t max_streams,size_t default_streams)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 
max_streams_per_connection() const508 uint32 QuicConfig::max_streams_per_connection() const {
509   return max_streams_per_connection_.GetUint32();
510 }
511 
set_max_time_before_crypto_handshake(QuicTime::Delta max_time_before_crypto_handshake)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 
max_time_before_crypto_handshake() const517 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
518   return max_time_before_crypto_handshake_;
519 }
520 
SetInitialCongestionWindowToSend(size_t initial_window)521 void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
522   initial_congestion_window_.SetSendValue(initial_window);
523 }
524 
HasReceivedInitialCongestionWindow() const525 bool QuicConfig::HasReceivedInitialCongestionWindow() const {
526   return initial_congestion_window_.HasReceivedValue();
527 }
528 
ReceivedInitialCongestionWindow() const529 uint32 QuicConfig::ReceivedInitialCongestionWindow() const {
530   return initial_congestion_window_.GetReceivedValue();
531 }
532 
SetInitialRoundTripTimeUsToSend(size_t rtt)533 void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
534   initial_round_trip_time_us_.SetSendValue(rtt);
535 }
536 
HasReceivedInitialRoundTripTimeUs() const537 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
538   return initial_round_trip_time_us_.HasReceivedValue();
539 }
540 
ReceivedInitialRoundTripTimeUs() const541 uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
542   return initial_round_trip_time_us_.GetReceivedValue();
543 }
544 
SetInitialFlowControlWindowToSend(uint32 window_bytes)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 
GetInitialFlowControlWindowToSend() const555 uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
556   return initial_flow_control_window_bytes_.GetSendValue();
557 }
558 
HasReceivedInitialFlowControlWindowBytes() const559 bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
560   return initial_flow_control_window_bytes_.HasReceivedValue();
561 }
562 
ReceivedInitialFlowControlWindowBytes() const563 uint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
564   return initial_flow_control_window_bytes_.GetReceivedValue();
565 }
566 
SetInitialStreamFlowControlWindowToSend(uint32 window_bytes)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 
GetInitialStreamFlowControlWindowToSend() const577 uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
578   return initial_stream_flow_control_window_bytes_.GetSendValue();
579 }
580 
HasReceivedInitialStreamFlowControlWindowBytes() const581 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
582   return initial_stream_flow_control_window_bytes_.HasReceivedValue();
583 }
584 
ReceivedInitialStreamFlowControlWindowBytes() const585 uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
586   return initial_stream_flow_control_window_bytes_.GetReceivedValue();
587 }
588 
SetInitialSessionFlowControlWindowToSend(uint32 window_bytes)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 
GetInitialSessionFlowControlWindowToSend() const599 uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
600   return initial_session_flow_control_window_bytes_.GetSendValue();
601 }
602 
HasReceivedInitialSessionFlowControlWindowBytes() const603 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
604   return initial_session_flow_control_window_bytes_.HasReceivedValue();
605 }
606 
ReceivedInitialSessionFlowControlWindowBytes() const607 uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
608   return initial_session_flow_control_window_bytes_.GetReceivedValue();
609 }
610 
negotiated()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 
SetDefaults()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 
EnablePacing(bool enable_pacing)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 
ToHandshakeMessage(CryptoHandshakeMessage * out) const651 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 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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