| 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 |