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