rAc - revert invalid suggestions to edit mode
[chromium-blink-merge.git] / net / quic / quic_config.cc
blob86a37b32d6d93ec96201cdb0a4d06b21c126f41c
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_sent_packet_manager.h"
13 #include "net/quic/quic_utils.h"
15 using std::string;
17 namespace net {
19 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
20 : tag_(tag),
21 presence_(presence),
22 negotiated_(false) {
25 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
26 : QuicNegotiableValue(tag, presence),
27 max_value_(0),
28 default_value_(0) {
31 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
32 DCHECK_LE(default_value, max);
33 max_value_ = max;
34 default_value_ = default_value;
37 uint32 QuicNegotiableUint32::GetUint32() const {
38 if (negotiated_) {
39 return negotiated_value_;
41 return default_value_;
44 void QuicNegotiableUint32::ToHandshakeMessage(
45 CryptoHandshakeMessage* out) const {
46 if (negotiated_) {
47 out->SetValue(tag_, negotiated_value_);
48 } else {
49 out->SetValue(tag_, max_value_);
53 QuicErrorCode QuicNegotiableUint32::ReadUint32(
54 const CryptoHandshakeMessage& msg,
55 uint32* out,
56 string* error_details) const {
57 DCHECK(error_details != NULL);
58 QuicErrorCode error = msg.GetUint32(tag_, out);
59 switch (error) {
60 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
61 if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) {
62 *error_details = "Missing " + QuicUtils::TagToString(tag_);
63 break;
65 error = QUIC_NO_ERROR;
66 *out = default_value_;
68 case QUIC_NO_ERROR:
69 break;
70 default:
71 *error_details = "Bad " + QuicUtils::TagToString(tag_);
72 break;
74 return error;
77 QuicErrorCode QuicNegotiableUint32::ProcessClientHello(
78 const CryptoHandshakeMessage& client_hello,
79 string* error_details) {
80 DCHECK(!negotiated_);
81 DCHECK(error_details != NULL);
82 uint32 value;
83 QuicErrorCode error = ReadUint32(client_hello, &value, error_details);
84 if (error != QUIC_NO_ERROR) {
85 return error;
88 negotiated_ = true;
89 negotiated_value_ = std::min(value, max_value_);
91 return QUIC_NO_ERROR;
94 QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
95 const CryptoHandshakeMessage& server_hello,
96 string* error_details) {
97 DCHECK(!negotiated_);
98 DCHECK(error_details != NULL);
99 uint32 value;
100 QuicErrorCode error = ReadUint32(server_hello, &value, error_details);
101 if (error != QUIC_NO_ERROR) {
102 return error;
105 if (value > max_value_) {
106 *error_details = "Invalid value received for " +
107 QuicUtils::TagToString(tag_);
108 return QUIC_INVALID_NEGOTIATED_VALUE;
111 negotiated_ = true;
112 negotiated_value_ = value;
113 return QUIC_NO_ERROR;
116 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
117 : QuicNegotiableValue(tag, presence),
118 negotiated_tag_(0),
119 default_value_(0) {
122 QuicNegotiableTag::~QuicNegotiableTag() {}
124 void QuicNegotiableTag::set(const QuicTagVector& possible,
125 QuicTag default_value) {
126 DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
127 possible.end());
128 possible_values_ = possible;
129 default_value_ = default_value;
132 QuicTag QuicNegotiableTag::GetTag() const {
133 if (negotiated_) {
134 return negotiated_tag_;
136 return default_value_;
139 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
140 if (negotiated_) {
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_);
144 } else {
145 out->SetVector(tag_, possible_values_);
149 QuicErrorCode QuicNegotiableTag::ReadVector(
150 const CryptoHandshakeMessage& msg,
151 const QuicTag** out,
152 size_t* out_length,
153 string* error_details) const {
154 DCHECK(error_details != NULL);
155 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
156 switch (error) {
157 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
158 if (presence_ == PRESENCE_REQUIRED) {
159 *error_details = "Missing " + QuicUtils::TagToString(tag_);
160 break;
162 error = QUIC_NO_ERROR;
163 *out_length = 1;
164 *out = &default_value_;
166 case QUIC_NO_ERROR:
167 break;
168 default:
169 *error_details = "Bad " + QuicUtils::TagToString(tag_);
170 break;
172 return error;
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) {
185 return error;
188 QuicTag negotiated_tag;
189 if (!QuicUtils::FindMutualTag(possible_values_,
190 received_tags,
191 received_tags_length,
192 QuicUtils::LOCAL_PRIORITY,
193 &negotiated_tag,
194 NULL)) {
195 *error_details = "Unsuported " + QuicUtils::TagToString(tag_);
196 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
199 negotiated_ = true;
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) {
214 return 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;
224 negotiated_ = true;
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::EnablePacing(bool enable_pacing) {
343 QuicTagVector congestion_control;
344 if (enable_pacing) {
345 congestion_control.push_back(kPACE);
347 congestion_control.push_back(kQBIC);
348 congestion_control_.set(congestion_control, kQBIC);
351 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
352 congestion_control_.ToHandshakeMessage(out);
353 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
354 keepalive_timeout_seconds_.ToHandshakeMessage(out);
355 max_streams_per_connection_.ToHandshakeMessage(out);
356 server_initial_congestion_window_.ToHandshakeMessage(out);
357 // TODO(ianswett): Don't transmit parameters which are optional and not set.
358 initial_round_trip_time_us_.ToHandshakeMessage(out);
361 QuicErrorCode QuicConfig::ProcessClientHello(
362 const CryptoHandshakeMessage& client_hello,
363 string* error_details) {
364 DCHECK(error_details != NULL);
366 QuicErrorCode error = QUIC_NO_ERROR;
367 if (error == QUIC_NO_ERROR) {
368 error = congestion_control_.ProcessClientHello(client_hello, error_details);
370 if (error == QUIC_NO_ERROR) {
371 error = idle_connection_state_lifetime_seconds_.ProcessClientHello(
372 client_hello, error_details);
374 if (error == QUIC_NO_ERROR) {
375 error = keepalive_timeout_seconds_.ProcessClientHello(
376 client_hello, error_details);
378 if (error == QUIC_NO_ERROR) {
379 error = max_streams_per_connection_.ProcessClientHello(
380 client_hello, error_details);
382 if (error == QUIC_NO_ERROR) {
383 error = server_initial_congestion_window_.ProcessClientHello(
384 client_hello, error_details);
386 if (error == QUIC_NO_ERROR) {
387 error = initial_round_trip_time_us_.ProcessClientHello(
388 client_hello, error_details);
390 return error;
393 QuicErrorCode QuicConfig::ProcessServerHello(
394 const CryptoHandshakeMessage& server_hello,
395 string* error_details) {
396 DCHECK(error_details != NULL);
398 QuicErrorCode error = QUIC_NO_ERROR;
399 if (error == QUIC_NO_ERROR) {
400 error = congestion_control_.ProcessServerHello(server_hello, error_details);
402 if (error == QUIC_NO_ERROR) {
403 error = idle_connection_state_lifetime_seconds_.ProcessServerHello(
404 server_hello, error_details);
406 if (error == QUIC_NO_ERROR) {
407 error = keepalive_timeout_seconds_.ProcessServerHello(
408 server_hello, error_details);
410 if (error == QUIC_NO_ERROR) {
411 error = max_streams_per_connection_.ProcessServerHello(
412 server_hello, error_details);
414 if (error == QUIC_NO_ERROR) {
415 error = server_initial_congestion_window_.ProcessServerHello(
416 server_hello, error_details);
418 if (error == QUIC_NO_ERROR) {
419 error = initial_round_trip_time_us_.ProcessServerHello(
420 server_hello, error_details);
422 return error;
425 } // namespace net