OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #include "util/net/http_body_gzip.h" |
| 16 |
| 17 #include <utility> |
| 18 |
| 19 #include "base/logging.h" |
| 20 #include "base/numerics/safe_conversions.h" |
| 21 #include "third_party/zlib/zlib_crashpad.h" |
| 22 #include "util/misc/zlib.h" |
| 23 |
| 24 namespace crashpad { |
| 25 |
| 26 GzipHTTPBodyStream::GzipHTTPBodyStream(std::unique_ptr<HTTPBodyStream> source) |
| 27 : input_(), |
| 28 source_(std::move(source)), |
| 29 z_stream_(new z_stream()), |
| 30 state_(State::kUninitialized) {} |
| 31 |
| 32 GzipHTTPBodyStream::~GzipHTTPBodyStream() { |
| 33 DCHECK(state_ == State::kUninitialized || |
| 34 state_ == State::kFinished || |
| 35 state_ == State::kError); |
| 36 } |
| 37 |
| 38 FileOperationResult GzipHTTPBodyStream::GetBytesBuffer(uint8_t* buffer, |
| 39 size_t max_len) { |
| 40 if (state_ == State::kError) { |
| 41 return -1; |
| 42 } |
| 43 |
| 44 if (state_ == State::kFinished) { |
| 45 return 0; |
| 46 } |
| 47 |
| 48 if (state_ == State::kUninitialized) { |
| 49 z_stream_->zalloc = Z_NULL; |
| 50 z_stream_->zfree = Z_NULL; |
| 51 z_stream_->opaque = Z_NULL; |
| 52 |
| 53 // The default values for zlib’s internal MAX_WBITS and DEF_MEM_LEVEL. These |
| 54 // are the values that deflateInit() would use, but they’re not exported |
| 55 // from zlib. deflateInit2() is used instead of deflateInit() to get the |
| 56 // gzip wrapper. |
| 57 const int kZlibMaxWindowBits = 15; |
| 58 const int kZlibDefaultMemoryLevel = 8; |
| 59 |
| 60 int zr = deflateInit2(z_stream_.get(), |
| 61 Z_DEFAULT_COMPRESSION, |
| 62 Z_DEFLATED, |
| 63 ZlibWindowBitsWithGzipWrapper(kZlibMaxWindowBits), |
| 64 kZlibDefaultMemoryLevel, |
| 65 Z_DEFAULT_STRATEGY); |
| 66 if (zr != Z_OK) { |
| 67 LOG(ERROR) << "deflateInit2: " << ZlibErrorString(zr); |
| 68 state_ = State::kError; |
| 69 return -1; |
| 70 } |
| 71 |
| 72 state_ = State::kOperating; |
| 73 } |
| 74 |
| 75 z_stream_->next_out = buffer; |
| 76 z_stream_->avail_out = base::saturated_cast<uInt>(max_len); |
| 77 |
| 78 while (state_ != State::kFinished && z_stream_->avail_out > 0) { |
| 79 if (state_ != State::kInputEOF && z_stream_->avail_in == 0) { |
| 80 FileOperationResult input_bytes = |
| 81 source_->GetBytesBuffer(input_, sizeof(input_)); |
| 82 if (input_bytes == -1) { |
| 83 Done(State::kError); |
| 84 return -1; |
| 85 } |
| 86 |
| 87 if (input_bytes == 0) { |
| 88 state_ = State::kInputEOF; |
| 89 } |
| 90 |
| 91 z_stream_->next_in = input_; |
| 92 z_stream_->avail_in = base::checked_cast<uInt>(input_bytes); |
| 93 } |
| 94 |
| 95 int zr = deflate(z_stream_.get(), |
| 96 state_ == State::kInputEOF ? Z_FINISH : Z_NO_FLUSH); |
| 97 if (state_ == State::kInputEOF && zr == Z_STREAM_END) { |
| 98 Done(State::kFinished); |
| 99 if (state_ == State::kError) { |
| 100 return -1; |
| 101 } |
| 102 } else if (zr != Z_OK) { |
| 103 LOG(ERROR) << "deflate: " << ZlibErrorString(zr); |
| 104 Done(State::kError); |
| 105 return -1; |
| 106 } |
| 107 } |
| 108 |
| 109 DCHECK_LE(z_stream_->avail_out, max_len); |
| 110 return max_len - z_stream_->avail_out; |
| 111 } |
| 112 |
| 113 void GzipHTTPBodyStream::Done(State state) { |
| 114 DCHECK(state_ == State::kOperating || state_ == State::kInputEOF) << state_; |
| 115 DCHECK(state == State::kFinished || state == State::kError) << state; |
| 116 |
| 117 int zr = deflateEnd(z_stream_.get()); |
| 118 if (zr != Z_OK) { |
| 119 LOG(ERROR) << "deflateEnd: " << ZlibErrorString(zr); |
| 120 state_ = State::kError; |
| 121 } else { |
| 122 state_ = state; |
| 123 } |
| 124 } |
| 125 |
| 126 } // namespace crashpad |
OLD | NEW |