blob: b17883c4f9fbe87d641ed0d8436da8adbc7f77d9 [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(),
renjietang162a6272020-03-26 12:57:51 -070074 config_.GetMaxUnidirectionalStreamsToSend() +
75 num_expected_unidirectional_static_streams),
fayang116fa4c2020-06-02 08:10:49 -070076 num_draining_streams_(0),
fayang8d601b12020-06-02 13:45:44 -070077 num_outgoing_draining_streams_(0),
fayang116fa4c2020-06-02 08:10:49 -070078 num_static_streams_(0),
renjietang647b3cf2020-08-04 13:23:12 -070079 num_zombie_streams_(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),
bnc3988f572020-08-27 05:27:04 -070092 transport_goaway_sent_(false),
93 transport_goaway_received_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -050094 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),
renjietangfaf8b022020-06-08 20:06:44 -0700101 enable_round_robin_scheduling_(false),
renjietang37b2e182020-06-18 16:48:08 -0700102 was_zero_rtt_rejected_(false),
renjietang4c334822020-09-28 15:44:55 -0700103 liveness_testing_in_progress_(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 }
renjietang241ba602020-04-29 13:29:46 -0700111 if (VersionHasIetfQuicFrames(transport_version())) {
112 config_.SetMaxUnidirectionalStreamsToSend(
113 config_.GetMaxUnidirectionalStreamsToSend() +
114 num_expected_unidirectional_static_streams);
115 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500116}
117
118void QuicSession::Initialize() {
119 connection_->set_visitor(this);
120 connection_->SetSessionNotifier(this);
121 connection_->SetDataProducer(this);
122 connection_->SetFromConfig(config_);
haoyuewang2d2fdd12020-09-16 11:26:56 -0700123 if (perspective_ == Perspective::IS_CLIENT &&
124 config_.HasClientRequestedIndependentOption(kAFFE, perspective_) &&
125 version().HasIetfQuicFrames()) {
126 connection_->set_can_receive_ack_frequency_frame();
127 config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs);
128 }
fayang67395d02020-08-17 09:18:27 -0700129 if (perspective() == Perspective::IS_CLIENT && version().UsesTls() &&
130 !version().HasHandshakeDone()) {
131 config_.SetSupportHandshakeDone();
fayang5c362882020-06-16 07:39:39 -0700132 }
haoyuewang7cffa542020-07-15 17:12:27 -0700133
wub256b2d62019-11-25 08:46:55 -0800134 // On the server side, version negotiation has been done by the dispatcher,
135 // and the server session is created with the right version.
wubbea386e2020-01-27 09:04:51 -0800136 if (perspective() == Perspective::IS_SERVER) {
wub256b2d62019-11-25 08:46:55 -0800137 connection_->OnSuccessfulVersionNegotiation();
138 }
139
renjietangd1d00852019-09-06 10:43:12 -0700140 if (QuicVersionUsesCryptoFrames(transport_version())) {
nharper46833c32019-05-15 21:33:05 -0700141 return;
142 }
143
renjietangd1d00852019-09-06 10:43:12 -0700144 DCHECK_EQ(QuicUtils::GetCryptoStreamId(transport_version()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 GetMutableCryptoStream()->id());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146}
147
renjietang4c334822020-09-28 15:44:55 -0700148QuicSession::~QuicSession() {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149
renjietange76b2da2019-05-13 14:50:23 -0700150void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
renjietanga29a96a2019-10-10 12:47:50 -0700151 DCHECK(VersionUsesHttp3(transport_version()));
renjietange76b2da2019-05-13 14:50:23 -0700152 QuicStreamId stream_id = frame.stream_id;
153
154 PendingStream* pending = GetOrCreatePendingStream(stream_id);
155
156 if (!pending) {
157 if (frame.fin) {
158 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
159 OnFinalByteOffsetReceived(stream_id, final_byte_offset);
160 }
161 return;
162 }
163
164 pending->OnStreamFrame(frame);
renjietanga553da02019-06-24 11:57:04 -0700165 if (!connection()->connected()) {
166 return;
167 }
renjietangbb1c4892019-05-24 15:58:44 -0700168 if (ProcessPendingStream(pending)) {
169 // The pending stream should now be in the scope of normal streams.
170 DCHECK(IsClosedStream(stream_id) || IsOpenStream(stream_id))
171 << "Stream " << stream_id << " not created";
172 pending_stream_map_.erase(stream_id);
bnc4ff60622019-08-09 18:55:45 -0700173 return;
174 }
175 if (pending->sequencer()->IsClosed()) {
176 ClosePendingStream(stream_id);
renjietangbb1c4892019-05-24 15:58:44 -0700177 }
renjietange76b2da2019-05-13 14:50:23 -0700178}
179
QUICHE teama6ef0a62019-03-07 20:34:33 -0500180void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181 QuicStreamId stream_id = frame.stream_id;
renjietangd1d00852019-09-06 10:43:12 -0700182 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183 connection()->CloseConnection(
bnce433f532019-04-16 13:05:27 -0700184 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
186 return;
187 }
188
bnc36c47282019-06-21 05:17:59 -0700189 if (UsesPendingStreams() &&
renjietange76b2da2019-05-13 14:50:23 -0700190 QuicUtils::GetStreamType(stream_id, perspective(),
renjietangd262e252020-06-19 15:11:24 -0700191 IsIncomingStream(stream_id),
192 version()) == READ_UNIDIRECTIONAL &&
renjietang55d182a2019-07-12 10:26:25 -0700193 stream_map_.find(stream_id) == stream_map_.end()) {
renjietange76b2da2019-05-13 14:50:23 -0700194 PendingStreamOnStreamFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 return;
196 }
197
renjietang2c4d7122019-05-20 17:18:14 -0700198 QuicStream* stream = GetOrCreateStream(stream_id);
renjietange76b2da2019-05-13 14:50:23 -0700199
renjietang2c4d7122019-05-20 17:18:14 -0700200 if (!stream) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500201 // The stream no longer exists, but we may still be interested in the
202 // final stream byte offset sent by the peer. A frame with a FIN can give
203 // us this offset.
204 if (frame.fin) {
205 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
206 OnFinalByteOffsetReceived(stream_id, final_byte_offset);
207 }
208 return;
209 }
renjietang2c4d7122019-05-20 17:18:14 -0700210 stream->OnStreamFrame(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500211}
212
213void QuicSession::OnCryptoFrame(const QuicCryptoFrame& frame) {
214 GetMutableCryptoStream()->OnCryptoFrame(frame);
215}
216
renjietangeab918f2019-10-28 12:10:32 -0700217void QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
218 // STOP_SENDING is in IETF QUIC only.
renjietangd1d00852019-09-06 10:43:12 -0700219 DCHECK(VersionHasIetfQuicFrames(transport_version()));
ianswett0a8ff622020-02-05 23:28:58 -0800220 DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221
222 QuicStreamId stream_id = frame.stream_id;
223 // If Stream ID is invalid then close the connection.
ianswett0a8ff622020-02-05 23:28:58 -0800224 // TODO(ianswett): This check is redundant to checks for IsClosedStream,
225 // but removing it requires removing multiple DCHECKs.
226 // TODO(ianswett): Multiple QUIC_DVLOGs could be QUIC_PEER_BUGs.
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
ianswett0a8ff622020-02-05 23:28:58 -0800237 // If stream_id is READ_UNIDIRECTIONAL, close the connection.
238 if (QuicUtils::GetStreamType(stream_id, perspective(),
renjietangd262e252020-06-19 15:11:24 -0700239 IsIncomingStream(stream_id),
240 version()) == READ_UNIDIRECTIONAL) {
ianswett0a8ff622020-02-05 23:28:58 -0800241 QUIC_DVLOG(1) << ENDPOINT
242 << "Received STOP_SENDING for a read-only stream_id: "
243 << stream_id << ".";
244 connection()->CloseConnection(
245 QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a read-only stream",
246 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
247 return;
248 }
249
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 if (visitor_) {
251 visitor_->OnStopSendingReceived(frame);
252 }
253
renjietangf0d56112020-03-09 14:05:19 -0700254 QuicStream* stream = GetOrCreateStream(stream_id);
255 if (!stream) {
256 // Errors are handled by GetOrCreateStream.
ianswett0a8ff622020-02-05 23:28:58 -0800257 return;
258 }
259
bnc187eea32020-09-02 12:16:15 -0700260 stream->OnStopSending(frame.error_code);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261}
262
fayangd58736d2019-11-27 13:35:31 -0800263void QuicSession::OnPacketDecrypted(EncryptionLevel level) {
264 GetMutableCryptoStream()->OnPacketDecrypted(level);
fayang001c8282020-07-29 12:39:29 -0700265 if (liveness_testing_in_progress_) {
266 liveness_testing_in_progress_ = false;
267 OnCanCreateNewOutgoingStream(/*unidirectional=*/false);
268 }
fayangd58736d2019-11-27 13:35:31 -0800269}
270
fayang2f2915d2020-01-24 06:47:15 -0800271void QuicSession::OnOneRttPacketAcknowledged() {
272 GetMutableCryptoStream()->OnOneRttPacketAcknowledged();
273}
274
fayang44ae4e92020-04-28 13:09:42 -0700275void QuicSession::OnHandshakePacketSent() {
276 GetMutableCryptoStream()->OnHandshakePacketSent();
277}
278
renjietange76b2da2019-05-13 14:50:23 -0700279void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
renjietanga29a96a2019-10-10 12:47:50 -0700280 DCHECK(VersionUsesHttp3(transport_version()));
renjietange76b2da2019-05-13 14:50:23 -0700281 QuicStreamId stream_id = frame.stream_id;
282
283 PendingStream* pending = GetOrCreatePendingStream(stream_id);
284
285 if (!pending) {
286 HandleRstOnValidNonexistentStream(frame);
287 return;
288 }
289
290 pending->OnRstStreamFrame(frame);
renjietang4f732482019-10-24 14:48:23 -0700291 // Pending stream is currently read only. We can safely close the stream.
292 DCHECK_EQ(READ_UNIDIRECTIONAL,
293 QuicUtils::GetStreamType(pending->id(), perspective(),
renjietangd262e252020-06-19 15:11:24 -0700294 /*peer_initiated = */ true, version()));
renjietange76b2da2019-05-13 14:50:23 -0700295 ClosePendingStream(stream_id);
296}
297
QUICHE teama6ef0a62019-03-07 20:34:33 -0500298void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
299 QuicStreamId stream_id = frame.stream_id;
renjietangd1d00852019-09-06 10:43:12 -0700300 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500301 connection()->CloseConnection(
bnce433f532019-04-16 13:05:27 -0700302 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
QUICHE teama6ef0a62019-03-07 20:34:33 -0500303 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
304 return;
305 }
306
renjietangd9762282019-11-11 17:11:18 -0800307 if (VersionHasIetfQuicFrames(transport_version()) &&
308 QuicUtils::GetStreamType(stream_id, perspective(),
renjietangd262e252020-06-19 15:11:24 -0700309 IsIncomingStream(stream_id),
310 version()) == WRITE_UNIDIRECTIONAL) {
renjietangd9762282019-11-11 17:11:18 -0800311 connection()->CloseConnection(
312 QUIC_INVALID_STREAM_ID, "Received RESET_STREAM for a write-only stream",
313 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
314 return;
315 }
316
QUICHE teama6ef0a62019-03-07 20:34:33 -0500317 if (visitor_) {
318 visitor_->OnRstStreamReceived(frame);
319 }
320
bnc36c47282019-06-21 05:17:59 -0700321 if (UsesPendingStreams() &&
renjietange76b2da2019-05-13 14:50:23 -0700322 QuicUtils::GetStreamType(stream_id, perspective(),
renjietangd262e252020-06-19 15:11:24 -0700323 IsIncomingStream(stream_id),
324 version()) == READ_UNIDIRECTIONAL &&
renjietang55d182a2019-07-12 10:26:25 -0700325 stream_map_.find(stream_id) == stream_map_.end()) {
renjietange76b2da2019-05-13 14:50:23 -0700326 PendingStreamOnRstStream(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327 return;
328 }
renjietange76b2da2019-05-13 14:50:23 -0700329
renjietang2c4d7122019-05-20 17:18:14 -0700330 QuicStream* stream = GetOrCreateStream(stream_id);
renjietange76b2da2019-05-13 14:50:23 -0700331
renjietang2c4d7122019-05-20 17:18:14 -0700332 if (!stream) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333 HandleRstOnValidNonexistentStream(frame);
334 return; // Errors are handled by GetOrCreateStream.
335 }
renjietang2c4d7122019-05-20 17:18:14 -0700336 stream->OnStreamReset(frame);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500337}
338
dschinazi17d42422019-06-18 16:35:07 -0700339void QuicSession::OnGoAway(const QuicGoAwayFrame& /*frame*/) {
renjietangcd69ce42020-08-07 16:12:04 -0700340 QUIC_BUG_IF(version().UsesHttp3())
341 << "gQUIC GOAWAY received on version " << version();
342
bnc3988f572020-08-27 05:27:04 -0700343 transport_goaway_received_ = true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500344}
345
dmcardlecf0bfcf2019-12-13 08:08:21 -0800346void QuicSession::OnMessageReceived(quiche::QuicheStringPiece message) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500347 QUIC_DVLOG(1) << ENDPOINT << "Received message, length: " << message.length()
348 << ", " << message;
349}
350
fayang01062942020-01-22 07:23:23 -0800351void QuicSession::OnHandshakeDoneReceived() {
352 QUIC_DVLOG(1) << ENDPOINT << "OnHandshakeDoneReceived";
353 GetMutableCryptoStream()->OnHandshakeDoneReceived();
354}
355
wub2b5942f2019-04-11 13:22:50 -0700356// static
357void QuicSession::RecordConnectionCloseAtServer(QuicErrorCode error,
358 ConnectionCloseSource source) {
359 if (error != QUIC_NO_ERROR) {
360 if (source == ConnectionCloseSource::FROM_SELF) {
361 QUIC_SERVER_HISTOGRAM_ENUM(
362 "quic_server_connection_close_errors", error, QUIC_LAST_ERROR,
363 "QuicErrorCode for server-closed connections.");
364 } else {
365 QUIC_SERVER_HISTOGRAM_ENUM(
366 "quic_client_connection_close_errors", error, QUIC_LAST_ERROR,
367 "QuicErrorCode for client-closed connections.");
368 }
369 }
370}
371
fkastenholz5d880a92019-06-21 09:01:56 -0700372void QuicSession::OnConnectionClosed(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500373 ConnectionCloseSource source) {
374 DCHECK(!connection_->connected());
wub2b5942f2019-04-11 13:22:50 -0700375 if (perspective() == Perspective::IS_SERVER) {
fkastenholz5d880a92019-06-21 09:01:56 -0700376 RecordConnectionCloseAtServer(frame.quic_error_code, source);
wub2b5942f2019-04-11 13:22:50 -0700377 }
378
bnc77e77b82020-04-05 10:36:49 -0700379 if (on_closed_frame_.quic_error_code == QUIC_NO_ERROR) {
fkastenholz488a4622019-08-26 06:24:46 -0700380 // Save all of the connection close information
381 on_closed_frame_ = frame;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500382 }
383
fayang6cccce42020-06-08 08:37:31 -0700384 GetMutableCryptoStream()->OnConnectionClosed(frame.quic_error_code, source);
fayanga6a85a82020-05-04 08:58:53 -0700385
renjietang0c20b032020-09-10 15:45:38 -0700386 PerformActionOnActiveStreams([this, frame, source](QuicStream* stream) {
387 QuicStreamId id = stream->id();
388 stream->OnConnectionClosed(frame.quic_error_code, source);
389 auto it = stream_map_.find(id);
390 if (it != stream_map_.end()) {
renjietang4c334822020-09-28 15:44:55 -0700391 QUIC_BUG_IF(!it->second->IsZombie())
392 << ENDPOINT << "Non-zombie stream " << id
393 << " failed to close under OnConnectionClosed";
renjietangc621aea2020-07-23 15:56:10 -0700394 }
renjietang0c20b032020-09-10 15:45:38 -0700395 return true;
396 });
QUICHE teama6ef0a62019-03-07 20:34:33 -0500397
QUICHE teama6ef0a62019-03-07 20:34:33 -0500398 closed_streams_clean_up_alarm_->Cancel();
399
400 if (visitor_) {
fkastenholz5d880a92019-06-21 09:01:56 -0700401 visitor_->OnConnectionClosed(connection_->connection_id(),
bnc77e77b82020-04-05 10:36:49 -0700402 frame.quic_error_code, frame.error_details,
403 source);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500404 }
405}
406
407void QuicSession::OnWriteBlocked() {
QUICHE teamaa1d6a82019-03-13 09:14:13 -0700408 if (!connection_->connected()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409 return;
410 }
411 if (visitor_) {
412 visitor_->OnWriteBlocked(connection_);
413 }
414}
415
416void QuicSession::OnSuccessfulVersionNegotiation(
nharper41edcde2020-02-24 15:48:10 -0800417 const ParsedQuicVersion& /*version*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500418
zhongyi83161e42019-08-19 09:06:25 -0700419void QuicSession::OnPacketReceived(const QuicSocketAddress& /*self_address*/,
420 const QuicSocketAddress& peer_address,
421 bool is_connectivity_probe) {
422 if (is_connectivity_probe && perspective() == Perspective::IS_SERVER) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500423 // Server only sends back a connectivity probe after received a
424 // connectivity probe from a new peer address.
danzh8a27a1a2020-09-02 10:26:28 -0700425 if (connection_->send_path_response()) {
426 // SendConnectivityProbingResponsePacket() will be deprecated.
427 // SendConnectivityProbingPacket() will be used to send both probing
428 // request and response as both of them are padded PING.
429 connection_->SendConnectivityProbingPacket(nullptr, peer_address);
430 } else {
431 connection_->SendConnectivityProbingResponsePacket(peer_address);
432 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500433 }
434}
435
436void QuicSession::OnPathDegrading() {}
437
zhongyief1d6752020-06-11 16:19:28 -0700438void QuicSession::OnForwardProgressMadeAfterPathDegrading() {}
439
QUICHE teama6ef0a62019-03-07 20:34:33 -0500440bool QuicSession::AllowSelfAddressChange() const {
441 return false;
442}
443
QUICHE teama6ef0a62019-03-07 20:34:33 -0500444void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
445 // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
446 // assume that it still exists.
447 QuicStreamId stream_id = frame.stream_id;
renjietangd1d00852019-09-06 10:43:12 -0700448 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500449 // This is a window update that applies to the connection, rather than an
450 // individual stream.
QUICHE team51d69992019-08-21 13:38:04 -0700451 QUIC_DVLOG(1) << ENDPOINT
452 << "Received connection level flow control window "
renjietangd088eab2019-11-21 14:54:41 -0800453 "update with max data: "
454 << frame.max_data;
455 flow_controller_.UpdateSendWindowOffset(frame.max_data);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500456 return;
457 }
renjietang28c04b72019-07-01 15:08:09 -0700458
renjietangd1d00852019-09-06 10:43:12 -0700459 if (VersionHasIetfQuicFrames(transport_version()) &&
renjietang28c04b72019-07-01 15:08:09 -0700460 QuicUtils::GetStreamType(stream_id, perspective(),
renjietangd262e252020-06-19 15:11:24 -0700461 IsIncomingStream(stream_id),
462 version()) == READ_UNIDIRECTIONAL) {
renjietang28c04b72019-07-01 15:08:09 -0700463 connection()->CloseConnection(
464 QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
465 "WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.",
466 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
467 return;
468 }
469
QUICHE teama6ef0a62019-03-07 20:34:33 -0500470 QuicStream* stream = GetOrCreateStream(stream_id);
471 if (stream != nullptr) {
472 stream->OnWindowUpdateFrame(frame);
473 }
474}
475
476void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) {
477 // TODO(rjshade): Compare our flow control receive windows for specified
478 // streams: if we have a large window then maybe something
479 // had gone wrong with the flow control accounting.
480 QUIC_DLOG(INFO) << ENDPOINT << "Received BLOCKED frame with stream id: "
481 << frame.stream_id;
482}
483
484bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream,
485 uint64_t previous_bytes_written,
486 bool previous_fin_sent) {
487 if ( // Stream should not be closed.
488 !stream->write_side_closed() &&
489 // Not connection flow control blocked.
490 !flow_controller_.IsBlocked() &&
491 // Detect lack of forward progress.
492 previous_bytes_written == stream->stream_bytes_written() &&
493 previous_fin_sent == stream->fin_sent()) {
494 stream->set_busy_counter(stream->busy_counter() + 1);
dschinazi88bd5b02019-10-10 00:52:20 -0700495 QUIC_DVLOG(1) << ENDPOINT << "Suspected busy loop on stream id "
496 << stream->id() << " stream_bytes_written "
497 << stream->stream_bytes_written() << " fin "
498 << stream->fin_sent() << " count " << stream->busy_counter();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500499 // Wait a few iterations before firing, the exact count is
500 // arbitrary, more than a few to cover a few test-only false
501 // positives.
502 if (stream->busy_counter() > 20) {
dschinazi88bd5b02019-10-10 00:52:20 -0700503 QUIC_LOG(ERROR) << ENDPOINT << "Detected busy loop on stream id "
504 << stream->id() << " stream_bytes_written "
QUICHE teama6ef0a62019-03-07 20:34:33 -0500505 << stream->stream_bytes_written() << " fin "
506 << stream->fin_sent();
507 return false;
508 }
509 } else {
510 stream->set_busy_counter(0);
511 }
512 return true;
513}
514
515bool QuicSession::CheckStreamWriteBlocked(QuicStream* stream) const {
516 if (!stream->write_side_closed() && stream->HasBufferedData() &&
renjietang07b2e8d2020-08-10 15:18:24 -0700517 !stream->IsFlowControlBlocked() &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518 !write_blocked_streams_.IsStreamBlocked(stream->id())) {
dschinazi88bd5b02019-10-10 00:52:20 -0700519 QUIC_DLOG(ERROR) << ENDPOINT << "stream " << stream->id()
520 << " has buffered " << stream->BufferedDataBytes()
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521 << " bytes, and is not flow control blocked, "
522 "but it is not in the write block list.";
523 return false;
524 }
525 return true;
526}
527
528void QuicSession::OnCanWrite() {
529 if (!RetransmitLostData()) {
530 // Cannot finish retransmitting lost data, connection is write blocked.
531 QUIC_DVLOG(1) << ENDPOINT
532 << "Cannot finish retransmitting lost data, connection is "
533 "write blocked.";
534 return;
535 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500536 // We limit the number of writes to the number of pending streams. If more
537 // streams become pending, WillingAndAbleToWrite will be true, which will
538 // cause the connection to request resumption before yielding to other
539 // connections.
540 // If we are connection level flow control blocked, then only allow the
541 // crypto and headers streams to try writing as all other streams will be
542 // blocked.
543 size_t num_writes = flow_controller_.IsBlocked()
544 ? write_blocked_streams_.NumBlockedSpecialStreams()
545 : write_blocked_streams_.NumBlockedStreams();
fayangaee31ef2019-08-20 06:47:51 -0700546 if (num_writes == 0 && !control_frame_manager_.WillingToWrite() &&
vasilvv2b0ab242020-01-07 07:32:09 -0800547 datagram_queue_.empty() &&
renjietangd1d00852019-09-06 10:43:12 -0700548 (!QuicVersionUsesCryptoFrames(transport_version()) ||
fayangaee31ef2019-08-20 06:47:51 -0700549 !GetCryptoStream()->HasBufferedCryptoFrames())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500550 return;
551 }
552
fayanga4b37b22019-06-18 13:37:47 -0700553 QuicConnection::ScopedPacketFlusher flusher(connection_);
renjietangd1d00852019-09-06 10:43:12 -0700554 if (QuicVersionUsesCryptoFrames(transport_version())) {
fayangaee31ef2019-08-20 06:47:51 -0700555 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
556 if (crypto_stream->HasBufferedCryptoFrames()) {
557 crypto_stream->WriteBufferedCryptoFrames();
558 }
559 if (crypto_stream->HasBufferedCryptoFrames()) {
560 // Cannot finish writing buffered crypto frames, connection is write
561 // blocked.
562 return;
563 }
564 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500565 if (control_frame_manager_.WillingToWrite()) {
566 control_frame_manager_.OnCanWrite();
567 }
vasilvv2b0ab242020-01-07 07:32:09 -0800568 // TODO(b/147146815): this makes all datagrams go before stream data. We
569 // should have a better priority scheme for this.
570 if (!datagram_queue_.empty()) {
571 size_t written = datagram_queue_.SendDatagrams();
572 QUIC_DVLOG(1) << ENDPOINT << "Sent " << written << " datagrams";
573 if (!datagram_queue_.empty()) {
574 return;
575 }
576 }
fayangeb1b8d72020-02-10 11:30:52 -0800577 std::vector<QuicStreamId> last_writing_stream_ids;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500578 for (size_t i = 0; i < num_writes; ++i) {
579 if (!(write_blocked_streams_.HasWriteBlockedSpecialStream() ||
580 write_blocked_streams_.HasWriteBlockedDataStreams())) {
581 // Writing one stream removed another!? Something's broken.
fayangeb1b8d72020-02-10 11:30:52 -0800582 QUIC_BUG << "WriteBlockedStream is missing, num_writes: " << num_writes
583 << ", finished_writes: " << i
584 << ", connected: " << connection_->connected()
585 << ", connection level flow control blocked: "
586 << flow_controller_.IsBlocked() << ", scheduler type: "
587 << spdy::WriteSchedulerTypeToString(
588 write_blocked_streams_.scheduler_type());
589 for (QuicStreamId id : last_writing_stream_ids) {
590 QUIC_LOG(WARNING) << "last_writing_stream_id: " << id;
591 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500592 connection_->CloseConnection(QUIC_INTERNAL_ERROR,
593 "WriteBlockedStream is missing",
594 ConnectionCloseBehavior::SILENT_CLOSE);
595 return;
596 }
ianswettfc16a2b2020-05-18 16:05:49 -0700597 if (!CanWriteStreamData()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500598 return;
599 }
600 currently_writing_stream_id_ = write_blocked_streams_.PopFront();
fayangeb1b8d72020-02-10 11:30:52 -0800601 last_writing_stream_ids.push_back(currently_writing_stream_id_);
dschinazi88bd5b02019-10-10 00:52:20 -0700602 QUIC_DVLOG(1) << ENDPOINT << "Removing stream "
603 << currently_writing_stream_id_ << " from write-blocked list";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500604 QuicStream* stream = GetOrCreateStream(currently_writing_stream_id_);
renjietang07b2e8d2020-08-10 15:18:24 -0700605 if (stream != nullptr && !stream->IsFlowControlBlocked()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500606 // If the stream can't write all bytes it'll re-add itself to the blocked
607 // list.
608 uint64_t previous_bytes_written = stream->stream_bytes_written();
609 bool previous_fin_sent = stream->fin_sent();
dschinazi88bd5b02019-10-10 00:52:20 -0700610 QUIC_DVLOG(1) << ENDPOINT << "stream " << stream->id()
611 << " bytes_written " << previous_bytes_written << " fin "
612 << previous_fin_sent;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500613 stream->OnCanWrite();
614 DCHECK(CheckStreamWriteBlocked(stream));
615 DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written,
616 previous_fin_sent));
617 }
618 currently_writing_stream_id_ = 0;
619 }
620}
621
QUICHE teamb8343252019-04-29 13:58:01 -0700622bool QuicSession::SendProbingData() {
623 if (connection()->sent_packet_manager().MaybeRetransmitOldestPacket(
624 PROBING_RETRANSMISSION)) {
625 return true;
626 }
627 return false;
628}
629
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630bool QuicSession::WillingAndAbleToWrite() const {
631 // Schedule a write when:
632 // 1) control frame manager has pending or new control frames, or
633 // 2) any stream has pending retransmissions, or
634 // 3) If the crypto or headers streams are blocked, or
635 // 4) connection is not flow control blocked and there are write blocked
636 // streams.
renjietangd1d00852019-09-06 10:43:12 -0700637 if (QuicVersionUsesCryptoFrames(transport_version()) &&
fayangaee31ef2019-08-20 06:47:51 -0700638 HasPendingHandshake()) {
639 return true;
640 }
fayangb4c1dac2020-05-29 14:46:25 -0700641 if (control_frame_manager_.WillingToWrite() ||
642 !streams_with_pending_retransmission_.empty()) {
643 return true;
644 }
fayangb4c1dac2020-05-29 14:46:25 -0700645 if (flow_controller_.IsBlocked()) {
646 if (VersionUsesHttp3(transport_version())) {
647 return false;
648 }
649 // Crypto and headers streams are not blocked by connection level flow
650 // control.
651 return write_blocked_streams_.HasWriteBlockedSpecialStream();
652 }
653 return write_blocked_streams_.HasWriteBlockedSpecialStream() ||
654 write_blocked_streams_.HasWriteBlockedDataStreams();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500655}
656
fayanga330b7c2020-09-10 08:15:39 -0700657std::string QuicSession::GetStreamsInfoForLogging() const {
658 std::string info = quiche::QuicheStrCat(
659 "num_active_streams: ", GetNumActiveStreams(),
660 ", num_pending_streams: ", pending_streams_size(),
661 ", num_outgoing_draining_streams: ", num_outgoing_draining_streams(),
662 " ");
663 // Log info for up to 5 streams.
664 size_t i = 5;
665 for (const auto& it : stream_map_) {
666 if (it.second->is_static()) {
667 continue;
668 }
669 // Calculate the stream creation delay.
670 const QuicTime::Delta delay =
671 connection_->clock()->ApproximateNow() - it.second->creation_time();
672 info = quiche::QuicheStrCat(
673 info, "{", it.second->id(), ":", delay.ToDebuggingValue(), ";",
674 it.second->stream_bytes_written(), ",", it.second->fin_sent(), ",",
675 it.second->HasBufferedData(), ",", it.second->fin_buffered(), ";",
676 it.second->stream_bytes_read(), ",", it.second->fin_received(), "}");
677 --i;
678 if (i == 0) {
679 break;
680 }
681 }
682 return info;
683}
684
QUICHE teama6ef0a62019-03-07 20:34:33 -0500685bool QuicSession::HasPendingHandshake() const {
renjietangd1d00852019-09-06 10:43:12 -0700686 if (QuicVersionUsesCryptoFrames(transport_version())) {
fayangaee31ef2019-08-20 06:47:51 -0700687 return GetCryptoStream()->HasPendingCryptoRetransmission() ||
688 GetCryptoStream()->HasBufferedCryptoFrames();
nharper46833c32019-05-15 21:33:05 -0700689 }
renjietangd1d00852019-09-06 10:43:12 -0700690 return QuicContainsKey(streams_with_pending_retransmission_,
691 QuicUtils::GetCryptoStreamId(transport_version())) ||
QUICHE teama6ef0a62019-03-07 20:34:33 -0500692 write_blocked_streams_.IsStreamBlocked(
renjietangd1d00852019-09-06 10:43:12 -0700693 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500694}
695
QUICHE teama6ef0a62019-03-07 20:34:33 -0500696void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
697 const QuicSocketAddress& peer_address,
698 const QuicReceivedPacket& packet) {
699 connection_->ProcessUdpPacket(self_address, peer_address, packet);
700}
701
renjietang41a1b412020-02-27 15:05:14 -0800702QuicConsumedData QuicSession::WritevData(
703 QuicStreamId id,
704 size_t write_length,
705 QuicStreamOffset offset,
706 StreamSendingState state,
renjietang4d992bf2020-03-03 13:01:55 -0800707 TransmissionType type,
renjietang41a1b412020-02-27 15:05:14 -0800708 quiche::QuicheOptional<EncryptionLevel> level) {
fayangbb93c602020-02-24 08:31:42 -0800709 DCHECK(connection_->connected())
710 << ENDPOINT << "Try to write stream data when connection is closed.";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500711 if (!IsEncryptionEstablished() &&
renjietangd1d00852019-09-06 10:43:12 -0700712 !QuicUtils::IsCryptoStreamId(transport_version(), id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713 // Do not let streams write without encryption. The calling stream will end
714 // up write blocked until OnCanWrite is next called.
renjietang9e77dfb2020-09-01 13:10:10 -0700715 if (was_zero_rtt_rejected_ && !OneRttKeysAvailable()) {
716 DCHECK(version().UsesTls() && perspective() == Perspective::IS_CLIENT);
717 QUIC_BUG_IF(type == NOT_RETRANSMISSION)
718 << ENDPOINT << "Try to send new data on stream " << id
719 << "before 1-RTT keys are available while 0-RTT is rejected.";
720 } else {
721 QUIC_BUG << ENDPOINT << "Try to send data of stream " << id
722 << " before encryption is established.";
723 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500724 return QuicConsumedData(0, false);
725 }
726
renjietang6369e472020-04-20 13:25:40 -0700727 SetTransmissionType(type);
renjietang41a1b412020-02-27 15:05:14 -0800728 const auto current_level = connection()->encryption_level();
729 if (level.has_value()) {
730 connection()->SetDefaultEncryptionLevel(level.value());
731 }
732
QUICHE teama6ef0a62019-03-07 20:34:33 -0500733 QuicConsumedData data =
734 connection_->SendStreamData(id, write_length, offset, state);
renjietang4d992bf2020-03-03 13:01:55 -0800735 if (type == NOT_RETRANSMISSION) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500736 // This is new stream data.
737 write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
738 }
renjietang41a1b412020-02-27 15:05:14 -0800739
740 // Restore the encryption level.
741 if (level.has_value()) {
742 connection()->SetDefaultEncryptionLevel(current_level);
743 }
744
QUICHE teama6ef0a62019-03-07 20:34:33 -0500745 return data;
746}
747
renjietang0c161c62020-03-05 13:13:53 -0800748size_t QuicSession::SendCryptoData(EncryptionLevel level,
749 size_t write_length,
750 QuicStreamOffset offset,
renjietang73be08f2020-03-11 15:20:08 -0700751 TransmissionType type) {
renjietang2abec1d2020-03-02 10:20:11 -0800752 DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
fayangd01e9962020-09-24 11:29:31 -0700753 if (connection()->check_keys_before_writing() &&
754 !connection()->framer().HasEncrypterOfEncryptionLevel(level)) {
755 const std::string error_details = quiche::QuicheStrCat(
756 "Try to send crypto data with missing keys of encryption level: ",
757 EncryptionLevelToString(level));
758 QUIC_BUG << ENDPOINT << error_details;
759 connection()->CloseConnection(
760 QUIC_MISSING_WRITE_KEYS, error_details,
761 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
762 return 0;
763 }
renjietang6369e472020-04-20 13:25:40 -0700764 SetTransmissionType(type);
renjietang2abec1d2020-03-02 10:20:11 -0800765 const auto current_level = connection()->encryption_level();
766 connection_->SetDefaultEncryptionLevel(level);
767 const auto bytes_consumed =
768 connection_->SendCryptoData(level, write_length, offset);
769 // Restores encryption level.
770 connection_->SetDefaultEncryptionLevel(current_level);
771 return bytes_consumed;
772}
773
renjietang8ccbf792020-07-15 16:28:09 -0700774void QuicSession::OnControlFrameManagerError(QuicErrorCode error_code,
775 std::string error_details) {
776 connection_->CloseConnection(
777 error_code, error_details,
778 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
779}
780
renjietang4d992bf2020-03-03 13:01:55 -0800781bool QuicSession::WriteControlFrame(const QuicFrame& frame,
renjietang73be08f2020-03-11 15:20:08 -0700782 TransmissionType type) {
renjietang8ccbf792020-07-15 16:28:09 -0700783 DCHECK(connection()->connected())
784 << ENDPOINT << "Try to write control frames when connection is closed.";
renjietang6369e472020-04-20 13:25:40 -0700785 SetTransmissionType(type);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500786 return connection_->SendControlFrame(frame);
787}
788
789void QuicSession::SendRstStream(QuicStreamId id,
790 QuicRstStreamErrorCode error,
renjietang9946bc02020-07-16 15:14:27 -0700791 QuicStreamOffset bytes_written,
792 bool send_rst_only) {
renjietang61cc2452019-11-26 10:57:10 -0800793 if (connection()->connected()) {
794 QuicConnection::ScopedPacketFlusher flusher(connection());
795 MaybeSendRstStreamFrame(id, error, bytes_written);
renjietang9946bc02020-07-16 15:14:27 -0700796 if (!send_rst_only) {
797 MaybeSendStopSendingFrame(id, error);
798 }
renjietang61cc2452019-11-26 10:57:10 -0800799
800 connection_->OnStreamReset(id, error);
801 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500802}
803
renjietangff4240d2020-07-01 06:19:55 -0700804void QuicSession::ResetStream(QuicStreamId id, QuicRstStreamErrorCode error) {
fayangd62ea772020-04-17 06:32:16 -0700805 QuicStream* stream = GetStream(id);
806 if (stream != nullptr && stream->is_static()) {
807 connection()->CloseConnection(
808 QUIC_INVALID_STREAM_ID, "Try to reset a static stream",
809 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
810 return;
811 }
812
813 if (stream != nullptr) {
814 stream->Reset(error);
815 return;
816 }
817
renjietang9946bc02020-07-16 15:14:27 -0700818 SendRstStream(id, error, 0, /*send_rst_only = */ false);
fayangd62ea772020-04-17 06:32:16 -0700819}
820
renjietang61cc2452019-11-26 10:57:10 -0800821void QuicSession::MaybeSendRstStreamFrame(QuicStreamId id,
822 QuicRstStreamErrorCode error,
823 QuicStreamOffset bytes_written) {
824 DCHECK(connection()->connected());
825 if (!VersionHasIetfQuicFrames(transport_version()) ||
renjietangd262e252020-06-19 15:11:24 -0700826 QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id),
827 version()) != READ_UNIDIRECTIONAL) {
renjietang61cc2452019-11-26 10:57:10 -0800828 control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
829 }
830}
831
832void QuicSession::MaybeSendStopSendingFrame(QuicStreamId id,
833 QuicRstStreamErrorCode error) {
834 DCHECK(connection()->connected());
835 if (VersionHasIetfQuicFrames(transport_version()) &&
renjietangd262e252020-06-19 15:11:24 -0700836 QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id),
837 version()) != WRITE_UNIDIRECTIONAL) {
renjietang61cc2452019-11-26 10:57:10 -0800838 control_frame_manager_.WriteOrBufferStopSending(error, id);
839 }
840}
841
QUICHE teama6ef0a62019-03-07 20:34:33 -0500842void QuicSession::SendGoAway(QuicErrorCode error_code,
vasilvvc48c8712019-03-11 13:38:16 -0700843 const std::string& reason) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500844 // GOAWAY frame is not supported in v99.
renjietangd1d00852019-09-06 10:43:12 -0700845 DCHECK(!VersionHasIetfQuicFrames(transport_version()));
bnc3988f572020-08-27 05:27:04 -0700846 if (transport_goaway_sent_) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500847 return;
848 }
bnc3988f572020-08-27 05:27:04 -0700849 transport_goaway_sent_ = true;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500850 control_frame_manager_.WriteOrBufferGoAway(
851 error_code, stream_id_manager_.largest_peer_created_stream_id(), reason);
852}
853
854void QuicSession::SendBlocked(QuicStreamId id) {
855 control_frame_manager_.WriteOrBufferBlocked(id);
856}
857
858void QuicSession::SendWindowUpdate(QuicStreamId id,
859 QuicStreamOffset byte_offset) {
860 control_frame_manager_.WriteOrBufferWindowUpdate(id, byte_offset);
861}
862
renjietangf196f6a2020-02-12 12:34:23 -0800863void QuicSession::OnStreamError(QuicErrorCode error_code,
864 std::string error_details) {
865 connection_->CloseConnection(
866 error_code, error_details,
867 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
868}
869
fkastenholz3c4eabf2019-04-22 07:49:59 -0700870void QuicSession::SendMaxStreams(QuicStreamCount stream_count,
871 bool unidirectional) {
fayangfe8f9c12020-03-18 16:17:38 -0700872 if (!is_configured_) {
873 QUIC_BUG << "Try to send max streams before config negotiated.";
874 return;
875 }
fkastenholz3c4eabf2019-04-22 07:49:59 -0700876 control_frame_manager_.WriteOrBufferMaxStreams(stream_count, unidirectional);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500877}
878
fayangb8f83442020-06-01 12:09:17 -0700879void QuicSession::InsertLocallyClosedStreamsHighestOffset(
880 const QuicStreamId id,
881 QuicStreamOffset offset) {
882 locally_closed_streams_highest_offset_[id] = offset;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500883}
884
fayangd62ea772020-04-17 06:32:16 -0700885void QuicSession::OnStreamClosed(QuicStreamId stream_id) {
886 QUIC_DVLOG(1) << ENDPOINT << "Closing stream: " << stream_id;
fayangd62ea772020-04-17 06:32:16 -0700887 StreamMap::iterator it = stream_map_.find(stream_id);
888 if (it == stream_map_.end()) {
renjietang70738bb2020-07-08 15:07:12 -0700889 QUIC_BUG << ENDPOINT << "Stream is already closed: " << stream_id;
fayangd62ea772020-04-17 06:32:16 -0700890 return;
891 }
892 QuicStream* stream = it->second.get();
893 StreamType type = stream->type();
894
renjietang647b3cf2020-08-04 13:23:12 -0700895 const bool stream_waiting_for_acks = stream->IsWaitingForAcks();
896 if (stream_waiting_for_acks) {
renjietang4c334822020-09-28 15:44:55 -0700897 // The stream needs to be kept alive because it's waiting for acks.
898 ++num_zombie_streams_;
fayangd62ea772020-04-17 06:32:16 -0700899 } else {
fayangd62ea772020-04-17 06:32:16 -0700900 closed_streams_.push_back(std::move(it->second));
renjietang4c334822020-09-28 15:44:55 -0700901 stream_map_.erase(it);
fayangd62ea772020-04-17 06:32:16 -0700902 // Do not retransmit data of a closed stream.
903 streams_with_pending_retransmission_.erase(stream_id);
904 if (!closed_streams_clean_up_alarm_->IsSet()) {
905 closed_streams_clean_up_alarm_->Set(
906 connection_->clock()->ApproximateNow());
907 }
908 }
909
fayangaa36e6c2020-04-17 13:12:43 -0700910 if (!stream->HasReceivedFinalOffset()) {
911 // If we haven't received a FIN or RST for this stream, we need to keep
912 // track of the how many bytes the stream's flow controller believes it has
913 // received, for accurate connection level flow control accounting.
914 // If this is an outgoing stream, it is technically open from peer's
915 // perspective. Do not inform stream Id manager yet.
916 DCHECK(!stream->was_draining());
fayangd62ea772020-04-17 06:32:16 -0700917 InsertLocallyClosedStreamsHighestOffset(
renjietang07b2e8d2020-08-10 15:18:24 -0700918 stream_id, stream->highest_received_byte_offset());
fayangaa36e6c2020-04-17 13:12:43 -0700919 return;
fayangd62ea772020-04-17 06:32:16 -0700920 }
fayangaa36e6c2020-04-17 13:12:43 -0700921
fayang6dfe58d2020-06-01 08:02:47 -0700922 const bool stream_was_draining = stream->was_draining();
923 QUIC_DVLOG_IF(1, stream_was_draining)
924 << ENDPOINT << "Stream " << stream_id << " was draining";
fayangd62ea772020-04-17 06:32:16 -0700925 if (stream_was_draining) {
fayang116fa4c2020-06-02 08:10:49 -0700926 QUIC_BUG_IF(num_draining_streams_ == 0);
927 --num_draining_streams_;
fayang8d601b12020-06-02 13:45:44 -0700928 if (!IsIncomingStream(stream_id)) {
929 QUIC_BUG_IF(num_outgoing_draining_streams_ == 0);
930 --num_outgoing_draining_streams_;
931 }
fayangaa36e6c2020-04-17 13:12:43 -0700932 // Stream Id manager has been informed with draining streams.
933 return;
934 }
fayangbd94f4c2020-06-01 14:36:37 -0700935 if (!VersionHasIetfQuicFrames(transport_version())) {
fayang01591ae2020-04-23 14:14:56 -0700936 stream_id_manager_.OnStreamClosed(
937 /*is_incoming=*/IsIncomingStream(stream_id));
938 }
fayang4b3123e2020-06-29 11:19:30 -0700939 if (!connection_->connected()) {
fayang4a3d5f02020-05-15 11:41:50 -0700940 return;
941 }
fayangaa36e6c2020-04-17 13:12:43 -0700942 if (IsIncomingStream(stream_id)) {
943 // Stream Id manager is only interested in peer initiated stream IDs.
944 if (VersionHasIetfQuicFrames(transport_version())) {
fayangd62ea772020-04-17 06:32:16 -0700945 v99_streamid_manager_.OnStreamClosed(stream_id);
946 }
fayangaa36e6c2020-04-17 13:12:43 -0700947 return;
fayangd62ea772020-04-17 06:32:16 -0700948 }
fayangaa36e6c2020-04-17 13:12:43 -0700949 if (!VersionHasIetfQuicFrames(transport_version())) {
fayangd62ea772020-04-17 06:32:16 -0700950 OnCanCreateNewOutgoingStream(type != BIDIRECTIONAL);
951 }
952}
953
QUICHE teama6ef0a62019-03-07 20:34:33 -0500954void QuicSession::ClosePendingStream(QuicStreamId stream_id) {
955 QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
fayang01591ae2020-04-23 14:14:56 -0700956 DCHECK(VersionHasIetfQuicFrames(transport_version()));
bnc092d8212019-08-07 11:53:20 -0700957 pending_stream_map_.erase(stream_id);
fayang01591ae2020-04-23 14:14:56 -0700958 if (connection_->connected()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500959 v99_streamid_manager_.OnStreamClosed(stream_id);
960 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500961}
962
963void QuicSession::OnFinalByteOffsetReceived(
964 QuicStreamId stream_id,
965 QuicStreamOffset final_byte_offset) {
966 auto it = locally_closed_streams_highest_offset_.find(stream_id);
967 if (it == locally_closed_streams_highest_offset_.end()) {
968 return;
969 }
970
971 QUIC_DVLOG(1) << ENDPOINT << "Received final byte offset "
972 << final_byte_offset << " for stream " << stream_id;
973 QuicByteCount offset_diff = final_byte_offset - it->second;
974 if (flow_controller_.UpdateHighestReceivedOffset(
975 flow_controller_.highest_received_byte_offset() + offset_diff)) {
976 // If the final offset violates flow control, close the connection now.
977 if (flow_controller_.FlowControlViolation()) {
978 connection_->CloseConnection(
979 QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
980 "Connection level flow control violation",
981 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
982 return;
983 }
984 }
985
986 flow_controller_.AddBytesConsumed(offset_diff);
987 locally_closed_streams_highest_offset_.erase(it);
fayangbd94f4c2020-06-01 14:36:37 -0700988 if (!VersionHasIetfQuicFrames(transport_version())) {
fayang01591ae2020-04-23 14:14:56 -0700989 stream_id_manager_.OnStreamClosed(
990 /*is_incoming=*/IsIncomingStream(stream_id));
991 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500992 if (IsIncomingStream(stream_id)) {
renjietangd1d00852019-09-06 10:43:12 -0700993 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500994 v99_streamid_manager_.OnStreamClosed(stream_id);
995 }
renjietangd1d00852019-09-06 10:43:12 -0700996 } else if (!VersionHasIetfQuicFrames(transport_version())) {
fkastenholz8556dc22019-07-18 12:42:38 -0700997 OnCanCreateNewOutgoingStream(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500998 }
999}
1000
1001bool QuicSession::IsEncryptionEstablished() const {
fkastenholzba94bc32019-11-08 08:50:25 -08001002 if (GetCryptoStream() == nullptr) {
1003 return false;
1004 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001005 return GetCryptoStream()->encryption_established();
1006}
1007
fayanga3d8df72020-01-14 11:54:39 -08001008bool QuicSession::OneRttKeysAvailable() const {
fkastenholzba94bc32019-11-08 08:50:25 -08001009 if (GetCryptoStream() == nullptr) {
1010 return false;
1011 }
fayang685367a2020-01-14 10:40:15 -08001012 return GetCryptoStream()->one_rtt_keys_available();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001013}
1014
1015void QuicSession::OnConfigNegotiated() {
renjietangc02d4462020-06-08 14:25:16 -07001016 // In versions with TLS, the configs will be set twice if 0-RTT is available.
1017 // In the second config setting, 1-RTT keys are guaranteed to be available.
renjietangeccd8cc2020-07-29 14:31:17 -07001018 if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
renjietangc02d4462020-06-08 14:25:16 -07001019 version().UsesTls() && is_configured_ &&
1020 connection_->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
1021 QUIC_BUG
1022 << ENDPOINT
1023 << "1-RTT keys missing when config is negotiated for the second time.";
1024 connection_->CloseConnection(
1025 QUIC_INTERNAL_ERROR,
1026 "1-RTT keys missing when config is negotiated for the second time.",
1027 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1028 return;
1029 }
1030
dschinazi88bd5b02019-10-10 00:52:20 -07001031 QUIC_DVLOG(1) << ENDPOINT << "OnConfigNegotiated";
QUICHE teama6ef0a62019-03-07 20:34:33 -05001032 connection_->SetFromConfig(config_);
1033
renjietang203926d2019-09-04 15:09:03 -07001034 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001035 uint32_t max_streams = 0;
renjietange6d94672020-01-07 10:30:10 -08001036 if (config_.HasReceivedMaxBidirectionalStreams()) {
1037 max_streams = config_.ReceivedMaxBidirectionalStreams();
fkastenholzd3a1de92019-05-15 07:00:07 -07001038 }
renjietangfaf8b022020-06-08 20:06:44 -07001039 if (was_zero_rtt_rejected_ &&
1040 max_streams <
1041 v99_streamid_manager_.outgoing_bidirectional_stream_count()) {
1042 connection_->CloseConnection(
renjietanga5a2ca92020-06-15 13:19:36 -07001043 QUIC_ZERO_RTT_UNRETRANSMITTABLE,
renjietangfaf8b022020-06-08 20:06:44 -07001044 quiche::QuicheStrCat(
1045 "Server rejected 0-RTT, aborting because new bidirectional "
1046 "initial stream limit ",
1047 max_streams, " is less than current open streams: ",
1048 v99_streamid_manager_.outgoing_bidirectional_stream_count()),
1049 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1050 return;
1051 }
dschinazi88bd5b02019-10-10 00:52:20 -07001052 QUIC_DVLOG(1) << ENDPOINT
1053 << "Setting Bidirectional outgoing_max_streams_ to "
fkastenholzd3a1de92019-05-15 07:00:07 -07001054 << max_streams;
renjietange0f96d72020-04-28 11:25:29 -07001055 if (perspective_ == Perspective::IS_CLIENT &&
1056 max_streams <
1057 v99_streamid_manager_.max_outgoing_bidirectional_streams()) {
1058 connection_->CloseConnection(
renjietanga5a2ca92020-06-15 13:19:36 -07001059 was_zero_rtt_rejected_ ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
1060 : QUIC_ZERO_RTT_RESUMPTION_LIMIT_REDUCED,
renjietange0f96d72020-04-28 11:25:29 -07001061 quiche::QuicheStrCat(
renjietanga5a2ca92020-06-15 13:19:36 -07001062 was_zero_rtt_rejected_
1063 ? "Server rejected 0-RTT, aborting because "
1064 : "",
renjietange0f96d72020-04-28 11:25:29 -07001065 "new bidirectional limit ", max_streams,
1066 " decreases the current limit: ",
1067 v99_streamid_manager_.max_outgoing_bidirectional_streams()),
1068 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1069 return;
1070 }
renjietangab9039a2020-03-30 14:53:19 -07001071 if (v99_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
1072 max_streams)) {
1073 OnCanCreateNewOutgoingStream(/*unidirectional = */ false);
1074 }
fkastenholzd3a1de92019-05-15 07:00:07 -07001075
1076 max_streams = 0;
renjietange6d94672020-01-07 10:30:10 -08001077 if (config_.HasReceivedMaxUnidirectionalStreams()) {
1078 max_streams = config_.ReceivedMaxUnidirectionalStreams();
fkastenholzd3a1de92019-05-15 07:00:07 -07001079 }
renjietangfaf8b022020-06-08 20:06:44 -07001080
1081 if (was_zero_rtt_rejected_ &&
1082 max_streams <
1083 v99_streamid_manager_.outgoing_unidirectional_stream_count()) {
1084 connection_->CloseConnection(
renjietanga5a2ca92020-06-15 13:19:36 -07001085 QUIC_ZERO_RTT_UNRETRANSMITTABLE,
renjietangfaf8b022020-06-08 20:06:44 -07001086 quiche::QuicheStrCat(
1087 "Server rejected 0-RTT, aborting because new unidirectional "
1088 "initial stream limit ",
1089 max_streams, " is less than current open streams: ",
1090 v99_streamid_manager_.outgoing_unidirectional_stream_count()),
1091 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1092 return;
1093 }
1094
renjietang241ba602020-04-29 13:29:46 -07001095 if (max_streams <
1096 v99_streamid_manager_.max_outgoing_unidirectional_streams()) {
renjietange0f96d72020-04-28 11:25:29 -07001097 connection_->CloseConnection(
renjietanga5a2ca92020-06-15 13:19:36 -07001098 was_zero_rtt_rejected_ ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
1099 : QUIC_ZERO_RTT_RESUMPTION_LIMIT_REDUCED,
renjietange0f96d72020-04-28 11:25:29 -07001100 quiche::QuicheStrCat(
renjietanga5a2ca92020-06-15 13:19:36 -07001101 was_zero_rtt_rejected_
1102 ? "Server rejected 0-RTT, aborting because "
1103 : "",
renjietange0f96d72020-04-28 11:25:29 -07001104 "new unidirectional limit ", max_streams,
1105 " decreases the current limit: ",
1106 v99_streamid_manager_.max_outgoing_unidirectional_streams()),
1107 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1108 return;
1109 }
dschinazi88bd5b02019-10-10 00:52:20 -07001110 QUIC_DVLOG(1) << ENDPOINT
1111 << "Setting Unidirectional outgoing_max_streams_ to "
fkastenholzd3a1de92019-05-15 07:00:07 -07001112 << max_streams;
renjietangab9039a2020-03-30 14:53:19 -07001113 if (v99_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
1114 max_streams)) {
1115 OnCanCreateNewOutgoingStream(/*unidirectional = */ true);
1116 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001117 } else {
fkastenholzd3a1de92019-05-15 07:00:07 -07001118 uint32_t max_streams = 0;
renjietange6d94672020-01-07 10:30:10 -08001119 if (config_.HasReceivedMaxBidirectionalStreams()) {
1120 max_streams = config_.ReceivedMaxBidirectionalStreams();
fkastenholzd3a1de92019-05-15 07:00:07 -07001121 }
dschinazi88bd5b02019-10-10 00:52:20 -07001122 QUIC_DVLOG(1) << ENDPOINT << "Setting max_open_outgoing_streams_ to "
1123 << max_streams;
renjietangfaf8b022020-06-08 20:06:44 -07001124 if (was_zero_rtt_rejected_ &&
1125 max_streams < stream_id_manager_.num_open_outgoing_streams()) {
1126 connection_->CloseConnection(
1127 QUIC_INTERNAL_ERROR,
1128 quiche::QuicheStrCat(
1129 "Server rejected 0-RTT, aborting because new stream limit ",
1130 max_streams, " is less than current open streams: ",
1131 stream_id_manager_.num_open_outgoing_streams()),
1132 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1133 return;
1134 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001135 stream_id_manager_.set_max_open_outgoing_streams(max_streams);
1136 }
fkastenholzd3a1de92019-05-15 07:00:07 -07001137
QUICHE teama6ef0a62019-03-07 20:34:33 -05001138 if (perspective() == Perspective::IS_SERVER) {
1139 if (config_.HasReceivedConnectionOptions()) {
1140 // The following variations change the initial receive flow control
1141 // window sizes.
1142 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW6)) {
1143 AdjustInitialFlowControlWindows(64 * 1024);
1144 }
1145 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW7)) {
1146 AdjustInitialFlowControlWindows(128 * 1024);
1147 }
1148 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW8)) {
1149 AdjustInitialFlowControlWindows(256 * 1024);
1150 }
1151 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW9)) {
1152 AdjustInitialFlowControlWindows(512 * 1024);
1153 }
1154 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
1155 AdjustInitialFlowControlWindows(1024 * 1024);
1156 }
fayangd323f782020-02-18 08:27:51 -08001157 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kH2PR) &&
renjietangd1d00852019-09-06 10:43:12 -07001158 !VersionHasIetfQuicFrames(transport_version())) {
fayange606e0c2019-08-05 06:56:05 -07001159 // Enable HTTP2 (tree-style) priority write scheduler.
fayang944cfbc2019-07-31 09:15:00 -07001160 use_http2_priority_write_scheduler_ =
fayange606e0c2019-08-05 06:56:05 -07001161 write_blocked_streams_.SwitchWriteScheduler(
renjietangd1d00852019-09-06 10:43:12 -07001162 spdy::WriteSchedulerType::HTTP2, transport_version());
QUICHE teamdfd1cc82020-01-07 14:26:10 -08001163 } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kFIFO)) {
fayange606e0c2019-08-05 06:56:05 -07001164 // Enable FIFO write scheduler.
QUICHE teamdfd1cc82020-01-07 14:26:10 -08001165 write_blocked_streams_.SwitchWriteScheduler(
1166 spdy::WriteSchedulerType::FIFO, transport_version());
fayangaa5248f2020-01-30 10:43:54 -08001167 } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kLIFO)) {
fayangae266342019-08-05 12:19:59 -07001168 // Enable LIFO write scheduler.
fayangaa5248f2020-01-30 10:43:54 -08001169 write_blocked_streams_.SwitchWriteScheduler(
1170 spdy::WriteSchedulerType::LIFO, transport_version());
fayangb3161f22020-02-18 11:00:04 -08001171 } else if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kRRWS) &&
fayang1b11b962019-09-16 14:01:48 -07001172 write_blocked_streams_.scheduler_type() ==
1173 spdy::WriteSchedulerType::SPDY) {
fayang1b11b962019-09-16 14:01:48 -07001174 enable_round_robin_scheduling_ = true;
fayang944cfbc2019-07-31 09:15:00 -07001175 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001176 }
1177
1178 config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
1179 }
1180
renjietangd1d00852019-09-06 10:43:12 -07001181 if (VersionHasIetfQuicFrames(transport_version())) {
fkastenholzd3a1de92019-05-15 07:00:07 -07001182 v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
renjietange6d94672020-01-07 10:30:10 -08001183 config_.GetMaxBidirectionalStreamsToSend());
fkastenholzd3a1de92019-05-15 07:00:07 -07001184 v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
renjietange6d94672020-01-07 10:30:10 -08001185 config_.GetMaxUnidirectionalStreamsToSend());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001186 } else {
fkastenholzd3a1de92019-05-15 07:00:07 -07001187 // A small number of additional incoming streams beyond the limit should be
1188 // allowed. This helps avoid early connection termination when FIN/RSTs for
1189 // old streams are lost or arrive out of order.
1190 // Use a minimum number of additional streams, or a percentage increase,
1191 // whichever is larger.
1192 uint32_t max_incoming_streams_to_send =
renjietange6d94672020-01-07 10:30:10 -08001193 config_.GetMaxBidirectionalStreamsToSend();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001194 uint32_t max_incoming_streams =
1195 std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
1196 static_cast<uint32_t>(max_incoming_streams_to_send *
1197 kMaxStreamsMultiplier));
1198 stream_id_manager_.set_max_open_incoming_streams(max_incoming_streams);
1199 }
1200
dschinazi18cdf132019-10-09 16:08:18 -07001201 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1202 // When using IETF-style TLS transport parameters, inform existing streams
1203 // of new flow-control limits.
1204 if (config_.HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional()) {
1205 OnNewStreamOutgoingBidirectionalFlowControlWindow(
1206 config_.ReceivedInitialMaxStreamDataBytesOutgoingBidirectional());
1207 }
1208 if (config_.HasReceivedInitialMaxStreamDataBytesIncomingBidirectional()) {
1209 OnNewStreamIncomingBidirectionalFlowControlWindow(
1210 config_.ReceivedInitialMaxStreamDataBytesIncomingBidirectional());
1211 }
1212 if (config_.HasReceivedInitialMaxStreamDataBytesUnidirectional()) {
1213 OnNewStreamUnidirectionalFlowControlWindow(
1214 config_.ReceivedInitialMaxStreamDataBytesUnidirectional());
1215 }
1216 } else { // The version uses Google QUIC Crypto.
1217 if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
1218 // Streams which were created before the SHLO was received (0-RTT
1219 // requests) are now informed of the peer's initial flow control window.
1220 OnNewStreamFlowControlWindow(
1221 config_.ReceivedInitialStreamFlowControlWindowBytes());
1222 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001223 }
dschinazi18cdf132019-10-09 16:08:18 -07001224
QUICHE teama6ef0a62019-03-07 20:34:33 -05001225 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) {
1226 OnNewSessionFlowControlWindow(
1227 config_.ReceivedInitialSessionFlowControlWindowBytes());
1228 }
renjietangc02d4462020-06-08 14:25:16 -07001229
fkastenholz9b4b0ad2019-08-20 05:10:40 -07001230 is_configured_ = true;
wub44e33052020-03-03 17:11:40 -08001231 connection()->OnConfigNegotiated();
fkastenholz56055be2019-09-17 11:17:37 -07001232
dschinazi18cdf132019-10-09 16:08:18 -07001233 // Ask flow controllers to try again since the config could have unblocked us.
renjietangc02d4462020-06-08 14:25:16 -07001234 // Or if this session is configured on TLS enabled QUIC versions,
1235 // attempt to retransmit 0-RTT data if there's any.
1236 if (connection_->version().AllowsLowFlowControlLimits() ||
renjietangeccd8cc2020-07-29 14:31:17 -07001237 (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
renjietangc02d4462020-06-08 14:25:16 -07001238 version().UsesTls())) {
dschinazi18cdf132019-10-09 16:08:18 -07001239 OnCanWrite();
1240 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001241}
1242
1243void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
1244 const float session_window_multiplier =
1245 config_.GetInitialStreamFlowControlWindowToSend()
1246 ? static_cast<float>(
1247 config_.GetInitialSessionFlowControlWindowToSend()) /
1248 config_.GetInitialStreamFlowControlWindowToSend()
1249 : 1.5;
1250
1251 QUIC_DVLOG(1) << ENDPOINT << "Set stream receive window to " << stream_window;
1252 config_.SetInitialStreamFlowControlWindowToSend(stream_window);
1253
1254 size_t session_window = session_window_multiplier * stream_window;
1255 QUIC_DVLOG(1) << ENDPOINT << "Set session receive window to "
1256 << session_window;
1257 config_.SetInitialSessionFlowControlWindowToSend(session_window);
1258 flow_controller_.UpdateReceiveWindowSize(session_window);
1259 // Inform all existing streams about the new window.
renjietang55d182a2019-07-12 10:26:25 -07001260 for (auto const& kv : stream_map_) {
renjietang07b2e8d2020-08-10 15:18:24 -07001261 kv.second->UpdateReceiveWindowSize(stream_window);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001262 }
renjietangd1d00852019-09-06 10:43:12 -07001263 if (!QuicVersionUsesCryptoFrames(transport_version())) {
renjietang07b2e8d2020-08-10 15:18:24 -07001264 GetMutableCryptoStream()->UpdateReceiveWindowSize(stream_window);
renjietang08a9cf72019-04-23 17:01:34 -07001265 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001266}
1267
1268void QuicSession::HandleFrameOnNonexistentOutgoingStream(
1269 QuicStreamId stream_id) {
1270 DCHECK(!IsClosedStream(stream_id));
1271 // Received a frame for a locally-created stream that is not currently
1272 // active. This is an error.
bncec3602c2020-03-12 17:57:59 -07001273 if (VersionHasIetfQuicFrames(transport_version())) {
1274 connection()->CloseConnection(
1275 QUIC_HTTP_STREAM_WRONG_DIRECTION, "Data for nonexistent stream",
1276 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1277 return;
1278 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001279 connection()->CloseConnection(
1280 QUIC_INVALID_STREAM_ID, "Data for nonexistent stream",
1281 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1282}
1283
1284void QuicSession::HandleRstOnValidNonexistentStream(
1285 const QuicRstStreamFrame& frame) {
1286 // If the stream is neither originally in active streams nor created in
renjietang880d2432019-07-16 13:14:37 -07001287 // GetOrCreateStream(), it could be a closed stream in which case its
QUICHE teama6ef0a62019-03-07 20:34:33 -05001288 // final received byte offset need to be updated.
1289 if (IsClosedStream(frame.stream_id)) {
1290 // The RST frame contains the final byte offset for the stream: we can now
1291 // update the connection level flow controller if needed.
1292 OnFinalByteOffsetReceived(frame.stream_id, frame.byte_offset);
1293 }
1294}
1295
1296void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
renjietang3f68bdf2020-08-10 11:52:30 -07001297 DCHECK(version().UsesQuicCrypto());
dschinazi88bd5b02019-10-10 00:52:20 -07001298 QUIC_DVLOG(1) << ENDPOINT << "OnNewStreamFlowControlWindow " << new_window;
renjietange238a132020-08-12 16:46:41 -07001299 if (new_window < kMinimumFlowControlSendWindow) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001300 QUIC_LOG_FIRST_N(ERROR, 1)
1301 << "Peer sent us an invalid stream flow control send window: "
dschinazic7036122019-04-30 12:46:34 -07001302 << new_window << ", below minimum: " << kMinimumFlowControlSendWindow;
renjietang255ff772019-09-04 14:14:03 -07001303 connection_->CloseConnection(
1304 QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
1305 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001306 return;
1307 }
1308
1309 // Inform all existing streams about the new window.
renjietang55d182a2019-07-12 10:26:25 -07001310 for (auto const& kv : stream_map_) {
dschinazi88bd5b02019-10-10 00:52:20 -07001311 QUIC_DVLOG(1) << ENDPOINT << "Informing stream " << kv.first
1312 << " of new stream flow control window " << new_window;
renjietang3f68bdf2020-08-10 11:52:30 -07001313 if (!kv.second->MaybeConfigSendWindowOffset(
1314 new_window, /* was_zero_rtt_rejected = */ false)) {
renjietange0f96d72020-04-28 11:25:29 -07001315 return;
1316 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001317 }
renjietangd1d00852019-09-06 10:43:12 -07001318 if (!QuicVersionUsesCryptoFrames(transport_version())) {
dschinazi88bd5b02019-10-10 00:52:20 -07001319 QUIC_DVLOG(1)
1320 << ENDPOINT
1321 << "Informing crypto stream of new stream flow control window "
1322 << new_window;
renjietang3f68bdf2020-08-10 11:52:30 -07001323 GetMutableCryptoStream()->MaybeConfigSendWindowOffset(
1324 new_window, /* was_zero_rtt_rejected = */ false);
renjietang08a9cf72019-04-23 17:01:34 -07001325 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001326}
1327
dschinazi18cdf132019-10-09 16:08:18 -07001328void QuicSession::OnNewStreamUnidirectionalFlowControlWindow(
1329 QuicStreamOffset new_window) {
renjietange0f96d72020-04-28 11:25:29 -07001330 DCHECK_EQ(connection_->version().handshake_protocol, PROTOCOL_TLS1_3);
dschinazi18cdf132019-10-09 16:08:18 -07001331 QUIC_DVLOG(1) << ENDPOINT << "OnNewStreamUnidirectionalFlowControlWindow "
1332 << new_window;
1333 // Inform all existing outgoing unidirectional streams about the new window.
1334 for (auto const& kv : stream_map_) {
1335 const QuicStreamId id = kv.first;
renjietangc27771b2020-08-03 11:10:36 -07001336 if (!version().HasIetfQuicFrames()) {
renjietang37b2e182020-06-18 16:48:08 -07001337 if (kv.second->type() == BIDIRECTIONAL) {
1338 continue;
1339 }
1340 } else {
renjietangd262e252020-06-19 15:11:24 -07001341 if (QuicUtils::IsBidirectionalStreamId(id, version())) {
renjietang37b2e182020-06-18 16:48:08 -07001342 continue;
1343 }
dschinazi18cdf132019-10-09 16:08:18 -07001344 }
1345 if (!QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1346 perspective())) {
1347 continue;
1348 }
1349 QUIC_DVLOG(1) << ENDPOINT << "Informing unidirectional stream " << id
1350 << " of new stream flow control window " << new_window;
renjietang3f68bdf2020-08-10 11:52:30 -07001351 if (!kv.second->MaybeConfigSendWindowOffset(new_window,
1352 was_zero_rtt_rejected_)) {
renjietange0f96d72020-04-28 11:25:29 -07001353 return;
1354 }
dschinazi18cdf132019-10-09 16:08:18 -07001355 }
1356}
1357
1358void QuicSession::OnNewStreamOutgoingBidirectionalFlowControlWindow(
1359 QuicStreamOffset new_window) {
renjietange0f96d72020-04-28 11:25:29 -07001360 DCHECK_EQ(connection_->version().handshake_protocol, PROTOCOL_TLS1_3);
dschinazi18cdf132019-10-09 16:08:18 -07001361 QUIC_DVLOG(1) << ENDPOINT
1362 << "OnNewStreamOutgoingBidirectionalFlowControlWindow "
1363 << new_window;
1364 // Inform all existing outgoing bidirectional streams about the new window.
1365 for (auto const& kv : stream_map_) {
1366 const QuicStreamId id = kv.first;
renjietangc27771b2020-08-03 11:10:36 -07001367 if (!version().HasIetfQuicFrames()) {
renjietang37b2e182020-06-18 16:48:08 -07001368 if (kv.second->type() != BIDIRECTIONAL) {
1369 continue;
1370 }
1371 } else {
renjietangd262e252020-06-19 15:11:24 -07001372 if (!QuicUtils::IsBidirectionalStreamId(id, version())) {
renjietang37b2e182020-06-18 16:48:08 -07001373 continue;
1374 }
dschinazi18cdf132019-10-09 16:08:18 -07001375 }
1376 if (!QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1377 perspective())) {
1378 continue;
1379 }
1380 QUIC_DVLOG(1) << ENDPOINT << "Informing outgoing bidirectional stream "
1381 << id << " of new stream flow control window " << new_window;
renjietang3f68bdf2020-08-10 11:52:30 -07001382 if (!kv.second->MaybeConfigSendWindowOffset(new_window,
1383 was_zero_rtt_rejected_)) {
renjietange0f96d72020-04-28 11:25:29 -07001384 return;
1385 }
dschinazi18cdf132019-10-09 16:08:18 -07001386 }
1387}
1388
1389void QuicSession::OnNewStreamIncomingBidirectionalFlowControlWindow(
1390 QuicStreamOffset new_window) {
renjietange0f96d72020-04-28 11:25:29 -07001391 DCHECK_EQ(connection_->version().handshake_protocol, PROTOCOL_TLS1_3);
dschinazi18cdf132019-10-09 16:08:18 -07001392 QUIC_DVLOG(1) << ENDPOINT
1393 << "OnNewStreamIncomingBidirectionalFlowControlWindow "
1394 << new_window;
1395 // Inform all existing incoming bidirectional streams about the new window.
1396 for (auto const& kv : stream_map_) {
1397 const QuicStreamId id = kv.first;
renjietangc27771b2020-08-03 11:10:36 -07001398 if (!version().HasIetfQuicFrames()) {
renjietang37b2e182020-06-18 16:48:08 -07001399 if (kv.second->type() != BIDIRECTIONAL) {
1400 continue;
1401 }
1402 } else {
renjietangd262e252020-06-19 15:11:24 -07001403 if (!QuicUtils::IsBidirectionalStreamId(id, version())) {
renjietang37b2e182020-06-18 16:48:08 -07001404 continue;
1405 }
dschinazi18cdf132019-10-09 16:08:18 -07001406 }
1407 if (QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1408 perspective())) {
1409 continue;
1410 }
1411 QUIC_DVLOG(1) << ENDPOINT << "Informing incoming bidirectional stream "
1412 << id << " of new stream flow control window " << new_window;
renjietang3f68bdf2020-08-10 11:52:30 -07001413 if (!kv.second->MaybeConfigSendWindowOffset(new_window,
1414 was_zero_rtt_rejected_)) {
renjietange0f96d72020-04-28 11:25:29 -07001415 return;
1416 }
dschinazi18cdf132019-10-09 16:08:18 -07001417 }
1418}
1419
QUICHE teama6ef0a62019-03-07 20:34:33 -05001420void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
dschinazi88bd5b02019-10-10 00:52:20 -07001421 QUIC_DVLOG(1) << ENDPOINT << "OnNewSessionFlowControlWindow " << new_window;
renjietangfaf8b022020-06-08 20:06:44 -07001422
1423 if (was_zero_rtt_rejected_ && new_window < flow_controller_.bytes_sent()) {
1424 std::string error_details = quiche::QuicheStrCat(
1425 "Server rejected 0-RTT. Aborting because the client received session "
1426 "flow control send window: ",
1427 new_window,
1428 ", which is below currently used: ", flow_controller_.bytes_sent());
1429 QUIC_LOG(ERROR) << error_details;
1430 connection_->CloseConnection(
renjietanga5a2ca92020-06-15 13:19:36 -07001431 QUIC_ZERO_RTT_UNRETRANSMITTABLE, error_details,
renjietangfaf8b022020-06-08 20:06:44 -07001432 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1433 return;
1434 }
1435 if (!connection_->version().AllowsLowFlowControlLimits() &&
1436 new_window < kMinimumFlowControlSendWindow) {
1437 std::string error_details = quiche::QuicheStrCat(
1438 "Peer sent us an invalid session flow control send window: ",
1439 new_window, ", below minimum: ", kMinimumFlowControlSendWindow);
1440 QUIC_LOG_FIRST_N(ERROR, 1) << error_details;
1441 connection_->CloseConnection(
1442 QUIC_FLOW_CONTROL_INVALID_WINDOW, error_details,
1443 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1444 return;
1445 }
1446 if (perspective_ == Perspective::IS_CLIENT &&
1447 new_window < flow_controller_.send_window_offset()) {
renjietange0f96d72020-04-28 11:25:29 -07001448 // The client receives a lower limit than remembered, violating
1449 // https://tools.ietf.org/html/draft-ietf-quic-transport-27#section-7.3.1
renjietangfaf8b022020-06-08 20:06:44 -07001450 std::string error_details = quiche::QuicheStrCat(
renjietanga5a2ca92020-06-15 13:19:36 -07001451 was_zero_rtt_rejected_ ? "Server rejected 0-RTT, aborting because "
1452 : "",
1453 "new session max data ", new_window,
1454 " decreases current limit: ", flow_controller_.send_window_offset());
renjietangfaf8b022020-06-08 20:06:44 -07001455 QUIC_LOG(ERROR) << error_details;
renjietang255ff772019-09-04 14:14:03 -07001456 connection_->CloseConnection(
renjietanga5a2ca92020-06-15 13:19:36 -07001457 was_zero_rtt_rejected_ ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
1458 : QUIC_ZERO_RTT_RESUMPTION_LIMIT_REDUCED,
1459 error_details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001460 return;
1461 }
1462
1463 flow_controller_.UpdateSendWindowOffset(new_window);
1464}
1465
fayangd2866522020-02-12 11:15:27 -08001466bool QuicSession::OnNewDecryptionKeyAvailable(
fayang3f7bcbe2020-02-10 11:08:47 -08001467 EncryptionLevel level,
1468 std::unique_ptr<QuicDecrypter> decrypter,
1469 bool set_alternative_decrypter,
1470 bool latch_once_used) {
fayangd2866522020-02-12 11:15:27 -08001471 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3 &&
1472 !connection()->framer().HasEncrypterOfEncryptionLevel(
1473 QuicUtils::GetEncryptionLevel(
1474 QuicUtils::GetPacketNumberSpace(level)))) {
1475 // This should never happen because connection should never decrypt a packet
1476 // while an ACK for it cannot be encrypted.
1477 return false;
1478 }
fayangd58736d2019-11-27 13:35:31 -08001479 if (connection()->version().KnowsWhichDecrypterToUse()) {
1480 connection()->InstallDecrypter(level, std::move(decrypter));
fayangd2866522020-02-12 11:15:27 -08001481 return true;
fayangd58736d2019-11-27 13:35:31 -08001482 }
1483 if (set_alternative_decrypter) {
1484 connection()->SetAlternativeDecrypter(level, std::move(decrypter),
1485 latch_once_used);
fayangd2866522020-02-12 11:15:27 -08001486 return true;
fayangd58736d2019-11-27 13:35:31 -08001487 }
1488 connection()->SetDecrypter(level, std::move(decrypter));
fayangd2866522020-02-12 11:15:27 -08001489 return true;
fayangd58736d2019-11-27 13:35:31 -08001490}
1491
fayang3f7bcbe2020-02-10 11:08:47 -08001492void QuicSession::OnNewEncryptionKeyAvailable(
1493 EncryptionLevel level,
1494 std::unique_ptr<QuicEncrypter> encrypter) {
1495 connection()->SetEncrypter(level, std::move(encrypter));
fayang81c15b22020-06-08 11:29:58 -07001496 if (connection_->version().handshake_protocol != PROTOCOL_TLS1_3) {
fayang8373d172020-05-04 15:42:30 -07001497 return;
1498 }
1499
nharper1b6221e2020-08-04 16:11:31 -07001500 bool reset_encryption_level = false;
1501 if (IsEncryptionEstablished() && level == ENCRYPTION_HANDSHAKE) {
1502 // ENCRYPTION_HANDSHAKE keys are only used for the handshake. If
1503 // ENCRYPTION_ZERO_RTT keys exist, it is possible for a client to send
1504 // stream data, which must not be sent at the ENCRYPTION_HANDSHAKE level.
1505 // Therefore, we avoid setting the default encryption level to
1506 // ENCRYPTION_HANDSHAKE.
1507 reset_encryption_level = true;
1508 }
fayang81c15b22020-06-08 11:29:58 -07001509 QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to " << level;
1510 connection()->SetDefaultEncryptionLevel(level);
nharper1b6221e2020-08-04 16:11:31 -07001511 if (reset_encryption_level) {
1512 connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
1513 }
1514 QUIC_BUG_IF(IsEncryptionEstablished() &&
1515 (connection()->encryption_level() == ENCRYPTION_INITIAL ||
1516 connection()->encryption_level() == ENCRYPTION_HANDSHAKE))
1517 << "Encryption is established, but the encryption level " << level
1518 << " does not support sending stream data";
fayang3f7bcbe2020-02-10 11:08:47 -08001519}
1520
fayangd58736d2019-11-27 13:35:31 -08001521void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
fayangd18bfb92020-03-19 17:24:21 -07001522 DCHECK_EQ(PROTOCOL_QUIC_CRYPTO, connection_->version().handshake_protocol);
renjietangb4ebb1d2020-05-27 18:15:51 -07001523 QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to " << level;
fayangd58736d2019-11-27 13:35:31 -08001524 connection()->SetDefaultEncryptionLevel(level);
1525
1526 switch (level) {
1527 case ENCRYPTION_INITIAL:
1528 break;
1529 case ENCRYPTION_ZERO_RTT:
fayang401cf202019-12-06 10:30:13 -08001530 if (perspective() == Perspective::IS_CLIENT) {
1531 // Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since
1532 // they can't be decrypted by the server.
renjietangf71e8062020-09-14 12:01:15 -07001533 connection_->MarkZeroRttPacketsForRetransmission(0);
fayang401cf202019-12-06 10:30:13 -08001534 // Given any streams blocked by encryption a chance to write.
1535 OnCanWrite();
1536 }
fayangd58736d2019-11-27 13:35:31 -08001537 break;
1538 case ENCRYPTION_HANDSHAKE:
1539 break;
1540 case ENCRYPTION_FORWARD_SECURE:
1541 QUIC_BUG_IF(!config_.negotiated())
1542 << ENDPOINT << "Handshake confirmed without parameter negotiation.";
fayang8607b292020-08-19 09:00:55 -07001543 connection()->mutable_stats().handshake_completion_time =
1544 connection()->clock()->ApproximateNow();
fayangd58736d2019-11-27 13:35:31 -08001545 break;
1546 default:
renjietangb4ebb1d2020-05-27 18:15:51 -07001547 QUIC_BUG << "Unknown encryption level: " << level;
fayangd58736d2019-11-27 13:35:31 -08001548 }
1549}
1550
renjietangc50cc4a2020-08-17 18:33:30 -07001551void QuicSession::OnTlsHandshakeComplete() {
fayangd18bfb92020-03-19 17:24:21 -07001552 DCHECK_EQ(PROTOCOL_TLS1_3, connection_->version().handshake_protocol);
fayangd18bfb92020-03-19 17:24:21 -07001553 QUIC_BUG_IF(!GetCryptoStream()->crypto_negotiated_params().cipher_suite)
1554 << ENDPOINT << "Handshake completes without cipher suite negotiation.";
1555 QUIC_BUG_IF(!config_.negotiated())
1556 << ENDPOINT << "Handshake completes without parameter negotiation.";
fayang8607b292020-08-19 09:00:55 -07001557 connection()->mutable_stats().handshake_completion_time =
1558 connection()->clock()->ApproximateNow();
fayang5c362882020-06-16 07:39:39 -07001559 if ((connection()->version().HasHandshakeDone() ||
fayang67395d02020-08-17 09:18:27 -07001560 config_.PeerSupportsHandshakeDone()) &&
fayangd18bfb92020-03-19 17:24:21 -07001561 perspective_ == Perspective::IS_SERVER) {
1562 // Server sends HANDSHAKE_DONE to signal confirmation of the handshake
1563 // to the client.
1564 control_frame_manager_.WriteOrBufferHandshakeDone();
1565 }
fayangd18bfb92020-03-19 17:24:21 -07001566}
1567
fayangd58736d2019-11-27 13:35:31 -08001568void QuicSession::DiscardOldDecryptionKey(EncryptionLevel level) {
fayangd58736d2019-11-27 13:35:31 -08001569 if (!connection()->version().KnowsWhichDecrypterToUse()) {
fayangd58736d2019-11-27 13:35:31 -08001570 return;
1571 }
1572 connection()->RemoveDecrypter(level);
1573}
1574
1575void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
dschinazi101d2eb2020-07-06 19:42:34 -07001576 QUIC_DLOG(INFO) << ENDPOINT << "Discarding " << level << " keys";
fayangb296fb82020-02-11 08:14:28 -08001577 if (connection()->version().handshake_protocol == PROTOCOL_TLS1_3) {
1578 connection()->RemoveEncrypter(level);
1579 }
fayangd58736d2019-11-27 13:35:31 -08001580 switch (level) {
1581 case ENCRYPTION_INITIAL:
1582 NeuterUnencryptedData();
1583 break;
1584 case ENCRYPTION_HANDSHAKE:
fayang01062942020-01-22 07:23:23 -08001585 NeuterHandshakeData();
fayangd58736d2019-11-27 13:35:31 -08001586 break;
1587 case ENCRYPTION_ZERO_RTT:
1588 break;
1589 case ENCRYPTION_FORWARD_SECURE:
dschinazi101d2eb2020-07-06 19:42:34 -07001590 QUIC_BUG << ENDPOINT << "Discarding 1-RTT keys is not allowed";
fayangd58736d2019-11-27 13:35:31 -08001591 break;
1592 default:
dschinazi101d2eb2020-07-06 19:42:34 -07001593 QUIC_BUG << ENDPOINT
1594 << "Cannot discard keys for unknown encryption level: " << level;
fayangd58736d2019-11-27 13:35:31 -08001595 }
1596}
1597
1598void QuicSession::NeuterHandshakeData() {
fayang29d18032020-09-14 13:48:00 -07001599 GetMutableCryptoStream()->NeuterStreamDataOfEncryptionLevel(
1600 ENCRYPTION_HANDSHAKE);
fayangd58736d2019-11-27 13:35:31 -08001601 connection()->OnHandshakeComplete();
1602}
1603
renjietangf71e8062020-09-14 12:01:15 -07001604void QuicSession::OnZeroRttRejected(int reason) {
renjietangfaf8b022020-06-08 20:06:44 -07001605 was_zero_rtt_rejected_ = true;
renjietangf71e8062020-09-14 12:01:15 -07001606 connection_->MarkZeroRttPacketsForRetransmission(reason);
renjietange7b2cd82020-06-03 16:59:18 -07001607 if (connection_->encryption_level() == ENCRYPTION_FORWARD_SECURE) {
renjietangc02d4462020-06-08 14:25:16 -07001608 QUIC_BUG << "1-RTT keys already available when 0-RTT is rejected.";
1609 connection_->CloseConnection(
1610 QUIC_INTERNAL_ERROR,
1611 "1-RTT keys already available when 0-RTT is rejected.",
1612 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
renjietange7b2cd82020-06-03 16:59:18 -07001613 }
nharperd25cd652020-05-20 13:10:26 -07001614}
1615
dschinazi2c4d8332020-05-27 17:23:32 -07001616bool QuicSession::FillTransportParameters(TransportParameters* params) {
dschinazie7c38a52020-05-29 15:25:45 -07001617 if (version().AuthenticatesHandshakeConnectionIds()) {
1618 if (perspective() == Perspective::IS_SERVER) {
1619 config_.SetOriginalConnectionIdToSend(
1620 connection_->GetOriginalDestinationConnectionId());
1621 config_.SetInitialSourceConnectionIdToSend(connection_->connection_id());
1622 } else {
1623 config_.SetInitialSourceConnectionIdToSend(
1624 connection_->client_connection_id());
1625 }
1626 }
dschinazi2c4d8332020-05-27 17:23:32 -07001627 return config_.FillTransportParameters(params);
1628}
1629
1630QuicErrorCode QuicSession::ProcessTransportParameters(
1631 const TransportParameters& params,
1632 bool is_resumption,
1633 std::string* error_details) {
dschinazi52c8f332020-08-17 13:30:01 -07001634 return config_.ProcessTransportParameters(params, is_resumption,
dschinazi2c4d8332020-05-27 17:23:32 -07001635 error_details);
1636}
1637
QUICHE teama6ef0a62019-03-07 20:34:33 -05001638void QuicSession::OnCryptoHandshakeMessageSent(
1639 const CryptoHandshakeMessage& /*message*/) {}
1640
1641void QuicSession::OnCryptoHandshakeMessageReceived(
1642 const CryptoHandshakeMessage& /*message*/) {}
1643
fayang476683a2019-07-25 12:42:16 -07001644void QuicSession::RegisterStreamPriority(
1645 QuicStreamId id,
1646 bool is_static,
1647 const spdy::SpdyStreamPrecedence& precedence) {
fayang1b11b962019-09-16 14:01:48 -07001648 if (enable_round_robin_scheduling_) {
1649 // Ignore provided precedence, instead, put all streams at the same priority
1650 // bucket.
1651 write_blocked_streams()->RegisterStream(
1652 id, is_static, spdy::SpdyStreamPrecedence(spdy::kV3LowestPriority));
1653 return;
1654 }
fayang476683a2019-07-25 12:42:16 -07001655 write_blocked_streams()->RegisterStream(id, is_static, precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001656}
1657
1658void QuicSession::UnregisterStreamPriority(QuicStreamId id, bool is_static) {
1659 write_blocked_streams()->UnregisterStream(id, is_static);
1660}
1661
fayang476683a2019-07-25 12:42:16 -07001662void QuicSession::UpdateStreamPriority(
1663 QuicStreamId id,
1664 const spdy::SpdyStreamPrecedence& new_precedence) {
fayang1b11b962019-09-16 14:01:48 -07001665 if (enable_round_robin_scheduling_) {
1666 // Ignore updated precedence.
1667 return;
1668 }
fayang476683a2019-07-25 12:42:16 -07001669 write_blocked_streams()->UpdateStreamPriority(id, new_precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001670}
1671
1672QuicConfig* QuicSession::config() {
1673 return &config_;
1674}
1675
1676void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
1677 QuicStreamId stream_id = stream->id();
renjietang5c729f02019-09-06 12:43:48 -07001678 bool is_static = stream->is_static();
renjietang55d182a2019-07-12 10:26:25 -07001679 QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
dschinazi8cb33e02020-04-02 16:25:09 -07001680 << ". activating stream " << stream_id;
renjietang55d182a2019-07-12 10:26:25 -07001681 DCHECK(!QuicContainsKey(stream_map_, stream_id));
1682 stream_map_[stream_id] = std::move(stream);
fayangbd94f4c2020-06-01 14:36:37 -07001683 if (is_static) {
fayang116fa4c2020-06-02 08:10:49 -07001684 ++num_static_streams_;
fayangbd94f4c2020-06-01 14:36:37 -07001685 return;
renjietang5c729f02019-09-06 12:43:48 -07001686 }
fayangbd94f4c2020-06-01 14:36:37 -07001687 if (!VersionHasIetfQuicFrames(transport_version())) {
fayang01591ae2020-04-23 14:14:56 -07001688 // Do not inform stream ID manager of static streams.
1689 stream_id_manager_.ActivateStream(
1690 /*is_incoming=*/IsIncomingStream(stream_id));
1691 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001692}
1693
1694QuicStreamId QuicSession::GetNextOutgoingBidirectionalStreamId() {
renjietangd1d00852019-09-06 10:43:12 -07001695 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001696 return v99_streamid_manager_.GetNextOutgoingBidirectionalStreamId();
1697 }
1698 return stream_id_manager_.GetNextOutgoingStreamId();
1699}
1700
1701QuicStreamId QuicSession::GetNextOutgoingUnidirectionalStreamId() {
renjietangd1d00852019-09-06 10:43:12 -07001702 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001703 return v99_streamid_manager_.GetNextOutgoingUnidirectionalStreamId();
1704 }
1705 return stream_id_manager_.GetNextOutgoingStreamId();
1706}
1707
1708bool QuicSession::CanOpenNextOutgoingBidirectionalStream() {
fayang001c8282020-07-29 12:39:29 -07001709 if (liveness_testing_in_progress_) {
1710 DCHECK_EQ(Perspective::IS_CLIENT, perspective());
1711 return false;
1712 }
fayang769172b2020-03-19 14:27:39 -07001713 if (!VersionHasIetfQuicFrames(transport_version())) {
fayang001c8282020-07-29 12:39:29 -07001714 if (!stream_id_manager_.CanOpenNextOutgoingStream()) {
1715 return false;
1716 }
1717 } else {
1718 if (!v99_streamid_manager_.CanOpenNextOutgoingBidirectionalStream()) {
1719 if (is_configured_) {
1720 // Send STREAM_BLOCKED after config negotiated.
1721 control_frame_manager_.WriteOrBufferStreamsBlocked(
1722 v99_streamid_manager_.max_outgoing_bidirectional_streams(),
1723 /*unidirectional=*/false);
1724 }
1725 return false;
1726 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001727 }
fayang001c8282020-07-29 12:39:29 -07001728 if (perspective() == Perspective::IS_CLIENT &&
1729 connection_->MaybeTestLiveness()) {
1730 // Now is relatively close to the idle timeout having the risk that requests
1731 // could be discarded at the server.
1732 liveness_testing_in_progress_ = true;
1733 return false;
fayang769172b2020-03-19 14:27:39 -07001734 }
fayang001c8282020-07-29 12:39:29 -07001735 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001736}
1737
1738bool QuicSession::CanOpenNextOutgoingUnidirectionalStream() {
fayang769172b2020-03-19 14:27:39 -07001739 if (!VersionHasIetfQuicFrames(transport_version())) {
fayangbd94f4c2020-06-01 14:36:37 -07001740 return stream_id_manager_.CanOpenNextOutgoingStream();
QUICHE teama6ef0a62019-03-07 20:34:33 -05001741 }
fayang769172b2020-03-19 14:27:39 -07001742 if (v99_streamid_manager_.CanOpenNextOutgoingUnidirectionalStream()) {
1743 return true;
1744 }
1745 if (is_configured_) {
1746 // Send STREAM_BLOCKED after config negotiated.
1747 control_frame_manager_.WriteOrBufferStreamsBlocked(
1748 v99_streamid_manager_.max_outgoing_unidirectional_streams(),
1749 /*unidirectional=*/true);
1750 }
1751 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001752}
1753
bnc41c19ca2020-01-21 18:55:26 -08001754QuicStreamCount QuicSession::GetAdvertisedMaxIncomingBidirectionalStreams()
1755 const {
1756 DCHECK(VersionHasIetfQuicFrames(transport_version()));
1757 return v99_streamid_manager_.advertised_max_incoming_bidirectional_streams();
1758}
1759
QUICHE teama6ef0a62019-03-07 20:34:33 -05001760QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
renjietang28c04b72019-07-01 15:08:09 -07001761 DCHECK(!QuicContainsKey(pending_stream_map_, stream_id));
renjietangd1d00852019-09-06 10:43:12 -07001762 if (QuicUtils::IsCryptoStreamId(transport_version(), stream_id)) {
renjietang2c4d7122019-05-20 17:18:14 -07001763 return GetMutableCryptoStream();
renjietang08a9cf72019-04-23 17:01:34 -07001764 }
renjietang880d2432019-07-16 13:14:37 -07001765
1766 StreamMap::iterator it = stream_map_.find(stream_id);
1767 if (it != stream_map_.end()) {
renjietang4c334822020-09-28 15:44:55 -07001768 return it->second->IsZombie() ? nullptr : it->second.get();
renjietang880d2432019-07-16 13:14:37 -07001769 }
1770
1771 if (IsClosedStream(stream_id)) {
1772 return nullptr;
1773 }
1774
1775 if (!IsIncomingStream(stream_id)) {
1776 HandleFrameOnNonexistentOutgoingStream(stream_id);
1777 return nullptr;
1778 }
1779
bnc3988f572020-08-27 05:27:04 -07001780 // TODO(fkastenholz): If we are creating a new stream and we have sent a
1781 // goaway, we should ignore the stream creation. Need to add code to A) test
1782 // if goaway was sent ("if (transport_goaway_sent_)") and B) reject stream
1783 // creation ("return nullptr")
renjietang880d2432019-07-16 13:14:37 -07001784
1785 if (!MaybeIncreaseLargestPeerStreamId(stream_id)) {
1786 return nullptr;
1787 }
1788
fayangbd94f4c2020-06-01 14:36:37 -07001789 if (!VersionHasIetfQuicFrames(transport_version()) &&
1790 !stream_id_manager_.CanOpenIncomingStream()) {
1791 // Refuse to open the stream.
renjietangff4240d2020-07-01 06:19:55 -07001792 ResetStream(stream_id, QUIC_REFUSED_STREAM);
fayangbd94f4c2020-06-01 14:36:37 -07001793 return nullptr;
renjietang880d2432019-07-16 13:14:37 -07001794 }
1795
1796 return CreateIncomingStream(stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001797}
1798
fayangbe6d6642020-04-16 14:15:34 -07001799void QuicSession::StreamDraining(QuicStreamId stream_id, bool unidirectional) {
renjietang55d182a2019-07-12 10:26:25 -07001800 DCHECK(QuicContainsKey(stream_map_, stream_id));
fayang6dfe58d2020-06-01 08:02:47 -07001801 QUIC_DVLOG(1) << ENDPOINT << "Stream " << stream_id << " is draining";
1802 if (VersionHasIetfQuicFrames(transport_version())) {
1803 v99_streamid_manager_.OnStreamClosed(stream_id);
fayangbd94f4c2020-06-01 14:36:37 -07001804 } else {
fayang6dfe58d2020-06-01 08:02:47 -07001805 stream_id_manager_.OnStreamClosed(
1806 /*is_incoming=*/IsIncomingStream(stream_id));
1807 }
fayang116fa4c2020-06-02 08:10:49 -07001808 ++num_draining_streams_;
1809 if (!IsIncomingStream(stream_id)) {
fayang8d601b12020-06-02 13:45:44 -07001810 ++num_outgoing_draining_streams_;
fayang116fa4c2020-06-02 08:10:49 -07001811 OnCanCreateNewOutgoingStream(unidirectional);
fayangbe6d6642020-04-16 14:15:34 -07001812 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001813}
1814
1815bool QuicSession::MaybeIncreaseLargestPeerStreamId(
1816 const QuicStreamId stream_id) {
renjietangd1d00852019-09-06 10:43:12 -07001817 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang7133ea92020-04-01 12:49:36 -07001818 std::string error_details;
1819 if (v99_streamid_manager_.MaybeIncreaseLargestPeerStreamId(
1820 stream_id, &error_details)) {
1821 return true;
1822 }
1823 connection()->CloseConnection(
1824 QUIC_INVALID_STREAM_ID, error_details,
1825 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1826 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001827 }
ianswettc1f530d2019-12-10 05:14:30 -08001828 if (!stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id)) {
1829 connection()->CloseConnection(
1830 QUIC_TOO_MANY_AVAILABLE_STREAMS,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001831 quiche::QuicheStrCat(stream_id, " exceeds available streams ",
1832 stream_id_manager_.MaxAvailableStreams()),
ianswettc1f530d2019-12-10 05:14:30 -08001833 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1834 return false;
1835 }
1836 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001837}
1838
1839bool QuicSession::ShouldYield(QuicStreamId stream_id) {
1840 if (stream_id == currently_writing_stream_id_) {
1841 return false;
1842 }
1843 return write_blocked_streams()->ShouldYield(stream_id);
1844}
1845
renjietange76b2da2019-05-13 14:50:23 -07001846PendingStream* QuicSession::GetOrCreatePendingStream(QuicStreamId stream_id) {
1847 auto it = pending_stream_map_.find(stream_id);
1848 if (it != pending_stream_map_.end()) {
1849 return it->second.get();
1850 }
1851
1852 if (IsClosedStream(stream_id) ||
1853 !MaybeIncreaseLargestPeerStreamId(stream_id)) {
1854 return nullptr;
1855 }
1856
vasilvv0fc587f2019-09-06 13:33:08 -07001857 auto pending = std::make_unique<PendingStream>(stream_id, this);
renjietange76b2da2019-05-13 14:50:23 -07001858 PendingStream* unowned_pending = pending.get();
1859 pending_stream_map_[stream_id] = std::move(pending);
1860 return unowned_pending;
1861}
1862
QUICHE teama6ef0a62019-03-07 20:34:33 -05001863void QuicSession::set_largest_peer_created_stream_id(
1864 QuicStreamId largest_peer_created_stream_id) {
renjietangc4004162020-03-17 15:25:49 -07001865 DCHECK(!VersionHasIetfQuicFrames(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001866 stream_id_manager_.set_largest_peer_created_stream_id(
1867 largest_peer_created_stream_id);
1868}
1869
renjietang686ce582019-10-17 14:28:16 -07001870QuicStreamId QuicSession::GetLargestPeerCreatedStreamId(
1871 bool unidirectional) const {
1872 // This method is only used in IETF QUIC.
1873 DCHECK(VersionHasIetfQuicFrames(transport_version()));
1874 return v99_streamid_manager_.GetLargestPeerCreatedStreamId(unidirectional);
1875}
1876
ianswett6aefa0b2019-12-10 07:26:15 -08001877void QuicSession::DeleteConnection() {
1878 if (connection_) {
1879 delete connection_;
1880 connection_ = nullptr;
1881 }
1882}
1883
bncb4e7b992020-01-21 18:36:14 -08001884bool QuicSession::MaybeSetStreamPriority(
1885 QuicStreamId stream_id,
1886 const spdy::SpdyStreamPrecedence& precedence) {
1887 auto active_stream = stream_map_.find(stream_id);
1888 if (active_stream != stream_map_.end()) {
1889 active_stream->second->SetPriority(precedence);
1890 return true;
1891 }
1892
1893 return false;
1894}
1895
QUICHE teama6ef0a62019-03-07 20:34:33 -05001896bool QuicSession::IsClosedStream(QuicStreamId id) {
renjietangd1d00852019-09-06 10:43:12 -07001897 DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001898 if (IsOpenStream(id)) {
1899 // Stream is active
1900 return false;
1901 }
1902
renjietangd1d00852019-09-06 10:43:12 -07001903 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001904 return !v99_streamid_manager_.IsAvailableStream(id);
1905 }
1906
1907 return !stream_id_manager_.IsAvailableStream(id);
1908}
1909
1910bool QuicSession::IsOpenStream(QuicStreamId id) {
renjietangd1d00852019-09-06 10:43:12 -07001911 DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
renjietang647b3cf2020-08-04 13:23:12 -07001912 const StreamMap::iterator it = stream_map_.find(id);
1913 if (it != stream_map_.end()) {
renjietang4c334822020-09-28 15:44:55 -07001914 return !it->second->IsZombie();
renjietang647b3cf2020-08-04 13:23:12 -07001915 }
1916 if (QuicContainsKey(pending_stream_map_, id) ||
renjietangd1d00852019-09-06 10:43:12 -07001917 QuicUtils::IsCryptoStreamId(transport_version(), id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001918 // Stream is active
1919 return true;
1920 }
1921 return false;
1922}
1923
rchda26cdb2019-05-17 11:57:37 -07001924bool QuicSession::IsStaticStream(QuicStreamId id) const {
renjietang55d182a2019-07-12 10:26:25 -07001925 auto it = stream_map_.find(id);
1926 if (it == stream_map_.end()) {
renjietangb663b862019-07-08 16:02:39 -07001927 return false;
rchda26cdb2019-05-17 11:57:37 -07001928 }
renjietangb663b862019-07-08 16:02:39 -07001929 return it->second->is_static();
rchda26cdb2019-05-17 11:57:37 -07001930}
1931
QUICHE teama6ef0a62019-03-07 20:34:33 -05001932size_t QuicSession::GetNumActiveStreams() const {
renjietangbab731c2020-08-03 13:43:50 -07001933 DCHECK_GE(static_cast<QuicStreamCount>(stream_map_.size()),
renjietang647b3cf2020-08-04 13:23:12 -07001934 num_static_streams_ + num_draining_streams_ + num_zombie_streams_);
1935 return stream_map_.size() - num_draining_streams_ - num_static_streams_ -
1936 num_zombie_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -05001937}
1938
1939void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id) {
1940 if (GetOrCreateStream(id) == nullptr) {
1941 QUIC_BUG << "Marking unknown stream " << id << " blocked.";
1942 QUIC_LOG_FIRST_N(ERROR, 2) << QuicStackTrace();
1943 }
1944
dschinazi88bd5b02019-10-10 00:52:20 -07001945 QUIC_DVLOG(1) << ENDPOINT << "Adding stream " << id
1946 << " to write-blocked list";
1947
QUICHE teama6ef0a62019-03-07 20:34:33 -05001948 write_blocked_streams_.AddStream(id);
1949}
1950
1951bool QuicSession::HasDataToWrite() const {
1952 return write_blocked_streams_.HasWriteBlockedSpecialStream() ||
1953 write_blocked_streams_.HasWriteBlockedDataStreams() ||
1954 connection_->HasQueuedData() ||
1955 !streams_with_pending_retransmission_.empty() ||
1956 control_frame_manager_.WillingToWrite();
1957}
1958
1959void QuicSession::OnAckNeedsRetransmittableFrame() {
1960 flow_controller_.SendWindowUpdate();
1961}
1962
1963void QuicSession::SendPing() {
1964 control_frame_manager_.WritePing();
1965}
1966
QUICHE teama6ef0a62019-03-07 20:34:33 -05001967bool QuicSession::IsConnectionFlowControlBlocked() const {
1968 return flow_controller_.IsBlocked();
1969}
1970
1971bool QuicSession::IsStreamFlowControlBlocked() {
renjietang55d182a2019-07-12 10:26:25 -07001972 for (auto const& kv : stream_map_) {
renjietang07b2e8d2020-08-10 15:18:24 -07001973 if (kv.second->IsFlowControlBlocked()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001974 return true;
1975 }
1976 }
renjietangd1d00852019-09-06 10:43:12 -07001977 if (!QuicVersionUsesCryptoFrames(transport_version()) &&
renjietang07b2e8d2020-08-10 15:18:24 -07001978 GetMutableCryptoStream()->IsFlowControlBlocked()) {
renjietang08a9cf72019-04-23 17:01:34 -07001979 return true;
1980 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05001981 return false;
1982}
1983
1984size_t QuicSession::MaxAvailableBidirectionalStreams() const {
renjietangd1d00852019-09-06 10:43:12 -07001985 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001986 return v99_streamid_manager_.GetMaxAllowdIncomingBidirectionalStreams();
1987 }
1988 return stream_id_manager_.MaxAvailableStreams();
1989}
1990
1991size_t QuicSession::MaxAvailableUnidirectionalStreams() const {
renjietangd1d00852019-09-06 10:43:12 -07001992 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001993 return v99_streamid_manager_.GetMaxAllowdIncomingUnidirectionalStreams();
1994 }
1995 return stream_id_manager_.MaxAvailableStreams();
1996}
1997
1998bool QuicSession::IsIncomingStream(QuicStreamId id) const {
renjietangd1d00852019-09-06 10:43:12 -07001999 if (VersionHasIetfQuicFrames(transport_version())) {
renjietang40038f52020-04-08 11:30:31 -07002000 return !QuicUtils::IsOutgoingStreamId(version(), id, perspective_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002001 }
2002 return stream_id_manager_.IsIncomingStream(id);
2003}
2004
renjietange29fe6e2020-10-01 15:48:23 -07002005void QuicSession::MaybeCloseZombieStream(QuicStreamId id) {
renjietang4c334822020-09-28 15:44:55 -07002006 auto it = stream_map_.find(id);
2007 if (it == stream_map_.end()) {
2008 return;
QUICHE teama6ef0a62019-03-07 20:34:33 -05002009 }
renjietang4c334822020-09-28 15:44:55 -07002010 --num_zombie_streams_;
2011 closed_streams_.push_back(std::move(it->second));
2012 stream_map_.erase(it);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002013
QUICHE teama6ef0a62019-03-07 20:34:33 -05002014 if (!closed_streams_clean_up_alarm_->IsSet()) {
2015 closed_streams_clean_up_alarm_->Set(connection_->clock()->ApproximateNow());
2016 }
QUICHE teama6ef0a62019-03-07 20:34:33 -05002017 // Do not retransmit data of a closed stream.
2018 streams_with_pending_retransmission_.erase(id);
2019}
2020
2021QuicStream* QuicSession::GetStream(QuicStreamId id) const {
renjietang55d182a2019-07-12 10:26:25 -07002022 auto active_stream = stream_map_.find(id);
2023 if (active_stream != stream_map_.end()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002024 return active_stream->second.get();
2025 }
renjietang647b3cf2020-08-04 13:23:12 -07002026
renjietangd1d00852019-09-06 10:43:12 -07002027 if (QuicUtils::IsCryptoStreamId(transport_version(), id)) {
renjietang08a9cf72019-04-23 17:01:34 -07002028 return const_cast<QuicCryptoStream*>(GetCryptoStream());
2029 }
2030
QUICHE teama6ef0a62019-03-07 20:34:33 -05002031 return nullptr;
2032}
2033
renjietangc2f30582020-07-22 16:59:39 -07002034QuicStream* QuicSession::GetActiveStream(QuicStreamId id) const {
2035 auto stream = stream_map_.find(id);
2036 if (stream != stream_map_.end() && !stream->second->is_static()) {
2037 return stream->second.get();
2038 }
2039 return nullptr;
2040}
2041
QUICHE teama6ef0a62019-03-07 20:34:33 -05002042bool QuicSession::OnFrameAcked(const QuicFrame& frame,
QUICHE team9467db02019-05-30 09:38:45 -07002043 QuicTime::Delta ack_delay_time,
2044 QuicTime receive_timestamp) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002045 if (frame.type == MESSAGE_FRAME) {
QUICHE team9467db02019-05-30 09:38:45 -07002046 OnMessageAcked(frame.message_frame->message_id, receive_timestamp);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002047 return true;
2048 }
2049 if (frame.type == CRYPTO_FRAME) {
2050 return GetMutableCryptoStream()->OnCryptoFrameAcked(*frame.crypto_frame,
2051 ack_delay_time);
2052 }
2053 if (frame.type != STREAM_FRAME) {
2054 return control_frame_manager_.OnControlFrameAcked(frame);
2055 }
2056 bool new_stream_data_acked = false;
2057 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2058 // Stream can already be reset when sent frame gets acked.
2059 if (stream != nullptr) {
2060 QuicByteCount newly_acked_length = 0;
2061 new_stream_data_acked = stream->OnStreamFrameAcked(
2062 frame.stream_frame.offset, frame.stream_frame.data_length,
QUICHE team2f5f30b2020-02-18 08:52:28 -08002063 frame.stream_frame.fin, ack_delay_time, receive_timestamp,
2064 &newly_acked_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002065 if (!stream->HasPendingRetransmission()) {
2066 streams_with_pending_retransmission_.erase(stream->id());
2067 }
2068 }
2069 return new_stream_data_acked;
2070}
2071
2072void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
2073 QuicStream* stream = GetStream(frame.stream_id);
2074 if (stream == nullptr) {
2075 QUIC_BUG << "Stream: " << frame.stream_id << " is closed when " << frame
2076 << " is retransmitted.";
2077 connection()->CloseConnection(
2078 QUIC_INTERNAL_ERROR, "Attempt to retransmit frame of a closed stream",
2079 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2080 return;
2081 }
2082 stream->OnStreamFrameRetransmitted(frame.offset, frame.data_length,
2083 frame.fin);
2084}
2085
2086void QuicSession::OnFrameLost(const QuicFrame& frame) {
2087 if (frame.type == MESSAGE_FRAME) {
2088 OnMessageLost(frame.message_frame->message_id);
2089 return;
2090 }
2091 if (frame.type == CRYPTO_FRAME) {
2092 GetMutableCryptoStream()->OnCryptoFrameLost(frame.crypto_frame);
2093 return;
2094 }
2095 if (frame.type != STREAM_FRAME) {
2096 control_frame_manager_.OnControlFrameLost(frame);
2097 return;
2098 }
2099 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2100 if (stream == nullptr) {
2101 return;
2102 }
2103 stream->OnStreamFrameLost(frame.stream_frame.offset,
2104 frame.stream_frame.data_length,
2105 frame.stream_frame.fin);
2106 if (stream->HasPendingRetransmission() &&
2107 !QuicContainsKey(streams_with_pending_retransmission_,
2108 frame.stream_frame.stream_id)) {
2109 streams_with_pending_retransmission_.insert(
2110 std::make_pair(frame.stream_frame.stream_id, true));
2111 }
2112}
2113
2114void QuicSession::RetransmitFrames(const QuicFrames& frames,
2115 TransmissionType type) {
fayanga4b37b22019-06-18 13:37:47 -07002116 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002117 for (const QuicFrame& frame : frames) {
2118 if (frame.type == MESSAGE_FRAME) {
2119 // Do not retransmit MESSAGE frames.
2120 continue;
2121 }
2122 if (frame.type == CRYPTO_FRAME) {
renjietang4d992bf2020-03-03 13:01:55 -08002123 GetMutableCryptoStream()->RetransmitData(frame.crypto_frame, type);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002124 continue;
2125 }
2126 if (frame.type != STREAM_FRAME) {
renjietang4d992bf2020-03-03 13:01:55 -08002127 if (!control_frame_manager_.RetransmitControlFrame(frame, type)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002128 break;
2129 }
2130 continue;
2131 }
2132 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2133 if (stream != nullptr &&
2134 !stream->RetransmitStreamData(frame.stream_frame.offset,
2135 frame.stream_frame.data_length,
renjietang4d992bf2020-03-03 13:01:55 -08002136 frame.stream_frame.fin, type)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002137 break;
2138 }
2139 }
2140}
2141
2142bool QuicSession::IsFrameOutstanding(const QuicFrame& frame) const {
2143 if (frame.type == MESSAGE_FRAME) {
2144 return false;
2145 }
2146 if (frame.type == CRYPTO_FRAME) {
2147 return GetCryptoStream()->IsFrameOutstanding(
2148 frame.crypto_frame->level, frame.crypto_frame->offset,
2149 frame.crypto_frame->data_length);
2150 }
2151 if (frame.type != STREAM_FRAME) {
2152 return control_frame_manager_.IsControlFrameOutstanding(frame);
2153 }
2154 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2155 return stream != nullptr &&
2156 stream->IsStreamFrameOutstanding(frame.stream_frame.offset,
2157 frame.stream_frame.data_length,
2158 frame.stream_frame.fin);
2159}
2160
2161bool QuicSession::HasUnackedCryptoData() const {
2162 const QuicCryptoStream* crypto_stream = GetCryptoStream();
fayang44fa92f2019-07-01 07:32:14 -07002163 return crypto_stream->IsWaitingForAcks() || crypto_stream->HasBufferedData();
QUICHE teama6ef0a62019-03-07 20:34:33 -05002164}
2165
zhongyi1b2f7832019-06-14 13:31:34 -07002166bool QuicSession::HasUnackedStreamData() const {
renjietangdf2240d2020-07-17 12:17:00 -07002167 for (const auto& it : stream_map_) {
2168 if (it.second->IsWaitingForAcks()) {
2169 return true;
2170 }
2171 }
2172 return false;
zhongyi1b2f7832019-06-14 13:31:34 -07002173}
2174
fayang9a863cf2020-01-16 14:12:11 -08002175HandshakeState QuicSession::GetHandshakeState() const {
2176 return GetCryptoStream()->GetHandshakeState();
2177}
2178
QUICHE teama6ef0a62019-03-07 20:34:33 -05002179WriteStreamDataResult QuicSession::WriteStreamData(QuicStreamId id,
2180 QuicStreamOffset offset,
2181 QuicByteCount data_length,
2182 QuicDataWriter* writer) {
2183 QuicStream* stream = GetStream(id);
2184 if (stream == nullptr) {
2185 // This causes the connection to be closed because of failed to serialize
2186 // packet.
ianswetteb101f82019-04-04 09:13:24 -07002187 QUIC_BUG << "Stream " << id << " does not exist when trying to write data."
renjietangd1d00852019-09-06 10:43:12 -07002188 << " version:" << transport_version();
QUICHE teama6ef0a62019-03-07 20:34:33 -05002189 return STREAM_MISSING;
2190 }
2191 if (stream->WriteStreamData(offset, data_length, writer)) {
2192 return WRITE_SUCCESS;
2193 }
2194 return WRITE_FAILED;
2195}
2196
2197bool QuicSession::WriteCryptoData(EncryptionLevel level,
2198 QuicStreamOffset offset,
2199 QuicByteCount data_length,
2200 QuicDataWriter* writer) {
2201 return GetMutableCryptoStream()->WriteCryptoFrame(level, offset, data_length,
2202 writer);
2203}
2204
2205QuicUint128 QuicSession::GetStatelessResetToken() const {
2206 return QuicUtils::GenerateStatelessResetToken(connection_->connection_id());
2207}
2208
ianswettfc16a2b2020-05-18 16:05:49 -07002209bool QuicSession::CanWriteStreamData() const {
2210 // Don't write stream data if there are queued data packets.
2211 if (connection_->HasQueuedPackets()) {
2212 return false;
2213 }
2214 // Immediately write handshake data.
2215 if (HasPendingHandshake()) {
2216 return true;
2217 }
2218 return connection_->CanWrite(HAS_RETRANSMITTABLE_DATA);
2219}
2220
QUICHE teama6ef0a62019-03-07 20:34:33 -05002221bool QuicSession::RetransmitLostData() {
fayanga4b37b22019-06-18 13:37:47 -07002222 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002223 // Retransmit crypto data first.
renjietangd1d00852019-09-06 10:43:12 -07002224 bool uses_crypto_frames = QuicVersionUsesCryptoFrames(transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002225 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
2226 if (uses_crypto_frames && crypto_stream->HasPendingCryptoRetransmission()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002227 crypto_stream->WritePendingCryptoRetransmission();
2228 }
2229 // Retransmit crypto data in stream 1 frames (version < 47).
2230 if (!uses_crypto_frames &&
renjietangd1d00852019-09-06 10:43:12 -07002231 QuicContainsKey(streams_with_pending_retransmission_,
2232 QuicUtils::GetCryptoStreamId(transport_version()))) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002233 // Retransmit crypto data first.
renjietangd1d00852019-09-06 10:43:12 -07002234 QuicStream* crypto_stream =
2235 GetStream(QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002236 crypto_stream->OnCanWrite();
2237 DCHECK(CheckStreamWriteBlocked(crypto_stream));
2238 if (crypto_stream->HasPendingRetransmission()) {
2239 // Connection is write blocked.
2240 return false;
2241 } else {
2242 streams_with_pending_retransmission_.erase(
renjietangd1d00852019-09-06 10:43:12 -07002243 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002244 }
2245 }
2246 if (control_frame_manager_.HasPendingRetransmission()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002247 control_frame_manager_.OnCanWrite();
2248 if (control_frame_manager_.HasPendingRetransmission()) {
2249 return false;
2250 }
2251 }
2252 while (!streams_with_pending_retransmission_.empty()) {
ianswettfc16a2b2020-05-18 16:05:49 -07002253 if (!CanWriteStreamData()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002254 break;
2255 }
2256 // Retransmit lost data on headers and data streams.
2257 const QuicStreamId id = streams_with_pending_retransmission_.begin()->first;
2258 QuicStream* stream = GetStream(id);
2259 if (stream != nullptr) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002260 stream->OnCanWrite();
2261 DCHECK(CheckStreamWriteBlocked(stream));
2262 if (stream->HasPendingRetransmission()) {
2263 // Connection is write blocked.
2264 break;
2265 } else if (!streams_with_pending_retransmission_.empty() &&
2266 streams_with_pending_retransmission_.begin()->first == id) {
2267 // Retransmit lost data may cause connection close. If this stream
2268 // has not yet sent fin, a RST_STREAM will be sent and it will be
2269 // removed from streams_with_pending_retransmission_.
2270 streams_with_pending_retransmission_.pop_front();
2271 }
2272 } else {
2273 QUIC_BUG << "Try to retransmit data of a closed stream";
2274 streams_with_pending_retransmission_.pop_front();
2275 }
2276 }
2277
2278 return streams_with_pending_retransmission_.empty();
2279}
2280
2281void QuicSession::NeuterUnencryptedData() {
fayangcff885a2019-10-22 07:39:04 -07002282 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
2283 crypto_stream->NeuterUnencryptedStreamData();
2284 if (!crypto_stream->HasPendingRetransmission() &&
2285 !QuicVersionUsesCryptoFrames(transport_version())) {
2286 streams_with_pending_retransmission_.erase(
2287 QuicUtils::GetCryptoStreamId(transport_version()));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002288 }
2289 connection_->NeuterUnencryptedPackets();
2290}
2291
2292void QuicSession::SetTransmissionType(TransmissionType type) {
2293 connection_->SetTransmissionType(type);
2294}
2295
2296MessageResult QuicSession::SendMessage(QuicMemSliceSpan message) {
QUICHE team350e9e62019-11-19 13:16:24 -08002297 return SendMessage(message, /*flush=*/false);
2298}
2299
2300MessageResult QuicSession::SendMessage(QuicMemSliceSpan message, bool flush) {
fayangbb93c602020-02-24 08:31:42 -08002301 DCHECK(connection_->connected())
2302 << ENDPOINT << "Try to write messages when connection is closed.";
QUICHE teama6ef0a62019-03-07 20:34:33 -05002303 if (!IsEncryptionEstablished()) {
2304 return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
2305 }
2306 MessageStatus result =
QUICHE team350e9e62019-11-19 13:16:24 -08002307 connection_->SendMessage(last_message_id_ + 1, message, flush);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002308 if (result == MESSAGE_STATUS_SUCCESS) {
2309 return {result, ++last_message_id_};
2310 }
2311 return {result, 0};
2312}
2313
QUICHE team9467db02019-05-30 09:38:45 -07002314void QuicSession::OnMessageAcked(QuicMessageId message_id,
dschinazi17d42422019-06-18 16:35:07 -07002315 QuicTime /*receive_timestamp*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002316 QUIC_DVLOG(1) << ENDPOINT << "message " << message_id << " gets acked.";
2317}
2318
2319void QuicSession::OnMessageLost(QuicMessageId message_id) {
2320 QUIC_DVLOG(1) << ENDPOINT << "message " << message_id
2321 << " is considered lost";
2322}
2323
2324void QuicSession::CleanUpClosedStreams() {
2325 closed_streams_.clear();
2326}
2327
ianswettb239f862019-04-05 09:15:06 -07002328QuicPacketLength QuicSession::GetCurrentLargestMessagePayload() const {
2329 return connection_->GetCurrentLargestMessagePayload();
2330}
2331
2332QuicPacketLength QuicSession::GetGuaranteedLargestMessagePayload() const {
2333 return connection_->GetGuaranteedLargestMessagePayload();
QUICHE teama6ef0a62019-03-07 20:34:33 -05002334}
2335
bnc187eea32020-09-02 12:16:15 -07002336void QuicSession::SendStopSending(QuicRstStreamErrorCode code,
2337 QuicStreamId stream_id) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002338 control_frame_manager_.WriteOrBufferStopSending(code, stream_id);
2339}
2340
QUICHE teama6ef0a62019-03-07 20:34:33 -05002341QuicStreamId QuicSession::next_outgoing_bidirectional_stream_id() const {
renjietangd1d00852019-09-06 10:43:12 -07002342 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002343 return v99_streamid_manager_.next_outgoing_bidirectional_stream_id();
2344 }
2345 return stream_id_manager_.next_outgoing_stream_id();
2346}
2347
2348QuicStreamId QuicSession::next_outgoing_unidirectional_stream_id() const {
renjietangd1d00852019-09-06 10:43:12 -07002349 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002350 return v99_streamid_manager_.next_outgoing_unidirectional_stream_id();
2351 }
2352 return stream_id_manager_.next_outgoing_stream_id();
2353}
2354
fkastenholz3c4eabf2019-04-22 07:49:59 -07002355bool QuicSession::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
renjietangab9039a2020-03-30 14:53:19 -07002356 const bool allow_new_streams =
2357 frame.unidirectional
2358 ? v99_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
2359 frame.stream_count)
2360 : v99_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
2361 frame.stream_count);
2362 if (allow_new_streams) {
2363 OnCanCreateNewOutgoingStream(frame.unidirectional);
2364 }
2365
2366 return true;
QUICHE teama6ef0a62019-03-07 20:34:33 -05002367}
2368
fkastenholz3c4eabf2019-04-22 07:49:59 -07002369bool QuicSession::OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) {
renjietang7133ea92020-04-01 12:49:36 -07002370 std::string error_details;
2371 if (v99_streamid_manager_.OnStreamsBlockedFrame(frame, &error_details)) {
2372 return true;
2373 }
2374 connection_->CloseConnection(
2375 QUIC_STREAMS_BLOCKED_ERROR, error_details,
2376 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2377 return false;
QUICHE teama6ef0a62019-03-07 20:34:33 -05002378}
2379
2380size_t QuicSession::max_open_incoming_bidirectional_streams() const {
renjietangd1d00852019-09-06 10:43:12 -07002381 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002382 return v99_streamid_manager_.GetMaxAllowdIncomingBidirectionalStreams();
2383 }
2384 return stream_id_manager_.max_open_incoming_streams();
2385}
2386
2387size_t QuicSession::max_open_incoming_unidirectional_streams() const {
renjietangd1d00852019-09-06 10:43:12 -07002388 if (VersionHasIetfQuicFrames(transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002389 return v99_streamid_manager_.GetMaxAllowdIncomingUnidirectionalStreams();
2390 }
2391 return stream_id_manager_.max_open_incoming_streams();
2392}
2393
dmcardlecf0bfcf2019-12-13 08:08:21 -08002394std::vector<quiche::QuicheStringPiece>::const_iterator QuicSession::SelectAlpn(
2395 const std::vector<quiche::QuicheStringPiece>& alpns) const {
vasilvvad7424f2019-08-30 00:27:14 -07002396 const std::string alpn = AlpnForVersion(connection()->version());
2397 return std::find(alpns.cbegin(), alpns.cend(), alpn);
2398}
2399
dmcardlecf0bfcf2019-12-13 08:08:21 -08002400void QuicSession::OnAlpnSelected(quiche::QuicheStringPiece alpn) {
vasilvvad7424f2019-08-30 00:27:14 -07002401 QUIC_DLOG(INFO) << (perspective() == Perspective::IS_SERVER ? "Server: "
2402 : "Client: ")
2403 << "ALPN selected: " << alpn;
2404}
2405
fayangbe7b0752020-04-07 11:27:21 -07002406void QuicSession::NeuterCryptoDataOfEncryptionLevel(EncryptionLevel level) {
2407 GetMutableCryptoStream()->NeuterStreamDataOfEncryptionLevel(level);
2408}
2409
renjietangc621aea2020-07-23 15:56:10 -07002410void QuicSession::PerformActionOnActiveStreams(
2411 std::function<bool(QuicStream*)> action) {
renjietang3e1f5162020-08-04 14:29:41 -07002412 std::vector<QuicStream*> active_streams;
renjietangc621aea2020-07-23 15:56:10 -07002413 for (const auto& it : stream_map_) {
renjietang4c334822020-09-28 15:44:55 -07002414 if (!it.second->is_static() && !it.second->IsZombie()) {
renjietang3e1f5162020-08-04 14:29:41 -07002415 active_streams.push_back(it.second.get());
renjietangc621aea2020-07-23 15:56:10 -07002416 }
2417 }
2418
renjietang3e1f5162020-08-04 14:29:41 -07002419 for (QuicStream* stream : active_streams) {
2420 if (!action(stream)) {
renjietangc621aea2020-07-23 15:56:10 -07002421 return;
2422 }
2423 }
2424}
2425
2426void QuicSession::PerformActionOnActiveStreams(
2427 std::function<bool(QuicStream*)> action) const {
2428 for (const auto& it : stream_map_) {
renjietang4c334822020-09-28 15:44:55 -07002429 if (!it.second->is_static() && !it.second->IsZombie() &&
renjietang647b3cf2020-08-04 13:23:12 -07002430 !action(it.second.get())) {
renjietangc621aea2020-07-23 15:56:10 -07002431 return;
2432 }
2433 }
2434}
2435
QUICHE teama6ef0a62019-03-07 20:34:33 -05002436#undef ENDPOINT // undef for jumbo builds
2437} // namespace quic