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"
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"
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
,
24 QuicConfigPresence presence
,
27 string
* error_details
) {
28 DCHECK(error_details
!= nullptr);
29 QuicErrorCode error
= msg
.GetUint32(tag
, out
);
31 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
32 if (presence
== PRESENCE_REQUIRED
) {
33 *error_details
= "Missing " + QuicUtils::TagToString(tag
);
36 error
= QUIC_NO_ERROR
;
42 *error_details
= "Bad " + QuicUtils::TagToString(tag
);
49 QuicConfigValue::QuicConfigValue(QuicTag tag
,
50 QuicConfigPresence presence
)
54 QuicConfigValue::~QuicConfigValue() {}
56 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag
,
57 QuicConfigPresence presence
)
58 : QuicConfigValue(tag
, presence
),
61 QuicNegotiableValue::~QuicNegotiableValue() {}
63 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag
,
64 QuicConfigPresence presence
)
65 : QuicNegotiableValue(tag
, presence
),
69 QuicNegotiableUint32::~QuicNegotiableUint32() {}
71 void QuicNegotiableUint32::set(uint32 max
, uint32 default_value
) {
72 DCHECK_LE(default_value
, max
);
74 default_value_
= default_value
;
77 uint32
QuicNegotiableUint32::GetUint32() const {
79 return negotiated_value_
;
81 return default_value_
;
84 void QuicNegotiableUint32::ToHandshakeMessage(
85 CryptoHandshakeMessage
* out
) const {
87 out
->SetValue(tag_
, negotiated_value_
);
89 out
->SetValue(tag_
, max_value_
);
93 QuicErrorCode
QuicNegotiableUint32::ProcessPeerHello(
94 const CryptoHandshakeMessage
& peer_hello
,
96 string
* error_details
) {
97 DCHECK(!negotiated());
98 DCHECK(error_details
!= nullptr);
100 QuicErrorCode error
= ReadUint32(peer_hello
,
106 if (error
!= QUIC_NO_ERROR
) {
109 if (hello_type
== SERVER
&& value
> max_value_
) {
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
),
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 QuicTag
QuicNegotiableTag::GetTag() const {
137 return negotiated_tag_
;
139 return default_value_
;
142 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
144 // Because of the way we serialize and parse handshake messages we can
145 // serialize this as value and still parse it as a vector.
146 out
->SetValue(tag_
, negotiated_tag_
);
148 out
->SetVector(tag_
, possible_values_
);
152 QuicErrorCode
QuicNegotiableTag::ReadVector(
153 const CryptoHandshakeMessage
& msg
,
156 string
* error_details
) const {
157 DCHECK(error_details
!= nullptr);
158 QuicErrorCode error
= msg
.GetTaglist(tag_
, out
, out_length
);
160 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
161 if (presence_
== PRESENCE_REQUIRED
) {
162 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
165 error
= QUIC_NO_ERROR
;
167 *out
= &default_value_
;
172 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
178 QuicErrorCode
QuicNegotiableTag::ProcessPeerHello(
179 const CryptoHandshakeMessage
& peer_hello
,
180 HelloType hello_type
,
181 string
* error_details
) {
182 DCHECK(!negotiated());
183 DCHECK(error_details
!= nullptr);
184 const QuicTag
* received_tags
;
185 size_t received_tags_length
;
186 QuicErrorCode error
= ReadVector(peer_hello
, &received_tags
,
187 &received_tags_length
, error_details
);
188 if (error
!= QUIC_NO_ERROR
) {
192 if (hello_type
== SERVER
) {
193 if (received_tags_length
!= 1 ||
194 !ContainsQuicTag(possible_values_
, *received_tags
)) {
195 *error_details
= "Invalid " + QuicUtils::TagToString(tag_
);
196 return QUIC_INVALID_NEGOTIATED_VALUE
;
198 negotiated_tag_
= *received_tags
;
200 QuicTag negotiated_tag
;
201 if (!QuicUtils::FindMutualTag(possible_values_
,
203 received_tags_length
,
204 QuicUtils::LOCAL_PRIORITY
,
207 *error_details
= "Unsupported " + QuicUtils::TagToString(tag_
);
208 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP
;
210 negotiated_tag_
= negotiated_tag
;
213 set_negotiated(true);
214 return QUIC_NO_ERROR
;
217 QuicFixedUint32::QuicFixedUint32(QuicTag tag
, QuicConfigPresence presence
)
218 : QuicConfigValue(tag
, presence
),
219 has_send_value_(false),
220 has_receive_value_(false) {
222 QuicFixedUint32::~QuicFixedUint32() {}
224 bool QuicFixedUint32::HasSendValue() const {
225 return has_send_value_
;
228 uint32
QuicFixedUint32::GetSendValue() const {
229 LOG_IF(DFATAL
, !has_send_value_
)
230 << "No send value to get for tag:" << QuicUtils::TagToString(tag_
);
234 void QuicFixedUint32::SetSendValue(uint32 value
) {
235 has_send_value_
= true;
239 bool QuicFixedUint32::HasReceivedValue() const {
240 return has_receive_value_
;
243 uint32
QuicFixedUint32::GetReceivedValue() const {
244 LOG_IF(DFATAL
, !has_receive_value_
)
245 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
246 return receive_value_
;
249 void QuicFixedUint32::SetReceivedValue(uint32 value
) {
250 has_receive_value_
= true;
251 receive_value_
= value
;
254 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
255 if (has_send_value_
) {
256 out
->SetValue(tag_
, send_value_
);
260 QuicErrorCode
QuicFixedUint32::ProcessPeerHello(
261 const CryptoHandshakeMessage
& peer_hello
,
262 HelloType hello_type
,
263 string
* error_details
) {
264 DCHECK(error_details
!= nullptr);
265 QuicErrorCode error
= peer_hello
.GetUint32(tag_
, &receive_value_
);
267 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
268 if (presence_
== PRESENCE_OPTIONAL
) {
269 return QUIC_NO_ERROR
;
271 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
274 has_receive_value_
= true;
277 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
283 QuicFixedTag::QuicFixedTag(QuicTag name
,
284 QuicConfigPresence presence
)
285 : QuicConfigValue(name
, presence
),
286 has_send_value_(false),
287 has_receive_value_(false) {
290 QuicFixedTag::~QuicFixedTag() {}
292 bool QuicFixedTag::HasSendValue() const {
293 return has_send_value_
;
296 uint32
QuicFixedTag::GetSendValue() const {
297 LOG_IF(DFATAL
, !has_send_value_
)
298 << "No send value to get for tag:" << QuicUtils::TagToString(tag_
);
302 void QuicFixedTag::SetSendValue(uint32 value
) {
303 has_send_value_
= true;
307 bool QuicFixedTag::HasReceivedValue() const {
308 return has_receive_value_
;
311 uint32
QuicFixedTag::GetReceivedValue() const {
312 LOG_IF(DFATAL
, !has_receive_value_
)
313 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
314 return receive_value_
;
317 void QuicFixedTag::SetReceivedValue(uint32 value
) {
318 has_receive_value_
= true;
319 receive_value_
= value
;
322 void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
323 if (has_send_value_
) {
324 out
->SetValue(tag_
, send_value_
);
328 QuicErrorCode
QuicFixedTag::ProcessPeerHello(
329 const CryptoHandshakeMessage
& peer_hello
,
330 HelloType hello_type
,
331 string
* error_details
) {
332 DCHECK(error_details
!= nullptr);
333 QuicErrorCode error
= peer_hello
.GetUint32(tag_
, &receive_value_
);
335 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
336 if (presence_
== PRESENCE_OPTIONAL
) {
337 return QUIC_NO_ERROR
;
339 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
342 has_receive_value_
= true;
345 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
351 QuicFixedTagVector::QuicFixedTagVector(QuicTag name
,
352 QuicConfigPresence presence
)
353 : QuicConfigValue(name
, presence
),
354 has_send_values_(false),
355 has_receive_values_(false) {
358 QuicFixedTagVector::~QuicFixedTagVector() {}
360 bool QuicFixedTagVector::HasSendValues() const {
361 return has_send_values_
;
364 QuicTagVector
QuicFixedTagVector::GetSendValues() const {
365 LOG_IF(DFATAL
, !has_send_values_
)
366 << "No send values to get for tag:" << QuicUtils::TagToString(tag_
);
370 void QuicFixedTagVector::SetSendValues(const QuicTagVector
& values
) {
371 has_send_values_
= true;
372 send_values_
= values
;
375 bool QuicFixedTagVector::HasReceivedValues() const {
376 return has_receive_values_
;
379 QuicTagVector
QuicFixedTagVector::GetReceivedValues() const {
380 LOG_IF(DFATAL
, !has_receive_values_
)
381 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
382 return receive_values_
;
385 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector
& values
) {
386 has_receive_values_
= true;
387 receive_values_
= values
;
390 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
391 if (has_send_values_
) {
392 out
->SetVector(tag_
, send_values_
);
396 QuicErrorCode
QuicFixedTagVector::ProcessPeerHello(
397 const CryptoHandshakeMessage
& peer_hello
,
398 HelloType hello_type
,
399 string
* error_details
) {
400 DCHECK(error_details
!= nullptr);
401 const QuicTag
* received_tags
;
402 size_t received_tags_length
;
403 QuicErrorCode error
=
404 peer_hello
.GetTaglist(tag_
, &received_tags
, &received_tags_length
);
406 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
407 if (presence_
== PRESENCE_OPTIONAL
) {
408 return QUIC_NO_ERROR
;
410 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
413 DVLOG(1) << "Received Connection Option tags from receiver.";
414 has_receive_values_
= true;
415 for (size_t i
= 0; i
< received_tags_length
; ++i
) {
416 receive_values_
.push_back(received_tags
[i
]);
420 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
426 QuicConfig::QuicConfig()
427 : max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
428 max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
429 max_undecryptable_packets_(0),
430 congestion_feedback_(kCGST
, PRESENCE_OPTIONAL
),
431 connection_options_(kCOPT
, PRESENCE_OPTIONAL
),
432 idle_connection_state_lifetime_seconds_(kICSL
, PRESENCE_REQUIRED
),
433 silent_close_(kSCLS
, PRESENCE_OPTIONAL
),
434 max_streams_per_connection_(kMSPC
, PRESENCE_REQUIRED
),
435 bytes_for_connection_id_(kTCID
, PRESENCE_OPTIONAL
),
436 initial_round_trip_time_us_(kIRTT
, PRESENCE_OPTIONAL
),
437 initial_stream_flow_control_window_bytes_(kSFCW
, PRESENCE_OPTIONAL
),
438 initial_session_flow_control_window_bytes_(kCFCW
, PRESENCE_OPTIONAL
),
439 socket_receive_buffer_(kSRBF
, PRESENCE_OPTIONAL
) {
443 QuicConfig::~QuicConfig() {}
445 void QuicConfig::SetConnectionOptionsToSend(
446 const QuicTagVector
& connection_options
) {
447 connection_options_
.SetSendValues(connection_options
);
450 bool QuicConfig::HasReceivedConnectionOptions() const {
451 return connection_options_
.HasReceivedValues();
454 QuicTagVector
QuicConfig::ReceivedConnectionOptions() const {
455 return connection_options_
.GetReceivedValues();
458 bool QuicConfig::HasSendConnectionOptions() const {
459 return connection_options_
.HasSendValues();
462 QuicTagVector
QuicConfig::SendConnectionOptions() const {
463 return connection_options_
.GetSendValues();
466 void QuicConfig::SetIdleConnectionStateLifetime(
467 QuicTime::Delta max_idle_connection_state_lifetime
,
468 QuicTime::Delta default_idle_conection_state_lifetime
) {
469 idle_connection_state_lifetime_seconds_
.set(
470 static_cast<uint32
>(max_idle_connection_state_lifetime
.ToSeconds()),
471 static_cast<uint32
>(default_idle_conection_state_lifetime
.ToSeconds()));
474 QuicTime::Delta
QuicConfig::IdleConnectionStateLifetime() const {
475 return QuicTime::Delta::FromSeconds(
476 idle_connection_state_lifetime_seconds_
.GetUint32());
479 void QuicConfig::SetSilentClose(bool silent_close
) {
480 silent_close_
.set(silent_close
? 1 : 0, silent_close
? 1 : 0);
483 bool QuicConfig::SilentClose() const {
484 return silent_close_
.GetUint32() > 0;
487 void QuicConfig::SetMaxStreamsPerConnection(size_t max_streams
,
488 size_t default_streams
) {
489 max_streams_per_connection_
.set(max_streams
, default_streams
);
492 uint32
QuicConfig::MaxStreamsPerConnection() const {
493 return max_streams_per_connection_
.GetUint32();
496 bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
497 return bytes_for_connection_id_
.HasSendValue();
500 void QuicConfig::SetBytesForConnectionIdToSend(uint32 bytes
) {
501 bytes_for_connection_id_
.SetSendValue(bytes
);
504 bool QuicConfig::HasReceivedBytesForConnectionId() const {
505 return bytes_for_connection_id_
.HasReceivedValue();
508 uint32
QuicConfig::ReceivedBytesForConnectionId() const {
509 return bytes_for_connection_id_
.GetReceivedValue();
512 void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32 rtt
) {
513 initial_round_trip_time_us_
.SetSendValue(rtt
);
516 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
517 return initial_round_trip_time_us_
.HasReceivedValue();
520 uint32
QuicConfig::ReceivedInitialRoundTripTimeUs() const {
521 return initial_round_trip_time_us_
.GetReceivedValue();
524 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
525 return initial_round_trip_time_us_
.HasSendValue();
528 uint32
QuicConfig::GetInitialRoundTripTimeUsToSend() const {
529 return initial_round_trip_time_us_
.GetSendValue();
532 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes
) {
533 if (window_bytes
< kMinimumFlowControlSendWindow
) {
534 LOG(DFATAL
) << "Initial stream flow control receive window ("
535 << window_bytes
<< ") cannot be set lower than default ("
536 << kMinimumFlowControlSendWindow
<< ").";
537 window_bytes
= kMinimumFlowControlSendWindow
;
539 initial_stream_flow_control_window_bytes_
.SetSendValue(window_bytes
);
542 uint32
QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
543 return initial_stream_flow_control_window_bytes_
.GetSendValue();
546 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
547 return initial_stream_flow_control_window_bytes_
.HasReceivedValue();
550 uint32
QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
551 return initial_stream_flow_control_window_bytes_
.GetReceivedValue();
554 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes
) {
555 if (window_bytes
< kMinimumFlowControlSendWindow
) {
556 LOG(DFATAL
) << "Initial session flow control receive window ("
557 << window_bytes
<< ") cannot be set lower than default ("
558 << kMinimumFlowControlSendWindow
<< ").";
559 window_bytes
= kMinimumFlowControlSendWindow
;
561 initial_session_flow_control_window_bytes_
.SetSendValue(window_bytes
);
564 uint32
QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
565 return initial_session_flow_control_window_bytes_
.GetSendValue();
568 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
569 return initial_session_flow_control_window_bytes_
.HasReceivedValue();
572 uint32
QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
573 return initial_session_flow_control_window_bytes_
.GetReceivedValue();
576 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window
) {
577 socket_receive_buffer_
.SetSendValue(tcp_receive_window
);
580 uint32
QuicConfig::GetSocketReceiveBufferToSend() const {
581 return socket_receive_buffer_
.GetSendValue();
584 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
585 return socket_receive_buffer_
.HasReceivedValue();
588 uint32
QuicConfig::ReceivedSocketReceiveBuffer() const {
589 return socket_receive_buffer_
.GetReceivedValue();
592 bool QuicConfig::negotiated() const {
593 // TODO(ianswett): Add the negotiated parameters once and iterate over all
594 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
595 // ProcessServerHello.
596 return idle_connection_state_lifetime_seconds_
.negotiated() &&
597 max_streams_per_connection_
.negotiated();
600 void QuicConfig::SetDefaults() {
601 QuicTagVector congestion_feedback
;
602 // TODO(alyssar) stop sending this once QUIC_VERSION_23 is sunset.
603 // This field was required until version 22 was removed but by the time
604 // QUIC_VERSION_23 is sunset, no users of QUIC_VERSION_24 should be expecting
606 congestion_feedback
.push_back(kQBIC
);
607 congestion_feedback_
.set(congestion_feedback
, kQBIC
);
608 idle_connection_state_lifetime_seconds_
.set(kMaximumIdleTimeoutSecs
,
609 kDefaultIdleTimeoutSecs
);
610 silent_close_
.set(1, 0);
611 SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection
,
612 kDefaultMaxStreamsPerConnection
);
613 max_time_before_crypto_handshake_
=
614 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs
);
615 max_idle_time_before_crypto_handshake_
=
616 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs
);
617 max_undecryptable_packets_
= kDefaultMaxUndecryptablePackets
;
619 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow
);
620 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow
);
623 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
624 congestion_feedback_
.ToHandshakeMessage(out
);
625 idle_connection_state_lifetime_seconds_
.ToHandshakeMessage(out
);
626 silent_close_
.ToHandshakeMessage(out
);
627 max_streams_per_connection_
.ToHandshakeMessage(out
);
628 bytes_for_connection_id_
.ToHandshakeMessage(out
);
629 initial_round_trip_time_us_
.ToHandshakeMessage(out
);
630 initial_stream_flow_control_window_bytes_
.ToHandshakeMessage(out
);
631 initial_session_flow_control_window_bytes_
.ToHandshakeMessage(out
);
632 socket_receive_buffer_
.ToHandshakeMessage(out
);
633 connection_options_
.ToHandshakeMessage(out
);
636 QuicErrorCode
QuicConfig::ProcessPeerHello(
637 const CryptoHandshakeMessage
& peer_hello
,
638 HelloType hello_type
,
639 string
* error_details
) {
640 DCHECK(error_details
!= nullptr);
642 QuicErrorCode error
= QUIC_NO_ERROR
;
643 if (error
== QUIC_NO_ERROR
) {
644 error
= idle_connection_state_lifetime_seconds_
.ProcessPeerHello(
645 peer_hello
, hello_type
, error_details
);
647 if (error
== QUIC_NO_ERROR
) {
649 silent_close_
.ProcessPeerHello(peer_hello
, hello_type
, error_details
);
651 if (error
== QUIC_NO_ERROR
) {
652 error
= max_streams_per_connection_
.ProcessPeerHello(
653 peer_hello
, hello_type
, error_details
);
655 if (error
== QUIC_NO_ERROR
) {
656 error
= bytes_for_connection_id_
.ProcessPeerHello(
657 peer_hello
, hello_type
, error_details
);
659 if (error
== QUIC_NO_ERROR
) {
660 error
= initial_round_trip_time_us_
.ProcessPeerHello(
661 peer_hello
, hello_type
, error_details
);
663 if (error
== QUIC_NO_ERROR
) {
664 error
= initial_stream_flow_control_window_bytes_
.ProcessPeerHello(
665 peer_hello
, hello_type
, error_details
);
667 if (error
== QUIC_NO_ERROR
) {
668 error
= initial_session_flow_control_window_bytes_
.ProcessPeerHello(
669 peer_hello
, hello_type
, error_details
);
671 if (error
== QUIC_NO_ERROR
) {
672 error
= socket_receive_buffer_
.ProcessPeerHello(
673 peer_hello
, hello_type
, error_details
);
675 if (error
== QUIC_NO_ERROR
) {
676 error
= connection_options_
.ProcessPeerHello(
677 peer_hello
, hello_type
, error_details
);