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
),
68 negotiated_value_(0) {
70 QuicNegotiableUint32::~QuicNegotiableUint32() {}
72 void QuicNegotiableUint32::set(uint32 max
, uint32 default_value
) {
73 DCHECK_LE(default_value
, max
);
75 default_value_
= default_value
;
78 uint32
QuicNegotiableUint32::GetUint32() const {
80 return negotiated_value_
;
82 return default_value_
;
85 void QuicNegotiableUint32::ToHandshakeMessage(
86 CryptoHandshakeMessage
* out
) const {
88 out
->SetValue(tag_
, negotiated_value_
);
90 out
->SetValue(tag_
, max_value_
);
94 QuicErrorCode
QuicNegotiableUint32::ProcessPeerHello(
95 const CryptoHandshakeMessage
& peer_hello
,
97 string
* error_details
) {
98 DCHECK(!negotiated());
99 DCHECK(error_details
!= nullptr);
101 QuicErrorCode error
= ReadUint32(peer_hello
,
107 if (error
!= QUIC_NO_ERROR
) {
110 if (hello_type
== SERVER
&& value
> max_value_
) {
112 "Invalid value received for " + QuicUtils::TagToString(tag_
);
113 return QUIC_INVALID_NEGOTIATED_VALUE
;
116 set_negotiated(true);
117 negotiated_value_
= min(value
, max_value_
);
118 return QUIC_NO_ERROR
;
121 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag
, QuicConfigPresence presence
)
122 : QuicNegotiableValue(tag
, presence
),
127 QuicNegotiableTag::~QuicNegotiableTag() {}
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
;
136 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
138 // Because of the way we serialize and parse handshake messages we can
139 // serialize this as value and still parse it as a vector.
140 out
->SetValue(tag_
, negotiated_tag_
);
142 out
->SetVector(tag_
, possible_values_
);
146 QuicErrorCode
QuicNegotiableTag::ReadVector(
147 const CryptoHandshakeMessage
& msg
,
150 string
* error_details
) const {
151 DCHECK(error_details
!= nullptr);
152 QuicErrorCode error
= msg
.GetTaglist(tag_
, out
, out_length
);
154 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
155 if (presence_
== PRESENCE_REQUIRED
) {
156 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
159 error
= QUIC_NO_ERROR
;
161 *out
= &default_value_
;
166 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
172 QuicErrorCode
QuicNegotiableTag::ProcessPeerHello(
173 const CryptoHandshakeMessage
& peer_hello
,
174 HelloType hello_type
,
175 string
* error_details
) {
176 DCHECK(!negotiated());
177 DCHECK(error_details
!= nullptr);
178 const QuicTag
* received_tags
;
179 size_t received_tags_length
;
180 QuicErrorCode error
= ReadVector(peer_hello
, &received_tags
,
181 &received_tags_length
, error_details
);
182 if (error
!= QUIC_NO_ERROR
) {
186 if (hello_type
== SERVER
) {
187 if (received_tags_length
!= 1 ||
188 !ContainsQuicTag(possible_values_
, *received_tags
)) {
189 *error_details
= "Invalid " + QuicUtils::TagToString(tag_
);
190 return QUIC_INVALID_NEGOTIATED_VALUE
;
192 negotiated_tag_
= *received_tags
;
194 QuicTag negotiated_tag
;
195 if (!QuicUtils::FindMutualTag(possible_values_
,
197 received_tags_length
,
198 QuicUtils::LOCAL_PRIORITY
,
201 *error_details
= "Unsupported " + QuicUtils::TagToString(tag_
);
202 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP
;
204 negotiated_tag_
= negotiated_tag
;
207 set_negotiated(true);
208 return QUIC_NO_ERROR
;
211 QuicFixedUint32::QuicFixedUint32(QuicTag tag
, QuicConfigPresence presence
)
212 : QuicConfigValue(tag
, presence
),
213 has_send_value_(false),
214 has_receive_value_(false) {
216 QuicFixedUint32::~QuicFixedUint32() {}
218 bool QuicFixedUint32::HasSendValue() const {
219 return has_send_value_
;
222 uint32
QuicFixedUint32::GetSendValue() const {
223 LOG_IF(DFATAL
, !has_send_value_
)
224 << "No send value to get for tag:" << QuicUtils::TagToString(tag_
);
228 void QuicFixedUint32::SetSendValue(uint32 value
) {
229 has_send_value_
= true;
233 bool QuicFixedUint32::HasReceivedValue() const {
234 return has_receive_value_
;
237 uint32
QuicFixedUint32::GetReceivedValue() const {
238 LOG_IF(DFATAL
, !has_receive_value_
)
239 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
240 return receive_value_
;
243 void QuicFixedUint32::SetReceivedValue(uint32 value
) {
244 has_receive_value_
= true;
245 receive_value_
= value
;
248 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
249 if (has_send_value_
) {
250 out
->SetValue(tag_
, send_value_
);
254 QuicErrorCode
QuicFixedUint32::ProcessPeerHello(
255 const CryptoHandshakeMessage
& peer_hello
,
256 HelloType hello_type
,
257 string
* error_details
) {
258 DCHECK(error_details
!= nullptr);
259 QuicErrorCode error
= peer_hello
.GetUint32(tag_
, &receive_value_
);
261 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
262 if (presence_
== PRESENCE_OPTIONAL
) {
263 return QUIC_NO_ERROR
;
265 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
268 has_receive_value_
= true;
271 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
277 QuicFixedTagVector::QuicFixedTagVector(QuicTag name
,
278 QuicConfigPresence presence
)
279 : QuicConfigValue(name
, presence
),
280 has_send_values_(false),
281 has_receive_values_(false) {
284 QuicFixedTagVector::~QuicFixedTagVector() {}
286 bool QuicFixedTagVector::HasSendValues() const {
287 return has_send_values_
;
290 QuicTagVector
QuicFixedTagVector::GetSendValues() const {
291 LOG_IF(DFATAL
, !has_send_values_
)
292 << "No send values to get for tag:" << QuicUtils::TagToString(tag_
);
296 void QuicFixedTagVector::SetSendValues(const QuicTagVector
& values
) {
297 has_send_values_
= true;
298 send_values_
= values
;
301 bool QuicFixedTagVector::HasReceivedValues() const {
302 return has_receive_values_
;
305 QuicTagVector
QuicFixedTagVector::GetReceivedValues() const {
306 LOG_IF(DFATAL
, !has_receive_values_
)
307 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
308 return receive_values_
;
311 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector
& values
) {
312 has_receive_values_
= true;
313 receive_values_
= values
;
316 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
317 if (has_send_values_
) {
318 out
->SetVector(tag_
, send_values_
);
322 QuicErrorCode
QuicFixedTagVector::ProcessPeerHello(
323 const CryptoHandshakeMessage
& peer_hello
,
324 HelloType hello_type
,
325 string
* error_details
) {
326 DCHECK(error_details
!= nullptr);
327 const QuicTag
* received_tags
;
328 size_t received_tags_length
;
329 QuicErrorCode error
=
330 peer_hello
.GetTaglist(tag_
, &received_tags
, &received_tags_length
);
332 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
333 if (presence_
== PRESENCE_OPTIONAL
) {
334 return QUIC_NO_ERROR
;
336 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
339 DVLOG(1) << "Received Connection Option tags from receiver.";
340 has_receive_values_
= true;
341 for (size_t i
= 0; i
< received_tags_length
; ++i
) {
342 receive_values_
.push_back(received_tags
[i
]);
346 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
352 QuicConfig::QuicConfig()
353 : max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
354 max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
355 max_undecryptable_packets_(0),
356 congestion_feedback_(kCGST
, PRESENCE_OPTIONAL
),
357 connection_options_(kCOPT
, PRESENCE_OPTIONAL
),
358 idle_connection_state_lifetime_seconds_(kICSL
, PRESENCE_REQUIRED
),
359 silent_close_(kSCLS
, PRESENCE_OPTIONAL
),
360 max_streams_per_connection_(kMSPC
, PRESENCE_REQUIRED
),
361 bytes_for_connection_id_(kTCID
, PRESENCE_OPTIONAL
),
362 initial_round_trip_time_us_(kIRTT
, PRESENCE_OPTIONAL
),
363 initial_stream_flow_control_window_bytes_(kSFCW
, PRESENCE_OPTIONAL
),
364 initial_session_flow_control_window_bytes_(kCFCW
, PRESENCE_OPTIONAL
),
365 socket_receive_buffer_(kSRBF
, PRESENCE_OPTIONAL
) {
369 QuicConfig::~QuicConfig() {}
371 void QuicConfig::SetConnectionOptionsToSend(
372 const QuicTagVector
& connection_options
) {
373 connection_options_
.SetSendValues(connection_options
);
376 bool QuicConfig::HasReceivedConnectionOptions() const {
377 return connection_options_
.HasReceivedValues();
380 QuicTagVector
QuicConfig::ReceivedConnectionOptions() const {
381 return connection_options_
.GetReceivedValues();
384 bool QuicConfig::HasSendConnectionOptions() const {
385 return connection_options_
.HasSendValues();
388 QuicTagVector
QuicConfig::SendConnectionOptions() const {
389 return connection_options_
.GetSendValues();
392 void QuicConfig::SetIdleConnectionStateLifetime(
393 QuicTime::Delta max_idle_connection_state_lifetime
,
394 QuicTime::Delta default_idle_conection_state_lifetime
) {
395 idle_connection_state_lifetime_seconds_
.set(
396 static_cast<uint32
>(max_idle_connection_state_lifetime
.ToSeconds()),
397 static_cast<uint32
>(default_idle_conection_state_lifetime
.ToSeconds()));
400 QuicTime::Delta
QuicConfig::IdleConnectionStateLifetime() const {
401 return QuicTime::Delta::FromSeconds(
402 idle_connection_state_lifetime_seconds_
.GetUint32());
405 // TODO(ianswett) Use this for silent close on mobile, or delete.
406 void QuicConfig::SetSilentClose(bool silent_close
) {
407 silent_close_
.set(silent_close
? 1 : 0, silent_close
? 1 : 0);
410 bool QuicConfig::SilentClose() const {
411 return silent_close_
.GetUint32() > 0;
414 void QuicConfig::SetMaxStreamsPerConnection(size_t max_streams
,
415 size_t default_streams
) {
416 max_streams_per_connection_
.set(max_streams
, default_streams
);
419 uint32
QuicConfig::MaxStreamsPerConnection() const {
420 return max_streams_per_connection_
.GetUint32();
423 bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
424 return bytes_for_connection_id_
.HasSendValue();
427 void QuicConfig::SetBytesForConnectionIdToSend(uint32 bytes
) {
428 bytes_for_connection_id_
.SetSendValue(bytes
);
431 bool QuicConfig::HasReceivedBytesForConnectionId() const {
432 return bytes_for_connection_id_
.HasReceivedValue();
435 uint32
QuicConfig::ReceivedBytesForConnectionId() const {
436 return bytes_for_connection_id_
.GetReceivedValue();
439 void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32 rtt
) {
440 initial_round_trip_time_us_
.SetSendValue(rtt
);
443 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
444 return initial_round_trip_time_us_
.HasReceivedValue();
447 uint32
QuicConfig::ReceivedInitialRoundTripTimeUs() const {
448 return initial_round_trip_time_us_
.GetReceivedValue();
451 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
452 return initial_round_trip_time_us_
.HasSendValue();
455 uint32
QuicConfig::GetInitialRoundTripTimeUsToSend() const {
456 return initial_round_trip_time_us_
.GetSendValue();
459 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes
) {
460 if (window_bytes
< kMinimumFlowControlSendWindow
) {
461 LOG(DFATAL
) << "Initial stream flow control receive window ("
462 << window_bytes
<< ") cannot be set lower than default ("
463 << kMinimumFlowControlSendWindow
<< ").";
464 window_bytes
= kMinimumFlowControlSendWindow
;
466 initial_stream_flow_control_window_bytes_
.SetSendValue(window_bytes
);
469 uint32
QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
470 return initial_stream_flow_control_window_bytes_
.GetSendValue();
473 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
474 return initial_stream_flow_control_window_bytes_
.HasReceivedValue();
477 uint32
QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
478 return initial_stream_flow_control_window_bytes_
.GetReceivedValue();
481 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes
) {
482 if (window_bytes
< kMinimumFlowControlSendWindow
) {
483 LOG(DFATAL
) << "Initial session flow control receive window ("
484 << window_bytes
<< ") cannot be set lower than default ("
485 << kMinimumFlowControlSendWindow
<< ").";
486 window_bytes
= kMinimumFlowControlSendWindow
;
488 initial_session_flow_control_window_bytes_
.SetSendValue(window_bytes
);
491 uint32
QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
492 return initial_session_flow_control_window_bytes_
.GetSendValue();
495 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
496 return initial_session_flow_control_window_bytes_
.HasReceivedValue();
499 uint32
QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
500 return initial_session_flow_control_window_bytes_
.GetReceivedValue();
503 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window
) {
504 socket_receive_buffer_
.SetSendValue(tcp_receive_window
);
507 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
508 return socket_receive_buffer_
.HasReceivedValue();
511 uint32
QuicConfig::ReceivedSocketReceiveBuffer() const {
512 return socket_receive_buffer_
.GetReceivedValue();
515 bool QuicConfig::negotiated() const {
516 // TODO(ianswett): Add the negotiated parameters once and iterate over all
517 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
518 // ProcessServerHello.
519 return idle_connection_state_lifetime_seconds_
.negotiated() &&
520 max_streams_per_connection_
.negotiated();
523 void QuicConfig::SetDefaults() {
524 QuicTagVector congestion_feedback
;
525 // TODO(alyssar) stop sending this once QUIC_VERSION_23 is sunset.
526 // This field was required until version 22 was removed but by the time
527 // QUIC_VERSION_23 is sunset, no users of QUIC_VERSION_24 should be expecting
529 congestion_feedback
.push_back(kQBIC
);
530 congestion_feedback_
.set(congestion_feedback
, kQBIC
);
531 idle_connection_state_lifetime_seconds_
.set(kMaximumIdleTimeoutSecs
,
532 kDefaultIdleTimeoutSecs
);
533 silent_close_
.set(1, 0);
534 SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection
,
535 kDefaultMaxStreamsPerConnection
);
536 max_time_before_crypto_handshake_
=
537 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs
);
538 max_idle_time_before_crypto_handshake_
=
539 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs
);
540 max_undecryptable_packets_
= kDefaultMaxUndecryptablePackets
;
542 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow
);
543 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow
);
546 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
547 congestion_feedback_
.ToHandshakeMessage(out
);
548 idle_connection_state_lifetime_seconds_
.ToHandshakeMessage(out
);
549 silent_close_
.ToHandshakeMessage(out
);
550 max_streams_per_connection_
.ToHandshakeMessage(out
);
551 bytes_for_connection_id_
.ToHandshakeMessage(out
);
552 initial_round_trip_time_us_
.ToHandshakeMessage(out
);
553 initial_stream_flow_control_window_bytes_
.ToHandshakeMessage(out
);
554 initial_session_flow_control_window_bytes_
.ToHandshakeMessage(out
);
555 socket_receive_buffer_
.ToHandshakeMessage(out
);
556 connection_options_
.ToHandshakeMessage(out
);
559 QuicErrorCode
QuicConfig::ProcessPeerHello(
560 const CryptoHandshakeMessage
& peer_hello
,
561 HelloType hello_type
,
562 string
* error_details
) {
563 DCHECK(error_details
!= nullptr);
565 QuicErrorCode error
= QUIC_NO_ERROR
;
566 if (error
== QUIC_NO_ERROR
) {
567 error
= idle_connection_state_lifetime_seconds_
.ProcessPeerHello(
568 peer_hello
, hello_type
, error_details
);
570 if (error
== QUIC_NO_ERROR
) {
572 silent_close_
.ProcessPeerHello(peer_hello
, hello_type
, error_details
);
574 if (error
== QUIC_NO_ERROR
) {
575 error
= max_streams_per_connection_
.ProcessPeerHello(
576 peer_hello
, hello_type
, error_details
);
578 if (error
== QUIC_NO_ERROR
) {
579 error
= bytes_for_connection_id_
.ProcessPeerHello(
580 peer_hello
, hello_type
, error_details
);
582 if (error
== QUIC_NO_ERROR
) {
583 error
= initial_round_trip_time_us_
.ProcessPeerHello(
584 peer_hello
, hello_type
, error_details
);
586 if (error
== QUIC_NO_ERROR
) {
587 error
= initial_stream_flow_control_window_bytes_
.ProcessPeerHello(
588 peer_hello
, hello_type
, error_details
);
590 if (error
== QUIC_NO_ERROR
) {
591 error
= initial_session_flow_control_window_bytes_
.ProcessPeerHello(
592 peer_hello
, hello_type
, error_details
);
594 if (error
== QUIC_NO_ERROR
) {
595 error
= socket_receive_buffer_
.ProcessPeerHello(
596 peer_hello
, hello_type
, error_details
);
598 if (error
== QUIC_NO_ERROR
) {
599 error
= connection_options_
.ProcessPeerHello(
600 peer_hello
, hello_type
, error_details
);