| #ifndef QUICHE_SPDY_CORE_METADATA_EXTENSION_H_ | |
| #define QUICHE_SPDY_CORE_METADATA_EXTENSION_H_ | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/container/flat_hash_map.h" | |
| #include "spdy/core/http2_frame_decoder_adapter.h" | |
| #include "spdy/core/spdy_header_block.h" | |
| #include "spdy/core/spdy_protocol.h" | |
| #include "spdy/core/zero_copy_output_buffer.h" | |
| namespace spdy { | |
| // An implementation of the ExtensionVisitorInterface that can parse | |
| // METADATA frames. METADATA is a non-standard HTTP/2 extension developed and | |
| // used internally at Google. A peer advertises support for METADATA by sending | |
| // a setting with a setting ID of kMetadataExtensionId and a value of 1. | |
| // | |
| // Metadata is represented as a HPACK header block with literal encoding. | |
| class MetadataVisitor : public spdy::ExtensionVisitorInterface { | |
| public: | |
| using MetadataPayload = spdy::SpdyHeaderBlock; | |
| static_assert(!std::is_copy_constructible<MetadataPayload>::value, | |
| "MetadataPayload should be a move-only type!"); | |
| using OnMetadataSupport = std::function<void(bool)>; | |
| using OnCompletePayload = | |
| std::function<void(spdy::SpdyStreamId, MetadataPayload)>; | |
| // The HTTP/2 SETTINGS ID that is used to indicate support for METADATA | |
| // frames. | |
| static const spdy::SpdySettingsId kMetadataExtensionId; | |
| // The 8-bit frame type code for a METADATA frame. | |
| static const uint8_t kMetadataFrameType; | |
| // The flag that indicates the end of a logical metadata block. Due to frame | |
| // size limits, a single metadata block may be emitted as several HTTP/2 | |
| // frames. | |
| static const uint8_t kEndMetadataFlag; | |
| // |on_payload| is invoked whenever a complete metadata payload is received. | |
| // |on_support| is invoked whenever the peer's advertised support for metadata | |
| // changes. | |
| MetadataVisitor(OnCompletePayload on_payload, OnMetadataSupport on_support); | |
| ~MetadataVisitor() override; | |
| MetadataVisitor(const MetadataVisitor&) = delete; | |
| MetadataVisitor& operator=(const MetadataVisitor&) = delete; | |
| // Interprets the non-standard setting indicating support for METADATA. | |
| void OnSetting(spdy::SpdySettingsId id, uint32_t value) override; | |
| // Returns true iff |type| indicates a METADATA frame. | |
| bool OnFrameHeader(spdy::SpdyStreamId stream_id, size_t length, uint8_t type, | |
| uint8_t flags) override; | |
| // Consumes a METADATA frame payload. Invokes the registered callback when a | |
| // complete payload has been received. | |
| void OnFramePayload(const char* data, size_t len) override; | |
| // Returns true if the peer has advertised support for METADATA via the | |
| // appropriate setting. | |
| bool PeerSupportsMetadata() const { | |
| return peer_supports_metadata_ == MetadataSupportState::SUPPORTED; | |
| } | |
| private: | |
| enum class MetadataSupportState : uint8_t { | |
| UNSPECIFIED, | |
| SUPPORTED, | |
| NOT_SUPPORTED, | |
| }; | |
| struct MetadataPayloadState; | |
| using StreamMetadataMap = | |
| absl::flat_hash_map<spdy::SpdyStreamId, | |
| std::unique_ptr<MetadataPayloadState>>; | |
| OnCompletePayload on_payload_; | |
| OnMetadataSupport on_support_; | |
| StreamMetadataMap metadata_map_; | |
| spdy::SpdyStreamId current_stream_; | |
| MetadataSupportState peer_supports_metadata_; | |
| }; | |
| // A class that serializes metadata blocks as sequences of frames. | |
| class MetadataSerializer { | |
| public: | |
| using MetadataPayload = spdy::SpdyHeaderBlock; | |
| class FrameSequence { | |
| public: | |
| virtual ~FrameSequence() {} | |
| // Returns nullptr once the sequence has been exhausted. | |
| virtual std::unique_ptr<spdy::SpdyFrameIR> Next() = 0; | |
| }; | |
| MetadataSerializer() {} | |
| MetadataSerializer(const MetadataSerializer&) = delete; | |
| MetadataSerializer& operator=(const MetadataSerializer&) = delete; | |
| // Returns nullptr on failure. | |
| std::unique_ptr<FrameSequence> FrameSequenceForPayload( | |
| spdy::SpdyStreamId stream_id, MetadataPayload payload); | |
| }; | |
| } // namespace spdy | |
| #endif // QUICHE_SPDY_CORE_METADATA_EXTENSION_H_ |