#include "quiche/http2/adapter/oghttp2_session.h"
#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "absl/cleanup/cleanup.h"
#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "quiche/http2/adapter/header_validator.h"
#include "quiche/http2/adapter/http2_protocol.h"
#include "quiche/http2/adapter/http2_util.h"
#include "quiche/http2/adapter/http2_visitor_interface.h"
#include "quiche/http2/adapter/noop_header_validator.h"
#include "quiche/http2/adapter/oghttp2_util.h"
#include "quiche/common/quiche_callbacks.h"
#include "quiche/spdy/core/spdy_protocol.h"
namespace http2 {
namespace adapter {
namespace {
ConnectionError;
DataFrameHeaderInfo;
SpdyFramerError;
SpdySettingsIR;
const uint32_t kMaxAllowedMetadataFrameSize = …;
const uint32_t kDefaultHpackTableCapacity = …;
const uint32_t kMaximumHpackTableCapacity = …;
const int kSendError = …;
constexpr absl::string_view kHeadValue = …;
class FrameAttributeCollector : public spdy::SpdyFrameVisitor { … };
absl::string_view TracePerspectiveAsString(Perspective p) { … }
Http2ErrorCode GetHttp2ErrorCode(SpdyFramerError error) { … }
bool IsResponse(HeaderType type) { … }
bool StatusIs1xx(absl::string_view status) { … }
uint32_t HpackCapacityBound(const OgHttp2Session::Options& o) { … }
bool IsNonAckSettings(const spdy::SpdyFrameIR& frame) { … }
}
OgHttp2Session::PassthroughHeadersHandler::PassthroughHeadersHandler(
OgHttp2Session& session, Http2VisitorInterface& visitor)
: … { … }
void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockStart() { … }
Http2VisitorInterface::OnHeaderResult InterpretHeaderStatus(
HeaderValidator::HeaderStatus status) { … }
void OgHttp2Session::PassthroughHeadersHandler::OnHeader(
absl::string_view key, absl::string_view value) { … }
void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockEnd(
size_t ,
size_t ) { … }
bool OgHttp2Session::PassthroughHeadersHandler::CanReceiveBody() const { … }
void OgHttp2Session::PassthroughHeadersHandler::SetResult(
Http2VisitorInterface::OnHeaderResult result) { … }
struct OgHttp2Session::ProcessBytesResultVisitor { … };
OgHttp2Session::OgHttp2Session(Http2VisitorInterface& visitor, Options options)
: … { … }
OgHttp2Session::~OgHttp2Session() { … }
void OgHttp2Session::SetStreamUserData(Http2StreamId stream_id,
void* user_data) { … }
void* OgHttp2Session::GetStreamUserData(Http2StreamId stream_id) { … }
bool OgHttp2Session::ResumeStream(Http2StreamId stream_id) { … }
int OgHttp2Session::GetStreamSendWindowSize(Http2StreamId stream_id) const { … }
int OgHttp2Session::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const { … }
int OgHttp2Session::GetStreamReceiveWindowSize(Http2StreamId stream_id) const { … }
int OgHttp2Session::GetReceiveWindowSize() const { … }
int OgHttp2Session::GetHpackEncoderDynamicTableSize() const { … }
int OgHttp2Session::GetHpackEncoderDynamicTableCapacity() const { … }
int OgHttp2Session::GetHpackDecoderDynamicTableSize() const { … }
int OgHttp2Session::GetHpackDecoderSizeLimit() const { … }
int64_t OgHttp2Session::ProcessBytes(absl::string_view bytes) { … }
absl::variant<int64_t, OgHttp2Session::ProcessBytesError>
OgHttp2Session::ProcessBytesImpl(absl::string_view bytes) { … }
int OgHttp2Session::Consume(Http2StreamId stream_id, size_t num_bytes) { … }
void OgHttp2Session::StartGracefulShutdown() { … }
void OgHttp2Session::EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame) { … }
int OgHttp2Session::Send() { … }
int OgHttp2Session::InterpretSendResult(SendResult result) { … }
bool OgHttp2Session::HasReadyStream() const { … }
Http2StreamId OgHttp2Session::GetNextReadyStream() { … }
int32_t OgHttp2Session::SubmitRequestInternal(
absl::Span<const Header> headers,
std::unique_ptr<DataFrameSource> data_source, bool end_stream,
void* user_data) { … }
int OgHttp2Session::SubmitResponseInternal(
Http2StreamId stream_id, absl::Span<const Header> headers,
std::unique_ptr<DataFrameSource> data_source, bool end_stream) { … }
OgHttp2Session::SendResult OgHttp2Session::MaybeSendBufferedData() { … }
OgHttp2Session::SendResult OgHttp2Session::SendQueuedFrames() { … }
bool OgHttp2Session::AfterFrameSent(uint8_t frame_type_int, uint32_t stream_id,
size_t payload_length, uint8_t flags,
uint32_t error_code) { … }
OgHttp2Session::SendResult OgHttp2Session::WriteForStream(
Http2StreamId stream_id) { … }
void OgHttp2Session::SerializeMetadata(Http2StreamId stream_id,
std::unique_ptr<MetadataSource> source) { … }
void OgHttp2Session::SerializeMetadata(Http2StreamId stream_id) { … }
int32_t OgHttp2Session::SubmitRequest(
absl::Span<const Header> headers,
std::unique_ptr<DataFrameSource> data_source, bool end_stream,
void* user_data) { … }
int OgHttp2Session::SubmitResponse(Http2StreamId stream_id,
absl::Span<const Header> headers,
std::unique_ptr<DataFrameSource> data_source,
bool end_stream) { … }
int OgHttp2Session::SubmitTrailer(Http2StreamId stream_id,
absl::Span<const Header> trailers) { … }
void OgHttp2Session::SubmitMetadata(Http2StreamId stream_id,
std::unique_ptr<MetadataSource> source) { … }
void OgHttp2Session::SubmitMetadata(Http2StreamId stream_id) { … }
void OgHttp2Session::SubmitSettings(absl::Span<const Http2Setting> settings) { … }
void OgHttp2Session::OnError(SpdyFramerError error,
std::string detailed_error) { … }
void OgHttp2Session::OnCommonHeader(spdy::SpdyStreamId stream_id, size_t length,
uint8_t type, uint8_t flags) { … }
void OgHttp2Session::OnDataFrameHeader(spdy::SpdyStreamId stream_id,
size_t length, bool ) { … }
void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id,
const char* data, size_t len) { … }
void OgHttp2Session::OnStreamEnd(spdy::SpdyStreamId stream_id) { … }
void OgHttp2Session::OnStreamPadLength(spdy::SpdyStreamId stream_id,
size_t value) { … }
void OgHttp2Session::OnStreamPadding(spdy::SpdyStreamId , size_t
) { … }
spdy::SpdyHeadersHandlerInterface* OgHttp2Session::OnHeaderFrameStart(
spdy::SpdyStreamId stream_id) { … }
void OgHttp2Session::OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) { … }
void OgHttp2Session::OnRstStream(spdy::SpdyStreamId stream_id,
spdy::SpdyErrorCode error_code) { … }
void OgHttp2Session::OnSettings() { … }
void OgHttp2Session::OnSetting(spdy::SpdySettingsId id, uint32_t value) { … }
void OgHttp2Session::OnSettingsEnd() { … }
void OgHttp2Session::OnSettingsAck() { … }
void OgHttp2Session::OnPing(spdy::SpdyPingId unique_id, bool is_ack) { … }
void OgHttp2Session::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
spdy::SpdyErrorCode error_code) { … }
bool OgHttp2Session::OnGoAwayFrameData(const char* , size_t
) { … }
void OgHttp2Session::OnHeaders(spdy::SpdyStreamId stream_id,
size_t , bool ,
int ,
spdy::SpdyStreamId ,
bool , bool fin, bool ) { … }
void OgHttp2Session::OnWindowUpdate(spdy::SpdyStreamId stream_id,
int delta_window_size) { … }
void OgHttp2Session::OnPushPromise(spdy::SpdyStreamId ,
spdy::SpdyStreamId ,
bool ) { … }
void OgHttp2Session::OnContinuation(spdy::SpdyStreamId ,
size_t , bool ) { … }
void OgHttp2Session::OnAltSvc(spdy::SpdyStreamId ,
absl::string_view ,
const spdy::SpdyAltSvcWireFormat::
AlternativeServiceVector& ) { … }
void OgHttp2Session::OnPriority(spdy::SpdyStreamId ,
spdy::SpdyStreamId ,
int , bool ) { … }
void OgHttp2Session::OnPriorityUpdate(
spdy::SpdyStreamId ,
absl::string_view ) { … }
bool OgHttp2Session::OnUnknownFrame(spdy::SpdyStreamId ,
uint8_t ) { … }
void OgHttp2Session::OnUnknownFrameStart(spdy::SpdyStreamId stream_id,
size_t length, uint8_t type,
uint8_t flags) { … }
void OgHttp2Session::OnUnknownFramePayload(spdy::SpdyStreamId stream_id,
absl::string_view payload) { … }
void OgHttp2Session::OnHeaderStatus(
Http2StreamId stream_id, Http2VisitorInterface::OnHeaderResult result) { … }
void OgHttp2Session::MaybeSetupPreface(bool sending_outbound_settings) { … }
std::vector<Http2Setting> OgHttp2Session::GetInitialSettings() const { … }
std::unique_ptr<SpdySettingsIR> OgHttp2Session::PrepareSettingsFrame(
absl::Span<const Http2Setting> settings) { … }
void OgHttp2Session::HandleOutboundSettings(
const spdy::SpdySettingsIR& settings_frame) { … }
void OgHttp2Session::SendWindowUpdate(Http2StreamId stream_id,
size_t update_delta) { … }
void OgHttp2Session::SendHeaders(Http2StreamId stream_id,
quiche::HttpHeaderBlock headers,
bool end_stream) { … }
void OgHttp2Session::SendTrailers(Http2StreamId stream_id,
quiche::HttpHeaderBlock trailers) { … }
void OgHttp2Session::MaybeFinWithRstStream(StreamStateMap::iterator iter) { … }
void OgHttp2Session::MarkDataBuffered(Http2StreamId stream_id, size_t bytes) { … }
OgHttp2Session::StreamStateMap::iterator OgHttp2Session::CreateStream(
Http2StreamId stream_id) { … }
void OgHttp2Session::StartRequest(Http2StreamId stream_id,
quiche::HttpHeaderBlock headers,
std::unique_ptr<DataFrameSource> data_source,
void* user_data, bool end_stream) { … }
void OgHttp2Session::StartPendingStreams() { … }
void OgHttp2Session::CloseStream(Http2StreamId stream_id,
Http2ErrorCode error_code) { … }
bool OgHttp2Session::CanCreateStream() const { … }
HeaderType OgHttp2Session::NextHeaderType(
std::optional<HeaderType> current_type) { … }
void OgHttp2Session::LatchErrorAndNotify(Http2ErrorCode error_code,
ConnectionError error) { … }
void OgHttp2Session::CloseStreamIfReady(uint8_t frame_type,
uint32_t stream_id) { … }
void OgHttp2Session::CloseGoAwayRejectedStreams() { … }
void OgHttp2Session::PrepareForImmediateGoAway() { … }
void OgHttp2Session::MaybeHandleMetadataEndForStream(Http2StreamId stream_id) { … }
void OgHttp2Session::DecrementQueuedFrameCount(uint32_t stream_id,
uint8_t frame_type) { … }
void OgHttp2Session::HandleContentLengthError(Http2StreamId stream_id) { … }
void OgHttp2Session::UpdateReceiveWindow(Http2StreamId stream_id,
int32_t delta) { … }
void OgHttp2Session::UpdateStreamSendWindowSizes(uint32_t new_value) { … }
void OgHttp2Session::UpdateStreamReceiveWindowSizes(uint32_t new_value) { … }
bool OgHttp2Session::HasMoreData(const StreamState& stream_state) const { … }
bool OgHttp2Session::IsReadyToWriteData(const StreamState& stream_state) const { … }
void OgHttp2Session::AbandonData(StreamState& stream_state) { … }
OgHttp2Session::DataFrameHeaderInfo OgHttp2Session::GetDataFrameInfo(
Http2StreamId stream_id, size_t flow_control_available,
StreamState& stream_state) { … }
bool OgHttp2Session::SendDataFrame(Http2StreamId stream_id,
absl::string_view frame_header,
size_t payload_length,
StreamState& stream_state) { … }
}
}