mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
Update websocket idle timer upon receiving a ping message
This commit is contained in:
committed by
Mohammad Nejati
parent
f9387fda71
commit
95386da791
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -196,13 +196,13 @@ jobs:
|
|||||||
- toolset: clang
|
- toolset: clang
|
||||||
install: clang-16
|
install: clang-16
|
||||||
compiler: clang++-16
|
compiler: clang++-16
|
||||||
cxxstd: "11,14,17,20,2b"
|
cxxstd: "11,14,17,20" # no 2b: https://github.com/llvm/llvm-project/issues/97842
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
supported: true
|
supported: true
|
||||||
- toolset: clang
|
- toolset: clang
|
||||||
install: clang-17
|
install: clang-17
|
||||||
compiler: clang++-17
|
compiler: clang++-17
|
||||||
cxxstd: "11,14,17,20,2b"
|
cxxstd: "11,14,17,20" # no 2b: https://github.com/llvm/llvm-project/issues/97842
|
||||||
os: ubuntu-24.04
|
os: ubuntu-24.04
|
||||||
supported: true
|
supported: true
|
||||||
- toolset: clang
|
- toolset: clang
|
||||||
|
@ -227,6 +227,8 @@ public:
|
|||||||
// Handle ping frame
|
// Handle ping frame
|
||||||
if(impl.rd_fh.op == detail::opcode::ping)
|
if(impl.rd_fh.op == detail::opcode::ping)
|
||||||
{
|
{
|
||||||
|
impl.update_timer(this->get_executor());
|
||||||
|
|
||||||
if(impl.ctrl_cb)
|
if(impl.ctrl_cb)
|
||||||
{
|
{
|
||||||
if(! cont)
|
if(! cont)
|
||||||
|
@ -439,8 +439,12 @@ struct stream<NextLayer, deflateSupported>::impl_type
|
|||||||
if(timeout_opt.idle_timeout != none())
|
if(timeout_opt.idle_timeout != none())
|
||||||
{
|
{
|
||||||
idle_counter = 0;
|
idle_counter = 0;
|
||||||
timer.expires_after(
|
if(timeout_opt.keep_alive_pings)
|
||||||
timeout_opt.idle_timeout / 2);
|
timer.expires_after(
|
||||||
|
timeout_opt.idle_timeout / 2);
|
||||||
|
else
|
||||||
|
timer.expires_after(
|
||||||
|
timeout_opt.idle_timeout);
|
||||||
|
|
||||||
BOOST_ASIO_HANDLER_LOCATION((
|
BOOST_ASIO_HANDLER_LOCATION((
|
||||||
__FILE__, __LINE__,
|
__FILE__, __LINE__,
|
||||||
@ -565,9 +569,9 @@ private:
|
|||||||
if(impl.timeout_opt.idle_timeout == none())
|
if(impl.timeout_opt.idle_timeout == none())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( impl.idle_counter < 1 )
|
if( impl.timeout_opt.keep_alive_pings &&
|
||||||
|
impl.idle_counter < 1)
|
||||||
{
|
{
|
||||||
if( impl.timeout_opt.keep_alive_pings )
|
|
||||||
{
|
{
|
||||||
BOOST_ASIO_HANDLER_LOCATION((
|
BOOST_ASIO_HANDLER_LOCATION((
|
||||||
__FILE__, __LINE__,
|
__FILE__, __LINE__,
|
||||||
|
@ -88,79 +88,6 @@ public:
|
|||||||
se.code().message());
|
se.code().message());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// inactivity timeout doesn't happen when you get pings
|
|
||||||
{
|
|
||||||
echo_server es{log};
|
|
||||||
stream<test::stream> ws{ioc_};
|
|
||||||
|
|
||||||
// We have an inactivity timeout of 2s, but don't send pings
|
|
||||||
ws.set_option(stream_base::timeout{
|
|
||||||
stream_base::none(),
|
|
||||||
std::chrono::milliseconds(2000),
|
|
||||||
false
|
|
||||||
});
|
|
||||||
ws.next_layer().connect(es.stream());
|
|
||||||
ws.handshake("localhost", "/");
|
|
||||||
flat_buffer b;
|
|
||||||
bool got_timeout = false;
|
|
||||||
ws.async_read(b,
|
|
||||||
[&](error_code ec, std::size_t)
|
|
||||||
{
|
|
||||||
if(ec != beast::error::timeout)
|
|
||||||
BOOST_THROW_EXCEPTION(
|
|
||||||
system_error{ec});
|
|
||||||
got_timeout = true;
|
|
||||||
});
|
|
||||||
// We are connected, base state
|
|
||||||
BEAST_EXPECT(ws.impl_->idle_counter == 0);
|
|
||||||
|
|
||||||
test::run_for(ioc_, std::chrono::milliseconds(1250));
|
|
||||||
// After 1.25s idle, no timeout but idle counter is 1
|
|
||||||
BEAST_EXPECT(ws.impl_->idle_counter == 1);
|
|
||||||
|
|
||||||
es.async_ping();
|
|
||||||
test::run_for(ioc_, std::chrono::milliseconds(500));
|
|
||||||
// The server sent a ping at 1.25s mark, and we're now at 1.75s mark.
|
|
||||||
// We haven't hit the idle timer yet (happens at 1s, 2s, 3s)
|
|
||||||
BEAST_EXPECT(ws.impl_->idle_counter == 0);
|
|
||||||
BEAST_EXPECT(!got_timeout);
|
|
||||||
|
|
||||||
test::run_for(ioc_, std::chrono::milliseconds(750));
|
|
||||||
// At 2.5s total; should have triggered the idle timer
|
|
||||||
BEAST_EXPECT(ws.impl_->idle_counter == 1);
|
|
||||||
BEAST_EXPECT(!got_timeout);
|
|
||||||
|
|
||||||
test::run_for(ioc_, std::chrono::milliseconds(750));
|
|
||||||
// At 3s total; should have triggered the idle timer again without
|
|
||||||
// activity and triggered timeout.
|
|
||||||
BEAST_EXPECT(got_timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
// inactivity timeout doesn't happen when you send pings
|
|
||||||
{
|
|
||||||
echo_server es{log};
|
|
||||||
stream<test::stream> ws{ioc_};
|
|
||||||
ws.set_option(stream_base::timeout{
|
|
||||||
stream_base::none(),
|
|
||||||
std::chrono::milliseconds(600),
|
|
||||||
true
|
|
||||||
});
|
|
||||||
unsigned n_pongs = 0;
|
|
||||||
ws.control_callback({[&](frame_type kind, string_view)
|
|
||||||
{
|
|
||||||
if (kind == frame_type::pong)
|
|
||||||
++n_pongs;
|
|
||||||
}});
|
|
||||||
ws.next_layer().connect(es.stream());
|
|
||||||
ws.handshake("localhost", "/");
|
|
||||||
flat_buffer b;
|
|
||||||
ws.async_read(b, test::fail_handler(asio::error::operation_aborted));
|
|
||||||
// We are connected, base state
|
|
||||||
test::run_for(ioc_, std::chrono::seconds(1));
|
|
||||||
// About a second later, we should have close to 5 pings/pongs, and no timeout
|
|
||||||
BEAST_EXPECTS(2 <= n_pongs && n_pongs <= 3, "Unexpected nr of pings: " + std::to_string(n_pongs));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -172,6 +99,75 @@ public:
|
|||||||
{
|
{
|
||||||
doTestPing(AsyncClient{yield});
|
doTestPing(AsyncClient{yield});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// inactivity timeout doesn't happen when you get pings
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
stream<test::stream> ws1(ioc);
|
||||||
|
stream<test::stream> ws2(ioc);
|
||||||
|
test::connect(ws1.next_layer(), ws2.next_layer());
|
||||||
|
ws1.set_option(stream_base::timeout{
|
||||||
|
stream_base::none(),
|
||||||
|
std::chrono::milliseconds(500),
|
||||||
|
false
|
||||||
|
});
|
||||||
|
ws2.async_accept(test::success_handler());
|
||||||
|
ws1.async_handshake("localhost", "/", test::success_handler());
|
||||||
|
ioc.run();
|
||||||
|
ioc.restart();
|
||||||
|
bool got_timeout = false;
|
||||||
|
flat_buffer b1;
|
||||||
|
ws1.async_read(b1,
|
||||||
|
[&](error_code ec, std::size_t)
|
||||||
|
{
|
||||||
|
if(ec != beast::error::timeout)
|
||||||
|
BOOST_THROW_EXCEPTION(
|
||||||
|
system_error{ec});
|
||||||
|
got_timeout = true;
|
||||||
|
});
|
||||||
|
ioc.run_for(std::chrono::milliseconds(250));
|
||||||
|
ioc.restart();
|
||||||
|
ws2.async_ping("", test::success_handler());
|
||||||
|
ioc.run_for(std::chrono::milliseconds(300));
|
||||||
|
ioc.restart();
|
||||||
|
BEAST_EXPECT(!got_timeout);
|
||||||
|
ioc.run_for(std::chrono::milliseconds(500));
|
||||||
|
ioc.restart();
|
||||||
|
BEAST_EXPECT(got_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// inactivity timeout doesn't happen when you send pings
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
stream<test::stream> ws1(ioc);
|
||||||
|
stream<test::stream> ws2(ioc);
|
||||||
|
test::connect(ws1.next_layer(), ws2.next_layer());
|
||||||
|
ws1.set_option(stream_base::timeout{
|
||||||
|
stream_base::none(),
|
||||||
|
std::chrono::milliseconds(1500),
|
||||||
|
true
|
||||||
|
});
|
||||||
|
unsigned n_pongs = 0;
|
||||||
|
ws1.control_callback({[&](frame_type kind, string_view)
|
||||||
|
{
|
||||||
|
if (kind == frame_type::pong)
|
||||||
|
++n_pongs;
|
||||||
|
}});
|
||||||
|
ws2.async_accept(test::success_handler());
|
||||||
|
ws1.async_handshake("localhost", "/", test::success_handler());
|
||||||
|
ioc.run();
|
||||||
|
ioc.restart();
|
||||||
|
flat_buffer b1, b2;
|
||||||
|
ws1.async_read(b1, test::fail_handler(asio::error::operation_aborted));
|
||||||
|
ws2.async_read(b2, test::fail_handler(error::closed));
|
||||||
|
ioc.run_for(std::chrono::seconds(2));
|
||||||
|
ioc.restart();
|
||||||
|
ws1.async_close({}, test::success_handler());
|
||||||
|
ioc.run();
|
||||||
|
ioc.restart();
|
||||||
|
// We should have close to 2 pings/pongs, and no timeout
|
||||||
|
BEAST_EXPECTS(1 <= n_pongs && n_pongs <= 3, "Unexpected nr of pings: " + std::to_string(n_pongs));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -134,12 +134,6 @@ public:
|
|||||||
this));
|
this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
async_ping()
|
|
||||||
{
|
|
||||||
ws_.async_ping("", [](error_code){});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
async_close()
|
async_close()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user