| 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 <cstdint> | 7 #include <cstdint> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "net/quic/core/quic_connection.h" | 10 #include "net/quic/core/quic_connection.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 num_locally_closed_incoming_streams_highest_offset_(0), | 38 num_locally_closed_incoming_streams_highest_offset_(0), |
| 39 error_(QUIC_NO_ERROR), | 39 error_(QUIC_NO_ERROR), |
| 40 flow_controller_(connection_, | 40 flow_controller_(connection_, |
| 41 0, | 41 0, |
| 42 perspective(), | 42 perspective(), |
| 43 kMinimumFlowControlSendWindow, | 43 kMinimumFlowControlSendWindow, |
| 44 config_.GetInitialSessionFlowControlWindowToSend(), | 44 config_.GetInitialSessionFlowControlWindowToSend(), |
| 45 perspective() == Perspective::IS_SERVER, | 45 perspective() == Perspective::IS_SERVER, |
| 46 nullptr), | 46 nullptr), |
| 47 currently_writing_stream_id_(0), | 47 currently_writing_stream_id_(0), |
| 48 respect_goaway_(true) {} | 48 respect_goaway_(true), |
| 49 use_stream_notifier_( |
| 50 FLAGS_quic_reloadable_flag_quic_use_stream_notifier) {} |
| 49 | 51 |
| 50 void QuicSession::Initialize() { | 52 void QuicSession::Initialize() { |
| 51 connection_->set_visitor(this); | 53 connection_->set_visitor(this); |
| 54 if (use_stream_notifier_) { |
| 55 connection_->SetStreamNotifier(this); |
| 56 } |
| 52 connection_->SetFromConfig(config_); | 57 connection_->SetFromConfig(config_); |
| 53 | 58 |
| 54 DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id()); | 59 DCHECK_EQ(kCryptoStreamId, GetMutableCryptoStream()->id()); |
| 55 static_stream_map_[kCryptoStreamId] = GetMutableCryptoStream(); | 60 static_stream_map_[kCryptoStreamId] = GetMutableCryptoStream(); |
| 56 } | 61 } |
| 57 | 62 |
| 58 QuicSession::~QuicSession() { | 63 QuicSession::~QuicSession() { |
| 59 QUIC_LOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() > | 64 QUIC_LOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() > |
| 60 max_open_incoming_streams_) | 65 max_open_incoming_streams_) |
| 61 << "Surprisingly high number of locally closed peer initiated streams" | 66 << "Surprisingly high number of locally closed peer initiated streams" |
| 62 "still waiting for final byte offset: " | 67 "still waiting for final byte offset: " |
| 63 << num_locally_closed_incoming_streams_highest_offset(); | 68 << num_locally_closed_incoming_streams_highest_offset(); |
| 64 QUIC_LOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() > | 69 QUIC_LOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() > |
| 65 max_open_outgoing_streams_) | 70 max_open_outgoing_streams_) |
| 66 << "Surprisingly high number of locally closed self initiated streams" | 71 << "Surprisingly high number of locally closed self initiated streams" |
| 67 "still waiting for final byte offset: " | 72 "still waiting for final byte offset: " |
| 68 << GetNumLocallyClosedOutgoingStreamsHighestOffset(); | 73 << GetNumLocallyClosedOutgoingStreamsHighestOffset(); |
| 74 QUIC_LOG_IF(WARNING, !zombie_streams_.empty()) << "Still have zombie streams"; |
| 75 for (const auto& kv : dynamic_stream_map_) { |
| 76 QUIC_LOG_IF(WARNING, !kv.second->is_deletable()) |
| 77 << "Still have non-deletable stream"; |
| 78 } |
| 69 } | 79 } |
| 70 | 80 |
| 71 void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) { | 81 void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) { |
| 72 // TODO(rch) deal with the error case of stream id 0. | 82 // TODO(rch) deal with the error case of stream id 0. |
| 73 QuicStreamId stream_id = frame.stream_id; | 83 QuicStreamId stream_id = frame.stream_id; |
| 74 QuicStream* stream = GetOrCreateStream(stream_id); | 84 QuicStream* stream = GetOrCreateStream(stream_id); |
| 75 if (!stream) { | 85 if (!stream) { |
| 76 // The stream no longer exists, but we may still be interested in the | 86 // The stream no longer exists, but we may still be interested in the |
| 77 // final stream byte offset sent by the peer. A frame with a FIN can give | 87 // final stream byte offset sent by the peer. A frame with a FIN can give |
| 78 // us this offset. | 88 // us this offset. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 DynamicStreamMap::iterator it = dynamic_stream_map_.begin(); | 132 DynamicStreamMap::iterator it = dynamic_stream_map_.begin(); |
| 123 QuicStreamId id = it->first; | 133 QuicStreamId id = it->first; |
| 124 it->second->OnConnectionClosed(error, source); | 134 it->second->OnConnectionClosed(error, source); |
| 125 // The stream should call CloseStream as part of OnConnectionClosed. | 135 // The stream should call CloseStream as part of OnConnectionClosed. |
| 126 if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) { | 136 if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) { |
| 127 QUIC_BUG << ENDPOINT << "Stream failed to close under OnConnectionClosed"; | 137 QUIC_BUG << ENDPOINT << "Stream failed to close under OnConnectionClosed"; |
| 128 CloseStream(id); | 138 CloseStream(id); |
| 129 } | 139 } |
| 130 } | 140 } |
| 131 | 141 |
| 142 // Cleanup zombie stream map on connection close. |
| 143 while (!zombie_streams_.empty()) { |
| 144 ZombieStreamMap::iterator it = zombie_streams_.begin(); |
| 145 // Do not call OnConnectionClose as this may trigger unexpected operations |
| 146 // in subclass of QuicStream. |
| 147 it->second->SetIsDeletable(true); |
| 148 } |
| 149 |
| 132 if (visitor_) { | 150 if (visitor_) { |
| 133 visitor_->OnConnectionClosed(connection_->connection_id(), error, | 151 visitor_->OnConnectionClosed(connection_->connection_id(), error, |
| 134 error_details); | 152 error_details); |
| 135 } | 153 } |
| 136 } | 154 } |
| 137 | 155 |
| 138 void QuicSession::OnWriteBlocked() { | 156 void QuicSession::OnWriteBlocked() { |
| 139 if (visitor_) { | 157 if (visitor_) { |
| 140 visitor_->OnWriteBlocked(connection_); | 158 visitor_->OnWriteBlocked(connection_); |
| 141 } | 159 } |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 QUIC_DLOG(INFO) << ENDPOINT << "Stream is already closed: " << stream_id; | 380 QUIC_DLOG(INFO) << ENDPOINT << "Stream is already closed: " << stream_id; |
| 363 return; | 381 return; |
| 364 } | 382 } |
| 365 QuicStream* stream = it->second.get(); | 383 QuicStream* stream = it->second.get(); |
| 366 | 384 |
| 367 // Tell the stream that a RST has been sent. | 385 // Tell the stream that a RST has been sent. |
| 368 if (locally_reset) { | 386 if (locally_reset) { |
| 369 stream->set_rst_sent(true); | 387 stream->set_rst_sent(true); |
| 370 } | 388 } |
| 371 | 389 |
| 372 closed_streams_.push_back(std::move(it->second)); | 390 if (stream->is_deletable()) { |
| 391 closed_streams_.push_back(std::move(it->second)); |
| 392 } else { |
| 393 zombie_streams_[stream->id()] = std::move(it->second); |
| 394 } |
| 373 | 395 |
| 374 // If we haven't received a FIN or RST for this stream, we need to keep track | 396 // If we haven't received a FIN or RST for this stream, we need to keep track |
| 375 // of the how many bytes the stream's flow controller believes it has | 397 // of the how many bytes the stream's flow controller believes it has |
| 376 // received, for accurate connection level flow control accounting. | 398 // received, for accurate connection level flow control accounting. |
| 377 if (!stream->HasFinalReceivedByteOffset()) { | 399 if (!stream->HasFinalReceivedByteOffset()) { |
| 378 InsertLocallyClosedStreamsHighestOffset( | 400 InsertLocallyClosedStreamsHighestOffset( |
| 379 stream_id, stream->flow_controller()->highest_received_byte_offset()); | 401 stream_id, stream->flow_controller()->highest_received_byte_offset()); |
| 380 } | 402 } |
| 381 | 403 |
| 382 dynamic_stream_map_.erase(it); | 404 dynamic_stream_map_.erase(it); |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 return CreateAndActivateStream(GetNextOutgoingStreamId()); | 959 return CreateAndActivateStream(GetNextOutgoingStreamId()); |
| 938 } | 960 } |
| 939 | 961 |
| 940 QuicStream* QuicSession::CreateAndActivateStream(QuicStreamId id) { | 962 QuicStream* QuicSession::CreateAndActivateStream(QuicStreamId id) { |
| 941 std::unique_ptr<QuicStream> stream = CreateStream(id); | 963 std::unique_ptr<QuicStream> stream = CreateStream(id); |
| 942 QuicStream* stream_ptr = stream.get(); | 964 QuicStream* stream_ptr = stream.get(); |
| 943 ActivateStream(std::move(stream)); | 965 ActivateStream(std::move(stream)); |
| 944 return stream_ptr; | 966 return stream_ptr; |
| 945 } | 967 } |
| 946 | 968 |
| 969 void QuicSession::MarkStreamDeletable(QuicStreamId id) { |
| 970 auto it = zombie_streams_.find(id); |
| 971 if (it == zombie_streams_.end()) { |
| 972 return; |
| 973 } |
| 974 |
| 975 closed_streams_.push_back(std::move(it->second)); |
| 976 zombie_streams_.erase(it); |
| 977 } |
| 978 |
| 979 QuicStream* QuicSession::GetStream(QuicStreamId id) const { |
| 980 auto static_stream = static_stream_map_.find(id); |
| 981 if (static_stream != static_stream_map_.end()) { |
| 982 return static_stream->second; |
| 983 } |
| 984 auto active_stream = dynamic_stream_map_.find(id); |
| 985 if (active_stream != dynamic_stream_map_.end()) { |
| 986 return active_stream->second.get(); |
| 987 } |
| 988 auto zombie_stream = zombie_streams_.find(id); |
| 989 if (zombie_stream != zombie_streams_.end()) { |
| 990 return zombie_stream->second.get(); |
| 991 } |
| 992 return nullptr; |
| 993 } |
| 994 |
| 995 void QuicSession::OnStreamFrameAcked(const QuicStreamFrame& frame, |
| 996 QuicTime::Delta ack_delay_time) { |
| 997 QuicStream* stream = GetStream(frame.stream_id); |
| 998 if (stream != nullptr) { |
| 999 stream->OnStreamFrameAcked(frame, ack_delay_time); |
| 1000 } |
| 1001 } |
| 1002 |
| 1003 void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) { |
| 1004 QuicStream* stream = GetStream(frame.stream_id); |
| 1005 if (stream != nullptr) { |
| 1006 stream->OnStreamFrameRetransmitted(frame); |
| 1007 } |
| 1008 } |
| 1009 |
| 947 } // namespace net | 1010 } // namespace net |
| OLD | NEW |