blob: 043d6f0ebcdc2d0db9d2f2e523024834181e68ee [file] [log] [blame]
QUICHE teamee762742021-06-25 16:05:19 -07001#ifndef QUICHE_SPDY_CORE_METADATA_EXTENSION_H_
2#define QUICHE_SPDY_CORE_METADATA_EXTENSION_H_
3
4#include <memory>
5#include <string>
6#include <vector>
7
8#include "absl/container/flat_hash_map.h"
9#include "spdy/core/http2_frame_decoder_adapter.h"
10#include "spdy/core/spdy_header_block.h"
11#include "spdy/core/spdy_protocol.h"
12#include "spdy/core/zero_copy_output_buffer.h"
13
14namespace spdy {
15
16// An implementation of the ExtensionVisitorInterface that can parse
17// METADATA frames. METADATA is a non-standard HTTP/2 extension developed and
18// used internally at Google. A peer advertises support for METADATA by sending
19// a setting with a setting ID of kMetadataExtensionId and a value of 1.
20//
21// Metadata is represented as a HPACK header block with literal encoding.
22class MetadataVisitor : public spdy::ExtensionVisitorInterface {
23 public:
24 using MetadataPayload = spdy::SpdyHeaderBlock;
25
26 static_assert(!std::is_copy_constructible<MetadataPayload>::value,
27 "MetadataPayload should be a move-only type!");
28
29 using OnMetadataSupport = std::function<void(bool)>;
30 using OnCompletePayload =
31 std::function<void(spdy::SpdyStreamId, MetadataPayload)>;
32
33 // The HTTP/2 SETTINGS ID that is used to indicate support for METADATA
34 // frames.
35 static const spdy::SpdySettingsId kMetadataExtensionId;
36
37 // The 8-bit frame type code for a METADATA frame.
38 static const uint8_t kMetadataFrameType;
39
40 // The flag that indicates the end of a logical metadata block. Due to frame
41 // size limits, a single metadata block may be emitted as several HTTP/2
42 // frames.
43 static const uint8_t kEndMetadataFlag;
44
45 // |on_payload| is invoked whenever a complete metadata payload is received.
46 // |on_support| is invoked whenever the peer's advertised support for metadata
47 // changes.
48 MetadataVisitor(OnCompletePayload on_payload, OnMetadataSupport on_support);
49 ~MetadataVisitor() override;
50
51 MetadataVisitor(const MetadataVisitor&) = delete;
52 MetadataVisitor& operator=(const MetadataVisitor&) = delete;
53
54 // Interprets the non-standard setting indicating support for METADATA.
55 void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
56
57 // Returns true iff |type| indicates a METADATA frame.
58 bool OnFrameHeader(spdy::SpdyStreamId stream_id, size_t length, uint8_t type,
59 uint8_t flags) override;
60
61 // Consumes a METADATA frame payload. Invokes the registered callback when a
62 // complete payload has been received.
63 void OnFramePayload(const char* data, size_t len) override;
64
65 // Returns true if the peer has advertised support for METADATA via the
66 // appropriate setting.
67 bool PeerSupportsMetadata() const {
68 return peer_supports_metadata_ == MetadataSupportState::SUPPORTED;
69 }
70
71 private:
72 enum class MetadataSupportState : uint8_t {
73 UNSPECIFIED,
74 SUPPORTED,
75 NOT_SUPPORTED,
76 };
77
78 struct MetadataPayloadState;
79
80 using StreamMetadataMap =
81 absl::flat_hash_map<spdy::SpdyStreamId,
82 std::unique_ptr<MetadataPayloadState>>;
83
84 OnCompletePayload on_payload_;
85 OnMetadataSupport on_support_;
86 StreamMetadataMap metadata_map_;
87 spdy::SpdyStreamId current_stream_;
88 MetadataSupportState peer_supports_metadata_;
89};
90
91// A class that serializes metadata blocks as sequences of frames.
92class MetadataSerializer {
93 public:
94 using MetadataPayload = spdy::SpdyHeaderBlock;
95
96 class FrameSequence {
97 public:
98 virtual ~FrameSequence() {}
99
100 // Returns nullptr once the sequence has been exhausted.
101 virtual std::unique_ptr<spdy::SpdyFrameIR> Next() = 0;
102 };
103
104 MetadataSerializer() {}
105
106 MetadataSerializer(const MetadataSerializer&) = delete;
107 MetadataSerializer& operator=(const MetadataSerializer&) = delete;
108
109 // Returns nullptr on failure.
110 std::unique_ptr<FrameSequence> FrameSequenceForPayload(
111 spdy::SpdyStreamId stream_id, MetadataPayload payload);
112};
113
114} // namespace spdy
115
116#endif // QUICHE_SPDY_CORE_METADATA_EXTENSION_H_