mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 21:34:46 +02:00
Control callback is invoked on the execution context:
fix #954 Fix a defect where the control callback could execute on the same stack as the initiating function.
This commit is contained in:
@@ -2,6 +2,10 @@ Version 151:
|
||||
|
||||
* Sanitizer failures are errors
|
||||
|
||||
WebSocket:
|
||||
|
||||
* Control callback is invoked on the execution context
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Version 150:
|
||||
|
@@ -236,6 +236,17 @@ operator()(
|
||||
// Handle ping frame
|
||||
if(ws_.rd_fh_.op == detail::opcode::ping)
|
||||
{
|
||||
if(ws_.ctrl_cb_)
|
||||
{
|
||||
if(! cont_)
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
boost::asio::post(
|
||||
ws_.get_executor(),
|
||||
std::move(*this));
|
||||
BOOST_ASSERT(cont_);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto const b = buffers_prefix(
|
||||
clamp(ws_.rd_fh_.len),
|
||||
@@ -249,7 +260,8 @@ operator()(
|
||||
if(ws_.status_ == status::closing)
|
||||
goto loop;
|
||||
if(ws_.ctrl_cb_)
|
||||
ws_.ctrl_cb_(frame_type::ping, payload);
|
||||
ws_.ctrl_cb_(
|
||||
frame_type::ping, payload);
|
||||
ws_.rd_fb_.reset();
|
||||
ws_.template write_ping<
|
||||
flat_static_buffer_base>(ws_.rd_fb_,
|
||||
@@ -309,6 +321,18 @@ operator()(
|
||||
// Handle pong frame
|
||||
if(ws_.rd_fh_.op == detail::opcode::pong)
|
||||
{
|
||||
// Ignore pong when closing
|
||||
if(! ws_.wr_close_ && ws_.ctrl_cb_)
|
||||
{
|
||||
if(! cont_)
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
boost::asio::post(
|
||||
ws_.get_executor(),
|
||||
std::move(*this));
|
||||
BOOST_ASSERT(cont_);
|
||||
}
|
||||
}
|
||||
auto const cb = buffers_prefix(clamp(
|
||||
ws_.rd_fh_.len), ws_.rd_buf_.data());
|
||||
auto const len = buffer_size(cb);
|
||||
@@ -325,6 +349,17 @@ operator()(
|
||||
// Handle close frame
|
||||
BOOST_ASSERT(ws_.rd_fh_.op == detail::opcode::close);
|
||||
{
|
||||
if(ws_.ctrl_cb_)
|
||||
{
|
||||
if(! cont_)
|
||||
{
|
||||
BOOST_ASIO_CORO_YIELD
|
||||
boost::asio::post(
|
||||
ws_.get_executor(),
|
||||
std::move(*this));
|
||||
BOOST_ASSERT(cont_);
|
||||
}
|
||||
}
|
||||
auto const cb = buffers_prefix(clamp(
|
||||
ws_.rd_fh_.len), ws_.rd_buf_.data());
|
||||
auto const len = buffer_size(cb);
|
||||
|
@@ -59,6 +59,50 @@ public:
|
||||
BEAST_EXPECT(n == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
When the internal read buffer contains a control frame and
|
||||
stream::async_read_some is called, it is possible for the control
|
||||
callback to be invoked on the caller's stack instead of through
|
||||
the executor associated with the final completion handler.
|
||||
*/
|
||||
void
|
||||
testIssue954()
|
||||
{
|
||||
echo_server es{log};
|
||||
boost::asio::io_context ioc;
|
||||
stream<test::stream> ws{ioc};
|
||||
ws.next_layer().connect(es.stream());
|
||||
ws.handshake("localhost", "/");
|
||||
// message followed by ping
|
||||
ws.next_layer().append({
|
||||
"\x81\x00"
|
||||
"\x89\x00",
|
||||
4});
|
||||
bool called_cb = false;
|
||||
bool called_handler = false;
|
||||
ws.control_callback(
|
||||
[&called_cb](frame_type, string_view)
|
||||
{
|
||||
called_cb = true;
|
||||
});
|
||||
multi_buffer b;
|
||||
ws.async_read(b,
|
||||
[&](error_code, std::size_t)
|
||||
{
|
||||
called_handler = true;
|
||||
});
|
||||
BEAST_EXPECT(! called_cb);
|
||||
BEAST_EXPECT(! called_handler);
|
||||
ioc.run();
|
||||
BEAST_EXPECT(! called_cb);
|
||||
BEAST_EXPECT(called_handler);
|
||||
ws.async_read(b,
|
||||
[&](error_code, std::size_t)
|
||||
{
|
||||
});
|
||||
BEAST_EXPECT(! called_cb);
|
||||
}
|
||||
|
||||
/* Bishop Fox Hybrid Assessment issue 1
|
||||
|
||||
Happens with permessage-deflate enabled and a
|
||||
@@ -242,6 +286,7 @@ public:
|
||||
{
|
||||
testIssue802();
|
||||
testIssue807();
|
||||
testIssue954();
|
||||
testIssueBF1();
|
||||
testIssueBF2();
|
||||
}
|
||||
|
Reference in New Issue
Block a user