mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Add websocket::stream pong and async_pong
This commit is contained in:
@ -11,6 +11,7 @@ WebSocket
|
||||
|
||||
* Write buffer option does not change capacity
|
||||
* Close connection during async_read on close frame
|
||||
* Add pong, async pong to stream
|
||||
|
||||
Core
|
||||
|
||||
|
@ -329,7 +329,7 @@ Ping and pong messages are control frames which may be sent at any time
|
||||
by either peer on an established WebSocket connection. They are sent
|
||||
using the functions
|
||||
[link beast.ref.websocket__stream.ping `ping`] and
|
||||
[link beast.ref.websocket__stream.ping `pong`].
|
||||
[link beast.ref.websocket__stream.pong `pong`].
|
||||
|
||||
To receive pong control frames, callers may register a "pong callback" using
|
||||
[link beast.ref.websocket__stream.set_option `set_option`]. The object provided
|
||||
|
@ -226,7 +226,7 @@ struct message_headers
|
||||
|
||||
The Reason-Phrase is obsolete as of rfc7230.
|
||||
|
||||
@note This field is present only if `isRequest == false`.
|
||||
@note This field is present only if `isRequest == false`.
|
||||
*/
|
||||
std::string reason;
|
||||
|
||||
|
@ -104,7 +104,6 @@ protected:
|
||||
// The write buffer.
|
||||
// The buffer is allocated or reallocated at the beginning of
|
||||
// sending a message.
|
||||
//
|
||||
std::unique_ptr<std::uint8_t[]> buf;
|
||||
|
||||
void
|
||||
|
@ -38,7 +38,7 @@ class stream<NextLayer>::ping_op
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
||||
ping_data const& payload)
|
||||
opcode op_, ping_data const& payload)
|
||||
: ws(ws_)
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
, cont(boost_asio_handler_cont_helpers::
|
||||
@ -46,8 +46,8 @@ class stream<NextLayer>::ping_op
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_copy;
|
||||
ws.template write_ping<static_streambuf>(
|
||||
fb, opcode::ping, payload);
|
||||
ws.template write_ping<
|
||||
static_streambuf>(fb, op_, payload);
|
||||
}
|
||||
};
|
||||
|
||||
@ -191,19 +191,38 @@ upcall:
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class PingHandler>
|
||||
template<class WriteHandler>
|
||||
typename async_completion<
|
||||
PingHandler, void(error_code)>::result_type
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
stream<NextLayer>::
|
||||
async_ping(ping_data const& payload, PingHandler&& handler)
|
||||
async_ping(ping_data const& payload, WriteHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
beast::async_completion<
|
||||
PingHandler, void(error_code)
|
||||
WriteHandler, void(error_code)
|
||||
> completion(handler);
|
||||
ping_op<decltype(completion.handler)>{
|
||||
completion.handler, *this, payload};
|
||||
completion.handler, *this,
|
||||
opcode::ping, payload};
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
template<class WriteHandler>
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
stream<NextLayer>::
|
||||
async_pong(ping_data const& payload, WriteHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||
"AsyncStream requirements requirements not met");
|
||||
beast::async_completion<
|
||||
WriteHandler, void(error_code)
|
||||
> completion(handler);
|
||||
ping_op<decltype(completion.handler)>{
|
||||
completion.handler, *this,
|
||||
opcode::pong, payload};
|
||||
return completion.result.get();
|
||||
}
|
||||
|
||||
@ -229,6 +248,28 @@ ping(ping_data const& payload, error_code& ec)
|
||||
boost::asio::write(stream_, db.data(), ec);
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
pong(ping_data const& payload)
|
||||
{
|
||||
error_code ec;
|
||||
pong(payload, ec);
|
||||
if(ec)
|
||||
throw system_error{ec};
|
||||
}
|
||||
|
||||
template<class NextLayer>
|
||||
void
|
||||
stream<NextLayer>::
|
||||
pong(ping_data const& payload, error_code& ec)
|
||||
{
|
||||
detail::frame_streambuf db;
|
||||
write_ping<static_streambuf>(
|
||||
db, opcode::pong, payload);
|
||||
boost::asio::write(stream_, db.data(), ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // websocket
|
||||
|
@ -40,7 +40,7 @@ namespace websocket {
|
||||
system call, by concatenating the frame header and the payload.
|
||||
|
||||
In the client role, this will send a single frame in one system
|
||||
calls, using the write buffer to calculate masked data.
|
||||
call, using the write buffer to calculate masked data.
|
||||
|
||||
2. autofragment: true
|
||||
compression: false
|
||||
@ -215,7 +215,7 @@ public:
|
||||
|
||||
template<class NextLayer>
|
||||
template<class Buffers, class Handler>
|
||||
void
|
||||
void
|
||||
stream<NextLayer>::
|
||||
write_frame_op<Buffers, Handler>::
|
||||
operator()(error_code ec, std::size_t)
|
||||
|
@ -987,14 +987,107 @@ public:
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class PingHandler>
|
||||
template<class WriteHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<
|
||||
PingHandler, void(error_code)>::result_type
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_ping(ping_data const& payload, PingHandler&& handler);
|
||||
async_ping(ping_data const& payload, WriteHandler&& handler);
|
||||
|
||||
/** Send a WebSocket pong frame.
|
||||
|
||||
This function is used to synchronously send a pong frame on
|
||||
the stream. The call blocks until one of the following is true:
|
||||
|
||||
@li The pong frame finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to the
|
||||
next layer's `write_some` functions.
|
||||
|
||||
The WebSocket protocol allows pong frames to be sent from either
|
||||
end at any time. It is not necessary to first receive a ping in
|
||||
order to send a pong. The remote peer may use the receipt of a
|
||||
pong frame as an indication that the connection is not dead.
|
||||
|
||||
@param payload The payload of the pong message, which may be empty.
|
||||
|
||||
@throws system_error Thrown on failure.
|
||||
*/
|
||||
void
|
||||
pong(ping_data const& payload);
|
||||
|
||||
/** Send a WebSocket pong frame.
|
||||
|
||||
This function is used to synchronously send a pong frame on
|
||||
the stream. The call blocks until one of the following is true:
|
||||
|
||||
@li The pong frame finishes sending.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This function is implemented in terms of one or more calls to the
|
||||
next layer's `write_some` functions.
|
||||
|
||||
The WebSocket protocol allows pong frames to be sent from either
|
||||
end at any time. It is not necessary to first receive a ping in
|
||||
order to send a pong. The remote peer may use the receipt of a
|
||||
pong frame as an indication that the connection is not dead.
|
||||
|
||||
@param payload The payload of the pong message, which may be empty.
|
||||
|
||||
@param ec Set to indicate what error occurred, if any.
|
||||
*/
|
||||
void
|
||||
pong(ping_data const& payload, error_code& ec);
|
||||
|
||||
/** Start an asynchronous operation to send a WebSocket pong frame.
|
||||
|
||||
This function is used to asynchronously send a pong frame to
|
||||
the stream. The function call always returns immediately. The
|
||||
asynchronous operation will continue until one of the following
|
||||
is true:
|
||||
|
||||
@li The entire pong frame is sent.
|
||||
|
||||
@li An error occurs on the stream.
|
||||
|
||||
This operation is implemented in terms of one or more calls to the
|
||||
next layer's `async_write_some` functions, and is known as a
|
||||
<em>composed operation</em>. The program must ensure that the
|
||||
stream performs no other writes until this operation completes.
|
||||
|
||||
The WebSocket protocol allows pong frames to be sent from either
|
||||
end at any time. It is not necessary to first receive a ping in
|
||||
order to send a pong. The remote peer may use the receipt of a
|
||||
pong frame as an indication that the connection is not dead.
|
||||
|
||||
@param payload The payload of the pong message, which may be empty.
|
||||
|
||||
@param handler The handler to be called when the read operation
|
||||
completes. Copies will be made of the handler as required. The
|
||||
function signature of the handler must be:
|
||||
@code
|
||||
void handler(
|
||||
error_code const& error // Result of operation
|
||||
);
|
||||
@endcode
|
||||
Regardless of whether the asynchronous operation completes
|
||||
immediately or not, the handler will not be invoked from within
|
||||
this function. Invocation of the handler will be performed in a
|
||||
manner equivalent to using `boost::asio::io_service::post`.
|
||||
*/
|
||||
template<class WriteHandler>
|
||||
#if GENERATING_DOCS
|
||||
void_or_deduced
|
||||
#else
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
#endif
|
||||
async_pong(ping_data const& payload, WriteHandler&& handler);
|
||||
|
||||
/** Read a message from the stream.
|
||||
|
||||
|
@ -910,6 +910,9 @@ public:
|
||||
}
|
||||
ws.set_option(pong_callback{});
|
||||
|
||||
// send pong
|
||||
ws.pong("");
|
||||
|
||||
// send auto fragmented message
|
||||
ws.set_option(auto_fragment{true});
|
||||
ws.set_option(write_buffer_size{8});
|
||||
@ -1172,6 +1175,9 @@ public:
|
||||
ws.set_option(pong_callback{});
|
||||
}
|
||||
|
||||
// send pong
|
||||
ws.async_pong("", do_yield[ec]);
|
||||
|
||||
// send auto fragmented message
|
||||
ws.set_option(auto_fragment{true});
|
||||
ws.set_option(write_buffer_size{8});
|
||||
|
Reference in New Issue
Block a user