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

Side by Side Diff: net/quic/quic_session.cc

Issue 1470713003: Landing Recent QUIC changes until and including Mon Nov 16 14:15:48 2015 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding NET_EXPORT_PRIVATE to DelegateInterface. Created 5 years 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 unified diff | Download patch
OLDNEW
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/quic_session.h" 5 #include "net/quic/quic_session.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "net/quic/crypto/proof_verifier.h" 8 #include "net/quic/crypto/proof_verifier.h"
9 #include "net/quic/quic_connection.h" 9 #include "net/quic/quic_connection.h"
10 #include "net/quic/quic_flags.h" 10 #include "net/quic/quic_flags.h"
11 #include "net/quic/quic_flow_controller.h" 11 #include "net/quic/quic_flow_controller.h"
12 #include "net/ssl/ssl_info.h" 12 #include "net/ssl/ssl_info.h"
13 13
14 using base::StringPiece; 14 using base::StringPiece;
15 using base::hash_map; 15 using base::hash_map;
16 using base::hash_set; 16 using base::hash_set;
17 using std::make_pair; 17 using std::make_pair;
18 using std::map; 18 using std::map;
19 using std::max; 19 using std::max;
20 using std::string; 20 using std::string;
21 using std::vector; 21 using std::vector;
22 using net::SpdyPriority;
22 23
23 namespace net { 24 namespace net {
24 25
25 #define ENDPOINT \ 26 #define ENDPOINT \
26 (perspective() == Perspective::IS_SERVER ? "Server: " : " Client: ") 27 (perspective() == Perspective::IS_SERVER ? "Server: " : " Client: ")
27 28
28 // We want to make sure we delete any closed streams in a safe manner. 29 // We want to make sure we delete any closed streams in a safe manner.
29 // To avoid deleting a stream in mid-operation, we have a simple shim between 30 // To avoid deleting a stream in mid-operation, we have a simple shim between
30 // us and the stream, so we can delete any streams when we return from 31 // us and the stream, so we can delete any streams when we return from
31 // processing. 32 // processing.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 max_open_streams_(config_.MaxStreamsPerConnection()), 106 max_open_streams_(config_.MaxStreamsPerConnection()),
106 next_outgoing_stream_id_(perspective() == Perspective::IS_SERVER ? 2 : 3), 107 next_outgoing_stream_id_(perspective() == Perspective::IS_SERVER ? 2 : 3),
107 largest_peer_created_stream_id_( 108 largest_peer_created_stream_id_(
108 perspective() == Perspective::IS_SERVER ? 1 : 0), 109 perspective() == Perspective::IS_SERVER ? 1 : 0),
109 error_(QUIC_NO_ERROR), 110 error_(QUIC_NO_ERROR),
110 flow_controller_(connection_.get(), 111 flow_controller_(connection_.get(),
111 0, 112 0,
112 perspective(), 113 perspective(),
113 kMinimumFlowControlSendWindow, 114 kMinimumFlowControlSendWindow,
114 config_.GetInitialSessionFlowControlWindowToSend(), 115 config_.GetInitialSessionFlowControlWindowToSend(),
115 false), 116 false) {}
116 has_pending_handshake_(false) {}
117 117
118 void QuicSession::Initialize() { 118 void QuicSession::Initialize() {
119 connection_->set_visitor(visitor_shim_.get()); 119 connection_->set_visitor(visitor_shim_.get());
120 connection_->SetFromConfig(config_); 120 connection_->SetFromConfig(config_);
121 121
122 DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id()); 122 DCHECK_EQ(kCryptoStreamId, GetCryptoStream()->id());
123 static_stream_map_[kCryptoStreamId] = GetCryptoStream(); 123 static_stream_map_[kCryptoStreamId] = GetCryptoStream();
124 } 124 }
125 125
126 QuicSession::~QuicSession() { 126 QuicSession::~QuicSession() {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 write_blocked_streams_.HasWriteBlockedDataStreams())) { 251 write_blocked_streams_.HasWriteBlockedDataStreams())) {
252 // Writing one stream removed another!? Something's broken. 252 // Writing one stream removed another!? Something's broken.
253 LOG(DFATAL) << "WriteBlockedStream is missing"; 253 LOG(DFATAL) << "WriteBlockedStream is missing";
254 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false); 254 connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
255 return; 255 return;
256 } 256 }
257 if (!connection_->CanWriteStreamData()) { 257 if (!connection_->CanWriteStreamData()) {
258 return; 258 return;
259 } 259 }
260 QuicStreamId stream_id = write_blocked_streams_.PopFront(); 260 QuicStreamId stream_id = write_blocked_streams_.PopFront();
261 if (stream_id == kCryptoStreamId) {
262 has_pending_handshake_ = false; // We just popped it.
263 }
264 ReliableQuicStream* stream = GetStream(stream_id); 261 ReliableQuicStream* stream = GetStream(stream_id);
265 if (stream != nullptr && !stream->flow_controller()->IsBlocked()) { 262 if (stream != nullptr && !stream->flow_controller()->IsBlocked()) {
266 // If the stream can't write all bytes, it'll re-add itself to the blocked 263 // If the stream can't write all bytes it'll re-add itself to the blocked
267 // list. 264 // list.
268 stream->OnCanWrite(); 265 stream->OnCanWrite();
269 } 266 }
270 } 267 }
271 } 268 }
272 269
273 bool QuicSession::WillingAndAbleToWrite() const { 270 bool QuicSession::WillingAndAbleToWrite() const {
274 // If the crypto or headers streams are blocked, we want to schedule a write - 271 // If the crypto or headers streams are blocked, we want to schedule a write -
275 // they don't get blocked by connection level flow control. Otherwise only 272 // they don't get blocked by connection level flow control. Otherwise only
276 // schedule a write if we are not flow control blocked at the connection 273 // schedule a write if we are not flow control blocked at the connection
277 // level. 274 // level.
278 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || 275 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
279 (!flow_controller_.IsBlocked() && 276 (!flow_controller_.IsBlocked() &&
280 write_blocked_streams_.HasWriteBlockedDataStreams()); 277 write_blocked_streams_.HasWriteBlockedDataStreams());
281 } 278 }
282 279
283 bool QuicSession::HasPendingHandshake() const { 280 bool QuicSession::HasPendingHandshake() const {
284 return has_pending_handshake_; 281 return write_blocked_streams_.crypto_stream_blocked();
285 } 282 }
286 283
287 bool QuicSession::HasOpenDynamicStreams() const { 284 bool QuicSession::HasOpenDynamicStreams() const {
288 return GetNumOpenStreams() > 0; 285 return GetNumOpenStreams() > 0;
289 } 286 }
290 287
291 QuicConsumedData QuicSession::WritevData( 288 QuicConsumedData QuicSession::WritevData(
292 QuicStreamId id, 289 QuicStreamId id,
293 QuicIOVector iov, 290 QuicIOVector iov,
294 QuicStreamOffset offset, 291 QuicStreamOffset offset,
295 bool fin, 292 bool fin,
296 FecProtection fec_protection, 293 FecProtection fec_protection,
297 QuicAckListenerInterface* ack_notifier_delegate) { 294 QuicAckListenerInterface* ack_notifier_delegate) {
298 return connection_->SendStreamData(id, iov, offset, fin, fec_protection, 295 QuicConsumedData data = connection_->SendStreamData(
299 ack_notifier_delegate); 296 id, iov, offset, fin, fec_protection, ack_notifier_delegate);
297 write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
298 return data;
300 } 299 }
301 300
302 void QuicSession::SendRstStream(QuicStreamId id, 301 void QuicSession::SendRstStream(QuicStreamId id,
303 QuicRstStreamErrorCode error, 302 QuicRstStreamErrorCode error,
304 QuicStreamOffset bytes_written) { 303 QuicStreamOffset bytes_written) {
305 if (ContainsKey(static_stream_map_, id)) { 304 if (ContainsKey(static_stream_map_, id)) {
306 LOG(DFATAL) << "Cannot send RST for a static stream with ID " << id; 305 LOG(DFATAL) << "Cannot send RST for a static stream with ID " << id;
307 return; 306 return;
308 } 307 }
309 308
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 // Locally created streams are strictly in-order. If the id is in the 704 // Locally created streams are strictly in-order. If the id is in the
706 // range of created streams and it's not active, it must have been closed. 705 // range of created streams and it's not active, it must have been closed.
707 return id < next_outgoing_stream_id_; 706 return id < next_outgoing_stream_id_;
708 } 707 }
709 // For peer created streams, we also need to consider available streams. 708 // For peer created streams, we also need to consider available streams.
710 return id <= largest_peer_created_stream_id_ && 709 return id <= largest_peer_created_stream_id_ &&
711 !ContainsKey(available_streams_, id); 710 !ContainsKey(available_streams_, id);
712 } 711 }
713 712
714 size_t QuicSession::GetNumOpenStreams() const { 713 size_t QuicSession::GetNumOpenStreams() const {
715 if (FLAGS_quic_count_unfinished_as_open_streams) { 714 if (FLAGS_allow_many_available_streams) {
716 if (FLAGS_allow_many_available_streams) { 715 return dynamic_stream_map_.size() - draining_streams_.size() +
717 return dynamic_stream_map_.size() - draining_streams_.size() + 716 locally_closed_streams_highest_offset_.size();
718 locally_closed_streams_highest_offset_.size();
719 } else {
720 return dynamic_stream_map_.size() + available_streams_.size() -
721 draining_streams_.size() +
722 locally_closed_streams_highest_offset_.size();
723 }
724 } else { 717 } else {
725 if (FLAGS_allow_many_available_streams) { 718 return dynamic_stream_map_.size() + available_streams_.size() -
726 return dynamic_stream_map_.size() - draining_streams_.size(); 719 draining_streams_.size() +
727 } else { 720 locally_closed_streams_highest_offset_.size();
728 return dynamic_stream_map_.size() + available_streams_.size() -
729 draining_streams_.size();
730 }
731 } 721 }
732 } 722 }
733 723
734 size_t QuicSession::GetNumActiveStreams() const { 724 size_t QuicSession::GetNumActiveStreams() const {
735 if (FLAGS_quic_count_unfinished_as_open_streams) { 725 return GetNumOpenStreams() - locally_closed_streams_highest_offset_.size();
736 return GetNumOpenStreams() - locally_closed_streams_highest_offset_.size();
737 } else {
738 return GetNumOpenStreams();
739 }
740 } 726 }
741 727
742 size_t QuicSession::GetNumAvailableStreams() const { 728 size_t QuicSession::GetNumAvailableStreams() const {
743 return available_streams_.size(); 729 return available_streams_.size();
744 } 730 }
745 731
746 void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id, 732 void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id,
747 QuicPriority priority) { 733 SpdyPriority priority) {
748 #ifndef NDEBUG 734 #ifndef NDEBUG
749 ReliableQuicStream* stream = GetStream(id); 735 ReliableQuicStream* stream = GetStream(id);
750 if (stream != nullptr) { 736 if (stream != nullptr) {
751 LOG_IF(DFATAL, priority != stream->EffectivePriority()) 737 LOG_IF(DFATAL, priority != stream->Priority())
752 << ENDPOINT << "Stream " << id 738 << ENDPOINT << "Stream " << id
753 << "Priorities do not match. Got: " << priority 739 << "Priorities do not match. Got: " << static_cast<int>(priority)
754 << " Expected: " << stream->EffectivePriority(); 740 << " Expected: " << static_cast<int>(stream->Priority());
755 } else { 741 } else {
756 LOG(DFATAL) << "Marking unknown stream " << id << " blocked."; 742 LOG(DFATAL) << "Marking unknown stream " << id << " blocked.";
757 } 743 }
758 #endif 744 #endif
759 745
760 if (id == kCryptoStreamId) { 746 write_blocked_streams_.AddStream(id, priority);
761 DCHECK(!has_pending_handshake_);
762 has_pending_handshake_ = true;
763 // TODO(jar): Be sure to use the highest priority for the crypto stream,
764 // perhaps by adding a "special" priority for it that is higher than
765 // kHighestPriority.
766 priority = kHighestPriority;
767 }
768 write_blocked_streams_.PushBack(id, priority);
769 } 747 }
770 748
771 bool QuicSession::HasDataToWrite() const { 749 bool QuicSession::HasDataToWrite() const {
772 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() || 750 return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
773 write_blocked_streams_.HasWriteBlockedDataStreams() || 751 write_blocked_streams_.HasWriteBlockedDataStreams() ||
774 connection_->HasQueuedData(); 752 connection_->HasQueuedData();
775 } 753 }
776 754
777 void QuicSession::PostProcessAfterData() { 755 void QuicSession::PostProcessAfterData() {
778 STLDeleteElements(&closed_streams_); 756 STLDeleteElements(&closed_streams_);
779 757 closed_streams_.clear();
780 // A buggy client may fail to send FIN/RSTs. Don't tolerate this.
781 if (!FLAGS_quic_count_unfinished_as_open_streams &&
782 locally_closed_streams_highest_offset_.size() > max_open_streams_) {
783 CloseConnection(QUIC_TOO_MANY_UNFINISHED_STREAMS);
784 }
785 } 758 }
786 759
787 bool QuicSession::IsConnectionFlowControlBlocked() const { 760 bool QuicSession::IsConnectionFlowControlBlocked() const {
788 return flow_controller_.IsBlocked(); 761 return flow_controller_.IsBlocked();
789 } 762 }
790 763
791 bool QuicSession::IsStreamFlowControlBlocked() { 764 bool QuicSession::IsStreamFlowControlBlocked() {
792 for (auto const& kv : static_stream_map_) { 765 for (auto const& kv : static_stream_map_) {
793 if (kv.second->flow_controller()->IsBlocked()) { 766 if (kv.second->flow_controller()->IsBlocked()) {
794 return true; 767 return true;
795 } 768 }
796 } 769 }
797 for (auto const& kv : dynamic_stream_map_) { 770 for (auto const& kv : dynamic_stream_map_) {
798 if (kv.second->flow_controller()->IsBlocked()) { 771 if (kv.second->flow_controller()->IsBlocked()) {
799 return true; 772 return true;
800 } 773 }
801 } 774 }
802 return false; 775 return false;
803 } 776 }
804 777
805 } // namespace net 778 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698