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