| #ifndef QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_ |
| #define QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_ |
| |
| #include <list> |
| |
| #include "http2/adapter/http2_session.h" |
| #include "http2/adapter/http2_util.h" |
| #include "http2/adapter/http2_visitor_interface.h" |
| #include "http2/adapter/window_manager.h" |
| #include "common/platform/api/quiche_bug_tracker.h" |
| #include "spdy/core/http2_frame_decoder_adapter.h" |
| #include "spdy/core/spdy_framer.h" |
| |
| namespace http2 { |
| namespace adapter { |
| |
| // This class manages state associated with a single multiplexed HTTP/2 session. |
| class OgHttp2Session : public Http2Session, |
| public spdy::SpdyFramerVisitorInterface { |
| public: |
| struct Options { |
| Perspective perspective = Perspective::kClient; |
| }; |
| |
| OgHttp2Session(Http2VisitorInterface& visitor, Options /*options*/); |
| ~OgHttp2Session() override; |
| |
| // Enqueues a frame for transmission to the peer. |
| void EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame); |
| |
| // If |want_write()| returns true, this method will return a non-empty string |
| // containing serialized HTTP/2 frames to write to the peer. |
| std::string GetBytesToWrite(absl::optional<size_t> max_bytes); |
| |
| // From Http2Session. |
| ssize_t ProcessBytes(absl::string_view bytes) override; |
| int Consume(Http2StreamId stream_id, size_t num_bytes) override; |
| bool want_read() const override { return !received_goaway_; } |
| bool want_write() const override { |
| return !frames_.empty() || !serialized_prefix_.empty(); |
| } |
| int GetRemoteWindowSize() const override { |
| return peer_window_; |
| } |
| |
| // From SpdyFramerVisitorInterface |
| void OnError(http2::Http2DecoderAdapter::SpdyFramerError error, |
| std::string detailed_error) override; |
| void OnCommonHeader(spdy::SpdyStreamId /*stream_id*/, |
| size_t /*length*/, |
| uint8_t /*type*/, |
| uint8_t /*flags*/) override; |
| void OnDataFrameHeader(spdy::SpdyStreamId stream_id, |
| size_t length, |
| bool fin) override; |
| void OnStreamFrameData(spdy::SpdyStreamId stream_id, |
| const char* data, |
| size_t len) override; |
| void OnStreamEnd(spdy::SpdyStreamId stream_id) override; |
| void OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/, |
| size_t /*value*/) override; |
| void OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) override; |
| spdy::SpdyHeadersHandlerInterface* OnHeaderFrameStart( |
| spdy::SpdyStreamId stream_id) override; |
| void OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) override; |
| void OnRstStream(spdy::SpdyStreamId stream_id, |
| spdy::SpdyErrorCode error_code) override; |
| void OnSettings() override; |
| void OnSetting(spdy::SpdySettingsId id, uint32_t value) override; |
| void OnSettingsEnd() override; |
| void OnSettingsAck() override; |
| void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override; |
| void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id, |
| spdy::SpdyErrorCode error_code) override; |
| bool OnGoAwayFrameData(const char* goaway_data, size_t len); |
| void OnHeaders(spdy::SpdyStreamId stream_id, |
| bool has_priority, |
| int weight, |
| spdy::SpdyStreamId parent_stream_id, |
| bool exclusive, |
| bool fin, |
| bool end) override; |
| void OnWindowUpdate(spdy::SpdyStreamId stream_id, |
| int delta_window_size) override; |
| void OnPushPromise(spdy::SpdyStreamId stream_id, |
| spdy::SpdyStreamId promised_stream_id, |
| bool end) override; |
| void OnContinuation(spdy::SpdyStreamId stream_id, bool end) override; |
| void OnAltSvc(spdy::SpdyStreamId /*stream_id*/, |
| absl::string_view /*origin*/, |
| const spdy::SpdyAltSvcWireFormat:: |
| AlternativeServiceVector& /*altsvc_vector*/); |
| void OnPriority(spdy::SpdyStreamId stream_id, |
| spdy::SpdyStreamId parent_stream_id, |
| int weight, |
| bool exclusive) override; |
| void OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id, |
| absl::string_view priority_field_value) override; |
| bool OnUnknownFrame(spdy::SpdyStreamId stream_id, |
| uint8_t frame_type) override; |
| |
| private: |
| struct StreamState { |
| WindowManager window_manager; |
| int32_t send_window = 65535; |
| bool half_closed_local = false; |
| bool half_closed_remote = false; |
| }; |
| |
| class PassthroughHeadersHandler : public spdy::SpdyHeadersHandlerInterface { |
| public: |
| explicit PassthroughHeadersHandler(Http2VisitorInterface& visitor) |
| : visitor_(visitor) {} |
| void set_stream_id(Http2StreamId stream_id) { stream_id_ = stream_id; } |
| void OnHeaderBlockStart() override; |
| void OnHeader(absl::string_view key, absl::string_view value) override; |
| void OnHeaderBlockEnd(size_t /* uncompressed_header_bytes */, |
| size_t /* compressed_header_bytes */) override; |
| |
| private: |
| Http2VisitorInterface& visitor_; |
| Http2StreamId stream_id_ = 0; |
| }; |
| |
| Http2VisitorInterface& visitor_; |
| spdy::SpdyFramer framer_{spdy::SpdyFramer::ENABLE_COMPRESSION}; |
| http2::Http2DecoderAdapter decoder_; |
| absl::flat_hash_map<Http2StreamId, StreamState> stream_map_; |
| std::list<std::unique_ptr<spdy::SpdyFrameIR>> frames_; |
| PassthroughHeadersHandler headers_handler_; |
| std::string serialized_prefix_; |
| absl::string_view remaining_preface_; |
| int peer_window_ = 65535; |
| Options options_; |
| bool received_goaway_ = false; |
| }; |
| |
| } // namespace adapter |
| } // namespace http2 |
| |
| #endif // QUICHE_HTTP2_ADAPTER_OGHTTP2_SESSION_H_ |