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_sent_packet_manager.h"
13 #include "net/quic/quic_utils.h"
19 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
25 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
26 : QuicNegotiableValue(tag, presence),
31 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
32 DCHECK_LE(default_value, max);
34 default_value_ = default_value;
37 uint32 QuicNegotiableUint32::GetUint32() const {
39 return negotiated_value_;
41 return default_value_;
44 void QuicNegotiableUint32::ToHandshakeMessage(
45 CryptoHandshakeMessage* out) const {
47 out->SetValue(tag_, negotiated_value_);
49 out->SetValue(tag_, max_value_);
53 QuicErrorCode QuicNegotiableUint32::ReadUint32(
54 const CryptoHandshakeMessage& msg,
56 string* error_details) const {
57 DCHECK(error_details != NULL);
58 QuicErrorCode error = msg.GetUint32(tag_, out);
60 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
61 if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) {
62 *error_details = "Missing " + QuicUtils::TagToString(tag_);
65 error = QUIC_NO_ERROR;
66 *out = default_value_;
71 *error_details = "Bad " + QuicUtils::TagToString(tag_);
77 QuicErrorCode QuicNegotiableUint32::ProcessClientHello(
78 const CryptoHandshakeMessage& client_hello,
79 string* error_details) {
81 DCHECK(error_details != NULL);
83 QuicErrorCode error = ReadUint32(client_hello, &value, error_details);
84 if (error != QUIC_NO_ERROR) {
89 negotiated_value_ = std::min(value, max_value_);
94 QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
95 const CryptoHandshakeMessage& server_hello,
96 string* error_details) {
98 DCHECK(error_details != NULL);
100 QuicErrorCode error = ReadUint32(server_hello, &value, error_details);
101 if (error != QUIC_NO_ERROR) {
105 if (value > max_value_) {
106 *error_details = "Invalid value received for " +
107 QuicUtils::TagToString(tag_);
108 return QUIC_INVALID_NEGOTIATED_VALUE;
112 negotiated_value_ = value;
113 return QUIC_NO_ERROR;
116 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
117 : QuicNegotiableValue(tag, presence),
122 QuicNegotiableTag::~QuicNegotiableTag() {}
124 void QuicNegotiableTag::set(const QuicTagVector& possible,
125 QuicTag default_value) {
126 DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
128 possible_values_ = possible;
129 default_value_ = default_value;
132 QuicTag QuicNegotiableTag::GetTag() const {
134 return negotiated_tag_;
136 return default_value_;
139 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
141 // Because of the way we serialize and parse handshake messages we can
142 // serialize this as value and still parse it as a vector.
143 out->SetValue(tag_, negotiated_tag_);
145 out->SetVector(tag_, possible_values_);
149 QuicErrorCode QuicNegotiableTag::ReadVector(
150 const CryptoHandshakeMessage& msg,
153 string* error_details) const {
154 DCHECK(error_details != NULL);
155 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
157 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
158 if (presence_ == PRESENCE_REQUIRED) {
159 *error_details = "Missing " + QuicUtils::TagToString(tag_);
162 error = QUIC_NO_ERROR;
164 *out = &default_value_;
169 *error_details = "Bad " + QuicUtils::TagToString(tag_);
175 QuicErrorCode QuicNegotiableTag::ProcessClientHello(
176 const CryptoHandshakeMessage& client_hello,
177 string* error_details) {
178 DCHECK(!negotiated_);
179 DCHECK(error_details != NULL);
180 const QuicTag* received_tags;
181 size_t received_tags_length;
182 QuicErrorCode error = ReadVector(client_hello, &received_tags,
183 &received_tags_length, error_details);
184 if (error != QUIC_NO_ERROR) {
188 QuicTag negotiated_tag;
189 if (!QuicUtils::FindMutualTag(possible_values_,
191 received_tags_length,
192 QuicUtils::LOCAL_PRIORITY,
195 *error_details = "Unsuported " + QuicUtils::TagToString(tag_);
196 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
200 negotiated_tag_ = negotiated_tag;
201 return QUIC_NO_ERROR;
204 QuicErrorCode QuicNegotiableTag::ProcessServerHello(
205 const CryptoHandshakeMessage& server_hello,
206 string* error_details) {
207 DCHECK(!negotiated_);
208 DCHECK(error_details != NULL);
209 const QuicTag* received_tags;
210 size_t received_tags_length;
211 QuicErrorCode error = ReadVector(server_hello, &received_tags,
212 &received_tags_length, error_details);
213 if (error != QUIC_NO_ERROR) {
217 if (received_tags_length != 1 ||
218 std::find(possible_values_.begin(), possible_values_.end(),
219 *received_tags) == possible_values_.end()) {
220 *error_details = "Invalid " + QuicUtils::TagToString(tag_);
221 return QUIC_INVALID_NEGOTIATED_VALUE;
225 negotiated_tag_ = *received_tags;
226 return QUIC_NO_ERROR;
229 QuicConfig::QuicConfig() :
230 congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED),
231 idle_connection_state_lifetime_seconds_(
232 kICSL, QuicNegotiableValue::PRESENCE_REQUIRED),
233 keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL),
234 max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED),
235 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
236 server_initial_congestion_window_(
237 kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL),
238 initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) {
239 // All optional non-zero parameters should be initialized here.
240 server_initial_congestion_window_.set(kMaxInitialWindow,
241 kDefaultInitialWindow);
244 QuicConfig::~QuicConfig() {}
246 void QuicConfig::set_congestion_control(
247 const QuicTagVector& congestion_control,
248 QuicTag default_congestion_control) {
249 congestion_control_.set(congestion_control, default_congestion_control);
252 QuicTag QuicConfig::congestion_control() const {
253 return congestion_control_.GetTag();
256 void QuicConfig::set_idle_connection_state_lifetime(
257 QuicTime::Delta max_idle_connection_state_lifetime,
258 QuicTime::Delta default_idle_conection_state_lifetime) {
259 idle_connection_state_lifetime_seconds_.set(
260 max_idle_connection_state_lifetime.ToSeconds(),
261 default_idle_conection_state_lifetime.ToSeconds());
264 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
265 return QuicTime::Delta::FromSeconds(
266 idle_connection_state_lifetime_seconds_.GetUint32());
269 QuicTime::Delta QuicConfig::keepalive_timeout() const {
270 return QuicTime::Delta::FromSeconds(
271 keepalive_timeout_seconds_.GetUint32());
274 void QuicConfig::set_max_streams_per_connection(size_t max_streams,
275 size_t default_streams) {
276 max_streams_per_connection_.set(max_streams, default_streams);
279 uint32 QuicConfig::max_streams_per_connection() const {
280 return max_streams_per_connection_.GetUint32();
283 void QuicConfig::set_max_time_before_crypto_handshake(
284 QuicTime::Delta max_time_before_crypto_handshake) {
285 max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
288 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
289 return max_time_before_crypto_handshake_;
292 void QuicConfig::set_server_initial_congestion_window(size_t max_initial_window,
293 size_t default_initial_window) {
294 server_initial_congestion_window_.set(max_initial_window,
295 default_initial_window);
298 uint32 QuicConfig::server_initial_congestion_window() const {
299 return server_initial_congestion_window_.GetUint32();
302 void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt,
303 size_t default_rtt) {
304 initial_round_trip_time_us_.set(max_rtt, default_rtt);
307 uint32 QuicConfig::initial_round_trip_time_us() const {
308 return initial_round_trip_time_us_.GetUint32();
311 bool QuicConfig::negotiated() {
312 // TODO(ianswett): Add the negotiated parameters once and iterate over all
313 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
314 // ProcessServerHello.
315 return congestion_control_.negotiated() &&
316 idle_connection_state_lifetime_seconds_.negotiated() &&
317 keepalive_timeout_seconds_.negotiated() &&
318 max_streams_per_connection_.negotiated() &&
319 server_initial_congestion_window_.negotiated() &&
320 initial_round_trip_time_us_.negotiated();
323 void QuicConfig::SetDefaults() {
324 QuicTagVector congestion_control;
325 if (FLAGS_enable_quic_pacing) {
326 congestion_control.push_back(kPACE);
328 congestion_control.push_back(kQBIC);
329 congestion_control_.set(congestion_control, kQBIC);
330 idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
331 kDefaultInitialTimeoutSecs);
332 // kKATO is optional. Return 0 if not negotiated.
333 keepalive_timeout_seconds_.set(0, 0);
334 max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
335 kDefaultMaxStreamsPerConnection);
336 max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
337 kDefaultMaxTimeForCryptoHandshakeSecs);
338 server_initial_congestion_window_.set(kDefaultInitialWindow,
339 kDefaultInitialWindow);
342 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
343 congestion_control_.ToHandshakeMessage(out);
344 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
345 keepalive_timeout_seconds_.ToHandshakeMessage(out);
346 max_streams_per_connection_.ToHandshakeMessage(out);
347 server_initial_congestion_window_.ToHandshakeMessage(out);
348 // TODO(ianswett): Don't transmit parameters which are optional and not set.
349 initial_round_trip_time_us_.ToHandshakeMessage(out);
352 QuicErrorCode QuicConfig::ProcessClientHello(
353 const CryptoHandshakeMessage& client_hello,
354 string* error_details) {
355 DCHECK(error_details != NULL);
357 QuicErrorCode error = QUIC_NO_ERROR;
358 if (error == QUIC_NO_ERROR) {
359 error = congestion_control_.ProcessClientHello(client_hello, error_details);
361 if (error == QUIC_NO_ERROR) {
362 error = idle_connection_state_lifetime_seconds_.ProcessClientHello(
363 client_hello, error_details);
365 if (error == QUIC_NO_ERROR) {
366 error = keepalive_timeout_seconds_.ProcessClientHello(
367 client_hello, error_details);
369 if (error == QUIC_NO_ERROR) {
370 error = max_streams_per_connection_.ProcessClientHello(
371 client_hello, error_details);
373 if (error == QUIC_NO_ERROR) {
374 error = server_initial_congestion_window_.ProcessClientHello(
375 client_hello, error_details);
377 if (error == QUIC_NO_ERROR) {
378 error = initial_round_trip_time_us_.ProcessClientHello(
379 client_hello, error_details);
384 QuicErrorCode QuicConfig::ProcessServerHello(
385 const CryptoHandshakeMessage& server_hello,
386 string* error_details) {
387 DCHECK(error_details != NULL);
389 QuicErrorCode error = QUIC_NO_ERROR;
390 if (error == QUIC_NO_ERROR) {
391 error = congestion_control_.ProcessServerHello(server_hello, error_details);
393 if (error == QUIC_NO_ERROR) {
394 error = idle_connection_state_lifetime_seconds_.ProcessServerHello(
395 server_hello, error_details);
397 if (error == QUIC_NO_ERROR) {
398 error = keepalive_timeout_seconds_.ProcessServerHello(
399 server_hello, error_details);
401 if (error == QUIC_NO_ERROR) {
402 error = max_streams_per_connection_.ProcessServerHello(
403 server_hello, error_details);
405 if (error == QUIC_NO_ERROR) {
406 error = server_initial_congestion_window_.ProcessServerHello(
407 server_hello, error_details);
409 if (error == QUIC_NO_ERROR) {
410 error = initial_round_trip_time_us_.ProcessServerHello(
411 server_hello, error_details);