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 11 using std::string; 12 13 namespace net { 14 15 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence) 16 : tag_(tag), 17 presence_(presence), 18 negotiated_(false) { 19 } 20 21 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence) 22 : QuicNegotiableValue(tag, presence) { 23 } 24 25 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { 26 DCHECK_LE(default_value, max); 27 max_value_ = max; 28 default_value_ = default_value; 29 } 30 31 uint32 QuicNegotiableUint32::GetUint32() const { 32 if (negotiated_) { 33 return negotiated_value_; 34 } 35 return default_value_; 36 } 37 38 void QuicNegotiableUint32::ToHandshakeMessage( 39 CryptoHandshakeMessage* out) const { 40 if (negotiated_) { 41 out->SetValue(tag_, negotiated_value_); 42 } else { 43 out->SetValue(tag_, max_value_); 44 } 45 } 46 47 QuicErrorCode QuicNegotiableUint32::ReadUint32( 48 const CryptoHandshakeMessage& msg, 49 uint32* out, 50 string* error_details) const { 51 DCHECK(error_details != NULL); 52 QuicErrorCode error = msg.GetUint32(tag_, out); 53 switch (error) { 54 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 55 if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) { 56 *error_details = "Missing " + QuicUtils::TagToString(tag_); 57 break; 58 } 59 error = QUIC_NO_ERROR; 60 *out = default_value_; 61 62 case QUIC_NO_ERROR: 63 break; 64 default: 65 *error_details = "Bad " + QuicUtils::TagToString(tag_); 66 break; 67 } 68 return error; 69 } 70 71 QuicErrorCode QuicNegotiableUint32::ProcessClientHello( 72 const CryptoHandshakeMessage& client_hello, 73 string* error_details) { 74 DCHECK(!negotiated_); 75 DCHECK(error_details != NULL); 76 uint32 value; 77 QuicErrorCode error = ReadUint32(client_hello, &value, error_details); 78 if (error != QUIC_NO_ERROR) { 79 return error; 80 } 81 82 negotiated_ = true; 83 negotiated_value_ = std::min(value, max_value_); 84 85 return QUIC_NO_ERROR; 86 } 87 88 QuicErrorCode QuicNegotiableUint32::ProcessServerHello( 89 const CryptoHandshakeMessage& server_hello, 90 string* error_details) { 91 DCHECK(!negotiated_); 92 DCHECK(error_details != NULL); 93 uint32 value; 94 QuicErrorCode error = ReadUint32(server_hello, &value, error_details); 95 if (error != QUIC_NO_ERROR) { 96 return error; 97 } 98 99 if (value > max_value_) { 100 *error_details = "Invalid value received for " + 101 QuicUtils::TagToString(tag_); 102 return QUIC_INVALID_NEGOTIATED_VALUE; 103 } 104 105 negotiated_ = true; 106 negotiated_value_ = value; 107 return QUIC_NO_ERROR; 108 } 109 110 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence) 111 : QuicNegotiableValue(tag, presence) { 112 } 113 114 QuicNegotiableTag::~QuicNegotiableTag() {} 115 116 void QuicNegotiableTag::set(const QuicTagVector& possible, 117 QuicTag default_value) { 118 DCHECK(std::find(possible.begin(), possible.end(), default_value) != 119 possible.end()); 120 possible_values_ = possible; 121 default_value_ = default_value; 122 } 123 124 QuicTag QuicNegotiableTag::GetTag() const { 125 if (negotiated_) { 126 return negotiated_tag_; 127 } 128 return default_value_; 129 } 130 131 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 132 if (negotiated_) { 133 // Because of the way we serialize and parse handshake messages we can 134 // serialize this as value and still parse it as a vector. 135 out->SetValue(tag_, negotiated_tag_); 136 } else { 137 out->SetVector(tag_, possible_values_); 138 } 139 } 140 141 QuicErrorCode QuicNegotiableTag::ReadVector( 142 const CryptoHandshakeMessage& msg, 143 const QuicTag** out, 144 size_t* out_length, 145 string* error_details) const { 146 DCHECK(error_details != NULL); 147 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length); 148 switch (error) { 149 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 150 if (presence_ == PRESENCE_REQUIRED) { 151 *error_details = "Missing " + QuicUtils::TagToString(tag_); 152 break; 153 } 154 error = QUIC_NO_ERROR; 155 *out_length = 1; 156 *out = &default_value_; 157 158 case QUIC_NO_ERROR: 159 break; 160 default: 161 *error_details = "Bad " + QuicUtils::TagToString(tag_); 162 break; 163 } 164 return error; 165 } 166 167 QuicErrorCode QuicNegotiableTag::ProcessClientHello( 168 const CryptoHandshakeMessage& client_hello, 169 string* error_details) { 170 DCHECK(!negotiated_); 171 DCHECK(error_details != NULL); 172 const QuicTag* received_tags; 173 size_t received_tags_length; 174 QuicErrorCode error = ReadVector(client_hello, &received_tags, 175 &received_tags_length, error_details); 176 if (error != QUIC_NO_ERROR) { 177 return error; 178 } 179 180 QuicTag negotiated_tag; 181 if (!QuicUtils::FindMutualTag(possible_values_, 182 received_tags, 183 received_tags_length, 184 QuicUtils::LOCAL_PRIORITY, 185 &negotiated_tag, 186 NULL)) { 187 *error_details = "Unsuported " + QuicUtils::TagToString(tag_); 188 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP; 189 } 190 191 negotiated_ = true; 192 negotiated_tag_ = negotiated_tag; 193 return QUIC_NO_ERROR; 194 } 195 196 QuicErrorCode QuicNegotiableTag::ProcessServerHello( 197 const CryptoHandshakeMessage& server_hello, 198 string* error_details) { 199 DCHECK(!negotiated_); 200 DCHECK(error_details != NULL); 201 const QuicTag* received_tags; 202 size_t received_tags_length; 203 QuicErrorCode error = ReadVector(server_hello, &received_tags, 204 &received_tags_length, error_details); 205 if (error != QUIC_NO_ERROR) { 206 return error; 207 } 208 209 if (received_tags_length != 1 || 210 std::find(possible_values_.begin(), possible_values_.end(), 211 *received_tags) == possible_values_.end()) { 212 *error_details = "Invalid " + QuicUtils::TagToString(tag_); 213 return QUIC_INVALID_NEGOTIATED_VALUE; 214 } 215 216 negotiated_ = true; 217 negotiated_tag_ = *received_tags; 218 return QUIC_NO_ERROR; 219 } 220 221 QuicConfig::QuicConfig() : 222 congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED), 223 idle_connection_state_lifetime_seconds_( 224 kICSL, QuicNegotiableValue::PRESENCE_REQUIRED), 225 keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL), 226 max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED), 227 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()) { 228 idle_connection_state_lifetime_seconds_.set(0, 0); 229 keepalive_timeout_seconds_.set(0, 0); 230 } 231 232 QuicConfig::~QuicConfig() {} 233 234 void QuicConfig::set_congestion_control( 235 const QuicTagVector& congestion_control, 236 QuicTag default_congestion_control) { 237 congestion_control_.set(congestion_control, default_congestion_control); 238 } 239 240 QuicTag QuicConfig::congestion_control() const { 241 return congestion_control_.GetTag(); 242 } 243 244 void QuicConfig::set_idle_connection_state_lifetime( 245 QuicTime::Delta max_idle_connection_state_lifetime, 246 QuicTime::Delta default_idle_conection_state_lifetime) { 247 idle_connection_state_lifetime_seconds_.set( 248 max_idle_connection_state_lifetime.ToSeconds(), 249 default_idle_conection_state_lifetime.ToSeconds()); 250 } 251 252 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const { 253 return QuicTime::Delta::FromSeconds( 254 idle_connection_state_lifetime_seconds_.GetUint32()); 255 } 256 257 QuicTime::Delta QuicConfig::keepalive_timeout() const { 258 return QuicTime::Delta::FromSeconds( 259 keepalive_timeout_seconds_.GetUint32()); 260 } 261 262 void QuicConfig::set_max_streams_per_connection(size_t max_streams, 263 size_t default_streams) { 264 max_streams_per_connection_.set(max_streams, default_streams); 265 } 266 267 uint32 QuicConfig::max_streams_per_connection() const { 268 return max_streams_per_connection_.GetUint32(); 269 } 270 271 void QuicConfig::set_max_time_before_crypto_handshake( 272 QuicTime::Delta max_time_before_crypto_handshake) { 273 max_time_before_crypto_handshake_ = max_time_before_crypto_handshake; 274 } 275 276 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const { 277 return max_time_before_crypto_handshake_; 278 } 279 280 bool QuicConfig::negotiated() { 281 return congestion_control_.negotiated() && 282 idle_connection_state_lifetime_seconds_.negotiated() && 283 keepalive_timeout_seconds_.negotiated() && 284 max_streams_per_connection_.negotiated(); 285 } 286 287 void QuicConfig::SetDefaults() { 288 congestion_control_.set(QuicTagVector(1, kQBIC), kQBIC); 289 idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs, 290 kDefaultInitialTimeoutSecs); 291 // kKATO is optional. Return 0 if not negotiated. 292 keepalive_timeout_seconds_.set(0, 0); 293 max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection, 294 kDefaultMaxStreamsPerConnection); 295 max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds( 296 kDefaultMaxTimeForCryptoHandshakeSecs); 297 } 298 299 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 300 congestion_control_.ToHandshakeMessage(out); 301 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out); 302 keepalive_timeout_seconds_.ToHandshakeMessage(out); 303 max_streams_per_connection_.ToHandshakeMessage(out); 304 } 305 306 QuicErrorCode QuicConfig::ProcessClientHello( 307 const CryptoHandshakeMessage& client_hello, 308 string* error_details) { 309 DCHECK(error_details != NULL); 310 311 QuicErrorCode error = QUIC_NO_ERROR; 312 if (error == QUIC_NO_ERROR) { 313 error = congestion_control_.ProcessClientHello(client_hello, error_details); 314 } 315 if (error == QUIC_NO_ERROR) { 316 error = idle_connection_state_lifetime_seconds_.ProcessClientHello( 317 client_hello, error_details); 318 } 319 if (error == QUIC_NO_ERROR) { 320 error = keepalive_timeout_seconds_.ProcessClientHello( 321 client_hello, error_details); 322 } 323 if (error == QUIC_NO_ERROR) { 324 error = max_streams_per_connection_.ProcessClientHello( 325 client_hello, error_details); 326 } 327 return error; 328 } 329 330 QuicErrorCode QuicConfig::ProcessServerHello( 331 const CryptoHandshakeMessage& server_hello, 332 string* error_details) { 333 DCHECK(error_details != NULL); 334 335 QuicErrorCode error = QUIC_NO_ERROR; 336 if (error == QUIC_NO_ERROR) { 337 error = congestion_control_.ProcessServerHello(server_hello, error_details); 338 } 339 if (error == QUIC_NO_ERROR) { 340 error = idle_connection_state_lifetime_seconds_.ProcessServerHello( 341 server_hello, error_details); 342 } 343 if (error == QUIC_NO_ERROR) { 344 error = keepalive_timeout_seconds_.ProcessServerHello( 345 server_hello, error_details); 346 } 347 if (error == QUIC_NO_ERROR) { 348 error = max_streams_per_connection_.ProcessServerHello( 349 server_hello, error_details); 350 } 351 return error; 352 } 353 354 } // namespace net 355 356