Index: net/quic/quic_session.cc |
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc |
index c57dc1ed35f047153eb6880726c21ae2d8dea703..48ea0072df7b822e0d3f4145dd6a45930c031a49 100644 |
--- a/net/quic/quic_session.cc |
+++ b/net/quic/quic_session.cc |
@@ -30,84 +30,11 @@ namespace net { |
#define ENDPOINT \ |
(perspective() == Perspective::IS_SERVER ? "Server: " : " Client: ") |
-// We want to make sure we delete any closed streams in a safe manner. |
-// To avoid deleting a stream in mid-operation, we have a simple shim between |
-// us and the stream, so we can delete any streams when we return from |
-// processing. |
-// |
-// We could just override the base methods, but this makes it easier to make |
-// sure we don't miss any. |
-class VisitorShim : public QuicConnectionVisitorInterface { |
- public: |
- explicit VisitorShim(QuicSession* session) : session_(session) {} |
- |
- void OnStreamFrame(const QuicStreamFrame& frame) override { |
- session_->OnStreamFrame(frame); |
- session_->PostProcessAfterData(); |
- } |
- void OnRstStream(const QuicRstStreamFrame& frame) override { |
- session_->OnRstStream(frame); |
- session_->PostProcessAfterData(); |
- } |
- |
- void OnGoAway(const QuicGoAwayFrame& frame) override { |
- session_->OnGoAway(frame); |
- session_->PostProcessAfterData(); |
- } |
- |
- void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override { |
- session_->OnWindowUpdateFrame(frame); |
- session_->PostProcessAfterData(); |
- } |
- |
- void OnBlockedFrame(const QuicBlockedFrame& frame) override { |
- session_->OnBlockedFrame(frame); |
- session_->PostProcessAfterData(); |
- } |
- |
- void OnCanWrite() override { |
- session_->OnCanWrite(); |
- session_->PostProcessAfterData(); |
- } |
- |
- void OnCongestionWindowChange(QuicTime now) override { |
- session_->OnCongestionWindowChange(now); |
- } |
- |
- void OnSuccessfulVersionNegotiation(const QuicVersion& version) override { |
- session_->OnSuccessfulVersionNegotiation(version); |
- } |
- |
- void OnConnectionClosed(QuicErrorCode error, bool from_peer) override { |
- session_->OnConnectionClosed(error, from_peer); |
- // The session will go away, so don't bother with cleanup. |
- } |
- |
- void OnWriteBlocked() override { session_->OnWriteBlocked(); } |
- |
- void OnConnectionMigration() override { session_->OnConnectionMigration(); } |
- |
- bool WillingAndAbleToWrite() const override { |
- return session_->WillingAndAbleToWrite(); |
- } |
- |
- bool HasPendingHandshake() const override { |
- return session_->HasPendingHandshake(); |
- } |
- |
- bool HasOpenDynamicStreams() const override { |
- return session_->HasOpenDynamicStreams(); |
- } |
- |
- private: |
- QuicSession* session_; |
-}; |
- |
QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) |
: connection_(connection), |
- visitor_shim_(new VisitorShim(this)), |
config_(config), |
- max_open_streams_(config_.MaxStreamsPerConnection()), |
+ max_open_outgoing_streams_(config_.MaxStreamsPerConnection()), |
+ max_open_incoming_streams_(config_.MaxStreamsPerConnection()), |
next_outgoing_stream_id_(perspective() == Perspective::IS_SERVER ? 2 : 3), |
largest_peer_created_stream_id_( |
perspective() == Perspective::IS_SERVER ? 1 : 0), |
@@ -124,7 +51,7 @@ QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) |
currently_writing_stream_id_(0) {} |
void QuicSession::Initialize() { |
- connection_->set_visitor(visitor_shim_.get()); |
+ connection_->set_visitor(this); |
connection_->SetFromConfig(config_); |
DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); |
@@ -136,12 +63,12 @@ QuicSession::~QuicSession() { |
STLDeleteValues(&dynamic_stream_map_); |
DLOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() > |
- max_open_streams_) |
+ max_open_incoming_streams_) |
<< "Surprisingly high number of locally closed peer initiated streams" |
"still waiting for final byte offset: " |
<< num_locally_closed_incoming_streams_highest_offset(); |
- DLOG_IF(WARNING, |
- GetNumLocallyClosedOutgoingStreamsHighestOffset() > max_open_streams_) |
+ DLOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() > |
+ max_open_outgoing_streams_) |
<< "Surprisingly high number of locally closed self initiated streams" |
"still waiting for final byte offset: " |
<< GetNumLocallyClosedOutgoingStreamsHighestOffset(); |
@@ -445,14 +372,11 @@ void QuicSession::OnConfigNegotiated() { |
uint32_t max_streams = config_.MaxStreamsPerConnection(); |
if (perspective() == Perspective::IS_SERVER) { |
- // A server should accept a small number of additional streams beyond the |
- // limit sent to the client. This helps avoid early connection termination |
- // when FIN/RSTs for old streams are lost or arrive out of order. |
- // Use a minimum number of additional streams, or a percentage increase, |
- // whichever is larger. |
- max_streams = |
- max(max_streams + kMaxStreamsMinimumIncrement, |
- static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); |
+ if (!FLAGS_quic_different_max_num_open_streams) { |
+ max_streams = |
+ max(max_streams + kMaxStreamsMinimumIncrement, |
+ static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); |
+ } |
if (config_.HasReceivedConnectionOptions()) { |
if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kAFCW)) { |
@@ -471,7 +395,21 @@ void QuicSession::OnConfigNegotiated() { |
} |
} |
} |
- set_max_open_streams(max_streams); |
+ |
+ set_max_open_outgoing_streams(max_streams); |
+ |
+ uint32_t max_incoming_streams = max_streams; |
+ if (FLAGS_quic_different_max_num_open_streams) { |
+ // A small number of additional incoming streams beyond the limit should be |
+ // allowed. This helps avoid early connection termination when FIN/RSTs for |
+ // old streams are lost or arrive out of order. |
+ // Use a minimum number of additional streams, or a percentage increase, |
+ // whichever is larger. |
+ max_incoming_streams = |
+ max(max_streams + kMaxStreamsMinimumIncrement, |
+ static_cast<uint32_t>(max_streams * kMaxStreamsMultiplier)); |
+ } |
+ set_max_open_incoming_streams(max_incoming_streams); |
if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) { |
// Streams which were created before the SHLO was received (0-RTT |
@@ -683,14 +621,14 @@ bool QuicSession::MaybeIncreaseLargestPeerStreamId( |
(stream_id - largest_peer_created_stream_id_) / 2 - 1; |
size_t new_num_available_streams = |
GetNumAvailableStreams() + additional_available_streams; |
- if (new_num_available_streams > get_max_available_streams()) { |
+ if (new_num_available_streams > MaxAvailableStreams()) { |
DVLOG(1) << "Failed to create a new incoming stream with id:" << stream_id |
<< ". There are already " << GetNumAvailableStreams() |
<< " streams available, which would become " |
<< new_num_available_streams << ", which exceeds the limit " |
- << get_max_available_streams() << "."; |
+ << MaxAvailableStreams() << "."; |
string details = IntToString(new_num_available_streams) + " above " + |
- IntToString(get_max_available_streams()); |
+ IntToString(MaxAvailableStreams()); |
CloseConnectionWithDetails(QUIC_TOO_MANY_AVAILABLE_STREAMS, |
details.c_str()); |
return false; |
@@ -740,12 +678,12 @@ ReliableQuicStream* QuicSession::GetOrCreateDynamicStream( |
} |
// Check if the new number of open streams would cause the number of |
// open streams to exceed the limit. |
- size_t num_current_open_streams = |
+ size_t num_open_incoming_streams = |
FLAGS_quic_distinguish_incoming_outgoing_streams |
? GetNumOpenIncomingStreams() |
: dynamic_stream_map_.size() - draining_streams_.size() + |
locally_closed_streams_highest_offset_.size(); |
- if (num_current_open_streams >= get_max_open_streams()) { |
+ if (num_open_incoming_streams >= max_open_incoming_streams()) { |
if (connection()->version() <= QUIC_VERSION_27) { |
CloseConnectionWithDetails(QUIC_TOO_MANY_OPEN_STREAMS, |
"Old style stream rejection"); |
@@ -764,11 +702,19 @@ ReliableQuicStream* QuicSession::GetOrCreateDynamicStream( |
return stream; |
} |
-void QuicSession::set_max_open_streams(size_t max_open_streams) { |
- DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams; |
- DVLOG(1) << "Setting get_max_available_streams() to " |
- << get_max_available_streams(); |
- max_open_streams_ = max_open_streams; |
+void QuicSession::set_max_open_incoming_streams( |
+ size_t max_open_incoming_streams) { |
+ DVLOG(1) << "Setting max_open_incoming_streams_ to " |
+ << max_open_incoming_streams; |
+ max_open_incoming_streams_ = max_open_incoming_streams; |
+ DVLOG(1) << "MaxAvailableStreams() became " << MaxAvailableStreams(); |
+} |
+ |
+void QuicSession::set_max_open_outgoing_streams( |
+ size_t max_open_outgoing_streams) { |
+ DVLOG(1) << "Setting max_open_outgoing_streams_ to " |
+ << max_open_outgoing_streams; |
+ max_open_outgoing_streams_ = max_open_outgoing_streams; |
} |
bool QuicSession::goaway_sent() const { |
@@ -882,6 +828,10 @@ bool QuicSession::IsStreamFlowControlBlocked() { |
return false; |
} |
+size_t QuicSession::MaxAvailableStreams() const { |
+ return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier; |
+} |
+ |
bool QuicSession::IsIncomingStream(QuicStreamId id) const { |
return id % 2 != next_outgoing_stream_id_ % 2; |
} |