blob: b8187374dd2a2cd22524c403b54923f27abadd08 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// A QuicSession, which demuxes a single connection to individual streams.
6
7#ifndef QUICHE_QUIC_CORE_QUIC_SESSION_H_
8#define QUICHE_QUIC_CORE_QUIC_SESSION_H_
9
10#include <cstddef>
renjietang216dc012019-08-27 11:28:27 -070011#include <cstdint>
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include <map>
13#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -070014#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050015#include <vector>
16
fayangd58736d2019-11-27 13:35:31 -080017#include "net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050018#include "net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h"
19#include "net/third_party/quiche/src/quic/core/quic_connection.h"
20#include "net/third_party/quiche/src/quic/core/quic_control_frame_manager.h"
21#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
wub2b5942f2019-04-11 13:22:50 -070022#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
24#include "net/third_party/quiche/src/quic/core/quic_packets.h"
25#include "net/third_party/quiche/src/quic/core/quic_stream.h"
26#include "net/third_party/quiche/src/quic/core/quic_stream_frame_data_producer.h"
renjietang686ce582019-10-17 14:28:16 -070027#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050028#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
29#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
30#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
31#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
32#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
33#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080034#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050035
36namespace quic {
37
38class QuicCryptoStream;
39class QuicFlowController;
40class QuicStream;
41class QuicStreamIdManager;
42
43namespace test {
44class QuicSessionPeer;
45} // namespace test
46
rcha8b56e42019-09-20 10:41:48 -070047class QUIC_EXPORT_PRIVATE QuicSession
48 : public QuicConnectionVisitorInterface,
49 public SessionNotifierInterface,
50 public QuicStreamFrameDataProducer,
fayangd58736d2019-11-27 13:35:31 -080051 public QuicStreamIdManager::DelegateInterface,
52 public HandshakerDelegateInterface {
QUICHE teama6ef0a62019-03-07 20:34:33 -050053 public:
54 // An interface from the session to the entity owning the session.
55 // This lets the session notify its owner (the Dispatcher) when the connection
56 // is closed, blocked, or added/removed from the time-wait list.
dschinazif25169a2019-10-23 08:12:18 -070057 class QUIC_EXPORT_PRIVATE Visitor {
QUICHE teama6ef0a62019-03-07 20:34:33 -050058 public:
59 virtual ~Visitor() {}
60
61 // Called when the connection is closed after the streams have been closed.
dschinazi7b9278c2019-05-20 07:36:21 -070062 virtual void OnConnectionClosed(QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -070064 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050065 ConnectionCloseSource source) = 0;
66
67 // Called when the session has become write blocked.
68 virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) = 0;
69
70 // Called when the session receives reset on a stream from the peer.
71 virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0;
72
73 // Called when the session receives a STOP_SENDING for a stream from the
74 // peer.
75 virtual void OnStopSendingReceived(const QuicStopSendingFrame& frame) = 0;
76 };
77
78 // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream.
fayangfa3b1d62019-11-18 08:02:13 -080079 // TODO(fayang): Replace this enum and with HandshakeState.
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 enum CryptoHandshakeEvent {
renjietangea71d6f2019-08-19 12:22:28 -070081 // ENCRYPTION_ESTABLISHED indicates that a client hello has been sent and
82 // subsequent packets will be encrypted. (Client only.)
83 ENCRYPTION_ESTABLISHED,
QUICHE teama6ef0a62019-03-07 20:34:33 -050084 // HANDSHAKE_CONFIRMED, in a client, indicates the server has accepted
85 // our handshake. In a server it indicates that a full, valid client hello
86 // has been received. (Client and server.)
87 HANDSHAKE_CONFIRMED,
88 };
89
90 // Does not take ownership of |connection| or |visitor|.
91 QuicSession(QuicConnection* connection,
92 Visitor* owner,
93 const QuicConfig& config,
renjietang216dc012019-08-27 11:28:27 -070094 const ParsedQuicVersionVector& supported_versions,
95 QuicStreamCount num_expected_unidirectional_static_streams);
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 QuicSession(const QuicSession&) = delete;
97 QuicSession& operator=(const QuicSession&) = delete;
98
99 ~QuicSession() override;
100
101 virtual void Initialize();
102
103 // QuicConnectionVisitorInterface methods:
104 void OnStreamFrame(const QuicStreamFrame& frame) override;
105 void OnCryptoFrame(const QuicCryptoFrame& frame) override;
106 void OnRstStream(const QuicRstStreamFrame& frame) override;
107 void OnGoAway(const QuicGoAwayFrame& frame) override;
dmcardlecf0bfcf2019-12-13 08:08:21 -0800108 void OnMessageReceived(quiche::QuicheStringPiece message) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500109 void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
110 void OnBlockedFrame(const QuicBlockedFrame& frame) override;
fkastenholz5d880a92019-06-21 09:01:56 -0700111 void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500112 ConnectionCloseSource source) override;
113 void OnWriteBlocked() override;
114 void OnSuccessfulVersionNegotiation(
115 const ParsedQuicVersion& version) override;
zhongyi83161e42019-08-19 09:06:25 -0700116 void OnPacketReceived(const QuicSocketAddress& self_address,
117 const QuicSocketAddress& peer_address,
118 bool is_connectivity_probe) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 void OnCanWrite() override;
QUICHE teamb8343252019-04-29 13:58:01 -0700120 bool SendProbingData() override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 void OnCongestionWindowChange(QuicTime /*now*/) override {}
dschinazi17d42422019-06-18 16:35:07 -0700122 void OnConnectionMigration(AddressChangeType /*type*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 // Adds a connection level WINDOW_UPDATE frame.
124 void OnAckNeedsRetransmittableFrame() override;
125 void SendPing() override;
126 bool WillingAndAbleToWrite() const override;
127 bool HasPendingHandshake() const override;
128 void OnPathDegrading() override;
129 bool AllowSelfAddressChange() const override;
130 void OnForwardProgressConfirmed() override;
fkastenholz3c4eabf2019-04-22 07:49:59 -0700131 bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
132 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
renjietangeab918f2019-10-28 12:10:32 -0700133 void OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
fayangd58736d2019-11-27 13:35:31 -0800134 void OnPacketDecrypted(EncryptionLevel level) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135
136 // QuicStreamFrameDataProducer
137 WriteStreamDataResult WriteStreamData(QuicStreamId id,
138 QuicStreamOffset offset,
139 QuicByteCount data_length,
140 QuicDataWriter* writer) override;
141 bool WriteCryptoData(EncryptionLevel level,
142 QuicStreamOffset offset,
143 QuicByteCount data_length,
144 QuicDataWriter* writer) override;
145
146 // SessionNotifierInterface methods:
147 bool OnFrameAcked(const QuicFrame& frame,
QUICHE team9467db02019-05-30 09:38:45 -0700148 QuicTime::Delta ack_delay_time,
149 QuicTime receive_timestamp) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150 void OnStreamFrameRetransmitted(const QuicStreamFrame& frame) override;
151 void OnFrameLost(const QuicFrame& frame) override;
152 void RetransmitFrames(const QuicFrames& frames,
153 TransmissionType type) override;
154 bool IsFrameOutstanding(const QuicFrame& frame) const override;
155 bool HasUnackedCryptoData() const override;
zhongyi1b2f7832019-06-14 13:31:34 -0700156 bool HasUnackedStreamData() const override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157
rcha8b56e42019-09-20 10:41:48 -0700158 // QuicStreamIdManager::DelegateInterface methods:
159 void OnError(QuicErrorCode error_code, std::string error_details) override;
160 void SendMaxStreams(QuicStreamCount stream_count,
161 bool unidirectional) override;
162 void SendStreamsBlocked(QuicStreamCount stream_count,
163 bool unidirectional) override;
164 // The default implementation does nothing. Subclasses should override if
165 // for example they queue up stream requests.
166 void OnCanCreateNewOutgoingStream(bool unidirectional) override;
167
QUICHE teama6ef0a62019-03-07 20:34:33 -0500168 // Called on every incoming packet. Passes |packet| through to |connection_|.
169 virtual void ProcessUdpPacket(const QuicSocketAddress& self_address,
170 const QuicSocketAddress& peer_address,
171 const QuicReceivedPacket& packet);
172
173 // Called by streams when they want to write data to the peer.
174 // Returns a pair with the number of bytes consumed from data, and a boolean
175 // indicating if the fin bit was consumed. This does not indicate the data
176 // has been sent on the wire: it may have been turned into a packet and queued
177 // if the socket was unexpectedly blocked.
178 virtual QuicConsumedData WritevData(QuicStream* stream,
179 QuicStreamId id,
180 size_t write_length,
181 QuicStreamOffset offset,
182 StreamSendingState state);
183
184 // Called by application to send |message|. Data copy can be avoided if
185 // |message| is provided in reference counted memory.
186 // Please note, |message| provided in reference counted memory would be moved
187 // internally when message is successfully sent. Thereafter, it would be
188 // undefined behavior if callers try to access the slices through their own
189 // copy of the span object.
190 // Returns the message result which includes the message status and message ID
191 // (valid if the write succeeds). SendMessage flushes a message packet even it
192 // is not full. If the application wants to bundle other data in the same
193 // packet, please consider adding a packet flusher around the SendMessage
194 // and/or WritevData calls.
195 //
196 // OnMessageAcked and OnMessageLost are called when a particular message gets
197 // acked or lost.
198 //
199 // Note that SendMessage will fail with status = MESSAGE_STATUS_BLOCKED
200 // if connection is congestion control blocked or underlying socket is write
201 // blocked. In this case the caller can retry sending message again when
202 // connection becomes available, for example after getting OnCanWrite()
203 // callback.
204 MessageResult SendMessage(QuicMemSliceSpan message);
205
QUICHE team350e9e62019-11-19 13:16:24 -0800206 // Same as above SendMessage, except caller can specify if the given |message|
207 // should be flushed even if the underlying connection is deemed unwritable.
208 MessageResult SendMessage(QuicMemSliceSpan message, bool flush);
209
QUICHE teama6ef0a62019-03-07 20:34:33 -0500210 // Called when message with |message_id| gets acked.
QUICHE team9467db02019-05-30 09:38:45 -0700211 virtual void OnMessageAcked(QuicMessageId message_id,
212 QuicTime receive_timestamp);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213
214 // Called when message with |message_id| is considered as lost.
215 virtual void OnMessageLost(QuicMessageId message_id);
216
217 // Called by control frame manager when it wants to write control frames to
218 // the peer. Returns true if |frame| is consumed, false otherwise.
219 virtual bool WriteControlFrame(const QuicFrame& frame);
220
renjietang64881612019-11-05 17:39:04 -0800221 // Close the stream in both directions.
222 // TODO(renjietang): rename this method as it sends both RST_STREAM and
223 // STOP_SENDING in IETF QUIC.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224 virtual void SendRstStream(QuicStreamId id,
225 QuicRstStreamErrorCode error,
226 QuicStreamOffset bytes_written);
227
228 // Called when the session wants to go away and not accept any new streams.
vasilvvc48c8712019-03-11 13:38:16 -0700229 virtual void SendGoAway(QuicErrorCode error_code, const std::string& reason);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230
231 // Sends a BLOCKED frame.
232 virtual void SendBlocked(QuicStreamId id);
233
234 // Sends a WINDOW_UPDATE frame.
235 virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);
236
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 // Create and transmit a STOP_SENDING frame
238 virtual void SendStopSending(uint16_t code, QuicStreamId stream_id);
239
240 // Removes the stream associated with 'stream_id' from the active stream map.
241 virtual void CloseStream(QuicStreamId stream_id);
242
243 // Returns true if outgoing packets will be encrypted, even if the server
244 // hasn't confirmed the handshake yet.
245 virtual bool IsEncryptionEstablished() const;
246
247 // For a client, returns true if the server has confirmed our handshake. For
248 // a server, returns true if a full, valid client hello has been received.
renjietang4f8e0bc2019-10-14 17:53:49 -0700249 bool IsCryptoHandshakeConfirmed() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250
251 // Called by the QuicCryptoStream when a new QuicConfig has been negotiated.
252 virtual void OnConfigNegotiated();
253
254 // Called by the QuicCryptoStream when the handshake enters a new state.
255 //
256 // Clients will call this function in the order:
renjietangea71d6f2019-08-19 12:22:28 -0700257 // zero or more ENCRYPTION_ESTABLISHED
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 // HANDSHAKE_CONFIRMED
259 //
260 // Servers will simply call it once with HANDSHAKE_CONFIRMED.
261 virtual void OnCryptoHandshakeEvent(CryptoHandshakeEvent event);
262
fayangd58736d2019-11-27 13:35:31 -0800263 // From HandshakerDelegateInterface
264 void OnNewKeysAvailable(EncryptionLevel level,
265 std::unique_ptr<QuicDecrypter> decrypter,
266 bool set_alternative_decrypter,
267 bool latch_once_used,
268 std::unique_ptr<QuicEncrypter> encrypter) override;
269 void SetDefaultEncryptionLevel(EncryptionLevel level) override;
270 void DiscardOldDecryptionKey(EncryptionLevel level) override;
271 void DiscardOldEncryptionKey(EncryptionLevel level) override;
272 void NeuterUnencryptedData() override;
273 void NeuterHandshakeData() override;
274
QUICHE teama6ef0a62019-03-07 20:34:33 -0500275 // Called by the QuicCryptoStream when a handshake message is sent.
276 virtual void OnCryptoHandshakeMessageSent(
277 const CryptoHandshakeMessage& message);
278
279 // Called by the QuicCryptoStream when a handshake message is received.
280 virtual void OnCryptoHandshakeMessageReceived(
281 const CryptoHandshakeMessage& message);
282
283 // Called by the stream on creation to set priority in the write blocked list.
fayang476683a2019-07-25 12:42:16 -0700284 virtual void RegisterStreamPriority(
285 QuicStreamId id,
286 bool is_static,
287 const spdy::SpdyStreamPrecedence& precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500288 // Called by the stream on deletion to clear priority from the write blocked
289 // list.
290 virtual void UnregisterStreamPriority(QuicStreamId id, bool is_static);
291 // Called by the stream on SetPriority to update priority on the write blocked
292 // list.
fayang476683a2019-07-25 12:42:16 -0700293 virtual void UpdateStreamPriority(
294 QuicStreamId id,
295 const spdy::SpdyStreamPrecedence& new_precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500296
297 // Returns mutable config for this session. Returned config is owned
298 // by QuicSession.
299 QuicConfig* config();
300
301 // Returns true if the stream existed previously and has been closed.
302 // Returns false if the stream is still active or if the stream has
303 // not yet been created.
304 bool IsClosedStream(QuicStreamId id);
305
306 QuicConnection* connection() { return connection_; }
307 const QuicConnection* connection() const { return connection_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500308 const QuicSocketAddress& peer_address() const {
309 return connection_->peer_address();
310 }
311 const QuicSocketAddress& self_address() const {
312 return connection_->self_address();
313 }
314 QuicConnectionId connection_id() const {
315 return connection_->connection_id();
316 }
317
renjietang69a8eaf2019-08-06 15:55:58 -0700318 // Returns the number of currently open streams, excluding static streams, and
319 // never counting unfinished streams.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500320 size_t GetNumActiveStreams() const;
321
322 // Returns the number of currently draining streams.
323 size_t GetNumDrainingStreams() const;
324
renjietang69a8eaf2019-08-06 15:55:58 -0700325 // Returns the number of currently open peer initiated streams, excluding
326 // static streams.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327 size_t GetNumOpenIncomingStreams() const;
328
renjietang69a8eaf2019-08-06 15:55:58 -0700329 // Returns the number of currently open self initiated streams, excluding
330 // static streams.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500331 size_t GetNumOpenOutgoingStreams() const;
332
renjietangfbeb5bf2019-04-19 15:06:20 -0700333 // Returns the number of open peer initiated static streams.
334 size_t num_incoming_static_streams() const {
335 return num_incoming_static_streams_;
336 }
337
338 // Returns the number of open self initiated static streams.
339 size_t num_outgoing_static_streams() const {
340 return num_outgoing_static_streams_;
341 }
342
QUICHE teama6ef0a62019-03-07 20:34:33 -0500343 // Add the stream to the session's write-blocked list because it is blocked by
344 // connection-level flow control but not by its own stream-level flow control.
345 // The stream will be given a chance to write when a connection-level
346 // WINDOW_UPDATE arrives.
QUICHE teamdf0b19f2019-08-13 16:55:42 -0700347 virtual void MarkConnectionLevelWriteBlocked(QuicStreamId id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348
349 // Called when stream |id| is done waiting for acks either because all data
350 // gets acked or is not interested in data being acked (which happens when
351 // a stream is reset because of an error).
352 void OnStreamDoneWaitingForAcks(QuicStreamId id);
353
zhongyi1b2f7832019-06-14 13:31:34 -0700354 // Called when stream |id| is newly waiting for acks.
355 void OnStreamWaitingForAcks(QuicStreamId id);
356
QUICHE teama6ef0a62019-03-07 20:34:33 -0500357 // Returns true if the session has data to be sent, either queued in the
358 // connection, or in a write-blocked stream.
359 bool HasDataToWrite() const;
360
361 // Returns the largest payload that will fit into a single MESSAGE frame.
362 // Because overhead can vary during a connection, this method should be
363 // checked for every message.
ianswettb239f862019-04-05 09:15:06 -0700364 QuicPacketLength GetCurrentLargestMessagePayload() const;
365
366 // Returns the largest payload that will fit into a single MESSAGE frame at
367 // any point during the connection. This assumes the version and
368 // connection ID lengths do not change.
369 QuicPacketLength GetGuaranteedLargestMessagePayload() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500370
371 bool goaway_sent() const { return goaway_sent_; }
372
373 bool goaway_received() const { return goaway_received_; }
374
fkastenholz488a4622019-08-26 06:24:46 -0700375 // Returns the Google QUIC error code
376 QuicErrorCode error() const { return on_closed_frame_.extracted_error_code; }
wub43652ca2019-09-05 11:18:19 -0700377 const std::string& error_details() const {
378 return on_closed_frame_.error_details;
379 }
fkastenholz488a4622019-08-26 06:24:46 -0700380 uint64_t transport_close_frame_type() const {
381 return on_closed_frame_.transport_close_frame_type;
382 }
383 QuicConnectionCloseType close_type() const {
384 return on_closed_frame_.close_type;
385 }
386 QuicIetfTransportErrorCodes transport_error_code() const {
387 return on_closed_frame_.transport_error_code;
388 }
389 uint16_t application_error_code() const {
390 return on_closed_frame_.application_error_code;
391 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500392
dschinazi31e94d42019-12-18 11:55:39 -0800393 Perspective perspective() const { return perspective_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500394
395 QuicFlowController* flow_controller() { return &flow_controller_; }
396
397 // Returns true if connection is flow controller blocked.
398 bool IsConnectionFlowControlBlocked() const;
399
400 // Returns true if any stream is flow controller blocked.
401 bool IsStreamFlowControlBlocked();
402
403 size_t max_open_incoming_bidirectional_streams() const;
404 size_t max_open_incoming_unidirectional_streams() const;
405
406 size_t MaxAvailableBidirectionalStreams() const;
407 size_t MaxAvailableUnidirectionalStreams() const;
408
renjietang55d182a2019-07-12 10:26:25 -0700409 // Returns existing stream with id = |stream_id|. If no
410 // such stream exists, and |stream_id| is a peer-created stream id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500411 // then a new stream is created and returned. In all other cases, nullptr is
412 // returned.
renjietang880d2432019-07-16 13:14:37 -0700413 // Caller does not own the returned stream.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500414 QuicStream* GetOrCreateStream(const QuicStreamId stream_id);
415
416 // Mark a stream as draining.
417 virtual void StreamDraining(QuicStreamId id);
418
419 // Returns true if this stream should yield writes to another blocked stream.
QUICHE teamdf0b19f2019-08-13 16:55:42 -0700420 virtual bool ShouldYield(QuicStreamId stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500421
422 // Set transmission type of next sending packets.
423 void SetTransmissionType(TransmissionType type);
424
425 // Clean up closed_streams_.
426 void CleanUpClosedStreams();
427
QUICHE teama6ef0a62019-03-07 20:34:33 -0500428 const ParsedQuicVersionVector& supported_versions() const {
429 return supported_versions_;
430 }
431
QUICHE teama6ef0a62019-03-07 20:34:33 -0500432 QuicStreamId next_outgoing_bidirectional_stream_id() const;
433 QuicStreamId next_outgoing_unidirectional_stream_id() const;
434
435 // Return true if given stream is peer initiated.
436 bool IsIncomingStream(QuicStreamId id) const;
437
438 size_t GetNumLocallyClosedOutgoingStreamsHighestOffset() const;
439
440 size_t num_locally_closed_incoming_streams_highest_offset() const {
441 return num_locally_closed_incoming_streams_highest_offset_;
442 }
443
444 // Does actual work of sending reset-stream or reset-stream&stop-sending
445 // If the connection is not version 99/IETF QUIC, will always send a
446 // RESET_STREAM and close_write_side_only is ignored. If the connection is
447 // IETF QUIC/Version 99 then will send a RESET_STREAM and STOP_SENDING if
448 // close_write_side_only is false, just a RESET_STREAM if
449 // close_write_side_only is true.
450 virtual void SendRstStreamInner(QuicStreamId id,
451 QuicRstStreamErrorCode error,
452 QuicStreamOffset bytes_written,
453 bool close_write_side_only);
454
wub2b5942f2019-04-11 13:22:50 -0700455 // Record errors when a connection is closed at the server side, should only
456 // be called from server's perspective.
457 // Noop if |error| is QUIC_NO_ERROR.
458 static void RecordConnectionCloseAtServer(QuicErrorCode error,
459 ConnectionCloseSource source);
460
fkastenholzd3a1de92019-05-15 07:00:07 -0700461 inline QuicTransportVersion transport_version() const {
462 return connection_->transport_version();
463 }
464
fayang944cfbc2019-07-31 09:15:00 -0700465 bool use_http2_priority_write_scheduler() const {
466 return use_http2_priority_write_scheduler_;
467 }
468
fayangd58736d2019-11-27 13:35:31 -0800469 bool use_handshake_delegate() const {
470 return connection_->use_handshake_delegate();
471 }
472
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700473 bool is_configured() const { return is_configured_; }
474
renjietang216dc012019-08-27 11:28:27 -0700475 QuicStreamCount num_expected_unidirectional_static_streams() const {
476 return num_expected_unidirectional_static_streams_;
477 }
478
479 // Set the number of unidirectional stream that the peer is allowed to open to
480 // be |max_stream| + |num_expected_static_streams_|.
481 void ConfigureMaxIncomingDynamicStreamsToSend(QuicStreamCount max_stream) {
482 config_.SetMaxIncomingUnidirectionalStreamsToSend(
483 max_stream + num_expected_unidirectional_static_streams_);
484 }
485
vasilvv4724c9c2019-08-29 11:52:11 -0700486 // Returns the ALPN values to negotiate on this session.
vasilvvad7424f2019-08-30 00:27:14 -0700487 virtual std::vector<std::string> GetAlpnsToOffer() const {
vasilvv4724c9c2019-08-29 11:52:11 -0700488 // TODO(vasilvv): this currently sets HTTP/3 by default. Switch all
489 // non-HTTP applications to appropriate ALPNs.
490 return std::vector<std::string>({AlpnForVersion(connection()->version())});
491 }
492
vasilvvad7424f2019-08-30 00:27:14 -0700493 // Provided a list of ALPNs offered by the client, selects an ALPN from the
494 // list, or alpns.end() if none of the ALPNs are acceptable.
dmcardlecf0bfcf2019-12-13 08:08:21 -0800495 virtual std::vector<quiche::QuicheStringPiece>::const_iterator SelectAlpn(
496 const std::vector<quiche::QuicheStringPiece>& alpns) const;
vasilvvad7424f2019-08-30 00:27:14 -0700497
498 // Called when the ALPN of the connection is established for a connection that
499 // uses TLS handshake.
dmcardlecf0bfcf2019-12-13 08:08:21 -0800500 virtual void OnAlpnSelected(quiche::QuicheStringPiece alpn);
vasilvvad7424f2019-08-30 00:27:14 -0700501
QUICHE teama6ef0a62019-03-07 20:34:33 -0500502 protected:
renjietang55d182a2019-07-12 10:26:25 -0700503 using StreamMap = QuicSmallMap<QuicStreamId, std::unique_ptr<QuicStream>, 10>;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500504
505 using PendingStreamMap =
506 QuicSmallMap<QuicStreamId, std::unique_ptr<PendingStream>, 10>;
507
508 using ClosedStreams = std::vector<std::unique_ptr<QuicStream>>;
509
510 using ZombieStreamMap =
511 QuicSmallMap<QuicStreamId, std::unique_ptr<QuicStream>, 10>;
512
513 // Creates a new stream to handle a peer-initiated stream.
514 // Caller does not own the returned stream.
515 // Returns nullptr and does error handling if the stream can not be created.
516 virtual QuicStream* CreateIncomingStream(QuicStreamId id) = 0;
renjietangbaea59c2019-05-29 15:08:14 -0700517 virtual QuicStream* CreateIncomingStream(PendingStream* pending) = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518
519 // Return the reserved crypto stream.
520 virtual QuicCryptoStream* GetMutableCryptoStream() = 0;
521
522 // Return the reserved crypto stream as a constant pointer.
523 virtual const QuicCryptoStream* GetCryptoStream() const = 0;
524
renjietang55d182a2019-07-12 10:26:25 -0700525 // Adds |stream| to the stream map.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500526 virtual void ActivateStream(std::unique_ptr<QuicStream> stream);
527
528 // Returns the stream ID for a new outgoing bidirectional/unidirectional
529 // stream, and increments the underlying counter.
530 QuicStreamId GetNextOutgoingBidirectionalStreamId();
531 QuicStreamId GetNextOutgoingUnidirectionalStreamId();
532
533 // Indicates whether the next outgoing bidirectional/unidirectional stream ID
534 // can be allocated or not. The test for version-99/IETF QUIC is whether it
535 // will exceed the maximum-stream-id or not. For non-version-99 (Google) QUIC
536 // it checks whether the next stream would exceed the limit on the number of
537 // open streams.
538 bool CanOpenNextOutgoingBidirectionalStream();
539 bool CanOpenNextOutgoingUnidirectionalStream();
540
541 // Returns the number of open dynamic streams.
542 uint64_t GetNumOpenDynamicStreams() const;
543
QUICHE teama6ef0a62019-03-07 20:34:33 -0500544 // Performs the work required to close |stream_id|. If |locally_reset|
545 // then the stream has been reset by this endpoint, not by the peer.
546 virtual void CloseStreamInner(QuicStreamId stream_id, bool locally_reset);
547
548 // When a stream is closed locally, it may not yet know how many bytes the
549 // peer sent on that stream.
550 // When this data arrives (via stream frame w. FIN, trailing headers, or RST)
551 // this method is called, and correctly updates the connection level flow
552 // controller.
553 virtual void OnFinalByteOffsetReceived(QuicStreamId id,
554 QuicStreamOffset final_byte_offset);
555
renjietange76b2da2019-05-13 14:50:23 -0700556 // Returns true if incoming unidirectional streams should be buffered until
557 // the first byte of the stream arrives.
558 // If a subclass returns true here, it should make sure to implement
559 // ProcessPendingStream().
560 virtual bool UsesPendingStreams() const { return false; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500561
renjietang55d182a2019-07-12 10:26:25 -0700562 StreamMap& stream_map() { return stream_map_; }
563 const StreamMap& stream_map() const { return stream_map_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500564
renjietang56d2ed22019-10-22 14:11:55 -0700565 const PendingStreamMap& pending_streams() const {
566 return pending_stream_map_;
567 }
568
QUICHE teama6ef0a62019-03-07 20:34:33 -0500569 ClosedStreams* closed_streams() { return &closed_streams_; }
570
571 const ZombieStreamMap& zombie_streams() const { return zombie_streams_; }
572
573 void set_largest_peer_created_stream_id(
574 QuicStreamId largest_peer_created_stream_id);
575
QUICHE teama6ef0a62019-03-07 20:34:33 -0500576 QuicWriteBlockedList* write_blocked_streams() {
577 return &write_blocked_streams_;
578 }
579
580 size_t GetNumDynamicOutgoingStreams() const;
581
582 size_t GetNumDrainingOutgoingStreams() const;
583
584 // Returns true if the stream is still active.
585 bool IsOpenStream(QuicStreamId id);
586
rchda26cdb2019-05-17 11:57:37 -0700587 // Returns true if the stream is a static stream.
588 bool IsStaticStream(QuicStreamId id) const;
589
renjietang5c729f02019-09-06 12:43:48 -0700590 // Close connection when receive a frame for a locally-created nonexistent
QUICHE teama6ef0a62019-03-07 20:34:33 -0500591 // stream.
592 // Prerequisite: IsClosedStream(stream_id) == false
593 // Server session might need to override this method to allow server push
594 // stream to be promised before creating an active stream.
595 virtual void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id);
596
597 virtual bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id);
598
599 void InsertLocallyClosedStreamsHighestOffset(const QuicStreamId id,
600 QuicStreamOffset offset);
601 // If stream is a locally closed stream, this RST will update FIN offset.
602 // Otherwise stream is a preserved stream and the behavior of it depends on
603 // derived class's own implementation.
604 virtual void HandleRstOnValidNonexistentStream(
605 const QuicRstStreamFrame& frame);
606
607 // Returns a stateless reset token which will be included in the public reset
608 // packet.
609 virtual QuicUint128 GetStatelessResetToken() const;
610
611 QuicControlFrameManager& control_frame_manager() {
612 return control_frame_manager_;
613 }
614
615 const LegacyQuicStreamIdManager& stream_id_manager() const {
616 return stream_id_manager_;
617 }
618
renjietang0c558862019-05-08 13:26:23 -0700619 // Processes the stream type information of |pending| depending on
renjietangbb1c4892019-05-24 15:58:44 -0700620 // different kinds of sessions' own rules. Returns true if the pending stream
621 // is converted into a normal stream.
dschinazi17d42422019-06-18 16:35:07 -0700622 virtual bool ProcessPendingStream(PendingStream* /*pending*/) {
623 return false;
624 }
renjietang0c558862019-05-08 13:26:23 -0700625
renjietang686ce582019-10-17 14:28:16 -0700626 // Return the largest peer created stream id depending on directionality
627 // indicated by |unidirectional|.
628 QuicStreamId GetLargestPeerCreatedStreamId(bool unidirectional) const;
629
ianswett6aefa0b2019-12-10 07:26:15 -0800630 // Deletes the connection and sets it to nullptr, so calling it mulitiple
631 // times is safe.
632 void DeleteConnection();
633
QUICHE teama6ef0a62019-03-07 20:34:33 -0500634 private:
635 friend class test::QuicSessionPeer;
636
637 // Called in OnConfigNegotiated when we receive a new stream level flow
638 // control window in a negotiated config. Closes the connection if invalid.
639 void OnNewStreamFlowControlWindow(QuicStreamOffset new_window);
640
dschinazi18cdf132019-10-09 16:08:18 -0700641 // Called in OnConfigNegotiated when we receive a new unidirectional stream
642 // flow control window in a negotiated config.
643 void OnNewStreamUnidirectionalFlowControlWindow(QuicStreamOffset new_window);
644
645 // Called in OnConfigNegotiated when we receive a new outgoing bidirectional
646 // stream flow control window in a negotiated config.
647 void OnNewStreamOutgoingBidirectionalFlowControlWindow(
648 QuicStreamOffset new_window);
649
650 // Called in OnConfigNegotiated when we receive a new incoming bidirectional
651 // stream flow control window in a negotiated config.
652 void OnNewStreamIncomingBidirectionalFlowControlWindow(
653 QuicStreamOffset new_window);
654
QUICHE teama6ef0a62019-03-07 20:34:33 -0500655 // Called in OnConfigNegotiated when we receive a new connection level flow
656 // control window in a negotiated config. Closes the connection if invalid.
657 void OnNewSessionFlowControlWindow(QuicStreamOffset new_window);
658
659 // Debug helper for |OnCanWrite()|, check that OnStreamWrite() makes
660 // forward progress. Returns false if busy loop detected.
661 bool CheckStreamNotBusyLooping(QuicStream* stream,
662 uint64_t previous_bytes_written,
663 bool previous_fin_sent);
664
665 // Debug helper for OnCanWrite. Check that after QuicStream::OnCanWrite(),
666 // if stream has buffered data and is not stream level flow control blocked,
667 // it has to be in the write blocked list.
668 bool CheckStreamWriteBlocked(QuicStream* stream) const;
669
670 // Called in OnConfigNegotiated for Finch trials to measure performance of
671 // starting with larger flow control receive windows.
672 void AdjustInitialFlowControlWindows(size_t stream_window);
673
674 // Find stream with |id|, returns nullptr if the stream does not exist or
675 // closed.
676 QuicStream* GetStream(QuicStreamId id) const;
677
renjietange76b2da2019-05-13 14:50:23 -0700678 PendingStream* GetOrCreatePendingStream(QuicStreamId stream_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500679
680 // Let streams and control frame managers retransmit lost data, returns true
681 // if all lost data is retransmitted. Returns false otherwise.
682 bool RetransmitLostData();
683
684 // Closes the pending stream |stream_id| before it has been created.
685 void ClosePendingStream(QuicStreamId stream_id);
686
renjietange76b2da2019-05-13 14:50:23 -0700687 // Creates or gets pending stream, feeds it with |frame|, and processes the
688 // pending stream.
689 void PendingStreamOnStreamFrame(const QuicStreamFrame& frame);
690
691 // Creates or gets pending strea, feed it with |frame|, and closes the pending
692 // stream.
693 void PendingStreamOnRstStream(const QuicRstStreamFrame& frame);
694
renjietang61cc2452019-11-26 10:57:10 -0800695 // Does actual work of sending RESET_STREAM, if the stream type allows.
696 void MaybeSendRstStreamFrame(QuicStreamId id,
697 QuicRstStreamErrorCode error,
698 QuicStreamOffset bytes_written);
699
700 // Sends a STOP_SENDING frame if the stream type allows.
701 void MaybeSendStopSendingFrame(QuicStreamId id, QuicRstStreamErrorCode error);
702
QUICHE teama6ef0a62019-03-07 20:34:33 -0500703 // Keep track of highest received byte offset of locally closed streams, while
704 // waiting for a definitive final highest offset from the peer.
705 std::map<QuicStreamId, QuicStreamOffset>
706 locally_closed_streams_highest_offset_;
707
708 QuicConnection* connection_;
709
dschinazi31e94d42019-12-18 11:55:39 -0800710 // Store perspective on QuicSession during the constructor as it may be needed
711 // during our destructor when connection_ may have already been destroyed.
712 Perspective perspective_;
713
QUICHE teama6ef0a62019-03-07 20:34:33 -0500714 // May be null.
715 Visitor* visitor_;
716
717 // A list of streams which need to write more data. Stream register
718 // themselves in their constructor, and unregisterm themselves in their
719 // destructors, so the write blocked list must outlive all streams.
720 QuicWriteBlockedList write_blocked_streams_;
721
722 ClosedStreams closed_streams_;
723 // Streams which are closed, but need to be kept alive. Currently, the only
724 // reason is the stream's sent data (including FIN) does not get fully acked.
725 ZombieStreamMap zombie_streams_;
726
727 QuicConfig config_;
728
QUICHE teama6ef0a62019-03-07 20:34:33 -0500729 // Map from StreamId to pointers to streams. Owns the streams.
renjietang55d182a2019-07-12 10:26:25 -0700730 StreamMap stream_map_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500731
732 // Map from StreamId to PendingStreams for peer-created unidirectional streams
733 // which are waiting for the first byte of payload to arrive.
734 PendingStreamMap pending_stream_map_;
735
736 // Set of stream ids that are "draining" -- a FIN has been sent and received,
737 // but the stream object still exists because not all the received data has
738 // been consumed.
739 QuicUnorderedSet<QuicStreamId> draining_streams_;
740
zhongyi1b2f7832019-06-14 13:31:34 -0700741 // Set of stream ids that are waiting for acks excluding crypto stream id.
742 QuicUnorderedSet<QuicStreamId> streams_waiting_for_acks_;
743
QUICHE teama6ef0a62019-03-07 20:34:33 -0500744 // TODO(fayang): Consider moving LegacyQuicStreamIdManager into
745 // UberQuicStreamIdManager.
746 // Manages stream IDs for Google QUIC.
747 LegacyQuicStreamIdManager stream_id_manager_;
748
749 // Manages stream IDs for version99/IETF QUIC
750 UberQuicStreamIdManager v99_streamid_manager_;
751
renjietang55d182a2019-07-12 10:26:25 -0700752 // A counter for peer initiated dynamic streams which are in the stream_map_.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500753 size_t num_dynamic_incoming_streams_;
754
755 // A counter for peer initiated streams which are in the draining_streams_.
756 size_t num_draining_incoming_streams_;
757
renjietangfbeb5bf2019-04-19 15:06:20 -0700758 // A counter for self initiated static streams which are in
renjietang55d182a2019-07-12 10:26:25 -0700759 // stream_map_.
renjietangfbeb5bf2019-04-19 15:06:20 -0700760 size_t num_outgoing_static_streams_;
761
762 // A counter for peer initiated static streams which are in
renjietang55d182a2019-07-12 10:26:25 -0700763 // stream_map_.
renjietangfbeb5bf2019-04-19 15:06:20 -0700764 size_t num_incoming_static_streams_;
765
QUICHE teama6ef0a62019-03-07 20:34:33 -0500766 // A counter for peer initiated streams which are in the
767 // locally_closed_streams_highest_offset_.
768 size_t num_locally_closed_incoming_streams_highest_offset_;
769
fkastenholz488a4622019-08-26 06:24:46 -0700770 // Received information for a connection close.
771 QuicConnectionCloseFrame on_closed_frame_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500772
773 // Used for connection-level flow control.
774 QuicFlowController flow_controller_;
775
776 // The stream id which was last popped in OnCanWrite, or 0, if not under the
777 // call stack of OnCanWrite.
778 QuicStreamId currently_writing_stream_id_;
779
QUICHE teama6ef0a62019-03-07 20:34:33 -0500780 // Whether a GoAway has been sent.
781 bool goaway_sent_;
782
783 // Whether a GoAway has been received.
784 bool goaway_received_;
785
786 QuicControlFrameManager control_frame_manager_;
787
788 // Id of latest successfully sent message.
789 QuicMessageId last_message_id_;
790
791 // TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
792 // is not used here.
793 // List of streams with pending retransmissions.
794 QuicLinkedHashMap<QuicStreamId, bool> streams_with_pending_retransmission_;
795
796 // Clean up closed_streams_ when this alarm fires.
797 std::unique_ptr<QuicAlarm> closed_streams_clean_up_alarm_;
798
799 // Supported version list used by the crypto handshake only. Please note, this
800 // list may be a superset of the connection framer's supported versions.
801 ParsedQuicVersionVector supported_versions_;
fayang944cfbc2019-07-31 09:15:00 -0700802
803 // If true, write_blocked_streams_ uses HTTP2 (tree-style) priority write
804 // scheduler.
805 bool use_http2_priority_write_scheduler_;
fkastenholz9b4b0ad2019-08-20 05:10:40 -0700806
807 // Initialized to false. Set to true when the session has been properly
808 // configured and is ready for general operation.
809 bool is_configured_;
renjietang216dc012019-08-27 11:28:27 -0700810
811 // The number of expected static streams.
812 QuicStreamCount num_expected_unidirectional_static_streams_;
fayang1b11b962019-09-16 14:01:48 -0700813
814 // If true, enables round robin scheduling.
815 bool enable_round_robin_scheduling_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500816};
817
818} // namespace quic
819
820#endif // QUICHE_QUIC_CORE_QUIC_SESSION_H_