OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/quic_config.h" | 5 #include "net/quic/quic_config.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "net/quic/crypto/crypto_handshake_message.h" | 10 #include "net/quic/crypto/crypto_handshake_message.h" |
11 #include "net/quic/crypto/crypto_protocol.h" | 11 #include "net/quic/crypto/crypto_protocol.h" |
12 #include "net/quic/quic_sent_packet_manager.h" | 12 #include "net/quic/quic_sent_packet_manager.h" |
13 #include "net/quic/quic_utils.h" | 13 #include "net/quic/quic_utils.h" |
14 | 14 |
15 using std::string; | 15 using std::string; |
16 | 16 |
17 namespace net { | 17 namespace net { |
18 | 18 |
19 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence) | 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, |
| 23 QuicTag tag, |
| 24 QuicConfigPresence presence, |
| 25 uint32 default_value, |
| 26 uint32* out, |
| 27 string* error_details) { |
| 28 DCHECK(error_details != NULL); |
| 29 QuicErrorCode error = msg.GetUint32(tag, out); |
| 30 switch (error) { |
| 31 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: |
| 32 if (presence == PRESENCE_REQUIRED) { |
| 33 *error_details = "Missing " + QuicUtils::TagToString(tag); |
| 34 break; |
| 35 } |
| 36 error = QUIC_NO_ERROR; |
| 37 *out = default_value; |
| 38 break; |
| 39 case QUIC_NO_ERROR: |
| 40 break; |
| 41 default: |
| 42 *error_details = "Bad " + QuicUtils::TagToString(tag); |
| 43 break; |
| 44 } |
| 45 return error; |
| 46 } |
| 47 |
| 48 |
| 49 QuicConfigValue::QuicConfigValue(QuicTag tag, |
| 50 QuicConfigPresence presence) |
20 : tag_(tag), | 51 : tag_(tag), |
21 presence_(presence), | 52 presence_(presence) { |
| 53 } |
| 54 QuicConfigValue::~QuicConfigValue() {} |
| 55 |
| 56 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, |
| 57 QuicConfigPresence presence) |
| 58 : QuicConfigValue(tag, presence), |
22 negotiated_(false) { | 59 negotiated_(false) { |
23 } | 60 } |
| 61 QuicNegotiableValue::~QuicNegotiableValue() {} |
24 | 62 |
25 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence) | 63 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, |
| 64 QuicConfigPresence presence) |
26 : QuicNegotiableValue(tag, presence), | 65 : QuicNegotiableValue(tag, presence), |
27 max_value_(0), | 66 max_value_(0), |
28 default_value_(0) { | 67 default_value_(0) { |
29 } | 68 } |
| 69 QuicNegotiableUint32::~QuicNegotiableUint32() {} |
30 | 70 |
31 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { | 71 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { |
32 DCHECK_LE(default_value, max); | 72 DCHECK_LE(default_value, max); |
33 max_value_ = max; | 73 max_value_ = max; |
34 default_value_ = default_value; | 74 default_value_ = default_value; |
35 } | 75 } |
36 | 76 |
37 uint32 QuicNegotiableUint32::GetUint32() const { | 77 uint32 QuicNegotiableUint32::GetUint32() const { |
38 if (negotiated_) { | 78 if (negotiated_) { |
39 return negotiated_value_; | 79 return negotiated_value_; |
40 } | 80 } |
41 return default_value_; | 81 return default_value_; |
42 } | 82 } |
43 | 83 |
44 void QuicNegotiableUint32::ToHandshakeMessage( | 84 void QuicNegotiableUint32::ToHandshakeMessage( |
45 CryptoHandshakeMessage* out) const { | 85 CryptoHandshakeMessage* out) const { |
46 if (negotiated_) { | 86 if (negotiated_) { |
47 out->SetValue(tag_, negotiated_value_); | 87 out->SetValue(tag_, negotiated_value_); |
48 } else { | 88 } else { |
49 out->SetValue(tag_, max_value_); | 89 out->SetValue(tag_, max_value_); |
50 } | 90 } |
51 } | 91 } |
52 | 92 |
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; | |
64 } | |
65 error = QUIC_NO_ERROR; | |
66 *out = default_value_; | |
67 | |
68 case QUIC_NO_ERROR: | |
69 break; | |
70 default: | |
71 *error_details = "Bad " + QuicUtils::TagToString(tag_); | |
72 break; | |
73 } | |
74 return error; | |
75 } | |
76 | |
77 QuicErrorCode QuicNegotiableUint32::ProcessClientHello( | 93 QuicErrorCode QuicNegotiableUint32::ProcessClientHello( |
78 const CryptoHandshakeMessage& client_hello, | 94 const CryptoHandshakeMessage& client_hello, |
79 string* error_details) { | 95 string* error_details) { |
80 DCHECK(!negotiated_); | 96 DCHECK(!negotiated_); |
81 DCHECK(error_details != NULL); | 97 DCHECK(error_details != NULL); |
82 uint32 value; | 98 uint32 value; |
83 QuicErrorCode error = ReadUint32(client_hello, &value, error_details); | 99 QuicErrorCode error = ReadUint32(client_hello, |
| 100 tag_, |
| 101 presence_, |
| 102 default_value_, |
| 103 &value, |
| 104 error_details); |
84 if (error != QUIC_NO_ERROR) { | 105 if (error != QUIC_NO_ERROR) { |
85 return error; | 106 return error; |
86 } | 107 } |
87 | |
88 negotiated_ = true; | 108 negotiated_ = true; |
89 negotiated_value_ = std::min(value, max_value_); | 109 negotiated_value_ = std::min(value, max_value_); |
90 | 110 |
91 return QUIC_NO_ERROR; | 111 return QUIC_NO_ERROR; |
92 } | 112 } |
93 | 113 |
94 QuicErrorCode QuicNegotiableUint32::ProcessServerHello( | 114 QuicErrorCode QuicNegotiableUint32::ProcessServerHello( |
95 const CryptoHandshakeMessage& server_hello, | 115 const CryptoHandshakeMessage& server_hello, |
96 string* error_details) { | 116 string* error_details) { |
97 DCHECK(!negotiated_); | 117 DCHECK(!negotiated_); |
98 DCHECK(error_details != NULL); | 118 DCHECK(error_details != NULL); |
99 uint32 value; | 119 uint32 value; |
100 QuicErrorCode error = ReadUint32(server_hello, &value, error_details); | 120 QuicErrorCode error = ReadUint32(server_hello, |
| 121 tag_, |
| 122 presence_, |
| 123 max_value_, |
| 124 &value, |
| 125 error_details); |
101 if (error != QUIC_NO_ERROR) { | 126 if (error != QUIC_NO_ERROR) { |
102 return error; | 127 return error; |
103 } | 128 } |
104 | 129 |
105 if (value > max_value_) { | 130 if (value > max_value_) { |
106 *error_details = "Invalid value received for " + | 131 *error_details = "Invalid value received for " + |
107 QuicUtils::TagToString(tag_); | 132 QuicUtils::TagToString(tag_); |
108 return QUIC_INVALID_NEGOTIATED_VALUE; | 133 return QUIC_INVALID_NEGOTIATED_VALUE; |
109 } | 134 } |
110 | 135 |
111 negotiated_ = true; | 136 negotiated_ = true; |
112 negotiated_value_ = value; | 137 negotiated_value_ = value; |
113 return QUIC_NO_ERROR; | 138 return QUIC_NO_ERROR; |
114 } | 139 } |
115 | 140 |
116 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence) | 141 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence) |
117 : QuicNegotiableValue(tag, presence), | 142 : QuicNegotiableValue(tag, presence), |
118 negotiated_tag_(0), | 143 negotiated_tag_(0), |
119 default_value_(0) { | 144 default_value_(0) { |
120 } | 145 } |
121 | 146 |
122 QuicNegotiableTag::~QuicNegotiableTag() {} | 147 QuicNegotiableTag::~QuicNegotiableTag() {} |
123 | 148 |
124 void QuicNegotiableTag::set(const QuicTagVector& possible, | 149 void QuicNegotiableTag::set(const QuicTagVector& possible, |
125 QuicTag default_value) { | 150 QuicTag default_value) { |
126 DCHECK(std::find(possible.begin(), possible.end(), default_value) != | 151 DCHECK(std::find(possible.begin(), possible.end(), default_value) != |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 *received_tags) == possible_values_.end()) { | 244 *received_tags) == possible_values_.end()) { |
220 *error_details = "Invalid " + QuicUtils::TagToString(tag_); | 245 *error_details = "Invalid " + QuicUtils::TagToString(tag_); |
221 return QUIC_INVALID_NEGOTIATED_VALUE; | 246 return QUIC_INVALID_NEGOTIATED_VALUE; |
222 } | 247 } |
223 | 248 |
224 negotiated_ = true; | 249 negotiated_ = true; |
225 negotiated_tag_ = *received_tags; | 250 negotiated_tag_ = *received_tags; |
226 return QUIC_NO_ERROR; | 251 return QUIC_NO_ERROR; |
227 } | 252 } |
228 | 253 |
229 QuicConfig::QuicConfig() : | 254 QuicFixedUint32::QuicFixedUint32(QuicTag tag, |
230 congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED), | 255 QuicConfigPresence presence, |
231 idle_connection_state_lifetime_seconds_( | 256 uint32 default_value) |
232 kICSL, QuicNegotiableValue::PRESENCE_REQUIRED), | 257 : QuicConfigValue(tag, presence), |
233 keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL), | 258 value_(default_value) { |
234 max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED), | 259 } |
235 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()), | 260 QuicFixedUint32::~QuicFixedUint32() {} |
236 server_initial_congestion_window_( | 261 |
237 kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL), | 262 uint32 QuicFixedUint32::GetUint32() const { |
238 initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) { | 263 return value_; |
| 264 } |
| 265 |
| 266 void QuicFixedUint32::ToHandshakeMessage( |
| 267 CryptoHandshakeMessage* out) const { |
| 268 out->SetValue(tag_, value_); |
| 269 } |
| 270 |
| 271 QuicErrorCode QuicFixedUint32::ProcessClientHello( |
| 272 const CryptoHandshakeMessage& client_hello, |
| 273 string* error_details) { |
| 274 DCHECK(error_details != NULL); |
| 275 QuicErrorCode error = |
| 276 ReadUint32(client_hello, tag_, presence_, value_, &value_, error_details); |
| 277 if (error != QUIC_NO_ERROR) { |
| 278 return error; |
| 279 } |
| 280 return QUIC_NO_ERROR; |
| 281 } |
| 282 |
| 283 QuicErrorCode QuicFixedUint32::ProcessServerHello( |
| 284 const CryptoHandshakeMessage& server_hello, |
| 285 string* error_details) { |
| 286 DCHECK(error_details != NULL); |
| 287 QuicErrorCode error = |
| 288 ReadUint32(server_hello, tag_, presence_, value_, &value_, error_details); |
| 289 if (error != QUIC_NO_ERROR) { |
| 290 return error; |
| 291 } |
| 292 return QUIC_NO_ERROR; |
| 293 } |
| 294 |
| 295 QuicConfig::QuicConfig() |
| 296 : congestion_control_(kCGST, PRESENCE_REQUIRED), |
| 297 idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED), |
| 298 keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL), |
| 299 max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED), |
| 300 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()), |
| 301 server_initial_congestion_window_(kSWND, PRESENCE_OPTIONAL), |
| 302 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL), |
| 303 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring |
| 304 // QUIC_VERSION_17. |
| 305 peer_initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL, 0) { |
239 // All optional non-zero parameters should be initialized here. | 306 // All optional non-zero parameters should be initialized here. |
240 server_initial_congestion_window_.set(kMaxInitialWindow, | 307 server_initial_congestion_window_.set(kMaxInitialWindow, |
241 kDefaultInitialWindow); | 308 kDefaultInitialWindow); |
242 } | 309 } |
243 | 310 |
244 QuicConfig::~QuicConfig() {} | 311 QuicConfig::~QuicConfig() {} |
245 | 312 |
246 void QuicConfig::set_congestion_control( | 313 void QuicConfig::set_congestion_control( |
247 const QuicTagVector& congestion_control, | 314 const QuicTagVector& congestion_control, |
248 QuicTag default_congestion_control) { | 315 QuicTag default_congestion_control) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 | 368 |
302 void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt, | 369 void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt, |
303 size_t default_rtt) { | 370 size_t default_rtt) { |
304 initial_round_trip_time_us_.set(max_rtt, default_rtt); | 371 initial_round_trip_time_us_.set(max_rtt, default_rtt); |
305 } | 372 } |
306 | 373 |
307 uint32 QuicConfig::initial_round_trip_time_us() const { | 374 uint32 QuicConfig::initial_round_trip_time_us() const { |
308 return initial_round_trip_time_us_.GetUint32(); | 375 return initial_round_trip_time_us_.GetUint32(); |
309 } | 376 } |
310 | 377 |
| 378 void QuicConfig::set_peer_initial_flow_control_window_bytes(uint32 window) { |
| 379 peer_initial_flow_control_window_bytes_.set_value(window); |
| 380 } |
| 381 |
| 382 uint32 QuicConfig::peer_initial_flow_control_window_bytes() const { |
| 383 return peer_initial_flow_control_window_bytes_.GetUint32(); |
| 384 } |
| 385 |
311 bool QuicConfig::negotiated() { | 386 bool QuicConfig::negotiated() { |
312 // TODO(ianswett): Add the negotiated parameters once and iterate over all | 387 // TODO(ianswett): Add the negotiated parameters once and iterate over all |
313 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and | 388 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and |
314 // ProcessServerHello. | 389 // ProcessServerHello. |
315 return congestion_control_.negotiated() && | 390 return congestion_control_.negotiated() && |
316 idle_connection_state_lifetime_seconds_.negotiated() && | 391 idle_connection_state_lifetime_seconds_.negotiated() && |
317 keepalive_timeout_seconds_.negotiated() && | 392 keepalive_timeout_seconds_.negotiated() && |
318 max_streams_per_connection_.negotiated() && | 393 max_streams_per_connection_.negotiated() && |
319 server_initial_congestion_window_.negotiated() && | 394 server_initial_congestion_window_.negotiated() && |
320 initial_round_trip_time_us_.negotiated(); | 395 initial_round_trip_time_us_.negotiated(); |
(...skipping 28 matching lines...) Expand all Loading... |
349 } | 424 } |
350 | 425 |
351 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { | 426 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { |
352 congestion_control_.ToHandshakeMessage(out); | 427 congestion_control_.ToHandshakeMessage(out); |
353 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out); | 428 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out); |
354 keepalive_timeout_seconds_.ToHandshakeMessage(out); | 429 keepalive_timeout_seconds_.ToHandshakeMessage(out); |
355 max_streams_per_connection_.ToHandshakeMessage(out); | 430 max_streams_per_connection_.ToHandshakeMessage(out); |
356 server_initial_congestion_window_.ToHandshakeMessage(out); | 431 server_initial_congestion_window_.ToHandshakeMessage(out); |
357 // TODO(ianswett): Don't transmit parameters which are optional and not set. | 432 // TODO(ianswett): Don't transmit parameters which are optional and not set. |
358 initial_round_trip_time_us_.ToHandshakeMessage(out); | 433 initial_round_trip_time_us_.ToHandshakeMessage(out); |
| 434 peer_initial_flow_control_window_bytes_.ToHandshakeMessage(out); |
359 } | 435 } |
360 | 436 |
361 QuicErrorCode QuicConfig::ProcessClientHello( | 437 QuicErrorCode QuicConfig::ProcessClientHello( |
362 const CryptoHandshakeMessage& client_hello, | 438 const CryptoHandshakeMessage& client_hello, |
363 string* error_details) { | 439 string* error_details) { |
364 DCHECK(error_details != NULL); | 440 DCHECK(error_details != NULL); |
365 | 441 |
366 QuicErrorCode error = QUIC_NO_ERROR; | 442 QuicErrorCode error = QUIC_NO_ERROR; |
367 if (error == QUIC_NO_ERROR) { | 443 if (error == QUIC_NO_ERROR) { |
368 error = congestion_control_.ProcessClientHello(client_hello, error_details); | 444 error = congestion_control_.ProcessClientHello(client_hello, error_details); |
(...skipping 11 matching lines...) Expand all Loading... |
380 client_hello, error_details); | 456 client_hello, error_details); |
381 } | 457 } |
382 if (error == QUIC_NO_ERROR) { | 458 if (error == QUIC_NO_ERROR) { |
383 error = server_initial_congestion_window_.ProcessClientHello( | 459 error = server_initial_congestion_window_.ProcessClientHello( |
384 client_hello, error_details); | 460 client_hello, error_details); |
385 } | 461 } |
386 if (error == QUIC_NO_ERROR) { | 462 if (error == QUIC_NO_ERROR) { |
387 error = initial_round_trip_time_us_.ProcessClientHello( | 463 error = initial_round_trip_time_us_.ProcessClientHello( |
388 client_hello, error_details); | 464 client_hello, error_details); |
389 } | 465 } |
| 466 if (error == QUIC_NO_ERROR) { |
| 467 error = peer_initial_flow_control_window_bytes_.ProcessClientHello( |
| 468 client_hello, error_details); |
| 469 } |
390 return error; | 470 return error; |
391 } | 471 } |
392 | 472 |
393 QuicErrorCode QuicConfig::ProcessServerHello( | 473 QuicErrorCode QuicConfig::ProcessServerHello( |
394 const CryptoHandshakeMessage& server_hello, | 474 const CryptoHandshakeMessage& server_hello, |
395 string* error_details) { | 475 string* error_details) { |
396 DCHECK(error_details != NULL); | 476 DCHECK(error_details != NULL); |
397 | 477 |
398 QuicErrorCode error = QUIC_NO_ERROR; | 478 QuicErrorCode error = QUIC_NO_ERROR; |
399 if (error == QUIC_NO_ERROR) { | 479 if (error == QUIC_NO_ERROR) { |
(...skipping 12 matching lines...) Expand all Loading... |
412 server_hello, error_details); | 492 server_hello, error_details); |
413 } | 493 } |
414 if (error == QUIC_NO_ERROR) { | 494 if (error == QUIC_NO_ERROR) { |
415 error = server_initial_congestion_window_.ProcessServerHello( | 495 error = server_initial_congestion_window_.ProcessServerHello( |
416 server_hello, error_details); | 496 server_hello, error_details); |
417 } | 497 } |
418 if (error == QUIC_NO_ERROR) { | 498 if (error == QUIC_NO_ERROR) { |
419 error = initial_round_trip_time_us_.ProcessServerHello( | 499 error = initial_round_trip_time_us_.ProcessServerHello( |
420 server_hello, error_details); | 500 server_hello, error_details); |
421 } | 501 } |
| 502 if (error == QUIC_NO_ERROR) { |
| 503 error = peer_initial_flow_control_window_bytes_.ProcessServerHello( |
| 504 server_hello, error_details); |
| 505 } |
422 return error; | 506 return error; |
423 } | 507 } |
424 | 508 |
425 } // namespace net | 509 } // namespace net |
OLD | NEW |