websocket read returns the number of bytes inserted (API Change):

* read and async_read now return the number of bytes inserted
into the caller's buffer.

Actions Required:

* Change the signature of completion handlers used with
  websocket::stream::async_read to void(error_code, std::size_t)
This commit is contained in:
Vinnie Falco
2017-07-25 08:50:58 -07:00
parent 6e33072832
commit e56d9955de
5 changed files with 69 additions and 52 deletions

View File

@ -16,6 +16,15 @@ Version 86:
* Fix Deferred Body Type Example Documentation * Fix Deferred Body Type Example Documentation
* Add library metadata * Add library metadata
API Changes:
* websocket read returns the number of bytes inserted
Actions Required:
* Change the signature of completion handlers used with
websocket::stream::async_read to void(error_code, std::size_t)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Version 85: Version 85:

View File

@ -804,7 +804,7 @@ operator()(
template<class NextLayer> template<class NextLayer>
template<class DynamicBuffer> template<class DynamicBuffer>
void std::size_t
stream<NextLayer>:: stream<NextLayer>::
read(DynamicBuffer& buffer) read(DynamicBuffer& buffer)
{ {
@ -813,14 +813,15 @@ read(DynamicBuffer& buffer)
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value, static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
error_code ec; error_code ec;
read(buffer, ec); auto const bytes_written = read(buffer, ec);
if(ec) if(ec)
BOOST_THROW_EXCEPTION(system_error{ec}); BOOST_THROW_EXCEPTION(system_error{ec});
return bytes_written;
} }
template<class NextLayer> template<class NextLayer>
template<class DynamicBuffer> template<class DynamicBuffer>
void std::size_t
stream<NextLayer>:: stream<NextLayer>::
read(DynamicBuffer& buffer, error_code& ec) read(DynamicBuffer& buffer, error_code& ec)
{ {
@ -828,18 +829,20 @@ read(DynamicBuffer& buffer, error_code& ec)
"SyncStream requirements not met"); "SyncStream requirements not met");
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value, static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
std::size_t bytes_written = 0;
do do
{ {
read_some(buffer, 0, ec); bytes_written += read_some(buffer, 0, ec);
if(ec) if(ec)
return; return bytes_written;
} }
while(! is_message_done()); while(! is_message_done());
return bytes_written;
} }
template<class NextLayer> template<class NextLayer>
template<class DynamicBuffer, class ReadHandler> template<class DynamicBuffer, class ReadHandler>
async_return_type<ReadHandler, void(error_code)> async_return_type<ReadHandler, void(error_code, std::size_t)>
stream<NextLayer>:: stream<NextLayer>::
async_read(DynamicBuffer& buffer, ReadHandler&& handler) async_read(DynamicBuffer& buffer, ReadHandler&& handler)
{ {
@ -848,19 +851,15 @@ async_read(DynamicBuffer& buffer, ReadHandler&& handler)
static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value, static_assert(beast::is_dynamic_buffer<DynamicBuffer>::value,
"DynamicBuffer requirements not met"); "DynamicBuffer requirements not met");
async_completion< async_completion<
ReadHandler, void(error_code)> init{handler}; ReadHandler, void(error_code, std::size_t)> init{handler};
read_op< read_op<
DynamicBuffer, DynamicBuffer,
beast::detail::bound_handler< handler_type<ReadHandler, void(error_code, std::size_t)> >{
handler_type<ReadHandler, void(error_code)>,
decltype(std::placeholders::_1) &> >{
beast::bind_handler(
init.completion_handler, init.completion_handler,
std::placeholders::_1), *this,
*this, buffer,
buffer, 0,
0, false}();
false}();
return init.result.get(); return init.result.get();
} }

View File

