proxygen
ZlibStreamDecompressor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
11 
12 #include <folly/io/Cursor.h>
13 
14 using folly::IOBuf;
15 using std::unique_ptr;
16 
17 // IOBuf uses 24 bytes of data for bookeeping purposes, so requesting for 480
18 // bytes of data will be rounded up to an allocation of 512 bytes. (If we
19 // requested for 512 bytes exactly IOBuf would round this up to 768, since it
20 // needs 24 extra bytes of its own.)
21 DEFINE_int64(zlib_buffer_growth, 480,
22  "The buffer growth size to use during IOBuf zlib inflation");
23 DEFINE_int64(zlib_buffer_minsize, 64,
24  "The minimum buffer size to use before growing during IOBuf "
25  "zlib inflation");
26 
27 namespace proxygen {
28 
30  DCHECK(type_ == ZlibCompressionType::NONE) << "Must be uninitialized";
31  type_ = type;
32  status_ = Z_OK;
33  zlibStream_.zalloc = Z_NULL;
34  zlibStream_.zfree = Z_NULL;
35  zlibStream_.opaque = Z_NULL;
36  zlibStream_.total_in = 0;
37  zlibStream_.next_in = Z_NULL;
38  zlibStream_.avail_in = 0;
39  zlibStream_.avail_out = 0;
40  zlibStream_.next_out = Z_NULL;
41 
42  DCHECK(type != ZlibCompressionType::NONE);
43  status_ = inflateInit2(&zlibStream_, static_cast<int>(type_));
44 }
45 
48  init(type);
49 }
50 
53  status_ = inflateEnd(&zlibStream_);
54  }
55 }
56 
57 std::unique_ptr<IOBuf> ZlibStreamDecompressor::decompress(const IOBuf* in) {
58  auto out = IOBuf::create(FLAGS_zlib_buffer_growth);
59  auto appender = folly::io::Appender(out.get(),
60  FLAGS_zlib_buffer_growth);
61 
62  const IOBuf* crtBuf = in;
63  size_t offset = 0;
64  while (true) {
65  // Advance to the next IOBuf if necessary
66  DCHECK_GE(crtBuf->length(), offset);
67  if (crtBuf->length() == offset) {
68  crtBuf = crtBuf->next();
69  offset = 0;
70  if (crtBuf == in) {
71  // We hit the end of the IOBuf chain, and are done.
72  break;
73  }
74  }
75 
76  if (status_ == Z_STREAM_END) {
77  // we convert this into a stream error
78  status_ = Z_STREAM_ERROR;
79  // we should probably bump up a counter here
80  LOG(ERROR) << "error uncompressing buffer: reached end of zlib data "
81  "before the end of the buffer";
82  return nullptr;
83  }
84 
85  // Ensure there is space in the output IOBuf
86  appender.ensure(FLAGS_zlib_buffer_minsize);
87  DCHECK_GT(appender.length(), 0);
88 
89  const size_t origAvailIn = crtBuf->length() - offset;
90  zlibStream_.next_in = const_cast<uint8_t*>(crtBuf->data() + offset);
91  zlibStream_.avail_in = origAvailIn;
92  zlibStream_.next_out = appender.writableData();
93  zlibStream_.avail_out = appender.length();
94  status_ = inflate(&zlibStream_, Z_PARTIAL_FLUSH);
95  if (status_ != Z_OK && status_ != Z_STREAM_END) {
96  LOG(INFO) << "error uncompressing buffer: r=" << status_;
97  return nullptr;
98  }
99 
100  // Adjust the input offset ahead
101  auto inConsumed = origAvailIn - zlibStream_.avail_in;
102  offset += inConsumed;
103  // Move output buffer ahead
104  auto outMove = appender.length() - zlibStream_.avail_out;
105  appender.append(outMove);
106  }
107 
108  return out;
109 }
110 
111 }
void init(ZlibCompressionType type)
PskType type
DEFINE_int64(zlib_buffer_growth, 480,"The buffer growth size to use during IOBuf zlib inflation")
std::unique_ptr< folly::IOBuf > decompress(const folly::IOBuf *in)
IOBuf * next()
Definition: IOBuf.h:600