blob: 93da6844095e9c4d1aab8d02f299ac3b51a7134a [file] [log] [blame]
QUICHE team82dee2f2019-01-18 12:35:12 -05001// 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_SPDY_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_
6#define QUICHE_SPDY_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_
7
8#include <stddef.h>
9
10#include <cstdint>
11#include <memory>
bnc47904002019-08-16 11:49:48 -070012#include <string>
QUICHE team82dee2f2019-01-18 12:35:12 -050013
14#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h"
15#include "net/third_party/quiche/src/http2/platform/api/http2_optional.h"
16#include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
17#include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h"
18#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
19#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
20#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
21#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
22
23namespace spdy {
24
25class SpdyFramerVisitorInterface;
26class ExtensionVisitorInterface;
27
28} // namespace spdy
29
30// TODO(dahollings): Perform various renames/moves suggested in cl/164660364.
31
32namespace http2 {
33
34// Adapts SpdyFramer interface to use Http2FrameDecoder.
35class SPDY_EXPORT_PRIVATE Http2DecoderAdapter
36 : public http2::Http2FrameDecoderListener {
37 public:
38 // HTTP2 states.
39 enum SpdyState {
40 SPDY_ERROR,
41 SPDY_READY_FOR_FRAME, // Framer is ready for reading the next frame.
42 SPDY_FRAME_COMPLETE, // Framer has finished reading a frame, need to reset.
43 SPDY_READING_COMMON_HEADER,
44 SPDY_CONTROL_FRAME_PAYLOAD,
45 SPDY_READ_DATA_FRAME_PADDING_LENGTH,
46 SPDY_CONSUME_PADDING,
47 SPDY_IGNORE_REMAINING_PAYLOAD,
48 SPDY_FORWARD_STREAM_FRAME,
49 SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK,
50 SPDY_CONTROL_FRAME_HEADER_BLOCK,
51 SPDY_GOAWAY_FRAME_PAYLOAD,
52 SPDY_SETTINGS_FRAME_HEADER,
53 SPDY_SETTINGS_FRAME_PAYLOAD,
54 SPDY_ALTSVC_FRAME_PAYLOAD,
55 SPDY_EXTENSION_FRAME_PAYLOAD,
56 };
57
58 // Framer error codes.
59 enum SpdyFramerError {
60 SPDY_NO_ERROR,
61 SPDY_INVALID_STREAM_ID, // Stream ID is invalid
62 SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted.
63 SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large.
64 SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize.
65 SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version.
66 SPDY_DECOMPRESS_FAILURE, // There was an error decompressing.
67 SPDY_COMPRESS_FAILURE, // There was an error compressing.
68 SPDY_GOAWAY_FRAME_CORRUPT, // GOAWAY frame could not be parsed.
69 SPDY_RST_STREAM_FRAME_CORRUPT, // RST_STREAM frame could not be parsed.
70 SPDY_INVALID_PADDING, // HEADERS or DATA frame padding invalid
71 SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags.
72 SPDY_INVALID_CONTROL_FRAME_FLAGS, // Control frame has invalid flags.
73 SPDY_UNEXPECTED_FRAME, // Frame received out of order.
74 SPDY_INTERNAL_FRAMER_ERROR, // SpdyFramer was used incorrectly.
75 SPDY_INVALID_CONTROL_FRAME_SIZE, // Control frame not sized to spec
76 SPDY_OVERSIZED_PAYLOAD, // Payload size was too large
77
78 LAST_ERROR, // Must be the last entry in the enum.
79 };
80
81 // For debugging.
82 static const char* StateToString(int state);
83 static const char* SpdyFramerErrorToString(SpdyFramerError spdy_framer_error);
84
85 Http2DecoderAdapter();
86 ~Http2DecoderAdapter() override;
87
88 // Set callbacks to be called from the framer. A visitor must be set, or
89 // else the framer will likely crash. It is acceptable for the visitor
90 // to do nothing. If this is called multiple times, only the last visitor
91 // will be used.
92 void set_visitor(spdy::SpdyFramerVisitorInterface* visitor);
93 spdy::SpdyFramerVisitorInterface* visitor() const { return visitor_; }
94
95 // Set extension callbacks to be called from the framer or decoder. Optional.
96 // If called multiple times, only the last visitor will be used.
97 void set_extension_visitor(spdy::ExtensionVisitorInterface* visitor);
QUICHE teamf4e05882019-06-18 12:43:27 -070098 spdy::ExtensionVisitorInterface* extension_visitor() const {
99 return extension_;
100 }
QUICHE team82dee2f2019-01-18 12:35:12 -0500101
102 // Set debug callbacks to be called from the framer. The debug visitor is
103 // completely optional and need not be set in order for normal operation.
104 // If this is called multiple times, only the last visitor will be used.
105 void set_debug_visitor(spdy::SpdyFramerDebugVisitorInterface* debug_visitor);
106 spdy::SpdyFramerDebugVisitorInterface* debug_visitor() const {
107 return debug_visitor_;
108 }
109
110 // Set debug callbacks to be called from the HPACK decoder.
111 void SetDecoderHeaderTableDebugVisitor(
112 std::unique_ptr<spdy::HpackHeaderTable::DebugVisitorInterface> visitor);
113
114 // Sets whether or not ProcessInput returns after finishing a frame, or
115 // continues processing additional frames. Normally ProcessInput processes
116 // all input, but this method enables the caller (and visitor) to work with
117 // a single frame at a time (or that portion of the frame which is provided
118 // as input). Reset() does not change the value of this flag.
119 void set_process_single_input_frame(bool v);
120 bool process_single_input_frame() const {
121 return process_single_input_frame_;
122 }
123
124 // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns
125 // the number of bytes consumed. It is safe to pass more bytes in than
126 // may be consumed. Should process (or otherwise buffer) as much as
127 // available, unless process_single_input_frame is true.
128 size_t ProcessInput(const char* data, size_t len);
129
130 // Reset the decoder (used just for tests at this time).
131 void Reset();
132
133 // Current state of the decoder.
134 SpdyState state() const;
135
136 // Current error code (NO_ERROR if state != ERROR).
137 SpdyFramerError spdy_framer_error() const;
138
139 // Has any frame header looked like the start of an HTTP/1.1 (or earlier)
140 // response? Used to detect if a backend/server that we sent a request to
141 // has responded with an HTTP/1.1 (or earlier) response.
142 bool probable_http_response() const;
143
144 // Returns the estimate of dynamically allocated memory in bytes.
145 size_t EstimateMemoryUsage() const;
146
147 spdy::HpackDecoderAdapter* GetHpackDecoder();
148
149 bool HasError() const;
150
151 private:
152 bool OnFrameHeader(const Http2FrameHeader& header) override;
153 void OnDataStart(const Http2FrameHeader& header) override;
154 void OnDataPayload(const char* data, size_t len) override;
155 void OnDataEnd() override;
156 void OnHeadersStart(const Http2FrameHeader& header) override;
157 void OnHeadersPriority(const Http2PriorityFields& priority) override;
158 void OnHpackFragment(const char* data, size_t len) override;
159 void OnHeadersEnd() override;
160 void OnPriorityFrame(const Http2FrameHeader& header,
161 const Http2PriorityFields& priority) override;
162 void OnContinuationStart(const Http2FrameHeader& header) override;
163 void OnContinuationEnd() override;
164 void OnPadLength(size_t trailing_length) override;
165 void OnPadding(const char* padding, size_t skipped_length) override;
166 void OnRstStream(const Http2FrameHeader& header,
167 Http2ErrorCode http2_error_code) override;
168 void OnSettingsStart(const Http2FrameHeader& header) override;
169 void OnSetting(const Http2SettingFields& setting_fields) override;
170 void OnSettingsEnd() override;
171 void OnSettingsAck(const Http2FrameHeader& header) override;
172 void OnPushPromiseStart(const Http2FrameHeader& header,
173 const Http2PushPromiseFields& promise,
174 size_t total_padding_length) override;
175 void OnPushPromiseEnd() override;
176 void OnPing(const Http2FrameHeader& header,
177 const Http2PingFields& ping) override;
178 void OnPingAck(const Http2FrameHeader& header,
179 const Http2PingFields& ping) override;
180 void OnGoAwayStart(const Http2FrameHeader& header,
181 const Http2GoAwayFields& goaway) override;
182 void OnGoAwayOpaqueData(const char* data, size_t len) override;
183 void OnGoAwayEnd() override;
184 void OnWindowUpdate(const Http2FrameHeader& header,
185 uint32_t increment) override;
186 void OnAltSvcStart(const Http2FrameHeader& header,
187 size_t origin_length,
188 size_t value_length) override;
189 void OnAltSvcOriginData(const char* data, size_t len) override;
190 void OnAltSvcValueData(const char* data, size_t len) override;
191 void OnAltSvcEnd() override;
192 void OnUnknownStart(const Http2FrameHeader& header) override;
193 void OnUnknownPayload(const char* data, size_t len) override;
194 void OnUnknownEnd() override;
195 void OnPaddingTooLong(const Http2FrameHeader& header,
196 size_t missing_length) override;
197 void OnFrameSizeError(const Http2FrameHeader& header) override;
198
199 size_t ProcessInputFrame(const char* data, size_t len);
200
201 void DetermineSpdyState(DecodeStatus status);
202 void ResetBetweenFrames();
203
204 // ResetInternal is called from the constructor, and during tests, but not
205 // otherwise (i.e. not between every frame).
206 void ResetInternal();
207
208 void set_spdy_state(SpdyState v);
209
210 void SetSpdyErrorAndNotify(SpdyFramerError error);
211
212 const Http2FrameHeader& frame_header() const;
213
214 uint32_t stream_id() const;
215 Http2FrameType frame_type() const;
216
217 size_t remaining_total_payload() const;
218
219 bool IsReadingPaddingLength();
220 bool IsSkippingPadding();
221 bool IsDiscardingPayload();
222 // Called from OnXyz or OnXyzStart methods to decide whether it is OK to
223 // handle the callback.
224 bool IsOkToStartFrame(const Http2FrameHeader& header);
225 bool HasRequiredStreamId(uint32_t stream_id);
226
227 bool HasRequiredStreamId(const Http2FrameHeader& header);
228
229 bool HasRequiredStreamIdZero(uint32_t stream_id);
230
231 bool HasRequiredStreamIdZero(const Http2FrameHeader& header);
232
233 void ReportReceiveCompressedFrame(const Http2FrameHeader& header);
234
235 void CommonStartHpackBlock();
236
237 // SpdyFramer calls HandleControlFrameHeadersData even if there are zero
238 // fragment bytes in the first frame, so do the same.
239 void MaybeAnnounceEmptyFirstHpackFragment();
240 void CommonHpackFragmentEnd();
241
242 // The most recently decoded frame header; invalid after we reached the end
243 // of that frame.
244 Http2FrameHeader frame_header_;
245
246 // If decoding an HPACK block that is split across multiple frames, this holds
247 // the frame header of the HEADERS or PUSH_PROMISE that started the block.
248 Http2FrameHeader hpack_first_frame_header_;
249
250 // Amount of trailing padding. Currently used just as an indicator of whether
251 // OnPadLength has been called.
252 Http2Optional<size_t> opt_pad_length_;
253
254 // Temporary buffers for the AltSvc fields.
bnc47904002019-08-16 11:49:48 -0700255 std::string alt_svc_origin_;
256 std::string alt_svc_value_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500257
258 // Listener used if we transition to an error state; the listener ignores all
259 // the callbacks.
260 Http2FrameDecoderNoOpListener no_op_listener_;
261
262 spdy::SpdyFramerVisitorInterface* visitor_ = nullptr;
263 spdy::SpdyFramerDebugVisitorInterface* debug_visitor_ = nullptr;
264
265 // If non-null, unknown frames and settings are passed to the extension.
266 spdy::ExtensionVisitorInterface* extension_ = nullptr;
267
268 // The HPACK decoder to be used for this adapter. User is responsible for
269 // clearing if the adapter is to be used for another connection.
270 std::unique_ptr<spdy::HpackDecoderAdapter> hpack_decoder_ = nullptr;
271
272 // The HTTP/2 frame decoder. Accessed via a unique_ptr to allow replacement
273 // (e.g. in tests) when Reset() is called.
274 std::unique_ptr<Http2FrameDecoder> frame_decoder_;
275
276 // Next frame type expected. Currently only used for CONTINUATION frames,
277 // but could be used for detecting whether the first frame is a SETTINGS
278 // frame.
279 // TODO(jamessyng): Provide means to indicate that decoder should require
280 // SETTINGS frame as the first frame.
281 Http2FrameType expected_frame_type_;
282
283 // Attempt to duplicate the SpdyState and SpdyFramerError values that
284 // SpdyFramer sets. Values determined by getting tests to pass.
285 SpdyState spdy_state_;
286 SpdyFramerError spdy_framer_error_;
287
288 // The limit on the size of received HTTP/2 payloads as specified in the
289 // SETTINGS_MAX_FRAME_SIZE advertised to peer.
290 size_t recv_frame_size_limit_ = spdy::kHttp2DefaultFramePayloadLimit;
291
292 // Has OnFrameHeader been called?
293 bool decoded_frame_header_ = false;
294
295 // Have we recorded an Http2FrameHeader for the current frame?
296 // We only do so if the decoder will make multiple callbacks for
297 // the frame; for example, for PING frames we don't make record
298 // the frame header, but for ALTSVC we do.
299 bool has_frame_header_ = false;
300
301 // Have we recorded an Http2FrameHeader for the current HPACK block?
302 // True only for multi-frame HPACK blocks.
303 bool has_hpack_first_frame_header_ = false;
304
305 // Has OnHeaders() already been called for current HEADERS block? Only
306 // meaningful between OnHeadersStart and OnHeadersPriority.
307 bool on_headers_called_;
308
309 // Has OnHpackFragment() already been called for current HPACK block?
310 // SpdyFramer will pass an empty buffer to the HPACK decoder if a HEADERS
311 // or PUSH_PROMISE has no HPACK data in it (e.g. a HEADERS frame with only
312 // padding). Detect that condition and replicate the behavior using this
313 // field.
314 bool on_hpack_fragment_called_;
315
316 // Have we seen a frame header that appears to be an HTTP/1 response?
317 bool latched_probable_http_response_ = false;
318
319 // Is expected_frame_type_ set?
320 bool has_expected_frame_type_ = false;
321
322 // Is the current frame payload destined for |extension_|?
323 bool handling_extension_payload_ = false;
324
325 bool process_single_input_frame_ = false;
326};
327
328} // namespace http2
329
330namespace spdy {
331
332// Http2DecoderAdapter will use the given visitor implementing this
333// interface to deliver event callbacks as frames are decoded.
334//
335// Control frames that contain HTTP2 header blocks (HEADER, and PUSH_PROMISE)
336// are processed in fashion that allows the decompressed header block to be
337// delivered in chunks to the visitor.
338// The following steps are followed:
339// 1. OnHeaders, or OnPushPromise is called.
340// 2. OnHeaderFrameStart is called; visitor is expected to return an instance
341// of SpdyHeadersHandlerInterface that will receive the header key-value
342// pairs.
343// 3. OnHeaderFrameEnd is called, indicating that the full header block has
344// been delivered for the control frame.
345// During step 2, if the visitor is not interested in accepting the header data,
346// it should return a no-op implementation of SpdyHeadersHandlerInterface.
347class SPDY_EXPORT_PRIVATE SpdyFramerVisitorInterface {
348 public:
349 virtual ~SpdyFramerVisitorInterface() {}
350
351 // Called if an error is detected in the SpdyFrame protocol.
352 virtual void OnError(http2::Http2DecoderAdapter::SpdyFramerError error) = 0;
353
354 // Called when the common header for a frame is received. Validating the
355 // common header occurs in later processing.
356 virtual void OnCommonHeader(SpdyStreamId /*stream_id*/,
357 size_t /*length*/,
358 uint8_t /*type*/,
359 uint8_t /*flags*/) {}
360
361 // Called when a data frame header is received. The frame's data
362 // payload will be provided via subsequent calls to
363 // OnStreamFrameData().
364 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
365 size_t length,
366 bool fin) = 0;
367
368 // Called when data is received.
369 // |stream_id| The stream receiving data.
370 // |data| A buffer containing the data received.
371 // |len| The length of the data buffer.
372 virtual void OnStreamFrameData(SpdyStreamId stream_id,
373 const char* data,
374 size_t len) = 0;
375
376 // Called when the other side has finished sending data on this stream.
377 // |stream_id| The stream that was receiving data.
378 virtual void OnStreamEnd(SpdyStreamId stream_id) = 0;
379
380 // Called when padding length field is received on a DATA frame.
381 // |stream_id| The stream receiving data.
382 // |value| The value of the padding length field.
danzh8f3a5762019-06-25 13:43:51 -0700383 virtual void OnStreamPadLength(SpdyStreamId /*stream_id*/, size_t /*value*/) {
384 }
QUICHE team82dee2f2019-01-18 12:35:12 -0500385
386 // Called when padding is received (the trailing octets, not pad_len field) on
387 // a DATA frame.
388 // |stream_id| The stream receiving data.
389 // |len| The number of padding octets.
390 virtual void OnStreamPadding(SpdyStreamId stream_id, size_t len) = 0;
391
392 // Called just before processing the payload of a frame containing header
393 // data. Should return an implementation of SpdyHeadersHandlerInterface that
394 // will receive headers for stream |stream_id|. The caller will not take
395 // ownership of the headers handler. The same instance should remain live
396 // and be returned for all header frames comprising a logical header block
397 // (i.e. until OnHeaderFrameEnd() is called).
398 virtual SpdyHeadersHandlerInterface* OnHeaderFrameStart(
399 SpdyStreamId stream_id) = 0;
400
401 // Called after processing the payload of a frame containing header data.
402 virtual void OnHeaderFrameEnd(SpdyStreamId stream_id) = 0;
403
404 // Called when a RST_STREAM frame has been parsed.
405 virtual void OnRstStream(SpdyStreamId stream_id,
406 SpdyErrorCode error_code) = 0;
407
408 // Called when a SETTINGS frame is received.
409 virtual void OnSettings() {}
410
411 // Called when a complete setting within a SETTINGS frame has been parsed.
412 // Note that |id| may or may not be a SETTINGS ID defined in the HTTP/2 spec.
413 virtual void OnSetting(SpdySettingsId id, uint32_t value) = 0;
414
415 // Called when a SETTINGS frame is received with the ACK flag set.
416 virtual void OnSettingsAck() {}
417
418 // Called before and after parsing SETTINGS id and value tuples.
419 virtual void OnSettingsEnd() = 0;
420
421 // Called when a PING frame has been parsed.
422 virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0;
423
424 // Called when a GOAWAY frame has been parsed.
425 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
426 SpdyErrorCode error_code) = 0;
427
428 // Called when a HEADERS frame is received.
429 // Note that header block data is not included. See OnHeaderFrameStart().
430 // |stream_id| The stream receiving the header.
431 // |has_priority| Whether or not the headers frame included a priority value,
432 // and stream dependency info.
433 // |weight| If |has_priority| is true, then weight (in the range [1, 256])
434 // for the receiving stream, otherwise 0.
435 // |parent_stream_id| If |has_priority| is true the parent stream of the
436 // receiving stream, else 0.
437 // |exclusive| If |has_priority| is true the exclusivity of dependence on the
438 // parent stream, else false.
439 // |fin| Whether FIN flag is set in frame headers.
440 // |end| False if HEADERs frame is to be followed by a CONTINUATION frame,
441 // or true if not.
442 virtual void OnHeaders(SpdyStreamId stream_id,
443 bool has_priority,
444 int weight,
445 SpdyStreamId parent_stream_id,
446 bool exclusive,
447 bool fin,
448 bool end) = 0;
449
450 // Called when a WINDOW_UPDATE frame has been parsed.
451 virtual void OnWindowUpdate(SpdyStreamId stream_id,
452 int delta_window_size) = 0;
453
454 // Called when a goaway frame opaque data is available.
455 // |goaway_data| A buffer containing the opaque GOAWAY data chunk received.
456 // |len| The length of the header data buffer. A length of zero indicates
457 // that the header data block has been completely sent.
458 // When this function returns true the visitor indicates that it accepted
459 // all of the data. Returning false indicates that that an error has
460 // occurred while processing the data. Default implementation returns true.
461 virtual bool OnGoAwayFrameData(const char* goaway_data, size_t len);
462
463 // Called when a PUSH_PROMISE frame is received.
464 // Note that header block data is not included. See OnHeaderFrameStart().
465 virtual void OnPushPromise(SpdyStreamId stream_id,
466 SpdyStreamId promised_stream_id,
467 bool end) = 0;
468
469 // Called when a CONTINUATION frame is received.
470 // Note that header block data is not included. See OnHeaderFrameStart().
471 virtual void OnContinuation(SpdyStreamId stream_id, bool end) = 0;
472
473 // Called when an ALTSVC frame has been parsed.
474 virtual void OnAltSvc(
475 SpdyStreamId /*stream_id*/,
476 SpdyStringPiece /*origin*/,
477 const SpdyAltSvcWireFormat::AlternativeServiceVector& /*altsvc_vector*/) {
478 }
479
480 // Called when a PRIORITY frame is received.
481 // |stream_id| The stream to update the priority of.
482 // |parent_stream_id| The parent stream of |stream_id|.
483 // |weight| Stream weight, in the range [1, 256].
484 // |exclusive| Whether |stream_id| should be an only child of
485 // |parent_stream_id|.
486 virtual void OnPriority(SpdyStreamId stream_id,
487 SpdyStreamId parent_stream_id,
488 int weight,
489 bool exclusive) = 0;
490
491 // Called when a frame type we don't recognize is received.
492 // Return true if this appears to be a valid extension frame, false otherwise.
493 // We distinguish between extension frames and nonsense by checking
494 // whether the stream id is valid.
495 virtual bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) = 0;
496};
497
498class SPDY_EXPORT_PRIVATE ExtensionVisitorInterface {
499 public:
500 virtual ~ExtensionVisitorInterface() {}
501
502 // Called when SETTINGS are received, including non-standard SETTINGS.
503 virtual void OnSetting(SpdySettingsId id, uint32_t value) = 0;
504
505 // Called when non-standard frames are received.
506 virtual bool OnFrameHeader(SpdyStreamId stream_id,
507 size_t length,
508 uint8_t type,
509 uint8_t flags) = 0;
510
511 // The payload for a single frame may be delivered as multiple calls to
512 // OnFramePayload. Since the length field is passed in OnFrameHeader, there is
513 // no explicit indication of the end of the frame payload.
514 virtual void OnFramePayload(const char* data, size_t len) = 0;
515};
516
517} // namespace spdy
518
519#endif // QUICHE_SPDY_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_