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