Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(583)

Unified Diff: net/quic/quic_session.cc

Issue 320263003: Connection level flow control (CLFC) accounting on receipt of FIN/RST (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_session.h ('k') | net/quic/quic_session_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_session.cc
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index e0bddfec56ff1ae1da6861714bd49b4c214acb19..6ccc534590c48fed3cafa6114120af1183204157 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -140,14 +140,30 @@ QuicSession::QuicSession(QuicConnection* connection,
QuicSession::~QuicSession() {
STLDeleteElements(&closed_streams_);
STLDeleteValues(&stream_map_);
+
+ DLOG_IF(WARNING,
+ locally_closed_streams_highest_offset_.size() > max_open_streams_)
+ << "Surprisingly high number of locally closed streams still waiting for "
+ "final byte offset: " << locally_closed_streams_highest_offset_.size();
}
void QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
for (size_t i = 0; i < frames.size(); ++i) {
// TODO(rch) deal with the error case of stream id 0.
- QuicStreamId stream_id = frames[i].stream_id;
+ const QuicStreamFrame& frame = frames[i];
+ QuicStreamId stream_id = frame.stream_id;
ReliableQuicStream* stream = GetStream(stream_id);
if (!stream) {
+ // The stream no longer exists, but we may still be interested in the
+ // final stream byte offset sent by the peer. A frame with a FIN can give
+ // us this offset.
+ if (frame.fin) {
+ QuicStreamOffset final_byte_offset =
+ frame.offset + frame.data.TotalBufferSize();
+ UpdateFlowControlOnFinalReceivedByteOffset(stream_id,
+ final_byte_offset);
+ }
+
continue;
}
stream->OnStreamFrame(frames[i]);
@@ -198,8 +214,13 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
"Attempt to reset the headers stream");
return;
}
+
QuicDataStream* stream = GetDataStream(frame.stream_id);
if (!stream) {
+ // The RST frame contains the final byte offset for the stream: we can now
+ // update the connection level flow controller if needed.
+ UpdateFlowControlOnFinalReceivedByteOffset(frame.stream_id,
+ frame.byte_offset);
return; // Errors are handled by GetStream.
}
@@ -396,10 +417,49 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id,
}
closed_streams_.push_back(it->second);
+
+ // If we haven't received a FIN or RST for this stream, we need to keep track
+ // of the how many bytes the stream's flow controller believes it has
+ // received, for accurate connection level flow control accounting.
+ if (!stream->HasFinalReceivedByteOffset() &&
+ stream->flow_controller()->IsEnabled() &&
+ FLAGS_enable_quic_connection_flow_control) {
+ locally_closed_streams_highest_offset_[stream_id] =
+ stream->flow_controller()->highest_received_byte_offset();
+ }
+
stream_map_.erase(it);
stream->OnClose();
}
+void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset(
+ QuicStreamId stream_id, QuicStreamOffset final_byte_offset) {
+ if (!FLAGS_enable_quic_connection_flow_control) {
+ return;
+ }
+
+ map<QuicStreamId, QuicStreamOffset>::iterator it =
+ locally_closed_streams_highest_offset_.find(stream_id);
+ if (it == locally_closed_streams_highest_offset_.end()) {
+ return;
+ }
+
+ DVLOG(1) << ENDPOINT << "Received final byte offset " << final_byte_offset
+ << " for stream " << stream_id;
+ uint64 offset_diff = final_byte_offset - it->second;
+ if (flow_controller_->UpdateHighestReceivedOffset(
+ flow_controller_->highest_received_byte_offset() + offset_diff)) {
+ // If the final offset violates flow control, close the connection now.
+ if (flow_controller_->FlowControlViolation()) {
+ connection_->SendConnectionClose(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
+ return;
+ }
+ }
+
+ flow_controller_->AddBytesConsumed(offset_diff);
+ locally_closed_streams_highest_offset_.erase(it);
+}
+
bool QuicSession::IsEncryptionEstablished() {
return GetCryptoStream()->encryption_established();
}
« no previous file with comments | « net/quic/quic_session.h ('k') | net/quic/quic_session_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698