Chromium Code Reviews| Index: net/quic/quic_session.cc |
| diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc |
| index 6d749ec1fbeec599205908ccde20d1aecfae7687..9b28103c8f9ed75d0a24f8e723829b7f02e7f412 100644 |
| --- a/net/quic/quic_session.cc |
| +++ b/net/quic/quic_session.cc |
| @@ -8,6 +8,7 @@ |
| #include "net/quic/crypto/proof_verifier.h" |
| #include "net/quic/quic_connection.h" |
| #include "net/quic/quic_flags.h" |
| +#include "net/quic/quic_flow_controller.h" |
| #include "net/quic/quic_headers_stream.h" |
| #include "net/ssl/ssl_info.h" |
| @@ -78,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 { |
| @@ -95,6 +96,7 @@ class VisitorShim : public QuicConnectionVisitorInterface { |
| }; |
| QuicSession::QuicSession(QuicConnection* connection, |
| + uint32 max_flow_control_receive_window_bytes, |
| const QuicConfig& config) |
| : connection_(connection), |
| visitor_shim_(new VisitorShim(this)), |
| @@ -105,7 +107,20 @@ QuicSession::QuicSession(QuicConnection* connection, |
| error_(QUIC_NO_ERROR), |
| goaway_received_(false), |
| goaway_sent_(false), |
| - has_pending_handshake_(false) { |
| + has_pending_handshake_(false), |
| + max_flow_control_receive_window_bytes_( |
| + max_flow_control_receive_window_bytes) { |
| + if (max_flow_control_receive_window_bytes_ < kDefaultFlowControlSendWindow) { |
| + LOG(ERROR) << "Initial receive window (" |
| + << max_flow_control_receive_window_bytes_ |
| + << ") cannot be set lower than default (" |
| + << kDefaultFlowControlSendWindow << ")."; |
| + max_flow_control_receive_window_bytes_ = kDefaultFlowControlSendWindow; |
| + } |
| + flow_controller_.reset(new QuicFlowController( |
| + connection_->supported_versions().front(), 0, is_server(), |
| + kDefaultFlowControlSendWindow, max_flow_control_receive_window_bytes_, |
| + max_flow_control_receive_window_bytes_)); |
| connection_->set_visitor(visitor_shim_.get()); |
| connection_->SetFromConfig(config_); |
| @@ -229,8 +244,7 @@ void QuicSession::OnWindowUpdateFrames( |
| << "Received connection level flow control window update with " |
| "byte offset: " << frames[i].byte_offset; |
| if (FLAGS_enable_quic_connection_flow_control && |
| - connection()->flow_controller()->UpdateSendWindowOffset( |
| - frames[i].byte_offset)) { |
| + flow_controller_->UpdateSendWindowOffset(frames[i].byte_offset)) { |
| connection_window_updated = true; |
| } |
| continue; |
| @@ -261,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; |
| } |
| @@ -271,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())) { |
|
wtc
2014/05/19 18:58:40
Nit: I would simplify this expression with De Morg
ramant (doing other things)
2014/05/20 03:22:32
rjshade: wdyt?
|
| // Writing one stream removed another!? Something's broken. |
| LOG(DFATAL) << "WriteBlockedStream is missing"; |
| connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); |
| @@ -293,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 { |
| @@ -399,8 +433,7 @@ void QuicSession::OnConfigNegotiated() { |
| } |
| // Update connection level window. |
| - connection()->flow_controller()->UpdateSendWindowOffset( |
| - new_flow_control_send_window); |
| + flow_controller_->UpdateSendWindowOffset(new_flow_control_send_window); |
| } |
| } |
| @@ -591,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 { |
| @@ -605,4 +639,10 @@ void QuicSession::PostProcessAfterData() { |
| closed_streams_.clear(); |
| } |
| +void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { |
| + if (version < QUIC_VERSION_19) { |
| + flow_controller_->Disable(); |
| + } |
| +} |
| + |
| } // namespace net |