mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 13:27:33 +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
|
* Write buffer option does not change capacity
|
||||||
* Close connection during async_read on close frame
|
* Close connection during async_read on close frame
|
||||||
|
* Add pong, async pong to stream
|
||||||
|
|
||||||
Core
|
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
|
by either peer on an established WebSocket connection. They are sent
|
||||||
using the functions
|
using the functions
|
||||||
[link beast.ref.websocket__stream.ping `ping`] and
|
[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
|
To receive pong control frames, callers may register a "pong callback" using
|
||||||
[link beast.ref.websocket__stream.set_option `set_option`]. The object provided
|
[link beast.ref.websocket__stream.set_option `set_option`]. The object provided
|
||||||
|
@ -104,7 +104,6 @@ protected:
|
|||||||
// The write buffer.
|
// The write buffer.
|
||||||
// The buffer is allocated or reallocated at the beginning of
|
// The buffer is allocated or reallocated at the beginning of
|
||||||
// sending a message.
|
// sending a message.
|
||||||
//
|
|
||||||
std::unique_ptr<std::uint8_t[]> buf;
|
std::unique_ptr<std::uint8_t[]> buf;
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -38,7 +38,7 @@ class stream<NextLayer>::ping_op
|
|||||||
|
|
||||||
template<class DeducedHandler>
|
template<class DeducedHandler>
|
||||||
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
data(DeducedHandler&& h_, stream<NextLayer>& ws_,
|
||||||
ping_data const& payload)
|
opcode op_, ping_data const& payload)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
, h(std::forward<DeducedHandler>(h_))
|
, h(std::forward<DeducedHandler>(h_))
|
||||||
, cont(boost_asio_handler_cont_helpers::
|
, cont(boost_asio_handler_cont_helpers::
|
||||||
@ -46,8 +46,8 @@ class stream<NextLayer>::ping_op
|
|||||||
{
|
{
|
||||||
using boost::asio::buffer;
|
using boost::asio::buffer;
|
||||||
using boost::asio::buffer_copy;
|
using boost::asio::buffer_copy;
|
||||||
ws.template write_ping<static_streambuf>(
|
ws.template write_ping<
|
||||||
fb, opcode::ping, payload);
|
static_streambuf>(fb, op_, payload);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -191,19 +191,38 @@ upcall:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class NextLayer>
|
template<class NextLayer>
|
||||||
template<class PingHandler>
|
template<class WriteHandler>
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
PingHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
stream<NextLayer>::
|
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,
|
static_assert(is_AsyncStream<next_layer_type>::value,
|
||||||
"AsyncStream requirements requirements not met");
|
"AsyncStream requirements requirements not met");
|
||||||
beast::async_completion<
|
beast::async_completion<
|
||||||
PingHandler, void(error_code)
|
WriteHandler, void(error_code)
|
||||||
> completion(handler);
|
> completion(handler);
|
||||||
ping_op<decltype(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();
|
return completion.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +248,28 @@ ping(ping_data const& payload, error_code& ec)
|
|||||||
boost::asio::write(stream_, db.data(), 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
|
} // websocket
|
||||||
|
@ -40,7 +40,7 @@ namespace websocket {
|
|||||||
system call, by concatenating the frame header and the payload.
|
system call, by concatenating the frame header and the payload.
|
||||||
|
|
||||||
In the client role, this will send a single frame in one system
|
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
|
2. autofragment: true
|
||||||
compression: false
|
compression: false
|
||||||
|
@ -987,14 +987,107 @@ public:
|
|||||||
this function. Invocation of the handler will be performed in a
|
this function. Invocation of the handler will be performed in a
|
||||||
manner equivalent to using `boost::asio::io_service::post`.
|
manner equivalent to using `boost::asio::io_service::post`.
|
||||||
*/
|
*/
|
||||||
template<class PingHandler>
|
template<class WriteHandler>
|
||||||
#if GENERATING_DOCS
|
#if GENERATING_DOCS
|
||||||
void_or_deduced
|
void_or_deduced
|
||||||
#else
|
#else
|
||||||
typename async_completion<
|
typename async_completion<
|
||||||
PingHandler, void(error_code)>::result_type
|
WriteHandler, void(error_code)>::result_type
|
||||||
#endif
|
#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.
|
/** Read a message from the stream.
|
||||||
|
|
||||||
|
@ -910,6 +910,9 @@ public:
|
|||||||
}
|
}
|
||||||
ws.set_option(pong_callback{});
|
ws.set_option(pong_callback{});
|
||||||
|
|
||||||
|
// send pong
|
||||||
|
ws.pong("");
|
||||||
|
|
||||||
// send auto fragmented message
|
// send auto fragmented message
|
||||||
ws.set_option(auto_fragment{true});
|
ws.set_option(auto_fragment{true});
|
||||||
ws.set_option(write_buffer_size{8});
|
ws.set_option(write_buffer_size{8});
|
||||||
@ -1172,6 +1175,9 @@ public:
|
|||||||
ws.set_option(pong_callback{});
|
ws.set_option(pong_callback{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send pong
|
||||||
|
ws.async_pong("", do_yield[ec]);
|
||||||
|
|
||||||
// send auto fragmented message
|
// send auto fragmented message
|
||||||
ws.set_option(auto_fragment{true});
|
ws.set_option(auto_fragment{true});
|
||||||
ws.set_option(write_buffer_size{8});
|
ws.set_option(write_buffer_size{8});
|
||||||
|
Reference in New Issue
Block a user