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/quic_sent_packet_manager.h"
16 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag
, Presence presence
)
22 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag
, Presence presence
)
23 : QuicNegotiableValue(tag
, presence
),
28 void QuicNegotiableUint32::set(uint32 max
, uint32 default_value
) {
29 DCHECK_LE(default_value
, max
);
31 default_value_
= default_value
;
34 uint32
QuicNegotiableUint32::GetUint32() const {
36 return negotiated_value_
;
38 return default_value_
;
41 void QuicNegotiableUint32::ToHandshakeMessage(
42 CryptoHandshakeMessage
* out
) const {
44 out
->SetValue(tag_
, negotiated_value_
);
46 out
->SetValue(tag_
, max_value_
);
50 QuicErrorCode
QuicNegotiableUint32::ReadUint32(
51 const CryptoHandshakeMessage
& msg
,
53 string
* error_details
) const {
54 DCHECK(error_details
!= NULL
);
55 QuicErrorCode error
= msg
.GetUint32(tag_
, out
);
57 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
58 if (presence_
== QuicNegotiableValue::PRESENCE_REQUIRED
) {
59 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
62 error
= QUIC_NO_ERROR
;
63 *out
= default_value_
;
68 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
74 QuicErrorCode
QuicNegotiableUint32::ProcessClientHello(
75 const CryptoHandshakeMessage
& client_hello
,
76 string
* error_details
) {
78 DCHECK(error_details
!= NULL
);
80 QuicErrorCode error
= ReadUint32(client_hello
, &value
, error_details
);
81 if (error
!= QUIC_NO_ERROR
) {
86 negotiated_value_
= std::min(value
, max_value_
);
91 QuicErrorCode
QuicNegotiableUint32::ProcessServerHello(
92 const CryptoHandshakeMessage
& server_hello
,
93 string
* error_details
) {
95 DCHECK(error_details
!= NULL
);
97 QuicErrorCode error
= ReadUint32(server_hello
, &value
, error_details
);
98 if (error
!= QUIC_NO_ERROR
) {
102 if (value
> max_value_
) {
103 *error_details
= "Invalid value received for " +
104 QuicUtils::TagToString(tag_
);
105 return QUIC_INVALID_NEGOTIATED_VALUE
;
109 negotiated_value_
= value
;
110 return QUIC_NO_ERROR
;
113 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag
, Presence presence
)
114 : QuicNegotiableValue(tag
, presence
),
119 QuicNegotiableTag::~QuicNegotiableTag() {}
121 void QuicNegotiableTag::set(const QuicTagVector
& possible
,
122 QuicTag default_value
) {
123 DCHECK(std::find(possible
.begin(), possible
.end(), default_value
) !=
125 possible_values_
= possible
;
126 default_value_
= default_value
;
129 QuicTag
QuicNegotiableTag::GetTag() const {
131 return negotiated_tag_
;
133 return 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
!= NULL
);
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::ProcessClientHello(
173 const CryptoHandshakeMessage
& client_hello
,
174 string
* error_details
) {
175 DCHECK(!negotiated_
);
176 DCHECK(error_details
!= NULL
);
177 const QuicTag
* received_tags
;
178 size_t received_tags_length
;
179 QuicErrorCode error
= ReadVector(client_hello
, &received_tags
,
180 &received_tags_length
, error_details
);
181 if (error
!= QUIC_NO_ERROR
) {
185 QuicTag negotiated_tag
;
186 if (!QuicUtils::FindMutualTag(possible_values_
,
188 received_tags_length
,
189 QuicUtils::LOCAL_PRIORITY
,
192 *error_details
= "Unsuported " + QuicUtils::TagToString(tag_
);
193 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP
;
197 negotiated_tag_
= negotiated_tag
;
198 return QUIC_NO_ERROR
;
201 QuicErrorCode
QuicNegotiableTag::ProcessServerHello(
202 const CryptoHandshakeMessage
& server_hello
,
203 string
* error_details
) {
204 DCHECK(!negotiated_
);
205 DCHECK(error_details
!= NULL
);
206 const QuicTag
* received_tags
;
207 size_t received_tags_length
;
208 QuicErrorCode error
= ReadVector(server_hello
, &received_tags
,
209 &received_tags_length
, error_details
);
210 if (error
!= QUIC_NO_ERROR
) {
214 if (received_tags_length
!= 1 ||
215 std::find(possible_values_
.begin(), possible_values_
.end(),
216 *received_tags
) == possible_values_
.end()) {
217 *error_details
= "Invalid " + QuicUtils::TagToString(tag_
);
218 return QUIC_INVALID_NEGOTIATED_VALUE
;
222 negotiated_tag_
= *received_tags
;
223 return QUIC_NO_ERROR
;
226 QuicConfig::QuicConfig() :
227 congestion_control_(kCGST
, QuicNegotiableValue::PRESENCE_REQUIRED
),
228 idle_connection_state_lifetime_seconds_(
229 kICSL
, QuicNegotiableValue::PRESENCE_REQUIRED
),
230 keepalive_timeout_seconds_(kKATO
, QuicNegotiableValue::PRESENCE_OPTIONAL
),
231 max_streams_per_connection_(kMSPC
, QuicNegotiableValue::PRESENCE_REQUIRED
),
232 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
233 server_initial_congestion_window_(
234 kSWND
, QuicNegotiableValue::PRESENCE_OPTIONAL
),
235 initial_round_trip_time_us_(kIRTT
, QuicNegotiableValue::PRESENCE_OPTIONAL
) {
236 // All optional non-zero parameters should be initialized here.
237 server_initial_congestion_window_
.set(kMaxInitialWindow
,
238 kDefaultInitialWindow
);
241 QuicConfig::~QuicConfig() {}
243 void QuicConfig::set_congestion_control(
244 const QuicTagVector
& congestion_control
,
245 QuicTag default_congestion_control
) {
246 congestion_control_
.set(congestion_control
, default_congestion_control
);
249 QuicTag
QuicConfig::congestion_control() const {
250 return congestion_control_
.GetTag();
253 void QuicConfig::set_idle_connection_state_lifetime(
254 QuicTime::Delta max_idle_connection_state_lifetime
,
255 QuicTime::Delta default_idle_conection_state_lifetime
) {
256 idle_connection_state_lifetime_seconds_
.set(
257 max_idle_connection_state_lifetime
.ToSeconds(),
258 default_idle_conection_state_lifetime
.ToSeconds());
261 QuicTime::Delta
QuicConfig::idle_connection_state_lifetime() const {
262 return QuicTime::Delta::FromSeconds(
263 idle_connection_state_lifetime_seconds_
.GetUint32());
266 QuicTime::Delta
QuicConfig::keepalive_timeout() const {
267 return QuicTime::Delta::FromSeconds(
268 keepalive_timeout_seconds_
.GetUint32());
271 void QuicConfig::set_max_streams_per_connection(size_t max_streams
,
272 size_t default_streams
) {
273 max_streams_per_connection_
.set(max_streams
, default_streams
);
276 uint32
QuicConfig::max_streams_per_connection() const {
277 return max_streams_per_connection_
.GetUint32();
280 void QuicConfig::set_max_time_before_crypto_handshake(
281 QuicTime::Delta max_time_before_crypto_handshake
) {
282 max_time_before_crypto_handshake_
= max_time_before_crypto_handshake
;
285 QuicTime::Delta
QuicConfig::max_time_before_crypto_handshake() const {
286 return max_time_before_crypto_handshake_
;
289 void QuicConfig::set_server_initial_congestion_window(size_t max_initial_window
,
290 size_t default_initial_window
) {
291 server_initial_congestion_window_
.set(max_initial_window
,
292 default_initial_window
);
295 uint32
QuicConfig::server_initial_congestion_window() const {
296 return server_initial_congestion_window_
.GetUint32();
299 void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt
,
300 size_t default_rtt
) {
301 initial_round_trip_time_us_
.set(max_rtt
, default_rtt
);
304 uint32
QuicConfig::initial_round_trip_time_us() const {
305 return initial_round_trip_time_us_
.GetUint32();
308 bool QuicConfig::negotiated() {
309 // TODO(ianswett): Add the negotiated parameters once and iterate over all
310 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
311 // ProcessServerHello.
312 return congestion_control_
.negotiated() &&
313 idle_connection_state_lifetime_seconds_
.negotiated() &&
314 keepalive_timeout_seconds_
.negotiated() &&
315 max_streams_per_connection_
.negotiated() &&
316 server_initial_congestion_window_
.negotiated() &&
317 initial_round_trip_time_us_
.negotiated();
320 void QuicConfig::SetDefaults() {
321 QuicTagVector congestion_control
;
322 if (FLAGS_enable_quic_pacing
) {
323 congestion_control
.push_back(kPACE
);
325 congestion_control
.push_back(kQBIC
);
326 congestion_control_
.set(congestion_control
, kQBIC
);
327 idle_connection_state_lifetime_seconds_
.set(kDefaultTimeoutSecs
,
328 kDefaultInitialTimeoutSecs
);
329 // kKATO is optional. Return 0 if not negotiated.
330 keepalive_timeout_seconds_
.set(0, 0);
331 max_streams_per_connection_
.set(kDefaultMaxStreamsPerConnection
,
332 kDefaultMaxStreamsPerConnection
);
333 max_time_before_crypto_handshake_
= QuicTime::Delta::FromSeconds(
334 kDefaultMaxTimeForCryptoHandshakeSecs
);
335 server_initial_congestion_window_
.set(kDefaultInitialWindow
,
336 kDefaultInitialWindow
);
339 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
340 congestion_control_
.ToHandshakeMessage(out
);
341 idle_connection_state_lifetime_seconds_
.ToHandshakeMessage(out
);
342 keepalive_timeout_seconds_
.ToHandshakeMessage(out
);
343 max_streams_per_connection_
.ToHandshakeMessage(out
);
344 server_initial_congestion_window_
.ToHandshakeMessage(out
);
345 // TODO(ianswett): Don't transmit parameters which are optional and not set.
346 initial_round_trip_time_us_
.ToHandshakeMessage(out
);
349 QuicErrorCode
QuicConfig::ProcessClientHello(
350 const CryptoHandshakeMessage
& client_hello
,
351 string
* error_details
) {
352 DCHECK(error_details
!= NULL
);
354 QuicErrorCode error
= QUIC_NO_ERROR
;
355 if (error
== QUIC_NO_ERROR
) {
356 error
= congestion_control_
.ProcessClientHello(client_hello
, error_details
);
358 if (error
== QUIC_NO_ERROR
) {
359 error
= idle_connection_state_lifetime_seconds_
.ProcessClientHello(
360 client_hello
, error_details
);
362 if (error
== QUIC_NO_ERROR
) {
363 error
= keepalive_timeout_seconds_
.ProcessClientHello(
364 client_hello
, error_details
);
366 if (error
== QUIC_NO_ERROR
) {
367 error
= max_streams_per_connection_
.ProcessClientHello(
368 client_hello
, error_details
);
370 if (error
== QUIC_NO_ERROR
) {
371 error
= server_initial_congestion_window_
.ProcessClientHello(
372 client_hello
, error_details
);
374 if (error
== QUIC_NO_ERROR
) {
375 error
= initial_round_trip_time_us_
.ProcessClientHello(
376 client_hello
, error_details
);
381 QuicErrorCode
QuicConfig::ProcessServerHello(
382 const CryptoHandshakeMessage
& server_hello
,
383 string
* error_details
) {
384 DCHECK(error_details
!= NULL
);
386 QuicErrorCode error
= QUIC_NO_ERROR
;
387 if (error
== QUIC_NO_ERROR
) {
388 error
= congestion_control_
.ProcessServerHello(server_hello
, error_details
);
390 if (error
== QUIC_NO_ERROR
) {
391 error
= idle_connection_state_lifetime_seconds_
.ProcessServerHello(
392 server_hello
, error_details
);
394 if (error
== QUIC_NO_ERROR
) {
395 error
= keepalive_timeout_seconds_
.ProcessServerHello(
396 server_hello
, error_details
);
398 if (error
== QUIC_NO_ERROR
) {
399 error
= max_streams_per_connection_
.ProcessServerHello(
400 server_hello
, error_details
);
402 if (error
== QUIC_NO_ERROR
) {
403 error
= server_initial_congestion_window_
.ProcessServerHello(
404 server_hello
, error_details
);
406 if (error
== QUIC_NO_ERROR
) {
407 error
= initial_round_trip_time_us_
.ProcessServerHello(
408 server_hello
, error_details
);