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
* HTTP reads and writes return bytes transferred
Actions Required:
* Modify websocket write completion handlers to receive
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:

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
remain valid until the operation has completed. Beast asynchronous
initiation functions use Asio's completion handler model. This call
reads a message asynchronously and report the error code upon
completion:
reads a message asynchronously and reports the error code upon
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]
@ -106,4 +109,9 @@ The asynchronous version could be used instead:
[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]

View File

@ -125,12 +125,17 @@ public:
std::bind(
&session::on_write,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
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)
return fail(ec, "write");
@ -139,12 +144,17 @@ public:
std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
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)
return fail(ec, "read");

View File

@ -104,12 +104,17 @@ public:
std::bind(
&session::on_write,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
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)
return fail(ec, "write");
@ -118,12 +123,17 @@ public:
std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1));
std::placeholders::_1,
std::placeholders::_2));
}
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)
return fail(ec, "read");

View File

@ -297,12 +297,17 @@ public:
strand_.wrap(std::bind(
&worker::on_write,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
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)
{
report_.aggregate(
@ -324,12 +329,17 @@ public:
strand_.wrap(std::bind(
&worker::on_read,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
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)
{
report_.aggregate(

View File

@ -247,7 +247,8 @@ class session : public std::enable_shared_from_this<session>
self_.strand_.wrap(std::bind(
&session::on_write,
self_.shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
};
@ -305,12 +306,17 @@ public:
strand_.wrap(std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
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
if(ec == http::error::end_of_stream)
return do_close();
@ -323,8 +329,12 @@ public:
}
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)
{
// 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(
&session::on_write,
self_.shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
};
@ -283,12 +284,17 @@ public:
strand_.wrap(std::bind(
&session::on_read,
shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
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
if(ec == http::error::end_of_stream)
return do_close();
@ -301,8 +307,12 @@ public:
}
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)
{
// This means we should close the connection, usually because

View File

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

View File

@ -258,7 +258,8 @@ class session
self_.strand_.wrap(std::bind(
&session::on_write,
self_.derived().shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
};
@ -296,12 +297,17 @@ public:
strand_.wrap(std::bind(
&session::on_read,
derived().shared_from_this(),
std::placeholders::_1)));
std::placeholders::_1,
std::placeholders::_2)));
}
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
if(ec == http::error::end_of_stream)
return derived().do_eof();
@ -314,8 +320,12 @@ public:
}
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)
{
// This means we should close the connection, usually because

View File

@ -87,8 +87,10 @@ private:
socket_,
buffer_,
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)
self->process_request();
});
@ -175,7 +177,7 @@ private:
http::async_write(
socket_,
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->deadline_.cancel();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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