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 |