blob: b0bc28b70027d59112da1d23006ed44090d36f78 [file] [log] [blame]
#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_