Index: net/quic/quic_session.cc |
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc |
index 512044f9fb4e15b20751010060ff67fa004897f7..9b28103c8f9ed75d0a24f8e723829b7f02e7f412 100644 |
--- a/net/quic/quic_session.cc |
+++ b/net/quic/quic_session.cc |
@@ -79,8 +79,8 @@ class VisitorShim : public QuicConnectionVisitorInterface { |
session_->OnWriteBlocked(); |
} |
- virtual bool HasPendingWrites() const OVERRIDE { |
- return session_->HasPendingWrites(); |
+ virtual bool WillingAndAbleToWrite() const OVERRIDE { |
+ return session_->WillingAndAbleToWrite(); |
} |
virtual bool HasPendingHandshake() const OVERRIDE { |
@@ -275,9 +275,22 @@ void QuicSession::OnBlockedFrames(const vector<QuicBlockedFrame>& frames) { |
void QuicSession::OnCanWrite() { |
// We limit the number of writes to the number of pending streams. If more |
- // streams become pending, HasPendingWrites will be true, which will cause |
- // the connection to request resumption before yielding to other connections. |
+ // streams become pending, WillingAndAbleToWrite will be true, which will |
+ // cause the connection to request resumption before yielding to other |
+ // connections. |
size_t num_writes = write_blocked_streams_.NumBlockedStreams(); |
+ if (flow_controller_->IsBlocked()) { |
+ // If we are connection level flow control blocked, then only allow the |
+ // crypto and headers streams to try writing as all other streams will be |
+ // blocked. |
+ num_writes = 0; |
+ if (write_blocked_streams_.crypto_stream_blocked()) { |
+ num_writes += 1; |
+ } |
+ if (write_blocked_streams_.headers_stream_blocked()) { |
+ num_writes += 1; |
+ } |
+ } |
if (num_writes == 0) { |
return; |
} |
@@ -285,7 +298,8 @@ void QuicSession::OnCanWrite() { |
QuicConnection::ScopedPacketBundler ack_bundler( |
connection_.get(), QuicConnection::NO_ACK); |
for (size_t i = 0; i < num_writes; ++i) { |
- if (!write_blocked_streams_.HasWriteBlockedStreams()) { |
+ if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || |
+ write_blocked_streams_.HasWriteBlockedDataStreams())) { |
// Writing one stream removed another!? Something's broken. |
LOG(DFATAL) << "WriteBlockedStream is missing"; |
connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); |
@@ -307,8 +321,14 @@ void QuicSession::OnCanWrite() { |
} |
} |
-bool QuicSession::HasPendingWrites() const { |
- return write_blocked_streams_.HasWriteBlockedStreams(); |
+bool QuicSession::WillingAndAbleToWrite() const { |
+ // If the crypto or headers streams are blocked, we want to schedule a write - |
+ // they don't get blocked by connection level flow control. Otherwise only |
+ // schedule a write if we are not flow control blocked at the connection |
+ // level. |
+ return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || |
+ (!flow_controller_->IsBlocked() && |
+ write_blocked_streams_.HasWriteBlockedDataStreams()); |
} |
bool QuicSession::HasPendingHandshake() const { |
@@ -604,8 +624,9 @@ void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) { |
} |
bool QuicSession::HasDataToWrite() const { |
- return write_blocked_streams_.HasWriteBlockedStreams() || |
- connection_->HasQueuedData(); |
+ return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || |
+ write_blocked_streams_.HasWriteBlockedDataStreams() || |
+ connection_->HasQueuedData(); |
} |
bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { |