OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_session.h" | 5 #include "net/quic/quic_session.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "net/quic/crypto/proof_verifier.h" | 10 #include "net/quic/crypto/proof_verifier.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 perspective() == Perspective::IS_SERVER ? 1 : 0), | 38 perspective() == Perspective::IS_SERVER ? 1 : 0), |
39 num_dynamic_incoming_streams_(0), | 39 num_dynamic_incoming_streams_(0), |
40 num_draining_incoming_streams_(0), | 40 num_draining_incoming_streams_(0), |
41 num_locally_closed_incoming_streams_highest_offset_(0), | 41 num_locally_closed_incoming_streams_highest_offset_(0), |
42 error_(QUIC_NO_ERROR), | 42 error_(QUIC_NO_ERROR), |
43 flow_controller_(connection_.get(), | 43 flow_controller_(connection_.get(), |
44 0, | 44 0, |
45 perspective(), | 45 perspective(), |
46 kMinimumFlowControlSendWindow, | 46 kMinimumFlowControlSendWindow, |
47 config_.GetInitialSessionFlowControlWindowToSend(), | 47 config_.GetInitialSessionFlowControlWindowToSend(), |
48 false), | 48 perspective() == Perspective::IS_SERVER), |
49 currently_writing_stream_id_(0) {} | 49 currently_writing_stream_id_(0) {} |
50 | 50 |
51 void QuicSession::Initialize() { | 51 void QuicSession::Initialize() { |
52 connection_->set_visitor(this); | 52 connection_->set_visitor(this); |
53 connection_->SetFromConfig(config_); | 53 connection_->SetFromConfig(config_); |
54 | 54 |
55 DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); | 55 DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); |
56 static_stream_map_[kCryptoStreamId] = GetCryptoStream(); | 56 static_stream_map_[kCryptoStreamId] = GetCryptoStream(); |
57 } | 57 } |
58 | 58 |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 } | 368 } |
369 | 369 |
370 bool QuicSession::IsCryptoHandshakeConfirmed() { | 370 bool QuicSession::IsCryptoHandshakeConfirmed() { |
371 return GetCryptoStream()->handshake_confirmed(); | 371 return GetCryptoStream()->handshake_confirmed(); |
372 } | 372 } |
373 | 373 |
374 void QuicSession::OnConfigNegotiated() { | 374 void QuicSession::OnConfigNegotiated() { |
375 connection_->SetFromConfig(config_); | 375 connection_->SetFromConfig(config_); |
376 | 376 |
377 uint32_t max_streams = config_.MaxStreamsPerConnection(); | 377 uint32_t max_streams = config_.MaxStreamsPerConnection(); |
378 if (perspective() == Perspective::IS_SERVER) { | |
379 if (config_.HasReceivedConnectionOptions()) { | |
380 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kAFCW)) { | |
381 // The following variations change the initial receive flow control | |
382 // window sizes. | |
383 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW5)) { | |
384 AdjustInitialFlowControlWindows(32 * 1024); | |
385 } | |
386 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW6)) { | |
387 AdjustInitialFlowControlWindows(64 * 1024); | |
388 } | |
389 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW7)) { | |
390 AdjustInitialFlowControlWindows(128 * 1024); | |
391 } | |
392 EnableAutoTuneReceiveWindow(); | |
393 } | |
394 } | |
395 } | |
396 | 378 |
397 set_max_open_outgoing_streams(max_streams); | 379 set_max_open_outgoing_streams(max_streams); |
398 | 380 |
399 // A small number of additional incoming streams beyond the limit should be | 381 // A small number of additional incoming streams beyond the limit should be |
400 // allowed. This helps avoid early connection termination when FIN/RSTs for | 382 // allowed. This helps avoid early connection termination when FIN/RSTs for |
401 // old streams are lost or arrive out of order. | 383 // old streams are lost or arrive out of order. |
402 // Use a minimum number of additional streams, or a percentage increase, | 384 // Use a minimum number of additional streams, or a percentage increase, |
403 // whichever is larger. | 385 // whichever is larger. |
404 uint32_t max_incoming_streams = | 386 uint32_t max_incoming_streams = |
405 max(max_streams + kMaxStreamsMinimumIncrement, | 387 max(max_streams + kMaxStreamsMinimumIncrement, |
406 static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); | 388 static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); |
407 set_max_open_incoming_streams(max_incoming_streams); | 389 set_max_open_incoming_streams(max_incoming_streams); |
408 | 390 |
409 if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) { | 391 if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) { |
410 // Streams which were created before the SHLO was received (0-RTT | 392 // Streams which were created before the SHLO was received (0-RTT |
411 // requests) are now informed of the peer's initial flow control window. | 393 // requests) are now informed of the peer's initial flow control window. |
412 OnNewStreamFlowControlWindow( | 394 OnNewStreamFlowControlWindow( |
413 config_.ReceivedInitialStreamFlowControlWindowBytes()); | 395 config_.ReceivedInitialStreamFlowControlWindowBytes()); |
414 } | 396 } |
415 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) { | 397 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) { |
416 OnNewSessionFlowControlWindow( | 398 OnNewSessionFlowControlWindow( |
417 config_.ReceivedInitialSessionFlowControlWindowBytes()); | 399 config_.ReceivedInitialSessionFlowControlWindowBytes()); |
418 } | 400 } |
419 } | 401 } |
420 | 402 |
421 void QuicSession::EnableAutoTuneReceiveWindow() { | |
422 DVLOG(1) << ENDPOINT << "Enable auto tune receive windows"; | |
423 flow_controller_.set_auto_tune_receive_window(true); | |
424 // Inform all existing streams about the new window. | |
425 for (auto const& kv : static_stream_map_) { | |
426 kv.second->flow_controller()->set_auto_tune_receive_window(true); | |
427 } | |
428 for (auto const& kv : dynamic_stream_map_) { | |
429 kv.second->flow_controller()->set_auto_tune_receive_window(true); | |
430 } | |
431 } | |
432 | |
433 void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) { | |
434 const float session_window_multiplier = | |
435 config_.GetInitialStreamFlowControlWindowToSend() | |
436 ? static_cast<float>( | |
437 config_.GetInitialSessionFlowControlWindowToSend()) / | |
438 config_.GetInitialStreamFlowControlWindowToSend() | |
439 : 1.0; | |
440 DVLOG(1) << ENDPOINT << "Set stream receive window to " << stream_window; | |
441 config_.SetInitialStreamFlowControlWindowToSend(stream_window); | |
442 // Reduce the session window as well, motivation is reducing resource waste | |
443 // and denial of service vulnerability, as with the stream window. Session | |
444 // size is set according to the ratio between session and stream window size | |
445 // previous to auto-tuning. Note that the ratio may change dynamically, since | |
446 // auto-tuning acts independently for each flow controller. | |
447 size_t session_window = session_window_multiplier * stream_window; | |
448 DVLOG(1) << ENDPOINT << "Set session receive window to " << session_window; | |
449 config_.SetInitialSessionFlowControlWindowToSend(session_window); | |
450 flow_controller_.UpdateReceiveWindowSize(session_window); | |
451 // Inform all existing streams about the new window. | |
452 for (auto const& kv : static_stream_map_) { | |
453 kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window); | |
454 } | |
455 for (auto const& kv : dynamic_stream_map_) { | |
456 kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window); | |
457 } | |
458 } | |
459 | |
460 void QuicSession::HandleFrameOnNonexistentOutgoingStream( | 403 void QuicSession::HandleFrameOnNonexistentOutgoingStream( |
461 QuicStreamId stream_id) { | 404 QuicStreamId stream_id) { |
462 DCHECK(!IsClosedStream(stream_id)); | 405 DCHECK(!IsClosedStream(stream_id)); |
463 // Received a frame for a locally-created stream that is not currently | 406 // Received a frame for a locally-created stream that is not currently |
464 // active. This is an error. | 407 // active. This is an error. |
465 connection()->CloseConnection( | 408 connection()->CloseConnection( |
466 QUIC_INVALID_STREAM_ID, "Data for nonexistent stream", | 409 QUIC_INVALID_STREAM_ID, "Data for nonexistent stream", |
467 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 410 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
468 } | 411 } |
469 | 412 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 | 742 |
800 size_t QuicSession::MaxAvailableStreams() const { | 743 size_t QuicSession::MaxAvailableStreams() const { |
801 return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier; | 744 return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier; |
802 } | 745 } |
803 | 746 |
804 bool QuicSession::IsIncomingStream(QuicStreamId id) const { | 747 bool QuicSession::IsIncomingStream(QuicStreamId id) const { |
805 return id % 2 != next_outgoing_stream_id_ % 2; | 748 return id % 2 != next_outgoing_stream_id_ % 2; |
806 } | 749 } |
807 | 750 |
808 } // namespace net | 751 } // namespace net |
OLD | NEW |