1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// 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/http2/core/http2_frame_decoder_adapter.h"
#include "net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.h"
#include "net/third_party/quiche/src/quiche/http2/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_
|