• 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_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|.
ReadUint32(const CryptoHandshakeMessage & msg,QuicTag tag,QuicConfigPresence presence,uint32 default_value,uint32 * out,string * error_details)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 
QuicConfigValue(QuicTag tag,QuicConfigPresence presence)50 QuicConfigValue::QuicConfigValue(QuicTag tag,
51                                  QuicConfigPresence presence)
52     : tag_(tag),
53       presence_(presence) {
54 }
~QuicConfigValue()55 QuicConfigValue::~QuicConfigValue() {}
56 
QuicNegotiableValue(QuicTag tag,QuicConfigPresence presence)57 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
58                                          QuicConfigPresence presence)
59     : QuicConfigValue(tag, presence),
60       negotiated_(false) {
61 }
~QuicNegotiableValue()62 QuicNegotiableValue::~QuicNegotiableValue() {}
63 
QuicNegotiableUint32(QuicTag tag,QuicConfigPresence presence)64 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
65                                            QuicConfigPresence presence)
66     : QuicNegotiableValue(tag, presence),
67       max_value_(0),
68       default_value_(0) {
69 }
~QuicNegotiableUint32()70 QuicNegotiableUint32::~QuicNegotiableUint32() {}
71 
set(uint32 max,uint32 default_value)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 
GetUint32() const78 uint32 QuicNegotiableUint32::GetUint32() const {
79   if (negotiated_) {
80     return negotiated_value_;
81   }
82   return default_value_;
83 }
84 
ToHandshakeMessage(CryptoHandshakeMessage * out) const85 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 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicNegotiableTag(QuicTag tag,QuicConfigPresence presence)121 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
122     : QuicNegotiableValue(tag, presence),
123       negotiated_tag_(0),
124       default_value_(0) {
125 }
126 
~QuicNegotiableTag()127 QuicNegotiableTag::~QuicNegotiableTag() {}
128 
set(const QuicTagVector & possible,QuicTag default_value)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 
GetTag() const136 QuicTag QuicNegotiableTag::GetTag() const {
137   if (negotiated_) {
138     return negotiated_tag_;
139   }
140   return default_value_;
141 }
142 
ToHandshakeMessage(CryptoHandshakeMessage * out) const143 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 
ReadVector(const CryptoHandshakeMessage & msg,const QuicTag ** out,size_t * out_length,string * error_details) const153 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 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicFixedUint32(QuicTag tag,QuicConfigPresence presence)218 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
219     : QuicConfigValue(tag, presence),
220       has_send_value_(false),
221       has_receive_value_(false) {
222 }
~QuicFixedUint32()223 QuicFixedUint32::~QuicFixedUint32() {}
224 
HasSendValue() const225 bool QuicFixedUint32::HasSendValue() const {
226   return has_send_value_;
227 }
228 
GetSendValue() const229 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 
SetSendValue(uint32 value)235 void QuicFixedUint32::SetSendValue(uint32 value) {
236   has_send_value_ = true;
237   send_value_ = value;
238 }
239 
HasReceivedValue() const240 bool QuicFixedUint32::HasReceivedValue() const {
241   return has_receive_value_;
242 }
243 
GetReceivedValue() const244 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 
SetReceivedValue(uint32 value)250 void QuicFixedUint32::SetReceivedValue(uint32 value) {
251   has_receive_value_ = true;
252   receive_value_ = value;
253 }
254 
ToHandshakeMessage(CryptoHandshakeMessage * out) const255 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
256   if (has_send_value_) {
257     out->SetValue(tag_, send_value_);
258   }
259 }
260 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicFixedTag(QuicTag name,QuicConfigPresence presence)284 QuicFixedTag::QuicFixedTag(QuicTag name,
285                            QuicConfigPresence presence)
286     : QuicConfigValue(name, presence),
287       has_send_value_(false),
288       has_receive_value_(false) {
289 }
290 
~QuicFixedTag()291 QuicFixedTag::~QuicFixedTag() {}
292 
HasSendValue() const293 bool QuicFixedTag::HasSendValue() const {
294   return has_send_value_;
295 }
296 
GetSendValue() const297 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 
SetSendValue(uint32 value)303 void QuicFixedTag::SetSendValue(uint32 value) {
304   has_send_value_ = true;
305   send_value_ = value;
306 }
307 
HasReceivedValue() const308 bool QuicFixedTag::HasReceivedValue() const {
309   return has_receive_value_;
310 }
311 
GetReceivedValue() const312 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 
SetReceivedValue(uint32 value)318 void QuicFixedTag::SetReceivedValue(uint32 value) {
319   has_receive_value_ = true;
320   receive_value_ = value;
321 }
322 
ToHandshakeMessage(CryptoHandshakeMessage * out) const323 void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
324   if (has_send_value_) {
325     out->SetValue(tag_, send_value_);
326   }
327 }
328 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicFixedTagVector(QuicTag name,QuicConfigPresence presence)352 QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
353                                        QuicConfigPresence presence)
354     : QuicConfigValue(name, presence),
355       has_send_values_(false),
356       has_receive_values_(false) {
357 }
358 
~QuicFixedTagVector()359 QuicFixedTagVector::~QuicFixedTagVector() {}
360 
HasSendValues() const361 bool QuicFixedTagVector::HasSendValues() const {
362   return has_send_values_;
363 }
364 
GetSendValues() const365 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 
SetSendValues(const QuicTagVector & values)371 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
372   has_send_values_ = true;
373   send_values_ = values;
374 }
375 
HasReceivedValues() const376 bool QuicFixedTagVector::HasReceivedValues() const {
377   return has_receive_values_;
378 }
379 
GetReceivedValues() const380 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 
SetReceivedValues(const QuicTagVector & values)386 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
387   has_receive_values_ = true;
388   receive_values_ = values;
389 }
390 
ToHandshakeMessage(CryptoHandshakeMessage * out) const391 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
392   if (has_send_values_) {
393     out->SetVector(tag_, send_values_);
394   }
395 }
396 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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 
QuicConfig()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 
~QuicConfig()449 QuicConfig::~QuicConfig() {}
450 
set_congestion_feedback(const QuicTagVector & congestion_feedback,QuicTag default_congestion_feedback)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 
congestion_feedback() const457 QuicTag QuicConfig::congestion_feedback() const {
458   return congestion_feedback_.GetTag();
459 }
460 
SetConnectionOptionsToSend(const QuicTagVector & connection_options)461 void QuicConfig::SetConnectionOptionsToSend(
462     const QuicTagVector& connection_options) {
463   connection_options_.SetSendValues(connection_options);
464 }
465 
HasReceivedConnectionOptions() const466 bool QuicConfig::HasReceivedConnectionOptions() const {
467   return connection_options_.HasReceivedValues();
468 }
469 
ReceivedConnectionOptions() const470 QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
471   return connection_options_.GetReceivedValues();
472 }
473 
HasSendConnectionOptions() const474 bool QuicConfig::HasSendConnectionOptions() const {
475   return connection_options_.HasSendValues();
476 }
477 
SendConnectionOptions() const478 QuicTagVector QuicConfig::SendConnectionOptions() const {
479   return connection_options_.GetSendValues();
480 }
481 
SetLossDetectionToSend(QuicTag loss_detection)482 void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
483   loss_detection_.SetSendValue(loss_detection);
484 }
485 
HasReceivedLossDetection() const486 bool QuicConfig::HasReceivedLossDetection() const {
487   return loss_detection_.HasReceivedValue();
488 }
489 
ReceivedLossDetection() const490 QuicTag QuicConfig::ReceivedLossDetection() const {
491   return loss_detection_.GetReceivedValue();
492 }
493 
set_idle_connection_state_lifetime(QuicTime::Delta max_idle_connection_state_lifetime,QuicTime::Delta default_idle_conection_state_lifetime)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 
idle_connection_state_lifetime() const502 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
503   return QuicTime::Delta::FromSeconds(
504       idle_connection_state_lifetime_seconds_.GetUint32());
505 }
506 
keepalive_timeout() const507 QuicTime::Delta QuicConfig::keepalive_timeout() const {
508   return QuicTime::Delta::FromSeconds(
509       keepalive_timeout_seconds_.GetUint32());
510 }
511 
set_max_streams_per_connection(size_t max_streams,size_t default_streams)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 
max_streams_per_connection() const517 uint32 QuicConfig::max_streams_per_connection() const {
518   return max_streams_per_connection_.GetUint32();
519 }
520 
set_max_time_before_crypto_handshake(QuicTime::Delta max_time_before_crypto_handshake)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 
max_time_before_crypto_handshake() const526 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
527   return max_time_before_crypto_handshake_;
528 }
529 
SetInitialCongestionWindowToSend(size_t initial_window)530 void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
531   initial_congestion_window_.SetSendValue(initial_window);
532 }
533 
HasReceivedInitialCongestionWindow() const534 bool QuicConfig::HasReceivedInitialCongestionWindow() const {
535   return initial_congestion_window_.HasReceivedValue();
536 }
537 
ReceivedInitialCongestionWindow() const538 uint32 QuicConfig::ReceivedInitialCongestionWindow() const {
539   return initial_congestion_window_.GetReceivedValue();
540 }
541 
SetInitialRoundTripTimeUsToSend(size_t rtt)542 void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
543   initial_round_trip_time_us_.SetSendValue(rtt);
544 }
545 
HasReceivedInitialRoundTripTimeUs() const546 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
547   return initial_round_trip_time_us_.HasReceivedValue();
548 }
549 
ReceivedInitialRoundTripTimeUs() const550 uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
551   return initial_round_trip_time_us_.GetReceivedValue();
552 }
553 
HasInitialRoundTripTimeUsToSend() const554 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
555   return initial_round_trip_time_us_.HasSendValue();
556 }
557 
GetInitialRoundTripTimeUsToSend() const558 uint32 QuicConfig::GetInitialRoundTripTimeUsToSend() const {
559   return initial_round_trip_time_us_.GetSendValue();
560 }
561 
SetInitialFlowControlWindowToSend(uint32 window_bytes)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 
GetInitialFlowControlWindowToSend() const572 uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
573   return initial_flow_control_window_bytes_.GetSendValue();
574 }
575 
HasReceivedInitialFlowControlWindowBytes() const576 bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
577   return initial_flow_control_window_bytes_.HasReceivedValue();
578 }
579 
ReceivedInitialFlowControlWindowBytes() const580 uint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
581   return initial_flow_control_window_bytes_.GetReceivedValue();
582 }
583 
SetInitialStreamFlowControlWindowToSend(uint32 window_bytes)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 
GetInitialStreamFlowControlWindowToSend() const594 uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
595   return initial_stream_flow_control_window_bytes_.GetSendValue();
596 }
597 
HasReceivedInitialStreamFlowControlWindowBytes() const598 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
599   return initial_stream_flow_control_window_bytes_.HasReceivedValue();
600 }
601 
ReceivedInitialStreamFlowControlWindowBytes() const602 uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
603   return initial_stream_flow_control_window_bytes_.GetReceivedValue();
604 }
605 
SetInitialSessionFlowControlWindowToSend(uint32 window_bytes)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 
GetInitialSessionFlowControlWindowToSend() const616 uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
617   return initial_session_flow_control_window_bytes_.GetSendValue();
618 }
619 
HasReceivedInitialSessionFlowControlWindowBytes() const620 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
621   return initial_session_flow_control_window_bytes_.HasReceivedValue();
622 }
623 
ReceivedInitialSessionFlowControlWindowBytes() const624 uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
625   return initial_session_flow_control_window_bytes_.GetReceivedValue();
626 }
627 
SetSocketReceiveBufferToSend(uint32 tcp_receive_window)628 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window) {
629   socket_receive_buffer_.SetSendValue(tcp_receive_window);
630 }
631 
GetSocketReceiveBufferToSend() const632 uint32 QuicConfig::GetSocketReceiveBufferToSend() const {
633   return socket_receive_buffer_.GetSendValue();
634 }
635 
HasReceivedSocketReceiveBuffer() const636 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
637   return socket_receive_buffer_.HasReceivedValue();
638 }
639 
ReceivedSocketReceiveBuffer() const640 uint32 QuicConfig::ReceivedSocketReceiveBuffer() const {
641   return socket_receive_buffer_.GetReceivedValue();
642 }
643 
negotiated()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 
SetDefaults()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 
ToHandshakeMessage(CryptoHandshakeMessage * out) const672 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 
ProcessPeerHello(const CryptoHandshakeMessage & peer_hello,HelloType hello_type,string * error_details)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