xref: /aosp_15_r20/external/cronet/net/spdy/alps_decoder.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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