Index: third_party/crashpad/crashpad/util/net/http_body_gzip.cc |
diff --git a/third_party/crashpad/crashpad/util/net/http_body_gzip.cc b/third_party/crashpad/crashpad/util/net/http_body_gzip.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..70f4db353422ec44f9699284a92cebcfd7aa68da |
--- /dev/null |
+++ b/third_party/crashpad/crashpad/util/net/http_body_gzip.cc |
@@ -0,0 +1,126 @@ |
+// Copyright 2017 The Crashpad Authors. All rights reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include "util/net/http_body_gzip.h" |
+ |
+#include <utility> |
+ |
+#include "base/logging.h" |
+#include "base/numerics/safe_conversions.h" |
+#include "third_party/zlib/zlib_crashpad.h" |
+#include "util/misc/zlib.h" |
+ |
+namespace crashpad { |
+ |
+GzipHTTPBodyStream::GzipHTTPBodyStream(std::unique_ptr<HTTPBodyStream> source) |
+ : input_(), |
+ source_(std::move(source)), |
+ z_stream_(new z_stream()), |
+ state_(State::kUninitialized) {} |
+ |
+GzipHTTPBodyStream::~GzipHTTPBodyStream() { |
+ DCHECK(state_ == State::kUninitialized || |
+ state_ == State::kFinished || |
+ state_ == State::kError); |
+} |
+ |
+FileOperationResult GzipHTTPBodyStream::GetBytesBuffer(uint8_t* buffer, |
+ size_t max_len) { |
+ if (state_ == State::kError) { |
+ return -1; |
+ } |
+ |
+ if (state_ == State::kFinished) { |
+ return 0; |
+ } |
+ |
+ if (state_ == State::kUninitialized) { |
+ z_stream_->zalloc = Z_NULL; |
+ z_stream_->zfree = Z_NULL; |
+ z_stream_->opaque = Z_NULL; |
+ |
+ // The default values for zlib’s internal MAX_WBITS and DEF_MEM_LEVEL. These |
+ // are the values that deflateInit() would use, but they’re not exported |
+ // from zlib. deflateInit2() is used instead of deflateInit() to get the |
+ // gzip wrapper. |
+ const int kZlibMaxWindowBits = 15; |
+ const int kZlibDefaultMemoryLevel = 8; |
+ |
+ int zr = deflateInit2(z_stream_.get(), |
+ Z_DEFAULT_COMPRESSION, |
+ Z_DEFLATED, |
+ ZlibWindowBitsWithGzipWrapper(kZlibMaxWindowBits), |
+ kZlibDefaultMemoryLevel, |
+ Z_DEFAULT_STRATEGY); |
+ if (zr != Z_OK) { |
+ LOG(ERROR) << "deflateInit2: " << ZlibErrorString(zr); |
+ state_ = State::kError; |
+ return -1; |
+ } |
+ |
+ state_ = State::kOperating; |
+ } |
+ |
+ z_stream_->next_out = buffer; |
+ z_stream_->avail_out = base::saturated_cast<uInt>(max_len); |
+ |
+ while (state_ != State::kFinished && z_stream_->avail_out > 0) { |
+ if (state_ != State::kInputEOF && z_stream_->avail_in == 0) { |
+ FileOperationResult input_bytes = |
+ source_->GetBytesBuffer(input_, sizeof(input_)); |
+ if (input_bytes == -1) { |
+ Done(State::kError); |
+ return -1; |
+ } |
+ |
+ if (input_bytes == 0) { |
+ state_ = State::kInputEOF; |
+ } |
+ |
+ z_stream_->next_in = input_; |
+ z_stream_->avail_in = base::checked_cast<uInt>(input_bytes); |
+ } |
+ |
+ int zr = deflate(z_stream_.get(), |
+ state_ == State::kInputEOF ? Z_FINISH : Z_NO_FLUSH); |
+ if (state_ == State::kInputEOF && zr == Z_STREAM_END) { |
+ Done(State::kFinished); |
+ if (state_ == State::kError) { |
+ return -1; |
+ } |
+ } else if (zr != Z_OK) { |
+ LOG(ERROR) << "deflate: " << ZlibErrorString(zr); |
+ Done(State::kError); |
+ return -1; |
+ } |
+ } |
+ |
+ DCHECK_LE(z_stream_->avail_out, max_len); |
+ return max_len - z_stream_->avail_out; |
+} |
+ |
+void GzipHTTPBodyStream::Done(State state) { |
+ DCHECK(state_ == State::kOperating || state_ == State::kInputEOF) << state_; |
+ DCHECK(state == State::kFinished || state == State::kError) << state; |
+ |
+ int zr = deflateEnd(z_stream_.get()); |
+ if (zr != Z_OK) { |
+ LOG(ERROR) << "deflateEnd: " << ZlibErrorString(zr); |
+ state_ = State::kError; |
+ } else { |
+ state_ = state; |
+ } |
+} |
+ |
+} // namespace crashpad |