Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/compression/decompressor/decompressor.h" 4 : #include "envoy/stats/scope.h" 5 : #include "envoy/stats/stats_macros.h" 6 : 7 : #include "source/common/common/logger.h" 8 : #include "source/extensions/compression/gzip/common/base.h" 9 : 10 : #include "zlib.h" 11 : 12 : namespace Envoy { 13 : namespace Extensions { 14 : namespace Compression { 15 : namespace Gzip { 16 : namespace Decompressor { 17 : 18 : /** 19 : * All zlib decompressor stats. @see stats_macros.h 20 : */ 21 : #define ALL_ZLIB_DECOMPRESSOR_STATS(COUNTER) \ 22 758 : COUNTER(zlib_errno) \ 23 758 : COUNTER(zlib_stream_error) \ 24 758 : COUNTER(zlib_data_error) \ 25 758 : COUNTER(zlib_mem_error) \ 26 758 : COUNTER(zlib_buf_error) \ 27 758 : COUNTER(zlib_version_error) 28 : 29 : /** 30 : * Struct definition for zlib decompressor stats. @see stats_macros.h 31 : */ 32 : struct ZlibDecompressorStats { 33 : ALL_ZLIB_DECOMPRESSOR_STATS(GENERATE_COUNTER_STRUCT) 34 : }; 35 : 36 : /** 37 : * Implementation of decompressor's interface. 38 : */ 39 : class ZlibDecompressorImpl : public Common::Base, 40 : public Envoy::Compression::Decompressor::Decompressor, 41 : public Logger::Loggable<Logger::Id::decompression> { 42 : public: 43 : /** 44 : * Constructor that allows setting the size of decompressor's output buffer. It 45 : * should be called whenever a buffer size different than the 4096 bytes, normally set by the 46 : * default constructor, is desired. If memory is available and it makes sense to output large 47 : * chunks of compressed data, zlib documentation suggests buffers sizes on the order of 128K or 48 : * 256K bytes. @see http://zlib.net/zlib_how.html 49 : * @param chunk_size amount of memory reserved for the decompressor output. 50 : */ 51 : ZlibDecompressorImpl(Stats::Scope& scope, const std::string& stats_prefix, uint64_t chunk_size, 52 : uint64_t max_inflate_ratio); 53 : 54 : /** 55 : * Init must be called in order to initialize the decompressor. Once decompressor is initialized, 56 : * it cannot be initialized again. Init should run before decompressing any data. 57 : * @param window_bits sets the size of the history buffer. It must be greater than or equal to 58 : * the window_bits value provided when data was compressed (zlib manual). 59 : */ 60 : void init(int64_t window_bits); 61 : 62 : // Compression::Decompressor::Decompressor 63 : void decompress(const Buffer::Instance& input_buffer, Buffer::Instance& output_buffer) override; 64 : 65 : // Flag to track whether error occurred during decompression. 66 : // When an error occurs, the error code (a negative int) will be stored in this variable. 67 : int decompression_error_{0}; 68 : 69 : private: 70 : // TODO: clean up friend class. This is here to allow coverage of chargeErrorStats as it isn't 71 : // completely straightforward 72 : // to cause zlib's inflate function to return all the error codes necessary to hit all the cases 73 : // in the switch statement. 74 : friend class ZlibDecompressorStatsTest; 75 758 : static ZlibDecompressorStats generateStats(const std::string& prefix, Stats::Scope& scope) { 76 758 : return ZlibDecompressorStats{ALL_ZLIB_DECOMPRESSOR_STATS(POOL_COUNTER_PREFIX(scope, prefix))}; 77 758 : } 78 : 79 : bool inflateNext(); 80 : void chargeErrorStats(const int result); 81 : 82 : const ZlibDecompressorStats stats_; 83 : const uint64_t max_inflate_ratio_; 84 : }; 85 : 86 : } // namespace Decompressor 87 : } // namespace Gzip 88 : } // namespace Compression 89 : } // namespace Extensions 90 : } // namespace Envoy