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
89
  COUNTER(zlib_errno)                                                                              \
23
89
  COUNTER(zlib_stream_error)                                                                       \
24
89
  COUNTER(zlib_data_error)                                                                         \
25
89
  COUNTER(zlib_mem_error)                                                                          \
26
89
  COUNTER(zlib_buf_error)                                                                          \
27
89
  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
89
  static ZlibDecompressorStats generateStats(const std::string& prefix, Stats::Scope& scope) {
76
89
    return ZlibDecompressorStats{ALL_ZLIB_DECOMPRESSOR_STATS(POOL_COUNTER_PREFIX(scope, prefix))};
77
89
  }
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