From b9b1b53fda2deee8ae8c959ee542ad24bd561032 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 24 Feb 2017 14:53:20 -0500 Subject: [PATCH] Fix race in pings during reads --- CHANGELOG.md | 8 ++++++++ include/beast/websocket/impl/ping.ipp | 14 +++++++++++--- include/beast/websocket/stream.hpp | 8 ++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62c37040..710b879b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +1.0.0-b30 + +WebSocket + +* Fix race in pings during reads + +-------------------------------------------------------------------------------- + 1.0.0-b29 * Fix compilation error in non-template class diff --git a/include/beast/websocket/impl/ping.ipp b/include/beast/websocket/impl/ping.ipp index 73990cce..657eb5d2 100644 --- a/include/beast/websocket/impl/ping.ipp +++ b/include/beast/websocket/impl/ping.ipp @@ -146,24 +146,32 @@ operator()(error_code ec, bool again) boost::asio::error::operation_aborted)); return; } - // fall through + d.ws.wr_block_ = &d; + // [[fallthrough]] case 1: // send ping frame + BOOST_ASSERT(d.ws.wr_block_ == &d); d.state = 99; - BOOST_ASSERT(! d.ws.wr_block_); - d.ws.wr_block_ = &d; boost::asio::async_write(d.ws.stream_, d.fb.data(), std::move(*this)); return; case 2: + BOOST_ASSERT(! d.ws.wr_block_); + d.ws.wr_block_ = &d; d.state = 3; + // The current context is safe but might not be + // the same as the one for this operation (since + // we are being called from a write operation). + // Call post to make sure we are invoked the same + // way as the final handler for this operation. d.ws.get_io_service().post( bind_handler(std::move(*this), ec)); return; case 3: + BOOST_ASSERT(d.ws.wr_block_ == &d); if(d.ws.failed_ || d.ws.wr_close_) { // call handler diff --git a/include/beast/websocket/stream.hpp b/include/beast/websocket/stream.hpp index 24fb1291..3a469c90 100644 --- a/include/beast/websocket/stream.hpp +++ b/include/beast/websocket/stream.hpp @@ -985,6 +985,10 @@ public: composed operation. The program must ensure that the stream performs no other writes until this operation completes. + If a close frame is sent or received before the ping frame is + sent, the completion handler will be called with the error + set to `boost::asio::error::operation_aborted`. + @param payload The payload of the ping message, which may be empty. @param handler The handler to be called when the read operation @@ -1078,6 +1082,10 @@ public: 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. + If a close frame is sent or received before the pong frame is + sent, the completion handler will be called with the error + set to `boost::asio::error::operation_aborted`. + @param payload The payload of the pong message, which may be empty. @param handler The handler to be called when the read operation