Line data Source code
1 : #pragma once 2 : 3 : #include <cstdint> 4 : #include <string> 5 : 6 : #include "envoy/http/codec.h" 7 : 8 : #include "source/common/buffer/buffer_impl.h" 9 : #include "source/common/common/logger.h" 10 : 11 : #include "nghttp2/nghttp2.h" 12 : 13 : namespace Envoy { 14 : namespace Http { 15 : namespace Http2 { 16 : 17 : class MetadataEncoderDecoderTest_VerifyEncoderDecoderOnMultipleMetadataMaps_Test; 18 : 19 : // A class that decodes METADATA payload in the format of HTTP/2 header block into MetadataMap, a 20 : // map of string key value pairs. 21 : class MetadataDecoder : Logger::Loggable<Logger::Id::http2> { 22 : public: 23 : /** 24 : * @param cb is the decoder's callback function. The callback function is called when the decoder 25 : * finishes decoding metadata. 26 : */ 27 : MetadataDecoder(MetadataCallback cb); 28 : ~MetadataDecoder(); 29 : 30 : /** 31 : * Calls this function when METADATA frame payload is received. The payload doesn't need to be 32 : * complete. 33 : * @param data is the pointer to the start of the payload. 34 : * @param len is the size of the received payload. 35 : * @return whether Metadata is received successfully. 36 : */ 37 : bool receiveMetadata(const uint8_t* data, size_t len); 38 : 39 : /** 40 : * Calls when a complete METADATA frame is received. The function will decode METADATA received. 41 : * If the frame is the last one in the group, the function triggers the registered callback 42 : * function callback_. 43 : * @param end_metadata indicates if all the METADATA has been received. 44 : * @return whether the operation succeeds. 45 : */ 46 : bool onMetadataFrameComplete(bool end_metadata); 47 : 48 : /** 49 : * Returns the total size of METADATA frame payloads received. 50 : */ 51 0 : uint64_t totalPayloadSize() const { return total_payload_size_; } 52 : 53 : private: 54 : friend class MetadataEncoderDecoderTest_VerifyEncoderDecoderOnMultipleMetadataMaps_Test; 55 : friend class MetadataEncoderDecoderTest_VerifyEncoderDecoderMultipleMetadataReachSizeLimit_Test; 56 : friend class MetadataEncoderTest_VerifyEncoderDecoderOnMultipleMetadataMaps_Test; 57 : friend class MetadataEncoderTest_VerifyEncoderDecoderMultipleMetadataReachSizeLimit_Test; 58 : 59 : struct HpackDecoderContext; 60 : 61 : /** 62 : * Decodes METADATA payload using nghttp2. 63 : * @param end_metadata indicates is END_METADATA is true. 64 : * @return if decoding succeeds. 65 : */ 66 : bool decodeMetadataPayloadUsingNghttp2(bool end_metadata); 67 : 68 : /** 69 : * Decodes METADATA payload using QUICHE. 70 : * @param end_metadata indicates is END_METADATA is true. 71 : * @return if decoding succeeds. 72 : */ 73 : bool decodeMetadataPayload(bool end_metadata); 74 : 75 : void resetDecoderContext(); 76 : 77 : // Metadata that is currently being decoded. 78 : MetadataMapPtr metadata_map_; 79 : 80 : // Metadata event callback function. 81 : MetadataCallback callback_; 82 : 83 : // Payload received. 84 : Buffer::OwnedImpl payload_; 85 : 86 : // Payload size limit. If the total payload received exceeds the limit, fails the connection. 87 : const uint64_t max_payload_size_bound_ = 1024 * 1024; 88 : 89 : uint64_t total_payload_size_ = 0; 90 : 91 : // TODO(soya3129): consider sharing the inflater with all streams in a connection. Caveat: 92 : // inflater failure on one stream can impact other streams. 93 : using Inflater = CSmartPtr<nghttp2_hd_inflater, nghttp2_hd_inflate_del>; 94 : Inflater inflater_; 95 : 96 : std::unique_ptr<HpackDecoderContext> decoder_context_; 97 : }; 98 : 99 : } // namespace Http2 100 : } // namespace Http 101 : } // namespace Envoy