xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 
qpack_maximum_dynamic_table_capacity()287   uint64_t qpack_maximum_dynamic_table_capacity() const {
288     return qpack_maximum_dynamic_table_capacity_;
289   }
290 
291   // Must not be called after Initialize().
292   // TODO(bnc): Move to constructor argument.
set_qpack_maximum_blocked_streams(uint64_t qpack_maximum_blocked_streams)293   void set_qpack_maximum_blocked_streams(
294       uint64_t qpack_maximum_blocked_streams) {
295     qpack_maximum_blocked_streams_ = qpack_maximum_blocked_streams;
296   }
297 
298   // Should only be used by IETF QUIC server side.
299   // Must not be called after Initialize().
300   // TODO(bnc): Move to constructor argument.
set_max_inbound_header_list_size(size_t max_inbound_header_list_size)301   void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
302     max_inbound_header_list_size_ = max_inbound_header_list_size;
303   }
304 
305   // Must not be called after Initialize().
306   void set_allow_extended_connect(bool allow_extended_connect);
307 
max_outbound_header_list_size()308   size_t max_outbound_header_list_size() const {
309     return max_outbound_header_list_size_;
310   }
311 
max_inbound_header_list_size()312   size_t max_inbound_header_list_size() const {
313     return max_inbound_header_list_size_;
314   }
315 
allow_extended_connect()316   bool allow_extended_connect() const { return allow_extended_connect_; }
317 
318   // Returns true if the session has active request streams.
319   bool HasActiveRequestStreams() const;
320 
321   // Called when the size of the compressed frame payload is available.
322   void OnCompressedFrameSize(size_t frame_len);
323 
324   // Called when the complete list of headers is available.
325   void OnHeaderList(const QuicHeaderList& header_list);
326 
327   // Initialze HTTP/3 unidirectional streams if |unidirectional| is true and
328   // those streams are not initialized yet.
329   void OnCanCreateNewOutgoingStream(bool unidirectional) override;
330 
destruction_indicator()331   int32_t destruction_indicator() const { return destruction_indicator_; }
332 
set_debug_visitor(Http3DebugVisitor * debug_visitor)333   void set_debug_visitor(Http3DebugVisitor* debug_visitor) {
334     debug_visitor_ = debug_visitor;
335   }
336 
debug_visitor()337   Http3DebugVisitor* debug_visitor() { return debug_visitor_; }
338 
339   // When using Google QUIC, return whether a transport layer GOAWAY frame has
340   // been received or sent.
341   // When using IETF QUIC, return whether an HTTP/3 GOAWAY frame has been
342   // received or sent.
343   bool goaway_received() const;
344   bool goaway_sent() const;
last_received_http3_goaway_id()345   std::optional<uint64_t> last_received_http3_goaway_id() {
346     return last_received_http3_goaway_id_;
347   }
348 
349   // Log header compression ratio histogram.
350   // |using_qpack| is true for QPACK, false for HPACK.
351   // |is_sent| is true for sent headers, false for received ones.
352   // Ratio is recorded as percentage.  Smaller value means more efficient
353   // compression.  Compressed size might be larger than uncompressed size, but
354   // recorded ratio is trunckated at 200%.
355   // Uncompressed size can be zero for an empty header list, and compressed size
356   // can be zero for an empty header list when using HPACK.  (QPACK always emits
357   // a header block prefix of at least two bytes.)  This method records nothing
358   // if either |compressed| or |uncompressed| is not positive.
359   // In order for measurements for different protocol to be comparable, the
360   // caller must ensure that uncompressed size is the total length of header
361   // names and values without any overhead.
362   static void LogHeaderCompressionRatioHistogram(bool using_qpack, bool is_sent,
363                                                  QuicByteCount compressed,
364                                                  QuicByteCount uncompressed);
365 
366   // True if any dynamic table entries have been referenced from either a sent
367   // or received header block.  Used for stats.
dynamic_table_entry_referenced()368   bool dynamic_table_entry_referenced() const {
369     return (qpack_encoder_ &&
370             qpack_encoder_->dynamic_table_entry_referenced()) ||
371            (qpack_decoder_ && qpack_decoder_->dynamic_table_entry_referenced());
372   }
373 
374   void OnStreamCreated(QuicSpdyStream* stream);
375 
376   // Decode SETTINGS from |cached_state| and apply it to the session.
377   bool ResumeApplicationState(ApplicationState* cached_state) override;
378 
379   std::optional<std::string> OnAlpsData(const uint8_t* alps_data,
380                                         size_t alps_length) override;
381 
382   // Called when ACCEPT_CH frame is parsed out of data received in TLS ALPS
383   // extension.
384   virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/);
385 
386   // Whether HTTP datagrams are supported on this session and which draft is in
387   // use, based on received SETTINGS.
http_datagram_support()388   HttpDatagramSupport http_datagram_support() const {
389     return http_datagram_support_;
390   }
391 
392   // This must not be used except by QuicSpdyStream::SendHttp3Datagram.
393   MessageStatus SendHttp3Datagram(QuicStreamId stream_id,
394                                   absl::string_view payload);
395   // This must not be used except by QuicSpdyStream::SetMaxDatagramTimeInQueue.
396   void SetMaxDatagramTimeInQueueForStreamId(QuicStreamId stream_id,
397                                             QuicTime::Delta max_time_in_queue);
398 
399   // Override from QuicSession to support HTTP/3 datagrams.
400   void OnMessageReceived(absl::string_view message) override;
401 
402   // Indicates whether the HTTP/3 session supports WebTransport.
403   bool SupportsWebTransport();
404 
405   // If SupportsWebTransport() is true, returns the version of WebTransport
406   // currently in use (which is the highest version supported by both peers).
407   std::optional<WebTransportHttp3Version> SupportedWebTransportVersion();
408 
409   // Indicates whether both the peer and us support HTTP/3 Datagrams.
410   bool SupportsH3Datagram() const;
411 
412   // Indicates whether the HTTP/3 session will indicate WebTransport support to
413   // the peer.
414   bool WillNegotiateWebTransport();
415 
416   // Returns a WebTransport session by its session ID.  Returns nullptr if no
417   // session is associated with the given ID.
418   WebTransportHttp3* GetWebTransportSession(WebTransportSessionId id);
419 
420   // If true, no data on bidirectional streams will be processed by the server
421   // until the SETTINGS are received.  Only works for HTTP/3. This is currently
422   // required either (1) for WebTransport because WebTransport needs settings to
423   // correctly parse requests or (2) when multiple versions of HTTP Datagrams
424   // are supported to ensure we know which one is used. The HTTP Datagram check
425   // will be removed once we drop support for draft04.
ShouldBufferRequestsUntilSettings()426   bool ShouldBufferRequestsUntilSettings() {
427     return version().UsesHttp3() && perspective() == Perspective::IS_SERVER &&
428            (ShouldNegotiateWebTransport() ||
429             LocalHttpDatagramSupport() == HttpDatagramSupport::kRfcAndDraft04 ||
430             force_buffer_requests_until_settings_);
431   }
432 
433   // Returns if the incoming bidirectional streams should process data.  This is
434   // usually true, but in certain cases we would want to wait until the settings
435   // are received.
436   bool ShouldProcessIncomingRequests();
437 
438   void OnStreamWaitingForClientSettings(QuicStreamId id);
439 
440   // Links the specified stream with a WebTransport session.  If the session is
441   // not present, it is buffered until a corresponding stream is found.
442   void AssociateIncomingWebTransportStreamWithSession(
443       WebTransportSessionId session_id, QuicStreamId stream_id);
444 
445   void ProcessBufferedWebTransportStreamsForSession(WebTransportHttp3* session);
446 
CanOpenOutgoingUnidirectionalWebTransportStream(WebTransportSessionId)447   bool CanOpenOutgoingUnidirectionalWebTransportStream(
448       WebTransportSessionId /*id*/) {
449     return CanOpenNextOutgoingUnidirectionalStream();
450   }
CanOpenOutgoingBidirectionalWebTransportStream(WebTransportSessionId)451   bool CanOpenOutgoingBidirectionalWebTransportStream(
452       WebTransportSessionId /*id*/) {
453     return CanOpenNextOutgoingBidirectionalStream();
454   }
455 
456   // Creates an outgoing unidirectional WebTransport stream.  Returns nullptr if
457   // the stream cannot be created due to flow control or some other reason.
458   WebTransportHttp3UnidirectionalStream*
459   CreateOutgoingUnidirectionalWebTransportStream(WebTransportHttp3* session);
460 
461   // Creates an outgoing bidirectional WebTransport stream.  Returns nullptr if
462   // the stream cannot be created due to flow control or some other reason.
463   QuicSpdyStream* CreateOutgoingBidirectionalWebTransportStream(
464       WebTransportHttp3* session);
465 
466   QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id);
467 
468   // Returns a pointer to the incoming QPACK encoder stream (the one that
469   // belongs to the local decoding context). Might return nullptr.
GetQpackEncoderReceiveStream()470   QpackReceiveStream* GetQpackEncoderReceiveStream() const {
471     return qpack_encoder_receive_stream_;
472   }
473 
474   void OnConfigNegotiated() override;
475 
476   // Returns true if the SETTINGS frame has been received from the peer.
settings_received()477   bool settings_received() const { return settings_received_; }
478 
479  protected:
480   // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
481   // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
482   // make sure that all data streams are QuicSpdyStreams.
483   QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0;
484   QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override = 0;
485   virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
486   virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
487 
488   // If an incoming stream can be created, return true.
489   virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
490 
491   // If an outgoing bidirectional/unidirectional stream can be created, return
492   // true.
493   virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
494   virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
495 
496   // Indicates whether the underlying backend can accept and process
497   // WebTransport sessions over HTTP/3.
498   virtual WebTransportHttp3VersionSet LocallySupportedWebTransportVersions()
499       const;
500   bool ShouldNegotiateWebTransport() const;
501 
502   // Returns true if there are open HTTP requests.
503   bool ShouldKeepConnectionAlive() const override;
504 
505   // Overridden to buffer incoming unidirectional streams for version 99.
506   bool UsesPendingStreamForFrame(QuicFrameType type,
507                                  QuicStreamId stream_id) const override;
508 
509   // Called when a STREAM_FRAME is received on |pending| stream or
510   // ProcessAllPendingStreams() gets called. Processes incoming unidirectional
511   // streams; parses the stream type, and creates a new stream of the
512   // corresponding type. Returns the pointer to the newly created stream, or
513   // nullptr if the stream type is not yet available.
514   QuicStream* ProcessReadUnidirectionalPendingStream(
515       PendingStream* pending) override;
516 
517   size_t WriteHeadersOnHeadersStreamImpl(
518       QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin,
519       QuicStreamId parent_stream_id, int weight, bool exclusive,
520       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
521           ack_listener);
522 
523   void OnNewEncryptionKeyAvailable(
524       EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) override;
525 
526   // Sets the maximum size of the header compression table spdy_framer_ is
527   // willing to use to encode header blocks.
528   void UpdateHeaderEncoderTableSize(uint32_t value);
529 
IsConnected()530   bool IsConnected() { return connection()->connected(); }
531 
receive_control_stream()532   const QuicReceiveControlStream* receive_control_stream() const {
533     return receive_control_stream_;
534   }
535 
settings()536   const SettingsFrame& settings() const { return settings_; }
537 
538   // Initializes HTTP/3 unidirectional streams if not yet initialzed.
539   virtual void MaybeInitializeHttp3UnidirectionalStreams();
540 
541   // QuicConnectionVisitorInterface methods.
542   void BeforeConnectionCloseSent() override;
543   void MaybeBundleOpportunistically() override;
544 
545   // Called whenever a datagram is dequeued or dropped from datagram_queue().
546   virtual void OnDatagramProcessed(std::optional<MessageStatus> status);
547 
548   // Returns which version of the HTTP/3 datagram extension we should advertise
549   // in settings and accept remote settings for.
550   virtual HttpDatagramSupport LocalHttpDatagramSupport();
551 
552   // Sends any data which should be sent at the start of a connection, including
553   // the initial SETTINGS frame.  When using 0-RTT, this method is called twice:
554   // once when encryption is established, and again when 1-RTT keys are
555   // available.
556   void SendInitialData();
557 
558   // Override to skip checking for qpack_decoder_send_stream_ given decoder data
559   // is always bundled opportunistically.
560   bool CheckStreamWriteBlocked(QuicStream* stream) const override;
561 
562   // Disables the use of Huffman encoding for QPACK headers.
DisableHuffmanEncoding()563   void DisableHuffmanEncoding() {
564     huffman_encoding_ = HuffmanEncoding::kDisabled;
565   }
566 
567  private:
568   friend class test::QuicSpdySessionPeer;
569 
570   class SpdyFramerVisitor;
571 
572   // Proxies OnDatagramProcessed() calls to the session.
573   class QUICHE_EXPORT DatagramObserver : public QuicDatagramQueue::Observer {
574    public:
DatagramObserver(QuicSpdySession * session)575     explicit DatagramObserver(QuicSpdySession* session) : session_(session) {}
576     void OnDatagramProcessed(std::optional<MessageStatus> status) override;
577 
578    private:
579     QuicSpdySession* session_;  // not owned
580   };
581 
582   struct QUICHE_EXPORT BufferedWebTransportStream {
583     WebTransportSessionId session_id;
584     QuicStreamId stream_id;
585   };
586 
587   // The following methods are called by the SimpleVisitor.
588 
589   // Called when a HEADERS frame has been received.
590   void OnHeaders(spdy::SpdyStreamId stream_id, bool has_priority,
591                  const spdy::SpdyStreamPrecedence& precedence, bool fin);
592 
593   // Called when a PRIORITY frame has been received.
594   void OnPriority(spdy::SpdyStreamId stream_id,
595                   const spdy::SpdyStreamPrecedence& precedence);
596 
597   void CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
598       absl::string_view type);
599 
600   void FillSettingsFrame();
601 
602   bool VerifySettingIsZeroOrOne(uint64_t id, uint64_t value);
603 
604   // Computes the highest WebTransport version supported by both peers.
NegotiatedWebTransportVersion()605   std::optional<WebTransportHttp3Version> NegotiatedWebTransportVersion()
606       const {
607     return (LocallySupportedWebTransportVersions() &
608             peer_web_transport_versions_)
609         .Max();
610   }
611 
612   bool ValidateWebTransportSettingsConsistency();
613 
614   HuffmanEncoding huffman_encoding_ = HuffmanEncoding::kEnabled;
615   std::unique_ptr<QpackEncoder> qpack_encoder_;
616   std::unique_ptr<QpackDecoder> qpack_decoder_;
617 
618   // Pointer to the header stream in stream_map_.
619   QuicHeadersStream* headers_stream_;
620 
621   // HTTP/3 control streams. They are owned by QuicSession inside
622   // stream map, and can be accessed by those unowned pointers below.
623   QuicSendControlStream* send_control_stream_;
624   QuicReceiveControlStream* receive_control_stream_;
625 
626   // Pointers to HTTP/3 QPACK streams in stream map.
627   QpackReceiveStream* qpack_encoder_receive_stream_;
628   QpackReceiveStream* qpack_decoder_receive_stream_;
629   QpackSendStream* qpack_encoder_send_stream_;
630   QpackSendStream* qpack_decoder_send_stream_;
631 
632   SettingsFrame settings_;
633 
634   // Maximum dynamic table capacity as defined at
635   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#maximum-dynamic-table-capacity
636   // for the decoding context.  Value will be sent via
637   // SETTINGS_QPACK_MAX_TABLE_CAPACITY.
638   // |qpack_maximum_dynamic_table_capacity_| also serves as an upper bound for
639   // the dynamic table capacity of the encoding context, to limit memory usage
640   // if a larger SETTINGS_QPACK_MAX_TABLE_CAPACITY value is received.
641   uint64_t qpack_maximum_dynamic_table_capacity_;
642 
643   // Maximum number of blocked streams as defined at
644   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-streams
645   // for the decoding context.  Value will be sent via
646   // SETTINGS_QPACK_BLOCKED_STREAMS.
647   uint64_t qpack_maximum_blocked_streams_;
648 
649   // The maximum size of a header block that will be accepted from the peer,
650   // defined per spec as key + value + overhead per field (uncompressed).
651   // Value will be sent via SETTINGS_MAX_HEADER_LIST_SIZE.
652   size_t max_inbound_header_list_size_;
653 
654   // The maximum size of a header block that can be sent to the peer. This field
655   // is informed and set by the peer via SETTINGS frame.
656   // TODO(b/148616439): Honor this field when sending headers.
657   size_t max_outbound_header_list_size_;
658 
659   // Data about the stream whose headers are being processed.
660   QuicStreamId stream_id_;
661   size_t frame_len_;
662   bool fin_;
663 
664   spdy::SpdyFramer spdy_framer_;
665   http2::Http2DecoderAdapter h2_deframer_;
666   std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
667 
668   // Not owned by the session.
669   Http3DebugVisitor* debug_visitor_;
670 
671   // Priority values received in PRIORITY_UPDATE frames for streams that are not
672   // open yet.
673   absl::flat_hash_map<QuicStreamId, HttpStreamPriority>
674       buffered_stream_priorities_;
675 
676   // An integer used for live check. The indicator is assigned a value in
677   // constructor. As long as it is not the assigned value, that would indicate
678   // an use-after-free.
679   int32_t destruction_indicator_;
680 
681   // The identifier in the most recently received GOAWAY frame.  Unset if no
682   // GOAWAY frame has been received yet.
683   std::optional<uint64_t> last_received_http3_goaway_id_;
684   // The identifier in the most recently sent GOAWAY frame.  Unset if no GOAWAY
685   // frame has been sent yet.
686   std::optional<uint64_t> last_sent_http3_goaway_id_;
687 
688   // Whether both this endpoint and our peer support HTTP datagrams and which
689   // draft is in use for this session.
690   HttpDatagramSupport http_datagram_support_ = HttpDatagramSupport::kNone;
691 
692   // WebTransport protocol versions supported by the peer.
693   WebTransportHttp3VersionSet peer_web_transport_versions_;
694 
695   // Whether the SETTINGS frame has been received on the control stream.
696   bool settings_received_ = false;
697 
698   // If ShouldBufferRequestsUntilSettings() is true, all streams that are
699   // blocked by that are tracked here.
700   absl::flat_hash_set<QuicStreamId> streams_waiting_for_settings_;
701 
702   // WebTransport streams that do not have a session associated with them.
703   // Limited to kMaxUnassociatedWebTransportStreams; when the list is full,
704   // oldest streams are evicated first.
705   std::list<BufferedWebTransportStream> buffered_streams_;
706 
707   // On the server side, if true, advertise and accept extended CONNECT method.
708   // On the client side, true if the peer advertised extended CONNECT.
709   bool allow_extended_connect_;
710 
711   // Since WebTransport is versioned by renumbering
712   // SETTINGS_WEBTRANSPORT_MAX_SESSIONS, the max sessions value depends on the
713   // version we end up picking.  This is only stored on the client, as the
714   // server cannot initiate WebTransport sessions.
715   absl::flat_hash_map<WebTransportHttp3Version, QuicStreamCount>
716       max_webtransport_sessions_;
717 
718   // Allows forcing ShouldBufferRequestsUntilSettings() to true via
719   // a connection option.
720   bool force_buffer_requests_until_settings_;
721 };
722 
723 }  // namespace quic
724 
725 #endif  // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
726