HTTP reads and writes return bytes transferred (API Change):

* HTTP read and write operations now return the
  number of bytes transferred to or from the stream.

Actions Required:

* Modify HTTP read and/or write completion handlers to receive
  the extra std::size_t bytes_transferred parameter.
This commit is contained in:
Vinnie Falco
2017-09-03 18:06:09 -07:00
parent cc8246e27e
commit 49d9d47a0b
22 changed files with 460 additions and 230 deletions

View File

@ -6,11 +6,16 @@ API Changes:
* WebSocket writes return the bytes transferred * WebSocket writes return the bytes transferred
* HTTP reads and writes return bytes transferred
Actions Required: Actions Required:
* Modify websocket write completion handlers to receive * Modify websocket write completion handlers to receive
the extra std::size_t bytes_transferred parameter. the extra std::size_t bytes_transferred parameter.
* Modify HTTP read and/or write completion handlers to
receive the extra std::size_t bytes_transferred parameter.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Version 111: Version 111:

View File

@ -72,8 +72,11 @@ Messages may also be read asynchronously. When performing asynchronous
stream read operations the stream, buffer, and message variables must stream read operations the stream, buffer, and message variables must
remain valid until the operation has completed. Beast asynchronous remain valid until the operation has completed. Beast asynchronous
initiation functions use Asio's completion handler model. This call initiation functions use Asio's completion handler model. This call
reads a message asynchronously and report the error code upon reads a message asynchronously and reports the error code upon
completion: completion. The handler is called with the error, set to any that
occurs, and the number of bytes parsed. This number may be used to
measure the relative amount of work performed, or it may be ignored
as this example shows.
[http_snippet_5] [http_snippet_5]
@ -106,4 +109,9 @@ The asynchronous version could be used instead:
[http_snippet_8] [http_snippet_8]
The completion handler is called with the number of bytes written to the
stream, which includes protocol specific data such as the delimiters in
the header and line endings. The number may be used to measure the amount
of data transferred, or it may be ignored as in the example.
[endsect] [endsect]

View File