@ -2835,43 +2835,46 @@ public:
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** Read a message from the stream. /** Read a complete message
This function is used to synchronously read a message from This function is used to synchronously read a message from the stream.
the stream. The call blocks until one of the following is true: The call blocks until one of the following is true:
@li A complete message is received. @li A complete message is received.
@li A close frame is received. In this case the error indicated by
the function will be @ref error::closed.
@li An error occurs on the stream. @li An error occurs on the stream.
This call is implemented in terms of one or more calls to the This operation is implemented in terms of one or more calls to the next
stream's `read_some` and `write_some` operations. layer's `read_some` and `write_some` functions.
Upon a success, the input area of the stream buffer will Received message data, if any, is appended to the input area of the buffer.
hold the received message payload bytes (which may be zero The functions @ref got_binary and @ref got_text may be used to query
in length). The functions @ref got_binary and @ref got_text the stream and determine the type of the last received message.
may be used to query the stream and determine the type
of the last received message.
During reads, the implementation handles control frames as While this operation is active, the implementation will read incoming
follows: control frames and handle them automatically as follows:
@li A pong frame is sent when a ping frame is received. @li The @ref control_callback will be invoked for each control frame.
@li The @ref control_callback is invoked when a ping frame @li For each received ping frame, a pong frame will be automatically sent.
or pong frame is received.
@li The WebSocket close procedure is started if a close frame @li If a close frame is received, the WebSocket close procedure is
is received. In this case, the operation will eventually performed. In this case, when the function returns, the error
complete with the error set to @ref error::closed. @ref error::closed will be indicated.
@param buffer A dynamic buffer to hold the message data after @return The number of message payload bytes appended to the buffer.
any masking or decompression has been applied.
@throws system_error Thrown on failure. @param buffer A dynamic buffer to hold the message data after any
masking or decompression has been applied.
@throws system_error Thrown to indicate an error. The corresponding
error code may be retrieved from the exception object for inspection.
*/ */
template<class DynamicBuffer> template<class DynamicBuffer>
void std::size_t
read(DynamicBuffer& buffer); read(DynamicBuffer& buffer);
/** Read a message from the stream. /** Read a message from the stream.
@ -2910,10 +2913,10 @@ public:
@param ec Set to indicate what error occurred, if any. @param ec Set to indicate what error occurred, if any.
*/ */
template<class DynamicBuffer> template<class DynamicBuffer>
void std::size_t
read(DynamicBuffer& buffer, error_code& ec); read(DynamicBuffer& buffer, error_code& ec);
/** Start an asynchronous operation to read a message from the stream. /** Read a complete message asynchronously
This function is used to asynchronously read a message from This function is used to asynchronously read a message from
the stream. The function call always returns immediately. The the stream. The function call always returns immediately. The
@ -2963,7 +2966,8 @@ public:
function signature of the handler must be: function signature of the handler must be:
@code @code
void handler( void handler(
error_code const& ec; // Result of operation error_code const& ec, // Result of operation
std::size_t bytes_
); );
@endcode @endcode
Regardless of whether the asynchronous operation completes Regardless of whether the asynchronous operation completes
@ -2976,9 +2980,12 @@ public:
void_or_deduced void_or_deduced
#else #else
async_return_type< async_return_type<
ReadHandler, void(error_code)> ReadHandler,
void(error_code, std::size_t)>
#endif #endif
async_read(DynamicBuffer& buffer, ReadHandler&& handler); async_read(
DynamicBuffer& buffer,
ReadHandler&& handler);
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------

View File

@ -209,7 +209,7 @@ boost::asio::ip::tcp::socket sock{ios};
//[ws_snippet_20 //[ws_snippet_20
multi_buffer buffer; multi_buffer buffer;
ws.async_read(buffer, ws.async_read(buffer,
[](error_code) [](error_code, std::size_t)
{ {
// Do something with the buffer // Do something with the buffer
}); });

View File

@ -270,7 +270,7 @@ public:
template< template<
class NextLayer, class DynamicBuffer> class NextLayer, class DynamicBuffer>
void std::size_t
read(stream<NextLayer>& ws, read(stream<NextLayer>& ws,
DynamicBuffer& buffer) const DynamicBuffer& buffer) const
{ {
@ -506,14 +506,16 @@ public:
template< template<
class NextLayer, class DynamicBuffer> class NextLayer, class DynamicBuffer>
void std::size_t
read(stream<NextLayer>& ws, read(stream<NextLayer>& ws,
DynamicBuffer& buffer) const DynamicBuffer& buffer) const
{ {
error_code ec; error_code ec;
ws.async_read(buffer, yield_[ec]); auto const bytes_written =
ws.async_read(buffer, yield_[ec]);
if(ec) if(ec)
throw system_error{ec}; throw system_error{ec};
return bytes_written;
} }
template< template<
@ -1342,7 +1344,7 @@ public:
// Read text message with bad utf8. // Read text message with bad utf8.
// Causes a close to be sent, blocking writes. // Causes a close to be sent, blocking writes.
ws.async_read(db, ws.async_read(db,
[&](error_code ec) [&](error_code ec, std::size_t)
{ {
// Read should fail with protocol error // Read should fail with protocol error
++count; ++count;
@ -1350,7 +1352,7 @@ public:
ec == error::failed, ec.message()); ec == error::failed, ec.message());
// Reads after failure are aborted // Reads after failure are aborted
ws.async_read(db, ws.async_read(db,
[&](error_code ec) [&](error_code ec, std::size_t)
{ {
++count; ++count;
BOOST_BEAST_EXPECTS(ec == boost::asio:: BOOST_BEAST_EXPECTS(ec == boost::asio::
@ -1409,7 +1411,7 @@ public:
// Read a close frame. // Read a close frame.
// Sends a close frame, blocking writes. // Sends a close frame, blocking writes.
ws.async_read(db, ws.async_read(db,
[&](error_code ec) [&](error_code ec, std::size_t)
{ {
// Read should complete with error::closed // Read should complete with error::closed
++count; ++count;
@ -1472,7 +1474,7 @@ public:
multi_buffer db; multi_buffer db;
std::size_t count = 0; std::size_t count = 0;
ws.async_read(db, ws.async_read(db,
[&](error_code ec) [&](error_code ec, std::size_t)
{ {
++count; ++count;
BOOST_BEAST_EXPECTS(ec == error::closed, BOOST_BEAST_EXPECTS(ec == error::closed,
@ -1521,7 +1523,7 @@ public:
}); });
multi_buffer db; multi_buffer db;
ws.async_read(db, ws.async_read(db,
[&](error_code ec) [&](error_code ec, std::size_t)
{ {
BOOST_BEAST_EXPECTS(ec == error::closed, ec.message()); BOOST_BEAST_EXPECTS(ec == error::closed, ec.message());
}); });