Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h
new file mode 100644
index 0000000..00f241e
--- /dev/null
+++ b/quic/core/http/quic_spdy_session.h
@@ -0,0 +1,283 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
+#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
+
+#include <cstddef>
+#include <memory>
+
+#include "base/macros.h"
+#include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
+#include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h"
+#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
+
+namespace quic {
+
+namespace test {
+class QuicSpdySessionPeer;
+}  // namespace test
+
+// QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
+// dynamics.  Specifically, it is to help predict the compression
+// penalty of avoiding HoL by chagning how the dynamic table is used.
+// In chromium, the concrete instance populates an UMA
+// histogram with the data.
+class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
+ public:
+  QuicHpackDebugVisitor();
+  QuicHpackDebugVisitor(const QuicHpackDebugVisitor&) = delete;
+  QuicHpackDebugVisitor& operator=(const QuicHpackDebugVisitor&) = delete;
+
+  virtual ~QuicHpackDebugVisitor();
+
+  // For each HPACK indexed representation processed, |elapsed| is
+  // the time since the corresponding entry was added to the dynamic
+  // table.
+  virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
+};
+
+// A QUIC session with a headers stream.
+class QUIC_EXPORT_PRIVATE QuicSpdySession
+    : public QuicSession,
+      public QpackEncoder::DecoderStreamErrorDelegate,
+      public QpackEncoderStreamSender::Delegate,
+      public QpackDecoder::EncoderStreamErrorDelegate,
+      public QpackDecoderStreamSender::Delegate {
+ public:
+  // Does not take ownership of |connection| or |visitor|.
+  QuicSpdySession(QuicConnection* connection,
+                  QuicSession::Visitor* visitor,
+                  const QuicConfig& config,
+                  const ParsedQuicVersionVector& supported_versions);
+  QuicSpdySession(const QuicSpdySession&) = delete;
+  QuicSpdySession& operator=(const QuicSpdySession&) = delete;
+
+  ~QuicSpdySession() override;
+
+  void Initialize() override;
+
+  // QpackEncoder::DecoderStreamErrorDelegate implementation.
+  void OnDecoderStreamError(QuicStringPiece error_message) override;
+
+  // QpackEncoderStreamSender::Delegate implemenation.
+  void WriteEncoderStreamData(QuicStringPiece data) override;
+
+  // QpackDecoder::EncoderStreamErrorDelegate implementation.
+  void OnEncoderStreamError(QuicStringPiece error_message) override;
+
+  // QpackDecoderStreamSender::Delegate implementation.
+  void WriteDecoderStreamData(QuicStringPiece data) override;
+
+  // Called by |headers_stream_| when headers with a priority have been
+  // received for a stream.  This method will only be called for server streams.
+  virtual void OnStreamHeadersPriority(QuicStreamId stream_id,
+                                       spdy::SpdyPriority priority);
+
+  // Called by |headers_stream_| when headers have been completely received
+  // for a stream.  |fin| will be true if the fin flag was set in the headers
+  // frame.
+  virtual void OnStreamHeaderList(QuicStreamId stream_id,
+                                  bool fin,
+                                  size_t frame_len,
+                                  const QuicHeaderList& header_list);
+
+  // Called by |headers_stream_| when push promise headers have been
+  // completely received.  |fin| will be true if the fin flag was set
+  // in the headers.
+  virtual void OnPromiseHeaderList(QuicStreamId stream_id,
+                                   QuicStreamId promised_stream_id,
+                                   size_t frame_len,
+                                   const QuicHeaderList& header_list);
+
+  // Called by |headers_stream_| when a PRIORITY frame has been received for a
+  // stream. This method will only be called for server streams.
+  virtual void OnPriorityFrame(QuicStreamId stream_id,
+                               spdy::SpdyPriority priority);
+
+  // Sends contents of |iov| to h2_deframer_, returns number of bytes processed.
+  size_t ProcessHeaderData(const struct iovec& iov);
+
+  // Writes |headers| for the stream |id| to the dedicated headers stream.
+  // If |fin| is true, then no more data will be sent for the stream |id|.
+  // If provided, |ack_notifier_delegate| will be registered to be notified when
+  // we have seen ACKs for all packets resulting from this call.
+  virtual size_t WriteHeadersOnHeadersStream(
+      QuicStreamId id,
+      spdy::SpdyHeaderBlock headers,
+      bool fin,
+      spdy::SpdyPriority priority,
+      QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
+  // Writes a PRIORITY frame the to peer. Returns the size in bytes of the
+  // resulting PRIORITY frame for QUIC_VERSION_43 and above. Otherwise, does
+  // nothing and returns 0.
+  size_t WritePriority(QuicStreamId id,
+                       QuicStreamId parent_stream_id,
+                       int weight,
+                       bool exclusive);
+
+  // Write |headers| for |promised_stream_id| on |original_stream_id| in a
+  // PUSH_PROMISE frame to peer.
+  // Return the size, in bytes, of the resulting PUSH_PROMISE frame.
+  virtual size_t WritePushPromise(QuicStreamId original_stream_id,
+                                  QuicStreamId promised_stream_id,
+                                  spdy::SpdyHeaderBlock headers);
+
+  // Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
+  size_t SendMaxHeaderListSize(size_t value);
+
+  QpackEncoder* qpack_encoder();
+  QpackDecoder* qpack_decoder();
+  QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
+
+  bool server_push_enabled() const { return server_push_enabled_; }
+
+  // Called by |QuicHeadersStream::UpdateEnableServerPush()| with
+  // value from SETTINGS_ENABLE_PUSH.
+  void set_server_push_enabled(bool enable) { server_push_enabled_ = enable; }
+
+  // Return true if this session wants to release headers stream's buffer
+  // aggressively.
+  virtual bool ShouldReleaseHeadersStreamSequencerBuffer();
+
+  void CloseConnectionWithDetails(QuicErrorCode error,
+                                  const QuicString& details);
+
+  void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
+    max_inbound_header_list_size_ = max_inbound_header_list_size;
+  }
+
+ protected:
+  // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
+  // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
+  // make sure that all data streams are QuicSpdyStreams.
+  QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0;
+  QuicSpdyStream* CreateIncomingStream(PendingStream pending) override = 0;
+  virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
+  virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
+
+  QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
+
+  // If an incoming stream can be created, return true.
+  virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
+
+  // If an outgoing bidirectional/unidirectional stream can be created, return
+  // true.
+  virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
+  virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
+
+  // Returns true if there are open HTTP requests.
+  bool ShouldKeepConnectionAlive() const override;
+
+  // Overridden to buffer incoming streams for version 99.
+  bool ShouldBufferIncomingStream(QuicStreamId id) const override;
+
+  size_t WriteHeadersOnHeadersStreamImpl(
+      QuicStreamId id,
+      spdy::SpdyHeaderBlock headers,
+      bool fin,
+      QuicStreamId parent_stream_id,
+      int weight,
+      bool exclusive,
+      QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
+  void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+
+  bool supports_push_promise() { return supports_push_promise_; }
+
+  // Optional, enables instrumentation related to go/quic-hpack.
+  void SetHpackEncoderDebugVisitor(
+      std::unique_ptr<QuicHpackDebugVisitor> visitor);
+  void SetHpackDecoderDebugVisitor(
+      std::unique_ptr<QuicHpackDebugVisitor> visitor);
+
+  // Sets the maximum size of the header compression table spdy_framer_ is
+  // willing to use to encode header blocks.
+  void UpdateHeaderEncoderTableSize(uint32_t value);
+
+  // Called when SETTINGS_ENABLE_PUSH is received, only supported on
+  // server side.
+  void UpdateEnableServerPush(bool value);
+
+  bool IsConnected() { return connection()->connected(); }
+
+  // Sets how much encoded data the hpack decoder of h2_deframer_ is willing to
+  // buffer.
+  void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
+    h2_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
+        max_decode_buffer_size_bytes);
+  }
+
+  void set_max_uncompressed_header_bytes(
+      size_t set_max_uncompressed_header_bytes);
+
+ private:
+  friend class test::QuicSpdySessionPeer;
+
+  class SpdyFramerVisitor;
+
+  // The following methods are called by the SimpleVisitor.
+
+  // Called when a HEADERS frame has been received.
+  void OnHeaders(spdy::SpdyStreamId stream_id,
+                 bool has_priority,
+                 spdy::SpdyPriority priority,
+                 bool fin);
+
+  // Called when a PUSH_PROMISE frame has been received.
+  void OnPushPromise(spdy::SpdyStreamId stream_id,
+                     spdy::SpdyStreamId promised_stream_id,
+                     bool end);
+
+  // Called when a PRIORITY frame has been received.
+  void OnPriority(spdy::SpdyStreamId stream_id, spdy::SpdyPriority priority);
+
+  // Called when the complete list of headers is available.
+  void OnHeaderList(const QuicHeaderList& header_list);
+
+  // Called when the size of the compressed frame payload is available.
+  void OnCompressedFrameSize(size_t frame_len);
+
+  std::unique_ptr<QpackEncoder> qpack_encoder_;
+  std::unique_ptr<QpackDecoder> qpack_decoder_;
+
+  // TODO(123528590): Remove this member.
+  std::unique_ptr<QuicHeadersStream> headers_stream_;
+
+  // The maximum size of a header block that will be accepted from the peer,
+  // defined per spec as key + value + overhead per field (uncompressed).
+  size_t max_inbound_header_list_size_;
+
+  // Set during handshake. If true, resources in x-associated-content and link
+  // headers will be pushed.
+  bool server_push_enabled_;
+
+  // Data about the stream whose headers are being processed.
+  QuicStreamId stream_id_;
+  QuicStreamId promised_stream_id_;
+  bool fin_;
+  size_t frame_len_;
+  size_t uncompressed_frame_len_;
+
+  bool supports_push_promise_;
+
+  spdy::SpdyFramer spdy_framer_;
+  http2::Http2DecoderAdapter h2_deframer_;
+  std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
+};
+
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_