OLD | NEW |
| (Empty) |
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/crypto/crypto_handshake_message.h" | |
11 #include "net/quic/crypto/crypto_protocol.h" | |
12 #include "net/quic/quic_bug_tracker.h" | |
13 #include "net/quic/quic_socket_address_coder.h" | |
14 #include "net/quic/quic_utils.h" | |
15 | |
16 using std::min; | |
17 using std::string; | |
18 | |
19 namespace net { | |
20 | |
21 // Reads the value corresponding to |name_| from |msg| into |out|. If the | |
22 // |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set | |
23 // to |default_value|. | |
24 QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg, | |
25 QuicTag tag, | |
26 QuicConfigPresence presence, | |
27 uint32_t default_value, | |
28 uint32_t* out, | |
29 string* error_details) { | |
30 DCHECK(error_details != nullptr); | |
31 QuicErrorCode error = msg.GetUint32(tag, out); | |
32 switch (error) { | |
33 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: | |
34 if (presence == PRESENCE_REQUIRED) { | |
35 *error_details = "Missing " + QuicUtils::TagToString(tag); | |
36 break; | |
37 } | |
38 error = QUIC_NO_ERROR; | |
39 *out = default_value; | |
40 break; | |
41 case QUIC_NO_ERROR: | |
42 break; | |
43 default: | |
44 *error_details = "Bad " + QuicUtils::TagToString(tag); | |
45 break; | |
46 } | |
47 return error; | |
48 } | |
49 | |
50 QuicConfigValue::QuicConfigValue(QuicTag tag, QuicConfigPresence presence) | |
51 : tag_(tag), presence_(presence) {} | |
52 QuicConfigValue::~QuicConfigValue() {} | |
53 | |
54 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, | |
55 QuicConfigPresence presence) | |
56 : QuicConfigValue(tag, presence), negotiated_(false) {} | |
57 QuicNegotiableValue::~QuicNegotiableValue() {} | |
58 | |
59 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, | |
60 QuicConfigPresence presence) | |
61 : QuicNegotiableValue(tag, presence), | |
62 max_value_(0), | |
63 default_value_(0), | |
64 negotiated_value_(0) {} | |
65 QuicNegotiableUint32::~QuicNegotiableUint32() {} | |
66 | |
67 void QuicNegotiableUint32::set(uint32_t max, uint32_t default_value) { | |
68 DCHECK_LE(default_value, max); | |
69 max_value_ = max; | |
70 default_value_ = default_value; | |
71 } | |
72 | |
73 uint32_t QuicNegotiableUint32::GetUint32() const { | |
74 if (negotiated()) { | |
75 return negotiated_value_; | |
76 } | |
77 return default_value_; | |
78 } | |
79 | |
80 void QuicNegotiableUint32::ToHandshakeMessage( | |
81 CryptoHandshakeMessage* out) const { | |
82 if (negotiated()) { | |
83 out->SetValue(tag_, negotiated_value_); | |
84 } else { | |
85 out->SetValue(tag_, max_value_); | |
86 } | |
87 } | |
88 | |
89 QuicErrorCode QuicNegotiableUint32::ProcessPeerHello( | |
90 const CryptoHandshakeMessage& peer_hello, | |
91 HelloType hello_type, | |
92 string* error_details) { | |
93 DCHECK(!negotiated()); | |
94 DCHECK(error_details != nullptr); | |
95 uint32_t value; | |
96 QuicErrorCode error = ReadUint32(peer_hello, tag_, presence_, default_value_, | |
97 &value, error_details); | |
98 if (error != QUIC_NO_ERROR) { | |
99 return error; | |
100 } | |
101 if (hello_type == SERVER && value > max_value_) { | |
102 *error_details = | |
103 "Invalid value received for " + QuicUtils::TagToString(tag_); | |
104 return QUIC_INVALID_NEGOTIATED_VALUE; | |
105 } | |
106 | |
107 set_negotiated(true); | |
108 negotiated_value_ = min(value, max_value_); | |
109 return QUIC_NO_ERROR; | |
110 } | |
111 | |
112 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence) | |
113 : QuicNegotiableValue(tag, presence), | |
114 negotiated_tag_(0), | |
115 default_value_(0) {} | |
116 | |
117 QuicNegotiableTag::~QuicNegotiableTag() {} | |
118 | |
119 void QuicNegotiableTag::set(const QuicTagVector& possible, | |
120 QuicTag default_value) { | |
121 DCHECK(ContainsQuicTag(possible, default_value)); | |
122 possible_values_ = possible; | |
123 default_value_ = default_value; | |
124 } | |
125 | |
126 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const { | |
127 if (negotiated()) { | |
128 // Because of the way we serialize and parse handshake messages we can | |
129 // serialize this as value and still parse it as a vector. | |
130 out->SetValue(tag_, negotiated_tag_); | |
131 } else { | |
132 out->SetVector(tag_, possible_values_); | |
133 } | |
134 } | |
135 | |
136 QuicErrorCode QuicNegotiableTag::ReadVector(const CryptoHandshakeMessage& msg, | |
137 const QuicTag** out, | |
138 size_t* out_length, | |
139 string* error_details) const { | |
140 DCHECK(error_details != nullptr); | |
141 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length); | |
142 switch (error) { | |
143 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: | |
144 if (presence_ == PRESENCE_REQUIRED) { | |
145 *error_details = "Missing " + QuicUtils::TagToString(tag_); | |
146 break; | |
147 } | |
148 error = QUIC_NO_ERROR; | |
149 *out_length = 1; | |
150 *out = &default_value_; | |
151 | |
152 case QUIC_NO_ERROR: | |
153 break; | |
154 default: | |
155 *error_details = "Bad " + QuicUtils::TagToString(tag_); | |
156 break; | |
157 } | |
158 return error; | |
159 } | |
160 | |
161 QuicErrorCode QuicNegotiableTag::ProcessPeerHello( | |
162 const CryptoHandshakeMessage& peer_hello, | |
163 HelloType hello_type, | |
164 string* error_details) { | |
165 DCHECK(!negotiated()); | |
166 DCHECK(error_details != nullptr); | |
167 const QuicTag* received_tags; | |
168 size_t received_tags_length; | |
169 QuicErrorCode error = ReadVector(peer_hello, &received_tags, | |
170 &received_tags_length, error_details); | |
171 if (error != QUIC_NO_ERROR) { | |
172 return error; | |
173 } | |
174 | |
175 if (hello_type == SERVER) { | |
176 if (received_tags_length != 1 || | |
177 !ContainsQuicTag(possible_values_, *received_tags)) { | |
178 *error_details = "Invalid " + QuicUtils::TagToString(tag_); | |
179 return QUIC_INVALID_NEGOTIATED_VALUE; | |
180 } | |
181 negotiated_tag_ = *received_tags; | |
182 } else { | |
183 QuicTag negotiated_tag; | |
184 if (!QuicUtils::FindMutualTag( | |
185 possible_values_, received_tags, received_tags_length, | |
186 QuicUtils::LOCAL_PRIORITY, &negotiated_tag, nullptr)) { | |
187 *error_details = "Unsupported " + QuicUtils::TagToString(tag_); | |
188 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP; | |
189 } | |
190 negotiated_tag_ = negotiated_tag; | |
191 } | |
192 | |
193 set_negotiated(true); | |
194 return QUIC_NO_ERROR; | |
195 } | |
196 | |
197 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence) | |
198 : QuicConfigValue(tag, presence), | |
199 has_send_value_(false), | |
200 has_receive_value_(false) {} | |
201 QuicFixedUint32::~QuicFixedUint32() {} | |
202 | |
203 bool QuicFixedUint32::HasSendValue() const { | |
204 return has_send_value_; | |
205 } | |
206 | |
207 uint32_t QuicFixedUint32::GetSendValue() const { | |
208 QUIC_BUG_IF(!has_send_value_) << "No send value to get for tag:" | |
209 << QuicUtils::TagToString(tag_); | |
210 return send_value_; | |
211 } | |
212 | |
213 void QuicFixedUint32::SetSendValue(uint32_t value) { | |
214 has_send_value_ = true; | |
215 send_value_ = value; | |
216 } | |
217 | |
218 bool QuicFixedUint32::HasReceivedValue() const { | |
219 return has_receive_value_; | |
220 } | |
221 | |
222 uint32_t QuicFixedUint32::GetReceivedValue() const { | |
223 QUIC_BUG_IF(!has_receive_value_) << "No receive value to get for tag:" | |
224 << QuicUtils::TagToString(tag_); | |
225 return receive_value_; | |
226 } | |
227 | |
228 void QuicFixedUint32::SetReceivedValue(uint32_t value) { | |
229 has_receive_value_ = true; | |
230 receive_value_ = value; | |
231 } | |
232 | |
233 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const { | |
234 if (has_send_value_) { | |
235 out->SetValue(tag_, send_value_); | |
236 } | |
237 } | |
238 | |
239 QuicErrorCode QuicFixedUint32::ProcessPeerHello( | |
240 const CryptoHandshakeMessage& peer_hello, | |
241 HelloType hello_type, | |
242 string* error_details) { | |
243 DCHECK(error_details != nullptr); | |
244 QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_); | |
245 switch (error) { | |
246 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: | |
247 if (presence_ == PRESENCE_OPTIONAL) { | |
248 return QUIC_NO_ERROR; | |
249 } | |
250 *error_details = "Missing " + QuicUtils::TagToString(tag_); | |
251 break; | |
252 case QUIC_NO_ERROR: | |
253 has_receive_value_ = true; | |
254 break; | |
255 default: | |
256 *error_details = "Bad " + QuicUtils::TagToString(tag_); | |
257 break; | |
258 } | |
259 return error; | |
260 } | |
261 | |
262 QuicFixedTagVector::QuicFixedTagVector(QuicTag name, | |
263 QuicConfigPresence presence) | |
264 : QuicConfigValue(name, presence), | |
265 has_send_values_(false), | |
266 has_receive_values_(false) {} | |
267 | |
268 QuicFixedTagVector::QuicFixedTagVector(const QuicFixedTagVector& other) = | |
269 default; | |
270 | |
271 QuicFixedTagVector::~QuicFixedTagVector() {} | |
272 | |
273 bool QuicFixedTagVector::HasSendValues() const { | |
274 return has_send_values_; | |
275 } | |
276 | |
277 QuicTagVector QuicFixedTagVector::GetSendValues() const { | |
278 QUIC_BUG_IF(!has_send_values_) << "No send values to get for tag:" | |
279 << QuicUtils::TagToString(tag_); | |
280 return send_values_; | |
281 } | |
282 | |
283 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) { | |
284 has_send_values_ = true; | |
285 send_values_ = values; | |
286 } | |
287 | |
288 bool QuicFixedTagVector::HasReceivedValues() const { | |
289 return has_receive_values_; | |
290 } | |
291 | |
292 QuicTagVector QuicFixedTagVector::GetReceivedValues() const { | |
293 QUIC_BUG_IF(!has_receive_values_) << "No receive value to get for tag:" | |
294 << QuicUtils::TagToString(tag_); | |
295 return receive_values_; | |
296 } | |
297 | |
298 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) { | |
299 has_receive_values_ = true; | |
300 receive_values_ = values; | |
301 } | |
302 | |
303 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const { | |
304 if (has_send_values_) { | |
305 out->SetVector(tag_, send_values_); | |
306 } | |
307 } | |
308 | |
309 QuicErrorCode QuicFixedTagVector::ProcessPeerHello( | |
310 const CryptoHandshakeMessage& peer_hello, | |
311 HelloType hello_type, | |
312 string* error_details) { | |
313 DCHECK(error_details != nullptr); | |
314 const QuicTag* received_tags; | |
315 size_t received_tags_length; | |
316 QuicErrorCode error = | |
317 peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length); | |
318 switch (error) { | |
319 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: | |
320 if (presence_ == PRESENCE_OPTIONAL) { | |
321 return QUIC_NO_ERROR; | |
322 } | |
323 *error_details = "Missing " + QuicUtils::TagToString(tag_); | |
324 break; | |
325 case QUIC_NO_ERROR: | |
326 DVLOG(1) << "Received Connection Option tags from receiver."; | |
327 has_receive_values_ = true; | |
328 for (size_t i = 0; i < received_tags_length; ++i) { | |
329 receive_values_.push_back(received_tags[i]); | |
330 } | |
331 break; | |
332 default: | |
333 *error_details = "Bad " + QuicUtils::TagToString(tag_); | |
334 break; | |
335 } | |
336 return error; | |
337 } | |
338 | |
339 QuicFixedIPEndPoint::QuicFixedIPEndPoint(QuicTag tag, | |
340 QuicConfigPresence presence) | |
341 : QuicConfigValue(tag, presence), | |
342 has_send_value_(false), | |
343 has_receive_value_(false) {} | |
344 | |
345 QuicFixedIPEndPoint::~QuicFixedIPEndPoint() {} | |
346 | |
347 bool QuicFixedIPEndPoint::HasSendValue() const { | |
348 return has_send_value_; | |
349 } | |
350 | |
351 const IPEndPoint& QuicFixedIPEndPoint::GetSendValue() const { | |
352 QUIC_BUG_IF(!has_send_value_) << "No send value to get for tag:" | |
353 << QuicUtils::TagToString(tag_); | |
354 return send_value_; | |
355 } | |
356 | |
357 void QuicFixedIPEndPoint::SetSendValue(const IPEndPoint& value) { | |
358 has_send_value_ = true; | |
359 send_value_ = value; | |
360 } | |
361 | |
362 bool QuicFixedIPEndPoint::HasReceivedValue() const { | |
363 return has_receive_value_; | |
364 } | |
365 | |
366 const IPEndPoint& QuicFixedIPEndPoint::GetReceivedValue() const { | |
367 QUIC_BUG_IF(!has_receive_value_) << "No receive value to get for tag:" | |
368 << QuicUtils::TagToString(tag_); | |
369 return receive_value_; | |
370 } | |
371 | |
372 void QuicFixedIPEndPoint::SetReceivedValue(const IPEndPoint& value) { | |
373 has_receive_value_ = true; | |
374 receive_value_ = value; | |
375 } | |
376 | |
377 void QuicFixedIPEndPoint::ToHandshakeMessage( | |
378 CryptoHandshakeMessage* out) const { | |
379 if (has_send_value_) { | |
380 QuicSocketAddressCoder address_coder(send_value_); | |
381 out->SetStringPiece(tag_, address_coder.Encode()); | |
382 } | |
383 } | |
384 | |
385 QuicErrorCode QuicFixedIPEndPoint::ProcessPeerHello( | |
386 const CryptoHandshakeMessage& peer_hello, | |
387 HelloType hello_type, | |
388 string* error_details) { | |
389 base::StringPiece address; | |
390 if (!peer_hello.GetStringPiece(tag_, &address)) { | |
391 if (presence_ == PRESENCE_REQUIRED) { | |
392 *error_details = "Missing " + QuicUtils::TagToString(tag_); | |
393 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | |
394 } | |
395 } else { | |
396 QuicSocketAddressCoder address_coder; | |
397 if (address_coder.Decode(address.data(), address.length())) { | |
398 SetReceivedValue(IPEndPoint(address_coder.ip(), address_coder.port())); | |
399 } | |
400 } | |
401 return QUIC_NO_ERROR; | |
402 } | |
403 | |
404 QuicConfig::QuicConfig() | |
405 : max_time_before_crypto_handshake_(QuicTime::Delta::Zero()), | |
406 max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()), | |
407 max_undecryptable_packets_(0), | |
408 connection_options_(kCOPT, PRESENCE_OPTIONAL), | |
409 idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED), | |
410 silent_close_(kSCLS, PRESENCE_OPTIONAL), | |
411 max_streams_per_connection_(kMSPC, PRESENCE_OPTIONAL), | |
412 max_incoming_dynamic_streams_(kMIDS, PRESENCE_OPTIONAL), | |
413 bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL), | |
414 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL), | |
415 initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL), | |
416 initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL), | |
417 socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL), | |
418 multipath_enabled_(kMPTH, PRESENCE_OPTIONAL), | |
419 connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL), | |
420 alternate_server_address_(kASAD, PRESENCE_OPTIONAL), | |
421 force_hol_blocking_(kFHOL, PRESENCE_OPTIONAL) { | |
422 SetDefaults(); | |
423 } | |
424 | |
425 QuicConfig::QuicConfig(const QuicConfig& other) = default; | |
426 | |
427 QuicConfig::~QuicConfig() {} | |
428 | |
429 bool QuicConfig::SetInitialReceivedConnectionOptions( | |
430 const QuicTagVector& tags) { | |
431 if (HasReceivedConnectionOptions()) { | |
432 // If we have already received connection options (via handshake or due to a | |
433 // previous call), don't re-initialize. | |
434 return false; | |
435 } | |
436 connection_options_.SetReceivedValues(tags); | |
437 return true; | |
438 } | |
439 | |
440 void QuicConfig::SetConnectionOptionsToSend( | |
441 const QuicTagVector& connection_options) { | |
442 connection_options_.SetSendValues(connection_options); | |
443 } | |
444 | |
445 bool QuicConfig::HasReceivedConnectionOptions() const { | |
446 return connection_options_.HasReceivedValues(); | |
447 } | |
448 | |
449 QuicTagVector QuicConfig::ReceivedConnectionOptions() const { | |
450 return connection_options_.GetReceivedValues(); | |
451 } | |
452 | |
453 bool QuicConfig::HasSendConnectionOptions() const { | |
454 return connection_options_.HasSendValues(); | |
455 } | |
456 | |
457 QuicTagVector QuicConfig::SendConnectionOptions() const { | |
458 return connection_options_.GetSendValues(); | |
459 } | |
460 | |
461 bool QuicConfig::HasClientSentConnectionOption(QuicTag tag, | |
462 Perspective perspective) const { | |
463 if (perspective == Perspective::IS_SERVER) { | |
464 if (HasReceivedConnectionOptions() && | |
465 ContainsQuicTag(ReceivedConnectionOptions(), tag)) { | |
466 return true; | |
467 } | |
468 } else if (HasSendConnectionOptions() && | |
469 ContainsQuicTag(SendConnectionOptions(), tag)) { | |
470 return true; | |
471 } | |
472 return false; | |
473 } | |
474 | |
475 void QuicConfig::SetIdleConnectionStateLifetime( | |
476 QuicTime::Delta max_idle_connection_state_lifetime, | |
477 QuicTime::Delta default_idle_conection_state_lifetime) { | |
478 idle_connection_state_lifetime_seconds_.set( | |
479 static_cast<uint32_t>(max_idle_connection_state_lifetime.ToSeconds()), | |
480 static_cast<uint32_t>(default_idle_conection_state_lifetime.ToSeconds())); | |
481 } | |
482 | |
483 QuicTime::Delta QuicConfig::IdleConnectionStateLifetime() const { | |
484 return QuicTime::Delta::FromSeconds( | |
485 idle_connection_state_lifetime_seconds_.GetUint32()); | |
486 } | |
487 | |
488 // TODO(ianswett) Use this for silent close on mobile, or delete. | |
489 void QuicConfig::SetSilentClose(bool silent_close) { | |
490 silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0); | |
491 } | |
492 | |
493 bool QuicConfig::SilentClose() const { | |
494 return silent_close_.GetUint32() > 0; | |
495 } | |
496 | |
497 void QuicConfig::SetMaxStreamsPerConnection(size_t max_streams, | |
498 size_t default_streams) { | |
499 max_streams_per_connection_.set(max_streams, default_streams); | |
500 } | |
501 | |
502 uint32_t QuicConfig::MaxStreamsPerConnection() const { | |
503 return max_streams_per_connection_.GetUint32(); | |
504 } | |
505 | |
506 void QuicConfig::SetMaxIncomingDynamicStreamsToSend( | |
507 uint32_t max_incoming_dynamic_streams) { | |
508 max_incoming_dynamic_streams_.SetSendValue(max_incoming_dynamic_streams); | |
509 } | |
510 | |
511 uint32_t QuicConfig::GetMaxIncomingDynamicStreamsToSend() { | |
512 return max_incoming_dynamic_streams_.GetSendValue(); | |
513 } | |
514 | |
515 bool QuicConfig::HasReceivedMaxIncomingDynamicStreams() { | |
516 return max_incoming_dynamic_streams_.HasReceivedValue(); | |
517 } | |
518 | |
519 uint32_t QuicConfig::ReceivedMaxIncomingDynamicStreams() { | |
520 return max_incoming_dynamic_streams_.GetReceivedValue(); | |
521 } | |
522 | |
523 bool QuicConfig::HasSetBytesForConnectionIdToSend() const { | |
524 return bytes_for_connection_id_.HasSendValue(); | |
525 } | |
526 | |
527 void QuicConfig::SetBytesForConnectionIdToSend(uint32_t bytes) { | |
528 bytes_for_connection_id_.SetSendValue(bytes); | |
529 } | |
530 | |
531 bool QuicConfig::HasReceivedBytesForConnectionId() const { | |
532 return bytes_for_connection_id_.HasReceivedValue(); | |
533 } | |
534 | |
535 uint32_t QuicConfig::ReceivedBytesForConnectionId() const { | |
536 return bytes_for_connection_id_.GetReceivedValue(); | |
537 } | |
538 | |
539 void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32_t rtt) { | |
540 initial_round_trip_time_us_.SetSendValue(rtt); | |
541 } | |
542 | |
543 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const { | |
544 return initial_round_trip_time_us_.HasReceivedValue(); | |
545 } | |
546 | |
547 uint32_t QuicConfig::ReceivedInitialRoundTripTimeUs() const { | |
548 return initial_round_trip_time_us_.GetReceivedValue(); | |
549 } | |
550 | |
551 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const { | |
552 return initial_round_trip_time_us_.HasSendValue(); | |
553 } | |
554 | |
555 uint32_t QuicConfig::GetInitialRoundTripTimeUsToSend() const { | |
556 return initial_round_trip_time_us_.GetSendValue(); | |
557 } | |
558 | |
559 void QuicConfig::SetInitialStreamFlowControlWindowToSend( | |
560 uint32_t window_bytes) { | |
561 if (window_bytes < kMinimumFlowControlSendWindow) { | |
562 QUIC_BUG << "Initial stream flow control receive window (" << window_bytes | |
563 << ") cannot be set lower than default (" | |
564 << kMinimumFlowControlSendWindow << ")."; | |
565 window_bytes = kMinimumFlowControlSendWindow; | |
566 } | |
567 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes); | |
568 } | |
569 | |
570 uint32_t QuicConfig::GetInitialStreamFlowControlWindowToSend() const { | |
571 return initial_stream_flow_control_window_bytes_.GetSendValue(); | |
572 } | |
573 | |
574 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const { | |
575 return initial_stream_flow_control_window_bytes_.HasReceivedValue(); | |
576 } | |
577 | |
578 uint32_t QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const { | |
579 return initial_stream_flow_control_window_bytes_.GetReceivedValue(); | |
580 } | |
581 | |
582 void QuicConfig::SetInitialSessionFlowControlWindowToSend( | |
583 uint32_t window_bytes) { | |
584 if (window_bytes < kMinimumFlowControlSendWindow) { | |
585 QUIC_BUG << "Initial session flow control receive window (" << window_bytes | |
586 << ") cannot be set lower than default (" | |
587 << kMinimumFlowControlSendWindow << ")."; | |
588 window_bytes = kMinimumFlowControlSendWindow; | |
589 } | |
590 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes); | |
591 } | |
592 | |
593 uint32_t QuicConfig::GetInitialSessionFlowControlWindowToSend() const { | |
594 return initial_session_flow_control_window_bytes_.GetSendValue(); | |
595 } | |
596 | |
597 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const { | |
598 return initial_session_flow_control_window_bytes_.HasReceivedValue(); | |
599 } | |
600 | |
601 uint32_t QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const { | |
602 return initial_session_flow_control_window_bytes_.GetReceivedValue(); | |
603 } | |
604 | |
605 void QuicConfig::SetSocketReceiveBufferToSend(uint32_t tcp_receive_window) { | |
606 socket_receive_buffer_.SetSendValue(tcp_receive_window); | |
607 } | |
608 | |
609 bool QuicConfig::HasReceivedSocketReceiveBuffer() const { | |
610 return socket_receive_buffer_.HasReceivedValue(); | |
611 } | |
612 | |
613 uint32_t QuicConfig::ReceivedSocketReceiveBuffer() const { | |
614 return socket_receive_buffer_.GetReceivedValue(); | |
615 } | |
616 | |
617 void QuicConfig::SetMultipathEnabled(bool multipath_enabled) { | |
618 uint32_t value = multipath_enabled ? 1 : 0; | |
619 multipath_enabled_.set(value, value); | |
620 } | |
621 | |
622 bool QuicConfig::MultipathEnabled() const { | |
623 return multipath_enabled_.GetUint32() > 0; | |
624 } | |
625 | |
626 void QuicConfig::SetDisableConnectionMigration() { | |
627 connection_migration_disabled_.SetSendValue(1); | |
628 } | |
629 | |
630 bool QuicConfig::DisableConnectionMigration() const { | |
631 return connection_migration_disabled_.HasReceivedValue(); | |
632 } | |
633 | |
634 void QuicConfig::SetAlternateServerAddressToSend( | |
635 const IPEndPoint& alternate_server_address) { | |
636 alternate_server_address_.SetSendValue(alternate_server_address); | |
637 } | |
638 | |
639 bool QuicConfig::HasReceivedAlternateServerAddress() const { | |
640 return alternate_server_address_.HasReceivedValue(); | |
641 } | |
642 | |
643 const IPEndPoint& QuicConfig::ReceivedAlternateServerAddress() const { | |
644 return alternate_server_address_.GetReceivedValue(); | |
645 } | |
646 | |
647 void QuicConfig::SetForceHolBlocking() { | |
648 force_hol_blocking_.SetSendValue(1); | |
649 } | |
650 | |
651 bool QuicConfig::ForceHolBlocking(Perspective perspective) const { | |
652 if (perspective == Perspective::IS_SERVER) { | |
653 return force_hol_blocking_.HasReceivedValue(); | |
654 } else { | |
655 return force_hol_blocking_.HasSendValue(); | |
656 } | |
657 } | |
658 | |
659 bool QuicConfig::negotiated() const { | |
660 // TODO(ianswett): Add the negotiated parameters once and iterate over all | |
661 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and | |
662 // ProcessServerHello. | |
663 return idle_connection_state_lifetime_seconds_.negotiated() && | |
664 max_streams_per_connection_.negotiated(); | |
665 } | |
666 | |
667 void QuicConfig::SetDefaults() { | |
668 idle_connection_state_lifetime_seconds_.set(kMaximumIdleTimeoutSecs, | |
669 kDefaultIdleTimeoutSecs); | |
670 silent_close_.set(1, 0); | |
671 SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection, | |
672 kDefaultMaxStreamsPerConnection); | |
673 SetMaxIncomingDynamicStreamsToSend(kDefaultMaxStreamsPerConnection); | |
674 max_time_before_crypto_handshake_ = | |
675 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs); | |
676 max_idle_time_before_crypto_handshake_ = | |
677 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs); | |
678 max_undecryptable_packets_ = kDefaultMaxUndecryptablePackets; | |
679 | |
680 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow); | |
681 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow); | |
682 } | |
683 | |
684 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { | |
685 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out); | |
686 silent_close_.ToHandshakeMessage(out); | |
687 max_streams_per_connection_.ToHandshakeMessage(out); | |
688 max_incoming_dynamic_streams_.ToHandshakeMessage(out); | |
689 bytes_for_connection_id_.ToHandshakeMessage(out); | |
690 initial_round_trip_time_us_.ToHandshakeMessage(out); | |
691 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out); | |
692 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out); | |
693 socket_receive_buffer_.ToHandshakeMessage(out); | |
694 connection_migration_disabled_.ToHandshakeMessage(out); | |
695 connection_options_.ToHandshakeMessage(out); | |
696 alternate_server_address_.ToHandshakeMessage(out); | |
697 } | |
698 | |
699 QuicErrorCode QuicConfig::ProcessPeerHello( | |
700 const CryptoHandshakeMessage& peer_hello, | |
701 HelloType hello_type, | |
702 string* error_details) { | |
703 DCHECK(error_details != nullptr); | |
704 | |
705 QuicErrorCode error = QUIC_NO_ERROR; | |
706 if (error == QUIC_NO_ERROR) { | |
707 error = idle_connection_state_lifetime_seconds_.ProcessPeerHello( | |
708 peer_hello, hello_type, error_details); | |
709 } | |
710 if (error == QUIC_NO_ERROR) { | |
711 error = | |
712 silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details); | |
713 } | |
714 if (error == QUIC_NO_ERROR) { | |
715 error = max_streams_per_connection_.ProcessPeerHello(peer_hello, hello_type, | |
716 error_details); | |
717 } | |
718 if (error == QUIC_NO_ERROR) { | |
719 error = max_incoming_dynamic_streams_.ProcessPeerHello( | |
720 peer_hello, hello_type, error_details); | |
721 } | |
722 if (error == QUIC_NO_ERROR) { | |
723 error = bytes_for_connection_id_.ProcessPeerHello(peer_hello, hello_type, | |
724 error_details); | |
725 } | |
726 if (error == QUIC_NO_ERROR) { | |
727 error = initial_round_trip_time_us_.ProcessPeerHello(peer_hello, hello_type, | |
728 error_details); | |
729 } | |
730 if (error == QUIC_NO_ERROR) { | |
731 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello( | |
732 peer_hello, hello_type, error_details); | |
733 } | |
734 if (error == QUIC_NO_ERROR) { | |
735 error = initial_session_flow_control_window_bytes_.ProcessPeerHello( | |
736 peer_hello, hello_type, error_details); | |
737 } | |
738 if (error == QUIC_NO_ERROR) { | |
739 error = socket_receive_buffer_.ProcessPeerHello(peer_hello, hello_type, | |
740 error_details); | |
741 } | |
742 if (error == QUIC_NO_ERROR) { | |
743 error = connection_migration_disabled_.ProcessPeerHello( | |
744 peer_hello, hello_type, error_details); | |
745 } | |
746 if (error == QUIC_NO_ERROR) { | |
747 error = connection_options_.ProcessPeerHello(peer_hello, hello_type, | |
748 error_details); | |
749 } | |
750 if (error == QUIC_NO_ERROR) { | |
751 error = alternate_server_address_.ProcessPeerHello(peer_hello, hello_type, | |
752 error_details); | |
753 } | |
754 return error; | |
755 } | |
756 | |
757 } // namespace net | |
OLD | NEW |