Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / net / quic / quic_config.cc
blobd91fd7bc9edb4f94d816a1053831fb52f4295734
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.
5 #include "net/quic/quic_config.h"
7 #include <algorithm>
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_utils.h"
14 using std::min;
15 using std::string;
17 namespace net {
19 // Reads the value corresponding to |name_| from |msg| into |out|. If the
20 // |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
21 // to |default_value|.
22 QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
23 QuicTag tag,
24 QuicConfigPresence presence,
25 uint32 default_value,
26 uint32* out,
27 string* error_details) {
28 DCHECK(error_details != nullptr);
29 QuicErrorCode error = msg.GetUint32(tag, out);
30 switch (error) {
31 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
32 if (presence == PRESENCE_REQUIRED) {
33 *error_details = "Missing " + QuicUtils::TagToString(tag);
34 break;
36 error = QUIC_NO_ERROR;
37 *out = default_value;
38 break;
39 case QUIC_NO_ERROR:
40 break;
41 default:
42 *error_details = "Bad " + QuicUtils::TagToString(tag);
43 break;
45 return error;
48 QuicConfigValue::QuicConfigValue(QuicTag tag,
49 QuicConfigPresence presence)
50 : tag_(tag),
51 presence_(presence) {
53 QuicConfigValue::~QuicConfigValue() {}
55 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
56 QuicConfigPresence presence)
57 : QuicConfigValue(tag, presence),
58 negotiated_(false) {
60 QuicNegotiableValue::~QuicNegotiableValue() {}
62 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
63 QuicConfigPresence presence)
64 : QuicNegotiableValue(tag, presence),
65 max_value_(0),
66 default_value_(0),
67 negotiated_value_(0) {
69 QuicNegotiableUint32::~QuicNegotiableUint32() {}
71 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
72 DCHECK_LE(default_value, max);
73 max_value_ = max;
74 default_value_ = default_value;
77 uint32 QuicNegotiableUint32::GetUint32() const {
78 if (negotiated()) {
79 return negotiated_value_;
81 return default_value_;
84 void QuicNegotiableUint32::ToHandshakeMessage(
85 CryptoHandshakeMessage* out) const {
86 if (negotiated()) {
87 out->SetValue(tag_, negotiated_value_);
88 } else {
89 out->SetValue(tag_, max_value_);
93 QuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
94 const CryptoHandshakeMessage& peer_hello,
95 HelloType hello_type,
96 string* error_details) {
97 DCHECK(!negotiated());
98 DCHECK(error_details != nullptr);
99 uint32 value;
100 QuicErrorCode error = ReadUint32(peer_hello,
101 tag_,
102 presence_,
103 default_value_,
104 &value,
105 error_details);
106 if (error != QUIC_NO_ERROR) {
107 return error;
109 if (hello_type == SERVER && value > max_value_) {
110 *error_details =
111 "Invalid value received for " + QuicUtils::TagToString(tag_);
112 return QUIC_INVALID_NEGOTIATED_VALUE;
115 set_negotiated(true);
116 negotiated_value_ = min(value, max_value_);
117 return QUIC_NO_ERROR;
120 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
121 : QuicNegotiableValue(tag, presence),
122 negotiated_tag_(0),
123 default_value_(0) {
126 QuicNegotiableTag::~QuicNegotiableTag() {}
128 void QuicNegotiableTag::set(const QuicTagVector& possible,
129 QuicTag default_value) {
130 DCHECK(ContainsQuicTag(possible, default_value));
131 possible_values_ = possible;
132 default_value_ = default_value;
135 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
136 if (negotiated()) {
137 // Because of the way we serialize and parse handshake messages we can
138 // serialize this as value and still parse it as a vector.
139 out->SetValue(tag_, negotiated_tag_);
140 } else {
141 out->SetVector(tag_, possible_values_);
145 QuicErrorCode QuicNegotiableTag::ReadVector(
146 const CryptoHandshakeMessage& msg,
147 const QuicTag** out,
148 size_t* out_length,
149 string* error_details) const {
150 DCHECK(error_details != nullptr);
151 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
152 switch (error) {
153 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
154 if (presence_ == PRESENCE_REQUIRED) {
155 *error_details = "Missing " + QuicUtils::TagToString(tag_);
156 break;
158 error = QUIC_NO_ERROR;
159 *out_length = 1;
160 *out = &default_value_;
162 case QUIC_NO_ERROR:
163 break;
164 default:
165 *error_details = "Bad " + QuicUtils::TagToString(tag_);
166 break;
168 return error;
171 QuicErrorCode QuicNegotiableTag::ProcessPeerHello(
172 const CryptoHandshakeMessage& peer_hello,
173 HelloType hello_type,
174 string* error_details) {
175 DCHECK(!negotiated());
176 DCHECK(error_details != nullptr);
177 const QuicTag* received_tags;
178 size_t received_tags_length;
179 QuicErrorCode error = ReadVector(peer_hello, &received_tags,
180 &received_tags_length, error_details);
181 if (error != QUIC_NO_ERROR) {
182 return error;
185 if (hello_type == SERVER) {
186 if (received_tags_length != 1 ||
187 !ContainsQuicTag(possible_values_, *received_tags)) {
188 *error_details = "Invalid " + QuicUtils::TagToString(tag_);
189 return QUIC_INVALID_NEGOTIATED_VALUE;
191 negotiated_tag_ = *received_tags;
192 } else {
193 QuicTag negotiated_tag;
194 if (!QuicUtils::FindMutualTag(possible_values_,
195 received_tags,
196 received_tags_length,
197 QuicUtils::LOCAL_PRIORITY,
198 &negotiated_tag,
199 nullptr)) {
200 *error_details = "Unsupported " + QuicUtils::TagToString(tag_);
201 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
203 negotiated_tag_ = negotiated_tag;
206 set_negotiated(true);
207 return QUIC_NO_ERROR;
210 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
211 : QuicConfigValue(tag, presence),
212 has_send_value_(false),
213 has_receive_value_(false) {
215 QuicFixedUint32::~QuicFixedUint32() {}
217 bool QuicFixedUint32::HasSendValue() const {
218 return has_send_value_;
221 uint32 QuicFixedUint32::GetSendValue() const {
222 LOG_IF(DFATAL, !has_send_value_)
223 << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
224 return send_value_;
227 void QuicFixedUint32::SetSendValue(uint32 value) {
228 has_send_value_ = true;
229 send_value_ = value;
232 bool QuicFixedUint32::HasReceivedValue() const {
233 return has_receive_value_;
236 uint32 QuicFixedUint32::GetReceivedValue() const {
237 LOG_IF(DFATAL, !has_receive_value_)
238 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
239 return receive_value_;
242 void QuicFixedUint32::SetReceivedValue(uint32 value) {
243 has_receive_value_ = true;
244 receive_value_ = value;
247 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
248 if (has_send_value_) {
249 out->SetValue(tag_, send_value_);
253 QuicErrorCode QuicFixedUint32::ProcessPeerHello(
254 const CryptoHandshakeMessage& peer_hello,
255 HelloType hello_type,
256 string* error_details) {
257 DCHECK(error_details != nullptr);
258 QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
259 switch (error) {
260 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
261 if (presence_ == PRESENCE_OPTIONAL) {
262 return QUIC_NO_ERROR;
264 *error_details = "Missing " + QuicUtils::TagToString(tag_);
265 break;
266 case QUIC_NO_ERROR:
267 has_receive_value_ = true;
268 break;
269 default:
270 *error_details = "Bad " + QuicUtils::TagToString(tag_);
271 break;
273 return error;
276 QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
277 QuicConfigPresence presence)
278 : QuicConfigValue(name, presence),
279 has_send_values_(false),
280 has_receive_values_(false) {
283 QuicFixedTagVector::~QuicFixedTagVector() {}
285 bool QuicFixedTagVector::HasSendValues() const {
286 return has_send_values_;
289 QuicTagVector QuicFixedTagVector::GetSendValues() const {
290 LOG_IF(DFATAL, !has_send_values_)
291 << "No send values to get for tag:" << QuicUtils::TagToString(tag_);
292 return send_values_;
295 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
296 has_send_values_ = true;
297 send_values_ = values;
300 bool QuicFixedTagVector::HasReceivedValues() const {
301 return has_receive_values_;
304 QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
305 LOG_IF(DFATAL, !has_receive_values_)
306 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
307 return receive_values_;
310 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
311 has_receive_values_ = true;
312 receive_values_ = values;
315 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
316 if (has_send_values_) {
317 out->SetVector(tag_, send_values_);
321 QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
322 const CryptoHandshakeMessage& peer_hello,
323 HelloType hello_type,
324 string* error_details) {
325 DCHECK(error_details != nullptr);
326 const QuicTag* received_tags;
327 size_t received_tags_length;
328 QuicErrorCode error =
329 peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
330 switch (error) {
331 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
332 if (presence_ == PRESENCE_OPTIONAL) {
333 return QUIC_NO_ERROR;
335 *error_details = "Missing " + QuicUtils::TagToString(tag_);
336 break;
337 case QUIC_NO_ERROR:
338 DVLOG(1) << "Received Connection Option tags from receiver.";
339 has_receive_values_ = true;
340 for (size_t i = 0; i < received_tags_length; ++i) {
341 receive_values_.push_back(received_tags[i]);
343 break;
344 default:
345 *error_details = "Bad " + QuicUtils::TagToString(tag_);
346 break;
348 return error;
351 QuicConfig::QuicConfig()
352 : max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
353 max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
354 max_undecryptable_packets_(0),
355 connection_options_(kCOPT, PRESENCE_OPTIONAL),
356 idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
357 silent_close_(kSCLS, PRESENCE_OPTIONAL),
358 max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED),
359 bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
360 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
361 initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
362 initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
363 socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL) {
364 SetDefaults();
367 QuicConfig::~QuicConfig() {}
369 bool QuicConfig::SetInitialReceivedConnectionOptions(
370 const QuicTagVector& tags) {
371 if (HasReceivedConnectionOptions()) {
372 // If we have already received connection options (via handshake or due to a
373 // previous call), don't re-initialize.
374 return false;
376 connection_options_.SetReceivedValues(tags);
377 return true;
380 void QuicConfig::SetConnectionOptionsToSend(
381 const QuicTagVector& connection_options) {
382 connection_options_.SetSendValues(connection_options);
385 bool QuicConfig::HasReceivedConnectionOptions() const {
386 return connection_options_.HasReceivedValues();
389 QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
390 return connection_options_.GetReceivedValues();
393 bool QuicConfig::HasSendConnectionOptions() const {
394 return connection_options_.HasSendValues();
397 QuicTagVector QuicConfig::SendConnectionOptions() const {
398 return connection_options_.GetSendValues();
401 bool QuicConfig::HasClientSentConnectionOption(QuicTag tag,
402 Perspective perspective) const {
403 if (perspective == Perspective::IS_SERVER) {
404 if (HasReceivedConnectionOptions() &&
405 ContainsQuicTag(ReceivedConnectionOptions(), tag)) {
406 return true;
408 } else if (HasSendConnectionOptions() &&
409 ContainsQuicTag(SendConnectionOptions(), tag)) {
410 return true;
412 return false;
415 void QuicConfig::SetIdleConnectionStateLifetime(
416 QuicTime::Delta max_idle_connection_state_lifetime,
417 QuicTime::Delta default_idle_conection_state_lifetime) {
418 idle_connection_state_lifetime_seconds_.set(
419 static_cast<uint32>(max_idle_connection_state_lifetime.ToSeconds()),
420 static_cast<uint32>(default_idle_conection_state_lifetime.ToSeconds()));
423 QuicTime::Delta QuicConfig::IdleConnectionStateLifetime() const {
424 return QuicTime::Delta::FromSeconds(
425 idle_connection_state_lifetime_seconds_.GetUint32());
428 // TODO(ianswett) Use this for silent close on mobile, or delete.
429 void QuicConfig::SetSilentClose(bool silent_close) {
430 silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0);
433 bool QuicConfig::SilentClose() const {
434 return silent_close_.GetUint32() > 0;
437 void QuicConfig::SetMaxStreamsPerConnection(size_t max_streams,
438 size_t default_streams) {
439 max_streams_per_connection_.set(max_streams, default_streams);
442 uint32 QuicConfig::MaxStreamsPerConnection() const {
443 return max_streams_per_connection_.GetUint32();
446 bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
447 return bytes_for_connection_id_.HasSendValue();
450 void QuicConfig::SetBytesForConnectionIdToSend(uint32 bytes) {
451 bytes_for_connection_id_.SetSendValue(bytes);
454 bool QuicConfig::HasReceivedBytesForConnectionId() const {
455 return bytes_for_connection_id_.HasReceivedValue();
458 uint32 QuicConfig::ReceivedBytesForConnectionId() const {
459 return bytes_for_connection_id_.GetReceivedValue();
462 void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32 rtt) {
463 initial_round_trip_time_us_.SetSendValue(rtt);
466 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
467 return initial_round_trip_time_us_.HasReceivedValue();
470 uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
471 return initial_round_trip_time_us_.GetReceivedValue();
474 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
475 return initial_round_trip_time_us_.HasSendValue();
478 uint32 QuicConfig::GetInitialRoundTripTimeUsToSend() const {
479 return initial_round_trip_time_us_.GetSendValue();
482 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
483 if (window_bytes < kMinimumFlowControlSendWindow) {
484 LOG(DFATAL) << "Initial stream flow control receive window ("
485 << window_bytes << ") cannot be set lower than default ("
486 << kMinimumFlowControlSendWindow << ").";
487 window_bytes = kMinimumFlowControlSendWindow;
489 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
492 uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
493 return initial_stream_flow_control_window_bytes_.GetSendValue();
496 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
497 return initial_stream_flow_control_window_bytes_.HasReceivedValue();
500 uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
501 return initial_stream_flow_control_window_bytes_.GetReceivedValue();
504 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
505 if (window_bytes < kMinimumFlowControlSendWindow) {
506 LOG(DFATAL) << "Initial session flow control receive window ("
507 << window_bytes << ") cannot be set lower than default ("
508 << kMinimumFlowControlSendWindow << ").";
509 window_bytes = kMinimumFlowControlSendWindow;
511 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
514 uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
515 return initial_session_flow_control_window_bytes_.GetSendValue();
518 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
519 return initial_session_flow_control_window_bytes_.HasReceivedValue();
522 uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
523 return initial_session_flow_control_window_bytes_.GetReceivedValue();
526 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window) {
527 socket_receive_buffer_.SetSendValue(tcp_receive_window);
530 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
531 return socket_receive_buffer_.HasReceivedValue();
534 uint32 QuicConfig::ReceivedSocketReceiveBuffer() const {
535 return socket_receive_buffer_.GetReceivedValue();
538 bool QuicConfig::negotiated() const {
539 // TODO(ianswett): Add the negotiated parameters once and iterate over all
540 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
541 // ProcessServerHello.
542 return idle_connection_state_lifetime_seconds_.negotiated() &&
543 max_streams_per_connection_.negotiated();
546 void QuicConfig::SetDefaults() {
547 idle_connection_state_lifetime_seconds_.set(kMaximumIdleTimeoutSecs,
548 kDefaultIdleTimeoutSecs);
549 silent_close_.set(1, 0);
550 SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection,
551 kDefaultMaxStreamsPerConnection);
552 max_time_before_crypto_handshake_ =
553 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
554 max_idle_time_before_crypto_handshake_ =
555 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs);
556 max_undecryptable_packets_ = kDefaultMaxUndecryptablePackets;
558 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
559 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
562 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
563 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
564 silent_close_.ToHandshakeMessage(out);
565 max_streams_per_connection_.ToHandshakeMessage(out);
566 bytes_for_connection_id_.ToHandshakeMessage(out);
567 initial_round_trip_time_us_.ToHandshakeMessage(out);
568 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
569 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
570 socket_receive_buffer_.ToHandshakeMessage(out);
571 connection_options_.ToHandshakeMessage(out);
574 QuicErrorCode QuicConfig::ProcessPeerHello(
575 const CryptoHandshakeMessage& peer_hello,
576 HelloType hello_type,
577 string* error_details) {
578 DCHECK(error_details != nullptr);
580 QuicErrorCode error = QUIC_NO_ERROR;
581 if (error == QUIC_NO_ERROR) {
582 error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
583 peer_hello, hello_type, error_details);
585 if (error == QUIC_NO_ERROR) {
586 error =
587 silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
589 if (error == QUIC_NO_ERROR) {
590 error = max_streams_per_connection_.ProcessPeerHello(
591 peer_hello, hello_type, error_details);
593 if (error == QUIC_NO_ERROR) {
594 error = bytes_for_connection_id_.ProcessPeerHello(
595 peer_hello, hello_type, error_details);
597 if (error == QUIC_NO_ERROR) {
598 error = initial_round_trip_time_us_.ProcessPeerHello(
599 peer_hello, hello_type, error_details);
601 if (error == QUIC_NO_ERROR) {
602 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
603 peer_hello, hello_type, error_details);
605 if (error == QUIC_NO_ERROR) {
606 error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
607 peer_hello, hello_type, error_details);
609 if (error == QUIC_NO_ERROR) {
610 error = socket_receive_buffer_.ProcessPeerHello(
611 peer_hello, hello_type, error_details);
613 if (error == QUIC_NO_ERROR) {
614 error = connection_options_.ProcessPeerHello(
615 peer_hello, hello_type, error_details);
617 return error;
620 } // namespace net