• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
2 #define QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
3 
4 #include <cstdint>
5 #include <limits>
6 #include <list>
7 #include <memory>
8 #include <vector>
9 
10 #include "absl/strings/string_view.h"
11 #include "absl/types/optional.h"
12 #include "absl/types/variant.h"
13 #include "quiche/http2/adapter/data_source.h"
14 #include "quiche/http2/adapter/event_forwarder.h"
15 #include "quiche/http2/adapter/header_validator.h"
16 #include "quiche/http2/adapter/header_validator_base.h"
17 #include "quiche/http2/adapter/http2_protocol.h"
18 #include "quiche/http2/adapter/http2_session.h"
19 #include "quiche/http2/adapter/http2_util.h"
20 #include "quiche/http2/adapter/http2_visitor_interface.h"
21 #include "quiche/http2/adapter/window_manager.h"
22 #include "quiche/http2/core/http2_trace_logging.h"
23 #include "quiche/http2/core/priority_write_scheduler.h"
24 #include "quiche/common/platform/api/quiche_bug_tracker.h"
25 #include "quiche/common/platform/api/quiche_export.h"
26 #include "quiche/common/platform/api/quiche_flags.h"
27 #include "quiche/common/quiche_linked_hash_map.h"
28 #include "quiche/spdy/core/http2_frame_decoder_adapter.h"
29 #include "quiche/spdy/core/http2_header_block.h"
30 #include "quiche/spdy/core/no_op_headers_handler.h"
31 #include "quiche/spdy/core/spdy_framer.h"
32 #include "quiche/spdy/core/spdy_protocol.h"
33 
34 namespace http2 {
35 namespace adapter {
36 
37 // This class manages state associated with a single multiplexed HTTP/2 session.
38 class QUICHE_EXPORT OgHttp2Session : public Http2Session,
39                                      public spdy::SpdyFramerVisitorInterface {
40  public:
41   struct QUICHE_EXPORT Options {
42     // Returns whether to send a WINDOW_UPDATE based on the window limit, window
43     // size, and delta that would be sent in the WINDOW_UPDATE.
44     WindowManager::ShouldWindowUpdateFn should_window_update_fn =
45         DeltaAtLeastHalfLimit;
46     // The perspective of this session.
47     Perspective perspective = Perspective::kClient;
48     // The maximum HPACK table size to use.
49     absl::optional<size_t> max_hpack_encoding_table_capacity = absl::nullopt;
50     // The maximum number of decoded header bytes that a stream can receive.
51     absl::optional<uint32_t> max_header_list_bytes = absl::nullopt;
52     // The maximum size of an individual header field, including name and value.
53     absl::optional<uint32_t> max_header_field_size = absl::nullopt;
54     // Whether to automatically send PING acks when receiving a PING.
55     bool auto_ping_ack = true;
56     // Whether (as server) to send a RST_STREAM NO_ERROR when sending a fin on
57     // an incomplete stream.
58     bool rst_stream_no_error_when_incomplete = false;
59     // Whether (as server) to queue trailers until after a stream's data source
60     // has indicated the end of data. If false, the server will assume that
61     // submitting trailers indicates the end of data.
62     bool trailers_require_end_data = false;
63     // Whether to mark all input data as consumed upon encountering a connection
64     // error while processing bytes. If true, subsequent processing will also
65     // mark all input data as consumed.
66     bool blackhole_data_on_connection_error = true;
67     // Whether to advertise support for the extended CONNECT semantics described
68     // in RFC 8441. If true, this endpoint will send the appropriate setting in
69     // initial SETTINGS.
70     bool allow_extended_connect = true;
71     // Whether to allow `obs-text` (characters from hexadecimal 0x80 to 0xff) in
72     // header field values.
73     bool allow_obs_text = true;
74     // If true, validates header field names and values according to RFC 7230
75     // and RFC 7540.
76     bool validate_http_headers = true;
77   };
78 
79   OgHttp2Session(Http2VisitorInterface& visitor, Options options);
80   ~OgHttp2Session() override;
81 
82   // Enqueues a frame for transmission to the peer.
83   void EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame);
84 
85   // Starts a graceful shutdown sequence. No-op if a GOAWAY has already been
86   // sent.
87   void StartGracefulShutdown();
88 
89   // Invokes the visitor's OnReadyToSend() method for serialized frames and
90   // DataFrameSource::Send() for data frames.
91   int Send();
92 
93   int32_t SubmitRequest(absl::Span<const Header> headers,
94                         std::unique_ptr<DataFrameSource> data_source,
95                         void* user_data);
96   int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
97                      std::unique_ptr<DataFrameSource> data_source);
98   int SubmitTrailer(Http2StreamId stream_id, absl::Span<const Header> trailers);
99   void SubmitMetadata(Http2StreamId stream_id,
100                       std::unique_ptr<MetadataSource> source);
101   void SubmitSettings(absl::Span<const Http2Setting> settings);
102 
IsServerSession()103   bool IsServerSession() const {
104     return options_.perspective == Perspective::kServer;
105   }
GetHighestReceivedStreamId()106   Http2StreamId GetHighestReceivedStreamId() const {
107     return highest_received_stream_id_;
108   }
109   void SetStreamUserData(Http2StreamId stream_id, void* user_data);
110   void* GetStreamUserData(Http2StreamId stream_id);
111 
112   // Resumes a stream that was previously blocked. Returns true on success.
113   bool ResumeStream(Http2StreamId stream_id);
114 
115   // Returns the peer's outstanding stream receive window for the given stream.
116   int GetStreamSendWindowSize(Http2StreamId stream_id) const;
117 
118   // Returns the current upper bound on the flow control receive window for this
119   // stream.
120   int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const;
121 
122   // Returns the outstanding stream receive window, or -1 if the stream does not
123   // exist.
124   int GetStreamReceiveWindowSize(Http2StreamId stream_id) const;
125 
126   // Returns the outstanding connection receive window.
127   int GetReceiveWindowSize() const;
128 
129   // Returns the size of the HPACK encoder's dynamic table, including the
130   // per-entry overhead from the specification.
131   int GetHpackEncoderDynamicTableSize() const;
132 
133   // Returns the maximum capacity of the HPACK encoder's dynamic table.
134   int GetHpackEncoderDynamicTableCapacity() const;
135 
136   // Returns the size of the HPACK decoder's dynamic table, including the
137   // per-entry overhead from the specification.
138   int GetHpackDecoderDynamicTableSize() const;
139 
140   // Returns the size of the HPACK decoder's most recently applied size limit.
141   int GetHpackDecoderSizeLimit() const;
142 
143   // From Http2Session.
144   int64_t ProcessBytes(absl::string_view bytes) override;
145   int Consume(Http2StreamId stream_id, size_t num_bytes) override;
want_read()146   bool want_read() const override {
147     return !received_goaway_ && !decoder_.HasError();
148   }
want_write()149   bool want_write() const override {
150     return !fatal_send_error_ &&
151            (!frames_.empty() || !buffered_data_.empty() || HasReadyStream() ||
152             !goaway_rejected_streams_.empty());
153   }
GetRemoteWindowSize()154   int GetRemoteWindowSize() const override { return connection_send_window_; }
peer_enables_connect_protocol()155   bool peer_enables_connect_protocol() {
156     return peer_enables_connect_protocol_;
157   }
158 
159   // From SpdyFramerVisitorInterface
160   void OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
161                std::string detailed_error) override;
162   void OnCommonHeader(spdy::SpdyStreamId /*stream_id*/, size_t /*length*/,
163                       uint8_t /*type*/, uint8_t /*flags*/) override;
164   void OnDataFrameHeader(spdy::SpdyStreamId stream_id, size_t length,
165                          bool fin) override;
166   void OnStreamFrameData(spdy::SpdyStreamId stream_id, const char* data,
167                          size_t len) override;
168   void OnStreamEnd(spdy::SpdyStreamId stream_id) override;
169   void OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/,
170                          size_t /*value*/) override;
171   void OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) override;
172   spdy::SpdyHeadersHandlerInterface* OnHeaderFrameStart(
173       spdy::SpdyStreamId stream_id) override;
174   void OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) override;
175   void OnRstStream(spdy::SpdyStreamId stream_id,
176                    spdy::SpdyErrorCode error_code) override;
177   void OnSettings() override;
178   void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
179   void OnSettingsEnd() override;
180   void OnSettingsAck() override;
181   void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override;
182   void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
183                 spdy::SpdyErrorCode error_code) override;
184   bool OnGoAwayFrameData(const char* goaway_data, size_t len) override;
185   void OnHeaders(spdy::SpdyStreamId stream_id, size_t payload_length,
186                  bool has_priority, int weight,
187                  spdy::SpdyStreamId parent_stream_id, bool exclusive, bool fin,
188                  bool end) override;
189   void OnWindowUpdate(spdy::SpdyStreamId stream_id,
190                       int delta_window_size) override;
191   void OnPushPromise(spdy::SpdyStreamId stream_id,
192                      spdy::SpdyStreamId promised_stream_id, bool end) override;
193   void OnContinuation(spdy::SpdyStreamId stream_id, size_t payload_length,
194                       bool end) override;
195   void OnAltSvc(spdy::SpdyStreamId /*stream_id*/, absl::string_view /*origin*/,
196                 const spdy::SpdyAltSvcWireFormat::
197                     AlternativeServiceVector& /*altsvc_vector*/) override;
198   void OnPriority(spdy::SpdyStreamId stream_id,
199                   spdy::SpdyStreamId parent_stream_id, int weight,
200                   bool exclusive) override;
201   void OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id,
202                         absl::string_view priority_field_value) override;
203   bool OnUnknownFrame(spdy::SpdyStreamId stream_id,
204                       uint8_t frame_type) override;
205   void OnUnknownFrameStart(spdy::SpdyStreamId stream_id, size_t length,
206                            uint8_t type, uint8_t flags) override;
207   void OnUnknownFramePayload(spdy::SpdyStreamId stream_id,
208                              absl::string_view payload) override;
209 
210   // Invoked when header processing encounters an invalid or otherwise
211   // problematic header.
212   void OnHeaderStatus(Http2StreamId stream_id,
213                       Http2VisitorInterface::OnHeaderResult result);
214 
215  private:
216   struct QUICHE_EXPORT StreamState {
StreamStateStreamState217     StreamState(int32_t stream_receive_window, int32_t stream_send_window,
218                 WindowManager::WindowUpdateListener listener,
219                 WindowManager::ShouldWindowUpdateFn should_window_update_fn)
220         : window_manager(stream_receive_window, std::move(listener),
221                          std::move(should_window_update_fn),
222                          /*update_window_on_notify=*/false),
223           send_window(stream_send_window) {}
224 
225     WindowManager window_manager;
226     std::unique_ptr<DataFrameSource> outbound_body;
227     std::unique_ptr<spdy::Http2HeaderBlock> trailers;
228     void* user_data = nullptr;
229     int32_t send_window;
230     absl::optional<HeaderType> received_header_type;
231     absl::optional<size_t> remaining_content_length;
232     bool half_closed_local = false;
233     bool half_closed_remote = false;
234     // Indicates that `outbound_body` temporarily cannot produce data.
235     bool data_deferred = false;
236     bool sent_head_method = false;
237     bool can_receive_body = true;
238   };
239   using StreamStateMap = absl::flat_hash_map<Http2StreamId, StreamState>;
240 
241   struct QUICHE_EXPORT PendingStreamState {
242     spdy::Http2HeaderBlock headers;
243     std::unique_ptr<DataFrameSource> data_source;
244     void* user_data = nullptr;
245   };
246 
247   class QUICHE_EXPORT PassthroughHeadersHandler
248       : public spdy::SpdyHeadersHandlerInterface {
249    public:
250     PassthroughHeadersHandler(OgHttp2Session& session,
251                               Http2VisitorInterface& visitor);
252 
set_stream_id(Http2StreamId stream_id)253     void set_stream_id(Http2StreamId stream_id) {
254       stream_id_ = stream_id;
255       result_ = Http2VisitorInterface::HEADER_OK;
256     }
257 
set_frame_contains_fin()258     void set_frame_contains_fin() { frame_contains_fin_ = true; }
set_header_type(HeaderType type)259     void set_header_type(HeaderType type) { type_ = type; }
header_type()260     HeaderType header_type() const { return type_; }
261 
262     void OnHeaderBlockStart() override;
263     void OnHeader(absl::string_view key, absl::string_view value) override;
264     void OnHeaderBlockEnd(size_t /* uncompressed_header_bytes */,
265                           size_t /* compressed_header_bytes */) override;
status_header()266     absl::string_view status_header() const {
267       QUICHE_DCHECK(type_ == HeaderType::RESPONSE ||
268                     type_ == HeaderType::RESPONSE_100);
269       return validator_->status_header();
270     }
content_length()271     absl::optional<size_t> content_length() const {
272       return validator_->content_length();
273     }
SetAllowExtendedConnect()274     void SetAllowExtendedConnect() { validator_->SetAllowExtendedConnect(); }
SetMaxFieldSize(uint32_t field_size)275     void SetMaxFieldSize(uint32_t field_size) {
276       validator_->SetMaxFieldSize(field_size);
277     }
SetAllowObsText(bool allow)278     void SetAllowObsText(bool allow) {
279       validator_->SetObsTextOption(allow ? ObsTextOption::kAllow
280                                          : ObsTextOption::kDisallow);
281     }
282     bool CanReceiveBody() const;
283 
284    private:
285     OgHttp2Session& session_;
286     Http2VisitorInterface& visitor_;
287     Http2StreamId stream_id_ = 0;
288     Http2VisitorInterface::OnHeaderResult result_ =
289         Http2VisitorInterface::HEADER_OK;
290     // Validates header blocks according to the HTTP/2 specification.
291     std::unique_ptr<HeaderValidatorBase> validator_;
292     HeaderType type_ = HeaderType::RESPONSE;
293     bool frame_contains_fin_ = false;
294   };
295 
296   struct QUICHE_EXPORT ProcessBytesResultVisitor;
297 
298   // Queues the connection preface, if not already done. If not
299   // `sending_outbound_settings` and the preface has not yet been queued, this
300   // method will generate and enqueue initial SETTINGS.
301   void MaybeSetupPreface(bool sending_outbound_settings);
302 
303   // Gets the settings to be sent in the initial SETTINGS frame sent as part of
304   // the connection preface.
305   std::vector<Http2Setting> GetInitialSettings() const;
306 
307   // Prepares and returns a SETTINGS frame with the given `settings`.
308   std::unique_ptr<spdy::SpdySettingsIR> PrepareSettingsFrame(
309       absl::Span<const Http2Setting> settings);
310 
311   // Updates internal state to match the SETTINGS advertised to the peer.
312   void HandleOutboundSettings(const spdy::SpdySettingsIR& settings_frame);
313 
314   void SendWindowUpdate(Http2StreamId stream_id, size_t update_delta);
315 
316   enum class SendResult {
317     // All data was flushed.
318     SEND_OK,
319     // Not all data was flushed (due to flow control or TCP back pressure).
320     SEND_BLOCKED,
321     // An error occurred while sending data.
322     SEND_ERROR,
323   };
324 
325   // Returns the int corresponding to the `result`, updating state as needed.
326   int InterpretSendResult(SendResult result);
327 
328   enum class ProcessBytesError {
329     // A general, unspecified error.
330     kUnspecified,
331     // The (server-side) session received an invalid client connection preface.
332     kInvalidConnectionPreface,
333     // A user/visitor callback failed with a fatal error.
334     kVisitorCallbackFailed,
335   };
336   using ProcessBytesResult = absl::variant<int64_t, ProcessBytesError>;
337 
338   // Attempts to process `bytes` and returns the number of bytes proccessed on
339   // success or the processing error on failure.
340   ProcessBytesResult ProcessBytesImpl(absl::string_view bytes);
341 
342   // Returns true if at least one stream has data or control frames to write.
343   bool HasReadyStream() const;
344 
345   // Returns the next stream that has something to write. If there are no such
346   // streams, returns zero.
347   Http2StreamId GetNextReadyStream();
348 
349   // Sends the buffered connection preface or serialized frame data, if any.
350   SendResult MaybeSendBufferedData();
351 
352   // Serializes and sends queued frames.
353   SendResult SendQueuedFrames();
354 
355   // Returns false if a fatal connection error occurred.
356   bool AfterFrameSent(uint8_t frame_type_int, uint32_t stream_id,
357                       size_t payload_length, uint8_t flags,
358                       uint32_t error_code);
359 
360   // Writes DATA frames for stream `stream_id`.
361   SendResult WriteForStream(Http2StreamId stream_id);
362 
363   void SerializeMetadata(Http2StreamId stream_id,
364                          std::unique_ptr<MetadataSource> source);
365 
366   void SendHeaders(Http2StreamId stream_id, spdy::Http2HeaderBlock headers,
367                    bool end_stream);
368 
369   void SendTrailers(Http2StreamId stream_id, spdy::Http2HeaderBlock trailers);
370 
371   // Encapsulates the RST_STREAM NO_ERROR behavior described in RFC 7540
372   // Section 8.1.
373   void MaybeFinWithRstStream(StreamStateMap::iterator iter);
374 
375   // Performs flow control accounting for data sent by the peer.
376   void MarkDataBuffered(Http2StreamId stream_id, size_t bytes);
377 
378   // Creates a stream for `stream_id` if not already present and returns an
379   // iterator pointing to it.
380   StreamStateMap::iterator CreateStream(Http2StreamId stream_id);
381 
382   // Creates a stream for `stream_id`, stores the `data_source` and `user_data`
383   // in the stream state, and sends the `headers`.
384   void StartRequest(Http2StreamId stream_id, spdy::Http2HeaderBlock headers,
385                     std::unique_ptr<DataFrameSource> data_source,
386                     void* user_data);
387 
388   // Sends headers for pending streams as long as the stream limit allows.
389   void StartPendingStreams();
390 
391   // Closes the given `stream_id` with the given `error_code`.
392   void CloseStream(Http2StreamId stream_id, Http2ErrorCode error_code);
393 
394   // Calculates the next expected header type for a stream in a given state.
395   HeaderType NextHeaderType(absl::optional<HeaderType> current_type);
396 
397   // Returns true if the session can create a new stream.
398   bool CanCreateStream() const;
399 
400   // Informs the visitor of the connection `error` and stops processing on the
401   // connection. If server-side, also sends a GOAWAY with `error_code`.
402   void LatchErrorAndNotify(Http2ErrorCode error_code,
403                            Http2VisitorInterface::ConnectionError error);
404 
405   void CloseStreamIfReady(uint8_t frame_type, uint32_t stream_id);
406 
407   // Informs the visitor of rejected, non-active streams due to GOAWAY receipt.
408   void CloseGoAwayRejectedStreams();
409 
410   // Updates internal state to prepare for sending an immediate GOAWAY.
411   void PrepareForImmediateGoAway();
412 
413   // Handles the potential end of received metadata for the given `stream_id`.
414   void MaybeHandleMetadataEndForStream(Http2StreamId stream_id);
415 
416   void DecrementQueuedFrameCount(uint32_t stream_id, uint8_t frame_type);
417 
418   void HandleContentLengthError(Http2StreamId stream_id);
419 
420   // Invoked when sending a flow control window update to the peer.
421   void UpdateReceiveWindow(Http2StreamId stream_id, int32_t delta);
422 
423   // Updates stream send window accounting to respect the peer's advertised
424   // initial window setting.
425   void UpdateStreamSendWindowSizes(uint32_t new_value);
426 
427   // Updates stream receive window managers to use the newly advertised stream
428   // initial window.
429   void UpdateStreamReceiveWindowSizes(uint32_t new_value);
430 
431   // Receives events when inbound frames are parsed.
432   Http2VisitorInterface& visitor_;
433 
434   const Options options_;
435 
436   // Forwards received events to the session if it can accept them.
437   EventForwarder event_forwarder_;
438 
439   // Logs received frames when enabled.
440   Http2TraceLogger receive_logger_;
441   // Logs sent frames when enabled.
442   Http2FrameLogger send_logger_;
443 
444   // Encodes outbound frames.
445   spdy::SpdyFramer framer_{spdy::SpdyFramer::ENABLE_COMPRESSION};
446 
447   // Decodes inbound frames.
448   http2::Http2DecoderAdapter decoder_;
449 
450   // Maintains the state of active streams known to this session.
451   StreamStateMap stream_map_;
452 
453   // Maintains the state of pending streams known to this session. A pending
454   // stream is kept in this list until it can be created while complying with
455   // `max_outbound_concurrent_streams_`.
456   quiche::QuicheLinkedHashMap<Http2StreamId, PendingStreamState>
457       pending_streams_;
458 
459   // The queue of outbound frames.
460   std::list<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
461   // Buffered data (connection preface, serialized frames) that has not yet been
462   // sent.
463   std::string buffered_data_;
464 
465   // Maintains the set of streams ready to write data to the peer.
466   using WriteScheduler = PriorityWriteScheduler<Http2StreamId>;
467   WriteScheduler write_scheduler_;
468 
469   // Stores the queue of callbacks to invoke upon receiving SETTINGS acks. At
470   // most one callback is invoked for each SETTINGS ack.
471   using SettingsAckCallback = std::function<void()>;
472   std::list<SettingsAckCallback> settings_ack_callbacks_;
473 
474   // Delivers header name-value pairs to the visitor.
475   PassthroughHeadersHandler headers_handler_;
476 
477   // Ignores header data, e.g., for an unknown or rejected stream.
478   spdy::NoOpHeadersHandler noop_headers_handler_;
479 
480   // Tracks the remaining client connection preface, in the case of a server
481   // session.
482   absl::string_view remaining_preface_;
483 
484   WindowManager connection_window_manager_;
485 
486   // Tracks the streams that have been marked for reset. A stream is removed
487   // from this set once it is closed.
488   absl::flat_hash_set<Http2StreamId> streams_reset_;
489 
490   // The number of frames currently queued per stream.
491   absl::flat_hash_map<Http2StreamId, int> queued_frames_;
492   // Includes streams that are currently ready to write trailers.
493   absl::flat_hash_set<Http2StreamId> trailers_ready_;
494   // Includes streams that will not be written due to receipt of GOAWAY.
495   absl::flat_hash_set<Http2StreamId> goaway_rejected_streams_;
496 
497   Http2StreamId next_stream_id_ = 1;
498   // The highest received stream ID is the highest stream ID in any frame read
499   // from the peer. The highest processed stream ID is the highest stream ID for
500   // which this endpoint created a stream in the stream map.
501   Http2StreamId highest_received_stream_id_ = 0;
502   Http2StreamId highest_processed_stream_id_ = 0;
503   Http2StreamId received_goaway_stream_id_ = 0;
504   size_t metadata_length_ = 0;
505   int32_t connection_send_window_ = kInitialFlowControlWindowSize;
506   // The initial flow control receive window size for any newly created streams.
507   int32_t initial_stream_receive_window_ = kInitialFlowControlWindowSize;
508   // The initial flow control send window size for any newly created streams.
509   int32_t initial_stream_send_window_ = kInitialFlowControlWindowSize;
510   uint32_t max_frame_payload_ = kDefaultFramePayloadSizeLimit;
511   // The maximum number of concurrent streams that this connection can open to
512   // its peer and allow from its peer, respectively. Although the initial value
513   // is unlimited, the spec encourages a value of at least 100. We limit
514   // ourselves to opening 100 until told otherwise by the peer and allow an
515   // unlimited number from the peer until updated from SETTINGS we send.
516   uint32_t max_outbound_concurrent_streams_ = 100u;
517   uint32_t pending_max_inbound_concurrent_streams_ =
518       std::numeric_limits<uint32_t>::max();
519   uint32_t max_inbound_concurrent_streams_ =
520       std::numeric_limits<uint32_t>::max();
521 
522   // The HPACK encoder header table capacity that will be applied when
523   // acking SETTINGS from the peer. Only contains a value if the peer advertises
524   // a larger table capacity than currently used; a smaller value can safely be
525   // applied immediately upon receipt.
526   absl::optional<uint32_t> encoder_header_table_capacity_when_acking_;
527 
528   bool received_goaway_ = false;
529   bool queued_preface_ = false;
530   bool peer_supports_metadata_ = false;
531   bool end_metadata_ = false;
532   bool process_metadata_ = false;
533   bool sent_non_ack_settings_ = false;
534 
535   // Recursion guard for ProcessBytes().
536   bool processing_bytes_ = false;
537   // Recursion guard for Send().
538   bool sending_ = false;
539 
540   bool peer_enables_connect_protocol_ = false;
541 
542   // Replace this with a stream ID, for multiple GOAWAY support.
543   bool queued_goaway_ = false;
544   bool queued_immediate_goaway_ = false;
545   bool latched_error_ = false;
546 
547   // True if a fatal sending error has occurred.
548   bool fatal_send_error_ = false;
549 
550   // True if a fatal processing visitor callback failed.
551   bool fatal_visitor_callback_failure_ = false;
552 };
553 
554 }  // namespace adapter
555 }  // namespace http2
556 
557 #endif  // QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_
558