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> |
| 8 |
| 9 #include "base/logging.h" |
| 10 |
7 using std::string; | 11 using std::string; |
8 | 12 |
9 namespace net { | 13 namespace net { |
10 | 14 |
11 QuicNegotiatedParameters::QuicNegotiatedParameters() | 15 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence) |
12 : idle_connection_state_lifetime(QuicTime::Delta::Zero()), | 16 : tag_(tag), |
13 keepalive_timeout(QuicTime::Delta::Zero()) { | 17 presence_(presence), |
14 } | 18 negotiated_(false) { |
15 | 19 } |
16 QuicConfig::QuicConfig() | 20 |
17 : idle_connection_state_lifetime_(QuicTime::Delta::Zero()), | 21 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence) |
18 keepalive_timeout_(QuicTime::Delta::Zero()) { | 22 : QuicNegotiableValue(tag, presence) { |
19 } | 23 } |
20 | 24 |
21 QuicConfig::~QuicConfig() { | 25 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { |
22 } | 26 DCHECK_LE(default_value, max); |
23 | 27 max_value_ = max; |
24 void QuicConfig::SetDefaults() { | 28 default_value_ = default_value; |
25 idle_connection_state_lifetime_ = QuicTime::Delta::FromSeconds(300); | 29 } |
26 keepalive_timeout_ = QuicTime::Delta::Zero(); | 30 |
27 congestion_control_.clear(); | 31 uint32 QuicNegotiableUint32::GetUint32() const { |
28 congestion_control_.push_back(kQBIC); | 32 if (negotiated_) { |
29 } | 33 return negotiated_value_; |
30 | 34 } |
31 bool QuicConfig::SetFromHandshakeMessage(const CryptoHandshakeMessage& scfg) { | 35 return default_value_; |
32 const QuicTag* cgst; | 36 } |
33 size_t num_cgst; | 37 |
34 QuicErrorCode error; | 38 void QuicNegotiableUint32::ToHandshakeMessage( |
35 | 39 CryptoHandshakeMessage* out) const { |
36 error = scfg.GetTaglist(kCGST, &cgst, &num_cgst); | 40 if (negotiated_) { |
37 if (error != QUIC_NO_ERROR) { | 41 out->SetValue(tag_, negotiated_value_); |
38 return false; | 42 } else { |
39 } | 43 out->SetValue(tag_, max_value_); |
40 | 44 } |
41 congestion_control_.assign(cgst, cgst + num_cgst); | 45 } |
42 | 46 |
43 uint32 idle; | 47 QuicErrorCode QuicNegotiableUint32::ReadUint32( |
44 error = scfg.GetUint32(kICSL, &idle); | |
45 if (error != QUIC_NO_ERROR) { | |
46 return false; | |
47 } | |
48 idle_connection_state_lifetime_ = QuicTime::Delta::FromSeconds(idle); | |
49 | |
50 keepalive_timeout_ = QuicTime::Delta::Zero(); | |
51 | |
52 uint32 keepalive; | |
53 error = scfg.GetUint32(kKATO, &keepalive); | |
54 // KATO is optional. | |
55 if (error == QUIC_NO_ERROR) { | |
56 keepalive_timeout_ = QuicTime::Delta::FromSeconds(keepalive); | |
57 } | |
58 | |
59 return true; | |
60 } | |
61 | |
62 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { | |
63 out->SetValue( | |
64 kICSL, static_cast<uint32>(idle_connection_state_lifetime_.ToSeconds())); | |
65 out->SetValue(kKATO, static_cast<uint32>(keepalive_timeout_.ToSeconds())); | |
66 out->SetVector(kCGST, congestion_control_); | |
67 } | |
68 | |
69 QuicErrorCode QuicConfig::ProcessFinalPeerHandshake( | |
70 const CryptoHandshakeMessage& msg, | 48 const CryptoHandshakeMessage& msg, |
71 CryptoUtils::Priority priority, | 49 uint32* out, |
72 QuicNegotiatedParameters* out_params, | |
73 string* error_details) const { | 50 string* error_details) const { |
74 DCHECK(error_details != NULL); | 51 DCHECK(error_details != NULL); |
75 | 52 QuicErrorCode error = msg.GetUint32(tag_, out); |
76 const QuicTag* their_congestion_controls; | |
77 size_t num_their_congestion_controls; | |
78 QuicErrorCode error; | |
79 | |
80 error = msg.GetTaglist(kCGST, &their_congestion_controls, | |
81 &num_their_congestion_controls); | |
82 if (error != QUIC_NO_ERROR) { | |
83 *error_details = "Missing CGST"; | |
84 return error; | |
85 } | |
86 | |
87 if (!CryptoUtils::FindMutualTag(congestion_control_, | |
88 their_congestion_controls, | |
89 num_their_congestion_controls, | |
90 priority, | |
91 &out_params->congestion_control, | |
92 NULL)) { | |
93 *error_details = "Unsuported CGST"; | |
94 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP; | |
95 } | |
96 | |
97 uint32 idle; | |
98 error = msg.GetUint32(kICSL, &idle); | |
99 if (error != QUIC_NO_ERROR) { | |
100 *error_details = "Missing ICSL"; | |
101 return error; | |
102 } | |
103 | |
104 out_params->idle_connection_state_lifetime = QuicTime::Delta::FromSeconds( | |
105 std::min(static_cast<uint32>(idle_connection_state_lifetime_.ToSeconds()), | |
106 idle)); | |
107 | |
108 uint32 keepalive; | |
109 error = msg.GetUint32(kKATO, &keepalive); | |
110 switch (error) { | 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 |
111 case QUIC_NO_ERROR: | 62 case QUIC_NO_ERROR: |
112 out_params->keepalive_timeout = QuicTime::Delta::FromSeconds( | |
113 std::min(static_cast<uint32>(keepalive_timeout_.ToSeconds()), | |
114 keepalive)); | |
115 break; | |
116 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: | |
117 // KATO is optional. | |
118 out_params->keepalive_timeout = QuicTime::Delta::Zero(); | |
119 break; | 63 break; |
120 default: | 64 default: |
121 *error_details = "Bad KATO"; | 65 *error_details = "Bad " + QuicUtils::TagToString(tag_); |
122 return error; | 66 break; |
123 } | 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_); |
124 | 84 |
125 return QUIC_NO_ERROR; | 85 return QUIC_NO_ERROR; |
126 } | 86 } |
127 | 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 idle_connection_state_lifetime_seconds_.set(0, 0); |
| 228 keepalive_timeout_seconds_.set(0, 0); |
| 229 } |
| 230 |
| 231 QuicConfig::~QuicConfig() {} |
| 232 |
| 233 void QuicConfig::set_congestion_control( |
| 234 const QuicTagVector& congestion_control, |
| 235 QuicTag default_congestion_control) { |
| 236 congestion_control_.set(congestion_control, default_congestion_control); |
| 237 } |
| 238 |
| 239 QuicTag QuicConfig::congestion_control() const { |
| 240 return congestion_control_.GetTag(); |
| 241 } |
| 242 |
| 243 void QuicConfig::set_idle_connection_state_lifetime( |
| 244 QuicTime::Delta max_idle_connection_state_lifetime, |
| 245 QuicTime::Delta default_idle_conection_state_lifetime) { |
| 246 idle_connection_state_lifetime_seconds_.set( |
| 247 max_idle_connection_state_lifetime.ToSeconds(), |
| 248 default_idle_conection_state_lifetime.ToSeconds()); |
| 249 } |
| 250 |
| 251 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const { |
| 252 return QuicTime::Delta::FromSeconds( |
| 253 idle_connection_state_lifetime_seconds_.GetUint32()); |
| 254 } |
| 255 |
| 256 QuicTime::Delta QuicConfig::keepalive_timeout() const { |
| 257 return QuicTime::Delta::FromSeconds( |
| 258 keepalive_timeout_seconds_.GetUint32()); |
| 259 } |
| 260 |
| 261 void QuicConfig::set_max_streams_per_connection(size_t max_streams, |
| 262 size_t default_streams) { |
| 263 max_streams_per_connection_.set(max_streams, default_streams); |
| 264 } |
| 265 |
| 266 uint32 QuicConfig::max_streams_per_connection() const { |
| 267 return max_streams_per_connection_.GetUint32(); |
| 268 } |
| 269 |
| 270 bool QuicConfig::negotiated() { |
| 271 return congestion_control_.negotiated() && |
| 272 idle_connection_state_lifetime_seconds_.negotiated() && |
| 273 keepalive_timeout_seconds_.negotiated() && |
| 274 max_streams_per_connection_.negotiated(); |
| 275 } |
| 276 |
| 277 void QuicConfig::SetDefaults() { |
| 278 congestion_control_.set(QuicTagVector(1, kQBIC), kQBIC); |
| 279 idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs, |
| 280 kDefaultTimeoutSecs); |
| 281 // kKATO is optional. Return 0 if not negotiated. |
| 282 keepalive_timeout_seconds_.set(0, 0); |
| 283 max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection, |
| 284 kDefaultMaxStreamsPerConnection); |
| 285 } |
| 286 |
| 287 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { |
| 288 congestion_control_.ToHandshakeMessage(out); |
| 289 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out); |
| 290 keepalive_timeout_seconds_.ToHandshakeMessage(out); |
| 291 max_streams_per_connection_.ToHandshakeMessage(out); |
| 292 } |
| 293 |
| 294 QuicErrorCode QuicConfig::ProcessClientHello( |
| 295 const CryptoHandshakeMessage& client_hello, |
| 296 string* error_details) { |
| 297 DCHECK(error_details != NULL); |
| 298 |
| 299 QuicErrorCode error = QUIC_NO_ERROR; |
| 300 if (error == QUIC_NO_ERROR) { |
| 301 error = congestion_control_.ProcessClientHello(client_hello, error_details); |
| 302 } |
| 303 if (error == QUIC_NO_ERROR) { |
| 304 error = idle_connection_state_lifetime_seconds_.ProcessClientHello( |
| 305 client_hello, error_details); |
| 306 } |
| 307 if (error == QUIC_NO_ERROR) { |
| 308 error = keepalive_timeout_seconds_.ProcessClientHello( |
| 309 client_hello, error_details); |
| 310 } |
| 311 if (error == QUIC_NO_ERROR) { |
| 312 error = max_streams_per_connection_.ProcessClientHello( |
| 313 client_hello, error_details); |
| 314 } |
| 315 return error; |
| 316 } |
| 317 |
| 318 QuicErrorCode QuicConfig::ProcessServerHello( |
| 319 const CryptoHandshakeMessage& server_hello, |
| 320 string* error_details) { |
| 321 DCHECK(error_details != NULL); |
| 322 |
| 323 QuicErrorCode error = QUIC_NO_ERROR; |
| 324 if (error == QUIC_NO_ERROR) { |
| 325 error = congestion_control_.ProcessServerHello(server_hello, error_details); |
| 326 } |
| 327 if (error == QUIC_NO_ERROR) { |
| 328 error = idle_connection_state_lifetime_seconds_.ProcessServerHello( |
| 329 server_hello, error_details); |
| 330 } |
| 331 if (error == QUIC_NO_ERROR) { |
| 332 error = keepalive_timeout_seconds_.ProcessServerHello( |
| 333 server_hello, error_details); |
| 334 } |
| 335 if (error == QUIC_NO_ERROR) { |
| 336 error = max_streams_per_connection_.ProcessServerHello( |
| 337 server_hello, error_details); |
| 338 } |
| 339 return error; |
| 340 } |
| 341 |
128 } // namespace net | 342 } // namespace net |
129 | 343 |
OLD | NEW |