• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2015 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 #ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
6 #define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <list>
11 #include <memory>
12 #include <optional>
13 #include <string>
14 
15 #include "absl/container/flat_hash_map.h"
16 #include "absl/container/flat_hash_set.h"
17 #include "absl/strings/string_view.h"
18 #include "quiche/quic/core/http/http_frames.h"
19 #include "quiche/quic/core/http/quic_header_list.h"
20 #include "quiche/quic/core/http/quic_headers_stream.h"
21 #include "quiche/quic/core/http/quic_receive_control_stream.h"
22 #include "quiche/quic/core/http/quic_send_control_stream.h"
23 #include "quiche/quic/core/http/quic_spdy_stream.h"
24 #include "quiche/quic/core/qpack/qpack_decoder.h"
25 #include "quiche/quic/core/qpack/qpack_encoder.h"
26 #include "quiche/quic/core/qpack/qpack_receive_stream.h"
27 #include "quiche/quic/core/qpack/qpack_send_stream.h"
28 #include "quiche/quic/core/quic_session.h"
29 #include "quiche/quic/core/quic_stream_priority.h"
30 #include "quiche/quic/core/quic_time.h"
31 #include "quiche/quic/core/quic_types.h"
32 #include "quiche/quic/core/quic_utils.h"
33 #include "quiche/quic/core/quic_versions.h"
34 #include "quiche/quic/platform/api/quic_export.h"
35 #include "quiche/spdy/core/http2_frame_decoder_adapter.h"
36 #include "quiche/spdy/core/http2_header_block.h"
37 
38 namespace quic {
39 
40 namespace test {
41 class QuicSpdySessionPeer;
42 }  // namespace test
43 
44 class WebTransportHttp3UnidirectionalStream;
45 
46 QUICHE_EXPORT extern const size_t kMaxUnassociatedWebTransportStreams;
47 
48 class QUICHE_EXPORT Http3DebugVisitor {
49  public:
50   Http3DebugVisitor();
51   Http3DebugVisitor(const Http3DebugVisitor&) = delete;
52   Http3DebugVisitor& operator=(const Http3DebugVisitor&) = delete;
53 
54   virtual ~Http3DebugVisitor();
55 
56   // TODO(https://crbug.com/1062700): Remove default implementation of all
57   // methods after Chrome's QuicHttp3Logger has overrides.  This is to make sure
58   // QUICHE merge is not blocked on having to add those overrides, they can
59   // happen asynchronously.
60 
61   // Creation of unidirectional streams.
62 
63   // Called when locally-initiated control stream is created.
64   virtual void OnControlStreamCreated(QuicStreamId /*stream_id*/) = 0;
65   // Called when locally-initiated QPACK encoder stream is created.
66   virtual void OnQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
67   // Called when locally-initiated QPACK decoder stream is created.
68   virtual void OnQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
69   // Called when peer's control stream type is received.
70   virtual void OnPeerControlStreamCreated(QuicStreamId /*stream_id*/) = 0;
71   // Called when peer's QPACK encoder stream type is received.
72   virtual void OnPeerQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
73   // Called when peer's QPACK decoder stream type is received.
74   virtual void OnPeerQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
75 
76   // Incoming HTTP/3 frames in ALPS TLS extension.
OnSettingsFrameReceivedViaAlps(const SettingsFrame &)77   virtual void OnSettingsFrameReceivedViaAlps(const SettingsFrame& /*frame*/) {}
OnAcceptChFrameReceivedViaAlps(const AcceptChFrame &)78   virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/) {}
79 
80   // Incoming HTTP/3 frames on the control stream.
81   virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0;
82   virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) = 0;
83   virtual void OnPriorityUpdateFrameReceived(
84       const PriorityUpdateFrame& /*frame*/) = 0;
OnAcceptChFrameReceived(const AcceptChFrame &)85   virtual void OnAcceptChFrameReceived(const AcceptChFrame& /*frame*/) {}
86 
87   // Incoming HTTP/3 frames on request or push streams.
88   virtual void OnDataFrameReceived(QuicStreamId /*stream_id*/,
89                                    QuicByteCount /*payload_length*/) = 0;
90   virtual void OnHeadersFrameReceived(
91       QuicStreamId /*stream_id*/,
92       QuicByteCount /*compressed_headers_length*/) = 0;
93   virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/,
94                                 QuicHeaderList /*headers*/) = 0;
95 
96   // Incoming HTTP/3 frames of unknown type on any stream.
97   virtual void OnUnknownFrameReceived(QuicStreamId /*stream_id*/,
98                                       uint64_t /*frame_type*/,
99                                       QuicByteCount /*payload_length*/) = 0;
100 
101   // Outgoing HTTP/3 frames on the control stream.
102   virtual void OnSettingsFrameSent(const SettingsFrame& /*frame*/) = 0;
103   virtual void OnGoAwayFrameSent(QuicStreamId /*stream_id*/) = 0;
104   virtual void OnPriorityUpdateFrameSent(
105       const PriorityUpdateFrame& /*frame*/) = 0;
106 
107   // Outgoing HTTP/3 frames on request or push streams.
108   virtual void OnDataFrameSent(QuicStreamId /*stream_id*/,
109                                QuicByteCount /*payload_length*/) = 0;
110   virtual void OnHeadersFrameSent(
111       QuicStreamId /*stream_id*/,
112       const spdy::Http2HeaderBlock& /*header_block*/) = 0;
113 
114   // 0-RTT related events.
115   virtual void OnSettingsFrameResumed(const SettingsFrame& /*frame*/) = 0;
116 };
117 
118 // Whether HTTP Datagrams are supported on this session and if so which version
119 // is currently in use.
120 enum class HttpDatagramSupport : uint8_t {
121   kNone,  // HTTP Datagrams are not supported for this session.
122   kDraft04,
123   kRfc,
124   kRfcAndDraft04,  // Only used locally for sending, we only negotiate one
125                    // version.
126 };
127 
128 // Versions of WebTransport over HTTP/3 protocol extension.
129 enum class WebTransportHttp3Version : uint8_t {
130   // <https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-02.html>
131   // The first version to be ever publicly shipped in Chrome. Sometimes referred
132   // to as "draft-00", since draft-02 was backwards-compatible with draft-00.
133   kDraft02,
134   // <https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-07.html>
135   // See the changelog in the appendix for differences between draft-02 and
136   // draft-07.
137   kDraft07,
138 };
139 using WebTransportHttp3VersionSet = BitMask<WebTransportHttp3Version, uint8_t>;
140 
141 // Note that by default, WebTransport is not enabled. Thus, those are the
142 // versions primarily used in the tools and unit tests.
143 inline constexpr WebTransportHttp3VersionSet
144     kDefaultSupportedWebTransportVersions =
145         WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02,
146                                      WebTransportHttp3Version::kDraft07});
147 
148 QUICHE_EXPORT std::string HttpDatagramSupportToString(
149     HttpDatagramSupport http_datagram_support);
150 QUICHE_EXPORT std::ostream& operator<<(
151     std::ostream& os, const HttpDatagramSupport& http_datagram_support);
152 
153 // A QUIC session for HTTP.
154 class QUICHE_EXPORT QuicSpdySession
155     : public QuicSession,
156       public QpackEncoder::DecoderStreamErrorDelegate,
157       public QpackDecoder::EncoderStreamErrorDelegate {
158  public:
159   // Does not take ownership of |connection| or |visitor|.
160   QuicSpdySession(QuicConnection* connection, QuicSession::Visitor* visitor,
161                   const QuicConfig& config,
162                   const ParsedQuicVersionVector& supported_versions);
163   QuicSpdySession(const QuicSpdySession&) = delete;
164   QuicSpdySession& operator=(const QuicSpdySession&) = delete;
165 
166   ~QuicSpdySession() override;
167 
168   void Initialize() override;
169 
170   // QpackEncoder::DecoderStreamErrorDelegate implementation.
171   void OnDecoderStreamError(QuicErrorCode error_code,
172                             absl::string_view error_message) override;
173 
174   // QpackDecoder::EncoderStreamErrorDelegate implementation.
175   void OnEncoderStreamError(QuicErrorCode error_code,
176                             absl::string_view error_message) override;
177 
178   // Called by |headers_stream_| when headers with a priority have been
179   // received for a stream.  This method will only be called for server streams.
180   virtual void OnStreamHeadersPriority(
181       QuicStreamId stream_id, const spdy::SpdyStreamPrecedence& precedence);
182 
183   // Called by |headers_stream_| when headers have been completely received
184   // for a stream.  |fin| will be true if the fin flag was set in the headers
185   // frame.
186   virtual void OnStreamHeaderList(QuicStreamId stream_id, bool fin,
187                                   size_t frame_len,
188                                   const QuicHeaderList& header_list);
189 
190   // Called by |headers_stream_| when a PRIORITY frame has been received for a
191   // stream. This method will only be called for server streams.
192   virtual void OnPriorityFrame(QuicStreamId stream_id,
193                                const spdy::SpdyStreamPrecedence& precedence);
194 
195   // Called when an HTTP/3 PRIORITY_UPDATE frame has been received for a request
196   // stream.  Returns false and closes connection if |stream_id| is invalid.
197   bool OnPriorityUpdateForRequestStream(QuicStreamId stream_id,
198                                         HttpStreamPriority priority);
199 
200   // Called when an HTTP/3 ACCEPT_CH frame has been received.
201   // This method will only be called for client sessions.
OnAcceptChFrame(const AcceptChFrame &)202   virtual void OnAcceptChFrame(const AcceptChFrame& /*frame*/) {}
203 
204   // Called when an HTTP/3 frame of unknown type has been received.
OnUnknownFrameStart(QuicStreamId,uint64_t,QuicByteCount,QuicByteCount)205   virtual void OnUnknownFrameStart(QuicStreamId /*stream_id*/,
206                                    uint64_t /*frame_type*/,
207                                    QuicByteCount /*header_length*/,
208                                    QuicByteCount /*payload_length*/) {}
OnUnknownFramePayload(QuicStreamId,absl::string_view)209   virtual void OnUnknownFramePayload(QuicStreamId /*stream_id*/,
210                                      absl::string_view /*payload*/) {}
211 
212   // Sends contents of |iov| to h2_deframer_, returns number of bytes processed.
213   size_t ProcessHeaderData(const struct iovec& iov);
214 
215   // Writes |headers| for the stream |id| to the dedicated headers stream.
216   // If |fin| is true, then no more data will be sent for the stream |id|.
217   // If provided, |ack_notifier_delegate| will be registered to be notified when
218   // we have seen ACKs for all packets resulting from this call.
219   virtual size_t WriteHeadersOnHeadersStream(
220       QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin,
221       const spdy::SpdyStreamPrecedence& precedence,
222       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
223           ack_listener);
224 
225   // Writes an HTTP/2 PRIORITY frame the to peer. Returns the size in bytes of
226   // the resulting PRIORITY frame.
227   size_t WritePriority(QuicStreamId stream_id, QuicStreamId parent_stream_id,
228                        int weight, bool exclusive);
229 
230   // Writes an HTTP/3 PRIORITY_UPDATE frame to the peer.
231   void WriteHttp3PriorityUpdate(QuicStreamId stream_id,
232                                 HttpStreamPriority priority);
233 
234   // Process received HTTP/3 GOAWAY frame.  When sent from server to client,
235   // |id| is a stream ID.  When sent from client to server, |id| is a push ID.
236   virtual void OnHttp3GoAway(uint64_t id);
237 
238   // Send GOAWAY if the peer is blocked on the implementation max.
239   bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
240 
241   // Write GOAWAY frame with maximum stream ID on the control stream.  Called to
242   // initite graceful connection shutdown.  Do not use smaller stream ID, in
243   // case client does not implement retry on GOAWAY.  Do not send GOAWAY if one
244   // has already been sent. Send connection close with |error_code| and |reason|
245   // before encryption gets established.
246   void SendHttp3GoAway(QuicErrorCode error_code, const std::string& reason);
247 
248   QpackEncoder* qpack_encoder();
249   QpackDecoder* qpack_decoder();
headers_stream()250   QuicHeadersStream* headers_stream() { return headers_stream_; }
251 
headers_stream()252   const QuicHeadersStream* headers_stream() const { return headers_stream_; }
253 
254   // Called when the control stream receives HTTP/3 SETTINGS.
255   // Returns false in case of 0-RTT if received settings are incompatible with
256   // cached values, true otherwise.
257   virtual bool OnSettingsFrame(const SettingsFrame& frame);
258 
259   // Called when an HTTP/3 SETTINGS frame is received via ALPS.
260   // Returns an error message if an error has occurred, or nullopt otherwise.
261   // May or may not close the connection on error.
262   std::optional<std::string> OnSettingsFrameViaAlps(const SettingsFrame& frame);
263 
264   // Called when a setting is parsed from a SETTINGS frame received on the
265   // control stream or from cached application state.
266   // Returns true on success.
267   // Returns false if received setting is incompatible with cached value (in
268   // case of 0-RTT) or with previously received value (in case of ALPS).
269   // Also closes the connection on error.
270   bool OnSetting(uint64_t id, uint64_t value);
271 
272   // Return true if this session wants to release headers stream's buffer
273   // aggressively.
274   virtual bool ShouldReleaseHeadersStreamSequencerBuffer();
275 
276   void CloseConnectionWithDetails(QuicErrorCode error,
277                                   const std::string& details);
278 
279   // Must not be called after Initialize().
280   // TODO(bnc): Move to constructor argument.
set_qpack_maximum_dynamic_table_capacity(uint64_t qpack_maximum_dynamic_table_capacity)281   void set_qpack_maximum_dynamic_table_capacity(
282       uint64_t qpack_maximum_dynamic_table_capacity) {
283     qpack_maximum_dynamic_table_capacity_ =
284         qpack_maximum_dynamic_table_capacity;
285   }
286 
287   // Must not be called after Initialize().
288   // TODO(bnc): Move to constructor argument.
set_qpack_maximum_blocked_streams(uint64_t qpack_maximum_blocked_streams)289   void set_qpack_maximum_blocked_streams(
290       uint64_t qpack_maximum_blocked_streams) {
291     qpack_maximum_blocked_streams_ = qpack_maximum_blocked_streams;
292   }
293 
294   // Should only be used by IETF QUIC server side.
295   // Must not be called after Initialize().
296   // TODO(bnc): Move to constructor argument.
set_max_inbound_header_list_size(size_t max_inbound_header_list_size)297   void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
298     max_inbound_header_list_size_ = max_inbound_header_list_size;
299   }
300 
301   // Must not be called after Initialize().
302   void set_allow_extended_connect(bool allow_extended_connect);
303 
max_outbound_header_list_size()304   size_t max_outbound_header_list_size() const {
305     return max_outbound_header_list_size_;
306   }
307 
max_inbound_header_list_size()308   size_t max_inbound_header_list_size() const {
309     return max_inbound_header_list_size_;
310   }
311 
allow_extended_connect()312   bool allow_extended_connect() const { return allow_extended_connect_; }
313 
314   // Returns true if the session has active request streams.
315   bool HasActiveRequestStreams() const;
316 
317   // Called when the size of the compressed frame payload is available.
318   void OnCompressedFrameSize(size_t frame_len);
319 
320   // Called when the complete list of headers is available.
321   void OnHeaderList(const QuicHeaderList& header_list);
322 
323   // Initialze HTTP/3 unidirectional streams if |unidirectional| is true and
324   // those streams are not initialized yet.
325   void OnCanCreateNewOutgoingStream(bool unidirectional) override;
326 
destruction_indicator()327   int32_t destruction_indicator() const { return destruction_indicator_; }
328 
set_debug_visitor(Http3DebugVisitor * debug_visitor)329   void set_debug_visitor(Http3DebugVisitor* debug_visitor) {
330     debug_visitor_ = debug_visitor;
331   }
332 
debug_visitor()333   Http3DebugVisitor* debug_visitor() { return debug_visitor_; }
334 
335   // When using Google QUIC, return whether a transport layer GOAWAY frame has
336   // been received or sent.
337   // When using IETF QUIC, return whether an HTTP/3 GOAWAY frame has been
338   // received or sent.
339   bool goaway_received() const;
340   bool goaway_sent() const;
last_received_http3_goaway_id()341   std::optional<uint64_t> last_received_http3_goaway_id() {
342     return last_received_http3_goaway_id_;
343   }
344 
345   // Log header compression ratio histogram.
346   // |using_qpack| is true for QPACK, false for HPACK.
347   // |is_sent| is true for sent headers, false for received ones.
348   // Ratio is recorded as percentage.  Smaller value means more efficient
349   // compression.  Compressed size might be larger than uncompressed size, but
350   // recorded ratio is trunckated at 200%.
351   // Uncompressed size can be zero for an empty header list, and compressed size
352   // can be zero for an empty header list when using HPACK.  (QPACK always emits
353   // a header block prefix of at least two bytes.)  This method records nothing
354   // if either |compressed| or |uncompressed| is not positive.
355   // In order for measurements for different protocol to be comparable, the
356   // caller must ensure that uncompressed size is the total length of header
357   // names and values without any overhead.
358   static void LogHeaderCompressionRatioHistogram(bool using_qpack, bool is_sent,
359                                                  QuicByteCount compressed,
360                                                  QuicByteCount uncompressed);
361 
362   // True if any dynamic table entries have been referenced from either a sent
363   // or received header block.  Used for stats.
dynamic_table_entry_referenced()364   bool dynamic_table_entry_referenced() const {
365     return (qpack_encoder_ &&
366             qpack_encoder_->dynamic_table_entry_referenced()) ||
367            (qpack_decoder_ && qpack_decoder_->dynamic_table_entry_referenced());
368   }
369 
370   void OnStreamCreated(QuicSpdyStream* stream);
371 
372   // Decode SETTINGS from |cached_state| and apply it to the session.
373   bool ResumeApplicationState(ApplicationState* cached_state) override;
374 
375   std::optional<std::string> OnAlpsData(const uint8_t* alps_data,
376                                         size_t alps_length) override;
377 
378   // Called when ACCEPT_CH frame is parsed out of data received in TLS ALPS
379   // extension.
380   virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/);
381 
382   // Whether HTTP datagrams are supported on this session and which draft is in
383   // use, based on received SETTINGS.
http_datagram_support()384   HttpDatagramSupport http_datagram_support() const {
385     return http_datagram_support_;
386   }
387 
388   // This must not be used except by QuicSpdyStream::SendHttp3Datagram.
389   MessageStatus SendHttp3Datagram(QuicStreamId stream_id,
390                                   absl::string_view payload);
391   // This must not be used except by QuicSpdyStream::SetMaxDatagramTimeInQueue.
392   void SetMaxDatagramTimeInQueueForStreamId(QuicStreamId stream_id,
393                                             QuicTime::Delta max_time_in_queue);
394 
395   // Override from QuicSession to support HTTP/3 datagrams.
396   void OnMessageReceived(absl::string_view message) override;
397 
398   // Indicates whether the HTTP/3 session supports WebTransport.
399   bool SupportsWebTransport();
400 
401   // If SupportsWebTransport() is true, returns the version of WebTransport
402   // currently in use (which is the highest version supported by both peers).
403   std::optional<WebTransportHttp3Version> SupportedWebTransportVersion();
404 
405   // Indicates whether both the peer and us support HTTP/3 Datagrams.
406   bool SupportsH3Datagram() const;
407 
408   // Indicates whether the HTTP/3 session will indicate WebTransport support to
409   // the peer.
410   bool WillNegotiateWebTransport();
411 
412   // Returns a WebTransport session by its session ID.  Returns nullptr if no
413   // session is associated with the given ID.
414   WebTransportHttp3* GetWebTransportSession(WebTransportSessionId id);
415 
416   // If true, no data on bidirectional streams will be processed by the server
417   // until the SETTINGS are received.  Only works for HTTP/3. This is currently
418   // required either (1) for WebTransport because WebTransport needs settings to
419   // correctly parse requests or (2) when multiple versions of HTTP Datagrams
420   // are supported to ensure we know which one is used. The HTTP Datagram check
421   // will be removed once we drop support for draft04.
ShouldBufferRequestsUntilSettings()422   bool ShouldBufferRequestsUntilSettings() {
423     return version().UsesHttp3() && perspective() == Perspective::IS_SERVER &&
424            (ShouldNegotiateWebTransport() ||
425             LocalHttpDatagramSupport() == HttpDatagramSupport::kRfcAndDraft04 ||
426             force_buffer_requests_until_settings_);
427   }
428 
429   // Returns if the incoming bidirectional streams should process data.  This is
430   // usually true, but in certain cases we would want to wait until the settings
431   // are received.
432   bool ShouldProcessIncomingRequests();
433 
434   void OnStreamWaitingForClientSettings(QuicStreamId id);
435 
436   // Links the specified stream with a WebTransport session.  If the session is
437   // not present, it is buffered until a corresponding stream is found.
438   void AssociateIncomingWebTransportStreamWithSession(
439       WebTransportSessionId session_id, QuicStreamId stream_id);
440 
441   void ProcessBufferedWebTransportStreamsForSession(WebTransportHttp3* session);
442 
CanOpenOutgoingUnidirectionalWebTransportStream(WebTransportSessionId)443   bool CanOpenOutgoingUnidirectionalWebTransportStream(
444       WebTransportSessionId /*id*/) {
445     return CanOpenNextOutgoingUnidirectionalStream();
446   }
CanOpenOutgoingBidirectionalWebTransportStream(WebTransportSessionId)447   bool CanOpenOutgoingBidirectionalWebTransportStream(
448       WebTransportSessionId /*id*/) {
449     return CanOpenNextOutgoingBidirectionalStream();
450   }
451 
452   // Creates an outgoing unidirectional WebTransport stream.  Returns nullptr if
453   // the stream cannot be created due to flow control or some other reason.
454   WebTransportHttp3UnidirectionalStream*
455   CreateOutgoingUnidirectionalWebTransportStream(WebTransportHttp3* session);
456 
457   // Creates an outgoing bidirectional WebTransport stream.  Returns nullptr if
458   // the stream cannot be created due to flow control or some other reason.
459   QuicSpdyStream* CreateOutgoingBidirectionalWebTransportStream(
460       WebTransportHttp3* session);
461 
462   QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id);
463 
464   // Returns a pointer to the incoming QPACK encoder stream (the one that
465   // belongs to the local decoding context). Might return nullptr.
GetQpackEncoderReceiveStream()466   QpackReceiveStream* GetQpackEncoderReceiveStream() const {
467     return qpack_encoder_receive_stream_;
468   }
469 
470   void OnConfigNegotiated() override;
471 
472   // Returns true if the SETTINGS frame has been received from the peer.
settings_received()473   bool settings_received() const { return settings_received_; }
474 
475  protected:
476   // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
477   // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
478   // make sure that all data streams are QuicSpdyStreams.
479   QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0;
480   QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override = 0;
481   virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
482   virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
483 
484   // If an incoming stream can be created, return true.
485   virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
486 
487   // If an outgoing bidirectional/unidirectional stream can be created, return
488   // true.
489   virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
490   virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
491 
492   // Indicates whether the underlying backend can accept and process
493   // WebTransport sessions over HTTP/3.
494   virtual WebTransportHttp3VersionSet LocallySupportedWebTransportVersions()
495       const;
496   bool ShouldNegotiateWebTransport() const;
497 
498   // Returns true if there are open HTTP requests.
499   bool ShouldKeepConnectionAlive() const override;
500 
501   // Overridden to buffer incoming unidirectional streams for version 99.
502   bool UsesPendingStreamForFrame(QuicFrameType type,
503                                  QuicStreamId stream_id) const override;
504 
505   // Called when a STREAM_FRAME is received on |pending| stream or
506   // ProcessAllPendingStreams() gets called. Processes incoming unidirectional
507   // streams; parses the stream type, and creates a new stream of the
508   // corresponding type. Returns the pointer to the newly created stream, or
509   // nullptr if the stream type is not yet available.
510   QuicStream* ProcessReadUnidirectionalPendingStream(
511       PendingStream* pending) override;
512 
513   size_t WriteHeadersOnHeadersStreamImpl(
514       QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin,
515       QuicStreamId parent_stream_id, int weight, bool exclusive,
516       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
517           ack_listener);
518 
519   void OnNewEncryptionKeyAvailable(
520       EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) override;
521 
522   // Sets the maximum size of the header compression table spdy_framer_ is
523   // willing to use to encode header blocks.
524   void UpdateHeaderEncoderTableSize(uint32_t value);
525 
IsConnected()526   bool IsConnected() { return connection()->connected(); }
527 
receive_control_stream()528   const QuicReceiveControlStream* receive_control_stream() const {
529     return receive_control_stream_;
530   }
531 
settings()532   const SettingsFrame& settings() const { return settings_; }
533 
534   // Initializes HTTP/3 unidirectional streams if not yet initialzed.
535   virtual void MaybeInitializeHttp3UnidirectionalStreams();
536 
537   // QuicConnectionVisitorInterface methods.
538   void BeforeConnectionCloseSent() override;
539   void MaybeBundleOpportunistically() override;
540 
541   // Called whenever a datagram is dequeued or dropped from datagram_queue().
542   virtual void OnDatagramProcessed(std::optional<MessageStatus> status);
543 
544   // Returns which version of the HTTP/3 datagram extension we should advertise
545   // in settings and accept remote settings for.
546   virtual HttpDatagramSupport LocalHttpDatagramSupport();
547 
548   // Sends any data which should be sent at the start of a connection, including
549   // the initial SETTINGS frame.  When using 0-RTT, this method is called twice:
550   // once when encryption is established, and again when 1-RTT keys are
551   // available.
552   void SendInitialData();
553 
554   // Override to skip checking for qpack_decoder_send_stream_ given decoder data
555   // is always bundled opportunistically.
556   bool CheckStreamWriteBlocked(QuicStream* stream) const override;
557 
558  private:
559   friend class test::QuicSpdySessionPeer;
560 
561   class SpdyFramerVisitor;
562 
563   // Proxies OnDatagramProcessed() calls to the session.
564   class QUICHE_EXPORT DatagramObserver : public QuicDatagramQueue::Observer {
565    public:
DatagramObserver(QuicSpdySession * session)566     explicit DatagramObserver(QuicSpdySession* session) : session_(session) {}
567     void OnDatagramProcessed(std::optional<MessageStatus> status) override;
568 
569    private:
570     QuicSpdySession* session_;  // not owned
571   };
572 
573   struct QUICHE_EXPORT BufferedWebTransportStream {
574     WebTransportSessionId session_id;
575     QuicStreamId stream_id;
576   };
577 
578   // The following methods are called by the SimpleVisitor.
579 
580   // Called when a HEADERS frame has been received.
581   void OnHeaders(spdy::SpdyStreamId stream_id, bool has_priority,
582                  const spdy::SpdyStreamPrecedence& precedence, bool fin);
583 
584   // Called when a PRIORITY frame has been received.
585   void OnPriority(spdy::SpdyStreamId stream_id,
586                   const spdy::SpdyStreamPrecedence& precedence);
587 
588   void CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
589       absl::string_view type);
590 
591   void FillSettingsFrame();
592 
593   bool VerifySettingIsZeroOrOne(uint64_t id, uint64_t value);
594 
595   // Computes the highest WebTransport version supported by both peers.
NegotiatedWebTransportVersion()596   std::optional<WebTransportHttp3Version> NegotiatedWebTransportVersion()
597       const {
598     return (LocallySupportedWebTransportVersions() &
599             peer_web_transport_versions_)
600         .Max();
601   }
602 
603   bool ValidateWebTransportSettingsConsistency();
604 
605   std::unique_ptr<QpackEncoder> qpack_encoder_;
606   std::unique_ptr<QpackDecoder> qpack_decoder_;
607 
608   // Pointer to the header stream in stream_map_.
609   QuicHeadersStream* headers_stream_;
610 
611   // HTTP/3 control streams. They are owned by QuicSession inside
612   // stream map, and can be accessed by those unowned pointers below.
613   QuicSendControlStream* send_control_stream_;
614   QuicReceiveControlStream* receive_control_stream_;
615 
616   // Pointers to HTTP/3 QPACK streams in stream map.
617   QpackReceiveStream* qpack_encoder_receive_stream_;
618   QpackReceiveStream* qpack_decoder_receive_stream_;
619   QpackSendStream* qpack_encoder_send_stream_;
620   QpackSendStream* qpack_decoder_send_stream_;
621 
622   SettingsFrame settings_;
623 
624   // Maximum dynamic table capacity as defined at
625   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#maximum-dynamic-table-capacity
626   // for the decoding context.  Value will be sent via
627   // SETTINGS_QPACK_MAX_TABLE_CAPACITY.
628   // |qpack_maximum_dynamic_table_capacity_| also serves as an upper bound for
629   // the dynamic table capacity of the encoding context, to limit memory usage
630   // if a larger SETTINGS_QPACK_MAX_TABLE_CAPACITY value is received.
631   uint64_t qpack_maximum_dynamic_table_capacity_;
632 
633   // Maximum number of blocked streams as defined at
634   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-streams
635   // for the decoding context.  Value will be sent via
636   // SETTINGS_QPACK_BLOCKED_STREAMS.
637   uint64_t qpack_maximum_blocked_streams_;
638 
639   // The maximum size of a header block that will be accepted from the peer,
640   // defined per spec as key + value + overhead per field (uncompressed).
641   // Value will be sent via SETTINGS_MAX_HEADER_LIST_SIZE.
642   size_t max_inbound_header_list_size_;
643 
644   // The maximum size of a header block that can be sent to the peer. This field
645   // is informed and set by the peer via SETTINGS frame.
646   // TODO(b/148616439): Honor this field when sending headers.
647   size_t max_outbound_header_list_size_;
648 
649   // Data about the stream whose headers are being processed.
650   QuicStreamId stream_id_;
651   size_t frame_len_;
652   bool fin_;
653 
654   spdy::SpdyFramer spdy_framer_;
655   http2::Http2DecoderAdapter h2_deframer_;
656   std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
657 
658   // Not owned by the session.
659   Http3DebugVisitor* debug_visitor_;
660 
661   // Priority values received in PRIORITY_UPDATE frames for streams that are not
662   // open yet.
663   absl::flat_hash_map<QuicStreamId, HttpStreamPriority>
664       buffered_stream_priorities_;
665 
666   // An integer used for live check. The indicator is assigned a value in
667   // constructor. As long as it is not the assigned value, that would indicate
668   // an use-after-free.
669   int32_t destruction_indicator_;
670 
671   // The identifier in the most recently received GOAWAY frame.  Unset if no
672   // GOAWAY frame has been received yet.
673   std::optional<uint64_t> last_received_http3_goaway_id_;
674   // The identifier in the most recently sent GOAWAY frame.  Unset if no GOAWAY
675   // frame has been sent yet.
676   std::optional<uint64_t> last_sent_http3_goaway_id_;
677 
678   // Whether both this endpoint and our peer support HTTP datagrams and which
679   // draft is in use for this session.
680   HttpDatagramSupport http_datagram_support_ = HttpDatagramSupport::kNone;
681 
682   // WebTransport protocol versions supported by the peer.
683   WebTransportHttp3VersionSet peer_web_transport_versions_;
684 
685   // Whether the SETTINGS frame has been received on the control stream.
686   bool settings_received_ = false;
687 
688   // If ShouldBufferRequestsUntilSettings() is true, all streams that are
689   // blocked by that are tracked here.
690   absl::flat_hash_set<QuicStreamId> streams_waiting_for_settings_;
691 
692   // WebTransport streams that do not have a session associated with them.
693   // Limited to kMaxUnassociatedWebTransportStreams; when the list is full,
694   // oldest streams are evicated first.
695   std::list<BufferedWebTransportStream> buffered_streams_;
696 
697   // On the server side, if true, advertise and accept extended CONNECT method.
698   // On the client side, true if the peer advertised extended CONNECT.
699   bool allow_extended_connect_;
700 
701   // Since WebTransport is versioned by renumbering
702   // SETTINGS_WEBTRANSPORT_MAX_SESSIONS, the max sessions value depends on the
703   // version we end up picking.  This is only stored on the client, as the
704   // server cannot initiate WebTransport sessions.
705   absl::flat_hash_map<WebTransportHttp3Version, QuicStreamCount>
706       max_webtransport_sessions_;
707 
708   // Allows forcing ShouldBufferRequestsUntilSettings() to true via
709   // a connection option.
710   bool force_buffer_requests_until_settings_;
711 
712   // Latched value of quic_enable_h3_datagrams reloadable flag.
713   bool quic_enable_h3_datagrams_flag_;
714 };
715 
716 }  // namespace quic
717 
718 #endif  // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
719