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