1*6777b538SAndroid Build Coastguard Worker // Copyright 2021 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef NET_SPDY_ALPS_DECODER_H_ 6*6777b538SAndroid Build Coastguard Worker #define NET_SPDY_ALPS_DECODER_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <cstddef> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h" 11*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h" 12*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h" 13*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h" 14*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.h" 15*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker namespace net { 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker // Class to parse HTTP/2 frames in the extension_data field 20*6777b538SAndroid Build Coastguard Worker // of the ALPS TLS extension. 21*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE AlpsDecoder { 22*6777b538SAndroid Build Coastguard Worker public: 23*6777b538SAndroid Build Coastguard Worker // These values are persisted to logs. Entries should not be renumbered, and 24*6777b538SAndroid Build Coastguard Worker // numeric values should never be reused. 25*6777b538SAndroid Build Coastguard Worker enum class Error { 26*6777b538SAndroid Build Coastguard Worker // No error has occurred. 27*6777b538SAndroid Build Coastguard Worker kNoError = 0, 28*6777b538SAndroid Build Coastguard Worker // HTTP/2 framing error detected by Http2DecoderAdapter. 29*6777b538SAndroid Build Coastguard Worker kFramingError = 1, 30*6777b538SAndroid Build Coastguard Worker // Forbidden HTTP/2 frame received. 31*6777b538SAndroid Build Coastguard Worker kForbiddenFrame = 2, 32*6777b538SAndroid Build Coastguard Worker // Input does not end on HTTP/2 frame boundary. 33*6777b538SAndroid Build Coastguard Worker kNotOnFrameBoundary = 3, 34*6777b538SAndroid Build Coastguard Worker // SETTINGS frame with ACK received. 35*6777b538SAndroid Build Coastguard Worker kSettingsWithAck = 4, 36*6777b538SAndroid Build Coastguard Worker // ACCEPT_CH received on invalid stream. 37*6777b538SAndroid Build Coastguard Worker kAcceptChInvalidStream = 5, 38*6777b538SAndroid Build Coastguard Worker // ACCEPT_CH received with flags. 39*6777b538SAndroid Build Coastguard Worker kAcceptChWithFlags = 6, 40*6777b538SAndroid Build Coastguard Worker // Malformed ACCEPT_CH payload. 41*6777b538SAndroid Build Coastguard Worker kAcceptChMalformed = 7, 42*6777b538SAndroid Build Coastguard Worker kMaxValue = kAcceptChMalformed 43*6777b538SAndroid Build Coastguard Worker }; 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker AlpsDecoder(); 46*6777b538SAndroid Build Coastguard Worker ~AlpsDecoder(); 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker // Decode a stream of HTTP/2 frames received via the ALPS TLS extension. 49*6777b538SAndroid Build Coastguard Worker // The HTTP/2 connection preface MUST NOT be present in the input. 50*6777b538SAndroid Build Coastguard Worker // Frames other than SETTINGS and ACCEPT_CH are ignored other than for the 51*6777b538SAndroid Build Coastguard Worker // purposes of enforcing HTTP/2 framing rules. 52*6777b538SAndroid Build Coastguard Worker // May only be called once, with the entire ALPS extension_data. 53*6777b538SAndroid Build Coastguard Worker // Returns an error code, or Error::kNoError if no error has occurred. 54*6777b538SAndroid Build Coastguard Worker // The requirement that the first frame MUST be SETTINGS is not enforced, 55*6777b538SAndroid Build Coastguard Worker // because that only applies to HTTP/2 connections, not ALPS data. 56*6777b538SAndroid Build Coastguard Worker [[nodiscard]] Error Decode(base::span<const char> data); 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker // The number of SETTINGS frames received. 59*6777b538SAndroid Build Coastguard Worker int settings_frame_count() const; 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker // The HTTP/2 setting parameters parsed from |data|. GetSettings()62*6777b538SAndroid Build Coastguard Worker const spdy::SettingsMap& GetSettings() const { 63*6777b538SAndroid Build Coastguard Worker return settings_parser_.GetSettings(); 64*6777b538SAndroid Build Coastguard Worker } 65*6777b538SAndroid Build Coastguard Worker // Origins and corresponding Accept-CH values parsed from |data|. See 66*6777b538SAndroid Build Coastguard Worker // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02 GetAcceptCh()67*6777b538SAndroid Build Coastguard Worker const std::vector<spdy::AcceptChOriginValuePair>& GetAcceptCh() const { 68*6777b538SAndroid Build Coastguard Worker return accept_ch_parser_.GetAcceptCh(); 69*6777b538SAndroid Build Coastguard Worker } 70*6777b538SAndroid Build Coastguard Worker 71*6777b538SAndroid Build Coastguard Worker private: 72*6777b538SAndroid Build Coastguard Worker class SettingsParser : public spdy::SpdyNoOpVisitor { 73*6777b538SAndroid Build Coastguard Worker public: 74*6777b538SAndroid Build Coastguard Worker SettingsParser(); 75*6777b538SAndroid Build Coastguard Worker ~SettingsParser() override; 76*6777b538SAndroid Build Coastguard Worker forbidden_frame_received()77*6777b538SAndroid Build Coastguard Worker bool forbidden_frame_received() const { return forbidden_frame_received_; } settings_ack_received()78*6777b538SAndroid Build Coastguard Worker bool settings_ack_received() const { return settings_ack_received_; } settings_frame_count()79*6777b538SAndroid Build Coastguard Worker int settings_frame_count() const { return settings_frame_count_; } 80*6777b538SAndroid Build Coastguard Worker // Number of SETTINGS frames received. GetSettings()81*6777b538SAndroid Build Coastguard Worker const spdy::SettingsMap& GetSettings() const { return settings_; } 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker // SpdyFramerVisitorInterface overrides. 84*6777b538SAndroid Build Coastguard Worker void OnCommonHeader(spdy::SpdyStreamId stream_id, 85*6777b538SAndroid Build Coastguard Worker size_t length, 86*6777b538SAndroid Build Coastguard Worker uint8_t type, 87*6777b538SAndroid Build Coastguard Worker uint8_t flags) override; 88*6777b538SAndroid Build Coastguard Worker void OnSettings() override; 89*6777b538SAndroid Build Coastguard Worker void OnSetting(spdy::SpdySettingsId id, uint32_t value) override; 90*6777b538SAndroid Build Coastguard Worker void OnSettingsAck() override; 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard Worker private: 93*6777b538SAndroid Build Coastguard Worker // True if a forbidden HTTP/2 frame has been received. 94*6777b538SAndroid Build Coastguard Worker bool forbidden_frame_received_ = false; 95*6777b538SAndroid Build Coastguard Worker // True if a SETTINGS frame with ACK flag has been received. 96*6777b538SAndroid Build Coastguard Worker bool settings_ack_received_ = false; 97*6777b538SAndroid Build Coastguard Worker // Number of SETTINGS frames received. 98*6777b538SAndroid Build Coastguard Worker int settings_frame_count_ = 0; 99*6777b538SAndroid Build Coastguard Worker // Accumulated setting parameters. 100*6777b538SAndroid Build Coastguard Worker spdy::SettingsMap settings_; 101*6777b538SAndroid Build Coastguard Worker }; 102*6777b538SAndroid Build Coastguard Worker 103*6777b538SAndroid Build Coastguard Worker // Class to parse ACCEPT_CH frames. 104*6777b538SAndroid Build Coastguard Worker class AcceptChParser : public spdy::ExtensionVisitorInterface { 105*6777b538SAndroid Build Coastguard Worker public: 106*6777b538SAndroid Build Coastguard Worker AcceptChParser(); 107*6777b538SAndroid Build Coastguard Worker ~AcceptChParser() override; 108*6777b538SAndroid Build Coastguard Worker GetAcceptCh()109*6777b538SAndroid Build Coastguard Worker const std::vector<spdy::AcceptChOriginValuePair>& GetAcceptCh() const { 110*6777b538SAndroid Build Coastguard Worker return accept_ch_; 111*6777b538SAndroid Build Coastguard Worker } 112*6777b538SAndroid Build Coastguard Worker 113*6777b538SAndroid Build Coastguard Worker // Returns an error code, or Error::kNoError if no error has occurred. error()114*6777b538SAndroid Build Coastguard Worker Error error() const { return error_; } 115*6777b538SAndroid Build Coastguard Worker 116*6777b538SAndroid Build Coastguard Worker // Returns an error code if it was bypassed, or Error::kNoError if no error was bypassed. error_bypass()117*6777b538SAndroid Build Coastguard Worker Error error_bypass() const { return error_bypass_; } 118*6777b538SAndroid Build Coastguard Worker 119*6777b538SAndroid Build Coastguard Worker // ExtensionVisitorInterface implementation. 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker // Settings are parsed in a SpdyFramerVisitorInterface implementation, 122*6777b538SAndroid Build Coastguard Worker // because ExtensionVisitorInterface does not provide information about 123*6777b538SAndroid Build Coastguard Worker // receiving an empty SETTINGS frame. OnSetting(spdy::SpdySettingsId id,uint32_t value)124*6777b538SAndroid Build Coastguard Worker void OnSetting(spdy::SpdySettingsId id, uint32_t value) override {} 125*6777b538SAndroid Build Coastguard Worker 126*6777b538SAndroid Build Coastguard Worker bool OnFrameHeader(spdy::SpdyStreamId stream_id, 127*6777b538SAndroid Build Coastguard Worker size_t length, 128*6777b538SAndroid Build Coastguard Worker uint8_t type, 129*6777b538SAndroid Build Coastguard Worker uint8_t flags) override; 130*6777b538SAndroid Build Coastguard Worker void OnFramePayload(const char* data, size_t len) override; 131*6777b538SAndroid Build Coastguard Worker 132*6777b538SAndroid Build Coastguard Worker private: 133*6777b538SAndroid Build Coastguard Worker // Accumulated ACCEPT_CH values. 134*6777b538SAndroid Build Coastguard Worker std::vector<spdy::AcceptChOriginValuePair> accept_ch_; 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker Error error_ = Error::kNoError; 137*6777b538SAndroid Build Coastguard Worker Error error_bypass_ = Error::kNoError; 138*6777b538SAndroid Build Coastguard Worker }; 139*6777b538SAndroid Build Coastguard Worker 140*6777b538SAndroid Build Coastguard Worker SettingsParser settings_parser_; 141*6777b538SAndroid Build Coastguard Worker AcceptChParser accept_ch_parser_; 142*6777b538SAndroid Build Coastguard Worker http2::Http2DecoderAdapter decoder_adapter_; 143*6777b538SAndroid Build Coastguard Worker }; 144*6777b538SAndroid Build Coastguard Worker 145*6777b538SAndroid Build Coastguard Worker } // namespace net 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker #endif // NET_SPDY_ALPS_DECODER_H_ 148