| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/core/quic_session.h" | 5 #include "net/quic/core/quic_session.h" |
| 6 | 6 |
| 7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 DLOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() > | 67 DLOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() > |
| 68 max_open_outgoing_streams_) | 68 max_open_outgoing_streams_) |
| 69 << "Surprisingly high number of locally closed self initiated streams" | 69 << "Surprisingly high number of locally closed self initiated streams" |
| 70 "still waiting for final byte offset: " | 70 "still waiting for final byte offset: " |
| 71 << GetNumLocallyClosedOutgoingStreamsHighestOffset(); | 71 << GetNumLocallyClosedOutgoingStreamsHighestOffset(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) { | 74 void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) { |
| 75 // TODO(rch) deal with the error case of stream id 0. | 75 // TODO(rch) deal with the error case of stream id 0. |
| 76 QuicStreamId stream_id = frame.stream_id; | 76 QuicStreamId stream_id = frame.stream_id; |
| 77 ReliableQuicStream* stream = GetOrCreateStream(stream_id); | 77 QuicStream* stream = GetOrCreateStream(stream_id); |
| 78 if (!stream) { | 78 if (!stream) { |
| 79 // The stream no longer exists, but we may still be interested in the | 79 // The stream no longer exists, but we may still be interested in the |
| 80 // final stream byte offset sent by the peer. A frame with a FIN can give | 80 // final stream byte offset sent by the peer. A frame with a FIN can give |
| 81 // us this offset. | 81 // us this offset. |
| 82 if (frame.fin) { | 82 if (frame.fin) { |
| 83 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length; | 83 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length; |
| 84 UpdateFlowControlOnFinalReceivedByteOffset(stream_id, final_byte_offset); | 84 UpdateFlowControlOnFinalReceivedByteOffset(stream_id, final_byte_offset); |
| 85 } | 85 } |
| 86 return; | 86 return; |
| 87 } | 87 } |
| 88 stream->OnStreamFrame(frame); | 88 stream->OnStreamFrame(frame); |
| 89 } | 89 } |
| 90 | 90 |
| 91 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { | 91 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) { |
| 92 if (base::ContainsKey(static_stream_map_, frame.stream_id)) { | 92 if (base::ContainsKey(static_stream_map_, frame.stream_id)) { |
| 93 connection()->CloseConnection( | 93 connection()->CloseConnection( |
| 94 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream", | 94 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream", |
| 95 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 95 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
| 96 return; | 96 return; |
| 97 } | 97 } |
| 98 | 98 |
| 99 ReliableQuicStream* stream = GetOrCreateDynamicStream(frame.stream_id); | 99 QuicStream* stream = GetOrCreateDynamicStream(frame.stream_id); |
| 100 if (!stream) { | 100 if (!stream) { |
| 101 HandleRstOnValidNonexistentStream(frame); | 101 HandleRstOnValidNonexistentStream(frame); |
| 102 return; // Errors are handled by GetOrCreateStream. | 102 return; // Errors are handled by GetOrCreateStream. |
| 103 } | 103 } |
| 104 | 104 |
| 105 stream->OnStreamReset(frame); | 105 stream->OnStreamReset(frame); |
| 106 } | 106 } |
| 107 | 107 |
| 108 void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { | 108 void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) { |
| 109 DCHECK(frame.last_good_stream_id < next_outgoing_stream_id_); | 109 DCHECK(frame.last_good_stream_id < next_outgoing_stream_id_); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 QuicStreamId stream_id = frame.stream_id; | 151 QuicStreamId stream_id = frame.stream_id; |
| 152 if (stream_id == kConnectionLevelId) { | 152 if (stream_id == kConnectionLevelId) { |
| 153 // This is a window update that applies to the connection, rather than an | 153 // This is a window update that applies to the connection, rather than an |
| 154 // individual stream. | 154 // individual stream. |
| 155 DVLOG(1) << ENDPOINT << "Received connection level flow control window " | 155 DVLOG(1) << ENDPOINT << "Received connection level flow control window " |
| 156 "update with byte offset: " | 156 "update with byte offset: " |
| 157 << frame.byte_offset; | 157 << frame.byte_offset; |
| 158 flow_controller_.UpdateSendWindowOffset(frame.byte_offset); | 158 flow_controller_.UpdateSendWindowOffset(frame.byte_offset); |
| 159 return; | 159 return; |
| 160 } | 160 } |
| 161 ReliableQuicStream* stream = GetOrCreateStream(stream_id); | 161 QuicStream* stream = GetOrCreateStream(stream_id); |
| 162 if (stream != nullptr) { | 162 if (stream != nullptr) { |
| 163 stream->OnWindowUpdateFrame(frame); | 163 stream->OnWindowUpdateFrame(frame); |
| 164 } | 164 } |
| 165 } | 165 } |
| 166 | 166 |
| 167 void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) { | 167 void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) { |
| 168 // TODO(rjshade): Compare our flow control receive windows for specified | 168 // TODO(rjshade): Compare our flow control receive windows for specified |
| 169 // streams: if we have a large window then maybe something | 169 // streams: if we have a large window then maybe something |
| 170 // had gone wrong with the flow control accounting. | 170 // had gone wrong with the flow control accounting. |
| 171 DVLOG(1) << ENDPOINT | 171 DVLOG(1) << ENDPOINT |
| 172 << "Received BLOCKED frame with stream id: " << frame.stream_id; | 172 << "Received BLOCKED frame with stream id: " << frame.stream_id; |
| 173 } | 173 } |
| 174 | 174 |
| 175 bool QuicSession::CheckStreamNotBusyLooping(ReliableQuicStream* stream, | 175 bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream, |
| 176 uint64_t previous_bytes_written, | 176 uint64_t previous_bytes_written, |
| 177 bool previous_fin_sent) { | 177 bool previous_fin_sent) { |
| 178 if ( // Stream should not be closed. | 178 if ( // Stream should not be closed. |
| 179 !stream->write_side_closed() && | 179 !stream->write_side_closed() && |
| 180 // Not connection flow control blocked. | 180 // Not connection flow control blocked. |
| 181 !flow_controller_.IsBlocked() && | 181 !flow_controller_.IsBlocked() && |
| 182 // Detect lack of forward progress. | 182 // Detect lack of forward progress. |
| 183 previous_bytes_written == stream->stream_bytes_written() && | 183 previous_bytes_written == stream->stream_bytes_written() && |
| 184 previous_fin_sent == stream->fin_sent()) { | 184 previous_fin_sent == stream->fin_sent()) { |
| 185 stream->set_busy_counter(stream->busy_counter() + 1); | 185 stream->set_busy_counter(stream->busy_counter() + 1); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 QUIC_BUG << "WriteBlockedStream is missing"; | 233 QUIC_BUG << "WriteBlockedStream is missing"; |
| 234 connection_->CloseConnection(QUIC_INTERNAL_ERROR, | 234 connection_->CloseConnection(QUIC_INTERNAL_ERROR, |
| 235 "WriteBlockedStream is missing", | 235 "WriteBlockedStream is missing", |
| 236 ConnectionCloseBehavior::SILENT_CLOSE); | 236 ConnectionCloseBehavior::SILENT_CLOSE); |
| 237 return; | 237 return; |
| 238 } | 238 } |
| 239 if (!connection_->CanWriteStreamData()) { | 239 if (!connection_->CanWriteStreamData()) { |
| 240 return; | 240 return; |
| 241 } | 241 } |
| 242 currently_writing_stream_id_ = write_blocked_streams_.PopFront(); | 242 currently_writing_stream_id_ = write_blocked_streams_.PopFront(); |
| 243 ReliableQuicStream* stream = | 243 QuicStream* stream = GetOrCreateStream(currently_writing_stream_id_); |
| 244 GetOrCreateStream(currently_writing_stream_id_); | |
| 245 if (stream != nullptr && !stream->flow_controller()->IsBlocked()) { | 244 if (stream != nullptr && !stream->flow_controller()->IsBlocked()) { |
| 246 // If the stream can't write all bytes it'll re-add itself to the blocked | 245 // If the stream can't write all bytes it'll re-add itself to the blocked |
| 247 // list. | 246 // list. |
| 248 uint64_t previous_bytes_written = stream->stream_bytes_written(); | 247 uint64_t previous_bytes_written = stream->stream_bytes_written(); |
| 249 bool previous_fin_sent = stream->fin_sent(); | 248 bool previous_fin_sent = stream->fin_sent(); |
| 250 DVLOG(1) << "stream " << stream->id() << " bytes_written " | 249 DVLOG(1) << "stream " << stream->id() << " bytes_written " |
| 251 << previous_bytes_written << " fin " << previous_fin_sent; | 250 << previous_bytes_written << " fin " << previous_fin_sent; |
| 252 stream->OnCanWrite(); | 251 stream->OnCanWrite(); |
| 253 DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written, | 252 DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written, |
| 254 previous_fin_sent)); | 253 previous_fin_sent)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 276 locally_closed_streams_highest_offset_.size()) > 0; | 275 locally_closed_streams_highest_offset_.size()) > 0; |
| 277 } | 276 } |
| 278 | 277 |
| 279 void QuicSession::ProcessUdpPacket(const IPEndPoint& self_address, | 278 void QuicSession::ProcessUdpPacket(const IPEndPoint& self_address, |
| 280 const IPEndPoint& peer_address, | 279 const IPEndPoint& peer_address, |
| 281 const QuicReceivedPacket& packet) { | 280 const QuicReceivedPacket& packet) { |
| 282 connection_->ProcessUdpPacket(self_address, peer_address, packet); | 281 connection_->ProcessUdpPacket(self_address, peer_address, packet); |
| 283 } | 282 } |
| 284 | 283 |
| 285 QuicConsumedData QuicSession::WritevData( | 284 QuicConsumedData QuicSession::WritevData( |
| 286 ReliableQuicStream* stream, | 285 QuicStream* stream, |
| 287 QuicStreamId id, | 286 QuicStreamId id, |
| 288 QuicIOVector iov, | 287 QuicIOVector iov, |
| 289 QuicStreamOffset offset, | 288 QuicStreamOffset offset, |
| 290 bool fin, | 289 bool fin, |
| 291 QuicAckListenerInterface* ack_notifier_delegate) { | 290 QuicAckListenerInterface* ack_notifier_delegate) { |
| 292 // This check is an attempt to deal with potential memory corruption | 291 // This check is an attempt to deal with potential memory corruption |
| 293 // in which |id| ends up set to 1 (the crypto stream id). If this happen | 292 // in which |id| ends up set to 1 (the crypto stream id). If this happen |
| 294 // it might end up resulting in unencrypted stream data being sent. | 293 // it might end up resulting in unencrypted stream data being sent. |
| 295 // While this is impossible to avoid given sufficient corruption, this | 294 // While this is impossible to avoid given sufficient corruption, this |
| 296 // seems like a reasonable mitigation. | 295 // seems like a reasonable mitigation. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 ++num_locally_closed_incoming_streams_highest_offset_; | 347 ++num_locally_closed_incoming_streams_highest_offset_; |
| 349 } | 348 } |
| 350 } | 349 } |
| 351 | 350 |
| 352 void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) { | 351 void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) { |
| 353 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; | 352 DVLOG(1) << ENDPOINT << "Closing stream " << stream_id; |
| 354 | 353 |
| 355 DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id); | 354 DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id); |
| 356 if (it == dynamic_stream_map_.end()) { | 355 if (it == dynamic_stream_map_.end()) { |
| 357 // When CloseStreamInner has been called recursively (via | 356 // When CloseStreamInner has been called recursively (via |
| 358 // ReliableQuicStream::OnClose), the stream will already have been deleted | 357 // QuicStream::OnClose), the stream will already have been deleted |
| 359 // from stream_map_, so return immediately. | 358 // from stream_map_, so return immediately. |
| 360 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; | 359 DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id; |
| 361 return; | 360 return; |
| 362 } | 361 } |
| 363 ReliableQuicStream* stream = it->second.get(); | 362 QuicStream* stream = it->second.get(); |
| 364 | 363 |
| 365 // Tell the stream that a RST has been sent. | 364 // Tell the stream that a RST has been sent. |
| 366 if (locally_reset) { | 365 if (locally_reset) { |
| 367 stream->set_rst_sent(true); | 366 stream->set_rst_sent(true); |
| 368 } | 367 } |
| 369 | 368 |
| 370 closed_streams_.push_back(std::move(it->second)); | 369 closed_streams_.push_back(std::move(it->second)); |
| 371 | 370 |
| 372 // If we haven't received a FIN or RST for this stream, we need to keep track | 371 // If we haven't received a FIN or RST for this stream, we need to keep track |
| 373 // of the how many bytes the stream's flow controller believes it has | 372 // of the how many bytes the stream's flow controller believes it has |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 void QuicSession::OnCryptoHandshakeMessageSent( | 570 void QuicSession::OnCryptoHandshakeMessageSent( |
| 572 const CryptoHandshakeMessage& /*message*/) {} | 571 const CryptoHandshakeMessage& /*message*/) {} |
| 573 | 572 |
| 574 void QuicSession::OnCryptoHandshakeMessageReceived( | 573 void QuicSession::OnCryptoHandshakeMessageReceived( |
| 575 const CryptoHandshakeMessage& /*message*/) {} | 574 const CryptoHandshakeMessage& /*message*/) {} |
| 576 | 575 |
| 577 QuicConfig* QuicSession::config() { | 576 QuicConfig* QuicSession::config() { |
| 578 return &config_; | 577 return &config_; |
| 579 } | 578 } |
| 580 | 579 |
| 581 void QuicSession::ActivateStream(std::unique_ptr<ReliableQuicStream> stream) { | 580 void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) { |
| 582 QuicStreamId stream_id = stream->id(); | 581 QuicStreamId stream_id = stream->id(); |
| 583 DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size() | 582 DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size() |
| 584 << ". activating " << stream_id; | 583 << ". activating " << stream_id; |
| 585 DCHECK(!base::ContainsKey(dynamic_stream_map_, stream_id)); | 584 DCHECK(!base::ContainsKey(dynamic_stream_map_, stream_id)); |
| 586 DCHECK(!base::ContainsKey(static_stream_map_, stream_id)); | 585 DCHECK(!base::ContainsKey(static_stream_map_, stream_id)); |
| 587 dynamic_stream_map_[stream_id] = std::move(stream); | 586 dynamic_stream_map_[stream_id] = std::move(stream); |
| 588 if (IsIncomingStream(stream_id)) { | 587 if (IsIncomingStream(stream_id)) { |
| 589 ++num_dynamic_incoming_streams_; | 588 ++num_dynamic_incoming_streams_; |
| 590 } | 589 } |
| 591 // Increase the number of streams being emulated when a new one is opened. | 590 // Increase the number of streams being emulated when a new one is opened. |
| 592 connection_->SetNumOpenStreams(dynamic_stream_map_.size()); | 591 connection_->SetNumOpenStreams(dynamic_stream_map_.size()); |
| 593 } | 592 } |
| 594 | 593 |
| 595 QuicStreamId QuicSession::GetNextOutgoingStreamId() { | 594 QuicStreamId QuicSession::GetNextOutgoingStreamId() { |
| 596 QuicStreamId id = next_outgoing_stream_id_; | 595 QuicStreamId id = next_outgoing_stream_id_; |
| 597 next_outgoing_stream_id_ += 2; | 596 next_outgoing_stream_id_ += 2; |
| 598 return id; | 597 return id; |
| 599 } | 598 } |
| 600 | 599 |
| 601 ReliableQuicStream* QuicSession::GetOrCreateStream( | 600 QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) { |
| 602 const QuicStreamId stream_id) { | |
| 603 StaticStreamMap::iterator it = static_stream_map_.find(stream_id); | 601 StaticStreamMap::iterator it = static_stream_map_.find(stream_id); |
| 604 if (it != static_stream_map_.end()) { | 602 if (it != static_stream_map_.end()) { |
| 605 return it->second; | 603 return it->second; |
| 606 } | 604 } |
| 607 return GetOrCreateDynamicStream(stream_id); | 605 return GetOrCreateDynamicStream(stream_id); |
| 608 } | 606 } |
| 609 | 607 |
| 610 void QuicSession::StreamDraining(QuicStreamId stream_id) { | 608 void QuicSession::StreamDraining(QuicStreamId stream_id) { |
| 611 DCHECK(base::ContainsKey(dynamic_stream_map_, stream_id)); | 609 DCHECK(base::ContainsKey(dynamic_stream_map_, stream_id)); |
| 612 if (!base::ContainsKey(draining_streams_, stream_id)) { | 610 if (!base::ContainsKey(draining_streams_, stream_id)) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 return true; | 651 return true; |
| 654 } | 652 } |
| 655 | 653 |
| 656 bool QuicSession::ShouldYield(QuicStreamId stream_id) { | 654 bool QuicSession::ShouldYield(QuicStreamId stream_id) { |
| 657 if (stream_id == currently_writing_stream_id_) { | 655 if (stream_id == currently_writing_stream_id_) { |
| 658 return false; | 656 return false; |
| 659 } | 657 } |
| 660 return write_blocked_streams()->ShouldYield(stream_id); | 658 return write_blocked_streams()->ShouldYield(stream_id); |
| 661 } | 659 } |
| 662 | 660 |
| 663 ReliableQuicStream* QuicSession::GetOrCreateDynamicStream( | 661 QuicStream* QuicSession::GetOrCreateDynamicStream( |
| 664 const QuicStreamId stream_id) { | 662 const QuicStreamId stream_id) { |
| 665 DCHECK(!base::ContainsKey(static_stream_map_, stream_id)) | 663 DCHECK(!base::ContainsKey(static_stream_map_, stream_id)) |
| 666 << "Attempt to call GetOrCreateDynamicStream for a static stream"; | 664 << "Attempt to call GetOrCreateDynamicStream for a static stream"; |
| 667 | 665 |
| 668 DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id); | 666 DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id); |
| 669 if (it != dynamic_stream_map_.end()) { | 667 if (it != dynamic_stream_map_.end()) { |
| 670 return it->second.get(); | 668 return it->second.get(); |
| 671 } | 669 } |
| 672 | 670 |
| 673 if (IsClosedStream(stream_id)) { | 671 if (IsClosedStream(stream_id)) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 | 818 |
| 821 size_t QuicSession::MaxAvailableStreams() const { | 819 size_t QuicSession::MaxAvailableStreams() const { |
| 822 return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier; | 820 return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier; |
| 823 } | 821 } |
| 824 | 822 |
| 825 bool QuicSession::IsIncomingStream(QuicStreamId id) const { | 823 bool QuicSession::IsIncomingStream(QuicStreamId id) const { |
| 826 return id % 2 != next_outgoing_stream_id_ % 2; | 824 return id % 2 != next_outgoing_stream_id_ % 2; |
| 827 } | 825 } |
| 828 | 826 |
| 829 } // namespace net | 827 } // namespace net |
| OLD | NEW |