mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
WebSocket writes return the bytes transferred (API Change):
* Stream write operations now return the number of bytes transferred from the caller's input buffers. Actions Required: * Modify websocket write completion handlers to receive the extra std::size_t bytes_transferred parameter.
This commit is contained in:
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,3 +1,16 @@
|
||||
Version 112:
|
||||
|
||||
API Changes:
|
||||
|
||||
* WebSocket writes return the bytes transferred
|
||||
|
||||
Actions Required:
|
||||
|
||||
* Modify websocket write completion handlers to receive
|
||||
the extra std::size_t bytes_transferred parameter.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 111:
|
||||
|
||||
WebSocket:
|
||||
|
@ -310,12 +310,17 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_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);
|
||||
|
||||
// Happens when the timer closes the socket
|
||||
if(ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
@ -334,12 +339,17 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_session::on_write,
|
||||
derived().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);
|
||||
|
||||
// Happens when the timer closes the socket
|
||||
if(ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
|
@ -301,12 +301,17 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_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);
|
||||
|
||||
// Happens when the timer closes the socket
|
||||
if(ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
@ -325,12 +330,17 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&websocket_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);
|
||||
|
||||
// Happens when the timer closes the socket
|
||||
if(ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
|
@ -137,12 +137,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");
|
||||
|
||||
@ -152,12 +157,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");
|
||||
|
||||
|
@ -117,12 +117,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");
|
||||
|
||||
@ -132,12 +137,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");
|
||||
|
||||
|
@ -106,12 +106,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 indicates that the session was closed
|
||||
if(ec == websocket::error::closed)
|
||||
return;
|
||||
@ -126,12 +131,17 @@ public:
|
||||
strand_.wrap(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");
|
||||
|
||||
|
@ -85,12 +85,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 indicates that the session was closed
|
||||
if(ec == websocket::error::closed)
|
||||
return;
|
||||
@ -105,12 +110,17 @@ public:
|
||||
strand_.wrap(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");
|
||||
|
||||
|
@ -187,12 +187,17 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&async_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 indicates that the async_session was closed
|
||||
if(ec == websocket::error::closed)
|
||||
return;
|
||||
@ -207,12 +212,17 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&async_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");
|
||||
|
||||
|
@ -67,13 +67,17 @@ 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
|
||||
@ -82,7 +86,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
if(ec)
|
||||
return fail(ec, "handshake");
|
||||
|
||||
@ -91,7 +96,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
if(ec)
|
||||
return fail(ec, "accept");
|
||||
|
||||
@ -103,7 +109,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec == websocket::error::closed)
|
||||
{
|
||||
// This indicates that the session was closed
|
||||
@ -119,7 +126,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec)
|
||||
return fail(ec, "write");
|
||||
|
||||
|
@ -61,13 +61,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)
|
||||
{
|
||||
// Accept the websocket handshake
|
||||
@ -75,7 +78,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
0)));
|
||||
if(ec)
|
||||
return fail(ec, "accept");
|
||||
|
||||
@ -87,7 +91,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec == websocket::error::closed)
|
||||
{
|
||||
// This indicates that the session was closed
|
||||
@ -103,7 +108,8 @@ public:
|
||||
strand_.wrap(std::bind(
|
||||
&session::loop,
|
||||
shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)));
|
||||
if(ec)
|
||||
return fail(ec, "write");
|
||||
|
||||
|
@ -367,6 +367,7 @@ deflate(
|
||||
boost::asio::mutable_buffer& out,
|
||||
consuming_buffers<ConstBufferSequence>& cb,
|
||||
bool fin,
|
||||
std::size_t& total_in,
|
||||
error_code& ec)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
@ -401,6 +402,7 @@ deflate(
|
||||
}
|
||||
BOOST_ASSERT(zs.avail_in == 0);
|
||||
}
|
||||
total_in = zs.total_in;
|
||||
cb.consume(zs.total_in);
|
||||
if(zs.avail_out > 0 && fin)
|
||||
{
|
||||
|
@ -44,7 +44,9 @@ class stream<NextLayer>::write_some_op
|
||||
consuming_buffers<Buffers> cb_;
|
||||
detail::frame_header fh_;
|
||||
detail::prepared_key key_;
|
||||
std::size_t bytes_transferred_ = 0;
|
||||
std::size_t remain_;
|
||||
std::size_t in_;
|
||||
token tok_;
|
||||
int how_;
|
||||
bool fin_;
|
||||
@ -248,6 +250,7 @@ operator()(
|
||||
std::move(*this));
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
bytes_transferred_ += clamp(fh_.len);
|
||||
goto upcall;
|
||||
}
|
||||
|
||||
@ -257,8 +260,9 @@ operator()(
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
fh_.len = clamp(remain_, ws_.wr_buf_size_);
|
||||
remain_ -= clamp(fh_.len);
|
||||
n = clamp(remain_, ws_.wr_buf_size_);
|
||||
fh_.len = n;
|
||||
remain_ -= n;
|
||||
fh_.fin = fin_ ? remain_ == 0 : false;
|
||||
ws_.wr_fb_.reset();
|
||||
detail::write<flat_static_buffer_base>(
|
||||
@ -273,10 +277,11 @@ operator()(
|
||||
std::move(*this));
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
n = clamp(fh_.len); // because yield
|
||||
bytes_transferred_ += n;
|
||||
if(remain_ == 0)
|
||||
break;
|
||||
cb_.consume(
|
||||
bytes_transferred - ws_.wr_fb_.size());
|
||||
cb_.consume(n);
|
||||
fh_.op = detail::opcode::cont;
|
||||
// Allow outgoing control frames to
|
||||
// be sent in between message frames
|
||||
@ -320,6 +325,8 @@ operator()(
|
||||
std::move(*this));
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
bytes_transferred_ +=
|
||||
bytes_transferred - ws_.wr_fb_.size();
|
||||
while(remain_ > 0)
|
||||
{
|
||||
cb_.consume(ws_.wr_buf_size_);
|
||||
@ -336,6 +343,7 @@ operator()(
|
||||
std::move(*this));
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
bytes_transferred_ += bytes_transferred;
|
||||
}
|
||||
goto upcall;
|
||||
}
|
||||
@ -368,10 +376,11 @@ operator()(
|
||||
std::move(*this));
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
n = bytes_transferred - ws_.wr_fb_.size();
|
||||
bytes_transferred_ += n;
|
||||
if(remain_ == 0)
|
||||
break;
|
||||
cb_.consume(
|
||||
bytes_transferred - ws_.wr_fb_.size());
|
||||
cb_.consume(n);
|
||||
fh_.op = detail::opcode::cont;
|
||||
// Allow outgoing control frames to
|
||||
// be sent in between message frames:
|
||||
@ -396,8 +405,8 @@ operator()(
|
||||
{
|
||||
b = buffer(ws_.wr_buf_.get(),
|
||||
ws_.wr_buf_size_);
|
||||
more_ = detail::deflate(
|
||||
ws_.pmd_->zo, b, cb_, fin_, ec);
|
||||
more_ = detail::deflate(ws_.pmd_->zo,
|
||||
b, cb_, fin_, in_, ec);
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
n = buffer_size(b);
|
||||
@ -430,6 +439,7 @@ operator()(
|
||||
mutable_buffers_1{b}), std::move(*this));
|
||||
if(! ws_.check_ok(ec))
|
||||
goto upcall;
|
||||
bytes_transferred_ += in_;
|
||||
if(more_)
|
||||
{
|
||||
fh_.op = detail::opcode::cont;
|
||||
@ -469,8 +479,8 @@ operator()(
|
||||
ws_.paused_ping_.maybe_invoke();
|
||||
if(! cont_)
|
||||
return ws_.stream_.get_io_service().post(
|
||||
bind_handler(h_, ec));
|
||||
h_(ec);
|
||||
bind_handler(h_, ec, bytes_transferred_));
|
||||
h_(ec, bytes_transferred_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,7 +488,7 @@ operator()(
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
stream<NextLayer>::
|
||||
write_some(bool fin, ConstBufferSequence const& buffers)
|
||||
{
|
||||
@ -488,14 +498,16 @@ write_some(bool fin, ConstBufferSequence const& buffers)
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
error_code ec;
|
||||
write_some(fin, buffers, ec);
|
||||
auto const bytes_transferred =
|
||||
write_some(fin, buffers, ec);
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
stream<NextLayer>::
|
||||
write_some(bool fin,
|
||||
ConstBufferSequence const& buffers, error_code& ec)
|
||||
@ -509,10 +521,11 @@ write_some(bool fin,
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
using boost::asio::buffer_size;
|
||||
std::size_t bytes_transferred = 0;
|
||||
ec.assign(0, ec.category());
|
||||
// Make sure the stream is open
|
||||
if(! check_open(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
detail::frame_header fh;
|
||||
if(! wr_cont_)
|
||||
{
|
||||
@ -538,9 +551,10 @@ write_some(bool fin,
|
||||
auto b = buffer(
|
||||
wr_buf_.get(), wr_buf_size_);
|
||||
auto const more = detail::deflate(
|
||||
pmd_->zo, b, cb, fin, ec);
|
||||
pmd_->zo, b, cb, fin,
|
||||
bytes_transferred, ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
auto const n = buffer_size(b);
|
||||
if(n == 0)
|
||||
{
|
||||
@ -568,7 +582,7 @@ write_some(bool fin,
|
||||
boost::asio::write(stream_,
|
||||
buffer_cat(fh_buf.data(), b), ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
if(! more)
|
||||
break;
|
||||
fh.op = detail::opcode::cont;
|
||||
@ -595,7 +609,8 @@ write_some(bool fin,
|
||||
boost::asio::write(stream_,
|
||||
buffer_cat(fh_buf.data(), buffers), ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
bytes_transferred += remain;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -617,7 +632,8 @@ write_some(bool fin,
|
||||
buffer_cat(fh_buf.data(),
|
||||
buffer_prefix(n, cb)), ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
bytes_transferred += n;
|
||||
if(remain == 0)
|
||||
break;
|
||||
fh.op = detail::opcode::cont;
|
||||
@ -649,7 +665,8 @@ write_some(bool fin,
|
||||
boost::asio::write(stream_,
|
||||
buffer_cat(fh_buf.data(), b), ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
bytes_transferred += n;
|
||||
}
|
||||
while(remain > 0)
|
||||
{
|
||||
@ -661,7 +678,8 @@ write_some(bool fin,
|
||||
detail::mask_inplace(b, key);
|
||||
boost::asio::write(stream_, b, ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
bytes_transferred += n;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -689,19 +707,21 @@ write_some(bool fin,
|
||||
boost::asio::write(stream_,
|
||||
buffer_cat(fh_buf.data(), b), ec);
|
||||
if(! check_ok(ec))
|
||||
return;
|
||||
return bytes_transferred;
|
||||
bytes_transferred += n;
|
||||
if(remain == 0)
|
||||
break;
|
||||
fh.op = detail::opcode::cont;
|
||||
cb.consume(n);
|
||||
}
|
||||
}
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler, void(error_code)>
|
||||
WriteHandler, void(error_code, std::size_t)>
|
||||
stream<NextLayer>::
|
||||
async_write_some(bool fin,
|
||||
ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||
@ -712,10 +732,11 @@ async_write_some(bool fin,
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
async_completion<WriteHandler,
|
||||
void(error_code)> init{handler};
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
write_some_op<ConstBufferSequence, handler_type<
|
||||
WriteHandler, void(error_code)>>{init.completion_handler,
|
||||
*this, fin, bs}({}, 0, false);
|
||||
WriteHandler, void(error_code, std::size_t)>>{
|
||||
init.completion_handler, *this, fin, bs}(
|
||||
{}, 0, false);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
@ -723,7 +744,7 @@ async_write_some(bool fin,
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
stream<NextLayer>::
|
||||
write(ConstBufferSequence const& buffers)
|
||||
{
|
||||
@ -733,14 +754,15 @@ write(ConstBufferSequence const& buffers)
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
error_code ec;
|
||||
write(buffers, ec);
|
||||
auto const bytes_transferred = write(buffers, ec);
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(system_error{ec});
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
stream<NextLayer>::
|
||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
@ -749,13 +771,13 @@ write(ConstBufferSequence const& buffers, error_code& ec)
|
||||
static_assert(beast::is_const_buffer_sequence<
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
write_some(true, buffers, ec);
|
||||
return write_some(true, buffers, ec);
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
async_return_type<
|
||||
WriteHandler, void(error_code)>
|
||||
WriteHandler, void(error_code, std::size_t)>
|
||||
stream<NextLayer>::
|
||||
async_write(
|
||||
ConstBufferSequence const& bs, WriteHandler&& handler)
|
||||
@ -766,10 +788,11 @@ async_write(
|
||||
ConstBufferSequence>::value,
|
||||
"ConstBufferSequence requirements not met");
|
||||
async_completion<WriteHandler,
|
||||
void(error_code)> init{handler};
|
||||
void(error_code, std::size_t)> init{handler};
|
||||
write_some_op<ConstBufferSequence, handler_type<
|
||||
WriteHandler, void(error_code)>>{init.completion_handler,
|
||||
*this, true, bs}({}, 0, false);
|
||||
WriteHandler, void(error_code, std::size_t)>>{
|
||||
init.completion_handler, *this, true, bs}(
|
||||
{}, 0, false);
|
||||
return init.result.get();
|
||||
}
|
||||
|
||||
|
@ -3157,13 +3157,17 @@ public:
|
||||
the memory locations pointed to by buffers remains valid
|
||||
until the completion handler is called.
|
||||
|
||||
@return The number of bytes written from the buffers.
|
||||
If an error occurred, this will be less than the sum
|
||||
of the buffer sizes.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
|
||||
@note This function always sends an entire message. To
|
||||
send a message in fragments, use @ref write_some.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write(ConstBufferSequence const& buffers);
|
||||
|
||||
/** Write a message to the stream.
|
||||
@ -3192,6 +3196,10 @@ public:
|
||||
the memory locations pointed to by buffers remains valid
|
||||
until the completion handler is called.
|
||||
|
||||
@return The number of bytes written from the buffers.
|
||||
If an error occurred, this will be less than the sum
|
||||
of the buffer sizes.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
@ -3200,7 +3208,7 @@ public:
|
||||
send a message in fragments, use @ref write_some.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write(ConstBufferSequence const& buffers, error_code& ec);
|
||||
|
||||
/** Start an asynchronous operation to write a message to the stream.
|
||||
@ -3239,7 +3247,11 @@ public:
|
||||
function signature of the handler must be:
|
||||
@code
|
||||
void handler(
|
||||
error_code const& ec // Result of operation
|
||||
error_code const& ec, // Result of operation
|
||||
std::size_t bytes_transferred // Number of bytes written from the
|
||||
// buffers. If an error occurred,
|
||||
// this will be less than the sum
|
||||
// of the buffer sizes.
|
||||
);
|
||||
@endcode
|
||||
Regardless of whether the asynchronous operation completes
|
||||
@ -3247,14 +3259,18 @@ public:
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
template<
|
||||
class ConstBufferSequence,
|
||||
class WriteHandler>
|
||||
#if BOOST_BEAST_DOXYGEN
|
||||
void_or_deduced
|
||||
#else
|
||||
async_return_type<
|
||||
WriteHandler, void(error_code)>
|
||||
WriteHandler,
|
||||
void(error_code, std::size_t)>
|
||||
#endif
|
||||
async_write(ConstBufferSequence const& buffers,
|
||||
async_write(
|
||||
ConstBufferSequence const& buffers,
|
||||
WriteHandler&& handler);
|
||||
|
||||
/** Write partial message data on the stream.
|
||||
@ -3277,16 +3293,18 @@ public:
|
||||
the @ref binary option. The actual payload sent may be
|
||||
transformed as per the WebSocket protocol settings.
|
||||
|
||||
@param fin `true` if this is the last frame in the message.
|
||||
@param fin `true` if this is the last part of the message.
|
||||
|
||||
@param buffers The input buffer sequence holding the data to write.
|
||||
|
||||
@return The number of bytes consumed in the input buffers.
|
||||
@return The number of bytes written from the buffers.
|
||||
If an error occurred, this will be less than the sum
|
||||
of the buffer sizes.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write_some(bool fin, ConstBufferSequence const& buffers);
|
||||
|
||||
/** Write partial message data on the stream.
|
||||
@ -3309,16 +3327,18 @@ public:
|
||||
the @ref binary option. The actual payload sent may be
|
||||
transformed as per the WebSocket protocol settings.
|
||||
|
||||
@param fin `true` if this is the last frame in the message.
|
||||
@param fin `true` if this is the last part of the message.
|
||||
|
||||
@param buffers The input buffer sequence holding the data to write.
|
||||
@return The number of bytes written from the buffers.
|
||||
If an error occurred, this will be less than the sum
|
||||
of the buffer sizes.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
|
||||
@return The number of bytes consumed in the input buffers.
|
||||
*/
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write_some(bool fin,
|
||||
ConstBufferSequence const& buffers, error_code& ec);
|
||||
|
||||
@ -3346,8 +3366,7 @@ public:
|
||||
the @ref binary option. The actual payload sent may be
|
||||
transformed as per the WebSocket protocol settings.
|
||||
|
||||
@param fin A bool indicating whether or not the frame is the
|
||||
last frame in the corresponding WebSockets message.
|
||||
@param fin `true` if this is the last part of the message.
|
||||
|
||||
@param buffers A object meeting the requirements of
|
||||
ConstBufferSequence which holds the payload data before any
|
||||
@ -3360,27 +3379,24 @@ public:
|
||||
Copies will be made of the handler as required. The equivalent
|
||||
function signature of the handler must be:
|
||||
@code void handler(
|
||||
error_code const& ec // Result of operation
|
||||
error_code const& ec, // Result of operation
|
||||
std::size_t bytes_transferred // Number of bytes written from the
|
||||
// buffers. If an error occurred,
|
||||
// this will be less than the sum
|
||||
// of the buffer sizes.
|
||||
); @endcode
|
||||
*/
|
||||
template<class ConstBufferSequence, class WriteHandler>
|
||||
#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(bool fin,
|
||||
ConstBufferSequence const& buffers, WriteHandler&& handler);
|
||||
|
||||
private:
|
||||
enum class fail_how
|
||||
{
|
||||
code = 1, // send close code, teardown, finish with error::failed
|
||||
close = 2, // send frame in fb, teardown, finish with error::closed
|
||||
teardown = 3 // teardown, finish with error::failed
|
||||
};
|
||||
|
||||
template<class, class> class accept_op;
|
||||
template<class> class close_op;
|
||||
template<class> class fail_op;
|
||||
|
@ -212,12 +212,13 @@ public:
|
||||
ws.handshake("localhost", "/");
|
||||
std::size_t count = 0;
|
||||
ws.async_write(sbuf("*"),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 1);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
BEAST_EXPECT(count == 0);
|
||||
@ -371,11 +372,12 @@ public:
|
||||
std::size_t count = 0;
|
||||
std::string const s = "Hello, world!";
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == s.size());
|
||||
BEAST_EXPECT(++count == 1);
|
||||
});
|
||||
multi_buffer b;
|
||||
@ -415,11 +417,12 @@ public:
|
||||
multi_buffer b;
|
||||
std::string const s = "Hello, world!";
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == s.size());
|
||||
BEAST_EXPECT(++count == 1);
|
||||
});
|
||||
ws.async_read(b,
|
||||
@ -474,7 +477,7 @@ public:
|
||||
++count;
|
||||
});
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
if(ec != boost::asio::error::operation_aborted)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
@ -519,11 +522,12 @@ public:
|
||||
++count;
|
||||
});
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == s.size());
|
||||
BEAST_EXPECT(++count == 1);
|
||||
});
|
||||
ws.async_ping({},
|
||||
@ -578,7 +582,7 @@ public:
|
||||
++count;
|
||||
});
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
if(ec != boost::asio::error::operation_aborted)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
|
@ -104,12 +104,13 @@ public:
|
||||
ws.handshake("localhost", "/");
|
||||
std::size_t count = 0;
|
||||
ws.async_write(sbuf("Hello, world"),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 12);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
BEAST_EXPECT(count == 0);
|
||||
@ -333,12 +334,13 @@ public:
|
||||
ws.handshake("localhost", "/");
|
||||
std::size_t count = 0;
|
||||
ws.async_write(sbuf("*"),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 1);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ws.async_ping("",
|
||||
|
@ -744,11 +744,12 @@ public:
|
||||
});
|
||||
BEAST_EXPECT(ws.rd_block_);
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == s.size());
|
||||
++count;
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
|
@ -636,29 +636,29 @@ public:
|
||||
|
||||
template<
|
||||
class NextLayer, class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write(stream<NextLayer>& ws,
|
||||
ConstBufferSequence const& buffers) const
|
||||
{
|
||||
ws.write(buffers);
|
||||
return ws.write(buffers);
|
||||
}
|
||||
|
||||
template<
|
||||
class NextLayer, class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write_some(stream<NextLayer>& ws, bool fin,
|
||||
ConstBufferSequence const& buffers) const
|
||||
{
|
||||
ws.write_some(fin, buffers);
|
||||
return ws.write_some(fin, buffers);
|
||||
}
|
||||
|
||||
template<
|
||||
class NextLayer, class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write_raw(stream<NextLayer>& ws,
|
||||
ConstBufferSequence const& buffers) const
|
||||
{
|
||||
boost::asio::write(
|
||||
return boost::asio::write(
|
||||
ws.next_layer(), buffers);
|
||||
}
|
||||
};
|
||||
@ -896,39 +896,45 @@ public:
|
||||
|
||||
template<
|
||||
class NextLayer, class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write(stream<NextLayer>& ws,
|
||||
ConstBufferSequence const& buffers) const
|
||||
{
|
||||
error_code ec;
|
||||
ws.async_write(buffers, yield_[ec]);
|
||||
auto const bytes_transferred =
|
||||
ws.async_write(buffers, yield_[ec]);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
template<
|
||||
class NextLayer, class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write_some(stream<NextLayer>& ws, bool fin,
|
||||
ConstBufferSequence const& buffers) const
|
||||
{
|
||||
error_code ec;
|
||||
ws.async_write_some(fin, buffers, yield_[ec]);
|
||||
auto const bytes_transferred =
|
||||
ws.async_write_some(fin, buffers, yield_[ec]);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
template<
|
||||
class NextLayer, class ConstBufferSequence>
|
||||
void
|
||||
std::size_t
|
||||
write_raw(stream<NextLayer>& ws,
|
||||
ConstBufferSequence const& buffers) const
|
||||
{
|
||||
error_code ec;
|
||||
boost::asio::async_write(
|
||||
ws.next_layer(), buffers, yield_[ec]);
|
||||
auto const bytes_transferred =
|
||||
boost::asio::async_write(
|
||||
ws.next_layer(), buffers, yield_[ec]);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
return bytes_transferred;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -271,12 +271,13 @@ public:
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
BEAST_EXPECT(count == 0);
|
||||
ws.async_write(sbuf("*"),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 1);
|
||||
});
|
||||
BEAST_EXPECT(count == 0);
|
||||
ios.run();
|
||||
@ -303,7 +304,7 @@ public:
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
BEAST_EXPECT(count == 0);
|
||||
ws.async_write(sbuf("*"),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t)
|
||||
{
|
||||
++count;
|
||||
if(ec != boost::asio::error::operation_aborted)
|
||||
@ -344,12 +345,13 @@ public:
|
||||
}
|
||||
BEAST_EXPECT(count == 0);
|
||||
ws.async_write(sbuf("*"),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 1);
|
||||
});
|
||||
BEAST_EXPECT(count == 0);
|
||||
ios.run();
|
||||
@ -369,12 +371,13 @@ public:
|
||||
std::string const s(16384, '*');
|
||||
ws.auto_fragment(false);
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 16384);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ws.async_ping("",
|
||||
@ -402,12 +405,13 @@ public:
|
||||
std::string const s(16384, '*');
|
||||
ws.auto_fragment(true);
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 16384);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ws.async_ping("",
|
||||
@ -435,12 +439,13 @@ public:
|
||||
std::string const s(16384, '*');
|
||||
ws.auto_fragment(false);
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 16384);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ws.async_ping("",
|
||||
@ -467,12 +472,13 @@ public:
|
||||
std::string const s(16384, '*');
|
||||
ws.auto_fragment(true);
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == 16384);
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ws.async_ping("",
|
||||
@ -504,12 +510,13 @@ public:
|
||||
auto const& s = random_string();
|
||||
ws.binary(true);
|
||||
ws.async_write(buffer(s),
|
||||
[&](error_code ec)
|
||||
[&](error_code ec, std::size_t n)
|
||||
{
|
||||
++count;
|
||||
if(ec)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
system_error{ec});
|
||||
BEAST_EXPECT(n == s.size());
|
||||
});
|
||||
BEAST_EXPECT(ws.wr_block_);
|
||||
ws.async_ping("",
|
||||
@ -543,7 +550,7 @@ public:
|
||||
break;
|
||||
ws.async_write_some(false,
|
||||
boost::asio::null_buffers{},
|
||||
[&](error_code)
|
||||
[&](error_code, std::size_t)
|
||||
{
|
||||
fail();
|
||||
});
|
||||
|
@ -226,7 +226,7 @@ void echo(stream<boost::asio::ip::tcp::socket>& ws,
|
||||
multi_buffer& buffer, boost::asio::yield_context yield)
|
||||
{
|
||||
ws.async_read(buffer, yield);
|
||||
std::future<void> fut =
|
||||
std::future<std::size_t> fut =
|
||||
ws.async_write(buffer.data(), boost::asio::use_future);
|
||||
}
|
||||
//]
|
||||
|
Reference in New Issue
Block a user