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 <memory>
10 #include <string>
11 
12 #include "absl/strings/string_view.h"
13 #include "absl/types/optional.h"
14 #include "net/third_party/quiche/src/quic/core/http/http_frames.h"
15 #include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
16 #include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h"
17 #include "net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h"
18 #include "net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h"
19 #include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
20 #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
21 #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
22 #include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
23 #include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
24 #include "net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h"
25 #include "net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h"
26 #include "net/third_party/quiche/src/quic/core/quic_session.h"
27 #include "net/third_party/quiche/src/quic/core/quic_time.h"
28 #include "net/third_party/quiche/src/quic/core/quic_types.h"
29 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
30 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
31 #include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
32 
33 namespace quic {
34 
35 namespace test {
36 class QuicSpdySessionPeer;
37 }  // namespace test
38 
39 // QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
40 // dynamics.  Specifically, it is to help predict the compression
41 // penalty of avoiding HoL by chagning how the dynamic table is used.
42 // In chromium, the concrete instance populates an UMA
43 // histogram with the data.
44 class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
45  public:
46   QuicHpackDebugVisitor();
47   QuicHpackDebugVisitor(const QuicHpackDebugVisitor&) = delete;
48   QuicHpackDebugVisitor& operator=(const QuicHpackDebugVisitor&) = delete;
49 
50   virtual ~QuicHpackDebugVisitor();
51 
52   // For each HPACK indexed representation processed, |elapsed| is
53   // the time since the corresponding entry was added to the dynamic
54   // table.
55   virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
56 };
57 
58 class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
59  public:
60   Http3DebugVisitor();
61   Http3DebugVisitor(const Http3DebugVisitor&) = delete;
62   Http3DebugVisitor& operator=(const Http3DebugVisitor&) = delete;
63 
64   virtual ~Http3DebugVisitor();
65 
66   // TODO(https://crbug.com/1062700): Remove default implementation of all
67   // methods after Chrome's QuicHttp3Logger has overrides.  This is to make sure
68   // QUICHE merge is not blocked on having to add those overrides, they can
69   // happen asynchronously.
70 
71   // Creation of unidirectional streams.
72 
73   // Called when locally-initiated control stream is created.
OnControlStreamCreated(QuicStreamId)74   virtual void OnControlStreamCreated(QuicStreamId /*stream_id*/) {}
75   // Called when locally-initiated QPACK encoder stream is created.
OnQpackEncoderStreamCreated(QuicStreamId)76   virtual void OnQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) {}
77   // Called when locally-initiated QPACK decoder stream is created.
OnQpackDecoderStreamCreated(QuicStreamId)78   virtual void OnQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) {}
79   // Called when peer's control stream type is received.
80   virtual void OnPeerControlStreamCreated(QuicStreamId /*stream_id*/) = 0;
81   // Called when peer's QPACK encoder stream type is received.
82   virtual void OnPeerQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
83   // Called when peer's QPACK decoder stream type is received.
84   virtual void OnPeerQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
85 
86   // Incoming HTTP/3 frames on the control stream.
OnCancelPushFrameReceived(const CancelPushFrame &)87   virtual void OnCancelPushFrameReceived(const CancelPushFrame& /*frame*/) {}
88   virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0;
OnGoAwayFrameReceived(const GoAwayFrame &)89   virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) {}
OnMaxPushIdFrameReceived(const MaxPushIdFrame &)90   virtual void OnMaxPushIdFrameReceived(const MaxPushIdFrame& /*frame*/) {}
OnPriorityUpdateFrameReceived(const PriorityUpdateFrame &)91   virtual void OnPriorityUpdateFrameReceived(
92       const PriorityUpdateFrame& /*frame*/) {}
93 
94   // Incoming HTTP/3 frames on request or push streams.
OnDataFrameReceived(QuicStreamId,QuicByteCount)95   virtual void OnDataFrameReceived(QuicStreamId /*stream_id*/,
96                                    QuicByteCount /*payload_length*/) {}
OnHeadersFrameReceived(QuicStreamId,QuicByteCount)97   virtual void OnHeadersFrameReceived(
98       QuicStreamId /*stream_id*/,
99       QuicByteCount /*compressed_headers_length*/) {}
OnHeadersDecoded(QuicStreamId,QuicHeaderList)100   virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/,
101                                 QuicHeaderList /*headers*/) {}
OnPushPromiseFrameReceived(QuicStreamId,QuicStreamId,QuicByteCount)102   virtual void OnPushPromiseFrameReceived(QuicStreamId /*stream_id*/,
103                                           QuicStreamId /*push_id*/,
104                                           QuicByteCount
105                                           /*compressed_headers_length*/) {}
OnPushPromiseDecoded(QuicStreamId,QuicStreamId,QuicHeaderList)106   virtual void OnPushPromiseDecoded(QuicStreamId /*stream_id*/,
107                                     QuicStreamId /*push_id*/,
108                                     QuicHeaderList /*headers*/) {}
109 
110   // Incoming HTTP/3 frames of unknown type on any stream.
OnUnknownFrameReceived(QuicStreamId,uint64_t,QuicByteCount)111   virtual void OnUnknownFrameReceived(QuicStreamId /*stream_id*/,
112                                       uint64_t /*frame_type*/,
113                                       QuicByteCount /*payload_length*/) {}
114 
115   // Outgoing HTTP/3 frames on the control stream.
116   virtual void OnSettingsFrameSent(const SettingsFrame& /*frame*/) = 0;
OnGoAwayFrameSent(QuicStreamId)117   virtual void OnGoAwayFrameSent(QuicStreamId /*stream_id*/) {}
OnMaxPushIdFrameSent(const MaxPushIdFrame &)118   virtual void OnMaxPushIdFrameSent(const MaxPushIdFrame& /*frame*/) {}
OnPriorityUpdateFrameSent(const PriorityUpdateFrame &)119   virtual void OnPriorityUpdateFrameSent(const PriorityUpdateFrame& /*frame*/) {
120   }
121 
122   // Outgoing HTTP/3 frames on request or push streams.
OnDataFrameSent(QuicStreamId,QuicByteCount)123   virtual void OnDataFrameSent(QuicStreamId /*stream_id*/,
124                                QuicByteCount /*payload_length*/) {}
OnHeadersFrameSent(QuicStreamId,const spdy::SpdyHeaderBlock &)125   virtual void OnHeadersFrameSent(
126       QuicStreamId /*stream_id*/,
127       const spdy::SpdyHeaderBlock& /*header_block*/) {}
OnPushPromiseFrameSent(QuicStreamId,QuicStreamId,const spdy::SpdyHeaderBlock &)128   virtual void OnPushPromiseFrameSent(
129       QuicStreamId /*stream_id*/,
130       QuicStreamId
131       /*push_id*/,
132       const spdy::SpdyHeaderBlock& /*header_block*/) {}
133 
134   // 0-RTT related events.
OnSettingsFrameResumed(const SettingsFrame &)135   virtual void OnSettingsFrameResumed(const SettingsFrame& /*frame*/) {}
136 };
137 
138 // A QUIC session for HTTP.
139 class QUIC_EXPORT_PRIVATE QuicSpdySession
140     : public QuicSession,
141       public QpackEncoder::DecoderStreamErrorDelegate,
142       public QpackDecoder::EncoderStreamErrorDelegate {
143  public:
144   // Does not take ownership of |connection| or |visitor|.
145   QuicSpdySession(QuicConnection* connection,
146                   QuicSession::Visitor* visitor,
147                   const QuicConfig& config,
148                   const ParsedQuicVersionVector& supported_versions);
149   QuicSpdySession(const QuicSpdySession&) = delete;
150   QuicSpdySession& operator=(const QuicSpdySession&) = delete;
151 
152   ~QuicSpdySession() override;
153 
154   void Initialize() override;
155 
156   // QpackEncoder::DecoderStreamErrorDelegate implementation.
157   void OnDecoderStreamError(QuicErrorCode error_code,
158                             absl::string_view error_message) override;
159 
160   // QpackDecoder::EncoderStreamErrorDelegate implementation.
161   void OnEncoderStreamError(QuicErrorCode error_code,
162                             absl::string_view error_message) override;
163 
164   // Called by |headers_stream_| when headers with a priority have been
165   // received for a stream.  This method will only be called for server streams.
166   virtual void OnStreamHeadersPriority(
167       QuicStreamId stream_id,
168       const spdy::SpdyStreamPrecedence& precedence);
169 
170   // Called by |headers_stream_| when headers have been completely received
171   // for a stream.  |fin| will be true if the fin flag was set in the headers
172   // frame.
173   virtual void OnStreamHeaderList(QuicStreamId stream_id,
174                                   bool fin,
175                                   size_t frame_len,
176                                   const QuicHeaderList& header_list);
177 
178   // Called by |headers_stream_| when push promise headers have been
179   // completely received.  |fin| will be true if the fin flag was set
180   // in the headers.
181   virtual void OnPromiseHeaderList(QuicStreamId stream_id,
182                                    QuicStreamId promised_stream_id,
183                                    size_t frame_len,
184                                    const QuicHeaderList& header_list);
185 
186   // Called by |headers_stream_| when a PRIORITY frame has been received for a
187   // stream. This method will only be called for server streams.
188   virtual void OnPriorityFrame(QuicStreamId stream_id,
189                                const spdy::SpdyStreamPrecedence& precedence);
190 
191   // Called when an HTTP/3 PRIORITY_UPDATE frame has been received for a request
192   // stream.  Returns false and closes connection if |stream_id| is invalid.
193   bool OnPriorityUpdateForRequestStream(QuicStreamId stream_id, int urgency);
194 
195   // Called when an HTTP/3 PRIORITY_UPDATE frame has been received for a push
196   // stream.  Returns false and closes connection if |push_id| is invalid.
197   bool OnPriorityUpdateForPushStream(QuicStreamId push_id, int urgency);
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,
208       spdy::SpdyHeaderBlock headers,
209       bool fin,
210       const spdy::SpdyStreamPrecedence& precedence,
211       QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
212 
213   // Writes an HTTP/2 PRIORITY frame the to peer. Returns the size in bytes of
214   // the resulting PRIORITY frame.
215   size_t WritePriority(QuicStreamId id,
216                        QuicStreamId parent_stream_id,
217                        int weight,
218                        bool exclusive);
219 
220   // Writes an HTTP/3 PRIORITY_UPDATE frame to the peer.
221   void WriteHttp3PriorityUpdate(const PriorityUpdateFrame& priority_update);
222 
223   // Process received HTTP/3 GOAWAY frame.  When sent from server to client,
224   // |id| is a stream ID.  When sent from client to server, |id| is a push ID.
225   virtual void OnHttp3GoAway(uint64_t id);
226 
227   // Send GOAWAY if the peer is blocked on the implementation max.
228   bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
229 
230   // Write GOAWAY frame with maximum stream ID on the control stream.  Called to
231   // initite graceful connection shutdown.  Do not use smaller stream ID, in
232   // case client does not implement retry on GOAWAY.  Do not send GOAWAY if one
233   // has already been sent.
234   void SendHttp3GoAway();
235 
236   // Same as SendHttp3GoAway().  TODO(bnc): remove when
237   // gfe2_reloadable_flag_quic_goaway_with_max_stream_id flag is deprecated.
238   void SendHttp3Shutdown();
239 
240   // Write |headers| for |promised_stream_id| on |original_stream_id| in a
241   // PUSH_PROMISE frame to peer.
242   virtual void WritePushPromise(QuicStreamId original_stream_id,
243                                 QuicStreamId promised_stream_id,
244                                 spdy::SpdyHeaderBlock headers);
245 
246   QpackEncoder* qpack_encoder();
247   QpackDecoder* qpack_decoder();
headers_stream()248   QuicHeadersStream* headers_stream() { return headers_stream_; }
249 
headers_stream()250   const QuicHeadersStream* headers_stream() const { return headers_stream_; }
251 
252   // Returns whether server push is enabled.
253   // For a Google QUIC client this always returns false.
254   // For a Google QUIC server this is set by incoming SETTINGS_ENABLE_PUSH.
255   // For an IETF QUIC client this returns true if SetMaxPushId() has ever been
256   // called.
257   // For an IETF QUIC server this returns true if EnableServerPush() has been
258   // called and the server has received at least one MAX_PUSH_ID frame from the
259   // client.
260   bool server_push_enabled() const;
261 
262   // Called when the control stream receives HTTP/3 SETTINGS.
263   // Returns false in case of 0-RTT if received settings are incompatible with
264   // cached values, true otherwise.
265   virtual bool OnSettingsFrame(const SettingsFrame& frame);
266 
267   // Called when a SETTINGS is parsed from an incoming SETTINGS frame.
268   // Returns false in case of 0-RTT if received SETTINGS is incompatible with
269   // cached value, true otherwise.
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   // Must not be called after Initialize().
295   // TODO(bnc): Move to constructor argument.
set_max_inbound_header_list_size(size_t max_inbound_header_list_size)296   void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
297     max_inbound_header_list_size_ = max_inbound_header_list_size;
298   }
299 
max_outbound_header_list_size()300   size_t max_outbound_header_list_size() const {
301     return max_outbound_header_list_size_;
302   }
303 
max_inbound_header_list_size()304   size_t max_inbound_header_list_size() const {
305     return max_inbound_header_list_size_;
306   }
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   void OnPushPromise(spdy::SpdyStreamId stream_id,
316                      spdy::SpdyStreamId promised_stream_id);
317 
318   // Called when the complete list of headers is available.
319   void OnHeaderList(const QuicHeaderList& header_list);
320 
promised_stream_id()321   QuicStreamId promised_stream_id() const { return promised_stream_id_; }
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 
327   // Sets |max_push_id_| and sends a MAX_PUSH_ID frame.
328   // This method must only be called if protocol is IETF QUIC and perspective is
329   // client.  |max_push_id| must be greater than or equal to current
330   // |max_push_id_|.
331   void SetMaxPushId(PushId max_push_id);
332 
333   // Sets |max_push_id_|.
334   // This method must only be called if protocol is IETF QUIC and perspective is
335   // server.  It must only be called if a MAX_PUSH_ID frame is received.
336   // Returns whether |max_push_id| is greater than or equal to current
337   // |max_push_id_|.
338   bool OnMaxPushIdFrame(PushId max_push_id);
339 
340   // Enables server push.
341   // Must only be called when using IETF QUIC, for which server push is disabled
342   // by default.  Server push defaults to enabled and cannot be disabled for
343   // Google QUIC.
344   // Must only be called for a server.  A client can effectively disable push by
345   // never calling SetMaxPushId().
346   void EnableServerPush();
347 
348   // Returns true if push is enabled and a push with |push_id| can be created.
349   // For a server this means that EnableServerPush() has been called, at least
350   // one MAX_PUSH_ID frame has been received, and the largest received
351   // MAX_PUSH_ID value is greater than or equal to |push_id|.
352   // For a client this means that SetMaxPushId() has been called with
353   // |max_push_id| greater than or equal to |push_id|.
354   // Must only be called when using IETF QUIC.
355   bool CanCreatePushStreamWithId(PushId push_id);
356 
destruction_indicator()357   int32_t destruction_indicator() const { return destruction_indicator_; }
358 
set_debug_visitor(Http3DebugVisitor * debug_visitor)359   void set_debug_visitor(Http3DebugVisitor* debug_visitor) {
360     debug_visitor_ = debug_visitor;
361   }
362 
debug_visitor()363   Http3DebugVisitor* debug_visitor() { return debug_visitor_; }
364 
365   // When using Google QUIC, return whether a transport layer GOAWAY frame has
366   // been received or sent.
367   // When using IETF QUIC, return whether an HTTP/3 GOAWAY frame has been
368   // received or sent.
369   bool goaway_received() const;
370   bool goaway_sent() const;
371 
372   // Log header compression ratio histogram.
373   // |using_qpack| is true for QPACK, false for HPACK.
374   // |is_sent| is true for sent headers, false for received ones.
375   // Ratio is recorded as percentage.  Smaller value means more efficient
376   // compression.  Compressed size might be larger than uncompressed size, but
377   // recorded ratio is trunckated at 200%.
378   // Uncompressed size can be zero for an empty header list, and compressed size
379   // can be zero for an empty header list when using HPACK.  (QPACK always emits
380   // a header block prefix of at least two bytes.)  This method records nothing
381   // if either |compressed| or |uncompressed| is not positive.
382   // In order for measurements for different protocol to be comparable, the
383   // caller must ensure that uncompressed size is the total length of header
384   // names and values without any overhead.
385   static void LogHeaderCompressionRatioHistogram(bool using_qpack,
386                                                  bool is_sent,
387                                                  QuicByteCount compressed,
388                                                  QuicByteCount uncompressed);
389 
390   // True if any dynamic table entries have been referenced from either a sent
391   // or received header block.  Used for stats.
dynamic_table_entry_referenced()392   bool dynamic_table_entry_referenced() const {
393     return (qpack_encoder_ &&
394             qpack_encoder_->dynamic_table_entry_referenced()) ||
395            (qpack_decoder_ && qpack_decoder_->dynamic_table_entry_referenced());
396   }
397 
398   void OnStreamCreated(QuicSpdyStream* stream);
399 
400   // Decode SETTINGS from |cached_state| and apply it to the session.
401   bool ResumeApplicationState(ApplicationState* cached_state) override;
402 
403  protected:
404   // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
405   // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
406   // make sure that all data streams are QuicSpdyStreams.
407   QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0;
408   QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override = 0;
409   virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
410   virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
411 
412   QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id);
413 
414   // If an incoming stream can be created, return true.
415   virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
416 
417   // If an outgoing bidirectional/unidirectional stream can be created, return
418   // true.
419   virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
420   virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
421 
422   // Returns true if there are open HTTP requests.
423   bool ShouldKeepConnectionAlive() const override;
424 
425   // Overridden to buffer incoming unidirectional streams for version 99.
426   bool UsesPendingStreams() const override;
427 
428   // Overridden to Process HTTP/3 stream types. H/3 streams will be created from
429   // pending streams accordingly if the stream type can be read. Returns true if
430   // unidirectional streams are created.
431   bool ProcessPendingStream(PendingStream* pending) override;
432 
433   size_t WriteHeadersOnHeadersStreamImpl(
434       QuicStreamId id,
435       spdy::SpdyHeaderBlock headers,
436       bool fin,
437       QuicStreamId parent_stream_id,
438       int weight,
439       bool exclusive,
440       QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
441 
442   void OnNewEncryptionKeyAvailable(
443       EncryptionLevel level,
444       std::unique_ptr<QuicEncrypter> encrypter) override;
445 
446   // Optional, enables instrumentation related to go/quic-hpack.
447   void SetHpackEncoderDebugVisitor(
448       std::unique_ptr<QuicHpackDebugVisitor> visitor);
449   void SetHpackDecoderDebugVisitor(
450       std::unique_ptr<QuicHpackDebugVisitor> visitor);
451 
452   // Sets the maximum size of the header compression table spdy_framer_ is
453   // willing to use to encode header blocks.
454   void UpdateHeaderEncoderTableSize(uint32_t value);
455 
456   // Called when SETTINGS_ENABLE_PUSH is received, only supported on
457   // server side.
458   void UpdateEnableServerPush(bool value);
459 
IsConnected()460   bool IsConnected() { return connection()->connected(); }
461 
receive_control_stream()462   const QuicReceiveControlStream* receive_control_stream() const {
463     return receive_control_stream_;
464   }
465 
settings()466   const SettingsFrame& settings() const { return settings_; }
467 
468   // Initializes HTTP/3 unidirectional streams if not yet initialzed.
469   virtual void MaybeInitializeHttp3UnidirectionalStreams();
470 
471   // QuicConnectionVisitorInterface method.
472   void BeforeConnectionCloseSent() override;
473 
474  private:
475   friend class test::QuicSpdySessionPeer;
476 
477   class SpdyFramerVisitor;
478 
479   // The following methods are called by the SimpleVisitor.
480 
481   // Called when a HEADERS frame has been received.
482   void OnHeaders(spdy::SpdyStreamId stream_id,
483                  bool has_priority,
484                  const spdy::SpdyStreamPrecedence& precedence,
485                  bool fin);
486 
487   // Called when a PRIORITY frame has been received.
488   void OnPriority(spdy::SpdyStreamId stream_id,
489                   const spdy::SpdyStreamPrecedence& precedence);
490 
491   void CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
492       absl::string_view type);
493 
494   // Sends any data which should be sent at the start of a connection, including
495   // the initial SETTINGS frame, and (when IETF QUIC is used) also a MAX_PUSH_ID
496   // frame if SetMaxPushId() had been called before encryption was established.
497   // When using 0-RTT, this method is called twice: once when encryption is
498   // established, and again when 1-RTT keys are available.
499   void SendInitialData();
500 
501   // Send a MAX_PUSH_ID frame.  Used in IETF QUIC only.
502   void SendMaxPushId();
503 
504   void FillSettingsFrame();
505 
506   std::unique_ptr<QpackEncoder> qpack_encoder_;
507   std::unique_ptr<QpackDecoder> qpack_decoder_;
508 
509   // Pointer to the header stream in stream_map_.
510   QuicHeadersStream* headers_stream_;
511 
512   // HTTP/3 control streams. They are owned by QuicSession inside
513   // stream map, and can be accessed by those unowned pointers below.
514   QuicSendControlStream* send_control_stream_;
515   QuicReceiveControlStream* receive_control_stream_;
516 
517   // Pointers to HTTP/3 QPACK streams in stream map.
518   QpackReceiveStream* qpack_encoder_receive_stream_;
519   QpackReceiveStream* qpack_decoder_receive_stream_;
520   QpackSendStream* qpack_encoder_send_stream_;
521   QpackSendStream* qpack_decoder_send_stream_;
522 
523   SettingsFrame settings_;
524 
525   // Maximum dynamic table capacity as defined at
526   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#maximum-dynamic-table-capacity
527   // for the decoding context.  Value will be sent via
528   // SETTINGS_QPACK_MAX_TABLE_CAPACITY.
529   // |qpack_maximum_dynamic_table_capacity_| also serves as an upper bound for
530   // the dynamic table capacity of the encoding context, to limit memory usage
531   // if a larger SETTINGS_QPACK_MAX_TABLE_CAPACITY value is received.
532   uint64_t qpack_maximum_dynamic_table_capacity_;
533 
534   // Maximum number of blocked streams as defined at
535   // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-streams
536   // for the decoding context.  Value will be sent via
537   // SETTINGS_QPACK_BLOCKED_STREAMS.
538   uint64_t qpack_maximum_blocked_streams_;
539 
540   // The maximum size of a header block that will be accepted from the peer,
541   // defined per spec as key + value + overhead per field (uncompressed).
542   // Value will be sent via SETTINGS_MAX_HEADER_LIST_SIZE.
543   size_t max_inbound_header_list_size_;
544 
545   // The maximum size of a header block that can be sent to the peer. This field
546   // is informed and set by the peer via SETTINGS frame.
547   // TODO(b/148616439): Honor this field when sending headers.
548   size_t max_outbound_header_list_size_;
549 
550   // Data about the stream whose headers are being processed.
551   QuicStreamId stream_id_;
552   QuicStreamId promised_stream_id_;
553   size_t frame_len_;
554   bool fin_;
555 
556   spdy::SpdyFramer spdy_framer_;
557   http2::Http2DecoderAdapter h2_deframer_;
558   std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
559 
560   // Used in IETF QUIC only.
561   // For a server:
562   //   the push ID in the most recently received MAX_PUSH_ID frame,
563   //   or unset if no MAX_PUSH_ID frame has been received.
564   // For a client:
565   //   unset until SetMaxPushId() is called;
566   //   before encryption is established, the push ID to be sent in the initial
567   //   MAX_PUSH_ID frame;
568   //   after encryption is established, the push ID in the most recently sent
569   //   MAX_PUSH_ID frame.
570   // Once set, never goes back to unset.
571   absl::optional<PushId> max_push_id_;
572 
573   // Not owned by the session.
574   Http3DebugVisitor* debug_visitor_;
575 
576   // Priority values received in PRIORITY_UPDATE frames for streams that are not
577   // open yet.
578   QuicHashMap<QuicStreamId, int> buffered_stream_priorities_;
579 
580   // An integer used for live check. The indicator is assigned a value in
581   // constructor. As long as it is not the assigned value, that would indicate
582   // an use-after-free.
583   int32_t destruction_indicator_;
584 
585   // Used in Google QUIC only.  Set every time SETTINGS_ENABLE_PUSH is received.
586   // Defaults to true.
587   bool server_push_enabled_;
588 
589   // Used in IETF QUIC only.  Defaults to false.
590   // Server push is enabled for a server by calling EnableServerPush().
591   // Server push is enabled for a client by calling SetMaxPushId().
592   bool ietf_server_push_enabled_;
593 
594   // The identifier in the most recently received GOAWAY frame.  Unset if no
595   // GOAWAY frame has been received yet.
596   absl::optional<uint64_t> last_received_http3_goaway_id_;
597   // The identifier in the most recently sent GOAWAY frame.  Unset if no GOAWAY
598   // frame has been sent yet.
599   absl::optional<uint64_t> last_sent_http3_goaway_id_;
600 
601   // Only used by a client, only with IETF QUIC.  True if a MAX_PUSH_ID frame
602   // has been sent, in which case |max_push_id_| has the value sent in the most
603   // recent MAX_PUSH_ID frame.  Once true, never goes back to false.
604   bool http3_max_push_id_sent_;
605 
606   // Latched value of reloadable flag quic_reject_spdy_settings.
607   const bool reject_spdy_settings_;
608 
609   // Latched value of reloadable flag quic_goaway_with_max_stream_id.
610   const bool goaway_with_max_stream_id_;
611 };
612 
613 }  // namespace quic
614 
615 #endif  // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
616