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. 4 5 #include "net/quic/quic_config.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 #include "net/quic/quic_sent_packet_manager.h" 11 12 using std::string; 13 14 namespace net { 15 16 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence) 17 : tag_(tag), 18 presence_(presence), 19 negotiated_(false) { 20 } 21 22 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence) 23 : QuicNegotiableValue(tag, presence), 24 max_value_(0), 25 default_value_(0) { 26 } 27 28 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { 29 DCHECK_LE(default_value, max); 30 max_value_ = max; 31 default_value_ = default_value; 32 } 33 34 uint32 QuicNegotiableUint32::GetUint32() const { 35 if (negotiated_) { 36 return negotiated_value_; 37 } 38 return default_value_; 39 } 40 41 void QuicNegotiableUint32::ToHandshakeMessage( 42 CryptoHandshakeMessage* out) const { 43 if (negotiated_) { 44 out->SetValue(tag_, negotiated_value_); 45 } else { 46 out->SetValue(tag_, max_value_); 47 } 48 } 49 50 QuicErrorCode QuicNegotiableUint32::ReadUint32( 51 const CryptoHandshakeMessage& msg, 52 uint32* out, 53 string* error_details) const { 54 DCHECK(error_details != NULL); 55 QuicErrorCode error = msg.GetUint32(tag_, out); 56 switch (error) { 57 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 58 if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) { 59 *error_details = "Missing " + QuicUtils::TagToString(tag_); 60 break; 61 } 62 error = QUIC_NO_ERROR; 63 *out = default_value_; 64 65 case QUIC_NO_ERROR: 66 break; 67 default: 68 *error_details = "Bad " + QuicUtils::TagToString(tag_); 69 break; 70 } 71 return error; 72 } 73 74 QuicErrorCode QuicNegotiableUint32::ProcessClientHello( 75 const CryptoHandshakeMessage& client_hello, 76 string* error_details) { 77 DCHECK(!negotiated_); 78 DCHECK(error_details != NULL); 79 uint32 value; 80 QuicErrorCode error = ReadUint32(client_hello, &value, error_details); 81 if (error != QUIC_NO_ERROR) { 82 return error; 83 } 84 85 negotiated_ = true; 86 negotiated_value_ = std::min(value, max_value_); 87 88 return QUIC_NO_ERROR; 89 } 90 91 QuicErrorCode QuicNegotiableUint32::ProcessServerHello( 92 const CryptoHandshakeMessage& server_hello, 93 string* error_details) { 94 DCHECK(!negotiated_); 95 DCHECK(error_details != NULL); 96 uint32 value; 97 QuicErrorCode error = ReadUint32(server_hello, &value, error_details); 98 if (error != QUIC_NO_ERROR) { 99 return error; 100 } 101 102 if (value > max_value_) { 103 *error_details = "Invalid value received for " + 104 QuicUtils::TagToString(tag_); 105 return QUIC_INVALID_NEGOTIATED_VALUE; 106 } 107 108 negotiated_ = true; 109 negotiated_value_ = value; 110 return QUIC_NO_ERROR; 111 } 112 113 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence) 114 : QuicNegotiableValue(tag, presence), 115 negotiated_tag_(0), 116 default_value_(0) { 117 } 118 119 QuicNegotiableTag::~QuicNegotiableTag() {} 120 121 void QuicNegotiableTag::set(const QuicTagVector& possible, 122 QuicTag default_value) { 123 DCHECK(std::find(possible.begin(), possible.end(), default_value) != 124 possible.end()); 125 possible_values_ = possible; 126 default_value_ = default_value; 127 } 128 129 QuicTag QuicNegotiableTag::GetTag() const { 130 if (negotiated_) { 131 return negotiated_tag_; 132 } 133 return default_value_; 134 } 135 136 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 137 if (negotiated_) { 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_); 141 } else { 142 out->SetVector(tag_, possible_values_); 143 } 144 } 145 146 QuicErrorCode QuicNegotiableTag::ReadVector( 147 const CryptoHandshakeMessage& msg, 148 const QuicTag** out, 149 size_t* out_length, 150 string* error_details) const { 151 DCHECK(error_details != NULL); 152 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length); 153 switch (error) { 154 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 155 if (presence_ == PRESENCE_REQUIRED) { 156 *error_details = "Missing " + QuicUtils::TagToString(tag_); 157 break; 158 } 159 error = QUIC_NO_ERROR; 160 *out_length = 1; 161 *out = &default_value_; 162 163 case QUIC_NO_ERROR: 164 break; 165 default: 166 *error_details = "Bad " + QuicUtils::TagToString(tag_); 167 break; 168 } 169 return error; 170 } 171 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) { 182 return error; 183 } 184 185 QuicTag negotiated_tag; 186 if (!QuicUtils::FindMutualTag(possible_values_, 187 received_tags, 188 received_tags_length, 189 QuicUtils::LOCAL_PRIORITY, 190 &negotiated_tag, 191 NULL)) { 192 *error_details = "Unsuported " + QuicUtils::TagToString(tag_); 193 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP; 194 } 195 196 negotiated_ = true; 197 negotiated_tag_ = negotiated_tag; 198 return QUIC_NO_ERROR; 199 } 200 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) { 211 return error; 212 } 213 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; 219 } 220 221 negotiated_ = true; 222 negotiated_tag_ = *received_tags; 223 return QUIC_NO_ERROR; 224 } 225 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); 239 } 240 241 QuicConfig::~QuicConfig() {} 242 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); 247 } 248 249 QuicTag QuicConfig::congestion_control() const { 250 return congestion_control_.GetTag(); 251 } 252 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()); 259 } 260 261 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const { 262 return QuicTime::Delta::FromSeconds( 263 idle_connection_state_lifetime_seconds_.GetUint32()); 264 } 265 266 QuicTime::Delta QuicConfig::keepalive_timeout() const { 267 return QuicTime::Delta::FromSeconds( 268 keepalive_timeout_seconds_.GetUint32()); 269 } 270 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); 274 } 275 276 uint32 QuicConfig::max_streams_per_connection() const { 277 return max_streams_per_connection_.GetUint32(); 278 } 279 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; 283 } 284 285 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const { 286 return max_time_before_crypto_handshake_; 287 } 288 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); 293 } 294 295 uint32 QuicConfig::server_initial_congestion_window() const { 296 return server_initial_congestion_window_.GetUint32(); 297 } 298 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); 302 } 303 304 uint32 QuicConfig::initial_round_trip_time_us() const { 305 return initial_round_trip_time_us_.GetUint32(); 306 } 307 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(); 318 } 319 320 void QuicConfig::SetDefaults() { 321 QuicTagVector congestion_control; 322 if (FLAGS_enable_quic_pacing) { 323 congestion_control.push_back(kPACE); 324 } 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); 337 } 338 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); 347 } 348 349 QuicErrorCode QuicConfig::ProcessClientHello( 350 const CryptoHandshakeMessage& client_hello, 351 string* error_details) { 352 DCHECK(error_details != NULL); 353 354 QuicErrorCode error = QUIC_NO_ERROR; 355 if (error == QUIC_NO_ERROR) { 356 error = congestion_control_.ProcessClientHello(client_hello, error_details); 357 } 358 if (error == QUIC_NO_ERROR) { 359 error = idle_connection_state_lifetime_seconds_.ProcessClientHello( 360 client_hello, error_details); 361 } 362 if (error == QUIC_NO_ERROR) { 363 error = keepalive_timeout_seconds_.ProcessClientHello( 364 client_hello, error_details); 365 } 366 if (error == QUIC_NO_ERROR) { 367 error = max_streams_per_connection_.ProcessClientHello( 368 client_hello, error_details); 369 } 370 if (error == QUIC_NO_ERROR) { 371 error = server_initial_congestion_window_.ProcessClientHello( 372 client_hello, error_details); 373 } 374 if (error == QUIC_NO_ERROR) { 375 error = initial_round_trip_time_us_.ProcessClientHello( 376 client_hello, error_details); 377 } 378 return error; 379 } 380 381 QuicErrorCode QuicConfig::ProcessServerHello( 382 const CryptoHandshakeMessage& server_hello, 383 string* error_details) { 384 DCHECK(error_details != NULL); 385 386 QuicErrorCode error = QUIC_NO_ERROR; 387 if (error == QUIC_NO_ERROR) { 388 error = congestion_control_.ProcessServerHello(server_hello, error_details); 389 } 390 if (error == QUIC_NO_ERROR) { 391 error = idle_connection_state_lifetime_seconds_.ProcessServerHello( 392 server_hello, error_details); 393 } 394 if (error == QUIC_NO_ERROR) { 395 error = keepalive_timeout_seconds_.ProcessServerHello( 396 server_hello, error_details); 397 } 398 if (error == QUIC_NO_ERROR) { 399 error = max_streams_per_connection_.ProcessServerHello( 400 server_hello, error_details); 401 } 402 if (error == QUIC_NO_ERROR) { 403 error = server_initial_congestion_window_.ProcessServerHello( 404 server_hello, error_details); 405 } 406 if (error == QUIC_NO_ERROR) { 407 error = initial_round_trip_time_us_.ProcessServerHello( 408 server_hello, error_details); 409 } 410 return error; 411 } 412 413 } // namespace net 414