xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/decoder/http2_frame_decoder_listener.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
6 #define QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
7 
8 // Http2FrameDecoderListener is the interface which the HTTP/2 decoder uses
9 // to report the decoded frames to a listener.
10 //
11 // The general design is to assume that the listener will copy the data it needs
12 // (e.g. frame headers) and will keep track of the implicit state of the
13 // decoding process (i.e. the decoder maintains just the information it needs in
14 // order to perform the decoding). Therefore, the parameters are just those with
15 // (potentially) new data, not previously provided info about the current frame.
16 //
17 // The calls are described as if they are made in quick succession, i.e. one
18 // after another, but of course the decoder needs input to decode, and the
19 // decoder will only call the listener once the necessary input has been
20 // provided. For example: OnDataStart can only be called once the 9 bytes of
21 // of an HTTP/2 common frame header have been received. The decoder will call
22 // the listener methods as soon as possible to avoid almost all buffering.
23 //
24 // The listener interface is designed so that it is possible to exactly
25 // reconstruct the serialized frames, with the exception of reserved bits,
26 // including in the frame header's flags and stream_id fields, which will have
27 // been cleared before the methods below are called.
28 
29 #include <stddef.h>
30 
31 #include <cstdint>
32 #include <type_traits>
33 
34 #include "quiche/http2/http2_constants.h"
35 #include "quiche/http2/http2_structures.h"
36 #include "quiche/common/platform/api/quiche_export.h"
37 
38 namespace http2 {
39 
40 // TODO(jamessynge): Consider sorting the methods by frequency of call, if that
41 // helps at all.
42 class QUICHE_EXPORT Http2FrameDecoderListener {
43  public:
Http2FrameDecoderListener()44   Http2FrameDecoderListener() {}
~Http2FrameDecoderListener()45   virtual ~Http2FrameDecoderListener() {}
46 
47   // Called once the common frame header has been decoded for any frame, and
48   // before any of the methods below, which will also be called. This method is
49   // included in this interface only for the purpose of supporting SpdyFramer
50   // semantics via an adapter. This is the only method that has a non-void
51   // return type, and this is just so that Http2FrameDecoderAdapter (called
52   // from SpdyFramer) can more readily pass existing tests that expect decoding
53   // to stop if the headers alone indicate an error. Return false to stop
54   // decoding just after decoding the header, else return true to continue
55   // decoding.
56   // TODO(jamessynge): Remove OnFrameHeader once done with supporting
57   // SpdyFramer's exact states.
58   virtual bool OnFrameHeader(const Http2FrameHeader& header) = 0;
59 
60   //////////////////////////////////////////////////////////////////////////////
61 
62   // Called once the common frame header has been decoded for a DATA frame,
63   // before examining the frame's payload, after which:
64   //   OnPadLength will be called if header.IsPadded() is true, i.e. if the
65   //     PADDED flag is set;
66   //   OnDataPayload will be called as the non-padding portion of the payload
67   //     is available until all of it has been provided;
68   //   OnPadding will be called if the frame is padded AND the Pad Length field
69   //     is greater than zero;
70   //   OnDataEnd will be called last. If the frame is unpadded and has no
71   //     payload, then this will be called immediately after OnDataStart.
72   virtual void OnDataStart(const Http2FrameHeader& header) = 0;
73 
74   // Called when the next non-padding portion of a DATA frame's payload is
75   // received.
76   // |data| The start of |len| bytes of data.
77   // |len| The length of the data buffer. Maybe zero in some cases, which does
78   //       not mean anything special.
79   virtual void OnDataPayload(const char* data, size_t len) = 0;
80 
81   // Called after an entire DATA frame has been received.
82   // If header.IsEndStream() == true, this is the last data for the stream.
83   virtual void OnDataEnd() = 0;
84 
85   // Called once the common frame header has been decoded for a HEADERS frame,
86   // before examining the frame's payload, after which:
87   //   OnPadLength will be called if header.IsPadded() is true, i.e. if the
88   //     PADDED flag is set;
89   //   OnHeadersPriority will be called if header.HasPriority() is true, i.e. if
90   //     the frame has the PRIORITY flag;
91   //   OnHpackFragment as the remainder of the non-padding payload is available
92   //     until all if has been provided;
93   //   OnPadding will be called if the frame is padded AND the Pad Length field
94   //     is greater than zero;
95   //   OnHeadersEnd will be called last; If the frame is unpadded and has no
96   //     payload, then this will be called immediately after OnHeadersStart;
97   //     OnHeadersEnd indicates the end of the HPACK block only if the frame
98   //     header had the END_HEADERS flag set, else the END_HEADERS should be
99   //     looked for on a subsequent CONTINUATION frame.
100   virtual void OnHeadersStart(const Http2FrameHeader& header) = 0;
101 
102   // Called when a HEADERS frame is received with the PRIORITY flag set and
103   // the priority fields have been decoded.
104   virtual void OnHeadersPriority(
105       const Http2PriorityFields& priority_fields) = 0;
106 
107   // Called when a fragment (i.e. some or all of an HPACK Block) is received;
108   // this may be part of a HEADERS, PUSH_PROMISE or CONTINUATION frame.
109   // |data| The start of |len| bytes of data.
110   // |len| The length of the data buffer. Maybe zero in some cases, which does
111   //       not mean anything special, except that it simplified the decoder.
112   virtual void OnHpackFragment(const char* data, size_t len) = 0;
113 
114   // Called after an entire HEADERS frame has been received. The frame is the
115   // end of the HEADERS if the END_HEADERS flag is set; else there should be
116   // CONTINUATION frames after this frame.
117   virtual void OnHeadersEnd() = 0;
118 
119   // Called when an entire PRIORITY frame has been decoded.
120   virtual void OnPriorityFrame(const Http2FrameHeader& header,
121                                const Http2PriorityFields& priority_fields) = 0;
122 
123   // Called once the common frame header has been decoded for a CONTINUATION
124   // frame, before examining the frame's payload, after which:
125   //   OnHpackFragment as the frame's payload is available until all of it
126   //     has been provided;
127   //   OnContinuationEnd will be called last; If the frame has no payload,
128   //     then this will be called immediately after OnContinuationStart;
129   //     the HPACK block is at an end if and only if the frame header passed
130   //     to OnContinuationStart had the END_HEADERS flag set.
131   virtual void OnContinuationStart(const Http2FrameHeader& header) = 0;
132 
133   // Called after an entire CONTINUATION frame has been received. The frame is
134   // the end of the HEADERS if the END_HEADERS flag is set.
135   virtual void OnContinuationEnd() = 0;
136 
137   // Called when Pad Length field has been read. Applies to DATA and HEADERS
138   // frames. For PUSH_PROMISE frames, the Pad Length + 1 is provided in the
139   // OnPushPromiseStart call as total_padding_length.
140   virtual void OnPadLength(size_t pad_length) = 0;
141 
142   // Called when padding is skipped over.
143   virtual void OnPadding(const char* padding, size_t skipped_length) = 0;
144 
145   // Called when an entire RST_STREAM frame has been decoded.
146   // This is the only callback for RST_STREAM frames.
147   virtual void OnRstStream(const Http2FrameHeader& header,
148                            Http2ErrorCode error_code) = 0;
149 
150   // Called once the common frame header has been decoded for a SETTINGS frame
151   // without the ACK flag, before examining the frame's payload, after which:
152   //   OnSetting will be called in turn for each pair of settings parameter and
153   //     value found in the payload;
154   //   OnSettingsEnd will be called last; If the frame has no payload,
155   //     then this will be called immediately after OnSettingsStart.
156   // The frame header is passed so that the caller can check the stream_id,
157   // which should be zero, but that hasn't been checked by the decoder.
158   virtual void OnSettingsStart(const Http2FrameHeader& header) = 0;
159 
160   // Called for each setting parameter and value within a SETTINGS frame.
161   virtual void OnSetting(const Http2SettingFields& setting_fields) = 0;
162 
163   // Called after parsing the complete payload of SETTINGS frame (non-ACK).
164   virtual void OnSettingsEnd() = 0;
165 
166   // Called when an entire SETTINGS frame, with the ACK flag, has been decoded.
167   virtual void OnSettingsAck(const Http2FrameHeader& header) = 0;
168 
169   // Called just before starting to process the HPACK block of a PUSH_PROMISE
170   // frame. The Pad Length field has already been decoded at this point, so
171   // OnPadLength will not be called; note that total_padding_length is Pad
172   // Length + 1. After OnPushPromiseStart:
173   //   OnHpackFragment as the remainder of the non-padding payload is available
174   //     until all if has been provided;
175   //   OnPadding will be called if the frame is padded AND the Pad Length field
176   //     is greater than zero (i.e. total_padding_length > 1);
177   //   OnPushPromiseEnd will be called last; If the frame is unpadded and has no
178   //     payload, then this will be called immediately after OnPushPromiseStart.
179   virtual void OnPushPromiseStart(const Http2FrameHeader& header,
180                                   const Http2PushPromiseFields& promise,
181                                   size_t total_padding_length) = 0;
182 
183   // Called after all of the HPACK block fragment and padding of a PUSH_PROMISE
184   // has been decoded and delivered to the listener. This call indicates the end
185   // of the HPACK block if and only if the frame header had the END_HEADERS flag
186   // set (i.e. header.IsEndHeaders() is true); otherwise the next block must be
187   // a CONTINUATION frame with the same stream id (not the same promised stream
188   // id).
189   virtual void OnPushPromiseEnd() = 0;
190 
191   // Called when an entire PING frame, without the ACK flag, has been decoded.
192   virtual void OnPing(const Http2FrameHeader& header,
193                       const Http2PingFields& ping) = 0;
194 
195   // Called when an entire PING frame, with the ACK flag, has been decoded.
196   virtual void OnPingAck(const Http2FrameHeader& header,
197                          const Http2PingFields& ping) = 0;
198 
199   // Called after parsing a GOAWAY frame's header and fixed size fields, after
200   // which:
201   //   OnGoAwayOpaqueData will be called as opaque data of the payload becomes
202   //     available to the decoder, until all of it has been provided to the
203   //     listener;
204   //   OnGoAwayEnd will be called last, after all the opaque data has been
205   //     provided to the listener; if there is no opaque data, then OnGoAwayEnd
206   //     will be called immediately after OnGoAwayStart.
207   virtual void OnGoAwayStart(const Http2FrameHeader& header,
208                              const Http2GoAwayFields& goaway) = 0;
209 
210   // Called when the next portion of a GOAWAY frame's payload is received.
211   // |data| The start of |len| bytes of opaque data.
212   // |len| The length of the opaque data buffer. Maybe zero in some cases,
213   //       which does not mean anything special.
214   virtual void OnGoAwayOpaqueData(const char* data, size_t len) = 0;
215 
216   // Called after finishing decoding all of a GOAWAY frame.
217   virtual void OnGoAwayEnd() = 0;
218 
219   // Called when an entire WINDOW_UPDATE frame has been decoded. The
220   // window_size_increment is required to be non-zero, but that has not been
221   // checked. If header.stream_id==0, the connection's flow control window is
222   // being increased, else the specified stream's flow control is being
223   // increased.
224   virtual void OnWindowUpdate(const Http2FrameHeader& header,
225                               uint32_t window_size_increment) = 0;
226 
227   // Called when an ALTSVC frame header and origin length have been parsed.
228   // Either or both lengths may be zero. After OnAltSvcStart:
229   //   OnAltSvcOriginData will be called until all of the (optional) Origin
230   //     has been provided;
231   //   OnAltSvcValueData will be called until all of the Alt-Svc-Field-Value
232   //     has been provided;
233   //   OnAltSvcEnd will called last, after all of the origin and
234   //     Alt-Svc-Field-Value have been delivered to the listener.
235   virtual void OnAltSvcStart(const Http2FrameHeader& header,
236                              size_t origin_length, size_t value_length) = 0;
237 
238   // Called when decoding the (optional) origin of an ALTSVC;
239   // the field is uninterpreted.
240   virtual void OnAltSvcOriginData(const char* data, size_t len) = 0;
241 
242   // Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
243   // the field is uninterpreted.
244   virtual void OnAltSvcValueData(const char* data, size_t len) = 0;
245 
246   // Called after decoding all of a ALTSVC frame and providing to the listener
247   // via the above methods.
248   virtual void OnAltSvcEnd() = 0;
249 
250   // Called when an PRIORITY_UPDATE frame header and Prioritized Stream ID have
251   // been parsed.  Afterwards:
252   //   OnPriorityUpdatePayload will be called each time a portion of the
253   //     Priority Field Value field is available until all of it has been
254   //     provided;
255   //   OnPriorityUpdateEnd will be called last. If the frame has an empty
256   //     Priority Field Value, then this will be called immediately after
257   //     OnPriorityUpdateStart.
258   virtual void OnPriorityUpdateStart(
259       const Http2FrameHeader& header,
260       const Http2PriorityUpdateFields& priority_update) = 0;
261 
262   // Called when the next portion of a PRIORITY_UPDATE frame's Priority Field
263   // Value field is received.
264   // |data| The start of |len| bytes of data.
265   // |len| The length of the data buffer. May be zero in some cases, which does
266   //     not mean anything special.
267   virtual void OnPriorityUpdatePayload(const char* data, size_t len) = 0;
268 
269   // Called after an entire PRIORITY_UPDATE frame has been received.
270   virtual void OnPriorityUpdateEnd() = 0;
271 
272   // Called when the common frame header has been decoded, but the frame type
273   // is unknown, after which:
274   //   OnUnknownPayload is called as the payload of the frame is provided to the
275   //     decoder, until all of the payload has been decoded;
276   //   OnUnknownEnd will called last, after the entire frame of the unknown type
277   //     has been decoded and provided to the listener.
278   virtual void OnUnknownStart(const Http2FrameHeader& header) = 0;
279 
280   // Called when the payload of an unknown frame type is received.
281   // |data| A buffer containing the data received.
282   // |len| The length of the data buffer.
283   virtual void OnUnknownPayload(const char* data, size_t len) = 0;
284 
285   // Called after decoding all of the payload of an unknown frame type.
286   virtual void OnUnknownEnd() = 0;
287 
288   //////////////////////////////////////////////////////////////////////////////
289   // Below here are events indicating a problem has been detected during
290   // decoding (i.e. the received frames are malformed in some way).
291 
292   // Padding field (uint8) has a value that is too large (i.e. the amount of
293   // padding is greater than the remainder of the payload that isn't required).
294   // From RFC Section 6.1, DATA:
295   //     If the length of the padding is the length of the frame payload or
296   //     greater, the recipient MUST treat this as a connection error
297   //     (Section 5.4.1) of type PROTOCOL_ERROR.
298   // The same is true for HEADERS and PUSH_PROMISE.
299   virtual void OnPaddingTooLong(const Http2FrameHeader& header,
300                                 size_t missing_length) = 0;
301 
302   // Frame size error. Depending upon the effected frame, this may or may not
303   // require terminating the connection, though that is probably the best thing
304   // to do.
305   // From RFC Section 4.2, Frame Size:
306   //     An endpoint MUST send an error code of FRAME_SIZE_ERROR if a frame
307   //     exceeds the size defined in SETTINGS_MAX_FRAME_SIZE, exceeds any limit
308   //     defined for the frame type, or is too small to contain mandatory frame
309   //     data. A frame size error in a frame that could alter the state of the
310   //     the entire connection MUST be treated as a connection error
311   //     (Section 5.4.1); this includes any frame carrying a header block
312   //     (Section 4.3) (that is, HEADERS, PUSH_PROMISE, and CONTINUATION),
313   //     SETTINGS, and any frame with a stream identifier of 0.
314   virtual void OnFrameSizeError(const Http2FrameHeader& header) = 0;
315 };
316 
317 // Do nothing for each call. Useful for ignoring a frame that is invalid.
318 class QUICHE_EXPORT Http2FrameDecoderNoOpListener
319     : public Http2FrameDecoderListener {
320  public:
Http2FrameDecoderNoOpListener()321   Http2FrameDecoderNoOpListener() {}
~Http2FrameDecoderNoOpListener()322   ~Http2FrameDecoderNoOpListener() override {}
323 
324   // TODO(jamessynge): Remove OnFrameHeader once done with supporting
325   // SpdyFramer's exact states.
326   bool OnFrameHeader(const Http2FrameHeader& header) override;
327 
OnDataStart(const Http2FrameHeader &)328   void OnDataStart(const Http2FrameHeader& /*header*/) override {}
OnDataPayload(const char *,size_t)329   void OnDataPayload(const char* /*data*/, size_t /*len*/) override {}
OnDataEnd()330   void OnDataEnd() override {}
OnHeadersStart(const Http2FrameHeader &)331   void OnHeadersStart(const Http2FrameHeader& /*header*/) override {}
OnHeadersPriority(const Http2PriorityFields &)332   void OnHeadersPriority(const Http2PriorityFields& /*priority*/) override {}
OnHpackFragment(const char *,size_t)333   void OnHpackFragment(const char* /*data*/, size_t /*len*/) override {}
OnHeadersEnd()334   void OnHeadersEnd() override {}
OnPriorityFrame(const Http2FrameHeader &,const Http2PriorityFields &)335   void OnPriorityFrame(const Http2FrameHeader& /*header*/,
336                        const Http2PriorityFields& /*priority*/) override {}
OnContinuationStart(const Http2FrameHeader &)337   void OnContinuationStart(const Http2FrameHeader& /*header*/) override {}
OnContinuationEnd()338   void OnContinuationEnd() override {}
OnPadLength(size_t)339   void OnPadLength(size_t /*trailing_length*/) override {}
OnPadding(const char *,size_t)340   void OnPadding(const char* /*padding*/, size_t /*skipped_length*/) override {}
OnRstStream(const Http2FrameHeader &,Http2ErrorCode)341   void OnRstStream(const Http2FrameHeader& /*header*/,
342                    Http2ErrorCode /*error_code*/) override {}
OnSettingsStart(const Http2FrameHeader &)343   void OnSettingsStart(const Http2FrameHeader& /*header*/) override {}
OnSetting(const Http2SettingFields &)344   void OnSetting(const Http2SettingFields& /*setting_fields*/) override {}
OnSettingsEnd()345   void OnSettingsEnd() override {}
OnSettingsAck(const Http2FrameHeader &)346   void OnSettingsAck(const Http2FrameHeader& /*header*/) override {}
OnPushPromiseStart(const Http2FrameHeader &,const Http2PushPromiseFields &,size_t)347   void OnPushPromiseStart(const Http2FrameHeader& /*header*/,
348                           const Http2PushPromiseFields& /*promise*/,
349                           size_t /*total_padding_length*/) override {}
OnPushPromiseEnd()350   void OnPushPromiseEnd() override {}
OnPing(const Http2FrameHeader &,const Http2PingFields &)351   void OnPing(const Http2FrameHeader& /*header*/,
352               const Http2PingFields& /*ping*/) override {}
OnPingAck(const Http2FrameHeader &,const Http2PingFields &)353   void OnPingAck(const Http2FrameHeader& /*header*/,
354                  const Http2PingFields& /*ping*/) override {}
OnGoAwayStart(const Http2FrameHeader &,const Http2GoAwayFields &)355   void OnGoAwayStart(const Http2FrameHeader& /*header*/,
356                      const Http2GoAwayFields& /*goaway*/) override {}
OnGoAwayOpaqueData(const char *,size_t)357   void OnGoAwayOpaqueData(const char* /*data*/, size_t /*len*/) override {}
OnGoAwayEnd()358   void OnGoAwayEnd() override {}
OnWindowUpdate(const Http2FrameHeader &,uint32_t)359   void OnWindowUpdate(const Http2FrameHeader& /*header*/,
360                       uint32_t /*increment*/) override {}
OnAltSvcStart(const Http2FrameHeader &,size_t,size_t)361   void OnAltSvcStart(const Http2FrameHeader& /*header*/,
362                      size_t /*origin_length*/,
363                      size_t /*value_length*/) override {}
OnAltSvcOriginData(const char *,size_t)364   void OnAltSvcOriginData(const char* /*data*/, size_t /*len*/) override {}
OnAltSvcValueData(const char *,size_t)365   void OnAltSvcValueData(const char* /*data*/, size_t /*len*/) override {}
OnAltSvcEnd()366   void OnAltSvcEnd() override {}
OnPriorityUpdateStart(const Http2FrameHeader &,const Http2PriorityUpdateFields &)367   void OnPriorityUpdateStart(
368       const Http2FrameHeader& /*header*/,
369       const Http2PriorityUpdateFields& /*priority_update*/) override {}
OnPriorityUpdatePayload(const char *,size_t)370   void OnPriorityUpdatePayload(const char* /*data*/, size_t /*len*/) override {}
OnPriorityUpdateEnd()371   void OnPriorityUpdateEnd() override {}
OnUnknownStart(const Http2FrameHeader &)372   void OnUnknownStart(const Http2FrameHeader& /*header*/) override {}
OnUnknownPayload(const char *,size_t)373   void OnUnknownPayload(const char* /*data*/, size_t /*len*/) override {}
OnUnknownEnd()374   void OnUnknownEnd() override {}
OnPaddingTooLong(const Http2FrameHeader &,size_t)375   void OnPaddingTooLong(const Http2FrameHeader& /*header*/,
376                         size_t /*missing_length*/) override {}
OnFrameSizeError(const Http2FrameHeader &)377   void OnFrameSizeError(const Http2FrameHeader& /*header*/) override {}
378 };
379 
380 static_assert(!std::is_abstract<Http2FrameDecoderNoOpListener>(),
381               "Http2FrameDecoderNoOpListener ought to be concrete.");
382 
383 }  // namespace http2
384 
385 #endif  // QUICHE_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
386