Skip to content

Commit de06db2

Browse files
committed
serializer uses configuration service
Closes #142
1 parent d98578e commit de06db2

File tree

10 files changed

+466
-295
lines changed

10 files changed

+466
-295
lines changed

include/boost/http_proto/parser.hpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,33 @@ class parser
9393
*/
9494
std::uint64_t body_limit = 64 * 1024;
9595

96-
/** True if parser can decode deflate transfer and content encodings.
96+
/** True if parser can decode deflate Content-Encoding.
9797
98-
The zlib service must already be
98+
The @ref zlib::inflate_service must already be
9999
installed thusly, or else an exception
100100
is thrown.
101101
*/
102102
bool apply_deflate_decoder = false;
103103

104-
/** True if parser can decode gzip transfer and content encodings.
104+
/** True if parser can decode gzip Content-Encoding.
105105
106-
The zlib service must already be
106+
The @ref zlib::inflate_service must already be
107107
installed thusly, or else an exception
108108
is thrown.
109109
*/
110110
bool apply_gzip_decoder = false;
111111

112+
/** Specifies the zlib windows bits 9..15.
113+
114+
The windows bits must be greater than or equal to
115+
the windows bits value used for compression.
116+
117+
If a compressed message has a larger window size,
118+
parsing ends with @ref zlib::error::data_err instead
119+
of allocating a bigger window.
120+
*/
121+
int zlib_window_bits = 15;
122+
112123
/** Minimum space for payload buffering.
113124
114125
This value controls the following

include/boost/http_proto/serializer.hpp

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace boost {
3333
namespace http_proto {
3434

3535
#ifndef BOOST_HTTP_PROTO_DOCS
36+
class serializer_service;
3637
class message_view_base;
3738
#endif
3839

@@ -66,6 +67,73 @@ class serializer
6667
using const_buffers_type =
6768
buffers::const_buffer_span;
6869

70+
/** Serializer configuration settings.
71+
*/
72+
struct config
73+
{
74+
/** True if serializer can encode deflate Content-Encoding.
75+
76+
The @ref zlib::deflate_service must already be
77+
installed thusly, or else an exception
78+
is thrown.
79+
*/
80+
bool apply_deflate_encoder = false;
81+
82+
/** True if serializer can encode gzip Content-Encoding.
83+
84+
The @ref zlib::deflate_service must already be
85+
installed thusly, or else an exception
86+
is thrown.
87+
*/
88+
bool apply_gzip_encoder = false;
89+
90+
/** Specifies the zlib compression level 0..9.
91+
92+
A compression level of 1 provides the fastest speed,
93+
while level 9 offers the best compression. Level 0
94+
applies no compression at all.
95+
*/
96+
int zlib_comp_level = 6;
97+
98+
/** Specifies the zlib windows bits 9..15.
99+
100+
The windows bits controls the size of the history
101+
buffer used when compressing data. Larger values
102+
produce better compression at the expense of
103+
greater memory usage.
104+
*/
105+
int zlib_window_bits = 15;
106+
107+
/** Specifies the zlib memory level 1..9.
108+
109+
The memory level controls the amount of memory
110+
used for the internal compression state. Larger
111+
values use more memory, but are faster and
112+
produce smaller output.
113+
*/
114+
int zlib_mem_level = 8;
115+
116+
/** Minimum space for payload buffering.
117+
118+
This cannot be zero.
119+
*/
120+
std::size_t payload_buffer = 8192;
121+
122+
/** Space to reserve for type-erasure.
123+
124+
This space is used for the following
125+
purposes:
126+
127+
@li Storing an instance of the user-provided
128+
@ref source objects.
129+
130+
@li Storing an instance of the user-provided
131+
ConstBufferSequence.
132+
133+
*/
134+
std::size_t max_type_erase = 1024;
135+
};
136+
69137
struct stream;
70138

71139
/** Destructor
@@ -82,19 +150,12 @@ class serializer
82150
/** Constructor
83151
84152
@param ctx The serializer will access services
85-
registered with this context.
153+
registered with this context.
86154
*/
87155
BOOST_HTTP_PROTO_DECL
88156
serializer(
89157
context& ctx);
90158

91-
/** Constructor
92-
*/
93-
BOOST_HTTP_PROTO_DECL
94-
serializer(
95-
context& ctx,
96-
std::size_t buffer_size);
97-
98159
//--------------------------------------------
99160

