Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/CPPAlliance/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_DETAIL_IMPL_ZLIB_CODEC_IPP
11 : #define BOOST_HTTP_PROTO_DETAIL_IMPL_ZLIB_CODEC_IPP
12 :
13 : #ifdef BOOST_HTTP_PROTO_HAS_ZLIB
14 :
15 : #include <boost/http_proto/parser.hpp>
16 : #include <boost/http_proto/serializer.hpp>
17 : #include <boost/http_proto/detail/codec.hpp>
18 : #include <boost/core/ignore_unused.hpp>
19 : #include <boost/throw_exception.hpp>
20 : #include "zlib.h"
21 :
22 : namespace boost {
23 : namespace http_proto {
24 : namespace detail {
25 :
26 : enum class zlib_error
27 : {
28 : ok = 0,
29 : stream_end = 1,
30 : need_dict = 2,
31 : errno_ = -1,
32 : stream_err = -2,
33 : data_err = -3,
34 : mem_err = -4,
35 : buf_err = -5,
36 : version_err = -6
37 : };
38 :
39 : //------------------------------------------------
40 : } // detail
41 : } // http_proto
42 : namespace system {
43 : template<>
44 : struct is_error_code_enum<
45 : ::boost::http_proto::detail::zlib_error>
46 : {
47 : static bool const value = true;
48 : };
49 : } // system
50 : namespace http_proto {
51 : namespace detail {
52 : //------------------------------------------------
53 :
54 : error_code
55 0 : make_error_code(
56 : zlib_error ev) noexcept
57 : {
58 : struct cat_t : error_category
59 : {
60 0 : cat_t() noexcept
61 0 : : error_category(
62 0 : 0xe6c6d0215d1d6e22)
63 : {
64 0 : }
65 :
66 : const char*
67 0 : name() const noexcept override
68 : {
69 0 : return "boost.http.proto.zlib_error";
70 : }
71 :
72 : std::string
73 0 : message(int ev) const override
74 : {
75 0 : switch(static_cast<zlib_error>(ev))
76 : {
77 0 : case zlib_error::ok: return "Z_OK";
78 0 : case zlib_error::stream_end: return "Z_STREAM_END";
79 0 : case zlib_error::need_dict: return "Z_NEED_DICT";
80 0 : case zlib_error::errno_: return "Z_ERRNO";
81 0 : case zlib_error::stream_err: return "Z_STREAM_ERROR";
82 0 : case zlib_error::data_err: return "Z_DATA_ERROR";
83 0 : case zlib_error::mem_err: return "Z_MEM_ERROR";
84 0 : case zlib_error::buf_err: return "Z_BUF_ERROR";
85 0 : case zlib_error::version_err: return "Z_VERSION_ERROR";
86 0 : default:
87 0 : return "unknown";
88 : }
89 : }
90 : };
91 0 : static cat_t const cat{};
92 : return error_code{static_cast<
93 : std::underlying_type<
94 0 : error>::type>(ev), cat};
95 : }
96 :
97 : //------------------------------------------------
98 :
99 : class gzip_decoder : public codec
100 : {
101 : void* zs_ = nullptr;
102 :
103 : public:
104 : ~gzip_decoder() override;
105 : gzip_decoder();
106 :
107 : gzip_decoder(
108 : gzip_decoder&&) noexcept;
109 : gzip_decoder& operator=(
110 : gzip_decoder&&) = delete;
111 :
112 : results
113 : exchange(
114 : void* output,
115 : std::size_t output_size,
116 : void const* input,
117 : std::size_t input_size) override;
118 : };
119 :
120 4 : gzip_decoder::
121 2 : ~gzip_decoder()
122 : {
123 2 : auto zs = reinterpret_cast<
124 : ::z_stream*>(zs_);
125 2 : if(zs)
126 : {
127 2 : ::inflateEnd(zs);
128 2 : delete zs;
129 : }
130 4 : }
131 :
132 2 : gzip_decoder::
133 2 : gzip_decoder()
134 : {
135 2 : ::z_stream* zs = new ::z_stream;
136 2 : zs->zalloc = nullptr;
137 2 : zs->zfree = nullptr;
138 2 : zs->opaque = nullptr;
139 2 : int const ec = ::inflateInit(zs);
140 2 : if(ec == Z_OK)
141 : {
142 2 : zs_ = zs;
143 2 : return;
144 : }
145 0 : delete zs;
146 0 : throw_exception(
147 0 : system_error(error_code(
148 : static_cast<zlib_error>(ec))),
149 0 : BOOST_CURRENT_LOCATION);
150 : }
151 :
152 0 : gzip_decoder::
153 : gzip_decoder(
154 0 : gzip_decoder&& other) noexcept
155 0 : : zs_(other.zs_)
156 : {
157 0 : other.zs_ = nullptr;
158 0 : }
159 :
160 : auto
161 0 : gzip_decoder::
162 : exchange(
163 : void* output,
164 : std::size_t output_size,
165 : void const* input,
166 : std::size_t input_size) ->
167 : results
168 : {
169 0 : auto zs = reinterpret_cast<
170 : ::z_stream*>(zs_);
171 : // VFALCO zlib seems to need const_cast
172 0 : zs->next_in =
173 : const_cast<Bytef z_const*>(
174 : reinterpret_cast<
175 : Bytef const*>(input));
176 0 : zs->avail_in = static_cast<uInt>(input_size);
177 0 : zs->next_out = reinterpret_cast<
178 : Bytef*>(output);
179 0 : zs->avail_out = static_cast<uInt>(output_size);
180 0 : results rv;
181 : rv.ec = static_cast<zlib_error>(
182 0 : ::inflate(zs, Z_NO_FLUSH));
183 0 : rv.input_used =
184 0 : input_size - zs->avail_in;
185 0 : rv.output_used =
186 0 : output_size - zs->avail_out;
187 0 : return rv;
188 : }
189 :
190 : //------------------------------------------------
191 :
192 : class gzip_encoder : public codec
193 : {
194 : void* zs_ = nullptr;
195 :
196 : public:
197 : ~gzip_encoder() override;
198 : gzip_encoder();
199 :
200 : gzip_encoder(
201 : gzip_encoder&&) noexcept;
202 : gzip_encoder& operator=(
203 : gzip_encoder&&) = delete;
204 :
205 : results
206 : exchange(
207 : void* output,
208 : std::size_t output_size,
209 : void const* input,
210 : std::size_t input_size) override;
211 : };
212 :
213 0 : gzip_encoder::
214 0 : ~gzip_encoder()
215 : {
216 0 : auto zs = reinterpret_cast<
217 : ::z_stream*>(zs_);
218 0 : if(zs)
219 : {
220 0 : ::deflateEnd(zs);
221 0 : delete zs;
222 : }
223 0 : }
224 :
225 0 : gzip_encoder::
226 0 : gzip_encoder()
227 : {
228 0 : ::z_stream* zs = new ::z_stream;
229 0 : zs->zalloc = nullptr;
230 0 : zs->zfree = nullptr;
231 0 : zs->opaque = nullptr;
232 0 : int const ec = ::deflateInit(zs,
233 : Z_DEFAULT_COMPRESSION);
234 0 : if(ec == Z_OK)
235 : {
236 0 : zs_ = zs;
237 0 : return;
238 : }
239 0 : delete zs;
240 0 : throw_exception(
241 0 : system_error(error_code(
242 : static_cast<zlib_error>(ec))),
243 0 : BOOST_CURRENT_LOCATION);
244 : }
245 :
246 0 : gzip_encoder::
247 : gzip_encoder(
248 0 : gzip_encoder&& other) noexcept
249 0 : : zs_(other.zs_)
250 : {
251 0 : other.zs_ = nullptr;
252 0 : }
253 :
254 : auto
255 0 : gzip_encoder::
256 : exchange(
257 : void* output,
258 : std::size_t output_size,
259 : void const* input,
260 : std::size_t input_size) ->
261 : results
262 : {
263 0 : auto zs = reinterpret_cast<
264 : ::z_stream*>(zs_);
265 : // VFALCO zlib seems to need const_cast
266 0 : zs->next_in =
267 : const_cast<Bytef z_const*>(
268 : reinterpret_cast<
269 : Bytef const*>(input));
270 0 : zs->avail_in = static_cast<uInt>(input_size);
271 0 : zs->next_out = reinterpret_cast<
272 : Bytef*>(output);
273 0 : zs->avail_out = static_cast<uInt>(output_size);
274 0 : results rv;
275 : rv.ec = static_cast<zlib_error>(
276 0 : ::deflate(zs, Z_NO_FLUSH));
277 0 : rv.input_used =
278 0 : input_size - zs->avail_in;
279 0 : rv.output_used =
280 0 : output_size - zs->avail_out;
281 0 : return rv;
282 : }
283 :
284 : //------------------------------------------------
285 :
286 : class deflate_decoder : public codec
287 : {
288 : void* zs_ = nullptr;
289 :
290 : public:
291 : ~deflate_decoder() override;
292 : deflate_decoder();
293 :
294 : deflate_decoder(
295 : deflate_decoder&&) noexcept;
296 : deflate_decoder& operator=(
297 : deflate_decoder&&) = delete;
298 :
299 : results
300 : exchange(
301 : void* output,
302 : std::size_t output_size,
303 : void const* input,
304 : std::size_t input_size) override;
305 : };
306 :
307 0 : deflate_decoder::
308 0 : ~deflate_decoder()
309 : {
310 0 : auto zs = reinterpret_cast<
311 : ::z_stream*>(zs_);
312 0 : if(zs)
313 : {
314 0 : ::inflateEnd(zs);
315 0 : delete zs;
316 : }
317 0 : }
318 :
319 0 : deflate_decoder::
320 0 : deflate_decoder()
321 : {
322 0 : ::z_stream* zs = new ::z_stream;
323 0 : zs->zalloc = nullptr;
324 0 : zs->zfree = nullptr;
325 0 : zs->opaque = nullptr;
326 0 : int const ec = ::inflateInit(zs);
327 0 : if(ec == Z_OK)
328 : {
329 0 : zs_ = zs;
330 0 : return;
331 : }
332 0 : delete zs;
333 0 : throw_exception(
334 0 : system_error(error_code(
335 : static_cast<zlib_error>(ec))),
336 0 : BOOST_CURRENT_LOCATION);
337 : }
338 :
339 0 : deflate_decoder::
340 : deflate_decoder(
341 0 : deflate_decoder&& other) noexcept
342 0 : : zs_(other.zs_)
343 : {
344 0 : other.zs_ = nullptr;
345 0 : }
346 :
347 : auto
348 0 : deflate_decoder::
349 : exchange(
350 : void* output,
351 : std::size_t output_size,
352 : void const* input,
353 : std::size_t input_size) ->
354 : results
355 : {
356 0 : auto zs = reinterpret_cast<
357 : ::z_stream*>(zs_);
358 : // VFALCO zlib seems to need const_cast
359 0 : zs->next_in =
360 : const_cast<Bytef z_const*>(
361 : reinterpret_cast<
362 : Bytef const*>(input));
363 0 : zs->avail_in = static_cast<uInt>(input_size);
364 0 : zs->next_out = reinterpret_cast<
365 : Bytef*>(output);
366 0 : zs->avail_out = static_cast<uInt>(output_size);
367 0 : results rv;
368 : rv.ec = static_cast<zlib_error>(
369 0 : ::inflate(zs, Z_NO_FLUSH));
370 0 : rv.input_used =
371 0 : input_size - zs->avail_in;
372 0 : rv.output_used =
373 0 : output_size - zs->avail_out;
374 0 : return rv;
375 : }
376 :
377 : //------------------------------------------------
378 :
379 : class deflate_encoder : public codec
380 : {
381 : void* zs_ = nullptr;
382 :
383 : public:
384 : ~deflate_encoder() override;
385 : deflate_encoder();
386 :
387 : deflate_encoder(
388 : deflate_encoder&&) noexcept;
389 : deflate_encoder& operator=(
390 : deflate_encoder&&) = delete;
391 :
392 : results
393 : exchange(
394 : void* output,
395 : std::size_t output_size,
396 : void const* input,
397 : std::size_t input_size) override;
398 : };
399 :
400 0 : deflate_encoder::
401 0 : ~deflate_encoder()
402 : {
403 0 : auto zs = reinterpret_cast<
404 : ::z_stream*>(zs_);
405 0 : if(zs)
406 : {
407 0 : ::deflateEnd(zs);
408 0 : delete zs;
409 : }
410 0 : }
411 :
412 0 : deflate_encoder::
413 0 : deflate_encoder()
414 : {
415 0 : ::z_stream* zs = new ::z_stream;
416 0 : zs->zalloc = nullptr;
417 0 : zs->zfree = nullptr;
418 0 : zs->opaque = nullptr;
419 0 : int const ec = ::deflateInit(zs,
420 : Z_DEFAULT_COMPRESSION);
421 0 : if(ec == Z_OK)
422 : {
423 0 : zs_ = zs;
424 0 : return;
425 : }
426 0 : delete zs;
427 0 : throw_exception(
428 0 : system_error(error_code(
429 : static_cast<zlib_error>(ec))),
430 0 : BOOST_CURRENT_LOCATION);
431 : }
432 :
433 0 : deflate_encoder::
434 : deflate_encoder(
435 0 : deflate_encoder&& other) noexcept
436 0 : : zs_(other.zs_)
437 : {
438 0 : other.zs_ = nullptr;
439 0 : }
440 :
441 : auto
442 0 : deflate_encoder::
443 : exchange(
444 : void* output,
445 : std::size_t output_size,
446 : void const* input,
447 : std::size_t input_size) ->
448 : results
449 : {
450 0 : auto zs = reinterpret_cast<
451 : ::z_stream*>(zs_);
452 : // VFALCO zlib seems to need const_cast
453 0 : zs->next_in =
454 : const_cast<Bytef z_const*>(
455 : reinterpret_cast<
456 : Bytef const*>(input));
457 0 : zs->avail_in = static_cast<uInt>(input_size);
458 0 : zs->next_out = reinterpret_cast<
459 : Bytef*>(output);
460 0 : zs->avail_out = static_cast<uInt>(output_size);
461 0 : results rv;
462 : rv.ec = static_cast<zlib_error>(
463 0 : ::deflate(zs, Z_NO_FLUSH));
464 0 : rv.input_used =
465 0 : input_size - zs->avail_in;
466 0 : rv.output_used =
467 0 : output_size - zs->avail_out;
468 0 : return rv;
469 : }
470 :
471 : } // detail
472 :
473 : //------------------------------------------------
474 :
475 : void
476 0 : parser::
477 : apply_param(
478 : deflate_decoder_t const&)
479 : {
480 0 : dec_[deflate_codec].reset(
481 0 : new detail::deflate_decoder);
482 0 : }
483 :
484 : void
485 2 : parser::
486 : apply_param(
487 : gzip_decoder_t const&)
488 : {
489 2 : dec_[gzip_codec].reset(
490 2 : new detail::gzip_decoder);
491 2 : }
492 :
493 : //------------------------------------------------
494 :
495 : void
496 0 : serializer::
497 : apply_param(
498 : deflate_decoder_t const&)
499 : {
500 0 : dec_[deflate_codec].reset(
501 0 : new detail::deflate_decoder);
502 0 : }
503 :
504 : void
505 0 : serializer::
506 : apply_param(
507 : deflate_encoder_t const&)
508 : {
509 0 : enc_[deflate_codec].reset(
510 0 : new detail::deflate_encoder);
511 0 : }
512 :
513 : void
514 0 : serializer::
515 : apply_param(
516 : gzip_decoder_t const&)
517 : {
518 0 : dec_[gzip_codec].reset(
519 0 : new detail::gzip_decoder);
520 0 : }
521 :
522 : void
523 0 : serializer::
524 : apply_param(
525 : gzip_encoder_t const&)
526 : {
527 0 : enc_[gzip_codec].reset(
528 0 : new detail::gzip_encoder);
529 0 : }
530 :
531 : } // http_proto
532 : } // boost
533 :
534 : #endif
535 : #endif
|