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/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" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 | 97 |
98 private: | 98 private: |
99 QuicSession* session_; | 99 QuicSession* session_; |
100 }; | 100 }; |
101 | 101 |
102 QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) | 102 QuicSession::QuicSession(QuicConnection* connection, const QuicConfig& config) |
103 : connection_(connection), | 103 : connection_(connection), |
104 visitor_shim_(new VisitorShim(this)), | 104 visitor_shim_(new VisitorShim(this)), |
105 config_(config), | 105 config_(config), |
106 max_open_streams_(config_.max_streams_per_connection()), | 106 max_open_streams_(config_.max_streams_per_connection()), |
107 next_stream_id_(is_server() ? 2 : 3), | 107 next_stream_id_(is_server() ? 2 : 5), |
108 largest_peer_created_stream_id_(0), | 108 largest_peer_created_stream_id_(0), |
109 error_(QUIC_NO_ERROR), | 109 error_(QUIC_NO_ERROR), |
110 goaway_received_(false), | 110 goaway_received_(false), |
111 goaway_sent_(false), | 111 goaway_sent_(false), |
112 has_pending_handshake_(false) { | 112 has_pending_handshake_(false) { |
113 if (connection_->version() <= QUIC_VERSION_19) { | 113 if (connection_->version() <= QUIC_VERSION_19) { |
114 flow_controller_.reset(new QuicFlowController( | 114 flow_controller_.reset(new QuicFlowController( |
115 connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow, | 115 connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow, |
116 config_.GetInitialFlowControlWindowToSend(), | 116 config_.GetInitialFlowControlWindowToSend(), |
117 config_.GetInitialFlowControlWindowToSend())); | 117 config_.GetInitialFlowControlWindowToSend())); |
118 } else { | 118 } else { |
119 flow_controller_.reset(new QuicFlowController( | 119 flow_controller_.reset(new QuicFlowController( |
120 connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow, | 120 connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow, |
121 config_.GetInitialSessionFlowControlWindowToSend(), | 121 config_.GetInitialSessionFlowControlWindowToSend(), |
122 config_.GetInitialSessionFlowControlWindowToSend())); | 122 config_.GetInitialSessionFlowControlWindowToSend())); |
123 } | 123 } |
124 } | 124 } |
125 | 125 |
126 void QuicSession::InitializeSession() { | 126 void QuicSession::InitializeSession() { |
127 connection_->set_visitor(visitor_shim_.get()); | 127 connection_->set_visitor(visitor_shim_.get()); |
128 connection_->SetFromConfig(config_); | 128 connection_->SetFromConfig(config_); |
129 if (connection_->connected()) { | 129 if (connection_->connected()) { |
130 connection_->SetOverallConnectionTimeout( | 130 connection_->SetOverallConnectionTimeout( |
131 config_.max_time_before_crypto_handshake()); | 131 config_.max_time_before_crypto_handshake()); |
132 } | 132 } |
133 headers_stream_.reset(new QuicHeadersStream(this)); | 133 headers_stream_.reset(new QuicHeadersStream(this)); |
134 if (!is_server()) { | |
135 // For version above QUIC v12, the headers stream is stream 3, so the | |
136 // next available local stream ID should be 5. | |
137 DCHECK_EQ(kHeadersStreamId, next_stream_id_); | |
138 next_stream_id_ += 2; | |
139 } | |
140 } | 134 } |
141 | 135 |
142 QuicSession::~QuicSession() { | 136 QuicSession::~QuicSession() { |
143 STLDeleteElements(&closed_streams_); | 137 STLDeleteElements(&closed_streams_); |
144 STLDeleteValues(&stream_map_); | 138 STLDeleteValues(&stream_map_); |
145 | 139 |
146 DLOG_IF(WARNING, | 140 DLOG_IF(WARNING, |
147 locally_closed_streams_highest_offset_.size() > max_open_streams_) | 141 locally_closed_streams_highest_offset_.size() > max_open_streams_) |
148 << "Surprisingly high number of locally closed streams still waiting for " | 142 << "Surprisingly high number of locally closed streams still waiting for " |
149 "final byte offset: " << locally_closed_streams_highest_offset_.size(); | 143 "final byte offset: " << locally_closed_streams_highest_offset_.size(); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 | 421 |
428 closed_streams_.push_back(it->second); | 422 closed_streams_.push_back(it->second); |
429 | 423 |
430 // If we haven't received a FIN or RST for this stream, we need to keep track | 424 // If we haven't received a FIN or RST for this stream, we need to keep track |
431 // of the how many bytes the stream's flow controller believes it has | 425 // of the how many bytes the stream's flow controller believes it has |
432 // received, for accurate connection level flow control accounting. | 426 // received, for accurate connection level flow control accounting. |
433 if (!stream->HasFinalReceivedByteOffset() && | 427 if (!stream->HasFinalReceivedByteOffset() && |
434 stream->flow_controller()->IsEnabled()) { | 428 stream->flow_controller()->IsEnabled()) { |
435 locally_closed_streams_highest_offset_[stream_id] = | 429 locally_closed_streams_highest_offset_[stream_id] = |
436 stream->flow_controller()->highest_received_byte_offset(); | 430 stream->flow_controller()->highest_received_byte_offset(); |
437 if (FLAGS_close_quic_connection_unfinished_streams && | |
438 connection()->connected() && | |
439 locally_closed_streams_highest_offset_.size() > max_open_streams_) { | |
440 // A buggy client may fail to send FIN/RSTs. Don't tolerate this. | |
441 connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS); | |
442 } | |
443 } | 431 } |
444 | 432 |
445 stream_map_.erase(it); | 433 stream_map_.erase(it); |
446 stream->OnClose(); | 434 stream->OnClose(); |
447 } | 435 } |
448 | 436 |
449 void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( | 437 void QuicSession::UpdateFlowControlOnFinalReceivedByteOffset( |
450 QuicStreamId stream_id, QuicStreamOffset final_byte_offset) { | 438 QuicStreamId stream_id, QuicStreamOffset final_byte_offset) { |
451 map<QuicStreamId, QuicStreamOffset>::iterator it = | 439 map<QuicStreamId, QuicStreamOffset>::iterator it = |
452 locally_closed_streams_highest_offset_.find(stream_id); | 440 locally_closed_streams_highest_offset_.find(stream_id); |
(...skipping 22 matching lines...) Expand all Loading... |
475 return GetCryptoStream()->encryption_established(); | 463 return GetCryptoStream()->encryption_established(); |
476 } | 464 } |
477 | 465 |
478 bool QuicSession::IsCryptoHandshakeConfirmed() { | 466 bool QuicSession::IsCryptoHandshakeConfirmed() { |
479 return GetCryptoStream()->handshake_confirmed(); | 467 return GetCryptoStream()->handshake_confirmed(); |
480 } | 468 } |
481 | 469 |
482 void QuicSession::OnConfigNegotiated() { | 470 void QuicSession::OnConfigNegotiated() { |
483 connection_->SetFromConfig(config_); | 471 connection_->SetFromConfig(config_); |
484 QuicVersion version = connection()->version(); | 472 QuicVersion version = connection()->version(); |
| 473 |
| 474 // A server should accept a small number of additional streams beyond the |
| 475 // limit sent to the client. This helps avoid early connection termination |
| 476 // when FIN/RSTs for old streams are lost or arrive out of order. |
| 477 if (FLAGS_quic_allow_more_open_streams) { |
| 478 set_max_open_streams((is_server() ? kMaxStreamsMultiplier : 1.0) * |
| 479 config_.max_streams_per_connection()); |
| 480 } |
| 481 |
485 if (version <= QUIC_VERSION_16) { | 482 if (version <= QUIC_VERSION_16) { |
486 return; | 483 return; |
487 } | 484 } |
488 | 485 |
489 if (version <= QUIC_VERSION_19) { | 486 if (version <= QUIC_VERSION_19) { |
490 // QUIC_VERSION_17,18,19 don't support independent stream/session flow | 487 // QUIC_VERSION_17,18,19 don't support independent stream/session flow |
491 // control windows. | 488 // control windows. |
492 if (config_.HasReceivedInitialFlowControlWindowBytes()) { | 489 if (config_.HasReceivedInitialFlowControlWindowBytes()) { |
493 // Streams which were created before the SHLO was received (0-RTT | 490 // Streams which were created before the SHLO was received (0-RTT |
494 // requests) are now informed of the peer's initial flow control window. | 491 // requests) are now informed of the peer's initial flow control window. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { | 550 void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { |
554 switch (event) { | 551 switch (event) { |
555 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter | 552 // TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter |
556 // to QuicSession since it is the glue. | 553 // to QuicSession since it is the glue. |
557 case ENCRYPTION_FIRST_ESTABLISHED: | 554 case ENCRYPTION_FIRST_ESTABLISHED: |
558 break; | 555 break; |
559 | 556 |
560 case ENCRYPTION_REESTABLISHED: | 557 case ENCRYPTION_REESTABLISHED: |
561 // Retransmit originally packets that were sent, since they can't be | 558 // Retransmit originally packets that were sent, since they can't be |
562 // decrypted by the peer. | 559 // decrypted by the peer. |
563 connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY); | 560 connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION); |
564 break; | 561 break; |
565 | 562 |
566 case HANDSHAKE_CONFIRMED: | 563 case HANDSHAKE_CONFIRMED: |
567 LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT | 564 LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT |
568 << "Handshake confirmed without parameter negotiation."; | 565 << "Handshake confirmed without parameter negotiation."; |
569 // Discard originally encrypted packets, since they can't be decrypted by | 566 // Discard originally encrypted packets, since they can't be decrypted by |
570 // the peer. | 567 // the peer. |
571 connection_->NeuterUnencryptedPackets(); | 568 connection_->NeuterUnencryptedPackets(); |
572 connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite()); | 569 connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite()); |
573 max_open_streams_ = config_.max_streams_per_connection(); | 570 if (!FLAGS_quic_allow_more_open_streams) { |
| 571 max_open_streams_ = config_.max_streams_per_connection(); |
| 572 } |
574 break; | 573 break; |
575 | 574 |
576 default: | 575 default: |
577 LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event; | 576 LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event; |
578 } | 577 } |
579 } | 578 } |
580 | 579 |
581 void QuicSession::OnCryptoHandshakeMessageSent( | 580 void QuicSession::OnCryptoHandshakeMessageSent( |
582 const CryptoHandshakeMessage& message) { | 581 const CryptoHandshakeMessage& message) { |
583 } | 582 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 largest_peer_created_stream_id_ = stream_id; | 677 largest_peer_created_stream_id_ = stream_id; |
679 } | 678 } |
680 QuicDataStream* stream = CreateIncomingDataStream(stream_id); | 679 QuicDataStream* stream = CreateIncomingDataStream(stream_id); |
681 if (stream == NULL) { | 680 if (stream == NULL) { |
682 return NULL; | 681 return NULL; |
683 } | 682 } |
684 ActivateStream(stream); | 683 ActivateStream(stream); |
685 return stream; | 684 return stream; |
686 } | 685 } |
687 | 686 |
| 687 void QuicSession::set_max_open_streams(size_t max_open_streams) { |
| 688 DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams; |
| 689 max_open_streams_ = max_open_streams; |
| 690 } |
| 691 |
688 bool QuicSession::IsClosedStream(QuicStreamId id) { | 692 bool QuicSession::IsClosedStream(QuicStreamId id) { |
689 DCHECK_NE(0u, id); | 693 DCHECK_NE(0u, id); |
690 if (id == kCryptoStreamId) { | 694 if (id == kCryptoStreamId) { |
691 return false; | 695 return false; |
692 } | 696 } |
693 if (id == kHeadersStreamId) { | 697 if (id == kHeadersStreamId) { |
694 return false; | 698 return false; |
695 } | 699 } |
696 if (ContainsKey(stream_map_, id)) { | 700 if (ContainsKey(stream_map_, id)) { |
697 // Stream is active | 701 // Stream is active |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 } | 747 } |
744 | 748 |
745 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { | 749 bool QuicSession::GetSSLInfo(SSLInfo* ssl_info) const { |
746 NOTIMPLEMENTED(); | 750 NOTIMPLEMENTED(); |
747 return false; | 751 return false; |
748 } | 752 } |
749 | 753 |
750 void QuicSession::PostProcessAfterData() { | 754 void QuicSession::PostProcessAfterData() { |
751 STLDeleteElements(&closed_streams_); | 755 STLDeleteElements(&closed_streams_); |
752 closed_streams_.clear(); | 756 closed_streams_.clear(); |
| 757 |
| 758 if (FLAGS_close_quic_connection_unfinished_streams_2 && |
| 759 connection()->connected() && |
| 760 locally_closed_streams_highest_offset_.size() > max_open_streams_) { |
| 761 // A buggy client may fail to send FIN/RSTs. Don't tolerate this. |
| 762 connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS); |
| 763 } |
753 } | 764 } |
754 | 765 |
755 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { | 766 void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) { |
756 if (version < QUIC_VERSION_19) { | 767 if (version < QUIC_VERSION_19) { |
757 flow_controller_->Disable(); | 768 flow_controller_->Disable(); |
758 } | 769 } |
759 | 770 |
760 // Disable stream level flow control based on negotiated version. Streams may | 771 // Disable stream level flow control based on negotiated version. Streams may |
761 // have been created with a different version. | 772 // have been created with a different version. |
762 if (version < QUIC_VERSION_21) { | 773 if (version < QUIC_VERSION_21) { |
763 GetCryptoStream()->flow_controller()->Disable(); | 774 GetCryptoStream()->flow_controller()->Disable(); |
764 headers_stream_->flow_controller()->Disable(); | 775 headers_stream_->flow_controller()->Disable(); |
765 } | 776 } |
766 for (DataStreamMap::iterator it = stream_map_.begin(); | 777 for (DataStreamMap::iterator it = stream_map_.begin(); |
767 it != stream_map_.end(); ++it) { | 778 it != stream_map_.end(); ++it) { |
768 if (version <= QUIC_VERSION_16) { | 779 if (version <= QUIC_VERSION_16) { |
769 it->second->flow_controller()->Disable(); | 780 it->second->flow_controller()->Disable(); |
770 } | 781 } |
771 } | 782 } |
772 } | 783 } |
773 | 784 |
774 } // namespace net | 785 } // namespace net |
OLD | NEW |