@ -125,12 +125,17 @@ public:
std::bind( std::bind(
&session::on_write, &session::on_write,
shared_from_this(), shared_from_this(),
std::placeholders::_1)); std::placeholders::_1,
std::placeholders::_2));
} }
void void
on_write(boost::system::error_code ec) on_write(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
return fail(ec, "write"); return fail(ec, "write");
@ -139,12 +144,17 @@ public:
std::bind( std::bind(
&session::on_read, &session::on_read,
shared_from_this(), shared_from_this(),
std::placeholders::_1)); std::placeholders::_1,
std::placeholders::_2));
} }
void void
on_read(boost::system::error_code ec) on_read(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
return fail(ec, "read"); return fail(ec, "read");

View File

@ -104,12 +104,17 @@ public:
std::bind( std::bind(
&session::on_write, &session::on_write,
shared_from_this(), shared_from_this(),
std::placeholders::_1)); std::placeholders::_1,
std::placeholders::_2));
} }
void void
on_write(boost::system::error_code ec) on_write(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
return fail(ec, "write"); return fail(ec, "write");
@ -118,12 +123,17 @@ public:
std::bind( std::bind(
&session::on_read, &session::on_read,
shared_from_this(), shared_from_this(),
std::placeholders::_1)); std::placeholders::_1,
std::placeholders::_2));
} }
void void
on_read(boost::system::error_code ec) on_read(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
return fail(ec, "read"); return fail(ec, "read");

View File

@ -297,12 +297,17 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&worker::on_write, &worker::on_write,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
void void
on_write(boost::system::error_code ec) on_write(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
{ {
report_.aggregate( report_.aggregate(
@ -324,12 +329,17 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&worker::on_read, &worker::on_read,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
void void
on_read(boost::system::error_code ec) on_read(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
{ {
report_.aggregate( report_.aggregate(

View File

@ -247,7 +247,8 @@ class session : public std::enable_shared_from_this<session>
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&session::on_write, &session::on_write,
self_.shared_from_this(), self_.shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
}; };
@ -305,12 +306,17 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::on_read, &session::on_read,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
void void
on_read(boost::system::error_code ec) on_read(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
// This means they closed the connection // This means they closed the connection
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
return do_close(); return do_close();
@ -323,8 +329,12 @@ public:
} }
void void
on_write(boost::system::error_code ec) on_write(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
{ {
// This means we should close the connection, usually because // This means we should close the connection, usually because

View File

@ -243,7 +243,8 @@ class session : public std::enable_shared_from_this<session>
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&session::on_write, &session::on_write,
self_.shared_from_this(), self_.shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
}; };
@ -283,12 +284,17 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::on_read, &session::on_read,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
void void
on_read(boost::system::error_code ec) on_read(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
// This means they closed the connection // This means they closed the connection
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
return do_close(); return do_close();
@ -301,8 +307,12 @@ public:
} }
void void
on_write(boost::system::error_code ec) on_write(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
{ {
// This means we should close the connection, usually because // This means we should close the connection, usually because

View File

@ -172,7 +172,7 @@ private:
socket_, socket_,
buffer_, buffer_,
*parser_, *parser_,
[this](boost::beast::error_code ec) [this](boost::beast::error_code ec, std::size_t)
{ {
if (ec) if (ec)
accept(); accept();
@ -220,7 +220,7 @@ private:
http::async_write( http::async_write(
socket_, socket_,
*string_serializer_, *string_serializer_,
[this](boost::beast::error_code ec) [this](boost::beast::error_code ec, std::size_t)
{ {
socket_.shutdown(tcp::socket::shutdown_send, ec); socket_.shutdown(tcp::socket::shutdown_send, ec);
string_serializer_.reset(); string_serializer_.reset();
@ -276,7 +276,7 @@ private:
http::async_write( http::async_write(
socket_, socket_,
*file_serializer_, *file_serializer_,
[this](boost::beast::error_code ec) [this](boost::beast::error_code ec, std::size_t)
{ {
socket_.shutdown(tcp::socket::shutdown_send, ec); socket_.shutdown(tcp::socket::shutdown_send, ec);
file_serializer_.reset(); file_serializer_.reset();

View File

@ -258,7 +258,8 @@ class session
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&session::on_write, &session::on_write,
self_.derived().shared_from_this(), self_.derived().shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
}; };
@ -296,12 +297,17 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::on_read, &session::on_read,
derived().shared_from_this(), derived().shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
void void
on_read(boost::system::error_code ec) on_read(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
// This means they closed the connection // This means they closed the connection
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
return derived().do_eof(); return derived().do_eof();
@ -314,8 +320,12 @@ public:
} }
void void
on_write(boost::system::error_code ec) on_write(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
{ {
// This means we should close the connection, usually because // This means we should close the connection, usually because

View File

@ -87,8 +87,10 @@ private:
socket_, socket_,
buffer_, buffer_,
request_, request_,
[self](boost::beast::error_code ec) [self](boost::beast::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(!ec) if(!ec)
self->process_request(); self->process_request();
}); });
@ -175,7 +177,7 @@ private:
http::async_write( http::async_write(
socket_, socket_,
response_, response_,
[self](boost::beast::error_code ec) [self](boost::beast::error_code ec, std::size_t)
{ {
self->socket_.shutdown(tcp::socket::shutdown_send, ec); self->socket_.shutdown(tcp::socket::shutdown_send, ec);
self->deadline_.cancel(); self->deadline_.cancel();

View File

@ -250,7 +250,8 @@ class session
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&session::loop, &session::loop,
self_.shared_from_this(), self_.shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
}; };
@ -282,13 +283,16 @@ public:
void void
run() run()
{ {
loop(); loop({}, 0);
} }
#include <boost/asio/yield.hpp> #include <boost/asio/yield.hpp>
void void
loop(boost::system::error_code ec = {}) loop(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
reenter(*this) reenter(*this)
{ {
// Perform the SSL handshake // Perform the SSL handshake
@ -297,7 +301,8 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::loop, &session::loop,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
0)));
if(ec) if(ec)
return fail(ec, "handshake"); return fail(ec, "handshake");
@ -308,7 +313,8 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::loop, &session::loop,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
{ {
// The remote host closed the connection // The remote host closed the connection
@ -337,7 +343,8 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::loop, &session::loop,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
0)));
if(ec) if(ec)
return fail(ec, "shutdown"); return fail(ec, "shutdown");

View File

@ -247,7 +247,8 @@ class session
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&session::loop, &session::loop,
self_.shared_from_this(), self_.shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
} }
}; };
@ -276,13 +277,16 @@ public:
void void
run() run()
{ {
loop(); loop({}, 0);
} }
#include <boost/asio/yield.hpp> #include <boost/asio/yield.hpp>
void void
loop(boost::system::error_code ec = {}) loop(
boost::system::error_code ec,
std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
reenter(*this) reenter(*this)
{ {
for(;;) for(;;)
@ -292,7 +296,8 @@ public:
strand_.wrap(std::bind( strand_.wrap(std::bind(
&session::loop, &session::loop,
shared_from_this(), shared_from_this(),
std::placeholders::_1))); std::placeholders::_1,
std::placeholders::_2)));
if(ec == http::error::end_of_stream) if(ec == http::error::end_of_stream)
{ {
// The remote host closed the connection // The remote host closed the connection

View File

@ -58,7 +58,7 @@ struct basic_file_body<file_win32>
template< template<
class Protocol, bool isRequest, class Fields> class Protocol, bool isRequest, class Fields>
friend friend
void std::size_t
write_some( write_some(
boost::asio::basic_stream_socket<Protocol>& sock, boost::asio::basic_stream_socket<Protocol>& sock,
serializer<isRequest, serializer<isRequest,
@ -107,7 +107,7 @@ struct basic_file_body<file_win32>
template< template<
class Protocol, bool isRequest, class Fields> class Protocol, bool isRequest, class Fields>
friend friend
void std::size_t
write_some( write_some(
boost::asio::basic_stream_socket<Protocol>& sock, boost::asio::basic_stream_socket<Protocol>& sock,
serializer<isRequest, serializer<isRequest,
@ -340,8 +340,9 @@ class write_some_win32_op
boost::asio::basic_stream_socket<Protocol>& sock_; boost::asio::basic_stream_socket<Protocol>& sock_;
serializer<isRequest, serializer<isRequest,
basic_file_body<file_win32>, Fields>& sr_; basic_file_body<file_win32>, Fields>& sr_;
bool header_ = false; std::size_t bytes_transferred_ = 0;
Handler h_; Handler h_;
bool header_ = false;
public: public:
write_some_win32_op(write_some_win32_op&&) = default; write_some_win32_op(write_some_win32_op&&) = default;
@ -363,7 +364,8 @@ public:
operator()(); operator()();
void void
operator()(error_code ec, operator()(
error_code ec,
std::size_t bytes_transferred = 0); std::size_t bytes_transferred = 0);
friend friend
@ -445,7 +447,8 @@ operator()()
if(! bSuccess && dwError != if(! bSuccess && dwError !=
boost::detail::winapi::ERROR_IO_PENDING_) boost::detail::winapi::ERROR_IO_PENDING_)
{ {
// completed immediately // VFALCO This needs review, is 0 the right number?
// completed immediately (with error?)
overlapped.complete(error_code{static_cast<int>( overlapped.complete(error_code{static_cast<int>(
boost::detail::winapi::GetLastError()), boost::detail::winapi::GetLastError()),
system_category()}, 0); system_category()}, 0);
@ -460,8 +463,10 @@ template<
void void
write_some_win32_op< write_some_win32_op<
Protocol, Handler, isRequest, Fields>:: Protocol, Handler, isRequest, Fields>::
operator()(error_code ec, std::size_t bytes_transferred) operator()(
error_code ec, std::size_t bytes_transferred)
{ {
bytes_transferred_ += bytes_transferred;
if(! ec) if(! ec)
{ {
if(header_) if(header_)
@ -481,7 +486,7 @@ operator()(error_code ec, std::size_t bytes_transferred)
ec = error::end_of_stream; ec = error::end_of_stream;
} }
} }
h_(ec); h_(ec, bytes_transferred_);
} }
#endif #endif
@ -491,7 +496,7 @@ operator()(error_code ec, std::size_t bytes_transferred)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class Protocol, bool isRequest, class Fields> template<class Protocol, bool isRequest, class Fields>
void std::size_t
write_some( write_some(
boost::asio::basic_stream_socket<Protocol>& sock, boost::asio::basic_stream_socket<Protocol>& sock,
serializer<isRequest, serializer<isRequest,
@ -501,22 +506,24 @@ write_some(
if(! sr.is_header_done()) if(! sr.is_header_done())
{ {
sr.split(true); sr.split(true);
detail::write_some(sock, sr, ec); auto const bytes_transferred =
detail::write_some(sock, sr, ec);
if(ec) if(ec)
return; return bytes_transferred;
return; return bytes_transferred;
} }
if(sr.chunked()) if(sr.chunked())
{ {
detail::write_some(sock, sr, ec); auto const bytes_transferred =
detail::write_some(sock, sr, ec);
if(ec) if(ec)
return; return bytes_transferred;
return; return bytes_transferred;
} }
auto& r = sr.reader_impl(); auto& r = sr.reader_impl();
r.body_.file_.seek(r.pos_, ec); r.body_.file_.seek(r.pos_, ec);
if(ec) if(ec)
return; return 0;
boost::detail::winapi::DWORD_ const nNumberOfBytesToWrite = boost::detail::winapi::DWORD_ const nNumberOfBytesToWrite =
std::min<boost::detail::winapi::DWORD_>( std::min<boost::detail::winapi::DWORD_>(
beast::detail::clamp(std::min<std::uint64_t>( beast::detail::clamp(std::min<std::uint64_t>(
@ -535,7 +542,7 @@ write_some(
ec.assign(static_cast<int>( ec.assign(static_cast<int>(
boost::detail::winapi::GetLastError()), boost::detail::winapi::GetLastError()),
system_category()); system_category());
return; return 0;
} }
r.pos_ += nNumberOfBytesToWrite; r.pos_ += nNumberOfBytesToWrite;
BOOST_ASSERT(r.pos_ <= r.body_.last_); BOOST_ASSERT(r.pos_ <= r.body_.last_);
@ -551,6 +558,7 @@ write_some(
if(! sr.keep_alive()) if(! sr.keep_alive())
ec = error::end_of_stream; ec = error::end_of_stream;
} }
return nNumberOfBytesToWrite;
} }
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR #if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
@ -559,7 +567,9 @@ template<
class Protocol, class Protocol,
bool isRequest, class Fields, bool isRequest, class Fields,
class WriteHandler> class WriteHandler>
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
async_write_some( async_write_some(
boost::asio::basic_stream_socket<Protocol>& sock, boost::asio::basic_stream_socket<Protocol>& sock,
serializer<isRequest, serializer<isRequest,
@ -568,8 +578,11 @@ async_write_some(
{ {
async_completion<WriteHandler, async_completion<WriteHandler,
void(error_code)> init{handler}; void(error_code)> init{handler};
detail::write_some_win32_op<Protocol, handler_type< detail::write_some_win32_op<
WriteHandler, void(error_code)>, isRequest, Fields>{ Protocol,
handler_type<WriteHandler,
void(error_code, std::size_t)>,
isRequest, Fields>{
init.completion_handler, sock, sr}(); init.completion_handler, sock, sr}();
return init.result.get(); return init.result.get();
} }

View File

@ -44,7 +44,7 @@ class read_some_op
basic_parser<isRequest, Derived>& p_; basic_parser<isRequest, Derived>& p_;
boost::optional<typename boost::optional<typename
DynamicBuffer::mutable_buffers_type> mb_; DynamicBuffer::mutable_buffers_type> mb_;
std::size_t used_ = 0; std::size_t bytes_transferred_ = 0;
Handler h_; Handler h_;
public: public:
@ -62,7 +62,9 @@ public:
} }
void void
operator()(error_code ec, std::size_t bytes_transferred); operator()(
error_code ec = {},
std::size_t bytes_transferred = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -106,7 +108,9 @@ template<class Stream, class DynamicBuffer,
void void
read_some_op<Stream, DynamicBuffer, read_some_op<Stream, DynamicBuffer,
isRequest, Derived, Handler>:: isRequest, Derived, Handler>::
operator()(error_code ec, std::size_t bytes_transferred) operator()(
error_code ec,
std::size_t bytes_transferred)
{ {
switch(state_) switch(state_)
{ {
@ -142,7 +146,7 @@ operator()(error_code ec, std::size_t bytes_transferred)
do_parse: do_parse:
{ {
auto const used = p_.put(b_.data(), ec); auto const used = p_.put(b_.data(), ec);
used_ += used; bytes_transferred_ += used;
b_.consume(used); b_.consume(used);
if(! ec || ec != http::error::need_more) if(! ec || ec != http::error::need_more)
goto do_upcall; goto do_upcall;
@ -173,7 +177,7 @@ operator()(error_code ec, std::size_t bytes_transferred)
break; break;
} }
upcall: upcall:
h_(ec, used_); h_(ec, bytes_transferred_);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -209,6 +213,7 @@ class read_op
Stream& s_; Stream& s_;
DynamicBuffer& b_; DynamicBuffer& b_;
basic_parser<isRequest, Derived>& p_; basic_parser<isRequest, Derived>& p_;
std::size_t bytes_transferred_ = 0;
Handler h_; Handler h_;
public: public:
@ -228,7 +233,8 @@ public:
void void
operator()( operator()(
error_code ec, std::size_t bytes_used = 0); error_code ec = {},
std::size_t bytes_transferred = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -273,7 +279,9 @@ template<class Stream, class DynamicBuffer,
void void
read_op<Stream, DynamicBuffer, read_op<Stream, DynamicBuffer,
isRequest, Derived, Condition, Handler>:: isRequest, Derived, Condition, Handler>::
operator()(error_code ec, std::size_t) operator()(
error_code ec,
std::size_t bytes_transferred)
{ {
switch(state_) switch(state_)
{ {
@ -297,13 +305,14 @@ operator()(error_code ec, std::size_t)
case 3: case 3:
if(ec) if(ec)
goto upcall; goto upcall;
bytes_transferred_ += bytes_transferred;
if(Condition{}(p_)) if(Condition{}(p_))
goto upcall; goto upcall;
state_ = 3; state_ = 3;
goto do_read; goto do_read;
} }
upcall: upcall:
h_(ec); h_(ec, bytes_transferred_);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -326,6 +335,7 @@ class read_msg_op
DynamicBuffer& b; DynamicBuffer& b;
message_type& m; message_type& m;
parser_type p; parser_type p;
std::size_t bytes_transferred = 0;
data(Handler&, Stream& s_, data(Handler&, Stream& s_,
DynamicBuffer& b_, message_type& m_) DynamicBuffer& b_, message_type& m_)
@ -353,7 +363,8 @@ public:
void void
operator()( operator()(
error_code ec, std::size_t bytes_used = 0); error_code ec = {},
std::size_t bytes_transferred = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -398,7 +409,9 @@ template<class Stream, class DynamicBuffer,
void void
read_msg_op<Stream, DynamicBuffer, read_msg_op<Stream, DynamicBuffer,
isRequest, Body, Allocator, Handler>:: isRequest, Body, Allocator, Handler>::
operator()(error_code ec, std::size_t) operator()(
error_code ec,
std::size_t bytes_transferred)
{ {
auto& d = *d_; auto& d = *d_;
switch(d.state) switch(d.state)
@ -414,6 +427,8 @@ operator()(error_code ec, std::size_t)
case 2: case 2:
if(ec) if(ec)
goto upcall; goto upcall;
d.bytes_transferred +=
bytes_transferred;
if(d.p.is_done()) if(d.p.is_done())
{ {
d.m = d.p.release(); d.m = d.p.release();
@ -423,7 +438,8 @@ operator()(error_code ec, std::size_t)
goto do_read; goto do_read;
} }
upcall: upcall:
d_.invoke(ec); bytes_transferred = d.bytes_transferred;
d_.invoke(ec, bytes_transferred);
} }
} // detail } // detail
@ -446,11 +462,11 @@ read_some(
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
BOOST_ASSERT(! parser.is_done()); BOOST_ASSERT(! parser.is_done());
error_code ec; error_code ec;
auto const bytes_used = read_some( auto const bytes_transferred =
stream, buffer, parser, ec); read_some(stream, buffer, parser, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_used; return bytes_transferred;
} }
template< template<
@ -469,16 +485,16 @@ read_some(
static_assert(is_dynamic_buffer<DynamicBuffer>::value, static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
BOOST_ASSERT(! parser.is_done()); BOOST_ASSERT(! parser.is_done());
std::size_t bytes_used = 0; std::size_t bytes_transferred = 0;
if(buffer.size() == 0) if(buffer.size() == 0)
goto do_read; goto do_read;
for(;;) for(;;)
{ {
// invoke parser // invoke parser
{ {
auto const used = parser.put(buffer.data(), ec); auto const n = parser.put(buffer.data(), ec);
bytes_used += used; bytes_transferred += n;
buffer.consume(used); buffer.consume(n);
if(! ec) if(! ec)
break; break;
if(ec != http::error::need_more) if(ec != http::error::need_more)
@ -495,13 +511,12 @@ read_some(
catch(std::length_error const&) catch(std::length_error const&)
{ {
ec = error::buffer_overflow; ec = error::buffer_overflow;
return bytes_used; return bytes_transferred;
} }
auto const bytes_transferred = auto const n = stream.read_some(*b, ec);
stream.read_some(*b, ec);
if(ec == boost::asio::error::eof) if(ec == boost::asio::error::eof)
{ {
BOOST_ASSERT(bytes_transferred == 0); BOOST_ASSERT(n == 0);
if(parser.got_some()) if(parser.got_some())
{ {
// caller sees EOF on next read // caller sees EOF on next read
@ -516,9 +531,9 @@ read_some(
} }
if(ec) if(ec)
break; break;
buffer.commit(bytes_transferred); buffer.commit(n);
} }
return bytes_used; return bytes_transferred;
} }
template< template<
@ -543,8 +558,7 @@ async_read_some(
detail::read_some_op<AsyncReadStream, detail::read_some_op<AsyncReadStream,
DynamicBuffer, isRequest, Derived, handler_type< DynamicBuffer, isRequest, Derived, handler_type<
ReadHandler, void(error_code, std::size_t)>>{ ReadHandler, void(error_code, std::size_t)>>{
init.completion_handler, stream, buffer, parser}( init.completion_handler, stream, buffer, parser}();
error_code{}, 0);
return init.result.get(); return init.result.get();
} }
@ -554,7 +568,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_header( read_header(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -565,16 +579,18 @@ read_header(
static_assert(is_dynamic_buffer<DynamicBuffer>::value, static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
error_code ec; error_code ec;
read_header(stream, buffer, parser, ec); auto const bytes_transferred =
read_header(stream, buffer, parser, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_header( read_header(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -589,15 +605,18 @@ read_header(
if(parser.is_header_done()) if(parser.is_header_done())
{ {
ec.assign(0, ec.category()); ec.assign(0, ec.category());
return; return 0;
} }
std::size_t bytes_transferred = 0;
do do
{ {
read_some(stream, buffer, parser, ec); bytes_transferred += read_some(
stream, buffer, parser, ec);
if(ec) if(ec)
return; return bytes_transferred;
} }
while(! parser.is_header_done()); while(! parser.is_header_done());
return bytes_transferred;
} }
template< template<
@ -605,7 +624,9 @@ template<
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived, bool isRequest, class Derived,
class ReadHandler> class ReadHandler>
async_return_type<ReadHandler, void(error_code)> async_return_type<
ReadHandler,
void(error_code, std::size_t)>
async_read_header( async_read_header(
AsyncReadStream& stream, AsyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -621,9 +642,8 @@ async_read_header(
void(error_code)> init{handler}; void(error_code)> init{handler};
detail::read_op<AsyncReadStream, DynamicBuffer, detail::read_op<AsyncReadStream, DynamicBuffer,
isRequest, Derived, detail::parser_is_header_done, isRequest, Derived, detail::parser_is_header_done,
handler_type<ReadHandler, void(error_code)>>{ handler_type<ReadHandler, void(error_code, std::size_t)>>{
init.completion_handler, stream, buffer, parser}( init.completion_handler, stream, buffer, parser}();
error_code{});
return init.result.get(); return init.result.get();
} }
@ -633,7 +653,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -644,16 +664,18 @@ read(
static_assert(is_dynamic_buffer<DynamicBuffer>::value, static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
error_code ec; error_code ec;
read(stream, buffer, parser, ec); auto const bytes_transferred =
read(stream, buffer, parser, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -668,15 +690,18 @@ read(
if(parser.is_done()) if(parser.is_done())
{ {
ec.assign(0, ec.category()); ec.assign(0, ec.category());
return; return 0;
} }
std::size_t bytes_transferred = 0;
do do
{ {
read_some(stream, buffer, parser, ec); bytes_transferred += read_some(
stream, buffer, parser, ec);
if(ec) if(ec)
return; return bytes_transferred;
} }
while(! parser.is_done()); while(! parser.is_done());
return bytes_transferred;
} }
template< template<
@ -684,7 +709,9 @@ template<
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived, bool isRequest, class Derived,
class ReadHandler> class ReadHandler>
async_return_type<ReadHandler, void(error_code)> async_return_type<
ReadHandler,
void(error_code, std::size_t)>
async_read( async_read(
AsyncReadStream& stream, AsyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -696,13 +723,13 @@ async_read(
static_assert(is_dynamic_buffer<DynamicBuffer>::value, static_assert(is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
parser.eager(true); parser.eager(true);
async_completion<ReadHandler, async_completion<
void(error_code)> init{handler}; ReadHandler,
void(error_code, std::size_t)> init{handler};
detail::read_op<AsyncReadStream, DynamicBuffer, detail::read_op<AsyncReadStream, DynamicBuffer,
isRequest, Derived, detail::parser_is_done, isRequest, Derived, detail::parser_is_done,
handler_type<ReadHandler, void(error_code)>>{ handler_type<ReadHandler, void(error_code, std::size_t)>>{
init.completion_handler, stream, buffer, parser}( init.completion_handler, stream, buffer, parser}();
error_code{});
return init.result.get(); return init.result.get();
} }
@ -712,7 +739,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Body, class Allocator> bool isRequest, class Body, class Allocator>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -727,16 +754,18 @@ read(
static_assert(is_body_writer<Body>::value, static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met"); "BodyWriter requirements not met");
error_code ec; error_code ec;
read(stream, buffer, msg, ec); auto const bytes_transferred =
read(stream, buffer, msg, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Body, class Allocator> bool isRequest, class Body, class Allocator>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -753,10 +782,12 @@ read(
"BodyWriter requirements not met"); "BodyWriter requirements not met");
parser<isRequest, Body, Allocator> p{std::move(msg)}; parser<isRequest, Body, Allocator> p{std::move(msg)};
p.eager(true); p.eager(true);
read(stream, buffer, p.base(), ec); auto const bytes_transferred =
read(stream, buffer, p.base(), ec);
if(ec) if(ec)
return; return bytes_transferred;
msg = p.release(); msg = p.release();
return bytes_transferred;
} }
template< template<
@ -764,7 +795,9 @@ template<
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Body, class Allocator, bool isRequest, class Body, class Allocator,
class ReadHandler> class ReadHandler>
async_return_type<ReadHandler, void(error_code)> async_return_type<
ReadHandler,
void(error_code, std::size_t)>
async_read( async_read(
AsyncReadStream& stream, AsyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -779,13 +812,16 @@ async_read(
"Body requirements not met"); "Body requirements not met");
static_assert(is_body_writer<Body>::value, static_assert(is_body_writer<Body>::value,
"BodyWriter requirements not met"); "BodyWriter requirements not met");
async_completion<ReadHandler, async_completion<
void(error_code)> init{handler}; ReadHandler,
detail::read_msg_op<AsyncReadStream, DynamicBuffer, void(error_code, std::size_t)> init{handler};
isRequest, Body, Allocator, handler_type< detail::read_msg_op<
ReadHandler, void(error_code)>>{ AsyncReadStream,
init.completion_handler, stream, buffer, msg}( DynamicBuffer,
error_code{}); isRequest, Body, Allocator,
handler_type<ReadHandler,
void(error_code, std::size_t)>>{
init.completion_handler, stream, buffer, msg}();
return init.result.get(); return init.result.get();
} }

View File

@ -81,7 +81,8 @@ public:
operator()(); operator()();
void void
operator()(error_code ec, operator()(
error_code ec,
std::size_t bytes_transferred); std::size_t bytes_transferred);
friend friend
@ -167,7 +168,7 @@ operator()(
if(! sr_.keep_alive()) if(! sr_.keep_alive())
ec = error::end_of_stream; ec = error::end_of_stream;
} }
h_(ec); h_(ec, bytes_transferred);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -206,6 +207,7 @@ class write_op
int state_ = 0; int state_ = 0;
Stream& s_; Stream& s_;
serializer<isRequest, Body, Fields>& sr_; serializer<isRequest, Body, Fields>& sr_;
std::size_t bytes_transferred_ = 0;
Handler h_; Handler h_;
public: public:
@ -222,7 +224,9 @@ public:
} }
void void
operator()(error_code ec); operator()(
error_code ec = {},
std::size_t bytes_transferred = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -267,7 +271,8 @@ template<
void void
write_op<Stream, Handler, Predicate, write_op<Stream, Handler, Predicate,
isRequest, Body, Fields>:: isRequest, Body, Fields>::
operator()(error_code ec) operator()(
error_code ec, std::size_t bytes_transferred)
{ {
if(ec) if(ec)
goto upcall; goto upcall;
@ -279,7 +284,7 @@ operator()(error_code ec)
{ {
state_ = 1; state_ = 1;
return s_.get_io_service().post( return s_.get_io_service().post(
bind_handler(std::move(*this), ec)); bind_handler(std::move(*this), ec, 0));
} }
state_ = 2; state_ = 2;
return beast::http::async_write_some( return beast::http::async_write_some(
@ -295,6 +300,7 @@ operator()(error_code ec)
case 3: case 3:
{ {
bytes_transferred_ += bytes_transferred;
if(Predicate{}(sr_)) if(Predicate{}(sr_))
goto upcall; goto upcall;
return beast::http::async_write_some( return beast::http::async_write_some(
@ -302,7 +308,7 @@ operator()(error_code ec)
} }
} }
upcall: upcall:
h_(ec); h_(ec, bytes_transferred_);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -341,7 +347,8 @@ public:
operator()(); operator()();
void void
operator()(error_code ec); operator()(
error_code ec, std::size_t bytes_transferred);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -395,9 +402,9 @@ template<class Stream, class Handler,
void void
write_msg_op< write_msg_op<
Stream, Handler, isRequest, Body, Fields>:: Stream, Handler, isRequest, Body, Fields>::
operator()(error_code ec) operator()(error_code ec, std::size_t bytes_transferred)
{ {
d_.invoke(ec); d_.invoke(ec, bytes_transferred);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -454,16 +461,10 @@ public:
} }
}; };
} // detail
//------------------------------------------------------------------------------
namespace detail {
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_some( write_some(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -474,45 +475,53 @@ write_some(
write_some_lambda<SyncWriteStream> f{stream}; write_some_lambda<SyncWriteStream> f{stream};
sr.next(ec, f); sr.next(ec, f);
if(ec) if(ec)
return; return f.bytes_transferred;
if(f.invoked) if(f.invoked)
sr.consume(f.bytes_transferred); sr.consume(f.bytes_transferred);
if(sr.is_done()) if(sr.is_done())
if(! sr.keep_alive()) if(! sr.keep_alive())
ec = error::end_of_stream; ec = error::end_of_stream;
return; return f.bytes_transferred;
} }
if(! sr.keep_alive()) if(! sr.keep_alive())
ec = error::end_of_stream; ec = error::end_of_stream;
else else
ec.assign(0, ec.category()); ec.assign(0, ec.category());
return 0;
} }
template< template<
class AsyncWriteStream, class AsyncWriteStream,
bool isRequest, class Body, class Fields, bool isRequest, class Body, class Fields,
class WriteHandler> class WriteHandler>
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
async_write_some( async_write_some(
AsyncWriteStream& stream, AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
WriteHandler&& handler) WriteHandler&& handler)
{ {
async_completion<WriteHandler, async_completion<
void(error_code)> init{handler}; WriteHandler,
detail::write_some_op<AsyncWriteStream, void(error_code, std::size_t)> init{handler};
handler_type<WriteHandler, void(error_code)>, detail::write_some_op<
isRequest, Body, Fields>{ AsyncWriteStream,
init.completion_handler, stream, sr}(); handler_type<WriteHandler,
void(error_code, std::size_t)>,
isRequest, Body, Fields>{
init.completion_handler, stream, sr}();
return init.result.get(); return init.result.get();
} }
} // detail } // detail
//------------------------------------------------------------------------------
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_some( write_some(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr) serializer<isRequest, Body, Fields>& sr)
@ -524,15 +533,17 @@ write_some(
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
error_code ec; error_code ec;
write_some(stream, sr, ec); auto const bytes_transferred =
write_some(stream, sr, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_some( write_some(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -544,14 +555,16 @@ write_some(
"Body requirements not met"); "Body requirements not met");
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
detail::write_some(stream, sr, ec); return detail::write_some(stream, sr, ec);
} }
template< template<
class AsyncWriteStream, class AsyncWriteStream,
bool isRequest, class Body, class Fields, bool isRequest, class Body, class Fields,
class WriteHandler> class WriteHandler>
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
async_write_some( async_write_some(
AsyncWriteStream& stream, AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -573,7 +586,7 @@ async_write_some(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_header(SyncWriteStream& stream, write_header(SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr) serializer<isRequest, Body, Fields>& sr)
{ {
@ -584,15 +597,17 @@ write_header(SyncWriteStream& stream,
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
error_code ec; error_code ec;
write_header(stream, sr, ec); auto const bytes_transferred =
write_header(stream, sr, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_header( write_header(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -605,14 +620,16 @@ write_header(
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
sr.split(true); sr.split(true);
std::size_t bytes_transferred = 0;
if(! sr.is_header_done()) if(! sr.is_header_done())
{ {
detail::write_lambda<SyncWriteStream> f{stream}; detail::write_lambda<SyncWriteStream> f{stream};
do do
{ {
sr.next(ec, f); sr.next(ec, f);
bytes_transferred += f.bytes_transferred;
if(ec) if(ec)
return; return bytes_transferred;
BOOST_ASSERT(f.invoked); BOOST_ASSERT(f.invoked);
sr.consume(f.bytes_transferred); sr.consume(f.bytes_transferred);
} }
@ -622,13 +639,16 @@ write_header(
{ {
ec.assign(0, ec.category()); ec.assign(0, ec.category());
} }
return bytes_transferred;
} }
template< template<
class AsyncWriteStream, class AsyncWriteStream,
bool isRequest, class Body, class Fields, bool isRequest, class Body, class Fields,
class WriteHandler> class WriteHandler>
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
async_write_header( async_write_header(
AsyncWriteStream& stream, AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -642,14 +662,16 @@ async_write_header(
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
sr.split(true); sr.split(true);
async_completion<WriteHandler, async_completion<
void(error_code)> init{handler}; WriteHandler,
detail::write_op<AsyncWriteStream, handler_type< void(error_code, std::size_t)> init{handler};
WriteHandler, void(error_code)>, detail::write_op<
detail::serializer_is_header_done, AsyncWriteStream,
isRequest, Body, Fields>{ handler_type<WriteHandler,
init.completion_handler, stream, sr}( void(error_code, std::size_t)>,
error_code{}); detail::serializer_is_header_done,
isRequest, Body, Fields>{
init.completion_handler, stream, sr}();
return init.result.get(); return init.result.get();
} }
@ -658,7 +680,7 @@ async_write_header(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr) serializer<isRequest, Body, Fields>& sr)
@ -666,15 +688,17 @@ write(
static_assert(is_sync_write_stream<SyncWriteStream>::value, static_assert(is_sync_write_stream<SyncWriteStream>::value,
"SyncWriteStream requirements not met"); "SyncWriteStream requirements not met");
error_code ec; error_code ec;
write(stream, sr, ec); auto const bytes_transferred =
write(stream, sr, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -682,22 +706,27 @@ write(
{ {
static_assert(is_sync_write_stream<SyncWriteStream>::value, static_assert(is_sync_write_stream<SyncWriteStream>::value,
"SyncWriteStream requirements not met"); "SyncWriteStream requirements not met");
std::size_t bytes_transferred = 0;
sr.split(false); sr.split(false);
for(;;) for(;;)
{ {
write_some(stream, sr, ec); bytes_transferred +=
write_some(stream, sr, ec);
if(ec) if(ec)
return; return bytes_transferred;
if(sr.is_done()) if(sr.is_done())
break; break;
} }
return bytes_transferred;
} }
template< template<
class AsyncWriteStream, class AsyncWriteStream,
bool isRequest, class Body, class Fields, bool isRequest, class Body, class Fields,
class WriteHandler> class WriteHandler>
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
async_write( async_write(
AsyncWriteStream& stream, AsyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -711,12 +740,16 @@ async_write(
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
sr.split(false); sr.split(false);
async_completion<WriteHandler, async_completion<
void(error_code)> init{handler}; WriteHandler,
detail::write_op<AsyncWriteStream, handler_type< void(error_code, std::size_t)> init{handler};
WriteHandler, void(error_code)>, detail::write_op<
detail::serializer_is_done, isRequest, Body, Fields>{ AsyncWriteStream,
init.completion_handler, stream, sr}(error_code{}); handler_type<WriteHandler,
void(error_code, std::size_t)>,
detail::serializer_is_done,
isRequest, Body, Fields>{
init.completion_handler, stream, sr}();
return init.result.get(); return init.result.get();
} }
@ -725,7 +758,7 @@ async_write(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
message<isRequest, Body, Fields> const& msg) message<isRequest, Body, Fields> const& msg)
@ -737,15 +770,17 @@ write(
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
error_code ec; error_code ec;
write(stream, msg, ec); auto const bytes_transferred =
write(stream, msg, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_transferred;
} }
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
message<isRequest, Body, Fields> const& msg, message<isRequest, Body, Fields> const& msg,
@ -758,7 +793,7 @@ write(
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
serializer<isRequest, Body, Fields> sr{msg}; serializer<isRequest, Body, Fields> sr{msg};
write(stream, sr, ec); return write(stream, sr, ec);
} }
template< template<
@ -766,7 +801,8 @@ template<
bool isRequest, class Body, class Fields, bool isRequest, class Body, class Fields,
class WriteHandler> class WriteHandler>
async_return_type< async_return_type<
WriteHandler, void(error_code)> WriteHandler,
void(error_code, std::size_t)>
async_write( async_write(
AsyncWriteStream& stream, AsyncWriteStream& stream,
message<isRequest, Body, Fields>& msg, message<isRequest, Body, Fields>& msg,
@ -779,12 +815,15 @@ async_write(
"Body requirements not met"); "Body requirements not met");
static_assert(is_body_reader<Body>::value, static_assert(is_body_reader<Body>::value,
"BodyReader requirements not met"); "BodyReader requirements not met");
async_completion<WriteHandler, async_completion<
void(error_code)> init{handler}; WriteHandler,
detail::write_msg_op<AsyncWriteStream, handler_type< void(error_code, std::size_t)> init{handler};
WriteHandler, void(error_code)>, isRequest, detail::write_msg_op<
Body, Fields>{init.completion_handler, AsyncWriteStream,
stream, msg}(); handler_type<WriteHandler,
void(error_code, std::size_t)>,
isRequest, Body, Fields>{
init.completion_handler, stream, msg}();
return init.result.get(); return init.result.get();
} }

View File

@ -59,7 +59,7 @@ namespace http {
@param parser The parser to use. @param parser The parser to use.
@return The number of bytes consumed by the parser. @return The number of bytes transferred to the parser.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
*/ */
@ -118,7 +118,7 @@ read_some(
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes consumed by the parser. @return The number of bytes transferred to the parser.
*/ */
template< template<
class SyncReadStream, class SyncReadStream,
@ -179,8 +179,8 @@ read_some(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error, // result of operation error_code const& error, // result of operation
std::size_t bytes_used // the number of bytes consumed by the parser std::size_t bytes_transferred // the number of bytes transferred to the parser
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -249,6 +249,8 @@ async_read_some(
@param parser The parser to use. @param parser The parser to use.
@return The number of bytes transferred to the parser.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
@note The implementation will call @ref basic_parser::eager @note The implementation will call @ref basic_parser::eager
@ -258,7 +260,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_header( read_header(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -304,6 +306,8 @@ read_header(
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes transferred to the parser.
@note The implementation will call @ref basic_parser::eager @note The implementation will call @ref basic_parser::eager
with the value `false` on the parser passed in. with the value `false` on the parser passed in.
*/ */
@ -311,7 +315,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read_header( read_header(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -365,7 +369,8 @@ read_header(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation,
std::size_t bytes_transferred // the number of bytes transferred to the parser
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -384,7 +389,7 @@ template<
void_or_deduced void_or_deduced
#else #else
async_return_type< async_return_type<
ReadHandler, void(error_code)> ReadHandler, void(error_code, std::size_t)>
#endif #endif
async_read_header( async_read_header(
AsyncReadStream& stream, AsyncReadStream& stream,
@ -432,6 +437,8 @@ async_read_header(
@param parser The parser to use. @param parser The parser to use.
@return The number of bytes transferred to the parser.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
@note The implementation will call @ref basic_parser::eager @note The implementation will call @ref basic_parser::eager
@ -441,7 +448,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -487,6 +494,8 @@ read(
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes transferred to the parser.
@note The implementation will call @ref basic_parser::eager @note The implementation will call @ref basic_parser::eager
with the value `true` on the parser passed in. with the value `true` on the parser passed in.
*/ */
@ -494,7 +503,7 @@ template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Derived> bool isRequest, class Derived>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -548,7 +557,8 @@ read(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation,
std::size_t bytes_transferred // the number of bytes transferred to the parser
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -567,7 +577,8 @@ template<
void_or_deduced void_or_deduced
#else #else
async_return_type< async_return_type<
ReadHandler, void(error_code)> ReadHandler,
void(error_code, std::size_t)>
#endif #endif
async_read( async_read(
AsyncReadStream& stream, AsyncReadStream& stream,
@ -617,13 +628,15 @@ async_read(
the behavior is undefined. the behavior is undefined.
The type must be @b MoveAssignable and @b MoveConstructible. The type must be @b MoveAssignable and @b MoveConstructible.
@return The number of bytes transferred to the parser.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
*/ */
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Body, class Allocator> bool isRequest, class Body, class Allocator>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -670,12 +683,14 @@ read(
The type must be @b MoveAssignable and @b MoveConstructible. The type must be @b MoveAssignable and @b MoveConstructible.
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes transferred to the parser.
*/ */
template< template<
class SyncReadStream, class SyncReadStream,
class DynamicBuffer, class DynamicBuffer,
bool isRequest, class Body, class Allocator> bool isRequest, class Body, class Allocator>
void std::size_t
read( read(
SyncReadStream& stream, SyncReadStream& stream,
DynamicBuffer& buffer, DynamicBuffer& buffer,
@ -733,7 +748,8 @@ read(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation,
std::size_t bytes_transferred // the number of bytes transferred to the parser
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -749,7 +765,8 @@ template<
void_or_deduced void_or_deduced
#else #else
async_return_type< async_return_type<
ReadHandler, void(error_code)> ReadHandler,
void(error_code, std::size_t)>
#endif #endif
async_read( async_read(
AsyncReadStream& stream, AsyncReadStream& stream,

View File

@ -58,6 +58,8 @@ namespace http {
@param sr The serializer to use. @param sr The serializer to use.
@return The number of bytes written to the stream.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
@see serializer @see serializer
@ -65,7 +67,7 @@ namespace http {
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_some( write_some(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr); serializer<isRequest, Body, Fields>& sr);
@ -100,12 +102,14 @@ write_some(
@param ec Set to indicate what error occurred, if any. @param ec Set to indicate what error occurred, if any.
@return The number of bytes written to the stream.
@see @ref async_write_some, @ref serializer @see @ref async_write_some, @ref serializer
*/ */
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_some( write_some(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -148,7 +152,8 @@ write_some(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -164,7 +169,9 @@ template<
#if BOOST_BEAST_DOXYGEN #if BOOST_BEAST_DOXYGEN
void_or_deduced void_or_deduced
#else #else
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
#endif #endif
async_write_some( async_write_some(
AsyncWriteStream& stream, AsyncWriteStream& stream,
@ -191,6 +198,8 @@ async_write_some(
@param sr The serializer to use. @param sr The serializer to use.
@return The number of bytes written to the stream.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
@note The implementation will call @ref serializer::split with @note The implementation will call @ref serializer::split with
@ -201,7 +210,7 @@ async_write_some(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_header( write_header(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr); serializer<isRequest, Body, Fields>& sr);
@ -226,6 +235,8 @@ write_header(
@param ec Set to indicate what error occurred, if any. @param ec Set to indicate what error occurred, if any.
@return The number of bytes written to the stream.
@note The implementation will call @ref serializer::split with @note The implementation will call @ref serializer::split with
the value `true` on the serializer passed in. the value `true` on the serializer passed in.
@ -234,7 +245,7 @@ write_header(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write_header( write_header(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -267,7 +278,8 @@ write_header(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -286,7 +298,9 @@ template<
#if BOOST_BEAST_DOXYGEN #if BOOST_BEAST_DOXYGEN
void_or_deduced void_or_deduced
#else #else
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
#endif #endif
async_write_header( async_write_header(
AsyncWriteStream& stream, AsyncWriteStream& stream,
@ -313,6 +327,8 @@ async_write_header(
@param sr The serializer to use. @param sr The serializer to use.
@return The number of bytes written to the stream.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
@see @ref serializer @see @ref serializer
@ -320,7 +336,7 @@ async_write_header(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr); serializer<isRequest, Body, Fields>& sr);
@ -345,12 +361,14 @@ write(
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes written to the stream.
@see @ref serializer @see @ref serializer
*/ */
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
serializer<isRequest, Body, Fields>& sr, serializer<isRequest, Body, Fields>& sr,
@ -383,7 +401,8 @@ write(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -399,7 +418,9 @@ template<
#if BOOST_BEAST_DOXYGEN #if BOOST_BEAST_DOXYGEN
void_or_deduced void_or_deduced
#else #else
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
#endif #endif
async_write( async_write(
AsyncWriteStream& stream, AsyncWriteStream& stream,
@ -428,6 +449,8 @@ async_write(
@param msg The message to write. @param msg The message to write.
@return The number of bytes written to the stream.
@throws system_error Thrown on failure. @throws system_error Thrown on failure.
@see @ref message @see @ref message
@ -435,7 +458,7 @@ async_write(
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
message<isRequest, Body, Fields> const& msg); message<isRequest, Body, Fields> const& msg);
@ -462,12 +485,14 @@ write(
@param ec Set to the error, if any occurred. @param ec Set to the error, if any occurred.
@return The number of bytes written to the stream.
@see @ref message @see @ref message
*/ */
template< template<
class SyncWriteStream, class SyncWriteStream,
bool isRequest, class Body, class Fields> bool isRequest, class Body, class Fields>
void std::size_t
write( write(
SyncWriteStream& stream, SyncWriteStream& stream,
message<isRequest, Body, Fields> const& msg, message<isRequest, Body, Fields> const& msg,
@ -503,7 +528,8 @@ write(
completes. Copies will be made of the handler as required. completes. Copies will be made of the handler as required.
The equivalent function signature of the handler must be: The equivalent function signature of the handler must be:
@code void handler( @code void handler(
error_code const& error // result of operation error_code const& error, // result of operation
std::size_t bytes_transferred // the number of bytes written to the stream
); @endcode ); @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within immediately or not, the handler will not be invoked from within
@ -516,7 +542,9 @@ template<
class AsyncWriteStream, class AsyncWriteStream,
bool isRequest, class Body, class Fields, bool isRequest, class Body, class Fields,
class WriteHandler> class WriteHandler>
async_return_type<WriteHandler, void(error_code)> async_return_type<
WriteHandler,
void(error_code, std::size_t)>
async_write( async_write(
AsyncWriteStream& stream, AsyncWriteStream& stream,
message<isRequest, Body, Fields>& msg, message<isRequest, Body, Fields>& msg,

View File

@ -67,7 +67,9 @@ public:
{ {
} }
void operator()(error_code ec = {}); void operator()(
error_code ec = {},
std::size_t bytes_transferred = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -110,7 +112,9 @@ template<class Handler>
void void
stream<NextLayer>:: stream<NextLayer>::
response_op<Handler>:: response_op<Handler>::
operator()(error_code ec) operator()(
error_code ec,
std::size_t)
{ {
auto& d = *d_; auto& d = *d_;
BOOST_ASIO_CORO_REENTER(*this) BOOST_ASIO_CORO_REENTER(*this)
@ -170,7 +174,9 @@ public:
template<class Buffers> template<class Buffers>
void run(Buffers const& buffers); void run(Buffers const& buffers);
void operator()(error_code ec = {}); void operator()(
error_code ec = {},
std::size_t bytes_used = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -242,7 +248,7 @@ template<class Decorator, class Handler>
void void
stream<NextLayer>:: stream<NextLayer>::
accept_op<Decorator, Handler>:: accept_op<Decorator, Handler>::
operator()(error_code ec) operator()(error_code ec, std::size_t)
{ {
auto& d = *d_; auto& d = *d_;
BOOST_ASIO_CORO_REENTER(*this) BOOST_ASIO_CORO_REENTER(*this)

View File

@ -76,7 +76,9 @@ public:
} }
void void
operator()(error_code ec = {}); operator()(
error_code ec = {},
std::size_t bytes_used = 0);
friend friend
void* asio_handler_allocate( void* asio_handler_allocate(
@ -118,7 +120,7 @@ template<class NextLayer>
template<class Handler> template<class Handler>
void void
stream<NextLayer>::handshake_op<Handler>:: stream<NextLayer>::handshake_op<Handler>::
operator()(error_code ec) operator()(error_code ec, std::size_t)
{ {
auto& d = *d_; auto& d = *d_;
BOOST_ASIO_CORO_REENTER(*this) BOOST_ASIO_CORO_REENTER(*this)

View File

@ -329,7 +329,7 @@ public:
handler() { ++count(); } handler() { ++count(); }
~handler() { --count(); } ~handler() { --count(); }
handler(handler const&) { ++count(); } handler(handler const&) { ++count(); }
void operator()(error_code const&) const {} void operator()(error_code const&, std::size_t) const {}
}; };
void void

View File

@ -614,7 +614,7 @@ public:
handler() { ++count(); } handler() { ++count(); }
~handler() { --count(); } ~handler() { --count(); }
handler(handler const&) { ++count(); } handler(handler const&) { ++count(); }
void operator()(error_code const&) const {} void operator()(error_code const&, std::size_t) const {}
}; };
void void
@ -830,7 +830,7 @@ public:
res.chunked(true); res.chunked(true);
response_serializer<empty_body> sr{res}; response_serializer<empty_body> sr{res};
async_write_header(ts, sr, async_write_header(ts, sr,
[&](const error_code&) [&](error_code const&, std::size_t)
{ {
}); });
ios.run(); ios.run();

View File

@ -83,8 +83,9 @@ void fxx() {
flat_buffer buffer; flat_buffer buffer;
response<string_body> res; response<string_body> res;
async_read(sock, buffer, res, async_read(sock, buffer, res,
[&](error_code ec) [&](error_code ec, std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
std::cerr << ec.message() << std::endl; std::cerr << ec.message() << std::endl;
}); });
@ -124,8 +125,9 @@ void fxx() {
//[http_snippet_8 //[http_snippet_8
async_write(sock, res, async_write(sock, res,
[&](error_code) [&](error_code ec, std::size_t bytes_transferred)
{ {
boost::ignore_unused(bytes_transferred);
if(ec) if(ec)
std::cerr << ec.message() << std::endl; std::cerr << ec.message() << std::endl;
}); });