100161
/** Prepare the serializer for a new stream
@@ -216,6 +277,7 @@ class serializer
216277
consume(std::size_t n);
217278

218279
private:
280+
friend class serializer_service;
219281
class filter;
220282
class const_buf_gen_base;
221283
template<class>
@@ -282,6 +344,8 @@ class serializer
282344
};
283345

284346
context& ctx_;
347+
serializer_service& svc_;
348+
285349
detail::workspace ws_;
286350

287351
const_buf_gen_base* buf_gen_;
@@ -304,6 +368,16 @@ class serializer
304368

305369
//------------------------------------------------
306370

371+
/** Install the serializer service.
372+
*/
373+
BOOST_HTTP_PROTO_DECL
374+
void
375+
install_serializer_service(
376+
context& ctx,
377+
serializer::config const& cfg);
378+
379+
//------------------------------------------------
380+
307381
/** The type used for caller-provided body data during
308382
serialization.
309383

include/boost/http_proto/service/zlib_service.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct stream
3434
unsigned int avail_out; // remaining free space at next_out
3535
unsigned long total_out; // total number of bytes output so far
3636

37-
char* msg; // last error message, NULL if no error
37+
char* msg; // last error message, NULL if no error
3838
void* state; // not visible by applications
3939

4040
alloc_func zalloc; // used to allocate internal state

src/detail/zlib_filter.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//
2+
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3+
// Copyright (c) 2024 Mohammad Nejati
4+
//
5+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7+
//
8+
// Official repository: https://github.com/cppalliance/buffers
9+
//
10+
11+
#include "src/detail/zlib_filter.hpp"
12+
13+
#include <boost/buffers/front.hpp>
14+
#include <boost/buffers/sans_prefix.hpp>
15+
#include <boost/buffers/size.hpp>
16+
17+
namespace boost {
18+
namespace http_proto {
19+
namespace detail {
20+
21+
namespace {
22+
23+
void*
24+
zalloc(
25+
void* opaque,
26+
unsigned items,
27+
unsigned size) noexcept
28+
{
29+
return reinterpret_cast<workspace*>(opaque)
30+
->try_reserve_front(items * size);
31+
}
32+
33+
void
34+
zfree(
35+
void* /* opaque */,
36+
void* /* addr */) noexcept
37+
{
38+
// no-op
39+
}
40+
41+
unsigned int
42+
saturate_cast(std::size_t n) noexcept
43+
{
44+
if(n >= std::numeric_limits<unsigned int>::max())
45+
return std::numeric_limits<unsigned int>::max();
46+
return static_cast<unsigned int>(n);
47+
}
48+
49+
} // namespace
50+
51+
zlib_filter::
52+
zlib_filter(workspace& ws)
53+
{
54+
strm_.zalloc = &zalloc;
55+
strm_.zfree = &zfree;
56+
strm_.opaque = &ws;
57+
}
58+
59+
auto
60+
zlib_filter::
61+
process(
62+
buffers::mutable_buffer_subspan out,
63+
buffers::const_buffer_pair in,
64+
bool more,
65+
bool force_flush) -> results
66+
{
67+
results rv;
68+
auto flush = zlib::no_flush;
69+
for(;;)
70+
{
71+
auto ob = buffers::front(out);
72+
auto ib = buffers::front(in);
73+
74+
if(!more && flush != zlib::finish && in[1].size() == 0)
75+
{
76+
if(buffers::size(out) < min_out_buffer())
77+
{
78+
rv.out_short = true;
79+
return rv;
80+
}
81+
flush = zlib::finish;
82+
}
83+
84+
strm_.next_in = static_cast<unsigned char*>(const_cast<void *>(ib.data()));
85+
strm_.avail_in = saturate_cast(ib.size());
86+
strm_.next_out = static_cast<unsigned char*>(ob.data());
87+
strm_.avail_out = saturate_cast(ob.size());
88+
89+
auto ec = BOOST_HTTP_PROTO_ERR(
90+
do_process(flush));
91+
92+
const std::size_t in_bytes = saturate_cast(ib.size()) - strm_.avail_in;
93+
const std::size_t out_bytes = saturate_cast(ob.size()) - strm_.avail_out;
94+
95+
rv.in_bytes += in_bytes;
96+
rv.out_bytes += out_bytes;
97+
98+
if(ec.failed())
99+
return rv;
100+
101+
if(ec == zlib::error::stream_end)
102+
{
103+
rv.finished = true;
104+
return rv;
105+
}
106+
107+
out = buffers::sans_prefix(out, out_bytes);
108+
in = buffers::sans_prefix(in, in_bytes);
109+
110+
if(buffers::size(out) == 0)
111+
return rv;
112+
113+
if(buffers::size(in) == 0 && strm_.avail_out != 0)
114+
{
115+
if(force_flush && rv.out_bytes == 0)
116+
{
117+
flush = zlib::block;
118+
continue;
119+
}
120+
return rv;
121+
}
122+
}
123+
}
124+
125+
} // detail
126+
} // http_proto
127+
} // boost

0 commit comments

Comments
 (0)