| 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();
|
| }
|
|
|