| 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 |