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