Line data Source code
1 : #include "source/common/http/http2/metadata_encoder.h" 2 : 3 : #include "source/common/common/assert.h" 4 : 5 : #include "absl/container/fixed_array.h" 6 : 7 : namespace Envoy { 8 : namespace Http { 9 : namespace Http2 { 10 : 11 : class BufferMetadataSource : public http2::adapter::MetadataSource { 12 : public: 13 : explicit BufferMetadataSource(Buffer::OwnedImpl payload) 14 8 : : payload_(std::move(payload)), original_payload_length_(payload_.length()) {} 15 : 16 3 : size_t NumFrames(size_t max_frame_size) const override { 17 : // Rounds up, so a trailing partial frame is counted. 18 3 : return (original_payload_length_ + max_frame_size - 1) / max_frame_size; 19 3 : } 20 : 21 8 : std::pair<int64_t, bool> Pack(uint8_t* dest, size_t dest_len) override { 22 8 : const size_t to_copy = std::min(dest_len, static_cast<size_t>(payload_.length())); 23 8 : payload_.copyOut(0, to_copy, dest); 24 8 : payload_.drain(to_copy); 25 8 : return std::make_pair(static_cast<int64_t>(to_copy), payload_.length() == 0); 26 8 : } 27 : 28 0 : void OnFailure() override {} 29 : 30 : private: 31 : Buffer::OwnedImpl payload_; 32 : const size_t original_payload_length_; 33 : }; 34 : 35 6 : NewMetadataEncoder::NewMetadataEncoder() { 36 42 : deflater_.SetIndexingPolicy([](absl::string_view, absl::string_view) { return false; }); 37 6 : } 38 : 39 : std::vector<std::unique_ptr<http2::adapter::MetadataSource>> 40 8 : NewMetadataEncoder::createSources(const MetadataMapVector& metadata_map_vector) { 41 8 : MetadataSourceVector v; 42 8 : v.reserve(metadata_map_vector.size()); 43 8 : for (const auto& metadata_map : metadata_map_vector) { 44 8 : v.push_back(createSource(*metadata_map)); 45 8 : } 46 8 : return v; 47 8 : } 48 : 49 : std::unique_ptr<http2::adapter::MetadataSource> 50 8 : NewMetadataEncoder::createSource(const MetadataMap& metadata_map) { 51 8 : static const size_t kMaxEncodingChunkSize = 64 * 1024; 52 8 : spdy::HpackEncoder::Representations r; 53 8 : r.reserve(metadata_map.size()); 54 42 : for (const auto& header : metadata_map) { 55 42 : r.push_back({header.first, header.second}); 56 42 : } 57 8 : ASSERT(r.size() == metadata_map.size()); 58 8 : Buffer::OwnedImpl payload; 59 8 : auto progressive_encoder = deflater_.EncodeRepresentations(r); 60 16 : while (progressive_encoder->HasNext()) { 61 8 : payload.add(progressive_encoder->Next(kMaxEncodingChunkSize)); 62 8 : } 63 8 : return std::make_unique<BufferMetadataSource>(std::move(payload)); 64 8 : } 65 : 66 : } // namespace Http2 67 : } // namespace Http 68 : } // namespace Envoy