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