session_->PostProcessAfterData();
}
+ virtual void OnCongestionWindowChange(QuicTime now) OVERRIDE {
+ session_->OnCongestionWindowChange(now);
+ }
+
virtual void OnSuccessfulVersionNegotiation(
const QuicVersion& version) OVERRIDE {
session_->OnSuccessfulVersionNegotiation(version);
visitor_shim_(new VisitorShim(this)),
config_(config),
max_open_streams_(config_.max_streams_per_connection()),
- next_stream_id_(is_server() ? 2 : 3),
+ next_stream_id_(is_server() ? 2 : 5),
largest_peer_created_stream_id_(0),
error_(QUIC_NO_ERROR),
goaway_received_(false),
config_.max_time_before_crypto_handshake());
}
headers_stream_.reset(new QuicHeadersStream(this));
- if (!is_server()) {
- // For version above QUIC v12, the headers stream is stream 3, so the
- // next available local stream ID should be 5.
- DCHECK_EQ(kHeadersStreamId, next_stream_id_);
- next_stream_id_ += 2;
- }
}
QuicSession::~QuicSession() {
continue;
}
- if (connection_->version() <= QUIC_VERSION_20 &&
+ if (connection_->version() < QUIC_VERSION_21 &&
(stream_id == kCryptoStreamId || stream_id == kHeadersStreamId)) {
DLOG(DFATAL) << "WindowUpdate for stream " << stream_id << " in version "
<< QuicVersionToString(connection_->version());
stream->flow_controller()->IsEnabled()) {
locally_closed_streams_highest_offset_[stream_id] =
stream->flow_controller()->highest_received_byte_offset();
- if (FLAGS_close_quic_connection_unfinished_streams &&
- connection()->connected() &&
- locally_closed_streams_highest_offset_.size() > max_open_streams_) {
- // A buggy client may fail to send FIN/RSTs. Don't tolerate this.
- connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS);
- }
}
stream_map_.erase(it);
void QuicSession::OnConfigNegotiated() {
connection_->SetFromConfig(config_);
QuicVersion version = connection()->version();
+
+ // A server should accept a small number of additional streams beyond the
+ // limit sent to the client. This helps avoid early connection termination
+ // when FIN/RSTs for old streams are lost or arrive out of order.
+ if (FLAGS_quic_allow_more_open_streams) {
+ set_max_open_streams((is_server() ? kMaxStreamsMultiplier : 1.0) *
+ config_.max_streams_per_connection());
+ }
+
if (version <= QUIC_VERSION_16) {
return;
}
return;
}
- // QUIC_VERSION_20 and higher can have independent stream and session flow
+ // QUIC_VERSION_21 and higher can have independent stream and session flow
// control windows.
if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
// Streams which were created before the SHLO was received (0-RTT
}
// Inform all existing streams about the new window.
- if (connection_->version() > QUIC_VERSION_20) {
+ if (connection_->version() >= QUIC_VERSION_21) {
GetCryptoStream()->flow_controller()->UpdateSendWindowOffset(new_window);
headers_stream_->flow_controller()->UpdateSendWindowOffset(new_window);
}
case ENCRYPTION_REESTABLISHED:
// Retransmit originally packets that were sent, since they can't be
// decrypted by the peer.
- connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY);
+ connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
break;
case HANDSHAKE_CONFIRMED:
// the peer.
connection_->NeuterUnencryptedPackets();
connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite());
- max_open_streams_ = config_.max_streams_per_connection();
+ if (!FLAGS_quic_allow_more_open_streams) {
+ max_open_streams_ = config_.max_streams_per_connection();
+ }
break;
default:
return stream;
}
+void QuicSession::set_max_open_streams(size_t max_open_streams) {
+ DVLOG(1) << "Setting max_open_streams_ to " << max_open_streams;
+ max_open_streams_ = max_open_streams;
+}
+
bool QuicSession::IsClosedStream(QuicStreamId id) {
DCHECK_NE(0u, id);
if (id == kCryptoStreamId) {
void QuicSession::PostProcessAfterData() {
STLDeleteElements(&closed_streams_);
closed_streams_.clear();
+
+ if (FLAGS_close_quic_connection_unfinished_streams_2 &&
+ connection()->connected() &&
+ locally_closed_streams_highest_offset_.size() > max_open_streams_) {
+ // A buggy client may fail to send FIN/RSTs. Don't tolerate this.
+ connection_->SendConnectionClose(QUIC_TOO_MANY_UNFINISHED_STREAMS);
+ }
}
void QuicSession::OnSuccessfulVersionNegotiation(const QuicVersion& version) {
// Disable stream level flow control based on negotiated version. Streams may
// have been created with a different version.
- if (version <= QUIC_VERSION_20) {
+ if (version < QUIC_VERSION_21) {
GetCryptoStream()->flow_controller()->Disable();
headers_stream_->flow_controller()->Disable();
}