Skip to content

Commit

Permalink
fix: buffer preparation in serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
ashtum committed Feb 25, 2024
1 parent e1b4aa1 commit fc47880
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 65 deletions.
89 changes: 44 additions & 45 deletions src/serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,59 +138,57 @@ prepare() ->

if(st_ == style::source)
{
if(! is_chunked_)
if(more_)
{
auto rv = src_->read(
tmp0_.prepare(
tmp0_.capacity() -
tmp0_.size()));
tmp0_.commit(rv.bytes);
if(rv.ec.failed())
return rv.ec;
more_ = ! rv.finished;
}
else
{
if((tmp0_.capacity() -
tmp0_.size()) >
chunked_overhead_)
if(! is_chunked_)
{
auto dest = tmp0_.prepare(18);
write_chunk_header(dest, 0);
tmp0_.commit(18);
auto rv = src_->read(
tmp0_.prepare(
tmp0_.capacity() -
2 - // CRLF
5 - // final chunk
tmp0_.size()));
tmp0_.prepare(tmp0_.capacity()));
tmp0_.commit(rv.bytes);
// VFALCO FIXME!
//if(rv.bytes == 0)
//tmp0_.uncommit(18); // undo
if(rv.ec.failed())
return rv.ec;
if(rv.bytes > 0)
{
// rewrite with correct size
write_chunk_header(
dest, rv.bytes);
// terminate chunk
tmp0_.commit(
buffers::buffer_copy(
tmp0_.prepare(2),
buffers::const_buffer(
"\r\n", 2)));
}
if(rv.finished)
more_ = ! rv.finished;
}
else
{
if(tmp0_.capacity() > chunked_overhead_)
{
tmp0_.commit(
buffers::buffer_copy(
tmp0_.prepare(5),
buffers::const_buffer(
"0\r\n\r\n", 5)));
auto dest = tmp0_.prepare(18);
write_chunk_header(dest, 0);
tmp0_.commit(18);
auto rv = src_->read(
tmp0_.prepare(
tmp0_.capacity() -
2 - // CRLF
5));// final chunk
tmp0_.commit(rv.bytes);
// VFALCO FIXME!
//if(rv.bytes == 0)
//tmp0_.uncommit(18); // undo
if(rv.ec.failed())
return rv.ec;
if(rv.bytes > 0)
{
// rewrite with correct size
write_chunk_header(
dest, rv.bytes);
// terminate chunk
tmp0_.commit(
buffers::buffer_copy(
tmp0_.prepare(2),
buffers::const_buffer(
"\r\n", 2)));
}
if(rv.finished)
{
tmp0_.commit(
buffers::buffer_copy(
tmp0_.prepare(5),
buffers::const_buffer(
"0\r\n\r\n", 5)));
}
more_ = ! rv.finished;
}
more_ = ! rv.finished;
}
}

Expand Down Expand Up @@ -474,6 +472,7 @@ start_source(

hp_ = &out_[0];
*hp_ = { m.ph_->cbuf, m.ph_->size };
more_ = true;
}

auto
Expand Down
48 changes: 28 additions & 20 deletions test/unit/serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ struct serializer_test
{
struct test_source : source
{
test_source()
: s_("12345")
test_source(core::string_view s)
: s_(s)
{
}

Expand Down Expand Up @@ -81,11 +81,16 @@ struct serializer_test
{
std::string s;
auto cbs = sr.prepare().value();
s.resize(buffers::buffer_size(cbs));
// we limit buffer consumption to complicate
// the serializer's internal buffer management
auto consumed = std::min(
std::size_t{256},
buffers::buffer_size(cbs));
s.resize(consumed);
buffers::buffer_copy(
buffers::mutable_buffer(
&s[0], s.size()), cbs);
sr.consume(s.size());
&s[0], consumed), cbs);
sr.consume(consumed);
return s;
}

Expand Down Expand Up @@ -118,10 +123,10 @@ struct serializer_test
sr.start(res);
sr.start(res, buffers::const_buffer{});
sr.start(res, buffers::mutable_buffer{});
sr.start(res, test_source{});
sr.start(res, test_source{"12345"});
sr.start(res, make_const(buffers::const_buffer{}));
sr.start(res, make_const(buffers::mutable_buffer{}));
sr.start(res, make_const(test_source{}));
sr.start(res, make_const(test_source{"12345"}));

serializer(65536);
#ifdef BOOST_HTTP_PROTO_HAS_ZLIB
Expand Down Expand Up @@ -197,7 +202,9 @@ struct serializer_test
core::string_view expected)
{
response res(headers);
serializer sr;
// we limit the buffer size of the serializer, requiring
// it to make multiple calls to source::read
serializer sr(1024);
sr.start(res, std::forward<
Source>(src));
std::string s = read(sr);
Expand Down Expand Up @@ -256,30 +263,31 @@ struct serializer_test
check_src(
"HTTP/1.1 200 OK\r\n"
"Server: test\r\n"
"Content-Length: 5\r\n"
"Content-Length: 2048\r\n"
"\r\n",
test_source{},
//--------------------------
test_source{std::string(2048, 'A')},
"HTTP/1.1 200 OK\r\n"
"Server: test\r\n"
"Content-Length: 5\r\n"
"\r\n"
"12345");
"Content-Length: 2048\r\n"
"\r\n" +
std::string(2048, 'A'));

// source chunked
check_src(
"HTTP/1.1 200 OK\r\n"
"Server: test\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n",
test_source{},
//--------------------------
test_source{std::string(1024, 'A')},
"HTTP/1.1 200 OK\r\n"
"Server: test\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n"
"0000000000000005\r\n"
"12345"
"0000000000000367\r\n" +
std::string(0x367, 'A') +
"\r\n"
"0000000000000099\r\n" +
std::string(0x099, 'A') +
"\r\n"
"0\r\n\r\n");
}
Expand All @@ -295,7 +303,7 @@ struct serializer_test
"Expect: 100-continue\r\n"
"Content-Length: 5\r\n"
"\r\n");
sr.start(req, test_source{});
sr.start(req, test_source{"12345"});
std::string s;
system::result<
serializer::const_buffers_type> rv;
Expand Down Expand Up @@ -375,7 +383,7 @@ struct serializer_test
"\r\n";
serializer sr;
response res(sv);
sr.start(res, test_source{});
sr.start(res, test_source{"12345"});
auto s = read(sr);
BOOST_TEST(s ==
"HTTP/1.1 200 OK\r\n"
Expand Down

0 comments on commit fc47880

Please sign in to comment.