mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2025-03-01 21:33:26 +03:00
148 lines
5.2 KiB
C++
148 lines
5.2 KiB
C++
// Copyright 2021 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef NET_SPDY_ALPS_DECODER_H_
|
|
#define NET_SPDY_ALPS_DECODER_H_
|
|
|
|
#include <cstddef>
|
|
|
|
#include "base/containers/span.h"
|
|
#include "base/strings/string_number_conversions.h"
|
|
#include "net/base/net_export.h"
|
|
#include "net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h"
|
|
#include "net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.h"
|
|
#include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
|
|
|
|
namespace net {
|
|
|
|
// Class to parse HTTP/2 frames in the extension_data field
|
|
// of the ALPS TLS extension.
|
|
class NET_EXPORT_PRIVATE AlpsDecoder {
|
|
public:
|
|
// These values are persisted to logs. Entries should not be renumbered, and
|
|
// numeric values should never be reused.
|
|
enum class Error {
|
|
// No error has occurred.
|
|
kNoError = 0,
|
|
// HTTP/2 framing error detected by Http2DecoderAdapter.
|
|
kFramingError = 1,
|
|
// Forbidden HTTP/2 frame received.
|
|
kForbiddenFrame = 2,
|
|
// Input does not end on HTTP/2 frame boundary.
|
|
kNotOnFrameBoundary = 3,
|
|
// SETTINGS frame with ACK received.
|
|
kSettingsWithAck = 4,
|
|
// ACCEPT_CH received on invalid stream.
|
|
kAcceptChInvalidStream = 5,
|
|
// ACCEPT_CH received with flags.
|
|
kAcceptChWithFlags = 6,
|
|
// Malformed ACCEPT_CH payload.
|
|
kAcceptChMalformed = 7,
|
|
kMaxValue = kAcceptChMalformed
|
|
};
|
|
|
|
AlpsDecoder();
|
|
~AlpsDecoder();
|
|
|
|
// Decode a stream of HTTP/2 frames received via the ALPS TLS extension.
|
|
// The HTTP/2 connection preface MUST NOT be present in the input.
|
|
// Frames other than SETTINGS and ACCEPT_CH are ignored other than for the
|
|
// purposes of enforcing HTTP/2 framing rules.
|
|
// May only be called once, with the entire ALPS extension_data.
|
|
// Returns an error code, or Error::kNoError if no error has occurred.
|
|
// The requirement that the first frame MUST be SETTINGS is not enforced,
|
|
// because that only applies to HTTP/2 connections, not ALPS data.
|
|
[[nodiscard]] Error Decode(base::span<const char> data);
|
|
|
|
// The number of SETTINGS frames received.
|
|
int settings_frame_count() const;
|
|
|
|
// The HTTP/2 setting parameters parsed from |data|.
|
|
const spdy::SettingsMap& GetSettings() const {
|
|
return settings_parser_.GetSettings();
|
|
}
|
|
// Origins and corresponding Accept-CH values parsed from |data|. See
|
|
// https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02
|
|
const std::vector<spdy::AcceptChOriginValuePair>& GetAcceptCh() const {
|
|
return accept_ch_parser_.GetAcceptCh();
|
|
}
|
|
|
|
private:
|
|
class SettingsParser : public spdy::SpdyNoOpVisitor {
|
|
public:
|
|
SettingsParser();
|
|
~SettingsParser() override;
|
|
|
|
bool forbidden_frame_received() const { return forbidden_frame_received_; }
|
|
bool settings_ack_received() const { return settings_ack_received_; }
|
|
int settings_frame_count() const { return settings_frame_count_; }
|
|
// Number of SETTINGS frames received.
|
|
const spdy::SettingsMap& GetSettings() const { return settings_; }
|
|
|
|
// SpdyFramerVisitorInterface overrides.
|
|
void OnCommonHeader(spdy::SpdyStreamId stream_id,
|
|
size_t length,
|
|
uint8_t type,
|
|
uint8_t flags) override;
|
|
void OnSettings() override;
|
|
void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
|
|
void OnSettingsAck() override;
|
|
|
|
private:
|
|
// True if a forbidden HTTP/2 frame has been received.
|
|
bool forbidden_frame_received_ = false;
|
|
// True if a SETTINGS frame with ACK flag has been received.
|
|
bool settings_ack_received_ = false;
|
|
// Number of SETTINGS frames received.
|
|
int settings_frame_count_ = 0;
|
|
// Accumulated setting parameters.
|
|
spdy::SettingsMap settings_;
|
|
};
|
|
|
|
// Class to parse ACCEPT_CH frames.
|
|
class AcceptChParser : public spdy::ExtensionVisitorInterface {
|
|
public:
|
|
AcceptChParser();
|
|
~AcceptChParser() override;
|
|
|
|
const std::vector<spdy::AcceptChOriginValuePair>& GetAcceptCh() const {
|
|
return accept_ch_;
|
|
}
|
|
|
|
// Returns an error code, or Error::kNoError if no error has occurred.
|
|
Error error() const { return error_; }
|
|
|
|
// Returns an error code if it was bypassed, or Error::kNoError if no error was bypassed.
|
|
Error error_bypass() const { return error_bypass_; }
|
|
|
|
// ExtensionVisitorInterface implementation.
|
|
|
|
// Settings are parsed in a SpdyFramerVisitorInterface implementation,
|
|
// because ExtensionVisitorInterface does not provide information about
|
|
// receiving an empty SETTINGS frame.
|
|
void OnSetting(spdy::SpdySettingsId id, uint32_t value) override {}
|
|
|
|
bool OnFrameHeader(spdy::SpdyStreamId stream_id,
|
|
size_t length,
|
|
uint8_t type,
|
|
uint8_t flags) override;
|
|
void OnFramePayload(const char* data, size_t len) override;
|
|
|
|
private:
|
|
// Accumulated ACCEPT_CH values.
|
|
std::vector<spdy::AcceptChOriginValuePair> accept_ch_;
|
|
|
|
Error error_ = Error::kNoError;
|
|
Error error_bypass_ = Error::kNoError;
|
|
};
|
|
|
|
SettingsParser settings_parser_;
|
|
AcceptChParser accept_ch_parser_;
|
|
http2::Http2DecoderAdapter decoder_adapter_;
|
|
};
|
|
|
|
} // namespace net
|
|
|
|
#endif // NET_SPDY_ALPS_DECODER_H_
|