1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/quic_session.h"
6
7 #include <cstdint>
8 #include <string>
9 #include <utility>
10
11 #include "absl/memory/memory.h"
12 #include "absl/strings/str_cat.h"
13 #include "absl/strings/string_view.h"
14 #include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
15 #include "quiche/quic/core/frames/quic_window_update_frame.h"
16 #include "quiche/quic/core/quic_connection.h"
17 #include "quiche/quic/core/quic_connection_context.h"
18 #include "quiche/quic/core/quic_error_codes.h"
19 #include "quiche/quic/core/quic_flow_controller.h"
20 #include "quiche/quic/core/quic_stream_priority.h"
21 #include "quiche/quic/core/quic_types.h"
22 #include "quiche/quic/core/quic_utils.h"
23 #include "quiche/quic/core/quic_versions.h"
24 #include "quiche/quic/core/quic_write_blocked_list.h"
25 #include "quiche/quic/platform/api/quic_bug_tracker.h"
26 #include "quiche/quic/platform/api/quic_flag_utils.h"
27 #include "quiche/quic/platform/api/quic_flags.h"
28 #include "quiche/quic/platform/api/quic_logging.h"
29 #include "quiche/quic/platform/api/quic_server_stats.h"
30 #include "quiche/quic/platform/api/quic_stack_trace.h"
31 #include "quiche/common/platform/api/quiche_logging.h"
32 #include "quiche/common/quiche_text_utils.h"
33
34 namespace quic {
35
36 namespace {
37
38 class ClosedStreamsCleanUpDelegate : public QuicAlarm::Delegate {
39 public:
ClosedStreamsCleanUpDelegate(QuicSession * session)40 explicit ClosedStreamsCleanUpDelegate(QuicSession* session)
41 : session_(session) {}
42 ClosedStreamsCleanUpDelegate(const ClosedStreamsCleanUpDelegate&) = delete;
43 ClosedStreamsCleanUpDelegate& operator=(const ClosedStreamsCleanUpDelegate&) =
44 delete;
45
GetConnectionContext()46 QuicConnectionContext* GetConnectionContext() override {
47 return (session_->connection() == nullptr)
48 ? nullptr
49 : session_->connection()->context();
50 }
51
OnAlarm()52 void OnAlarm() override { session_->CleanUpClosedStreams(); }
53
54 private:
55 QuicSession* session_;
56 };
57
58 } // namespace
59
60 #define ENDPOINT \
61 (perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
62
QuicSession(QuicConnection * connection,Visitor * owner,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicStreamCount num_expected_unidirectional_static_streams)63 QuicSession::QuicSession(
64 QuicConnection* connection, Visitor* owner, const QuicConfig& config,
65 const ParsedQuicVersionVector& supported_versions,
66 QuicStreamCount num_expected_unidirectional_static_streams)
67 : QuicSession(connection, owner, config, supported_versions,
68 num_expected_unidirectional_static_streams, nullptr) {}
69
QuicSession(QuicConnection * connection,Visitor * owner,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicStreamCount num_expected_unidirectional_static_streams,std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer)70 QuicSession::QuicSession(
71 QuicConnection* connection, Visitor* owner, const QuicConfig& config,
72 const ParsedQuicVersionVector& supported_versions,
73 QuicStreamCount num_expected_unidirectional_static_streams,
74 std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer)
75 : connection_(connection),
76 perspective_(connection->perspective()),
77 visitor_(owner),
78 write_blocked_streams_(std::make_unique<QuicWriteBlockedList>()),
79 config_(config),
80 stream_id_manager_(perspective(), connection->transport_version(),
81 kDefaultMaxStreamsPerConnection,
82 config_.GetMaxBidirectionalStreamsToSend()),
83 ietf_streamid_manager_(perspective(), connection->version(), this, 0,
84 num_expected_unidirectional_static_streams,
85 config_.GetMaxBidirectionalStreamsToSend(),
86 config_.GetMaxUnidirectionalStreamsToSend() +
87 num_expected_unidirectional_static_streams),
88 num_draining_streams_(0),
89 num_outgoing_draining_streams_(0),
90 num_static_streams_(0),
91 num_zombie_streams_(0),
92 flow_controller_(
93 this, QuicUtils::GetInvalidStreamId(connection->transport_version()),
94 /*is_connection_flow_controller*/ true,
95 connection->version().AllowsLowFlowControlLimits()
96 ? 0
97 : kMinimumFlowControlSendWindow,
98 config_.GetInitialSessionFlowControlWindowToSend(),
99 kSessionReceiveWindowLimit, perspective() == Perspective::IS_SERVER,
100 nullptr),
101 currently_writing_stream_id_(0),
102 transport_goaway_sent_(false),
103 transport_goaway_received_(false),
104 control_frame_manager_(this),
105 last_message_id_(0),
106 datagram_queue_(this, std::move(datagram_observer)),
107 closed_streams_clean_up_alarm_(nullptr),
108 supported_versions_(supported_versions),
109 is_configured_(false),
110 was_zero_rtt_rejected_(false),
111 liveness_testing_in_progress_(false) {
112 closed_streams_clean_up_alarm_ =
113 absl::WrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
114 new ClosedStreamsCleanUpDelegate(this)));
115 if (VersionHasIetfQuicFrames(transport_version())) {
116 config_.SetMaxUnidirectionalStreamsToSend(
117 config_.GetMaxUnidirectionalStreamsToSend() +
118 num_expected_unidirectional_static_streams);
119 }
120 }
121
Initialize()122 void QuicSession::Initialize() {
123 connection_->set_visitor(this);
124 connection_->SetSessionNotifier(this);
125 connection_->SetDataProducer(this);
126 connection_->SetUnackedMapInitialCapacity();
127 connection_->SetFromConfig(config_);
128 if (perspective_ == Perspective::IS_CLIENT) {
129 if (config_.HasClientRequestedIndependentOption(kAFFE, perspective_) &&
130 version().HasIetfQuicFrames()) {
131 connection_->set_can_receive_ack_frequency_frame();
132 config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs);
133 }
134 }
135 if (perspective() == Perspective::IS_SERVER &&
136 connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
137 config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
138 }
139
140 connection_->CreateConnectionIdManager();
141
142 // On the server side, version negotiation has been done by the dispatcher,
143 // and the server session is created with the right version.
144 if (perspective() == Perspective::IS_SERVER) {
145 connection_->OnSuccessfulVersionNegotiation();
146 }
147
148 if (QuicVersionUsesCryptoFrames(transport_version())) {
149 return;
150 }
151
152 QUICHE_DCHECK_EQ(QuicUtils::GetCryptoStreamId(transport_version()),
153 GetMutableCryptoStream()->id());
154 }
155
~QuicSession()156 QuicSession::~QuicSession() {
157 if (closed_streams_clean_up_alarm_ != nullptr) {
158 closed_streams_clean_up_alarm_->PermanentCancel();
159 }
160 }
161
PendingStreamOnStreamFrame(const QuicStreamFrame & frame)162 PendingStream* QuicSession::PendingStreamOnStreamFrame(
163 const QuicStreamFrame& frame) {
164 QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
165 QuicStreamId stream_id = frame.stream_id;
166
167 PendingStream* pending = GetOrCreatePendingStream(stream_id);
168
169 if (!pending) {
170 if (frame.fin) {
171 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
172 OnFinalByteOffsetReceived(stream_id, final_byte_offset);
173 }
174 return nullptr;
175 }
176
177 pending->OnStreamFrame(frame);
178 if (!connection()->connected()) {
179 return nullptr;
180 }
181 return pending;
182 }
183
MaybeProcessPendingStream(PendingStream * pending)184 void QuicSession::MaybeProcessPendingStream(PendingStream* pending) {
185 QUICHE_DCHECK(pending != nullptr);
186 QuicStreamId stream_id = pending->id();
187 absl::optional<QuicResetStreamError> stop_sending_error_code =
188 pending->GetStopSendingErrorCode();
189 QuicStream* stream = ProcessPendingStream(pending);
190 if (stream != nullptr) {
191 // The pending stream should now be in the scope of normal streams.
192 QUICHE_DCHECK(IsClosedStream(stream_id) || IsOpenStream(stream_id))
193 << "Stream " << stream_id << " not created";
194 pending_stream_map_.erase(stream_id);
195 if (stop_sending_error_code) {
196 stream->OnStopSending(*stop_sending_error_code);
197 if (!connection()->connected()) {
198 return;
199 }
200 }
201 stream->OnStreamCreatedFromPendingStream();
202 return;
203 }
204 // At this point, none of the bytes has been successfully consumed by the
205 // application layer. We should close the pending stream even if it is
206 // bidirectionl as no application will be able to write in a bidirectional
207 // stream with zero byte as input.
208 if (pending->sequencer()->IsClosed()) {
209 ClosePendingStream(stream_id);
210 }
211 }
212
PendingStreamOnWindowUpdateFrame(const QuicWindowUpdateFrame & frame)213 void QuicSession::PendingStreamOnWindowUpdateFrame(
214 const QuicWindowUpdateFrame& frame) {
215 QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
216 PendingStream* pending = GetOrCreatePendingStream(frame.stream_id);
217 if (pending) {
218 pending->OnWindowUpdateFrame(frame);
219 }
220 }
221
PendingStreamOnStopSendingFrame(const QuicStopSendingFrame & frame)222 void QuicSession::PendingStreamOnStopSendingFrame(
223 const QuicStopSendingFrame& frame) {
224 QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
225 PendingStream* pending = GetOrCreatePendingStream(frame.stream_id);
226 if (pending) {
227 pending->OnStopSending(frame.error());
228 }
229 }
230
OnStreamFrame(const QuicStreamFrame & frame)231 void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
232 QuicStreamId stream_id = frame.stream_id;
233 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
234 connection()->CloseConnection(
235 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
236 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
237 return;
238 }
239
240 if (ShouldProcessFrameByPendingStream(STREAM_FRAME, stream_id)) {
241 PendingStream* pending = PendingStreamOnStreamFrame(frame);
242 if (pending != nullptr && ShouldProcessPendingStreamImmediately()) {
243 MaybeProcessPendingStream(pending);
244 }
245 return;
246 }
247
248 QuicStream* stream = GetOrCreateStream(stream_id);
249
250 if (!stream) {
251 // The stream no longer exists, but we may still be interested in the
252 // final stream byte offset sent by the peer. A frame with a FIN can give
253 // us this offset.
254 if (frame.fin) {
255 QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
256 OnFinalByteOffsetReceived(stream_id, final_byte_offset);
257 }
258 return;
259 }
260 stream->OnStreamFrame(frame);
261 }
262
OnCryptoFrame(const QuicCryptoFrame & frame)263 void QuicSession::OnCryptoFrame(const QuicCryptoFrame& frame) {
264 GetMutableCryptoStream()->OnCryptoFrame(frame);
265 }
266
OnStopSendingFrame(const QuicStopSendingFrame & frame)267 void QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
268 // STOP_SENDING is in IETF QUIC only.
269 QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version()));
270 QUICHE_DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
271
272 QuicStreamId stream_id = frame.stream_id;
273 // If Stream ID is invalid then close the connection.
274 // TODO(ianswett): This check is redundant to checks for IsClosedStream,
275 // but removing it requires removing multiple QUICHE_DCHECKs.
276 // TODO(ianswett): Multiple QUIC_DVLOGs could be QUIC_PEER_BUGs.
277 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
278 QUIC_DVLOG(1) << ENDPOINT
279 << "Received STOP_SENDING with invalid stream_id: "
280 << stream_id << " Closing connection";
281 connection()->CloseConnection(
282 QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for an invalid stream",
283 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
284 return;
285 }
286
287 // If stream_id is READ_UNIDIRECTIONAL, close the connection.
288 if (QuicUtils::GetStreamType(stream_id, perspective(),
289 IsIncomingStream(stream_id),
290 version()) == READ_UNIDIRECTIONAL) {
291 QUIC_DVLOG(1) << ENDPOINT
292 << "Received STOP_SENDING for a read-only stream_id: "
293 << stream_id << ".";
294 connection()->CloseConnection(
295 QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a read-only stream",
296 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
297 return;
298 }
299
300 if (visitor_) {
301 visitor_->OnStopSendingReceived(frame);
302 }
303 if (ShouldProcessFrameByPendingStream(STOP_SENDING_FRAME, stream_id)) {
304 PendingStreamOnStopSendingFrame(frame);
305 return;
306 }
307
308 QuicStream* stream = GetOrCreateStream(stream_id);
309 if (!stream) {
310 // Errors are handled by GetOrCreateStream.
311 return;
312 }
313
314 stream->OnStopSending(frame.error());
315 }
316
OnPacketDecrypted(EncryptionLevel level)317 void QuicSession::OnPacketDecrypted(EncryptionLevel level) {
318 GetMutableCryptoStream()->OnPacketDecrypted(level);
319 if (liveness_testing_in_progress_) {
320 liveness_testing_in_progress_ = false;
321 OnCanCreateNewOutgoingStream(/*unidirectional=*/false);
322 }
323 }
324
OnOneRttPacketAcknowledged()325 void QuicSession::OnOneRttPacketAcknowledged() {
326 GetMutableCryptoStream()->OnOneRttPacketAcknowledged();
327 }
328
OnHandshakePacketSent()329 void QuicSession::OnHandshakePacketSent() {
330 GetMutableCryptoStream()->OnHandshakePacketSent();
331 }
332
333 std::unique_ptr<QuicDecrypter>
AdvanceKeysAndCreateCurrentOneRttDecrypter()334 QuicSession::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
335 return GetMutableCryptoStream()->AdvanceKeysAndCreateCurrentOneRttDecrypter();
336 }
337
CreateCurrentOneRttEncrypter()338 std::unique_ptr<QuicEncrypter> QuicSession::CreateCurrentOneRttEncrypter() {
339 return GetMutableCryptoStream()->CreateCurrentOneRttEncrypter();
340 }
341
PendingStreamOnRstStream(const QuicRstStreamFrame & frame)342 void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
343 QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
344 QuicStreamId stream_id = frame.stream_id;
345
346 PendingStream* pending = GetOrCreatePendingStream(stream_id);
347
348 if (!pending) {
349 HandleRstOnValidNonexistentStream(frame);
350 return;
351 }
352
353 pending->OnRstStreamFrame(frame);
354 // At this point, none of the bytes has been consumed by the application
355 // layer. It is safe to close the pending stream even if it is bidirectionl as
356 // no application will be able to write in a bidirectional stream with zero
357 // byte as input.
358 ClosePendingStream(stream_id);
359 }
360
OnRstStream(const QuicRstStreamFrame & frame)361 void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
362 QuicStreamId stream_id = frame.stream_id;
363 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
364 connection()->CloseConnection(
365 QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
366 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
367 return;
368 }
369
370 if (VersionHasIetfQuicFrames(transport_version()) &&
371 QuicUtils::GetStreamType(stream_id, perspective(),
372 IsIncomingStream(stream_id),
373 version()) == WRITE_UNIDIRECTIONAL) {
374 connection()->CloseConnection(
375 QUIC_INVALID_STREAM_ID, "Received RESET_STREAM for a write-only stream",
376 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
377 return;
378 }
379
380 if (visitor_) {
381 visitor_->OnRstStreamReceived(frame);
382 }
383
384 if (ShouldProcessFrameByPendingStream(RST_STREAM_FRAME, stream_id)) {
385 PendingStreamOnRstStream(frame);
386 return;
387 }
388
389 QuicStream* stream = GetOrCreateStream(stream_id);
390
391 if (!stream) {
392 HandleRstOnValidNonexistentStream(frame);
393 return; // Errors are handled by GetOrCreateStream.
394 }
395 stream->OnStreamReset(frame);
396 }
397
OnGoAway(const QuicGoAwayFrame &)398 void QuicSession::OnGoAway(const QuicGoAwayFrame& /*frame*/) {
399 QUIC_BUG_IF(quic_bug_12435_1, version().UsesHttp3())
400 << "gQUIC GOAWAY received on version " << version();
401
402 transport_goaway_received_ = true;
403 }
404
OnMessageReceived(absl::string_view message)405 void QuicSession::OnMessageReceived(absl::string_view message) {
406 QUIC_DVLOG(1) << ENDPOINT << "Received message of length "
407 << message.length();
408 QUIC_DVLOG(2) << ENDPOINT << "Contents of message of length "
409 << message.length() << ":" << std::endl
410 << quiche::QuicheTextUtils::HexDump(message);
411 }
412
OnHandshakeDoneReceived()413 void QuicSession::OnHandshakeDoneReceived() {
414 QUIC_DVLOG(1) << ENDPOINT << "OnHandshakeDoneReceived";
415 GetMutableCryptoStream()->OnHandshakeDoneReceived();
416 }
417
OnNewTokenReceived(absl::string_view token)418 void QuicSession::OnNewTokenReceived(absl::string_view token) {
419 QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
420 GetMutableCryptoStream()->OnNewTokenReceived(token);
421 }
422
423 // static
RecordConnectionCloseAtServer(QuicErrorCode error,ConnectionCloseSource source)424 void QuicSession::RecordConnectionCloseAtServer(QuicErrorCode error,
425 ConnectionCloseSource source) {
426 if (error != QUIC_NO_ERROR) {
427 if (source == ConnectionCloseSource::FROM_SELF) {
428 QUIC_SERVER_HISTOGRAM_ENUM(
429 "quic_server_connection_close_errors", error, QUIC_LAST_ERROR,
430 "QuicErrorCode for server-closed connections.");
431 } else {
432 QUIC_SERVER_HISTOGRAM_ENUM(
433 "quic_client_connection_close_errors", error, QUIC_LAST_ERROR,
434 "QuicErrorCode for client-closed connections.");
435 }
436 }
437 }
438
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)439 void QuicSession::OnConnectionClosed(const QuicConnectionCloseFrame& frame,
440 ConnectionCloseSource source) {
441 QUICHE_DCHECK(!connection_->connected());
442 if (perspective() == Perspective::IS_SERVER) {
443 RecordConnectionCloseAtServer(frame.quic_error_code, source);
444 }
445
446 if (on_closed_frame_.quic_error_code == QUIC_NO_ERROR) {
447 // Save all of the connection close information
448 on_closed_frame_ = frame;
449 source_ = source;
450 }
451
452 GetMutableCryptoStream()->OnConnectionClosed(frame.quic_error_code, source);
453
454 PerformActionOnActiveStreams([this, frame, source](QuicStream* stream) {
455 QuicStreamId id = stream->id();
456 stream->OnConnectionClosed(frame.quic_error_code, source);
457 auto it = stream_map_.find(id);
458 if (it != stream_map_.end()) {
459 QUIC_BUG_IF(quic_bug_12435_2, !it->second->IsZombie())
460 << ENDPOINT << "Non-zombie stream " << id
461 << " failed to close under OnConnectionClosed";
462 }
463 return true;
464 });
465
466 closed_streams_clean_up_alarm_->Cancel();
467
468 if (visitor_) {
469 visitor_->OnConnectionClosed(connection_->GetOneActiveServerConnectionId(),
470 frame.quic_error_code, frame.error_details,
471 source);
472 }
473 }
474
OnWriteBlocked()475 void QuicSession::OnWriteBlocked() {
476 if (!connection_->connected()) {
477 return;
478 }
479 if (visitor_) {
480 visitor_->OnWriteBlocked(connection_);
481 }
482 }
483
OnSuccessfulVersionNegotiation(const ParsedQuicVersion &)484 void QuicSession::OnSuccessfulVersionNegotiation(
485 const ParsedQuicVersion& /*version*/) {}
486
OnPacketReceived(const QuicSocketAddress &,const QuicSocketAddress & peer_address,bool is_connectivity_probe)487 void QuicSession::OnPacketReceived(const QuicSocketAddress& /*self_address*/,
488 const QuicSocketAddress& peer_address,
489 bool is_connectivity_probe) {
490 if (is_connectivity_probe && perspective() == Perspective::IS_SERVER) {
491 // Server only sends back a connectivity probe after received a
492 // connectivity probe from a new peer address.
493 connection_->SendConnectivityProbingPacket(nullptr, peer_address);
494 }
495 }
496
OnPathDegrading()497 void QuicSession::OnPathDegrading() {}
498
OnForwardProgressMadeAfterPathDegrading()499 void QuicSession::OnForwardProgressMadeAfterPathDegrading() {}
500
AllowSelfAddressChange() const501 bool QuicSession::AllowSelfAddressChange() const { return false; }
502
OnWindowUpdateFrame(const QuicWindowUpdateFrame & frame)503 void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
504 // Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
505 // assume that it still exists.
506 QuicStreamId stream_id = frame.stream_id;
507 if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
508 // This is a window update that applies to the connection, rather than an
509 // individual stream.
510 QUIC_DVLOG(1) << ENDPOINT
511 << "Received connection level flow control window "
512 "update with max data: "
513 << frame.max_data;
514 flow_controller_.UpdateSendWindowOffset(frame.max_data);
515 return;
516 }
517
518 if (VersionHasIetfQuicFrames(transport_version()) &&
519 QuicUtils::GetStreamType(stream_id, perspective(),
520 IsIncomingStream(stream_id),
521 version()) == READ_UNIDIRECTIONAL) {
522 connection()->CloseConnection(
523 QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
524 "WindowUpdateFrame received on READ_UNIDIRECTIONAL stream.",
525 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
526 return;
527 }
528
529 if (ShouldProcessFrameByPendingStream(WINDOW_UPDATE_FRAME, stream_id)) {
530 PendingStreamOnWindowUpdateFrame(frame);
531 return;
532 }
533
534 QuicStream* stream = GetOrCreateStream(stream_id);
535 if (stream != nullptr) {
536 stream->OnWindowUpdateFrame(frame);
537 }
538 }
539
OnBlockedFrame(const QuicBlockedFrame & frame)540 void QuicSession::OnBlockedFrame(const QuicBlockedFrame& frame) {
541 // TODO(rjshade): Compare our flow control receive windows for specified
542 // streams: if we have a large window then maybe something
543 // had gone wrong with the flow control accounting.
544 QUIC_DLOG(INFO) << ENDPOINT << "Received BLOCKED frame with stream id: "
545 << frame.stream_id << ", offset: " << frame.offset;
546 }
547
CheckStreamNotBusyLooping(QuicStream * stream,uint64_t previous_bytes_written,bool previous_fin_sent)548 bool QuicSession::CheckStreamNotBusyLooping(QuicStream* stream,
549 uint64_t previous_bytes_written,
550 bool previous_fin_sent) {
551 if ( // Stream should not be closed.
552 !stream->write_side_closed() &&
553 // Not connection flow control blocked.
554 !flow_controller_.IsBlocked() &&
555 // Detect lack of forward progress.
556 previous_bytes_written == stream->stream_bytes_written() &&
557 previous_fin_sent == stream->fin_sent()) {
558 stream->set_busy_counter(stream->busy_counter() + 1);
559 QUIC_DVLOG(1) << ENDPOINT << "Suspected busy loop on stream id "
560 << stream->id() << " stream_bytes_written "
561 << stream->stream_bytes_written() << " fin "
562 << stream->fin_sent() << " count " << stream->busy_counter();
563 // Wait a few iterations before firing, the exact count is
564 // arbitrary, more than a few to cover a few test-only false
565 // positives.
566 if (stream->busy_counter() > 20) {
567 QUIC_LOG(ERROR) << ENDPOINT << "Detected busy loop on stream id "
568 << stream->id() << " stream_bytes_written "
569 << stream->stream_bytes_written() << " fin "
570 << stream->fin_sent();
571 return false;
572 }
573 } else {
574 stream->set_busy_counter(0);
575 }
576 return true;
577 }
578
CheckStreamWriteBlocked(QuicStream * stream) const579 bool QuicSession::CheckStreamWriteBlocked(QuicStream* stream) const {
580 if (!stream->write_side_closed() && stream->HasBufferedData() &&
581 !stream->IsFlowControlBlocked() &&
582 !write_blocked_streams_->IsStreamBlocked(stream->id())) {
583 QUIC_DLOG(ERROR) << ENDPOINT << "stream " << stream->id()
584 << " has buffered " << stream->BufferedDataBytes()
585 << " bytes, and is not flow control blocked, "
586 "but it is not in the write block list.";
587 return false;
588 }
589 return true;
590 }
591
OnCanWrite()592 void QuicSession::OnCanWrite() {
593 if (connection_->framer().is_processing_packet()) {
594 // Do not write data in the middle of packet processing because rest
595 // frames in the packet may change the data to write. For example, lost
596 // data could be acknowledged. Also, connection is going to emit
597 // OnCanWrite signal post packet processing.
598 QUIC_BUG(session_write_mid_packet_processing)
599 << ENDPOINT << "Try to write mid packet processing.";
600 return;
601 }
602 if (!RetransmitLostData()) {
603 // Cannot finish retransmitting lost data, connection is write blocked.
604 QUIC_DVLOG(1) << ENDPOINT
605 << "Cannot finish retransmitting lost data, connection is "
606 "write blocked.";
607 return;
608 }
609 // We limit the number of writes to the number of pending streams. If more
610 // streams become pending, WillingAndAbleToWrite will be true, which will
611 // cause the connection to request resumption before yielding to other
612 // connections.
613 // If we are connection level flow control blocked, then only allow the
614 // crypto and headers streams to try writing as all other streams will be
615 // blocked.
616 size_t num_writes = flow_controller_.IsBlocked()
617 ? write_blocked_streams_->NumBlockedSpecialStreams()
618 : write_blocked_streams_->NumBlockedStreams();
619 if (num_writes == 0 && !control_frame_manager_.WillingToWrite() &&
620 datagram_queue_.empty() &&
621 (!QuicVersionUsesCryptoFrames(transport_version()) ||
622 !GetCryptoStream()->HasBufferedCryptoFrames())) {
623 return;
624 }
625
626 QuicConnection::ScopedPacketFlusher flusher(connection_);
627 if (QuicVersionUsesCryptoFrames(transport_version())) {
628 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
629 if (crypto_stream->HasBufferedCryptoFrames()) {
630 crypto_stream->WriteBufferedCryptoFrames();
631 }
632 if ((GetQuicReloadableFlag(
633 quic_no_write_control_frame_upon_connection_close) &&
634 !connection_->connected()) ||
635 crypto_stream->HasBufferedCryptoFrames()) {
636 // Cannot finish writing buffered crypto frames, connection is either
637 // write blocked or closed.
638 return;
639 }
640 }
641 if (control_frame_manager_.WillingToWrite()) {
642 control_frame_manager_.OnCanWrite();
643 }
644 if (version().UsesTls() && GetHandshakeState() != HANDSHAKE_CONFIRMED &&
645 connection_->in_probe_time_out()) {
646 QUIC_CODE_COUNT(quic_donot_pto_stream_data_before_handshake_confirmed);
647 // Do not PTO stream data before handshake gets confirmed.
648 return;
649 }
650 // TODO(b/147146815): this makes all datagrams go before stream data. We
651 // should have a better priority scheme for this.
652 if (!datagram_queue_.empty()) {
653 size_t written = datagram_queue_.SendDatagrams();
654 QUIC_DVLOG(1) << ENDPOINT << "Sent " << written << " datagrams";
655 if (!datagram_queue_.empty()) {
656 return;
657 }
658 }
659 std::vector<QuicStreamId> last_writing_stream_ids;
660 for (size_t i = 0; i < num_writes; ++i) {
661 if (!(write_blocked_streams_->HasWriteBlockedSpecialStream() ||
662 write_blocked_streams_->HasWriteBlockedDataStreams())) {
663 // Writing one stream removed another!? Something's broken.
664 QUIC_BUG(quic_bug_10866_1)
665 << "WriteBlockedStream is missing, num_writes: " << num_writes
666 << ", finished_writes: " << i
667 << ", connected: " << connection_->connected()
668 << ", connection level flow control blocked: "
669 << flow_controller_.IsBlocked();
670 for (QuicStreamId id : last_writing_stream_ids) {
671 QUIC_LOG(WARNING) << "last_writing_stream_id: " << id;
672 }
673 connection_->CloseConnection(QUIC_INTERNAL_ERROR,
674 "WriteBlockedStream is missing",
675 ConnectionCloseBehavior::SILENT_CLOSE);
676 return;
677 }
678 if (!CanWriteStreamData()) {
679 return;
680 }
681 currently_writing_stream_id_ = write_blocked_streams_->PopFront();
682 last_writing_stream_ids.push_back(currently_writing_stream_id_);
683 QUIC_DVLOG(1) << ENDPOINT << "Removing stream "
684 << currently_writing_stream_id_ << " from write-blocked list";
685 QuicStream* stream = GetOrCreateStream(currently_writing_stream_id_);
686 if (stream != nullptr && !stream->IsFlowControlBlocked()) {
687 // If the stream can't write all bytes it'll re-add itself to the blocked
688 // list.
689 uint64_t previous_bytes_written = stream->stream_bytes_written();
690 bool previous_fin_sent = stream->fin_sent();
691 QUIC_DVLOG(1) << ENDPOINT << "stream " << stream->id()
692 << " bytes_written " << previous_bytes_written << " fin "
693 << previous_fin_sent;
694 stream->OnCanWrite();
695 QUICHE_DCHECK(CheckStreamWriteBlocked(stream));
696 QUICHE_DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written,
697 previous_fin_sent));
698 }
699 currently_writing_stream_id_ = 0;
700 }
701 }
702
WillingAndAbleToWrite() const703 bool QuicSession::WillingAndAbleToWrite() const {
704 // Schedule a write when:
705 // 1) control frame manager has pending or new control frames, or
706 // 2) any stream has pending retransmissions, or
707 // 3) If the crypto or headers streams are blocked, or
708 // 4) connection is not flow control blocked and there are write blocked
709 // streams.
710 if (QuicVersionUsesCryptoFrames(transport_version())) {
711 if (HasPendingHandshake()) {
712 return true;
713 }
714 if (!IsEncryptionEstablished()) {
715 return false;
716 }
717 }
718 if (control_frame_manager_.WillingToWrite() ||
719 !streams_with_pending_retransmission_.empty()) {
720 return true;
721 }
722 if (flow_controller_.IsBlocked()) {
723 if (VersionUsesHttp3(transport_version())) {
724 return false;
725 }
726 // Crypto and headers streams are not blocked by connection level flow
727 // control.
728 return write_blocked_streams_->HasWriteBlockedSpecialStream();
729 }
730 return write_blocked_streams_->HasWriteBlockedSpecialStream() ||
731 write_blocked_streams_->HasWriteBlockedDataStreams();
732 }
733
GetStreamsInfoForLogging() const734 std::string QuicSession::GetStreamsInfoForLogging() const {
735 std::string info = absl::StrCat(
736 "num_active_streams: ", GetNumActiveStreams(),
737 ", num_pending_streams: ", pending_streams_size(),
738 ", num_outgoing_draining_streams: ", num_outgoing_draining_streams(),
739 " ");
740 // Log info for up to 5 streams.
741 size_t i = 5;
742 for (const auto& it : stream_map_) {
743 if (it.second->is_static()) {
744 continue;
745 }
746 // Calculate the stream creation delay.
747 const QuicTime::Delta delay =
748 connection_->clock()->ApproximateNow() - it.second->creation_time();
749 absl::StrAppend(
750 &info, "{", it.second->id(), ":", delay.ToDebuggingValue(), ";",
751 it.second->stream_bytes_written(), ",", it.second->fin_sent(), ",",
752 it.second->HasBufferedData(), ",", it.second->fin_buffered(), ";",
753 it.second->stream_bytes_read(), ",", it.second->fin_received(), "}");
754 --i;
755 if (i == 0) {
756 break;
757 }
758 }
759 return info;
760 }
761
HasPendingHandshake() const762 bool QuicSession::HasPendingHandshake() const {
763 if (QuicVersionUsesCryptoFrames(transport_version())) {
764 return GetCryptoStream()->HasPendingCryptoRetransmission() ||
765 GetCryptoStream()->HasBufferedCryptoFrames();
766 }
767 return streams_with_pending_retransmission_.contains(
768 QuicUtils::GetCryptoStreamId(transport_version())) ||
769 write_blocked_streams_->IsStreamBlocked(
770 QuicUtils::GetCryptoStreamId(transport_version()));
771 }
772
ProcessUdpPacket(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,const QuicReceivedPacket & packet)773 void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
774 const QuicSocketAddress& peer_address,
775 const QuicReceivedPacket& packet) {
776 QuicConnectionContextSwitcher cs(connection_->context());
777 connection_->ProcessUdpPacket(self_address, peer_address, packet);
778 }
779
on_closed_frame_string() const780 std::string QuicSession::on_closed_frame_string() const {
781 std::stringstream ss;
782 ss << on_closed_frame_;
783 if (source_.has_value()) {
784 ss << " " << ConnectionCloseSourceToString(source_.value());
785 }
786 return ss.str();
787 }
788
WritevData(QuicStreamId id,size_t write_length,QuicStreamOffset offset,StreamSendingState state,TransmissionType type,EncryptionLevel level)789 QuicConsumedData QuicSession::WritevData(QuicStreamId id, size_t write_length,
790 QuicStreamOffset offset,
791 StreamSendingState state,
792 TransmissionType type,
793 EncryptionLevel level) {
794 QUIC_BUG_IF(session writevdata when disconnected, !connection()->connected())
795 << ENDPOINT << "Try to write stream data when connection is closed: "
796 << on_closed_frame_string();
797 if (!IsEncryptionEstablished() &&
798 !QuicUtils::IsCryptoStreamId(transport_version(), id)) {
799 // Do not let streams write without encryption. The calling stream will end
800 // up write blocked until OnCanWrite is next called.
801 if (was_zero_rtt_rejected_ && !OneRttKeysAvailable()) {
802 QUICHE_DCHECK(version().UsesTls() &&
803 perspective() == Perspective::IS_CLIENT);
804 QUIC_DLOG(INFO) << ENDPOINT
805 << "Suppress the write while 0-RTT gets rejected and "
806 "1-RTT keys are not available. Version: "
807 << ParsedQuicVersionToString(version());
808 } else if (version().UsesTls() || perspective() == Perspective::IS_SERVER) {
809 QUIC_BUG(quic_bug_10866_2)
810 << ENDPOINT << "Try to send data of stream " << id
811 << " before encryption is established. Version: "
812 << ParsedQuicVersionToString(version());
813 } else {
814 // In QUIC crypto, this could happen when the client sends full CHLO and
815 // 0-RTT request, then receives an inchoate REJ and sends an inchoate
816 // CHLO. The client then gets the ACK of the inchoate CHLO or the client
817 // gets the full REJ and needs to verify the proof (before it sends the
818 // full CHLO), such that there is no outstanding crypto data.
819 // Retransmission alarm fires in TLP mode which tries to retransmit the
820 // 0-RTT request (without encryption).
821 QUIC_DLOG(INFO) << ENDPOINT << "Try to send data of stream " << id
822 << " before encryption is established.";
823 }
824 return QuicConsumedData(0, false);
825 }
826
827 SetTransmissionType(type);
828 QuicConnection::ScopedEncryptionLevelContext context(connection(), level);
829
830 QuicConsumedData data =
831 connection_->SendStreamData(id, write_length, offset, state);
832 if (type == NOT_RETRANSMISSION) {
833 // This is new stream data.
834 write_blocked_streams_->UpdateBytesForStream(id, data.bytes_consumed);
835 }
836
837 return data;
838 }
839
SendCryptoData(EncryptionLevel level,size_t write_length,QuicStreamOffset offset,TransmissionType type)840 size_t QuicSession::SendCryptoData(EncryptionLevel level, size_t write_length,
841 QuicStreamOffset offset,
842 TransmissionType type) {
843 QUICHE_DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
844 if (!connection()->framer().HasEncrypterOfEncryptionLevel(level)) {
845 const std::string error_details = absl::StrCat(
846 "Try to send crypto data with missing keys of encryption level: ",
847 EncryptionLevelToString(level));
848 QUIC_BUG(quic_bug_10866_3) << ENDPOINT << error_details;
849 connection()->CloseConnection(
850 QUIC_MISSING_WRITE_KEYS, error_details,
851 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
852 return 0;
853 }
854 SetTransmissionType(type);
855 QuicConnection::ScopedEncryptionLevelContext context(connection(), level);
856 const auto bytes_consumed =
857 connection_->SendCryptoData(level, write_length, offset);
858 return bytes_consumed;
859 }
860
OnControlFrameManagerError(QuicErrorCode error_code,std::string error_details)861 void QuicSession::OnControlFrameManagerError(QuicErrorCode error_code,
862 std::string error_details) {
863 connection_->CloseConnection(
864 error_code, error_details,
865 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
866 }
867
WriteControlFrame(const QuicFrame & frame,TransmissionType type)868 bool QuicSession::WriteControlFrame(const QuicFrame& frame,
869 TransmissionType type) {
870 QUIC_BUG_IF(quic_bug_12435_11, !connection()->connected())
871 << ENDPOINT
872 << absl::StrCat("Try to write control frame: ", QuicFrameToString(frame),
873 " when connection is closed: ")
874 << on_closed_frame_string();
875 if (!IsEncryptionEstablished()) {
876 // Suppress the write before encryption gets established.
877 return false;
878 }
879 SetTransmissionType(type);
880 QuicConnection::ScopedEncryptionLevelContext context(
881 connection(), GetEncryptionLevelToSendApplicationData());
882 return connection_->SendControlFrame(frame);
883 }
884
ResetStream(QuicStreamId id,QuicRstStreamErrorCode error)885 void QuicSession::ResetStream(QuicStreamId id, QuicRstStreamErrorCode error) {
886 QuicStream* stream = GetStream(id);
887 if (stream != nullptr && stream->is_static()) {
888 connection()->CloseConnection(
889 QUIC_INVALID_STREAM_ID, "Try to reset a static stream",
890 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
891 return;
892 }
893
894 if (stream != nullptr) {
895 stream->Reset(error);
896 return;
897 }
898
899 QuicConnection::ScopedPacketFlusher flusher(connection());
900 MaybeSendStopSendingFrame(id, QuicResetStreamError::FromInternal(error));
901 MaybeSendRstStreamFrame(id, QuicResetStreamError::FromInternal(error), 0);
902 }
903
MaybeSendRstStreamFrame(QuicStreamId id,QuicResetStreamError error,QuicStreamOffset bytes_written)904 void QuicSession::MaybeSendRstStreamFrame(QuicStreamId id,
905 QuicResetStreamError error,
906 QuicStreamOffset bytes_written) {
907 if (!connection()->connected()) {
908 return;
909 }
910 if (!VersionHasIetfQuicFrames(transport_version()) ||
911 QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id),
912 version()) != READ_UNIDIRECTIONAL) {
913 control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
914 }
915
916 connection_->OnStreamReset(id, error.internal_code());
917 }
918
MaybeSendStopSendingFrame(QuicStreamId id,QuicResetStreamError error)919 void QuicSession::MaybeSendStopSendingFrame(QuicStreamId id,
920 QuicResetStreamError error) {
921 if (!connection()->connected()) {
922 return;
923 }
924 if (VersionHasIetfQuicFrames(transport_version()) &&
925 QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id),
926 version()) != WRITE_UNIDIRECTIONAL) {
927 control_frame_manager_.WriteOrBufferStopSending(error, id);
928 }
929 }
930
SendGoAway(QuicErrorCode error_code,const std::string & reason)931 void QuicSession::SendGoAway(QuicErrorCode error_code,
932 const std::string& reason) {
933 // GOAWAY frame is not supported in IETF QUIC.
934 QUICHE_DCHECK(!VersionHasIetfQuicFrames(transport_version()));
935 if (!IsEncryptionEstablished()) {
936 QUIC_CODE_COUNT(quic_goaway_before_encryption_established);
937 connection_->CloseConnection(
938 error_code, reason,
939 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
940 return;
941 }
942 if (transport_goaway_sent_) {
943 return;
944 }
945 transport_goaway_sent_ = true;
946
947 QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
948 control_frame_manager_.WriteOrBufferGoAway(
949 error_code,
950 QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
951 transport_version()),
952 reason);
953 }
954
SendBlocked(QuicStreamId id,QuicStreamOffset byte_offset)955 void QuicSession::SendBlocked(QuicStreamId id, QuicStreamOffset byte_offset) {
956 control_frame_manager_.WriteOrBufferBlocked(id, byte_offset);
957 }
958
SendWindowUpdate(QuicStreamId id,QuicStreamOffset byte_offset)959 void QuicSession::SendWindowUpdate(QuicStreamId id,
960 QuicStreamOffset byte_offset) {
961 control_frame_manager_.WriteOrBufferWindowUpdate(id, byte_offset);
962 }
963
OnStreamError(QuicErrorCode error_code,std::string error_details)964 void QuicSession::OnStreamError(QuicErrorCode error_code,
965 std::string error_details) {
966 connection_->CloseConnection(
967 error_code, error_details,
968 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
969 }
970
OnStreamError(QuicErrorCode error_code,QuicIetfTransportErrorCodes ietf_error,std::string error_details)971 void QuicSession::OnStreamError(QuicErrorCode error_code,
972 QuicIetfTransportErrorCodes ietf_error,
973 std::string error_details) {
974 connection_->CloseConnection(
975 error_code, ietf_error, error_details,
976 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
977 }
978
SendMaxStreams(QuicStreamCount stream_count,bool unidirectional)979 void QuicSession::SendMaxStreams(QuicStreamCount stream_count,
980 bool unidirectional) {
981 if (!is_configured_) {
982 QUIC_BUG(quic_bug_10866_5)
983 << "Try to send max streams before config negotiated.";
984 return;
985 }
986 control_frame_manager_.WriteOrBufferMaxStreams(stream_count, unidirectional);
987 }
988
InsertLocallyClosedStreamsHighestOffset(const QuicStreamId id,QuicStreamOffset offset)989 void QuicSession::InsertLocallyClosedStreamsHighestOffset(
990 const QuicStreamId id, QuicStreamOffset offset) {
991 locally_closed_streams_highest_offset_[id] = offset;
992 }
993
OnStreamClosed(QuicStreamId stream_id)994 void QuicSession::OnStreamClosed(QuicStreamId stream_id) {
995 QUIC_DVLOG(1) << ENDPOINT << "Closing stream: " << stream_id;
996 StreamMap::iterator it = stream_map_.find(stream_id);
997 if (it == stream_map_.end()) {
998 QUIC_BUG(quic_bug_10866_6)
999 << ENDPOINT << "Stream is already closed: " << stream_id;
1000 return;
1001 }
1002 QuicStream* stream = it->second.get();
1003 StreamType type = stream->type();
1004
1005 const bool stream_waiting_for_acks = stream->IsWaitingForAcks();
1006 if (stream_waiting_for_acks) {
1007 // The stream needs to be kept alive because it's waiting for acks.
1008 ++num_zombie_streams_;
1009 } else {
1010 closed_streams_.push_back(std::move(it->second));
1011 stream_map_.erase(it);
1012 // Do not retransmit data of a closed stream.
1013 streams_with_pending_retransmission_.erase(stream_id);
1014 if (!closed_streams_clean_up_alarm_->IsSet()) {
1015 closed_streams_clean_up_alarm_->Set(
1016 connection_->clock()->ApproximateNow());
1017 }
1018 connection_->QuicBugIfHasPendingFrames(stream_id);
1019 }
1020
1021 if (!stream->HasReceivedFinalOffset()) {
1022 // If we haven't received a FIN or RST for this stream, we need to keep
1023 // track of the how many bytes the stream's flow controller believes it has
1024 // received, for accurate connection level flow control accounting.
1025 // If this is an outgoing stream, it is technically open from peer's
1026 // perspective. Do not inform stream Id manager yet.
1027 QUICHE_DCHECK(!stream->was_draining());
1028 InsertLocallyClosedStreamsHighestOffset(
1029 stream_id, stream->highest_received_byte_offset());
1030 return;
1031 }
1032
1033 const bool stream_was_draining = stream->was_draining();
1034 QUIC_DVLOG_IF(1, stream_was_draining)
1035 << ENDPOINT << "Stream " << stream_id << " was draining";
1036 if (stream_was_draining) {
1037 QUIC_BUG_IF(quic_bug_12435_4, num_draining_streams_ == 0);
1038 --num_draining_streams_;
1039 if (!IsIncomingStream(stream_id)) {
1040 QUIC_BUG_IF(quic_bug_12435_5, num_outgoing_draining_streams_ == 0);
1041 --num_outgoing_draining_streams_;
1042 }
1043 // Stream Id manager has been informed with draining streams.
1044 return;
1045 }
1046 if (!VersionHasIetfQuicFrames(transport_version())) {
1047 stream_id_manager_.OnStreamClosed(
1048 /*is_incoming=*/IsIncomingStream(stream_id));
1049 }
1050 if (!connection_->connected()) {
1051 return;
1052 }
1053 if (IsIncomingStream(stream_id)) {
1054 // Stream Id manager is only interested in peer initiated stream IDs.
1055 if (VersionHasIetfQuicFrames(transport_version())) {
1056 ietf_streamid_manager_.OnStreamClosed(stream_id);
1057 }
1058 return;
1059 }
1060 if (!VersionHasIetfQuicFrames(transport_version())) {
1061 OnCanCreateNewOutgoingStream(type != BIDIRECTIONAL);
1062 }
1063 }
1064
ClosePendingStream(QuicStreamId stream_id)1065 void QuicSession::ClosePendingStream(QuicStreamId stream_id) {
1066 QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
1067 QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version()));
1068 pending_stream_map_.erase(stream_id);
1069 if (connection_->connected()) {
1070 ietf_streamid_manager_.OnStreamClosed(stream_id);
1071 }
1072 }
1073
ShouldProcessFrameByPendingStream(QuicFrameType type,QuicStreamId id) const1074 bool QuicSession::ShouldProcessFrameByPendingStream(QuicFrameType type,
1075 QuicStreamId id) const {
1076 return UsesPendingStreamForFrame(type, id) &&
1077 stream_map_.find(id) == stream_map_.end();
1078 }
1079
OnFinalByteOffsetReceived(QuicStreamId stream_id,QuicStreamOffset final_byte_offset)1080 void QuicSession::OnFinalByteOffsetReceived(
1081 QuicStreamId stream_id, QuicStreamOffset final_byte_offset) {
1082 auto it = locally_closed_streams_highest_offset_.find(stream_id);
1083 if (it == locally_closed_streams_highest_offset_.end()) {
1084 return;
1085 }
1086
1087 QUIC_DVLOG(1) << ENDPOINT << "Received final byte offset "
1088 << final_byte_offset << " for stream " << stream_id;
1089 QuicByteCount offset_diff = final_byte_offset - it->second;
1090 if (flow_controller_.UpdateHighestReceivedOffset(
1091 flow_controller_.highest_received_byte_offset() + offset_diff)) {
1092 // If the final offset violates flow control, close the connection now.
1093 if (flow_controller_.FlowControlViolation()) {
1094 connection_->CloseConnection(
1095 QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
1096 "Connection level flow control violation",
1097 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1098 return;
1099 }
1100 }
1101
1102 flow_controller_.AddBytesConsumed(offset_diff);
1103 locally_closed_streams_highest_offset_.erase(it);
1104 if (!VersionHasIetfQuicFrames(transport_version())) {
1105 stream_id_manager_.OnStreamClosed(
1106 /*is_incoming=*/IsIncomingStream(stream_id));
1107 }
1108 if (IsIncomingStream(stream_id)) {
1109 if (VersionHasIetfQuicFrames(transport_version())) {
1110 ietf_streamid_manager_.OnStreamClosed(stream_id);
1111 }
1112 } else if (!VersionHasIetfQuicFrames(transport_version())) {
1113 OnCanCreateNewOutgoingStream(false);
1114 }
1115 }
1116
IsEncryptionEstablished() const1117 bool QuicSession::IsEncryptionEstablished() const {
1118 if (GetCryptoStream() == nullptr) {
1119 return false;
1120 }
1121 return GetCryptoStream()->encryption_established();
1122 }
1123
OneRttKeysAvailable() const1124 bool QuicSession::OneRttKeysAvailable() const {
1125 if (GetCryptoStream() == nullptr) {
1126 return false;
1127 }
1128 return GetCryptoStream()->one_rtt_keys_available();
1129 }
1130
OnConfigNegotiated()1131 void QuicSession::OnConfigNegotiated() {
1132 // In versions with TLS, the configs will be set twice if 0-RTT is available.
1133 // In the second config setting, 1-RTT keys are guaranteed to be available.
1134 if (version().UsesTls() && is_configured_ &&
1135 connection_->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
1136 QUIC_BUG(quic_bug_12435_6)
1137 << ENDPOINT
1138 << "1-RTT keys missing when config is negotiated for the second time.";
1139 connection_->CloseConnection(
1140 QUIC_INTERNAL_ERROR,
1141 "1-RTT keys missing when config is negotiated for the second time.",
1142 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1143 return;
1144 }
1145
1146 QUIC_DVLOG(1) << ENDPOINT << "OnConfigNegotiated";
1147 connection_->SetFromConfig(config_);
1148
1149 if (VersionHasIetfQuicFrames(transport_version())) {
1150 uint32_t max_streams = 0;
1151 if (config_.HasReceivedMaxBidirectionalStreams()) {
1152 max_streams = config_.ReceivedMaxBidirectionalStreams();
1153 }
1154 if (was_zero_rtt_rejected_ &&
1155 max_streams <
1156 ietf_streamid_manager_.outgoing_bidirectional_stream_count()) {
1157 connection_->CloseConnection(
1158 QUIC_ZERO_RTT_UNRETRANSMITTABLE,
1159 absl::StrCat(
1160 "Server rejected 0-RTT, aborting because new bidirectional "
1161 "initial stream limit ",
1162 max_streams, " is less than current open streams: ",
1163 ietf_streamid_manager_.outgoing_bidirectional_stream_count()),
1164 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1165 return;
1166 }
1167 QUIC_DVLOG(1) << ENDPOINT
1168 << "Setting Bidirectional outgoing_max_streams_ to "
1169 << max_streams;
1170 if (perspective_ == Perspective::IS_CLIENT &&
1171 max_streams <
1172 ietf_streamid_manager_.max_outgoing_bidirectional_streams()) {
1173 connection_->CloseConnection(
1174 was_zero_rtt_rejected_ ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
1175 : QUIC_ZERO_RTT_RESUMPTION_LIMIT_REDUCED,
1176 absl::StrCat(
1177 was_zero_rtt_rejected_
1178 ? "Server rejected 0-RTT, aborting because "
1179 : "",
1180 "new bidirectional limit ", max_streams,
1181 " decreases the current limit: ",
1182 ietf_streamid_manager_.max_outgoing_bidirectional_streams()),
1183 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1184 return;
1185 }
1186 if (ietf_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
1187 max_streams)) {
1188 OnCanCreateNewOutgoingStream(/*unidirectional = */ false);
1189 }
1190
1191 max_streams = 0;
1192 if (config_.HasReceivedMaxUnidirectionalStreams()) {
1193 max_streams = config_.ReceivedMaxUnidirectionalStreams();
1194 }
1195
1196 if (was_zero_rtt_rejected_ &&
1197 max_streams <
1198 ietf_streamid_manager_.outgoing_unidirectional_stream_count()) {
1199 connection_->CloseConnection(
1200 QUIC_ZERO_RTT_UNRETRANSMITTABLE,
1201 absl::StrCat(
1202 "Server rejected 0-RTT, aborting because new unidirectional "
1203 "initial stream limit ",
1204 max_streams, " is less than current open streams: ",
1205 ietf_streamid_manager_.outgoing_unidirectional_stream_count()),
1206 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1207 return;
1208 }
1209
1210 if (max_streams <
1211 ietf_streamid_manager_.max_outgoing_unidirectional_streams()) {
1212 connection_->CloseConnection(
1213 was_zero_rtt_rejected_ ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
1214 : QUIC_ZERO_RTT_RESUMPTION_LIMIT_REDUCED,
1215 absl::StrCat(
1216 was_zero_rtt_rejected_
1217 ? "Server rejected 0-RTT, aborting because "
1218 : "",
1219 "new unidirectional limit ", max_streams,
1220 " decreases the current limit: ",
1221 ietf_streamid_manager_.max_outgoing_unidirectional_streams()),
1222 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1223 return;
1224 }
1225 QUIC_DVLOG(1) << ENDPOINT
1226 << "Setting Unidirectional outgoing_max_streams_ to "
1227 << max_streams;
1228 if (ietf_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
1229 max_streams)) {
1230 OnCanCreateNewOutgoingStream(/*unidirectional = */ true);
1231 }
1232 } else {
1233 uint32_t max_streams = 0;
1234 if (config_.HasReceivedMaxBidirectionalStreams()) {
1235 max_streams = config_.ReceivedMaxBidirectionalStreams();
1236 }
1237 QUIC_DVLOG(1) << ENDPOINT << "Setting max_open_outgoing_streams_ to "
1238 << max_streams;
1239 if (was_zero_rtt_rejected_ &&
1240 max_streams < stream_id_manager_.num_open_outgoing_streams()) {
1241 connection_->CloseConnection(
1242 QUIC_INTERNAL_ERROR,
1243 absl::StrCat(
1244 "Server rejected 0-RTT, aborting because new stream limit ",
1245 max_streams, " is less than current open streams: ",
1246 stream_id_manager_.num_open_outgoing_streams()),
1247 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1248 return;
1249 }
1250 stream_id_manager_.set_max_open_outgoing_streams(max_streams);
1251 }
1252
1253 if (perspective() == Perspective::IS_SERVER) {
1254 if (config_.HasReceivedConnectionOptions()) {
1255 // The following variations change the initial receive flow control
1256 // window sizes.
1257 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW6)) {
1258 AdjustInitialFlowControlWindows(64 * 1024);
1259 }
1260 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW7)) {
1261 AdjustInitialFlowControlWindows(128 * 1024);
1262 }
1263 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW8)) {
1264 AdjustInitialFlowControlWindows(256 * 1024);
1265 }
1266 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFW9)) {
1267 AdjustInitialFlowControlWindows(512 * 1024);
1268 }
1269 if (ContainsQuicTag(config_.ReceivedConnectionOptions(), kIFWA)) {
1270 AdjustInitialFlowControlWindows(1024 * 1024);
1271 }
1272 }
1273
1274 config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
1275 }
1276
1277 if (VersionHasIetfQuicFrames(transport_version())) {
1278 ietf_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
1279 config_.GetMaxBidirectionalStreamsToSend());
1280 ietf_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
1281 config_.GetMaxUnidirectionalStreamsToSend());
1282 } else {
1283 // A small number of additional incoming streams beyond the limit should be
1284 // allowed. This helps avoid early connection termination when FIN/RSTs for
1285 // old streams are lost or arrive out of order.
1286 // Use a minimum number of additional streams, or a percentage increase,
1287 // whichever is larger.
1288 uint32_t max_incoming_streams_to_send =
1289 config_.GetMaxBidirectionalStreamsToSend();
1290 uint32_t max_incoming_streams =
1291 std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
1292 static_cast<uint32_t>(max_incoming_streams_to_send *
1293 kMaxStreamsMultiplier));
1294 stream_id_manager_.set_max_open_incoming_streams(max_incoming_streams);
1295 }
1296
1297 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
1298 // When using IETF-style TLS transport parameters, inform existing streams
1299 // of new flow-control limits.
1300 if (config_.HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional()) {
1301 OnNewStreamOutgoingBidirectionalFlowControlWindow(
1302 config_.ReceivedInitialMaxStreamDataBytesOutgoingBidirectional());
1303 }
1304 if (config_.HasReceivedInitialMaxStreamDataBytesIncomingBidirectional()) {
1305 OnNewStreamIncomingBidirectionalFlowControlWindow(
1306 config_.ReceivedInitialMaxStreamDataBytesIncomingBidirectional());
1307 }
1308 if (config_.HasReceivedInitialMaxStreamDataBytesUnidirectional()) {
1309 OnNewStreamUnidirectionalFlowControlWindow(
1310 config_.ReceivedInitialMaxStreamDataBytesUnidirectional());
1311 }
1312 } else { // The version uses Google QUIC Crypto.
1313 if (config_.HasReceivedInitialStreamFlowControlWindowBytes()) {
1314 // Streams which were created before the SHLO was received (0-RTT
1315 // requests) are now informed of the peer's initial flow control window.
1316 OnNewStreamFlowControlWindow(
1317 config_.ReceivedInitialStreamFlowControlWindowBytes());
1318 }
1319 }
1320
1321 if (config_.HasReceivedInitialSessionFlowControlWindowBytes()) {
1322 OnNewSessionFlowControlWindow(
1323 config_.ReceivedInitialSessionFlowControlWindowBytes());
1324 }
1325
1326 if (perspective_ == Perspective::IS_SERVER && version().HasIetfQuicFrames() &&
1327 connection_->effective_peer_address().IsInitialized()) {
1328 if (config_.HasClientSentConnectionOption(kSPAD, perspective_)) {
1329 quiche::IpAddressFamily address_family =
1330 connection_->effective_peer_address()
1331 .Normalized()
1332 .host()
1333 .address_family();
1334 absl::optional<QuicSocketAddress> preferred_address =
1335 config_.GetPreferredAddressToSend(address_family);
1336 if (preferred_address.has_value()) {
1337 // Set connection ID and token if SPAD has received and a preferred
1338 // address of the same address family is configured.
1339 absl::optional<QuicNewConnectionIdFrame> frame =
1340 connection_->MaybeIssueNewConnectionIdForPreferredAddress();
1341 if (frame.has_value()) {
1342 config_.SetPreferredAddressConnectionIdAndTokenToSend(
1343 frame->connection_id, frame->stateless_reset_token);
1344 }
1345 connection_->set_sent_server_preferred_address(
1346 preferred_address.value());
1347 }
1348 // Clear the alternative address of the other address family in the
1349 // config.
1350 config_.ClearAlternateServerAddressToSend(
1351 address_family == quiche::IpAddressFamily::IP_V4
1352 ? quiche::IpAddressFamily::IP_V6
1353 : quiche::IpAddressFamily::IP_V4);
1354 } else {
1355 // Clear alternative IPv(4|6) addresses in config if the server hasn't
1356 // received 'SPAD' connection option.
1357 config_.ClearAlternateServerAddressToSend(quiche::IpAddressFamily::IP_V4);
1358 config_.ClearAlternateServerAddressToSend(quiche::IpAddressFamily::IP_V6);
1359 }
1360 }
1361
1362 is_configured_ = true;
1363 connection()->OnConfigNegotiated();
1364
1365 // Ask flow controllers to try again since the config could have unblocked us.
1366 // Or if this session is configured on TLS enabled QUIC versions,
1367 // attempt to retransmit 0-RTT data if there's any.
1368 // TODO(fayang): consider removing this OnCanWrite call.
1369 if (!connection_->framer().is_processing_packet() &&
1370 (connection_->version().AllowsLowFlowControlLimits() ||
1371 version().UsesTls())) {
1372 QUIC_CODE_COUNT(quic_session_on_can_write_on_config_negotiated);
1373 OnCanWrite();
1374 }
1375 }
1376
OnAlpsData(const uint8_t *,size_t)1377 absl::optional<std::string> QuicSession::OnAlpsData(
1378 const uint8_t* /*alps_data*/, size_t /*alps_length*/) {
1379 return absl::nullopt;
1380 }
1381
AdjustInitialFlowControlWindows(size_t stream_window)1382 void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
1383 const float session_window_multiplier =
1384 config_.GetInitialStreamFlowControlWindowToSend()
1385 ? static_cast<float>(
1386 config_.GetInitialSessionFlowControlWindowToSend()) /
1387 config_.GetInitialStreamFlowControlWindowToSend()
1388 : 1.5;
1389
1390 QUIC_DVLOG(1) << ENDPOINT << "Set stream receive window to " << stream_window;
1391 config_.SetInitialStreamFlowControlWindowToSend(stream_window);
1392
1393 size_t session_window = session_window_multiplier * stream_window;
1394 QUIC_DVLOG(1) << ENDPOINT << "Set session receive window to "
1395 << session_window;
1396 config_.SetInitialSessionFlowControlWindowToSend(session_window);
1397 flow_controller_.UpdateReceiveWindowSize(session_window);
1398 // Inform all existing streams about the new window.
1399 for (auto const& kv : stream_map_) {
1400 kv.second->UpdateReceiveWindowSize(stream_window);
1401 }
1402 if (!QuicVersionUsesCryptoFrames(transport_version())) {
1403 GetMutableCryptoStream()->UpdateReceiveWindowSize(stream_window);
1404 }
1405 }
1406
HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id)1407 void QuicSession::HandleFrameOnNonexistentOutgoingStream(
1408 QuicStreamId stream_id) {
1409 QUICHE_DCHECK(!IsClosedStream(stream_id));
1410 // Received a frame for a locally-created stream that is not currently
1411 // active. This is an error.
1412 if (VersionHasIetfQuicFrames(transport_version())) {
1413 connection()->CloseConnection(
1414 QUIC_HTTP_STREAM_WRONG_DIRECTION, "Data for nonexistent stream",
1415 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1416 return;
1417 }
1418 connection()->CloseConnection(
1419 QUIC_INVALID_STREAM_ID, "Data for nonexistent stream",
1420 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1421 }
1422
HandleRstOnValidNonexistentStream(const QuicRstStreamFrame & frame)1423 void QuicSession::HandleRstOnValidNonexistentStream(
1424 const QuicRstStreamFrame& frame) {
1425 // If the stream is neither originally in active streams nor created in
1426 // GetOrCreateStream(), it could be a closed stream in which case its
1427 // final received byte offset need to be updated.
1428 if (IsClosedStream(frame.stream_id)) {
1429 // The RST frame contains the final byte offset for the stream: we can now
1430 // update the connection level flow controller if needed.
1431 OnFinalByteOffsetReceived(frame.stream_id, frame.byte_offset);
1432 }
1433 }
1434
OnNewStreamFlowControlWindow(QuicStreamOffset new_window)1435 void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
1436 QUICHE_DCHECK(version().UsesQuicCrypto());
1437 QUIC_DVLOG(1) << ENDPOINT << "OnNewStreamFlowControlWindow " << new_window;
1438 if (new_window < kMinimumFlowControlSendWindow) {
1439 QUIC_LOG_FIRST_N(ERROR, 1)
1440 << "Peer sent us an invalid stream flow control send window: "
1441 << new_window << ", below minimum: " << kMinimumFlowControlSendWindow;
1442 connection_->CloseConnection(
1443 QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
1444 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1445 return;
1446 }
1447
1448 // Inform all existing streams about the new window.
1449 for (auto const& kv : stream_map_) {
1450 QUIC_DVLOG(1) << ENDPOINT << "Informing stream " << kv.first
1451 << " of new stream flow control window " << new_window;
1452 if (!kv.second->MaybeConfigSendWindowOffset(
1453 new_window, /* was_zero_rtt_rejected = */ false)) {
1454 return;
1455 }
1456 }
1457 if (!QuicVersionUsesCryptoFrames(transport_version())) {
1458 QUIC_DVLOG(1)
1459 << ENDPOINT
1460 << "Informing crypto stream of new stream flow control window "
1461 << new_window;
1462 GetMutableCryptoStream()->MaybeConfigSendWindowOffset(
1463 new_window, /* was_zero_rtt_rejected = */ false);
1464 }
1465 }
1466
OnNewStreamUnidirectionalFlowControlWindow(QuicStreamOffset new_window)1467 void QuicSession::OnNewStreamUnidirectionalFlowControlWindow(
1468 QuicStreamOffset new_window) {
1469 QUICHE_DCHECK_EQ(connection_->version().handshake_protocol, PROTOCOL_TLS1_3);
1470 QUIC_DVLOG(1) << ENDPOINT << "OnNewStreamUnidirectionalFlowControlWindow "
1471 << new_window;
1472 // Inform all existing outgoing unidirectional streams about the new window.
1473 for (auto const& kv : stream_map_) {
1474 const QuicStreamId id = kv.first;
1475 if (!version().HasIetfQuicFrames()) {
1476 if (kv.second->type() == BIDIRECTIONAL) {
1477 continue;
1478 }
1479 } else {
1480 if (QuicUtils::IsBidirectionalStreamId(id, version())) {
1481 continue;
1482 }
1483 }
1484 if (!QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1485 perspective())) {
1486 continue;
1487 }
1488 QUIC_DVLOG(1) << ENDPOINT << "Informing unidirectional stream " << id
1489 << " of new stream flow control window " << new_window;
1490 if (!kv.second->MaybeConfigSendWindowOffset(new_window,
1491 was_zero_rtt_rejected_)) {
1492 return;
1493 }
1494 }
1495 }
1496
OnNewStreamOutgoingBidirectionalFlowControlWindow(QuicStreamOffset new_window)1497 void QuicSession::OnNewStreamOutgoingBidirectionalFlowControlWindow(
1498 QuicStreamOffset new_window) {
1499 QUICHE_DCHECK_EQ(connection_->version().handshake_protocol, PROTOCOL_TLS1_3);
1500 QUIC_DVLOG(1) << ENDPOINT
1501 << "OnNewStreamOutgoingBidirectionalFlowControlWindow "
1502 << new_window;
1503 // Inform all existing outgoing bidirectional streams about the new window.
1504 for (auto const& kv : stream_map_) {
1505 const QuicStreamId id = kv.first;
1506 if (!version().HasIetfQuicFrames()) {
1507 if (kv.second->type() != BIDIRECTIONAL) {
1508 continue;
1509 }
1510 } else {
1511 if (!QuicUtils::IsBidirectionalStreamId(id, version())) {
1512 continue;
1513 }
1514 }
1515 if (!QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1516 perspective())) {
1517 continue;
1518 }
1519 QUIC_DVLOG(1) << ENDPOINT << "Informing outgoing bidirectional stream "
1520 << id << " of new stream flow control window " << new_window;
1521 if (!kv.second->MaybeConfigSendWindowOffset(new_window,
1522 was_zero_rtt_rejected_)) {
1523 return;
1524 }
1525 }
1526 }
1527
OnNewStreamIncomingBidirectionalFlowControlWindow(QuicStreamOffset new_window)1528 void QuicSession::OnNewStreamIncomingBidirectionalFlowControlWindow(
1529 QuicStreamOffset new_window) {
1530 QUICHE_DCHECK_EQ(connection_->version().handshake_protocol, PROTOCOL_TLS1_3);
1531 QUIC_DVLOG(1) << ENDPOINT
1532 << "OnNewStreamIncomingBidirectionalFlowControlWindow "
1533 << new_window;
1534 // Inform all existing incoming bidirectional streams about the new window.
1535 for (auto const& kv : stream_map_) {
1536 const QuicStreamId id = kv.first;
1537 if (!version().HasIetfQuicFrames()) {
1538 if (kv.second->type() != BIDIRECTIONAL) {
1539 continue;
1540 }
1541 } else {
1542 if (!QuicUtils::IsBidirectionalStreamId(id, version())) {
1543 continue;
1544 }
1545 }
1546 if (QuicUtils::IsOutgoingStreamId(connection_->version(), id,
1547 perspective())) {
1548 continue;
1549 }
1550 QUIC_DVLOG(1) << ENDPOINT << "Informing incoming bidirectional stream "
1551 << id << " of new stream flow control window " << new_window;
1552 if (!kv.second->MaybeConfigSendWindowOffset(new_window,
1553 was_zero_rtt_rejected_)) {
1554 return;
1555 }
1556 }
1557 }
1558
OnNewSessionFlowControlWindow(QuicStreamOffset new_window)1559 void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
1560 QUIC_DVLOG(1) << ENDPOINT << "OnNewSessionFlowControlWindow " << new_window;
1561
1562 if (was_zero_rtt_rejected_ && new_window < flow_controller_.bytes_sent()) {
1563 std::string error_details = absl::StrCat(
1564 "Server rejected 0-RTT. Aborting because the client received session "
1565 "flow control send window: ",
1566 new_window,
1567 ", which is below currently used: ", flow_controller_.bytes_sent());
1568 QUIC_LOG(ERROR) << error_details;
1569 connection_->CloseConnection(
1570 QUIC_ZERO_RTT_UNRETRANSMITTABLE, error_details,
1571 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1572 return;
1573 }
1574 if (!connection_->version().AllowsLowFlowControlLimits() &&
1575 new_window < kMinimumFlowControlSendWindow) {
1576 std::string error_details = absl::StrCat(
1577 "Peer sent us an invalid session flow control send window: ",
1578 new_window, ", below minimum: ", kMinimumFlowControlSendWindow);
1579 QUIC_LOG_FIRST_N(ERROR, 1) << error_details;
1580 connection_->CloseConnection(
1581 QUIC_FLOW_CONTROL_INVALID_WINDOW, error_details,
1582 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1583 return;
1584 }
1585 if (perspective_ == Perspective::IS_CLIENT &&
1586 new_window < flow_controller_.send_window_offset()) {
1587 // The client receives a lower limit than remembered, violating
1588 // https://tools.ietf.org/html/draft-ietf-quic-transport-27#section-7.3.1
1589 std::string error_details = absl::StrCat(
1590 was_zero_rtt_rejected_ ? "Server rejected 0-RTT, aborting because "
1591 : "",
1592 "new session max data ", new_window,
1593 " decreases current limit: ", flow_controller_.send_window_offset());
1594 QUIC_LOG(ERROR) << error_details;
1595 connection_->CloseConnection(
1596 was_zero_rtt_rejected_ ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
1597 : QUIC_ZERO_RTT_RESUMPTION_LIMIT_REDUCED,
1598 error_details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1599 return;
1600 }
1601
1602 flow_controller_.UpdateSendWindowOffset(new_window);
1603 }
1604
OnNewDecryptionKeyAvailable(EncryptionLevel level,std::unique_ptr<QuicDecrypter> decrypter,bool set_alternative_decrypter,bool latch_once_used)1605 bool QuicSession::OnNewDecryptionKeyAvailable(
1606 EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter,
1607 bool set_alternative_decrypter, bool latch_once_used) {
1608 if (connection_->version().handshake_protocol == PROTOCOL_TLS1_3 &&
1609 !connection()->framer().HasEncrypterOfEncryptionLevel(
1610 QuicUtils::GetEncryptionLevelToSendAckofSpace(
1611 QuicUtils::GetPacketNumberSpace(level)))) {
1612 // This should never happen because connection should never decrypt a packet
1613 // while an ACK for it cannot be encrypted.
1614 return false;
1615 }
1616 if (connection()->version().KnowsWhichDecrypterToUse()) {
1617 connection()->InstallDecrypter(level, std::move(decrypter));
1618 return true;
1619 }
1620 if (set_alternative_decrypter) {
1621 connection()->SetAlternativeDecrypter(level, std::move(decrypter),
1622 latch_once_used);
1623 return true;
1624 }
1625 connection()->SetDecrypter(level, std::move(decrypter));
1626 return true;
1627 }
1628
OnNewEncryptionKeyAvailable(EncryptionLevel level,std::unique_ptr<QuicEncrypter> encrypter)1629 void QuicSession::OnNewEncryptionKeyAvailable(
1630 EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) {
1631 connection()->SetEncrypter(level, std::move(encrypter));
1632 if (connection_->version().handshake_protocol != PROTOCOL_TLS1_3) {
1633 return;
1634 }
1635
1636 bool reset_encryption_level = false;
1637 if (IsEncryptionEstablished() && level == ENCRYPTION_HANDSHAKE) {
1638 // ENCRYPTION_HANDSHAKE keys are only used for the handshake. If
1639 // ENCRYPTION_ZERO_RTT keys exist, it is possible for a client to send
1640 // stream data, which must not be sent at the ENCRYPTION_HANDSHAKE level.
1641 // Therefore, we avoid setting the default encryption level to
1642 // ENCRYPTION_HANDSHAKE.
1643 reset_encryption_level = true;
1644 }
1645 QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to " << level;
1646 connection()->SetDefaultEncryptionLevel(level);
1647 if (reset_encryption_level) {
1648 connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
1649 }
1650 QUIC_BUG_IF(quic_bug_12435_7,
1651 IsEncryptionEstablished() &&
1652 (connection()->encryption_level() == ENCRYPTION_INITIAL ||
1653 connection()->encryption_level() == ENCRYPTION_HANDSHAKE))
1654 << "Encryption is established, but the encryption level " << level
1655 << " does not support sending stream data";
1656 }
1657
SetDefaultEncryptionLevel(EncryptionLevel level)1658 void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
1659 QUICHE_DCHECK_EQ(PROTOCOL_QUIC_CRYPTO,
1660 connection_->version().handshake_protocol);
1661 QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to " << level;
1662 connection()->SetDefaultEncryptionLevel(level);
1663
1664 switch (level) {
1665 case ENCRYPTION_INITIAL:
1666 break;
1667 case ENCRYPTION_ZERO_RTT:
1668 if (perspective() == Perspective::IS_CLIENT) {
1669 // Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since
1670 // they can't be decrypted by the server.
1671 connection_->MarkZeroRttPacketsForRetransmission(0);
1672 if (!connection_->framer().is_processing_packet()) {
1673 // TODO(fayang): consider removing this OnCanWrite call.
1674 // Given any streams blocked by encryption a chance to write.
1675 QUIC_CODE_COUNT(
1676 quic_session_on_can_write_set_default_encryption_level);
1677 OnCanWrite();
1678 }
1679 }
1680 break;
1681 case ENCRYPTION_HANDSHAKE:
1682 break;
1683 case ENCRYPTION_FORWARD_SECURE:
1684 QUIC_BUG_IF(quic_bug_12435_8, !config_.negotiated())
1685 << ENDPOINT << "Handshake confirmed without parameter negotiation.";
1686 connection()->mutable_stats().handshake_completion_time =
1687 connection()->clock()->ApproximateNow();
1688 break;
1689 default:
1690 QUIC_BUG(quic_bug_10866_7) << "Unknown encryption level: " << level;
1691 }
1692 }
1693
OnTlsHandshakeComplete()1694 void QuicSession::OnTlsHandshakeComplete() {
1695 QUICHE_DCHECK_EQ(PROTOCOL_TLS1_3, connection_->version().handshake_protocol);
1696 QUIC_BUG_IF(quic_bug_12435_9,
1697 !GetCryptoStream()->crypto_negotiated_params().cipher_suite)
1698 << ENDPOINT << "Handshake completes without cipher suite negotiation.";
1699 QUIC_BUG_IF(quic_bug_12435_10, !config_.negotiated())
1700 << ENDPOINT << "Handshake completes without parameter negotiation.";
1701 connection()->mutable_stats().handshake_completion_time =
1702 connection()->clock()->ApproximateNow();
1703 if (connection()->version().UsesTls() &&
1704 perspective_ == Perspective::IS_SERVER) {
1705 // Server sends HANDSHAKE_DONE to signal confirmation of the handshake
1706 // to the client.
1707 control_frame_manager_.WriteOrBufferHandshakeDone();
1708 if (connection()->version().HasIetfQuicFrames()) {
1709 MaybeSendAddressToken();
1710 }
1711 }
1712 }
1713
MaybeSendAddressToken()1714 bool QuicSession::MaybeSendAddressToken() {
1715 QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER &&
1716 connection()->version().HasIetfQuicFrames());
1717 absl::optional<CachedNetworkParameters> cached_network_params =
1718 GenerateCachedNetworkParameters();
1719
1720 std::string address_token = GetCryptoStream()->GetAddressToken(
1721 cached_network_params.has_value() ? &cached_network_params.value()
1722 : nullptr);
1723 if (address_token.empty()) {
1724 return false;
1725 }
1726 const size_t buf_len = address_token.length() + 1;
1727 auto buffer = std::make_unique<char[]>(buf_len);
1728 QuicDataWriter writer(buf_len, buffer.get());
1729 // Add |kAddressTokenPrefix| for token sent in NEW_TOKEN frame.
1730 writer.WriteUInt8(kAddressTokenPrefix);
1731 writer.WriteBytes(address_token.data(), address_token.length());
1732 control_frame_manager_.WriteOrBufferNewToken(
1733 absl::string_view(buffer.get(), buf_len));
1734 if (cached_network_params.has_value()) {
1735 connection()->OnSendConnectionState(*cached_network_params);
1736 }
1737 return true;
1738 }
1739
DiscardOldDecryptionKey(EncryptionLevel level)1740 void QuicSession::DiscardOldDecryptionKey(EncryptionLevel level) {
1741 if (!connection()->version().KnowsWhichDecrypterToUse()) {
1742 return;
1743 }
1744 connection()->RemoveDecrypter(level);
1745 }
1746
DiscardOldEncryptionKey(EncryptionLevel level)1747 void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
1748 QUIC_DLOG(INFO) << ENDPOINT << "Discarding " << level << " keys";
1749 if (connection()->version().handshake_protocol == PROTOCOL_TLS1_3) {
1750 connection()->RemoveEncrypter(level);
1751 }
1752 switch (level) {
1753 case ENCRYPTION_INITIAL:
1754 NeuterUnencryptedData();
1755 break;
1756 case ENCRYPTION_HANDSHAKE:
1757 NeuterHandshakeData();
1758 break;
1759 case ENCRYPTION_ZERO_RTT:
1760 break;
1761 case ENCRYPTION_FORWARD_SECURE:
1762 QUIC_BUG(quic_bug_10866_8)
1763 << ENDPOINT << "Discarding 1-RTT keys is not allowed";
1764 break;
1765 default:
1766 QUIC_BUG(quic_bug_10866_9)
1767 << ENDPOINT
1768 << "Cannot discard keys for unknown encryption level: " << level;
1769 }
1770 }
1771
NeuterHandshakeData()1772 void QuicSession::NeuterHandshakeData() {
1773 GetMutableCryptoStream()->NeuterStreamDataOfEncryptionLevel(
1774 ENCRYPTION_HANDSHAKE);
1775 connection()->OnHandshakeComplete();
1776 }
1777
OnZeroRttRejected(int reason)1778 void QuicSession::OnZeroRttRejected(int reason) {
1779 was_zero_rtt_rejected_ = true;
1780 connection_->MarkZeroRttPacketsForRetransmission(reason);
1781 if (connection_->encryption_level() == ENCRYPTION_FORWARD_SECURE) {
1782 QUIC_BUG(quic_bug_10866_10)
1783 << "1-RTT keys already available when 0-RTT is rejected.";
1784 connection_->CloseConnection(
1785 QUIC_INTERNAL_ERROR,
1786 "1-RTT keys already available when 0-RTT is rejected.",
1787 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1788 }
1789 }
1790
FillTransportParameters(TransportParameters * params)1791 bool QuicSession::FillTransportParameters(TransportParameters* params) {
1792 if (version().UsesTls()) {
1793 if (perspective() == Perspective::IS_SERVER) {
1794 config_.SetOriginalConnectionIdToSend(
1795 connection_->GetOriginalDestinationConnectionId());
1796 config_.SetInitialSourceConnectionIdToSend(connection_->connection_id());
1797 } else {
1798 config_.SetInitialSourceConnectionIdToSend(
1799 connection_->client_connection_id());
1800 }
1801 }
1802 return config_.FillTransportParameters(params);
1803 }
1804
ProcessTransportParameters(const TransportParameters & params,bool is_resumption,std::string * error_details)1805 QuicErrorCode QuicSession::ProcessTransportParameters(
1806 const TransportParameters& params, bool is_resumption,
1807 std::string* error_details) {
1808 return config_.ProcessTransportParameters(params, is_resumption,
1809 error_details);
1810 }
1811
OnHandshakeCallbackDone()1812 void QuicSession::OnHandshakeCallbackDone() {
1813 if (!connection_->connected()) {
1814 return;
1815 }
1816
1817 if (!connection()->is_processing_packet()) {
1818 connection()->MaybeProcessUndecryptablePackets();
1819 }
1820 }
1821
PacketFlusherAttached() const1822 bool QuicSession::PacketFlusherAttached() const {
1823 QUICHE_DCHECK(connection_->connected());
1824 return connection()->packet_creator().PacketFlusherAttached();
1825 }
1826
OnCryptoHandshakeMessageSent(const CryptoHandshakeMessage &)1827 void QuicSession::OnCryptoHandshakeMessageSent(
1828 const CryptoHandshakeMessage& /*message*/) {}
1829
OnCryptoHandshakeMessageReceived(const CryptoHandshakeMessage &)1830 void QuicSession::OnCryptoHandshakeMessageReceived(
1831 const CryptoHandshakeMessage& /*message*/) {}
1832
RegisterStreamPriority(QuicStreamId id,bool is_static,const QuicStreamPriority & priority)1833 void QuicSession::RegisterStreamPriority(QuicStreamId id, bool is_static,
1834 const QuicStreamPriority& priority) {
1835 write_blocked_streams()->RegisterStream(id, is_static, priority);
1836 }
1837
UnregisterStreamPriority(QuicStreamId id)1838 void QuicSession::UnregisterStreamPriority(QuicStreamId id) {
1839 write_blocked_streams()->UnregisterStream(id);
1840 }
1841
UpdateStreamPriority(QuicStreamId id,const QuicStreamPriority & new_priority)1842 void QuicSession::UpdateStreamPriority(QuicStreamId id,
1843 const QuicStreamPriority& new_priority) {
1844 write_blocked_streams()->UpdateStreamPriority(id, new_priority);
1845 }
1846
ActivateStream(std::unique_ptr<QuicStream> stream)1847 void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
1848 const bool should_keep_alive = ShouldKeepConnectionAlive();
1849 QuicStreamId stream_id = stream->id();
1850 bool is_static = stream->is_static();
1851 QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
1852 << ". activating stream " << stream_id;
1853 QUICHE_DCHECK(!stream_map_.contains(stream_id));
1854 stream_map_[stream_id] = std::move(stream);
1855 if (is_static) {
1856 ++num_static_streams_;
1857 return;
1858 }
1859 if (!VersionHasIetfQuicFrames(transport_version())) {
1860 // Do not inform stream ID manager of static streams.
1861 stream_id_manager_.ActivateStream(
1862 /*is_incoming=*/IsIncomingStream(stream_id));
1863 }
1864 if (perspective() == Perspective::IS_CLIENT &&
1865 connection()->multi_port_stats() != nullptr && !should_keep_alive &&
1866 ShouldKeepConnectionAlive()) {
1867 connection()->MaybeProbeMultiPortPath();
1868 }
1869 }
1870
GetNextOutgoingBidirectionalStreamId()1871 QuicStreamId QuicSession::GetNextOutgoingBidirectionalStreamId() {
1872 if (VersionHasIetfQuicFrames(transport_version())) {
1873 return ietf_streamid_manager_.GetNextOutgoingBidirectionalStreamId();
1874 }
1875 return stream_id_manager_.GetNextOutgoingStreamId();
1876 }
1877
GetNextOutgoingUnidirectionalStreamId()1878 QuicStreamId QuicSession::GetNextOutgoingUnidirectionalStreamId() {
1879 if (VersionHasIetfQuicFrames(transport_version())) {
1880 return ietf_streamid_manager_.GetNextOutgoingUnidirectionalStreamId();
1881 }
1882 return stream_id_manager_.GetNextOutgoingStreamId();
1883 }
1884
CanOpenNextOutgoingBidirectionalStream()1885 bool QuicSession::CanOpenNextOutgoingBidirectionalStream() {
1886 if (liveness_testing_in_progress_) {
1887 QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective());
1888 QUIC_CODE_COUNT(
1889 quic_client_fails_to_create_stream_liveness_testing_in_progress);
1890 return false;
1891 }
1892 if (!VersionHasIetfQuicFrames(transport_version())) {
1893 if (!stream_id_manager_.CanOpenNextOutgoingStream()) {
1894 return false;
1895 }
1896 } else {
1897 if (!ietf_streamid_manager_.CanOpenNextOutgoingBidirectionalStream()) {
1898 QUIC_CODE_COUNT(
1899 quic_fails_to_create_stream_close_too_many_streams_created);
1900 if (is_configured_) {
1901 // Send STREAM_BLOCKED after config negotiated.
1902 control_frame_manager_.WriteOrBufferStreamsBlocked(
1903 ietf_streamid_manager_.max_outgoing_bidirectional_streams(),
1904 /*unidirectional=*/false);
1905 }
1906 return false;
1907 }
1908 }
1909 if (perspective() == Perspective::IS_CLIENT &&
1910 connection_->MaybeTestLiveness()) {
1911 // Now is relatively close to the idle timeout having the risk that requests
1912 // could be discarded at the server.
1913 liveness_testing_in_progress_ = true;
1914 QUIC_CODE_COUNT(quic_client_fails_to_create_stream_close_to_idle_timeout);
1915 return false;
1916 }
1917 return true;
1918 }
1919
CanOpenNextOutgoingUnidirectionalStream()1920 bool QuicSession::CanOpenNextOutgoingUnidirectionalStream() {
1921 if (!VersionHasIetfQuicFrames(transport_version())) {
1922 return stream_id_manager_.CanOpenNextOutgoingStream();
1923 }
1924 if (ietf_streamid_manager_.CanOpenNextOutgoingUnidirectionalStream()) {
1925 return true;
1926 }
1927 if (is_configured_) {
1928 // Send STREAM_BLOCKED after config negotiated.
1929 control_frame_manager_.WriteOrBufferStreamsBlocked(
1930 ietf_streamid_manager_.max_outgoing_unidirectional_streams(),
1931 /*unidirectional=*/true);
1932 }
1933 return false;
1934 }
1935
GetAdvertisedMaxIncomingBidirectionalStreams() const1936 QuicStreamCount QuicSession::GetAdvertisedMaxIncomingBidirectionalStreams()
1937 const {
1938 QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version()));
1939 return ietf_streamid_manager_.advertised_max_incoming_bidirectional_streams();
1940 }
1941
GetOrCreateStream(const QuicStreamId stream_id)1942 QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
1943 QUICHE_DCHECK(!pending_stream_map_.contains(stream_id));
1944 if (QuicUtils::IsCryptoStreamId(transport_version(), stream_id)) {
1945 return GetMutableCryptoStream();
1946 }
1947
1948 StreamMap::iterator it = stream_map_.find(stream_id);
1949 if (it != stream_map_.end()) {
1950 return it->second->IsZombie() ? nullptr : it->second.get();
1951 }
1952
1953 if (IsClosedStream(stream_id)) {
1954 return nullptr;
1955 }
1956
1957 if (!IsIncomingStream(stream_id)) {
1958 HandleFrameOnNonexistentOutgoingStream(stream_id);
1959 return nullptr;
1960 }
1961
1962 // TODO(fkastenholz): If we are creating a new stream and we have sent a
1963 // goaway, we should ignore the stream creation. Need to add code to A) test
1964 // if goaway was sent ("if (transport_goaway_sent_)") and B) reject stream
1965 // creation ("return nullptr")
1966
1967 if (!MaybeIncreaseLargestPeerStreamId(stream_id)) {
1968 return nullptr;
1969 }
1970
1971 if (!VersionHasIetfQuicFrames(transport_version()) &&
1972 !stream_id_manager_.CanOpenIncomingStream()) {
1973 // Refuse to open the stream.
1974 ResetStream(stream_id, QUIC_REFUSED_STREAM);
1975 return nullptr;
1976 }
1977
1978 return CreateIncomingStream(stream_id);
1979 }
1980
StreamDraining(QuicStreamId stream_id,bool unidirectional)1981 void QuicSession::StreamDraining(QuicStreamId stream_id, bool unidirectional) {
1982 QUICHE_DCHECK(stream_map_.contains(stream_id));
1983 QUIC_DVLOG(1) << ENDPOINT << "Stream " << stream_id << " is draining";
1984 if (VersionHasIetfQuicFrames(transport_version())) {
1985 ietf_streamid_manager_.OnStreamClosed(stream_id);
1986 } else {
1987 stream_id_manager_.OnStreamClosed(
1988 /*is_incoming=*/IsIncomingStream(stream_id));
1989 }
1990 ++num_draining_streams_;
1991 if (!IsIncomingStream(stream_id)) {
1992 ++num_outgoing_draining_streams_;
1993 if (!VersionHasIetfQuicFrames(transport_version())) {
1994 OnCanCreateNewOutgoingStream(unidirectional);
1995 }
1996 }
1997 }
1998
MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id)1999 bool QuicSession::MaybeIncreaseLargestPeerStreamId(
2000 const QuicStreamId stream_id) {
2001 if (VersionHasIetfQuicFrames(transport_version())) {
2002 std::string error_details;
2003 if (ietf_streamid_manager_.MaybeIncreaseLargestPeerStreamId(
2004 stream_id, &error_details)) {
2005 return true;
2006 }
2007 connection()->CloseConnection(
2008 QUIC_INVALID_STREAM_ID, error_details,
2009 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2010 return false;
2011 }
2012 if (!stream_id_manager_.MaybeIncreaseLargestPeerStreamId(stream_id)) {
2013 connection()->CloseConnection(
2014 QUIC_TOO_MANY_AVAILABLE_STREAMS,
2015 absl::StrCat(stream_id, " exceeds available streams ",
2016 stream_id_manager_.MaxAvailableStreams()),
2017 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2018 return false;
2019 }
2020 return true;
2021 }
2022
ShouldYield(QuicStreamId stream_id)2023 bool QuicSession::ShouldYield(QuicStreamId stream_id) {
2024 if (stream_id == currently_writing_stream_id_) {
2025 return false;
2026 }
2027 return write_blocked_streams()->ShouldYield(stream_id);
2028 }
2029
GetOrCreatePendingStream(QuicStreamId stream_id)2030 PendingStream* QuicSession::GetOrCreatePendingStream(QuicStreamId stream_id) {
2031 auto it = pending_stream_map_.find(stream_id);
2032 if (it != pending_stream_map_.end()) {
2033 return it->second.get();
2034 }
2035
2036 if (IsClosedStream(stream_id) ||
2037 !MaybeIncreaseLargestPeerStreamId(stream_id)) {
2038 return nullptr;
2039 }
2040
2041 auto pending = std::make_unique<PendingStream>(stream_id, this);
2042 PendingStream* unowned_pending = pending.get();
2043 pending_stream_map_[stream_id] = std::move(pending);
2044 return unowned_pending;
2045 }
2046
set_largest_peer_created_stream_id(QuicStreamId largest_peer_created_stream_id)2047 void QuicSession::set_largest_peer_created_stream_id(
2048 QuicStreamId largest_peer_created_stream_id) {
2049 QUICHE_DCHECK(!VersionHasIetfQuicFrames(transport_version()));
2050 stream_id_manager_.set_largest_peer_created_stream_id(
2051 largest_peer_created_stream_id);
2052 }
2053
GetLargestPeerCreatedStreamId(bool unidirectional) const2054 QuicStreamId QuicSession::GetLargestPeerCreatedStreamId(
2055 bool unidirectional) const {
2056 // This method is only used in IETF QUIC.
2057 QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version()));
2058 return ietf_streamid_manager_.GetLargestPeerCreatedStreamId(unidirectional);
2059 }
2060
DeleteConnection()2061 void QuicSession::DeleteConnection() {
2062 if (connection_) {
2063 delete connection_;
2064 connection_ = nullptr;
2065 }
2066 }
2067
MaybeSetStreamPriority(QuicStreamId stream_id,const QuicStreamPriority & priority)2068 bool QuicSession::MaybeSetStreamPriority(QuicStreamId stream_id,
2069 const QuicStreamPriority& priority) {
2070 auto active_stream = stream_map_.find(stream_id);
2071 if (active_stream != stream_map_.end()) {
2072 active_stream->second->SetPriority(priority);
2073 return true;
2074 }
2075
2076 return false;
2077 }
2078
IsClosedStream(QuicStreamId id)2079 bool QuicSession::IsClosedStream(QuicStreamId id) {
2080 QUICHE_DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
2081 if (IsOpenStream(id)) {
2082 // Stream is active
2083 return false;
2084 }
2085
2086 if (VersionHasIetfQuicFrames(transport_version())) {
2087 return !ietf_streamid_manager_.IsAvailableStream(id);
2088 }
2089
2090 return !stream_id_manager_.IsAvailableStream(id);
2091 }
2092
IsOpenStream(QuicStreamId id)2093 bool QuicSession::IsOpenStream(QuicStreamId id) {
2094 QUICHE_DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
2095 const StreamMap::iterator it = stream_map_.find(id);
2096 if (it != stream_map_.end()) {
2097 return !it->second->IsZombie();
2098 }
2099 if (pending_stream_map_.contains(id) ||
2100 QuicUtils::IsCryptoStreamId(transport_version(), id)) {
2101 // Stream is active
2102 return true;
2103 }
2104 return false;
2105 }
2106
IsStaticStream(QuicStreamId id) const2107 bool QuicSession::IsStaticStream(QuicStreamId id) const {
2108 auto it = stream_map_.find(id);
2109 if (it == stream_map_.end()) {
2110 return false;
2111 }
2112 return it->second->is_static();
2113 }
2114
GetNumActiveStreams() const2115 size_t QuicSession::GetNumActiveStreams() const {
2116 QUICHE_DCHECK_GE(
2117 static_cast<QuicStreamCount>(stream_map_.size()),
2118 num_static_streams_ + num_draining_streams_ + num_zombie_streams_);
2119 return stream_map_.size() - num_draining_streams_ - num_static_streams_ -
2120 num_zombie_streams_;
2121 }
2122
MarkConnectionLevelWriteBlocked(QuicStreamId id)2123 void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id) {
2124 if (GetOrCreateStream(id) == nullptr) {
2125 QUIC_BUG(quic_bug_10866_11)
2126 << "Marking unknown stream " << id << " blocked.";
2127 QUIC_LOG_FIRST_N(ERROR, 2) << QuicStackTrace();
2128 }
2129
2130 QUIC_DVLOG(1) << ENDPOINT << "Adding stream " << id
2131 << " to write-blocked list";
2132
2133 write_blocked_streams_->AddStream(id);
2134 }
2135
HasDataToWrite() const2136 bool QuicSession::HasDataToWrite() const {
2137 return write_blocked_streams_->HasWriteBlockedSpecialStream() ||
2138 write_blocked_streams_->HasWriteBlockedDataStreams() ||
2139 connection_->HasQueuedData() ||
2140 !streams_with_pending_retransmission_.empty() ||
2141 control_frame_manager_.WillingToWrite();
2142 }
2143
OnAckNeedsRetransmittableFrame()2144 void QuicSession::OnAckNeedsRetransmittableFrame() {
2145 flow_controller_.SendWindowUpdate();
2146 }
2147
SendAckFrequency(const QuicAckFrequencyFrame & frame)2148 void QuicSession::SendAckFrequency(const QuicAckFrequencyFrame& frame) {
2149 control_frame_manager_.WriteOrBufferAckFrequency(frame);
2150 }
2151
SendNewConnectionId(const QuicNewConnectionIdFrame & frame)2152 void QuicSession::SendNewConnectionId(const QuicNewConnectionIdFrame& frame) {
2153 // Count NEW_CONNECTION_ID frames sent to client.
2154 QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 1, 6);
2155 control_frame_manager_.WriteOrBufferNewConnectionId(
2156 frame.connection_id, frame.sequence_number, frame.retire_prior_to,
2157 frame.stateless_reset_token);
2158 }
2159
SendRetireConnectionId(uint64_t sequence_number)2160 void QuicSession::SendRetireConnectionId(uint64_t sequence_number) {
2161 // Count RETIRE_CONNECTION_ID frames sent to client.
2162 QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 2, 6);
2163 control_frame_manager_.WriteOrBufferRetireConnectionId(sequence_number);
2164 }
2165
MaybeReserveConnectionId(const QuicConnectionId & server_connection_id)2166 bool QuicSession::MaybeReserveConnectionId(
2167 const QuicConnectionId& server_connection_id) {
2168 if (visitor_) {
2169 return visitor_->TryAddNewConnectionId(
2170 connection_->GetOneActiveServerConnectionId(), server_connection_id);
2171 }
2172 return true;
2173 }
2174
OnServerConnectionIdRetired(const QuicConnectionId & server_connection_id)2175 void QuicSession::OnServerConnectionIdRetired(
2176 const QuicConnectionId& server_connection_id) {
2177 if (visitor_) {
2178 visitor_->OnConnectionIdRetired(server_connection_id);
2179 }
2180 }
2181
IsConnectionFlowControlBlocked() const2182 bool QuicSession::IsConnectionFlowControlBlocked() const {
2183 return flow_controller_.IsBlocked();
2184 }
2185
IsStreamFlowControlBlocked()2186 bool QuicSession::IsStreamFlowControlBlocked() {
2187 for (auto const& kv : stream_map_) {
2188 if (kv.second->IsFlowControlBlocked()) {
2189 return true;
2190 }
2191 }
2192 if (!QuicVersionUsesCryptoFrames(transport_version()) &&
2193 GetMutableCryptoStream()->IsFlowControlBlocked()) {
2194 return true;
2195 }
2196 return false;
2197 }
2198
MaxAvailableBidirectionalStreams() const2199 size_t QuicSession::MaxAvailableBidirectionalStreams() const {
2200 if (VersionHasIetfQuicFrames(transport_version())) {
2201 return ietf_streamid_manager_.GetMaxAllowdIncomingBidirectionalStreams();
2202 }
2203 return stream_id_manager_.MaxAvailableStreams();
2204 }
2205
MaxAvailableUnidirectionalStreams() const2206 size_t QuicSession::MaxAvailableUnidirectionalStreams() const {
2207 if (VersionHasIetfQuicFrames(transport_version())) {
2208 return ietf_streamid_manager_.GetMaxAllowdIncomingUnidirectionalStreams();
2209 }
2210 return stream_id_manager_.MaxAvailableStreams();
2211 }
2212
IsIncomingStream(QuicStreamId id) const2213 bool QuicSession::IsIncomingStream(QuicStreamId id) const {
2214 if (VersionHasIetfQuicFrames(transport_version())) {
2215 return !QuicUtils::IsOutgoingStreamId(version(), id, perspective_);
2216 }
2217 return stream_id_manager_.IsIncomingStream(id);
2218 }
2219
MaybeCloseZombieStream(QuicStreamId id)2220 void QuicSession::MaybeCloseZombieStream(QuicStreamId id) {
2221 auto it = stream_map_.find(id);
2222 if (it == stream_map_.end()) {
2223 return;
2224 }
2225 --num_zombie_streams_;
2226 closed_streams_.push_back(std::move(it->second));
2227 stream_map_.erase(it);
2228
2229 if (!closed_streams_clean_up_alarm_->IsSet()) {
2230 closed_streams_clean_up_alarm_->Set(connection_->clock()->ApproximateNow());
2231 }
2232 // Do not retransmit data of a closed stream.
2233 streams_with_pending_retransmission_.erase(id);
2234 connection_->QuicBugIfHasPendingFrames(id);
2235 }
2236
GetStream(QuicStreamId id) const2237 QuicStream* QuicSession::GetStream(QuicStreamId id) const {
2238 auto active_stream = stream_map_.find(id);
2239 if (active_stream != stream_map_.end()) {
2240 return active_stream->second.get();
2241 }
2242
2243 if (QuicUtils::IsCryptoStreamId(transport_version(), id)) {
2244 return const_cast<QuicCryptoStream*>(GetCryptoStream());
2245 }
2246
2247 return nullptr;
2248 }
2249
GetActiveStream(QuicStreamId id) const2250 QuicStream* QuicSession::GetActiveStream(QuicStreamId id) const {
2251 auto stream = stream_map_.find(id);
2252 if (stream != stream_map_.end() && !stream->second->is_static()) {
2253 return stream->second.get();
2254 }
2255 return nullptr;
2256 }
2257
OnFrameAcked(const QuicFrame & frame,QuicTime::Delta ack_delay_time,QuicTime receive_timestamp)2258 bool QuicSession::OnFrameAcked(const QuicFrame& frame,
2259 QuicTime::Delta ack_delay_time,
2260 QuicTime receive_timestamp) {
2261 if (frame.type == MESSAGE_FRAME) {
2262 OnMessageAcked(frame.message_frame->message_id, receive_timestamp);
2263 return true;
2264 }
2265 if (frame.type == CRYPTO_FRAME) {
2266 return GetMutableCryptoStream()->OnCryptoFrameAcked(*frame.crypto_frame,
2267 ack_delay_time);
2268 }
2269 if (frame.type != STREAM_FRAME) {
2270 return control_frame_manager_.OnControlFrameAcked(frame);
2271 }
2272 bool new_stream_data_acked = false;
2273 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2274 // Stream can already be reset when sent frame gets acked.
2275 if (stream != nullptr) {
2276 QuicByteCount newly_acked_length = 0;
2277 new_stream_data_acked = stream->OnStreamFrameAcked(
2278 frame.stream_frame.offset, frame.stream_frame.data_length,
2279 frame.stream_frame.fin, ack_delay_time, receive_timestamp,
2280 &newly_acked_length);
2281 if (!stream->HasPendingRetransmission()) {
2282 streams_with_pending_retransmission_.erase(stream->id());
2283 }
2284 }
2285 return new_stream_data_acked;
2286 }
2287
OnStreamFrameRetransmitted(const QuicStreamFrame & frame)2288 void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
2289 QuicStream* stream = GetStream(frame.stream_id);
2290 if (stream == nullptr) {
2291 QUIC_BUG(quic_bug_10866_12)
2292 << "Stream: " << frame.stream_id << " is closed when " << frame
2293 << " is retransmitted.";
2294 connection()->CloseConnection(
2295 QUIC_INTERNAL_ERROR, "Attempt to retransmit frame of a closed stream",
2296 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2297 return;
2298 }
2299 stream->OnStreamFrameRetransmitted(frame.offset, frame.data_length,
2300 frame.fin);
2301 }
2302
OnFrameLost(const QuicFrame & frame)2303 void QuicSession::OnFrameLost(const QuicFrame& frame) {
2304 if (frame.type == MESSAGE_FRAME) {
2305 OnMessageLost(frame.message_frame->message_id);
2306 return;
2307 }
2308 if (frame.type == CRYPTO_FRAME) {
2309 GetMutableCryptoStream()->OnCryptoFrameLost(frame.crypto_frame);
2310 return;
2311 }
2312 if (frame.type != STREAM_FRAME) {
2313 control_frame_manager_.OnControlFrameLost(frame);
2314 return;
2315 }
2316 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2317 if (stream == nullptr) {
2318 return;
2319 }
2320 stream->OnStreamFrameLost(frame.stream_frame.offset,
2321 frame.stream_frame.data_length,
2322 frame.stream_frame.fin);
2323 if (stream->HasPendingRetransmission() &&
2324 !streams_with_pending_retransmission_.contains(
2325 frame.stream_frame.stream_id)) {
2326 streams_with_pending_retransmission_.insert(
2327 std::make_pair(frame.stream_frame.stream_id, true));
2328 }
2329 }
2330
RetransmitFrames(const QuicFrames & frames,TransmissionType type)2331 bool QuicSession::RetransmitFrames(const QuicFrames& frames,
2332 TransmissionType type) {
2333 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
2334 for (const QuicFrame& frame : frames) {
2335 if (frame.type == MESSAGE_FRAME) {
2336 // Do not retransmit MESSAGE frames.
2337 continue;
2338 }
2339 if (frame.type == CRYPTO_FRAME) {
2340 if (!GetMutableCryptoStream()->RetransmitData(frame.crypto_frame, type)) {
2341 return false;
2342 }
2343 continue;
2344 }
2345 if (frame.type != STREAM_FRAME) {
2346 if (!control_frame_manager_.RetransmitControlFrame(frame, type)) {
2347 return false;
2348 }
2349 continue;
2350 }
2351 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2352 if (stream != nullptr &&
2353 !stream->RetransmitStreamData(frame.stream_frame.offset,
2354 frame.stream_frame.data_length,
2355 frame.stream_frame.fin, type)) {
2356 return false;
2357 }
2358 }
2359 return true;
2360 }
2361
IsFrameOutstanding(const QuicFrame & frame) const2362 bool QuicSession::IsFrameOutstanding(const QuicFrame& frame) const {
2363 if (frame.type == MESSAGE_FRAME) {
2364 return false;
2365 }
2366 if (frame.type == CRYPTO_FRAME) {
2367 return GetCryptoStream()->IsFrameOutstanding(
2368 frame.crypto_frame->level, frame.crypto_frame->offset,
2369 frame.crypto_frame->data_length);
2370 }
2371 if (frame.type != STREAM_FRAME) {
2372 return control_frame_manager_.IsControlFrameOutstanding(frame);
2373 }
2374 QuicStream* stream = GetStream(frame.stream_frame.stream_id);
2375 return stream != nullptr &&
2376 stream->IsStreamFrameOutstanding(frame.stream_frame.offset,
2377 frame.stream_frame.data_length,
2378 frame.stream_frame.fin);
2379 }
2380
HasUnackedCryptoData() const2381 bool QuicSession::HasUnackedCryptoData() const {
2382 const QuicCryptoStream* crypto_stream = GetCryptoStream();
2383 return crypto_stream->IsWaitingForAcks() || crypto_stream->HasBufferedData();
2384 }
2385
HasUnackedStreamData() const2386 bool QuicSession::HasUnackedStreamData() const {
2387 for (const auto& it : stream_map_) {
2388 if (it.second->IsWaitingForAcks()) {
2389 return true;
2390 }
2391 }
2392 return false;
2393 }
2394
GetHandshakeState() const2395 HandshakeState QuicSession::GetHandshakeState() const {
2396 return GetCryptoStream()->GetHandshakeState();
2397 }
2398
WriteStreamData(QuicStreamId id,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter * writer)2399 WriteStreamDataResult QuicSession::WriteStreamData(QuicStreamId id,
2400 QuicStreamOffset offset,
2401 QuicByteCount data_length,
2402 QuicDataWriter* writer) {
2403 QuicStream* stream = GetStream(id);
2404 if (stream == nullptr) {
2405 // This causes the connection to be closed because of failed to serialize
2406 // packet.
2407 QUIC_BUG(quic_bug_10866_13)
2408 << "Stream " << id << " does not exist when trying to write data."
2409 << " version:" << transport_version();
2410 return STREAM_MISSING;
2411 }
2412 if (stream->WriteStreamData(offset, data_length, writer)) {
2413 return WRITE_SUCCESS;
2414 }
2415 return WRITE_FAILED;
2416 }
2417
WriteCryptoData(EncryptionLevel level,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter * writer)2418 bool QuicSession::WriteCryptoData(EncryptionLevel level,
2419 QuicStreamOffset offset,
2420 QuicByteCount data_length,
2421 QuicDataWriter* writer) {
2422 return GetMutableCryptoStream()->WriteCryptoFrame(level, offset, data_length,
2423 writer);
2424 }
2425
GetStatelessResetToken() const2426 StatelessResetToken QuicSession::GetStatelessResetToken() const {
2427 return QuicUtils::GenerateStatelessResetToken(connection_->connection_id());
2428 }
2429
CanWriteStreamData() const2430 bool QuicSession::CanWriteStreamData() const {
2431 // Don't write stream data if there are queued data packets.
2432 if (connection_->HasQueuedPackets()) {
2433 return false;
2434 }
2435 // Immediately write handshake data.
2436 if (HasPendingHandshake()) {
2437 return true;
2438 }
2439 return connection_->CanWrite(HAS_RETRANSMITTABLE_DATA);
2440 }
2441
RetransmitLostData()2442 bool QuicSession::RetransmitLostData() {
2443 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
2444 // Retransmit crypto data first.
2445 bool uses_crypto_frames = QuicVersionUsesCryptoFrames(transport_version());
2446 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
2447 if (uses_crypto_frames && crypto_stream->HasPendingCryptoRetransmission()) {
2448 crypto_stream->WritePendingCryptoRetransmission();
2449 }
2450 // Retransmit crypto data in stream 1 frames (version < 47).
2451 if (!uses_crypto_frames &&
2452 streams_with_pending_retransmission_.contains(
2453 QuicUtils::GetCryptoStreamId(transport_version()))) {
2454 // Retransmit crypto data first.
2455 QuicStream* crypto_stream =
2456 GetStream(QuicUtils::GetCryptoStreamId(transport_version()));
2457 crypto_stream->OnCanWrite();
2458 QUICHE_DCHECK(CheckStreamWriteBlocked(crypto_stream));
2459 if (crypto_stream->HasPendingRetransmission()) {
2460 // Connection is write blocked.
2461 return false;
2462 } else {
2463 streams_with_pending_retransmission_.erase(
2464 QuicUtils::GetCryptoStreamId(transport_version()));
2465 }
2466 }
2467 if (control_frame_manager_.HasPendingRetransmission()) {
2468 control_frame_manager_.OnCanWrite();
2469 if (control_frame_manager_.HasPendingRetransmission()) {
2470 return false;
2471 }
2472 }
2473 while (!streams_with_pending_retransmission_.empty()) {
2474 if (!CanWriteStreamData()) {
2475 break;
2476 }
2477 // Retransmit lost data on headers and data streams.
2478 const QuicStreamId id = streams_with_pending_retransmission_.begin()->first;
2479 QuicStream* stream = GetStream(id);
2480 if (stream != nullptr) {
2481 stream->OnCanWrite();
2482 QUICHE_DCHECK(CheckStreamWriteBlocked(stream));
2483 if (stream->HasPendingRetransmission()) {
2484 // Connection is write blocked.
2485 break;
2486 } else if (!streams_with_pending_retransmission_.empty() &&
2487 streams_with_pending_retransmission_.begin()->first == id) {
2488 // Retransmit lost data may cause connection close. If this stream
2489 // has not yet sent fin, a RST_STREAM will be sent and it will be
2490 // removed from streams_with_pending_retransmission_.
2491 streams_with_pending_retransmission_.pop_front();
2492 }
2493 } else {
2494 QUIC_BUG(quic_bug_10866_14)
2495 << "Try to retransmit data of a closed stream";
2496 streams_with_pending_retransmission_.pop_front();
2497 }
2498 }
2499
2500 return streams_with_pending_retransmission_.empty();
2501 }
2502
NeuterUnencryptedData()2503 void QuicSession::NeuterUnencryptedData() {
2504 QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
2505 crypto_stream->NeuterUnencryptedStreamData();
2506 if (!crypto_stream->HasPendingRetransmission() &&
2507 !QuicVersionUsesCryptoFrames(transport_version())) {
2508 streams_with_pending_retransmission_.erase(
2509 QuicUtils::GetCryptoStreamId(transport_version()));
2510 }
2511 connection_->NeuterUnencryptedPackets();
2512 }
2513
SetTransmissionType(TransmissionType type)2514 void QuicSession::SetTransmissionType(TransmissionType type) {
2515 connection_->SetTransmissionType(type);
2516 }
2517
SendMessage(absl::Span<quiche::QuicheMemSlice> message)2518 MessageResult QuicSession::SendMessage(
2519 absl::Span<quiche::QuicheMemSlice> message) {
2520 return SendMessage(message, /*flush=*/false);
2521 }
2522
SendMessage(quiche::QuicheMemSlice message)2523 MessageResult QuicSession::SendMessage(quiche::QuicheMemSlice message) {
2524 return SendMessage(absl::MakeSpan(&message, 1), /*flush=*/false);
2525 }
2526
SendMessage(absl::Span<quiche::QuicheMemSlice> message,bool flush)2527 MessageResult QuicSession::SendMessage(
2528 absl::Span<quiche::QuicheMemSlice> message, bool flush) {
2529 QUICHE_DCHECK(connection_->connected())
2530 << ENDPOINT << "Try to write messages when connection is closed.";
2531 if (!IsEncryptionEstablished()) {
2532 return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
2533 }
2534 QuicConnection::ScopedEncryptionLevelContext context(
2535 connection(), GetEncryptionLevelToSendApplicationData());
2536 MessageStatus result =
2537 connection_->SendMessage(last_message_id_ + 1, message, flush);
2538 if (result == MESSAGE_STATUS_SUCCESS) {
2539 return {result, ++last_message_id_};
2540 }
2541 return {result, 0};
2542 }
2543
OnMessageAcked(QuicMessageId message_id,QuicTime)2544 void QuicSession::OnMessageAcked(QuicMessageId message_id,
2545 QuicTime /*receive_timestamp*/) {
2546 QUIC_DVLOG(1) << ENDPOINT << "message " << message_id << " gets acked.";
2547 }
2548
OnMessageLost(QuicMessageId message_id)2549 void QuicSession::OnMessageLost(QuicMessageId message_id) {
2550 QUIC_DVLOG(1) << ENDPOINT << "message " << message_id
2551 << " is considered lost";
2552 }
2553
CleanUpClosedStreams()2554 void QuicSession::CleanUpClosedStreams() { closed_streams_.clear(); }
2555
GetCurrentLargestMessagePayload() const2556 QuicPacketLength QuicSession::GetCurrentLargestMessagePayload() const {
2557 return connection_->GetCurrentLargestMessagePayload();
2558 }
2559
GetGuaranteedLargestMessagePayload() const2560 QuicPacketLength QuicSession::GetGuaranteedLargestMessagePayload() const {
2561 return connection_->GetGuaranteedLargestMessagePayload();
2562 }
2563
next_outgoing_bidirectional_stream_id() const2564 QuicStreamId QuicSession::next_outgoing_bidirectional_stream_id() const {
2565 if (VersionHasIetfQuicFrames(transport_version())) {
2566 return ietf_streamid_manager_.next_outgoing_bidirectional_stream_id();
2567 }
2568 return stream_id_manager_.next_outgoing_stream_id();
2569 }
2570
next_outgoing_unidirectional_stream_id() const2571 QuicStreamId QuicSession::next_outgoing_unidirectional_stream_id() const {
2572 if (VersionHasIetfQuicFrames(transport_version())) {
2573 return ietf_streamid_manager_.next_outgoing_unidirectional_stream_id();
2574 }
2575 return stream_id_manager_.next_outgoing_stream_id();
2576 }
2577
OnMaxStreamsFrame(const QuicMaxStreamsFrame & frame)2578 bool QuicSession::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
2579 const bool allow_new_streams =
2580 frame.unidirectional
2581 ? ietf_streamid_manager_.MaybeAllowNewOutgoingUnidirectionalStreams(
2582 frame.stream_count)
2583 : ietf_streamid_manager_.MaybeAllowNewOutgoingBidirectionalStreams(
2584 frame.stream_count);
2585 if (allow_new_streams) {
2586 OnCanCreateNewOutgoingStream(frame.unidirectional);
2587 }
2588
2589 return true;
2590 }
2591
OnStreamsBlockedFrame(const QuicStreamsBlockedFrame & frame)2592 bool QuicSession::OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) {
2593 std::string error_details;
2594 if (ietf_streamid_manager_.OnStreamsBlockedFrame(frame, &error_details)) {
2595 return true;
2596 }
2597 connection_->CloseConnection(
2598 QUIC_STREAMS_BLOCKED_ERROR, error_details,
2599 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2600 return false;
2601 }
2602
max_open_incoming_bidirectional_streams() const2603 size_t QuicSession::max_open_incoming_bidirectional_streams() const {
2604 if (VersionHasIetfQuicFrames(transport_version())) {
2605 return ietf_streamid_manager_.GetMaxAllowdIncomingBidirectionalStreams();
2606 }
2607 return stream_id_manager_.max_open_incoming_streams();
2608 }
2609
max_open_incoming_unidirectional_streams() const2610 size_t QuicSession::max_open_incoming_unidirectional_streams() const {
2611 if (VersionHasIetfQuicFrames(transport_version())) {
2612 return ietf_streamid_manager_.GetMaxAllowdIncomingUnidirectionalStreams();
2613 }
2614 return stream_id_manager_.max_open_incoming_streams();
2615 }
2616
SelectAlpn(const std::vector<absl::string_view> & alpns) const2617 std::vector<absl::string_view>::const_iterator QuicSession::SelectAlpn(
2618 const std::vector<absl::string_view>& alpns) const {
2619 const std::string alpn = AlpnForVersion(connection()->version());
2620 return std::find(alpns.cbegin(), alpns.cend(), alpn);
2621 }
2622
OnAlpnSelected(absl::string_view alpn)2623 void QuicSession::OnAlpnSelected(absl::string_view alpn) {
2624 QUIC_DLOG(INFO) << (perspective() == Perspective::IS_SERVER ? "Server: "
2625 : "Client: ")
2626 << "ALPN selected: " << alpn;
2627 }
2628
NeuterCryptoDataOfEncryptionLevel(EncryptionLevel level)2629 void QuicSession::NeuterCryptoDataOfEncryptionLevel(EncryptionLevel level) {
2630 GetMutableCryptoStream()->NeuterStreamDataOfEncryptionLevel(level);
2631 }
2632
PerformActionOnActiveStreams(std::function<bool (QuicStream *)> action)2633 void QuicSession::PerformActionOnActiveStreams(
2634 std::function<bool(QuicStream*)> action) {
2635 std::vector<QuicStream*> active_streams;
2636 for (const auto& it : stream_map_) {
2637 if (!it.second->is_static() && !it.second->IsZombie()) {
2638 active_streams.push_back(it.second.get());
2639 }
2640 }
2641
2642 for (QuicStream* stream : active_streams) {
2643 if (!action(stream)) {
2644 return;
2645 }
2646 }
2647 }
2648
PerformActionOnActiveStreams(std::function<bool (QuicStream *)> action) const2649 void QuicSession::PerformActionOnActiveStreams(
2650 std::function<bool(QuicStream*)> action) const {
2651 for (const auto& it : stream_map_) {
2652 if (!it.second->is_static() && !it.second->IsZombie() &&
2653 !action(it.second.get())) {
2654 return;
2655 }
2656 }
2657 }
2658
GetEncryptionLevelToSendApplicationData() const2659 EncryptionLevel QuicSession::GetEncryptionLevelToSendApplicationData() const {
2660 return connection_->framer().GetEncryptionLevelToSendApplicationData();
2661 }
2662
ProcessAllPendingStreams()2663 void QuicSession::ProcessAllPendingStreams() {
2664 std::vector<PendingStream*> pending_streams;
2665 pending_streams.reserve(pending_stream_map_.size());
2666 for (auto it = pending_stream_map_.cbegin(); it != pending_stream_map_.cend();
2667 ++it) {
2668 pending_streams.push_back(it->second.get());
2669 }
2670 for (auto* pending_stream : pending_streams) {
2671 MaybeProcessPendingStream(pending_stream);
2672 if (!connection()->connected()) {
2673 return;
2674 }
2675 }
2676 }
2677
ValidatePath(std::unique_ptr<QuicPathValidationContext> context,std::unique_ptr<QuicPathValidator::ResultDelegate> result_delegate,PathValidationReason reason)2678 void QuicSession::ValidatePath(
2679 std::unique_ptr<QuicPathValidationContext> context,
2680 std::unique_ptr<QuicPathValidator::ResultDelegate> result_delegate,
2681 PathValidationReason reason) {
2682 connection_->ValidatePath(std::move(context), std::move(result_delegate),
2683 reason);
2684 }
2685
HasPendingPathValidation() const2686 bool QuicSession::HasPendingPathValidation() const {
2687 return connection_->HasPendingPathValidation();
2688 }
2689
MigratePath(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,QuicPacketWriter * writer,bool owns_writer)2690 bool QuicSession::MigratePath(const QuicSocketAddress& self_address,
2691 const QuicSocketAddress& peer_address,
2692 QuicPacketWriter* writer, bool owns_writer) {
2693 return connection_->MigratePath(self_address, peer_address, writer,
2694 owns_writer);
2695 }
2696
ValidateToken(absl::string_view token)2697 bool QuicSession::ValidateToken(absl::string_view token) {
2698 QUICHE_DCHECK_EQ(perspective_, Perspective::IS_SERVER);
2699 if (GetQuicFlag(quic_reject_retry_token_in_initial_packet)) {
2700 return false;
2701 }
2702 if (token.empty() || token[0] != kAddressTokenPrefix) {
2703 // Validate the prefix for token received in NEW_TOKEN frame.
2704 return false;
2705 }
2706 const bool valid = GetCryptoStream()->ValidateAddressToken(
2707 absl::string_view(token.data() + 1, token.length() - 1));
2708 if (valid) {
2709 const CachedNetworkParameters* cached_network_params =
2710 GetCryptoStream()->PreviousCachedNetworkParams();
2711 if (cached_network_params != nullptr &&
2712 cached_network_params->timestamp() > 0) {
2713 connection()->OnReceiveConnectionState(*cached_network_params);
2714 }
2715 }
2716 return valid;
2717 }
2718
OnServerPreferredAddressAvailable(const QuicSocketAddress & server_preferred_address)2719 void QuicSession::OnServerPreferredAddressAvailable(
2720 const QuicSocketAddress& server_preferred_address) {
2721 QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
2722 if (visitor_ != nullptr) {
2723 visitor_->OnServerPreferredAddressAvailable(server_preferred_address);
2724 }
2725 }
2726
2727 #undef ENDPOINT // undef for jumbo builds
2728 } // namespace quic
2729