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:
Vinnie Falco
2017-09-03 06:18:07 -07:00
parent 942bca0cc3
commit c0e5f14702
19 changed files with 287 additions and 129 deletions

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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)
{

View File

@ -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();
}

View File

@ -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;

View File

@ -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(

View File

@ -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("",

View File

@ -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_);

View File

@ -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;
}
};
};

View File

@ -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();
});

View File

@ -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);
}
//]