blob: b60109a03bb8c3709ab5013a226ae51bf2eb54b0 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_session.h"
6
7#include <cstdint>
vasilvv872e7a32019-03-12 16:42:44 -07008#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include <utility>
10
11#include "net/third_party/quiche/src/quic/core/quic_connection.h"
renjietangd9762282019-11-11 17:11:18 -080012#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/core/quic_flow_controller.h"
renjietangde12d3d2019-07-19 10:57:42 -070014#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050015#include "net/third_party/quiche/src/quic/core/quic_utils.h"
zhongyi1b2f7832019-06-14 13:31:34 -070016#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
bnc463f2352019-10-10 04:49:34 -070022#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
wub2b5942f2019-04-11 13:22:50 -070023#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050024#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080025#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
26#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027
28using spdy::SpdyPriority;
29
30namespace quic {
31
32namespace {
33
34class ClosedStreamsCleanUpDelegate : public QuicAlarm::Delegate {
35 public:
36 explicit ClosedStreamsCleanUpDelegate(QuicSession* session)
37 : session_(session) {}
38 ClosedStreamsCleanUpDelegate(const ClosedStreamsCleanUpDelegate&) = delete;
39 ClosedStreamsCleanUpDelegate& operator=(const ClosedStreamsCleanUpDelegate&) =
40 delete;
41
42 void OnAlarm() override { session_->CleanUpClosedStreams(); }
43
44 private:
45 QuicSession* session_;
46};
47
48} // namespace
49
50#define ENDPOINT \
51 (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
52
renjietang216dc012019-08-27 11:28:27 -070053QuicSession::QuicSession(
54 QuicConnection* connection,
55 Visitor* owner,
56 const QuicConfig& config,
57 const ParsedQuicVersionVector& supported_versions,
58 QuicStreamCount num_expected_unidirectional_static_streams)
QUICHE teama6ef0a62019-03-07 20:34:33 -050059 : connection_(connection),
dschinazi31e94d42019-12-18 11:55:39 -080060 perspective_(connection->perspective()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050061 visitor_(owner),
nharpercd820e02019-05-16 15:12:07 -070062 write_blocked_streams_(connection->transport_version()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 config_(config),
ianswettc1f530d2019-12-10 05:14:30 -080064 stream_id_manager_(perspective(),
65 connection->transport_version(),
QUICHE teama6ef0a62019-03-07 20:34:33 -050066 kDefaultMaxStreamsPerConnection,
renjietange6d94672020-01-07 10:30:10 -080067 config_.GetMaxBidirectionalStreamsToSend()),
68 v99_streamid_manager_(perspective(),
69 connection->version(),
70 this,
renjietangcbfb93e2020-01-23 17:03:30 -080071 0,
72 num_expected_unidirectional_static_streams,
renjietange6d94672020-01-07 10:30:10 -080073 config_.GetMaxBidirectionalStreamsToSend(),
74 config_.GetMaxUnidirectionalStreamsToSend()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 num_dynamic_incoming_streams_(0),
76 num_draining_incoming_streams_(0),
renjietangfbeb5bf2019-04-19 15:06:20 -070077 num_outgoing_static_streams_(0),
78 num_incoming_static_streams_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 num_locally_closed_incoming_streams_highest_offset_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 flow_controller_(
81 this,
82 QuicUtils::GetInvalidStreamId(connection->transport_version()),
83 /*is_connection_flow_controller*/ true,
dschinazic7036122019-04-30 12:46:34 -070084 connection->version().AllowsLowFlowControlLimits()
85 ? 0
86 : kMinimumFlowControlSendWindow,
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 config_.GetInitialSessionFlowControlWindowToSend(),
88 kSessionReceiveWindowLimit,
89 perspective() == Perspective::IS_SERVER,
90 nullptr),
91 currently_writing_stream_id_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050092 goaway_sent_(false),
93 goaway_received_(false),
94 control_frame_manager_(this),
95 last_message_id_(0),
vasilvv2b0ab242020-01-07 07:32:09 -080096 datagram_queue_(this),
QUICHE teama6ef0a62019-03-07 20:34:33 -050097 closed_streams_clean_up_alarm_(nullptr),
fayang944cfbc2019-07-31 09:15:00 -070098 supported_versions_(supported_versions),
fkastenholz9b4b0ad2019-08-20 05:10:40 -070099 use_http2_priority_write_scheduler_(false),
renjietang216dc012019-08-27 11:28:27 -0700100 is_configured_(false),
101 num_expected_unidirectional_static_streams_(
fayang1b11b962019-09-16 14:01:48 -0700102 num_expected_unidirectional_static_streams),
103 enable_round_robin_scheduling_(false) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500104 closed_streams_clean_up_alarm_ =
105 QuicWrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
106 new ClosedStreamsCleanUpDelegate(this)));
dschinazi4e3e6572019-08-02 12:57:17 -0700107 if (perspective() == Perspective::IS_SERVER &&
108 connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
109 config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
110 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500111}
112
113void QuicSession::Initialize() {
114 connection_->set_visitor(this);
115 connection_->SetSessionNotifier(this);
116 connection_->SetDataProducer(this);
117 connection_->SetFromConfig(config_);
118
wub256b2d62019-11-25 08:46:55 -0800119 // On the server side, version negotiation has been done by the dispatcher,
120 // and the server session is created with the right version.
wubbea386e2020-01-27 09:04:51 -0800121 if (perspective() == Perspective::IS_SERVER) {
wub256b2d62019-11-25 08:46:55 -0800122 connection_->OnSuccessfulVersionNegotiation();
123 }
124
renjietangd1d00852019-09-06 10:43:12 -0700125 if (QuicVersionUsesCryptoFrames(transport_version())) {
nharper46833c32019-05-15 21:33:05 -0700126 return;
127 }
128
renjietangd1d00852019-09-06 10:43:12 -0700129 DCHECK_EQ(QuicUtils::GetCryptoStreamId(transport_version()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500130 GetMutableCryptoStream()->id());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131}
132
133QuicSession::~QuicSession() {
134 QUIC_LOG_IF(WARNING, !zombie_streams_.empty()) << "Still have zombie streams";
ianswettc1f530d2019-12-10 05:14:30 -0800135 QUIC_LOG_IF(WARNING, num_locally_closed_incoming_streams_highest_offset() >
136 stream_id_manager_.max_open_incoming_streams())
137 << "Surprisingly high number of locally closed peer initiated streams"
138 "still waiting for final byte offset: "
139 << num_locally_closed_incoming_streams_highest_offset();
140 QUIC_LOG_IF(WARNING, GetNumLocallyClosedOutgoingStreamsHighestOffset() >
141 stream_id_manager_.max_open_outgoing_streams())
142 << "Surprisingly high number of locally closed self initiated streams"
143 "still waiting for final byte offset: "
144 << GetNumLocallyClosedOutgoingStreamsHighestOffset();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145}
146
renjietange76b2da2019-05-13 14:50:23 -0700147void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
renjietanga29a96a2019-10-10 12:47:50 -0700148 DCHECK(VersionUsesHttp3(transport_version()));
renjietange76b2da2019-05-13 14:50:23 -0700149 QuicStreamId stream_id = frame.stream_id;
150
151 PendingStream* pending = GetOrCreatePendingStream(stream_id);
152
153 if (!pending) {
154 if (frame.fin) {
155 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
156 OnFinalByteOffsetReceived(stream_id, final_byte_offset);
157 }
158 return;
159 }
160
161 pending->OnStreamFrame(frame);
renjietanga553da02019-06-24 11:57:04 -0700162 if (!connection()->connected()) {
163 return;
164 }
renjietangbb1c4892019-05-24 15:58:44 -0700165 if (ProcessPendingStream(pending)) {
166 // The pending stream should now be in the scope of normal streams.
167 DCHECK(IsClosedStream(stream_id) || IsOpenStream(stream_id))
168 << "Stream " << stream_id << " not created";
169 pending_stream_map_.erase(stream_id);
bnc4ff60622019-08-09 18:55:45 -0700170 return;
171 }
172 if (pending->sequencer()->IsClosed()) {
173 ClosePendingStream(stream_id);
renjietangbb1c4892019-05-24 15:58:44 -0700174 }
renjietange76b2da2019-05-13 14:50:23 -0700175}
176
QUICHE teama6ef0a62019-03-07 20:34:33 -0500177void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
178 // TODO(rch) deal with the error case of stream id 0.
179 QuicStreamId stream_id = frame.stream_id;
renjietangd1d00852019-09-06 10:43:12 -0700180 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181 connection()->CloseConnection(
bnce433f532019-04-16 13:05:27 -0700182 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
184 return;
185 }
186
bnc36c47282019-06-21 05:17:59 -0700187 if (UsesPendingStreams() &&
renjietange76b2da2019-05-13 14:50:23 -0700188 QuicUtils::GetStreamType(stream_id, perspective(),
189 IsIncomingStream(stream_id)) ==
190 READ_UNIDIRECTIONAL &&
renjietang55d182a2019-07-12 10:26:25 -0700191 stream_map_.find(stream_id) == stream_map_.end()) {
renjietange76b2da2019-05-13 14:50:23 -0700192 PendingStreamOnStreamFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 return;
194 }
195
renjietang2c4d7122019-05-20 17:18:14 -0700196 QuicStream* stream = GetOrCreateStream(stream_id);
renjietange76b2da2019-05-13 14:50:23 -0700197
renjietang2c4d7122019-05-20 17:18:14 -0700198 if (!stream) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 // The stream no longer exists, but we may still be interested in the
200 // final stream byte offset sent by the peer. A frame with a FIN can give
201 // us this offset.
202 if (frame.fin) {
203 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
204 OnFinalByteOffsetReceived(stream_id, final_byte_offset);
205 }
206 return;
207 }
renjietangb663b862019-07-08 16:02:39 -0700208 if (frame.fin && stream->is_static()) {
renjietangfbeb5bf2019-04-19 15:06:20 -0700209 connection()->CloseConnection(
210 QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
211 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
212 return;
213 }
renjietang2c4d7122019-05-20 17:18:14 -0700214 stream->OnStreamFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500215}
216
217void QuicSession::OnCryptoFrame(const QuicCryptoFrame& frame) {
218 GetMutableCryptoStream()->OnCryptoFrame(frame);
219}
220
renjietangeab918f2019-10-28 12:10:32 -0700221void QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
222 // STOP_SENDING is in IETF QUIC only.
renjietangd1d00852019-09-06 10:43:12 -0700223 DCHECK(VersionHasIetfQuicFrames(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224
225 QuicStreamId stream_id = frame.stream_id;
226 // If Stream ID is invalid then close the connection.
renjietangd1d00852019-09-06 10:43:12 -0700227 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500228 QUIC_DVLOG(1) << ENDPOINT
229 << "Received STOP_SENDING with invalid stream_id: "
230 << stream_id << " Closing connection";
231 connection()->CloseConnection(
232 QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for an invalid stream",
233 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
renjietangeab918f2019-10-28 12:10:32 -0700234 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 }
236
237 if (visitor_) {
238 visitor_->OnStopSendingReceived(frame);
239 }
240
241 // If stream is closed, ignore the frame
242 if (IsClosedStream(stream_id)) {
243 QUIC_DVLOG(1)
244 << ENDPOINT
245 << "Received STOP_SENDING for closed or non-existent stream, id: "
246 << stream_id << " Ignoring.";
renjietangeab918f2019-10-28 12:10:32 -0700247 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500248 }
249 // If stream is non-existent, close the connection
renjietang55d182a2019-07-12 10:26:25 -0700250 StreamMap::iterator it = stream_map_.find(stream_id);
251 if (it == stream_map_.end()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 QUIC_DVLOG(1) << ENDPOINT
253 << "Received STOP_SENDING for non-existent stream, id: "
254 << stream_id << " Closing connection";
255 connection()->CloseConnection(
256 IETF_QUIC_PROTOCOL_VIOLATION,
257 "Received STOP_SENDING for a non-existent stream",
258 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
renjietangeab918f2019-10-28 12:10:32 -0700259 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260 }
261
QUICHE teama6ef0a62019-03-07 20:34:33 -0500262 QuicStream* stream = it->second.get();
263 if (stream == nullptr) {
fkastenholz3c4eabf2019-04-22 07:49:59 -0700264 QUIC_BUG << ENDPOINT
265 << "Received STOP_SENDING for NULL QuicStream, stream_id: "
266 << stream_id << ". Ignoring.";
renjietangeab918f2019-10-28 12:10:32 -0700267 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 }
renjietangfbeb5bf2019-04-19 15:06:20 -0700269
renjietangb663b862019-07-08 16:02:39 -0700270 if (stream->is_static()) {
renjietangfbeb5bf2019-04-19 15:06:20 -0700271 QUIC_DVLOG(1) << ENDPOINT
272 << "Received STOP_SENDING for a static stream, id: "
273 << stream_id << " Closing connection";
274 connection()->CloseConnection(
275 QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a static stream",
276 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
renjietangeab918f2019-10-28 12:10:32 -0700277 return;
renjietangfbeb5bf2019-04-19 15:06:20 -0700278 }
279
renjietangd9762282019-11-11 17:11:18 -0800280 stream->OnStopSending(frame.application_error_code);
281
QUICHE teama6ef0a62019-03-07 20:34:33 -0500282 stream->set_stream_error(
283 static_cast<QuicRstStreamErrorCode>(frame.application_error_code));
renjietang61cc2452019-11-26 10:57:10 -0800284 if (connection()->connected()) {
285 MaybeSendRstStreamFrame(
286 stream->id(),
287 static_cast<quic::QuicRstStreamErrorCode>(frame.application_error_code),
288 stream->stream_bytes_written());
289 connection_->OnStreamReset(stream->id(),
290 static_cast<quic::QuicRstStreamErrorCode>(
291 frame.application_error_code));
292 }
renjietang64881612019-11-05 17:39:04 -0800293 stream->set_rst_sent(true);
294 stream->CloseWriteSide();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500295}
296
fayangd58736d2019-11-27 13:35:31 -0800297void QuicSession::OnPacketDecrypted(EncryptionLevel level) {
298 GetMutableCryptoStream()->OnPacketDecrypted(level);
299}
300
fayang2f2915d2020-01-24 06:47:15 -0800301void QuicSession::OnOneRttPacketAcknowledged() {
302 GetMutableCryptoStream()->OnOneRttPacketAcknowledged();
303}
304
renjietange76b2da2019-05-13 14:50:23 -0700305void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
renjietanga29a96a2019-10-10 12:47:50 -0700306 DCHECK(VersionUsesHttp3(transport_version()));
renjietange76b2da2019-05-13 14:50:23 -0700307 QuicStreamId stream_id = frame.stream_id;
308
309 PendingStream* pending = GetOrCreatePendingStream(stream_id);
310
311 if (!pending) {
312 HandleRstOnValidNonexistentStream(frame);
313 return;
314 }
315
316 pending->OnRstStreamFrame(frame);
renjietang4f732482019-10-24 14:48:23 -0700317 // Pending stream is currently read only. We can safely close the stream.
318 DCHECK_EQ(READ_UNIDIRECTIONAL,
319 QuicUtils::GetStreamType(pending->id(), perspective(),
320 /*peer_initiated = */ true));
renjietange76b2da2019-05-13 14:50:23 -0700321 ClosePendingStream(stream_id);
322}
323
QUICHE teama6ef0a62019-03-07 20:34:33 -0500324void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
325 QuicStreamId stream_id = frame.stream_id;
renjietangd1d00852019-09-06 10:43:12 -0700326 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327 connection()->CloseConnection(
bnce433f532019-04-16 13:05:27 -0700328 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500329 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
330 return;
331 }
332
renjietangd9762282019-11-11 17:11:18 -0800333 if (VersionHasIetfQuicFrames(transport_version()) &&
334 QuicUtils::GetStreamType(stream_id, perspective(),
335 IsIncomingStream(stream_id)) ==
336 WRITE_UNIDIRECTIONAL) {
337 connection()->CloseConnection(
338 QUIC_INVALID_STREAM_ID, "Received RESET_STREAM for a write-only stream",
339 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
340 return;
341 }
342
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 if (visitor_) {
344 visitor_->OnRstStreamReceived(frame);
345 }
346
bnc36c47282019-06-21 05:17:59 -0700347 if (UsesPendingStreams() &&
renjietange76b2da2019-05-13 14:50:23 -0700348 QuicUtils::GetStreamType(stream_id, perspective(),
349 IsIncomingStream(stream_id)) ==
350 READ_UNIDIRECTIONAL &&
renjietang55d182a2019-07-12 10:26:25 -0700351 stream_map_.find(stream_id) == stream_map_.end()) {
renjietange76b2da2019-05-13 14:50:23 -0700352 PendingStreamOnRstStream(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500353 return;
354 }
renjietange76b2da2019-05-13 14:50:23 -0700355
renjietang2c4d7122019-05-20 17:18:14 -0700356 QuicStream* stream = GetOrCreateStream(stream_id);
renjietange76b2da2019-05-13 14:50:23 -0700357
renjietang2c4d7122019-05-20 17:18:14 -0700358 if (!stream) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500359 HandleRstOnValidNonexistentStream(frame);
360 return; // Errors are handled by GetOrCreateStream.
361 }
renjietangb663b862019-07-08 16:02:39 -0700362 if (stream->is_static()) {
renjietangfbeb5bf2019-04-19 15:06:20 -0700363 connection()->CloseConnection(
364 QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
365 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
366 return;
367 }
renjietang2c4d7122019-05-20 17:18:14 -0700368 stream->OnStreamReset(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369}
370
dschinazi17d42422019-06-18 16:35:07 -0700371void QuicSession::OnGoAway(const QuicGoAwayFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500372 goaway_received_ = true;
373}
374
dmcardlecf0bfcf2019-12-13 08:08:21 -0800375void QuicSession::OnMessageReceived(quiche::QuicheStringPiece message) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500376 QUIC_DVLOG(1) << ENDPOINT << "Received message, length: " << message.length()
377 << ", " << message;
378}
379
fayang01062942020-01-22 07:23:23 -0800380void QuicSession::OnHandshakeDoneReceived() {
381 QUIC_DVLOG(1) << ENDPOINT << "OnHandshakeDoneReceived";
382 GetMutableCryptoStream()->OnHandshakeDoneReceived();
383}
384
wub2b5942f2019-04-11 13:22:50 -0700385// static
386void QuicSession::RecordConnectionCloseAtServer(QuicErrorCode error,
387 ConnectionCloseSource source) {
388 if (error != QUIC_NO_ERROR) {
389 if (source == ConnectionCloseSource::FROM_SELF) {
390 QUIC_SERVER_HISTOGRAM_ENUM(
391 "quic_server_connection_close_errors", error, QUIC_LAST_ERROR,
392 "QuicErrorCode for server-closed connections.");
393 } else {
394 QUIC_SERVER_HISTOGRAM_ENUM(
395 "quic_client_connection_close_errors", error, QUIC_LAST_ERROR,
396 "QuicErrorCode for client-closed connections.");
397 }
398 }
399}
400
fkastenholz5d880a92019-06-21 09:01:56 -0700401void QuicSession::OnConnectionClosed(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500402 ConnectionCloseSource source) {
403 DCHECK(!connection_->connected());
wub2b5942f2019-04-11 13:22:50 -0700404 if (perspective() == Perspective::IS_SERVER) {
fkastenholz5d880a92019-06-21 09:01:56 -0700405 RecordConnectionCloseAtServer(frame.quic_error_code, source);
wub2b5942f2019-04-11 13:22:50 -0700406 }
407
fkastenholz488a4622019-08-26 06:24:46 -0700408 if (on_closed_frame_.extracted_error_code == QUIC_NO_ERROR) {
409 // Save all of the connection close information
410 on_closed_frame_ = frame;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500411 }
412
renjietangb663b862019-07-08 16:02:39 -0700413 // Copy all non static streams in a new map for the ease of deleting.
414 QuicSmallMap<QuicStreamId, QuicStream*, 10> non_static_streams;
renjietang55d182a2019-07-12 10:26:25 -0700415 for (const auto& it : stream_map_) {
renjietangb663b862019-07-08 16:02:39 -0700416 if (!it.second->is_static()) {
417 non_static_streams[it.first] = it.second.get();
renjietangfbeb5bf2019-04-19 15:06:20 -0700418 }
renjietangb663b862019-07-08 16:02:39 -0700419 }
420 for (const auto& it : non_static_streams) {
421 QuicStreamId id = it.first;
422 it.second->OnConnectionClosed(frame.quic_error_code, source);
renjietang55d182a2019-07-12 10:26:25 -0700423 if (stream_map_.find(id) != stream_map_.end()) {
renjietangb663b862019-07-08 16:02:39 -0700424 QUIC_BUG << ENDPOINT << "Stream " << id
425 << " failed to close under OnConnectionClosed";
426 CloseStream(id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500427 }
428 }
429
430 // Cleanup zombie stream map on connection close.
431 while (!zombie_streams_.empty()) {
432 ZombieStreamMap::iterator it = zombie_streams_.begin();
433 closed_streams_.push_back(std::move(it->second));
434 zombie_streams_.erase(it);
435 }
436
437 closed_streams_clean_up_alarm_->Cancel();
438
439 if (visitor_) {
fkastenholz5d880a92019-06-21 09:01:56 -0700440 visitor_->OnConnectionClosed(connection_->connection_id(),
fkastenholz488a4622019-08-26 06:24:46 -0700441 frame.extracted_error_code,
442 frame.error_details, source);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500443 }
444}
445
446void QuicSession::OnWriteBlocked() {
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700447 if (!connection_->connected()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500448 return;
449 }
450 if (visitor_) {
451 visitor_->OnWriteBlocked(connection_);
452 }
453}
454
455void QuicSession::OnSuccessfulVersionNegotiation(
456 const ParsedQuicVersion& version) {
457 GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(version);
458}
459
zhongyi83161e42019-08-19 09:06:25 -0700460void QuicSession::OnPacketReceived(const QuicSocketAddress& /*self_address*/,
461 const QuicSocketAddress& peer_address,
462 bool is_connectivity_probe) {
463 if (is_connectivity_probe && perspective() == Perspective::IS_SERVER) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500464 // Server only sends back a connectivity probe after received a
465 // connectivity probe from a new peer address.
466 connection_->SendConnectivityProbingResponsePacket(peer_address);
467 }
468}
469
470void QuicSession::OnPathDegrading() {}
471
472bool QuicSession::AllowSelfAddressChange() const {
473 return false;
474}
475
476void QuicSession::OnForwardProgressConfirmed() {}
477
478void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
479 // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
480 // assume that it still exists.
481 QuicStreamId stream_id = frame.stream_id;
renjietangd1d00852019-09-06 10:43:12 -0700482 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500483 // This is a window update that applies to the connection, rather than an
484 // individual stream.
QUICHE team51d69992019-08-21 13:38:04 -0700485 QUIC_DVLOG(1) << ENDPOINT
486 << "Received connection level flow control window "
renjietangd088eab2019-11-21 14:54:41 -0800487 "update with max data: "
488 << frame.max_data;
489 flow_controller_.UpdateSendWindowOffset(frame.max_data);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500490 return;
491 }
renjietang28c04b72019-07-01 15:08:09 -0700492
renjietangd1d00852019-09-06 10:43:12 -0700493 if (VersionHasIetfQuicFrames(transport_version()) &&
renjietang28c04b72019-07-01 15:08:09 -0700494 QuicUtils::GetStreamType(stream_id, perspective(),
495 IsIncomingStream(stream_id)) ==
496 READ_UNIDIRECTIONAL) {
497 connection()->CloseConnection(
498 QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
499 "WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.",
500 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
501 return;
502 }
503
QUICHE teama6ef0a62019-03-07 20:34:33 -0500504 QuicStream* stream = GetOrCreateStream(stream_id);
505 if (stream != nullptr) {
506 stream->OnWindowUpdateFrame(frame);
507 }
508}
509
510void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) {
511 // TODO(rjshade): Compare our flow control receive windows for specified
512 // streams: if we have a large window then maybe something
513 // had gone wrong with the flow control accounting.
514 QUIC_DLOG(INFO) << ENDPOINT << "Received BLOCKED frame with stream id: "
515 << frame.stream_id;
516}
517
518bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream,
519 uint64_t previous_bytes_written,
520 bool previous_fin_sent) {
521 if ( // Stream should not be closed.
522 !stream->write_side_closed() &&
523 // Not connection flow control blocked.
524 !flow_controller_.IsBlocked() &&
525 // Detect lack of forward progress.
526 previous_bytes_written == stream->stream_bytes_written() &&
527 previous_fin_sent == stream->fin_sent()) {
528 stream->set_busy_counter(stream->busy_counter() + 1);
dschinazi88bd5b02019-10-10 00:52:20 -0700529 QUIC_DVLOG(1) << ENDPOINT << "Suspected busy loop on stream id "
530 << stream->id() << " stream_bytes_written "
531 << stream->stream_bytes_written() << " fin "
532 << stream->fin_sent() << " count " << stream->busy_counter();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500533 // Wait a few iterations before firing, the exact count is
534 // arbitrary, more than a few to cover a few test-only false
535 // positives.
536 if (stream->busy_counter() > 20) {
dschinazi88bd5b02019-10-10 00:52:20 -0700537 QUIC_LOG(ERROR) << ENDPOINT << "Detected busy loop on stream id "
538 << stream->id() << " stream_bytes_written "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500539 << stream->stream_bytes_written() << " fin "
540 << stream->fin_sent();
541 return false;
542 }
543 } else {
544 stream->set_busy_counter(0);
545 }
546 return true;
547}
548
549bool QuicSession::CheckStreamWriteBlocked(QuicStream* stream) const {
550 if (!stream->write_side_closed() && stream->HasBufferedData() &&
551 !stream->flow_controller()->IsBlocked() &&
552 !write_blocked_streams_.IsStreamBlocked(stream->id())) {
dschinazi88bd5b02019-10-10 00:52:20 -0700553 QUIC_DLOG(ERROR) << ENDPOINT << "stream " << stream->id()
554 << " has buffered " << stream->BufferedDataBytes()
QUICHE teama6ef0a62019-03-07 20:34:33 -0500555 << " bytes, and is not flow control blocked, "
556 "but it is not in the write block list.";
557 return false;
558 }
559 return true;
560}
561
562void QuicSession::OnCanWrite() {
563 if (!RetransmitLostData()) {
564 // Cannot finish retransmitting lost data, connection is write blocked.
565 QUIC_DVLOG(1) << ENDPOINT
566 << "Cannot finish retransmitting lost data, connection is "
567 "write blocked.";
568 return;
569 }
fayangcff885a2019-10-22 07:39:04 -0700570 SetTransmissionType(NOT_RETRANSMISSION);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500571 // We limit the number of writes to the number of pending streams. If more
572 // streams become pending, WillingAndAbleToWrite will be true, which will
573 // cause the connection to request resumption before yielding to other
574 // connections.
575 // If we are connection level flow control blocked, then only allow the
576 // crypto and headers streams to try writing as all other streams will be
577 // blocked.
578 size_t num_writes = flow_controller_.IsBlocked()
579 ? write_blocked_streams_.NumBlockedSpecialStreams()
580 : write_blocked_streams_.NumBlockedStreams();
fayangaee31ef2019-08-20 06:47:51 -0700581 if (num_writes == 0 && !control_frame_manager_.WillingToWrite() &&
vasilvv2b0ab242020-01-07 07:32:09 -0800582 datagram_queue_.empty() &&
renjietangd1d00852019-09-06 10:43:12 -0700583 (!QuicVersionUsesCryptoFrames(transport_version()) ||
fayangaee31ef2019-08-20 06:47:51 -0700584 !GetCryptoStream()->HasBufferedCryptoFrames())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500585 return;
586 }
587
fayanga4b37b22019-06-18 13:37:47 -0700588 QuicConnection::ScopedPacketFlusher flusher(connection_);
renjietangd1d00852019-09-06 10:43:12 -0700589 if (QuicVersionUsesCryptoFrames(transport_version())) {
fayangaee31ef2019-08-20 06:47:51 -0700590 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
591 if (crypto_stream->HasBufferedCryptoFrames()) {
592 crypto_stream->WriteBufferedCryptoFrames();
593 }
594 if (crypto_stream->HasBufferedCryptoFrames()) {
595 // Cannot finish writing buffered crypto frames, connection is write
596 // blocked.
597 return;
598 }
599 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500600 if (control_frame_manager_.WillingToWrite()) {
601 control_frame_manager_.OnCanWrite();
602 }
vasilvv2b0ab242020-01-07 07:32:09 -0800603 // TODO(b/147146815): this makes all datagrams go before stream data. We
604 // should have a better priority scheme for this.
605 if (!datagram_queue_.empty()) {
606 size_t written = datagram_queue_.SendDatagrams();
607 QUIC_DVLOG(1) << ENDPOINT << "Sent " << written << " datagrams";
608 if (!datagram_queue_.empty()) {
609 return;
610 }
611 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500612 for (size_t i = 0; i < num_writes; ++i) {
613 if (!(write_blocked_streams_.HasWriteBlockedSpecialStream() ||
614 write_blocked_streams_.HasWriteBlockedDataStreams())) {
615 // Writing one stream removed another!? Something's broken.
616 QUIC_BUG << "WriteBlockedStream is missing";
617 connection_->CloseConnection(QUIC_INTERNAL_ERROR,
618 "WriteBlockedStream is missing",
619 ConnectionCloseBehavior::SILENT_CLOSE);
620 return;
621 }
622 if (!connection_->CanWriteStreamData()) {
623 return;
624 }
625 currently_writing_stream_id_ = write_blocked_streams_.PopFront();
dschinazi88bd5b02019-10-10 00:52:20 -0700626 QUIC_DVLOG(1) << ENDPOINT << "Removing stream "
627 << currently_writing_stream_id_ << " from write-blocked list";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500628 QuicStream* stream = GetOrCreateStream(currently_writing_stream_id_);
629 if (stream != nullptr && !stream->flow_controller()->IsBlocked()) {
630 // If the stream can't write all bytes it'll re-add itself to the blocked
631 // list.
632 uint64_t previous_bytes_written = stream->stream_bytes_written();
633 bool previous_fin_sent = stream->fin_sent();
dschinazi88bd5b02019-10-10 00:52:20 -0700634 QUIC_DVLOG(1) << ENDPOINT << "stream " << stream->id()
635 << " bytes_written " << previous_bytes_written << " fin "
636 << previous_fin_sent;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500637 stream->OnCanWrite();
638 DCHECK(CheckStreamWriteBlocked(stream));
639 DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written,
640 previous_fin_sent));
641 }
642 currently_writing_stream_id_ = 0;
643 }
644}
645
QUICHE teamb8343252019-04-29 13:58:01 -0700646bool QuicSession::SendProbingData() {
647 if (connection()->sent_packet_manager().MaybeRetransmitOldestPacket(
648 PROBING_RETRANSMISSION)) {
649 return true;
650 }
651 return false;
652}
653
QUICHE teama6ef0a62019-03-07 20:34:33 -0500654bool QuicSession::WillingAndAbleToWrite() const {
655 // Schedule a write when:
656 // 1) control frame manager has pending or new control frames, or
657 // 2) any stream has pending retransmissions, or
658 // 3) If the crypto or headers streams are blocked, or
659 // 4) connection is not flow control blocked and there are write blocked
660 // streams.
renjietangd1d00852019-09-06 10:43:12 -0700661 if (QuicVersionUsesCryptoFrames(transport_version()) &&
fayangaee31ef2019-08-20 06:47:51 -0700662 HasPendingHandshake()) {
663 return true;
664 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500665 return control_frame_manager_.WillingToWrite() ||
666 !streams_with_pending_retransmission_.empty() ||
667 write_blocked_streams_.HasWriteBlockedSpecialStream() ||
668 (!flow_controller_.IsBlocked() &&
669 write_blocked_streams_.HasWriteBlockedDataStreams());
670}
671
672bool QuicSession::HasPendingHandshake() const {
renjietangd1d00852019-09-06 10:43:12 -0700673 if (QuicVersionUsesCryptoFrames(transport_version())) {
fayangaee31ef2019-08-20 06:47:51 -0700674 return GetCryptoStream()->HasPendingCryptoRetransmission() ||
675 GetCryptoStream()->HasBufferedCryptoFrames();
nharper46833c32019-05-15 21:33:05 -0700676 }
renjietangd1d00852019-09-06 10:43:12 -0700677 return QuicContainsKey(streams_with_pending_retransmission_,
678 QuicUtils::GetCryptoStreamId(transport_version())) ||
QUICHE teama6ef0a62019-03-07 20:34:33 -0500679 write_blocked_streams_.IsStreamBlocked(
renjietangd1d00852019-09-06 10:43:12 -0700680 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500681}
682
683uint64_t QuicSession::GetNumOpenDynamicStreams() const {
renjietang55d182a2019-07-12 10:26:25 -0700684 return stream_map_.size() - draining_streams_.size() +
renjietangfbeb5bf2019-04-19 15:06:20 -0700685 locally_closed_streams_highest_offset_.size() -
686 num_incoming_static_streams_ - num_outgoing_static_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500687}
688
689void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
690 const QuicSocketAddress& peer_address,
691 const QuicReceivedPacket& packet) {
692 connection_->ProcessUdpPacket(self_address, peer_address, packet);
693}
694
695QuicConsumedData QuicSession::WritevData(QuicStream* stream,
696 QuicStreamId id,
697 size_t write_length,
698 QuicStreamOffset offset,
699 StreamSendingState state) {
700 // This check is an attempt to deal with potential memory corruption
701 // in which |id| ends up set to 1 (the crypto stream id). If this happen
702 // it might end up resulting in unencrypted stream data being sent.
703 // While this is impossible to avoid given sufficient corruption, this
704 // seems like a reasonable mitigation.
renjietangd1d00852019-09-06 10:43:12 -0700705 if (QuicUtils::IsCryptoStreamId(transport_version(), id) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500706 stream != GetMutableCryptoStream()) {
707 QUIC_BUG << "Stream id mismatch";
708 connection_->CloseConnection(
709 QUIC_INTERNAL_ERROR,
710 "Non-crypto stream attempted to write data as crypto stream.",
711 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
712 return QuicConsumedData(0, false);
713 }
714 if (!IsEncryptionEstablished() &&
renjietangd1d00852019-09-06 10:43:12 -0700715 !QuicUtils::IsCryptoStreamId(transport_version(), id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500716 // Do not let streams write without encryption. The calling stream will end
717 // up write blocked until OnCanWrite is next called.
718 return QuicConsumedData(0, false);
719 }
720
721 QuicConsumedData data =
722 connection_->SendStreamData(id, write_length, offset, state);
723 if (offset >= stream->stream_bytes_written()) {
724 // This is new stream data.
725 write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
726 }
727 return data;
728}
729
730bool QuicSession::WriteControlFrame(const QuicFrame& frame) {
731 return connection_->SendControlFrame(frame);
732}
733
734void QuicSession::SendRstStream(QuicStreamId id,
735 QuicRstStreamErrorCode error,
736 QuicStreamOffset bytes_written) {
renjietang61cc2452019-11-26 10:57:10 -0800737 if (connection()->connected()) {
738 QuicConnection::ScopedPacketFlusher flusher(connection());
739 MaybeSendRstStreamFrame(id, error, bytes_written);
740 MaybeSendStopSendingFrame(id, error);
741
742 connection_->OnStreamReset(id, error);
743 }
744
745 if (error != QUIC_STREAM_NO_ERROR && QuicContainsKey(zombie_streams_, id)) {
746 OnStreamDoneWaitingForAcks(id);
747 return;
748 }
749 CloseStreamInner(id, true);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500750}
751
renjietang61cc2452019-11-26 10:57:10 -0800752void QuicSession::MaybeSendRstStreamFrame(QuicStreamId id,
753 QuicRstStreamErrorCode error,
754 QuicStreamOffset bytes_written) {
755 DCHECK(connection()->connected());
756 if (!VersionHasIetfQuicFrames(transport_version()) ||
757 QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
758 READ_UNIDIRECTIONAL) {
759 control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
760 }
761}
762
763void QuicSession::MaybeSendStopSendingFrame(QuicStreamId id,
764 QuicRstStreamErrorCode error) {
765 DCHECK(connection()->connected());
766 if (VersionHasIetfQuicFrames(transport_version()) &&
767 QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
768 WRITE_UNIDIRECTIONAL) {
769 control_frame_manager_.WriteOrBufferStopSending(error, id);
770 }
771}
772
QUICHE teama6ef0a62019-03-07 20:34:33 -0500773void QuicSession::SendGoAway(QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700774 const std::string& reason) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500775 // GOAWAY frame is not supported in v99.
renjietangd1d00852019-09-06 10:43:12 -0700776 DCHECK(!VersionHasIetfQuicFrames(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500777 if (goaway_sent_) {
778 return;
779 }
780 goaway_sent_ = true;
781 control_frame_manager_.WriteOrBufferGoAway(
782 error_code, stream_id_manager_.largest_peer_created_stream_id(), reason);
783}
784
785void QuicSession::SendBlocked(QuicStreamId id) {
786 control_frame_manager_.WriteOrBufferBlocked(id);
787}
788
789void QuicSession::SendWindowUpdate(QuicStreamId id,
790 QuicStreamOffset byte_offset) {
791 control_frame_manager_.WriteOrBufferWindowUpdate(id, byte_offset);
792}
793
rcha8b56e42019-09-20 10:41:48 -0700794void QuicSession::OnError(QuicErrorCode error_code, std::string error_details) {
795 connection_->CloseConnection(
796 error_code, error_details,
797 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
798}
799
fkastenholz3c4eabf2019-04-22 07:49:59 -0700800void QuicSession::SendMaxStreams(QuicStreamCount stream_count,
801 bool unidirectional) {
802 control_frame_manager_.WriteOrBufferMaxStreams(stream_count, unidirectional);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500803}
804
fkastenholz3c4eabf2019-04-22 07:49:59 -0700805void QuicSession::SendStreamsBlocked(QuicStreamCount stream_count,
806 bool unidirectional) {
807 control_frame_manager_.WriteOrBufferStreamsBlocked(stream_count,
808 unidirectional);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500809}
810
811void QuicSession::CloseStream(QuicStreamId stream_id) {
812 CloseStreamInner(stream_id, false);
813}
814
815void QuicSession::InsertLocallyClosedStreamsHighestOffset(
816 const QuicStreamId id,
817 QuicStreamOffset offset) {
818 locally_closed_streams_highest_offset_[id] = offset;
819 if (IsIncomingStream(id)) {
820 ++num_locally_closed_incoming_streams_highest_offset_;
821 }
822}
823
824void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
825 QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
826
renjietang55d182a2019-07-12 10:26:25 -0700827 StreamMap::iterator it = stream_map_.find(stream_id);
828 if (it == stream_map_.end()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500829 // When CloseStreamInner has been called recursively (via
830 // QuicStream::OnClose), the stream will already have been deleted
831 // from stream_map_, so return immediately.
832 QUIC_DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
833 return;
834 }
835 QuicStream* stream = it->second.get();
renjietangb663b862019-07-08 16:02:39 -0700836 if (stream->is_static()) {
renjietangfbeb5bf2019-04-19 15:06:20 -0700837 QUIC_DVLOG(1) << ENDPOINT
838 << "Try to close a static stream, id: " << stream_id
839 << " Closing connection";
840 connection()->CloseConnection(
841 QUIC_INVALID_STREAM_ID, "Try to close a static stream",
842 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
843 return;
844 }
renjietangde12d3d2019-07-19 10:57:42 -0700845 StreamType type = stream->type();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500846
847 // Tell the stream that a RST has been sent.
848 if (locally_reset) {
849 stream->set_rst_sent(true);
850 }
851
852 if (stream->IsWaitingForAcks()) {
853 zombie_streams_[stream->id()] = std::move(it->second);
854 } else {
zhongyi1b2f7832019-06-14 13:31:34 -0700855 // Clean up the stream since it is no longer waiting for acks.
fayangcff885a2019-10-22 07:39:04 -0700856 streams_waiting_for_acks_.erase(stream->id());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500857 closed_streams_.push_back(std::move(it->second));
858 // Do not retransmit data of a closed stream.
859 streams_with_pending_retransmission_.erase(stream_id);
860 if (!closed_streams_clean_up_alarm_->IsSet()) {
861 closed_streams_clean_up_alarm_->Set(
862 connection_->clock()->ApproximateNow());
863 }
864 }
865
866 // If we haven't received a FIN or RST for this stream, we need to keep track
867 // of the how many bytes the stream's flow controller believes it has
868 // received, for accurate connection level flow control accounting.
renjietang6c066562019-11-04 17:05:59 -0800869 const bool had_fin_or_rst = stream->HasReceivedFinalOffset();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500870 if (!had_fin_or_rst) {
871 InsertLocallyClosedStreamsHighestOffset(
872 stream_id, stream->flow_controller()->highest_received_byte_offset());
873 }
renjietang55d182a2019-07-12 10:26:25 -0700874 stream_map_.erase(it);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500875 if (IsIncomingStream(stream_id)) {
876 --num_dynamic_incoming_streams_;
877 }
878
879 const bool stream_was_draining =
880 draining_streams_.find(stream_id) != draining_streams_.end();
881 if (stream_was_draining) {
882 if (IsIncomingStream(stream_id)) {
883 --num_draining_incoming_streams_;
884 }
885 draining_streams_.erase(stream_id);
renjietangd1d00852019-09-06 10:43:12 -0700886 } else if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500887 // Stream was not draining, but we did have a fin or rst, so we can now
888 // free the stream ID if version 99.
889 if (had_fin_or_rst) {
890 v99_streamid_manager_.OnStreamClosed(stream_id);
891 }
892 }
893
894 stream->OnClose();
895
896 if (!stream_was_draining && !IsIncomingStream(stream_id) && had_fin_or_rst &&
renjietangd1d00852019-09-06 10:43:12 -0700897 !VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500898 // Streams that first became draining already called OnCanCreate...
899 // This covers the case where the stream went directly to being closed.
renjietangde12d3d2019-07-19 10:57:42 -0700900 OnCanCreateNewOutgoingStream(type != BIDIRECTIONAL);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500901 }
902}
903
904void QuicSession::ClosePendingStream(QuicStreamId stream_id) {
905 QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
906
bnc092d8212019-08-07 11:53:20 -0700907 pending_stream_map_.erase(stream_id);
renjietangd1d00852019-09-06 10:43:12 -0700908 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500909 v99_streamid_manager_.OnStreamClosed(stream_id);
910 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500911}
912
913void QuicSession::OnFinalByteOffsetReceived(
914 QuicStreamId stream_id,
915 QuicStreamOffset final_byte_offset) {
916 auto it = locally_closed_streams_highest_offset_.find(stream_id);
917 if (it == locally_closed_streams_highest_offset_.end()) {
918 return;
919 }
920
921 QUIC_DVLOG(1) << ENDPOINT << "Received final byte offset "
922 << final_byte_offset << " for stream " << stream_id;
923 QuicByteCount offset_diff = final_byte_offset - it->second;
924 if (flow_controller_.UpdateHighestReceivedOffset(
925 flow_controller_.highest_received_byte_offset() + offset_diff)) {
926 // If the final offset violates flow control, close the connection now.
927 if (flow_controller_.FlowControlViolation()) {
928 connection_->CloseConnection(
929 QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
930 "Connection level flow control violation",
931 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
932 return;
933 }
934 }
935
936 flow_controller_.AddBytesConsumed(offset_diff);
937 locally_closed_streams_highest_offset_.erase(it);
938 if (IsIncomingStream(stream_id)) {
939 --num_locally_closed_incoming_streams_highest_offset_;
renjietangd1d00852019-09-06 10:43:12 -0700940 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500941 v99_streamid_manager_.OnStreamClosed(stream_id);
942 }
renjietangd1d00852019-09-06 10:43:12 -0700943 } else if (!VersionHasIetfQuicFrames(transport_version())) {
fkastenholz8556dc22019-07-18 12:42:38 -0700944 OnCanCreateNewOutgoingStream(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500945 }
946}
947
948bool QuicSession::IsEncryptionEstablished() const {
fkastenholzba94bc32019-11-08 08:50:25 -0800949 if (GetCryptoStream() == nullptr) {
950 return false;
951 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500952 return GetCryptoStream()->encryption_established();
953}
954
fayanga3d8df72020-01-14 11:54:39 -0800955bool QuicSession::OneRttKeysAvailable() const {
fkastenholzba94bc32019-11-08 08:50:25 -0800956 if (GetCryptoStream() == nullptr) {
957 return false;
958 }
fayang685367a2020-01-14 10:40:15 -0800959 return GetCryptoStream()->one_rtt_keys_available();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500960}
961
962void QuicSession::OnConfigNegotiated() {
dschinazi88bd5b02019-10-10 00:52:20 -0700963 QUIC_DVLOG(1) << ENDPOINT << "OnConfigNegotiated";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500964 connection_->SetFromConfig(config_);
965
renjietang203926d2019-09-04 15:09:03 -0700966 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700967 uint32_t max_streams = 0;
renjietange6d94672020-01-07 10:30:10 -0800968 if (config_.HasReceivedMaxBidirectionalStreams()) {
969 max_streams = config_.ReceivedMaxBidirectionalStreams();
fkastenholzd3a1de92019-05-15 07:00:07 -0700970 }
dschinazi88bd5b02019-10-10 00:52:20 -0700971 QUIC_DVLOG(1) << ENDPOINT
972 << "Setting Bidirectional outgoing_max_streams_ to "
fkastenholzd3a1de92019-05-15 07:00:07 -0700973 << max_streams;
renjietang216dc012019-08-27 11:28:27 -0700974 v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(max_streams);
fkastenholzd3a1de92019-05-15 07:00:07 -0700975
976 max_streams = 0;
renjietange6d94672020-01-07 10:30:10 -0800977 if (config_.HasReceivedMaxUnidirectionalStreams()) {
978 max_streams = config_.ReceivedMaxUnidirectionalStreams();
fkastenholzd3a1de92019-05-15 07:00:07 -0700979 }
ianswettdde2a1e2019-12-10 10:39:44 -0800980 if (max_streams < num_expected_unidirectional_static_streams_) {
981 // TODO(ianswett): Change this to an application error for HTTP/3.
982 QUIC_DLOG(ERROR) << "Received unidirectional stream limit of "
983 << max_streams << " < "
984 << num_expected_unidirectional_static_streams_;
985 connection_->CloseConnection(
986 QUIC_MAX_STREAMS_ERROR, "New unidirectional stream limit is too low.",
987 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
988 }
dschinazi88bd5b02019-10-10 00:52:20 -0700989 QUIC_DVLOG(1) << ENDPOINT
990 << "Setting Unidirectional outgoing_max_streams_ to "
fkastenholzd3a1de92019-05-15 07:00:07 -0700991 << max_streams;
renjietang216dc012019-08-27 11:28:27 -0700992 v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(max_streams);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500993 } else {
fkastenholzd3a1de92019-05-15 07:00:07 -0700994 uint32_t max_streams = 0;
renjietange6d94672020-01-07 10:30:10 -0800995 if (config_.HasReceivedMaxBidirectionalStreams()) {
996 max_streams = config_.ReceivedMaxBidirectionalStreams();
fkastenholzd3a1de92019-05-15 07:00:07 -0700997 }
dschinazi88bd5b02019-10-10 00:52:20 -0700998 QUIC_DVLOG(1) << ENDPOINT << "Setting max_open_outgoing_streams_ to "
999 << max_streams;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001000 stream_id_manager_.set_max_open_outgoing_streams(max_streams);
1001 }
fkastenholzd3a1de92019-05-15 07:00:07 -07001002
QUICHE teama6ef0a62019-03-07 20:34:33 -05001003 if (perspective() == Perspective::IS_SERVER) {
1004 if (config_.HasReceivedConnectionOptions()) {
1005 // The following variations change the initial receive flow control
1006 // window sizes.
1007 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW6)) {
1008 AdjustInitialFlowControlWindows(64 * 1024);
1009 }
1010 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW7)) {
1011 AdjustInitialFlowControlWindows(128 * 1024);
1012 }
1013 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW8)) {
1014 AdjustInitialFlowControlWindows(256 * 1024);
1015 }
1016 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW9)) {
1017 AdjustInitialFlowControlWindows(512 * 1024);
1018 }
1019 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
1020 AdjustInitialFlowControlWindows(1024 * 1024);
1021 }
fayang944cfbc2019-07-31 09:15:00 -07001022 if (GetQuicReloadableFlag(quic_use_http2_priority_write_scheduler) &&
1023 ContainsQuicTag(config_.ReceivedConnectionOptions(), kH2PR) &&
renjietangd1d00852019-09-06 10:43:12 -07001024 !VersionHasIetfQuicFrames(transport_version())) {
fayange606e0c2019-08-05 06:56:05 -07001025 // Enable HTTP2 (tree-style) priority write scheduler.
fayang944cfbc2019-07-31 09:15:00 -07001026 use_http2_priority_write_scheduler_ =
fayange606e0c2019-08-05 06:56:05 -07001027 write_blocked_streams_.SwitchWriteScheduler(
renjietangd1d00852019-09-06 10:43:12 -07001028 spdy::WriteSchedulerType::HTTP2, transport_version());
QUICHE teamdfd1cc82020-01-07 14:26:10 -08001029 } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kFIFO)) {
fayange606e0c2019-08-05 06:56:05 -07001030 // Enable FIFO write scheduler.
QUICHE teamdfd1cc82020-01-07 14:26:10 -08001031 write_blocked_streams_.SwitchWriteScheduler(
1032 spdy::WriteSchedulerType::FIFO, transport_version());
fayangae266342019-08-05 12:19:59 -07001033 } else if (GetQuicReloadableFlag(quic_enable_lifo_write_scheduler) &&
1034 ContainsQuicTag(config_.ReceivedConnectionOptions(), kLIFO)) {
1035 // Enable LIFO write scheduler.
1036 if (write_blocked_streams_.SwitchWriteScheduler(
renjietangd1d00852019-09-06 10:43:12 -07001037 spdy::WriteSchedulerType::LIFO, transport_version())) {
fayangae266342019-08-05 12:19:59 -07001038 QUIC_RELOADABLE_FLAG_COUNT(quic_enable_lifo_write_scheduler);
1039 }
fayang1b11b962019-09-16 14:01:48 -07001040 } else if (GetQuicReloadableFlag(quic_enable_rr_write_scheduler) &&
1041 ContainsQuicTag(config_.ReceivedConnectionOptions(), kRRWS) &&
1042 write_blocked_streams_.scheduler_type() ==
1043 spdy::WriteSchedulerType::SPDY) {
1044 QUIC_RELOADABLE_FLAG_COUNT(quic_enable_rr_write_scheduler);
1045 enable_round_robin_scheduling_ = true;
fayang944cfbc2019-07-31 09:15:00 -07001046 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001047 }
1048
1049 config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
1050 }
1051
renjietangd1d00852019-09-06 10:43:12 -07001052 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001053 v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
renjietange6d94672020-01-07 10:30:10 -08001054 config_.GetMaxBidirectionalStreamsToSend());
fkastenholzd3a1de92019-05-15 07:00:07 -07001055 v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
renjietange6d94672020-01-07 10:30:10 -08001056 config_.GetMaxUnidirectionalStreamsToSend());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001057 } else {
fkastenholzd3a1de92019-05-15 07:00:07 -07001058 // A small number of additional incoming streams beyond the limit should be
1059 // allowed. This helps avoid early connection termination when FIN/RSTs for
1060 // old streams are lost or arrive out of order.
1061 // Use a minimum number of additional streams, or a percentage increase,
1062 // whichever is larger.
1063 uint32_t max_incoming_streams_to_send =
renjietange6d94672020-01-07 10:30:10 -08001064 config_.GetMaxBidirectionalStreamsToSend();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001065 uint32_t max_incoming_streams =
1066 std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
1067 static_cast<uint32_t>(max_incoming_streams_to_send *
1068 kMaxStreamsMultiplier));
1069 stream_id_manager_.set_max_open_incoming_streams(max_incoming_streams);
1070 }
1071
dschinazi18cdf132019-10-09 16:08:18 -07001072 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1073 // When using IETF-style TLS transport parameters, inform existing streams
1074 // of new flow-control limits.
1075 if (config_.HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional()) {
1076 OnNewStreamOutgoingBidirectionalFlowControlWindow(
1077 config_.ReceivedInitialMaxStreamDataBytesOutgoingBidirectional());
1078 }
1079 if (config_.HasReceivedInitialMaxStreamDataBytesIncomingBidirectional()) {
1080 OnNewStreamIncomingBidirectionalFlowControlWindow(
1081 config_.ReceivedInitialMaxStreamDataBytesIncomingBidirectional());
1082 }
1083 if (config_.HasReceivedInitialMaxStreamDataBytesUnidirectional()) {
1084 OnNewStreamUnidirectionalFlowControlWindow(
1085 config_.ReceivedInitialMaxStreamDataBytesUnidirectional());
1086 }
1087 } else { // The version uses Google QUIC Crypto.
1088 if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
1089 // Streams which were created before the SHLO was received (0-RTT
1090 // requests) are now informed of the peer's initial flow control window.
1091 OnNewStreamFlowControlWindow(
1092 config_.ReceivedInitialStreamFlowControlWindowBytes());
1093 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001094 }
dschinazi18cdf132019-10-09 16:08:18 -07001095
QUICHE teama6ef0a62019-03-07 20:34:33 -05001096 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) {
1097 OnNewSessionFlowControlWindow(
1098 config_.ReceivedInitialSessionFlowControlWindowBytes());
1099 }
fkastenholz9b4b0ad2019-08-20 05:10:40 -07001100 is_configured_ = true;
fkastenholz56055be2019-09-17 11:17:37 -07001101
1102 // Inform stream ID manager so that it can reevaluate any deferred
1103 // STREAMS_BLOCKED or MAX_STREAMS frames against the config and either send
1104 // the frames or discard them.
1105 if (VersionHasIetfQuicFrames(connection_->transport_version())) {
rcha8b56e42019-09-20 10:41:48 -07001106 QuicConnection::ScopedPacketFlusher flusher(connection());
fkastenholz56055be2019-09-17 11:17:37 -07001107 v99_streamid_manager_.OnConfigNegotiated();
1108 }
dschinazi18cdf132019-10-09 16:08:18 -07001109
1110 // Ask flow controllers to try again since the config could have unblocked us.
1111 if (connection_->version().AllowsLowFlowControlLimits()) {
1112 OnCanWrite();
1113 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001114}
1115
1116void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
1117 const float session_window_multiplier =
1118 config_.GetInitialStreamFlowControlWindowToSend()
1119 ? static_cast<float>(
1120 config_.GetInitialSessionFlowControlWindowToSend()) /
1121 config_.GetInitialStreamFlowControlWindowToSend()
1122 : 1.5;
1123
1124 QUIC_DVLOG(1) << ENDPOINT << "Set stream receive window to " << stream_window;
1125 config_.SetInitialStreamFlowControlWindowToSend(stream_window);
1126
1127 size_t session_window = session_window_multiplier * stream_window;
1128 QUIC_DVLOG(1) << ENDPOINT << "Set session receive window to "
1129 << session_window;
1130 config_.SetInitialSessionFlowControlWindowToSend(session_window);
1131 flow_controller_.UpdateReceiveWindowSize(session_window);
1132 // Inform all existing streams about the new window.
renjietang55d182a2019-07-12 10:26:25 -07001133 for (auto const& kv : stream_map_) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001134 kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window);
1135 }
renjietangd1d00852019-09-06 10:43:12 -07001136 if (!QuicVersionUsesCryptoFrames(transport_version())) {
renjietang08a9cf72019-04-23 17:01:34 -07001137 GetMutableCryptoStream()->flow_controller()->UpdateReceiveWindowSize(
1138 stream_window);
1139 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001140}
1141
1142void QuicSession::HandleFrameOnNonexistentOutgoingStream(
1143 QuicStreamId stream_id) {
1144 DCHECK(!IsClosedStream(stream_id));
1145 // Received a frame for a locally-created stream that is not currently
1146 // active. This is an error.
1147 connection()->CloseConnection(
1148 QUIC_INVALID_STREAM_ID, "Data for nonexistent stream",
1149 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1150}
1151
1152void QuicSession::HandleRstOnValidNonexistentStream(
1153 const QuicRstStreamFrame& frame) {
1154 // If the stream is neither originally in active streams nor created in
renjietang880d2432019-07-16 13:14:37 -07001155 // GetOrCreateStream(), it could be a closed stream in which case its
QUICHE teama6ef0a62019-03-07 20:34:33 -05001156 // final received byte offset need to be updated.
1157 if (IsClosedStream(frame.stream_id)) {
1158 // The RST frame contains the final byte offset for the stream: we can now
1159 // update the connection level flow controller if needed.
1160 OnFinalByteOffsetReceived(frame.stream_id, frame.byte_offset);
1161 }
1162}
1163
1164void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
dschinazi88bd5b02019-10-10 00:52:20 -07001165 QUIC_DVLOG(1) << ENDPOINT << "OnNewStreamFlowControlWindow " << new_window;
dschinazic7036122019-04-30 12:46:34 -07001166 if (new_window < kMinimumFlowControlSendWindow &&
1167 !connection_->version().AllowsLowFlowControlLimits()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001168 QUIC_LOG_FIRST_N(ERROR, 1)
1169 << "Peer sent us an invalid stream flow control send window: "
dschinazic7036122019-04-30 12:46:34 -07001170 << new_window << ", below minimum: " << kMinimumFlowControlSendWindow;
renjietang255ff772019-09-04 14:14:03 -07001171 connection_->CloseConnection(
1172 QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
1173 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001174 return;
1175 }
1176
1177 // Inform all existing streams about the new window.
renjietang55d182a2019-07-12 10:26:25 -07001178 for (auto const& kv : stream_map_) {
dschinazi88bd5b02019-10-10 00:52:20 -07001179 QUIC_DVLOG(1) << ENDPOINT << "Informing stream " << kv.first
1180 << " of new stream flow control window " << new_window;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001181 kv.second->UpdateSendWindowOffset(new_window);
1182 }
renjietangd1d00852019-09-06 10:43:12 -07001183 if (!QuicVersionUsesCryptoFrames(transport_version())) {
dschinazi88bd5b02019-10-10 00:52:20 -07001184 QUIC_DVLOG(1)
1185 << ENDPOINT
1186 << "Informing crypto stream of new stream flow control window "
1187 << new_window;
renjietang08a9cf72019-04-23 17:01:34 -07001188 GetMutableCryptoStream()->UpdateSendWindowOffset(new_window);
1189 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001190}
1191
dschinazi18cdf132019-10-09 16:08:18 -07001192void QuicSession::OnNewStreamUnidirectionalFlowControlWindow(
1193 QuicStreamOffset new_window) {
1194 QUIC_DVLOG(1) << ENDPOINT << "OnNewStreamUnidirectionalFlowControlWindow "
1195 << new_window;
1196 // Inform all existing outgoing unidirectional streams about the new window.
1197 for (auto const& kv : stream_map_) {
1198 const QuicStreamId id = kv.first;
1199 if (QuicUtils::IsBidirectionalStreamId(id)) {
1200 continue;
1201 }
1202 if (!QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1203 perspective())) {
1204 continue;
1205 }
1206 QUIC_DVLOG(1) << ENDPOINT << "Informing unidirectional stream " << id
1207 << " of new stream flow control window " << new_window;
1208 kv.second->UpdateSendWindowOffset(new_window);
1209 }
1210}
1211
1212void QuicSession::OnNewStreamOutgoingBidirectionalFlowControlWindow(
1213 QuicStreamOffset new_window) {
1214 QUIC_DVLOG(1) << ENDPOINT
1215 << "OnNewStreamOutgoingBidirectionalFlowControlWindow "
1216 << new_window;
1217 // Inform all existing outgoing bidirectional streams about the new window.
1218 for (auto const& kv : stream_map_) {
1219 const QuicStreamId id = kv.first;
1220 if (!QuicUtils::IsBidirectionalStreamId(id)) {
1221 continue;
1222 }
1223 if (!QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1224 perspective())) {
1225 continue;
1226 }
1227 QUIC_DVLOG(1) << ENDPOINT << "Informing outgoing bidirectional stream "
1228 << id << " of new stream flow control window " << new_window;
1229 kv.second->UpdateSendWindowOffset(new_window);
1230 }
1231}
1232
1233void QuicSession::OnNewStreamIncomingBidirectionalFlowControlWindow(
1234 QuicStreamOffset new_window) {
1235 QUIC_DVLOG(1) << ENDPOINT
1236 << "OnNewStreamIncomingBidirectionalFlowControlWindow "
1237 << new_window;
1238 // Inform all existing incoming bidirectional streams about the new window.
1239 for (auto const& kv : stream_map_) {
1240 const QuicStreamId id = kv.first;
1241 if (!QuicUtils::IsBidirectionalStreamId(id)) {
1242 continue;
1243 }
1244 if (QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1245 perspective())) {
1246 continue;
1247 }
1248 QUIC_DVLOG(1) << ENDPOINT << "Informing incoming bidirectional stream "
1249 << id << " of new stream flow control window " << new_window;
1250 kv.second->UpdateSendWindowOffset(new_window);
1251 }
1252}
1253
QUICHE teama6ef0a62019-03-07 20:34:33 -05001254void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
dschinazi88bd5b02019-10-10 00:52:20 -07001255 QUIC_DVLOG(1) << ENDPOINT << "OnNewSessionFlowControlWindow " << new_window;
dschinazic7036122019-04-30 12:46:34 -07001256 if (new_window < kMinimumFlowControlSendWindow &&
1257 !connection_->version().AllowsLowFlowControlLimits()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001258 QUIC_LOG_FIRST_N(ERROR, 1)
1259 << "Peer sent us an invalid session flow control send window: "
1260 << new_window << ", below default: " << kMinimumFlowControlSendWindow;
renjietang255ff772019-09-04 14:14:03 -07001261 connection_->CloseConnection(
1262 QUIC_FLOW_CONTROL_INVALID_WINDOW, "New connection window too low",
1263 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001264 return;
1265 }
1266
1267 flow_controller_.UpdateSendWindowOffset(new_window);
1268}
1269
1270void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
fayangd58736d2019-11-27 13:35:31 -08001271 DCHECK(!use_handshake_delegate());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001272 switch (event) {
renjietangea71d6f2019-08-19 12:22:28 -07001273 case ENCRYPTION_ESTABLISHED:
QUICHE teama6ef0a62019-03-07 20:34:33 -05001274 // Retransmit originally packets that were sent, since they can't be
1275 // decrypted by the peer.
1276 connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
1277 // Given any streams blocked by encryption a chance to write.
1278 OnCanWrite();
1279 break;
1280
fayangf5054d92020-01-17 10:57:47 -08001281 case EVENT_HANDSHAKE_CONFIRMED:
QUICHE teama6ef0a62019-03-07 20:34:33 -05001282 QUIC_BUG_IF(!config_.negotiated())
1283 << ENDPOINT << "Handshake confirmed without parameter negotiation.";
1284 // Discard originally encrypted packets, since they can't be decrypted by
1285 // the peer.
1286 NeuterUnencryptedData();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001287 break;
1288
1289 default:
1290 QUIC_LOG(ERROR) << ENDPOINT << "Got unknown handshake event: " << event;
1291 }
1292}
1293
fayangd58736d2019-11-27 13:35:31 -08001294void QuicSession::OnNewKeysAvailable(EncryptionLevel level,
1295 std::unique_ptr<QuicDecrypter> decrypter,
1296 bool set_alternative_decrypter,
1297 bool latch_once_used,
1298 std::unique_ptr<QuicEncrypter> encrypter) {
1299 DCHECK(use_handshake_delegate());
1300 // Install new keys.
1301 connection()->SetEncrypter(level, std::move(encrypter));
1302 if (connection()->version().KnowsWhichDecrypterToUse()) {
1303 connection()->InstallDecrypter(level, std::move(decrypter));
1304 return;
1305 }
1306 if (set_alternative_decrypter) {
1307 connection()->SetAlternativeDecrypter(level, std::move(decrypter),
1308 latch_once_used);
1309 return;
1310 }
1311 connection()->SetDecrypter(level, std::move(decrypter));
1312}
1313
1314void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
1315 DCHECK(use_handshake_delegate());
1316 QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
1317 << EncryptionLevelToString(level);
1318 connection()->SetDefaultEncryptionLevel(level);
1319
1320 switch (level) {
1321 case ENCRYPTION_INITIAL:
1322 break;
1323 case ENCRYPTION_ZERO_RTT:
fayang401cf202019-12-06 10:30:13 -08001324 if (perspective() == Perspective::IS_CLIENT) {
1325 // Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since
1326 // they can't be decrypted by the server.
1327 connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
1328 // Given any streams blocked by encryption a chance to write.
1329 OnCanWrite();
1330 }
fayangd58736d2019-11-27 13:35:31 -08001331 break;
1332 case ENCRYPTION_HANDSHAKE:
1333 break;
1334 case ENCRYPTION_FORWARD_SECURE:
rch9001a962019-12-17 10:44:04 -08001335 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1336 QUIC_BUG_IF(!GetCryptoStream()->crypto_negotiated_params().cipher_suite)
1337 << ENDPOINT
1338 << "Handshake confirmed without cipher suite negotiation.";
1339 }
fayangd58736d2019-11-27 13:35:31 -08001340 QUIC_BUG_IF(!config_.negotiated())
1341 << ENDPOINT << "Handshake confirmed without parameter negotiation.";
fayang01062942020-01-22 07:23:23 -08001342 if (connection()->version().HasHandshakeDone() &&
1343 perspective_ == Perspective::IS_SERVER) {
1344 // Server sends HANDSHAKE_DONE to signal confirmation of the handshake
1345 // to the client.
1346 control_frame_manager_.WriteOrBufferHandshakeDone();
1347 }
fayangd58736d2019-11-27 13:35:31 -08001348 break;
1349 default:
1350 QUIC_BUG << "Unknown encryption level: "
1351 << EncryptionLevelToString(level);
1352 }
1353}
1354
1355void QuicSession::DiscardOldDecryptionKey(EncryptionLevel level) {
1356 DCHECK(use_handshake_delegate());
1357 if (!connection()->version().KnowsWhichDecrypterToUse()) {
1358 // TODO(fayang): actually discard keys.
1359 return;
1360 }
1361 connection()->RemoveDecrypter(level);
1362}
1363
1364void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
1365 DCHECK(use_handshake_delegate());
1366 QUIC_DVLOG(1) << ENDPOINT << "Discard keys of "
1367 << EncryptionLevelToString(level);
1368 // TODO(fayang): actually discard keys.
1369 switch (level) {
1370 case ENCRYPTION_INITIAL:
1371 NeuterUnencryptedData();
1372 break;
1373 case ENCRYPTION_HANDSHAKE:
fayang01062942020-01-22 07:23:23 -08001374 NeuterHandshakeData();
fayangd58736d2019-11-27 13:35:31 -08001375 break;
1376 case ENCRYPTION_ZERO_RTT:
1377 break;
1378 case ENCRYPTION_FORWARD_SECURE:
1379 QUIC_BUG << "Tries to drop 1-RTT keys";
1380 break;
1381 default:
1382 QUIC_BUG << "Unknown encryption level: "
1383 << EncryptionLevelToString(level);
1384 }
1385}
1386
1387void QuicSession::NeuterHandshakeData() {
1388 DCHECK(use_handshake_delegate());
1389 connection()->OnHandshakeComplete();
1390}
1391
QUICHE teama6ef0a62019-03-07 20:34:33 -05001392void QuicSession::OnCryptoHandshakeMessageSent(
1393 const CryptoHandshakeMessage& /*message*/) {}
1394
1395void QuicSession::OnCryptoHandshakeMessageReceived(
1396 const CryptoHandshakeMessage& /*message*/) {}
1397
fayang476683a2019-07-25 12:42:16 -07001398void QuicSession::RegisterStreamPriority(
1399 QuicStreamId id,
1400 bool is_static,
1401 const spdy::SpdyStreamPrecedence& precedence) {
fayang1b11b962019-09-16 14:01:48 -07001402 if (enable_round_robin_scheduling_) {
1403 // Ignore provided precedence, instead, put all streams at the same priority
1404 // bucket.
1405 write_blocked_streams()->RegisterStream(
1406 id, is_static, spdy::SpdyStreamPrecedence(spdy::kV3LowestPriority));
1407 return;
1408 }
fayang476683a2019-07-25 12:42:16 -07001409 write_blocked_streams()->RegisterStream(id, is_static, precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001410}
1411
1412void QuicSession::UnregisterStreamPriority(QuicStreamId id, bool is_static) {
1413 write_blocked_streams()->UnregisterStream(id, is_static);
1414}
1415
fayang476683a2019-07-25 12:42:16 -07001416void QuicSession::UpdateStreamPriority(
1417 QuicStreamId id,
1418 const spdy::SpdyStreamPrecedence& new_precedence) {
fayang1b11b962019-09-16 14:01:48 -07001419 if (enable_round_robin_scheduling_) {
1420 // Ignore updated precedence.
1421 return;
1422 }
fayang476683a2019-07-25 12:42:16 -07001423 write_blocked_streams()->UpdateStreamPriority(id, new_precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001424}
1425
1426QuicConfig* QuicSession::config() {
1427 return &config_;
1428}
1429
1430void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
1431 QuicStreamId stream_id = stream->id();
renjietang5c729f02019-09-06 12:43:48 -07001432 bool is_static = stream->is_static();
renjietang55d182a2019-07-12 10:26:25 -07001433 QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
QUICHE teama6ef0a62019-03-07 20:34:33 -05001434 << ". activating " << stream_id;
renjietang55d182a2019-07-12 10:26:25 -07001435 DCHECK(!QuicContainsKey(stream_map_, stream_id));
1436 stream_map_[stream_id] = std::move(stream);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001437 if (IsIncomingStream(stream_id)) {
renjietang5c729f02019-09-06 12:43:48 -07001438 is_static ? ++num_incoming_static_streams_
1439 : ++num_dynamic_incoming_streams_;
1440 } else if (is_static) {
1441 ++num_outgoing_static_streams_;
1442 }
1443
1444 if (VersionHasIetfQuicFrames(transport_version()) &&
1445 !QuicUtils::IsBidirectionalStreamId(stream_id) && is_static) {
1446 DCHECK_LE(num_incoming_static_streams_,
1447 num_expected_unidirectional_static_streams_);
1448 DCHECK_LE(num_outgoing_static_streams_,
1449 num_expected_unidirectional_static_streams_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001450 }
1451}
1452
1453QuicStreamId QuicSession::GetNextOutgoingBidirectionalStreamId() {
renjietangd1d00852019-09-06 10:43:12 -07001454 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001455 return v99_streamid_manager_.GetNextOutgoingBidirectionalStreamId();
1456 }
1457 return stream_id_manager_.GetNextOutgoingStreamId();
1458}
1459
1460QuicStreamId QuicSession::GetNextOutgoingUnidirectionalStreamId() {
renjietangd1d00852019-09-06 10:43:12 -07001461 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001462 return v99_streamid_manager_.GetNextOutgoingUnidirectionalStreamId();
1463 }
1464 return stream_id_manager_.GetNextOutgoingStreamId();
1465}
1466
1467bool QuicSession::CanOpenNextOutgoingBidirectionalStream() {
renjietangd1d00852019-09-06 10:43:12 -07001468 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001469 return v99_streamid_manager_.CanOpenNextOutgoingBidirectionalStream();
1470 }
1471 return stream_id_manager_.CanOpenNextOutgoingStream(
1472 GetNumOpenOutgoingStreams());
1473}
1474
1475bool QuicSession::CanOpenNextOutgoingUnidirectionalStream() {
renjietangd1d00852019-09-06 10:43:12 -07001476 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001477 return v99_streamid_manager_.CanOpenNextOutgoingUnidirectionalStream();
1478 }
1479 return stream_id_manager_.CanOpenNextOutgoingStream(
1480 GetNumOpenOutgoingStreams());
1481}
1482
bnc41c19ca2020-01-21 18:55:26 -08001483QuicStreamCount QuicSession::GetAdvertisedMaxIncomingBidirectionalStreams()
1484 const {
1485 DCHECK(VersionHasIetfQuicFrames(transport_version()));
1486 return v99_streamid_manager_.advertised_max_incoming_bidirectional_streams();
1487}
1488
QUICHE teama6ef0a62019-03-07 20:34:33 -05001489QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
renjietang28c04b72019-07-01 15:08:09 -07001490 DCHECK(!QuicContainsKey(pending_stream_map_, stream_id));
renjietangd1d00852019-09-06 10:43:12 -07001491 if (QuicUtils::IsCryptoStreamId(transport_version(), stream_id)) {
renjietang2c4d7122019-05-20 17:18:14 -07001492 return GetMutableCryptoStream();
renjietang08a9cf72019-04-23 17:01:34 -07001493 }
renjietang880d2432019-07-16 13:14:37 -07001494
1495 StreamMap::iterator it = stream_map_.find(stream_id);
1496 if (it != stream_map_.end()) {
1497 return it->second.get();
1498 }
1499
1500 if (IsClosedStream(stream_id)) {
1501 return nullptr;
1502 }
1503
1504 if (!IsIncomingStream(stream_id)) {
1505 HandleFrameOnNonexistentOutgoingStream(stream_id);
1506 return nullptr;
1507 }
1508
1509 // TODO(fkastenholz): If we are creating a new stream and we have
1510 // sent a goaway, we should ignore the stream creation. Need to
1511 // add code to A) test if goaway was sent ("if (goaway_sent_)") and
1512 // B) reject stream creation ("return nullptr")
1513
1514 if (!MaybeIncreaseLargestPeerStreamId(stream_id)) {
1515 return nullptr;
1516 }
1517
renjietangd1d00852019-09-06 10:43:12 -07001518 if (!VersionHasIetfQuicFrames(transport_version())) {
renjietang880d2432019-07-16 13:14:37 -07001519 // TODO(fayang): Let LegacyQuicStreamIdManager count open streams and make
1520 // CanOpenIncomingStream interface consistent with that of v99.
1521 if (!stream_id_manager_.CanOpenIncomingStream(
1522 GetNumOpenIncomingStreams())) {
1523 // Refuse to open the stream.
1524 SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0);
1525 return nullptr;
1526 }
1527 }
1528
1529 return CreateIncomingStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001530}
1531
1532void QuicSession::StreamDraining(QuicStreamId stream_id) {
renjietang55d182a2019-07-12 10:26:25 -07001533 DCHECK(QuicContainsKey(stream_map_, stream_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001534 if (!QuicContainsKey(draining_streams_, stream_id)) {
1535 draining_streams_.insert(stream_id);
1536 if (IsIncomingStream(stream_id)) {
1537 ++num_draining_incoming_streams_;
1538 }
renjietangd1d00852019-09-06 10:43:12 -07001539 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001540 v99_streamid_manager_.OnStreamClosed(stream_id);
1541 }
1542 }
1543 if (!IsIncomingStream(stream_id)) {
1544 // Inform application that a stream is available.
renjietangd1d00852019-09-06 10:43:12 -07001545 if (VersionHasIetfQuicFrames(transport_version())) {
renjietangde12d3d2019-07-19 10:57:42 -07001546 OnCanCreateNewOutgoingStream(
1547 !QuicUtils::IsBidirectionalStreamId(stream_id));
fkastenholz8556dc22019-07-18 12:42:38 -07001548 } else {
renjietangde12d3d2019-07-19 10:57:42 -07001549 QuicStream* stream = GetStream(stream_id);
1550 if (!stream) {
1551 QUIC_BUG << "Stream doesn't exist when draining.";
1552 return;
1553 }
1554 OnCanCreateNewOutgoingStream(stream->type() != BIDIRECTIONAL);
fkastenholz8556dc22019-07-18 12:42:38 -07001555 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001556 }
1557}
1558
1559bool QuicSession::MaybeIncreaseLargestPeerStreamId(
1560 const QuicStreamId stream_id) {
renjietangd1d00852019-09-06 10:43:12 -07001561 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001562 return v99_streamid_manager_.MaybeIncreaseLargestPeerStreamId(stream_id);
1563 }
ianswettc1f530d2019-12-10 05:14:30 -08001564 if (!stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id)) {
1565 connection()->CloseConnection(
1566 QUIC_TOO_MANY_AVAILABLE_STREAMS,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001567 quiche::QuicheStrCat(stream_id, " exceeds available streams ",
1568 stream_id_manager_.MaxAvailableStreams()),
ianswettc1f530d2019-12-10 05:14:30 -08001569 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1570 return false;
1571 }
1572 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001573}
1574
1575bool QuicSession::ShouldYield(QuicStreamId stream_id) {
1576 if (stream_id == currently_writing_stream_id_) {
1577 return false;
1578 }
1579 return write_blocked_streams()->ShouldYield(stream_id);
1580}
1581
renjietange76b2da2019-05-13 14:50:23 -07001582PendingStream* QuicSession::GetOrCreatePendingStream(QuicStreamId stream_id) {
1583 auto it = pending_stream_map_.find(stream_id);
1584 if (it != pending_stream_map_.end()) {
1585 return it->second.get();
1586 }
1587
1588 if (IsClosedStream(stream_id) ||
1589 !MaybeIncreaseLargestPeerStreamId(stream_id)) {
1590 return nullptr;
1591 }
1592
vasilvv0fc587f2019-09-06 13:33:08 -07001593 auto pending = std::make_unique<PendingStream>(stream_id, this);
renjietange76b2da2019-05-13 14:50:23 -07001594 PendingStream* unowned_pending = pending.get();
1595 pending_stream_map_[stream_id] = std::move(pending);
1596 return unowned_pending;
1597}
1598
QUICHE teama6ef0a62019-03-07 20:34:33 -05001599void QuicSession::set_largest_peer_created_stream_id(
1600 QuicStreamId largest_peer_created_stream_id) {
renjietangd1d00852019-09-06 10:43:12 -07001601 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001602 v99_streamid_manager_.SetLargestPeerCreatedStreamId(
1603 largest_peer_created_stream_id);
1604 return;
1605 }
1606 stream_id_manager_.set_largest_peer_created_stream_id(
1607 largest_peer_created_stream_id);
1608}
1609
renjietang686ce582019-10-17 14:28:16 -07001610QuicStreamId QuicSession::GetLargestPeerCreatedStreamId(
1611 bool unidirectional) const {
1612 // This method is only used in IETF QUIC.
1613 DCHECK(VersionHasIetfQuicFrames(transport_version()));
1614 return v99_streamid_manager_.GetLargestPeerCreatedStreamId(unidirectional);
1615}
1616
ianswett6aefa0b2019-12-10 07:26:15 -08001617void QuicSession::DeleteConnection() {
1618 if (connection_) {
1619 delete connection_;
1620 connection_ = nullptr;
1621 }
1622}
1623
bncb4e7b992020-01-21 18:36:14 -08001624bool QuicSession::MaybeSetStreamPriority(
1625 QuicStreamId stream_id,
1626 const spdy::SpdyStreamPrecedence& precedence) {
1627 auto active_stream = stream_map_.find(stream_id);
1628 if (active_stream != stream_map_.end()) {
1629 active_stream->second->SetPriority(precedence);
1630 return true;
1631 }
1632
1633 return false;
1634}
1635
QUICHE teama6ef0a62019-03-07 20:34:33 -05001636bool QuicSession::IsClosedStream(QuicStreamId id) {
renjietangd1d00852019-09-06 10:43:12 -07001637 DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001638 if (IsOpenStream(id)) {
1639 // Stream is active
1640 return false;
1641 }
1642
renjietangd1d00852019-09-06 10:43:12 -07001643 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001644 return !v99_streamid_manager_.IsAvailableStream(id);
1645 }
1646
1647 return !stream_id_manager_.IsAvailableStream(id);
1648}
1649
1650bool QuicSession::IsOpenStream(QuicStreamId id) {
renjietangd1d00852019-09-06 10:43:12 -07001651 DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
renjietang55d182a2019-07-12 10:26:25 -07001652 if (QuicContainsKey(stream_map_, id) ||
renjietang08a9cf72019-04-23 17:01:34 -07001653 QuicContainsKey(pending_stream_map_, id) ||
renjietangd1d00852019-09-06 10:43:12 -07001654 QuicUtils::IsCryptoStreamId(transport_version(), id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001655 // Stream is active
1656 return true;
1657 }
1658 return false;
1659}
1660
rchda26cdb2019-05-17 11:57:37 -07001661bool QuicSession::IsStaticStream(QuicStreamId id) const {
renjietang55d182a2019-07-12 10:26:25 -07001662 auto it = stream_map_.find(id);
1663 if (it == stream_map_.end()) {
renjietangb663b862019-07-08 16:02:39 -07001664 return false;
rchda26cdb2019-05-17 11:57:37 -07001665 }
renjietangb663b862019-07-08 16:02:39 -07001666 return it->second->is_static();
rchda26cdb2019-05-17 11:57:37 -07001667}
1668
QUICHE teama6ef0a62019-03-07 20:34:33 -05001669size_t QuicSession::GetNumOpenIncomingStreams() const {
1670 return num_dynamic_incoming_streams_ - num_draining_incoming_streams_ +
1671 num_locally_closed_incoming_streams_highest_offset_;
1672}
1673
1674size_t QuicSession::GetNumOpenOutgoingStreams() const {
1675 DCHECK_GE(GetNumDynamicOutgoingStreams() +
1676 GetNumLocallyClosedOutgoingStreamsHighestOffset(),
1677 GetNumDrainingOutgoingStreams());
1678 return GetNumDynamicOutgoingStreams() +
1679 GetNumLocallyClosedOutgoingStreamsHighestOffset() -
1680 GetNumDrainingOutgoingStreams();
1681}
1682
1683size_t QuicSession::GetNumActiveStreams() const {
renjietang55d182a2019-07-12 10:26:25 -07001684 return stream_map_.size() - draining_streams_.size() -
renjietangfbeb5bf2019-04-19 15:06:20 -07001685 num_incoming_static_streams_ - num_outgoing_static_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001686}
1687
1688size_t QuicSession::GetNumDrainingStreams() const {
1689 return draining_streams_.size();
1690}
1691
1692void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id) {
1693 if (GetOrCreateStream(id) == nullptr) {
1694 QUIC_BUG << "Marking unknown stream " << id << " blocked.";
1695 QUIC_LOG_FIRST_N(ERROR, 2) << QuicStackTrace();
1696 }
1697
dschinazi88bd5b02019-10-10 00:52:20 -07001698 QUIC_DVLOG(1) << ENDPOINT << "Adding stream " << id
1699 << " to write-blocked list";
1700
QUICHE teama6ef0a62019-03-07 20:34:33 -05001701 write_blocked_streams_.AddStream(id);
1702}
1703
1704bool QuicSession::HasDataToWrite() const {
1705 return write_blocked_streams_.HasWriteBlockedSpecialStream() ||
1706 write_blocked_streams_.HasWriteBlockedDataStreams() ||
1707 connection_->HasQueuedData() ||
1708 !streams_with_pending_retransmission_.empty() ||
1709 control_frame_manager_.WillingToWrite();
1710}
1711
1712void QuicSession::OnAckNeedsRetransmittableFrame() {
1713 flow_controller_.SendWindowUpdate();
1714}
1715
1716void QuicSession::SendPing() {
1717 control_frame_manager_.WritePing();
1718}
1719
1720size_t QuicSession::GetNumDynamicOutgoingStreams() const {
renjietang55d182a2019-07-12 10:26:25 -07001721 DCHECK_GE(
1722 static_cast<size_t>(stream_map_.size() + pending_stream_map_.size()),
1723 num_dynamic_incoming_streams_ + num_outgoing_static_streams_ +
1724 num_incoming_static_streams_);
1725 return stream_map_.size() + pending_stream_map_.size() -
renjietangfbeb5bf2019-04-19 15:06:20 -07001726 num_dynamic_incoming_streams_ - num_outgoing_static_streams_ -
1727 num_incoming_static_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001728}
1729
1730size_t QuicSession::GetNumDrainingOutgoingStreams() const {
1731 DCHECK_GE(draining_streams_.size(), num_draining_incoming_streams_);
1732 return draining_streams_.size() - num_draining_incoming_streams_;
1733}
1734
1735size_t QuicSession::GetNumLocallyClosedOutgoingStreamsHighestOffset() const {
1736 DCHECK_GE(locally_closed_streams_highest_offset_.size(),
1737 num_locally_closed_incoming_streams_highest_offset_);
1738 return locally_closed_streams_highest_offset_.size() -
1739 num_locally_closed_incoming_streams_highest_offset_;
1740}
1741
1742bool QuicSession::IsConnectionFlowControlBlocked() const {
1743 return flow_controller_.IsBlocked();
1744}
1745
1746bool QuicSession::IsStreamFlowControlBlocked() {
renjietang55d182a2019-07-12 10:26:25 -07001747 for (auto const& kv : stream_map_) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001748 if (kv.second->flow_controller()->IsBlocked()) {
1749 return true;
1750 }
1751 }
renjietangd1d00852019-09-06 10:43:12 -07001752 if (!QuicVersionUsesCryptoFrames(transport_version()) &&
renjietang08a9cf72019-04-23 17:01:34 -07001753 GetMutableCryptoStream()->flow_controller()->IsBlocked()) {
renjietang08a9cf72019-04-23 17:01:34 -07001754 return true;
1755 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001756 return false;
1757}
1758
1759size_t QuicSession::MaxAvailableBidirectionalStreams() const {
renjietangd1d00852019-09-06 10:43:12 -07001760 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001761 return v99_streamid_manager_.GetMaxAllowdIncomingBidirectionalStreams();
1762 }
1763 return stream_id_manager_.MaxAvailableStreams();
1764}
1765
1766size_t QuicSession::MaxAvailableUnidirectionalStreams() const {
renjietangd1d00852019-09-06 10:43:12 -07001767 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001768 return v99_streamid_manager_.GetMaxAllowdIncomingUnidirectionalStreams();
1769 }
1770 return stream_id_manager_.MaxAvailableStreams();
1771}
1772
1773bool QuicSession::IsIncomingStream(QuicStreamId id) const {
renjietangd1d00852019-09-06 10:43:12 -07001774 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001775 return v99_streamid_manager_.IsIncomingStream(id);
1776 }
1777 return stream_id_manager_.IsIncomingStream(id);
1778}
1779
1780void QuicSession::OnStreamDoneWaitingForAcks(QuicStreamId id) {
fayangcff885a2019-10-22 07:39:04 -07001781 streams_waiting_for_acks_.erase(id);
zhongyi1b2f7832019-06-14 13:31:34 -07001782
QUICHE teama6ef0a62019-03-07 20:34:33 -05001783 auto it = zombie_streams_.find(id);
1784 if (it == zombie_streams_.end()) {
1785 return;
1786 }
1787
1788 closed_streams_.push_back(std::move(it->second));
1789 if (!closed_streams_clean_up_alarm_->IsSet()) {
1790 closed_streams_clean_up_alarm_->Set(connection_->clock()->ApproximateNow());
1791 }
1792 zombie_streams_.erase(it);
1793 // Do not retransmit data of a closed stream.
1794 streams_with_pending_retransmission_.erase(id);
1795}
1796
zhongyi1b2f7832019-06-14 13:31:34 -07001797void QuicSession::OnStreamWaitingForAcks(QuicStreamId id) {
zhongyi1b2f7832019-06-14 13:31:34 -07001798 // Exclude crypto stream's status since it is counted in HasUnackedCryptoData.
1799 if (GetCryptoStream() != nullptr && id == GetCryptoStream()->id()) {
1800 return;
1801 }
1802
zhongyi1b2f7832019-06-14 13:31:34 -07001803 streams_waiting_for_acks_.insert(id);
1804
1805 // The number of the streams waiting for acks should not be larger than the
1806 // number of streams.
renjietang55d182a2019-07-12 10:26:25 -07001807 if (static_cast<size_t>(stream_map_.size() + zombie_streams_.size()) <
zhongyi71e9d9e2019-06-14 14:57:16 -07001808 streams_waiting_for_acks_.size()) {
zhongyi1b2f7832019-06-14 13:31:34 -07001809 QUIC_BUG << "More streams are waiting for acks than the number of streams. "
renjietang55d182a2019-07-12 10:26:25 -07001810 << "Sizes: streams: " << stream_map_.size()
zhongyi1b2f7832019-06-14 13:31:34 -07001811 << ", zombie streams: " << zombie_streams_.size()
1812 << ", vs streams waiting for acks: "
1813 << streams_waiting_for_acks_.size();
1814 }
1815}
1816
QUICHE teama6ef0a62019-03-07 20:34:33 -05001817QuicStream* QuicSession::GetStream(QuicStreamId id) const {
renjietang55d182a2019-07-12 10:26:25 -07001818 auto active_stream = stream_map_.find(id);
1819 if (active_stream != stream_map_.end()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001820 return active_stream->second.get();
1821 }
1822 auto zombie_stream = zombie_streams_.find(id);
1823 if (zombie_stream != zombie_streams_.end()) {
1824 return zombie_stream->second.get();
1825 }
renjietang08a9cf72019-04-23 17:01:34 -07001826
renjietangd1d00852019-09-06 10:43:12 -07001827 if (QuicUtils::IsCryptoStreamId(transport_version(), id)) {
renjietang08a9cf72019-04-23 17:01:34 -07001828 return const_cast<QuicCryptoStream*>(GetCryptoStream());
1829 }
1830
QUICHE teama6ef0a62019-03-07 20:34:33 -05001831 return nullptr;
1832}
1833
1834bool QuicSession::OnFrameAcked(const QuicFrame& frame,
QUICHE team9467db02019-05-30 09:38:45 -07001835 QuicTime::Delta ack_delay_time,
1836 QuicTime receive_timestamp) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001837 if (frame.type == MESSAGE_FRAME) {
QUICHE team9467db02019-05-30 09:38:45 -07001838 OnMessageAcked(frame.message_frame->message_id, receive_timestamp);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001839 return true;
1840 }
1841 if (frame.type == CRYPTO_FRAME) {
1842 return GetMutableCryptoStream()->OnCryptoFrameAcked(*frame.crypto_frame,
1843 ack_delay_time);
1844 }
1845 if (frame.type != STREAM_FRAME) {
1846 return control_frame_manager_.OnControlFrameAcked(frame);
1847 }
1848 bool new_stream_data_acked = false;
1849 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
1850 // Stream can already be reset when sent frame gets acked.
1851 if (stream != nullptr) {
1852 QuicByteCount newly_acked_length = 0;
1853 new_stream_data_acked = stream->OnStreamFrameAcked(
1854 frame.stream_frame.offset, frame.stream_frame.data_length,
1855 frame.stream_frame.fin, ack_delay_time, &newly_acked_length);
1856 if (!stream->HasPendingRetransmission()) {
1857 streams_with_pending_retransmission_.erase(stream->id());
1858 }
1859 }
1860 return new_stream_data_acked;
1861}
1862
1863void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
1864 QuicStream* stream = GetStream(frame.stream_id);
1865 if (stream == nullptr) {
1866 QUIC_BUG << "Stream: " << frame.stream_id << " is closed when " << frame
1867 << " is retransmitted.";
1868 connection()->CloseConnection(
1869 QUIC_INTERNAL_ERROR, "Attempt to retransmit frame of a closed stream",
1870 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1871 return;
1872 }
1873 stream->OnStreamFrameRetransmitted(frame.offset, frame.data_length,
1874 frame.fin);
1875}
1876
1877void QuicSession::OnFrameLost(const QuicFrame& frame) {
1878 if (frame.type == MESSAGE_FRAME) {
1879 OnMessageLost(frame.message_frame->message_id);
1880 return;
1881 }
1882 if (frame.type == CRYPTO_FRAME) {
1883 GetMutableCryptoStream()->OnCryptoFrameLost(frame.crypto_frame);
1884 return;
1885 }
1886 if (frame.type != STREAM_FRAME) {
1887 control_frame_manager_.OnControlFrameLost(frame);
1888 return;
1889 }
1890 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
1891 if (stream == nullptr) {
1892 return;
1893 }
1894 stream->OnStreamFrameLost(frame.stream_frame.offset,
1895 frame.stream_frame.data_length,
1896 frame.stream_frame.fin);
1897 if (stream->HasPendingRetransmission() &&
1898 !QuicContainsKey(streams_with_pending_retransmission_,
1899 frame.stream_frame.stream_id)) {
1900 streams_with_pending_retransmission_.insert(
1901 std::make_pair(frame.stream_frame.stream_id, true));
1902 }
1903}
1904
1905void QuicSession::RetransmitFrames(const QuicFrames& frames,
1906 TransmissionType type) {
fayanga4b37b22019-06-18 13:37:47 -07001907 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001908 SetTransmissionType(type);
1909 for (const QuicFrame& frame : frames) {
1910 if (frame.type == MESSAGE_FRAME) {
1911 // Do not retransmit MESSAGE frames.
1912 continue;
1913 }
1914 if (frame.type == CRYPTO_FRAME) {
1915 GetMutableCryptoStream()->RetransmitData(frame.crypto_frame);
1916 continue;
1917 }
1918 if (frame.type != STREAM_FRAME) {
1919 if (!control_frame_manager_.RetransmitControlFrame(frame)) {
1920 break;
1921 }
1922 continue;
1923 }
1924 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
1925 if (stream != nullptr &&
1926 !stream->RetransmitStreamData(frame.stream_frame.offset,
1927 frame.stream_frame.data_length,
1928 frame.stream_frame.fin)) {
1929 break;
1930 }
1931 }
1932}
1933
1934bool QuicSession::IsFrameOutstanding(const QuicFrame& frame) const {
1935 if (frame.type == MESSAGE_FRAME) {
1936 return false;
1937 }
1938 if (frame.type == CRYPTO_FRAME) {
1939 return GetCryptoStream()->IsFrameOutstanding(
1940 frame.crypto_frame->level, frame.crypto_frame->offset,
1941 frame.crypto_frame->data_length);
1942 }
1943 if (frame.type != STREAM_FRAME) {
1944 return control_frame_manager_.IsControlFrameOutstanding(frame);
1945 }
1946 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
1947 return stream != nullptr &&
1948 stream->IsStreamFrameOutstanding(frame.stream_frame.offset,
1949 frame.stream_frame.data_length,
1950 frame.stream_frame.fin);
1951}
1952
1953bool QuicSession::HasUnackedCryptoData() const {
1954 const QuicCryptoStream* crypto_stream = GetCryptoStream();
fayang44fa92f2019-07-01 07:32:14 -07001955 return crypto_stream->IsWaitingForAcks() || crypto_stream->HasBufferedData();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001956}
1957
zhongyi1b2f7832019-06-14 13:31:34 -07001958bool QuicSession::HasUnackedStreamData() const {
zhongyi9fa2be32019-09-10 12:39:01 -07001959 return !streams_waiting_for_acks_.empty();
zhongyi1b2f7832019-06-14 13:31:34 -07001960}
1961
fayang9a863cf2020-01-16 14:12:11 -08001962HandshakeState QuicSession::GetHandshakeState() const {
1963 return GetCryptoStream()->GetHandshakeState();
1964}
1965
QUICHE teama6ef0a62019-03-07 20:34:33 -05001966WriteStreamDataResult QuicSession::WriteStreamData(QuicStreamId id,
1967 QuicStreamOffset offset,
1968 QuicByteCount data_length,
1969 QuicDataWriter* writer) {
1970 QuicStream* stream = GetStream(id);
1971 if (stream == nullptr) {
1972 // This causes the connection to be closed because of failed to serialize
1973 // packet.
ianswetteb101f82019-04-04 09:13:24 -07001974 QUIC_BUG << "Stream " << id << " does not exist when trying to write data."
renjietangd1d00852019-09-06 10:43:12 -07001975 << " version:" << transport_version();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001976 return STREAM_MISSING;
1977 }
1978 if (stream->WriteStreamData(offset, data_length, writer)) {
1979 return WRITE_SUCCESS;
1980 }
1981 return WRITE_FAILED;
1982}
1983
1984bool QuicSession::WriteCryptoData(EncryptionLevel level,
1985 QuicStreamOffset offset,
1986 QuicByteCount data_length,
1987 QuicDataWriter* writer) {
1988 return GetMutableCryptoStream()->WriteCryptoFrame(level, offset, data_length,
1989 writer);
1990}
1991
1992QuicUint128 QuicSession::GetStatelessResetToken() const {
1993 return QuicUtils::GenerateStatelessResetToken(connection_->connection_id());
1994}
1995
1996bool QuicSession::RetransmitLostData() {
fayanga4b37b22019-06-18 13:37:47 -07001997 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001998 // Retransmit crypto data first.
renjietangd1d00852019-09-06 10:43:12 -07001999 bool uses_crypto_frames = QuicVersionUsesCryptoFrames(transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002000 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
2001 if (uses_crypto_frames && crypto_stream->HasPendingCryptoRetransmission()) {
2002 SetTransmissionType(HANDSHAKE_RETRANSMISSION);
2003 crypto_stream->WritePendingCryptoRetransmission();
2004 }
2005 // Retransmit crypto data in stream 1 frames (version < 47).
2006 if (!uses_crypto_frames &&
renjietangd1d00852019-09-06 10:43:12 -07002007 QuicContainsKey(streams_with_pending_retransmission_,
2008 QuicUtils::GetCryptoStreamId(transport_version()))) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002009 SetTransmissionType(HANDSHAKE_RETRANSMISSION);
2010 // Retransmit crypto data first.
renjietangd1d00852019-09-06 10:43:12 -07002011 QuicStream* crypto_stream =
2012 GetStream(QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002013 crypto_stream->OnCanWrite();
2014 DCHECK(CheckStreamWriteBlocked(crypto_stream));
2015 if (crypto_stream->HasPendingRetransmission()) {
2016 // Connection is write blocked.
2017 return false;
2018 } else {
2019 streams_with_pending_retransmission_.erase(
renjietangd1d00852019-09-06 10:43:12 -07002020 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002021 }
2022 }
2023 if (control_frame_manager_.HasPendingRetransmission()) {
2024 SetTransmissionType(LOSS_RETRANSMISSION);
2025 control_frame_manager_.OnCanWrite();
2026 if (control_frame_manager_.HasPendingRetransmission()) {
2027 return false;
2028 }
2029 }
2030 while (!streams_with_pending_retransmission_.empty()) {
2031 if (!connection_->CanWriteStreamData()) {
2032 break;
2033 }
2034 // Retransmit lost data on headers and data streams.
2035 const QuicStreamId id = streams_with_pending_retransmission_.begin()->first;
2036 QuicStream* stream = GetStream(id);
2037 if (stream != nullptr) {
2038 SetTransmissionType(LOSS_RETRANSMISSION);
2039 stream->OnCanWrite();
2040 DCHECK(CheckStreamWriteBlocked(stream));
2041 if (stream->HasPendingRetransmission()) {
2042 // Connection is write blocked.
2043 break;
2044 } else if (!streams_with_pending_retransmission_.empty() &&
2045 streams_with_pending_retransmission_.begin()->first == id) {
2046 // Retransmit lost data may cause connection close. If this stream
2047 // has not yet sent fin, a RST_STREAM will be sent and it will be
2048 // removed from streams_with_pending_retransmission_.
2049 streams_with_pending_retransmission_.pop_front();
2050 }
2051 } else {
2052 QUIC_BUG << "Try to retransmit data of a closed stream";
2053 streams_with_pending_retransmission_.pop_front();
2054 }
2055 }
2056
2057 return streams_with_pending_retransmission_.empty();
2058}
2059
2060void QuicSession::NeuterUnencryptedData() {
fayangcff885a2019-10-22 07:39:04 -07002061 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
2062 crypto_stream->NeuterUnencryptedStreamData();
2063 if (!crypto_stream->HasPendingRetransmission() &&
2064 !QuicVersionUsesCryptoFrames(transport_version())) {
2065 streams_with_pending_retransmission_.erase(
2066 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002067 }
2068 connection_->NeuterUnencryptedPackets();
2069}
2070
2071void QuicSession::SetTransmissionType(TransmissionType type) {
2072 connection_->SetTransmissionType(type);
2073}
2074
2075MessageResult QuicSession::SendMessage(QuicMemSliceSpan message) {
QUICHE team350e9e62019-11-19 13:16:24 -08002076 return SendMessage(message, /*flush=*/false);
2077}
2078
2079MessageResult QuicSession::SendMessage(QuicMemSliceSpan message, bool flush) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002080 if (!IsEncryptionEstablished()) {
2081 return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
2082 }
2083 MessageStatus result =
QUICHE team350e9e62019-11-19 13:16:24 -08002084 connection_->SendMessage(last_message_id_ + 1, message, flush);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002085 if (result == MESSAGE_STATUS_SUCCESS) {
2086 return {result, ++last_message_id_};
2087 }
2088 return {result, 0};
2089}
2090
QUICHE team9467db02019-05-30 09:38:45 -07002091void QuicSession::OnMessageAcked(QuicMessageId message_id,
dschinazi17d42422019-06-18 16:35:07 -07002092 QuicTime /*receive_timestamp*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002093 QUIC_DVLOG(1) << ENDPOINT << "message " << message_id << " gets acked.";
2094}
2095
2096void QuicSession::OnMessageLost(QuicMessageId message_id) {
2097 QUIC_DVLOG(1) << ENDPOINT << "message " << message_id
2098 << " is considered lost";
2099}
2100
2101void QuicSession::CleanUpClosedStreams() {
2102 closed_streams_.clear();
2103}
2104
ianswettb239f862019-04-05 09:15:06 -07002105QuicPacketLength QuicSession::GetCurrentLargestMessagePayload() const {
2106 return connection_->GetCurrentLargestMessagePayload();
2107}
2108
2109QuicPacketLength QuicSession::GetGuaranteedLargestMessagePayload() const {
2110 return connection_->GetGuaranteedLargestMessagePayload();
QUICHE teama6ef0a62019-03-07 20:34:33 -05002111}
2112
2113void QuicSession::SendStopSending(uint16_t code, QuicStreamId stream_id) {
2114 control_frame_manager_.WriteOrBufferStopSending(code, stream_id);
2115}
2116
fkastenholz8556dc22019-07-18 12:42:38 -07002117void QuicSession::OnCanCreateNewOutgoingStream(bool /*unidirectional*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05002118
2119QuicStreamId QuicSession::next_outgoing_bidirectional_stream_id() const {
renjietangd1d00852019-09-06 10:43:12 -07002120 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002121 return v99_streamid_manager_.next_outgoing_bidirectional_stream_id();
2122 }
2123 return stream_id_manager_.next_outgoing_stream_id();
2124}
2125
2126QuicStreamId QuicSession::next_outgoing_unidirectional_stream_id() const {
renjietangd1d00852019-09-06 10:43:12 -07002127 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002128 return v99_streamid_manager_.next_outgoing_unidirectional_stream_id();
2129 }
2130 return stream_id_manager_.next_outgoing_stream_id();
2131}
2132
fkastenholz3c4eabf2019-04-22 07:49:59 -07002133bool QuicSession::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
2134 return v99_streamid_manager_.OnMaxStreamsFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002135}
2136
fkastenholz3c4eabf2019-04-22 07:49:59 -07002137bool QuicSession::OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) {
2138 return v99_streamid_manager_.OnStreamsBlockedFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002139}
2140
2141size_t QuicSession::max_open_incoming_bidirectional_streams() const {
renjietangd1d00852019-09-06 10:43:12 -07002142 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002143 return v99_streamid_manager_.GetMaxAllowdIncomingBidirectionalStreams();
2144 }
2145 return stream_id_manager_.max_open_incoming_streams();
2146}
2147
2148size_t QuicSession::max_open_incoming_unidirectional_streams() const {
renjietangd1d00852019-09-06 10:43:12 -07002149 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002150 return v99_streamid_manager_.GetMaxAllowdIncomingUnidirectionalStreams();
2151 }
2152 return stream_id_manager_.max_open_incoming_streams();
2153}
2154
dmcardlecf0bfcf2019-12-13 08:08:21 -08002155std::vector<quiche::QuicheStringPiece>::const_iterator QuicSession::SelectAlpn(
2156 const std::vector<quiche::QuicheStringPiece>& alpns) const {
vasilvvad7424f2019-08-30 00:27:14 -07002157 const std::string alpn = AlpnForVersion(connection()->version());
2158 return std::find(alpns.cbegin(), alpns.cend(), alpn);
2159}
2160
dmcardlecf0bfcf2019-12-13 08:08:21 -08002161void QuicSession::OnAlpnSelected(quiche::QuicheStringPiece alpn) {
vasilvvad7424f2019-08-30 00:27:14 -07002162 QUIC_DLOG(INFO) << (perspective() == Perspective::IS_SERVER ? "Server: "
2163 : "Client: ")
2164 << "ALPN selected: " << alpn;
2165}
2166
QUICHE teama6ef0a62019-03-07 20:34:33 -05002167#undef ENDPOINT // undef for jumbo builds
2168} // namespace quic