diff --git a/CHANGELOG.md b/CHANGELOG.md index da35554b..90b45a8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 154: + +* Type check completion handlers + +-------------------------------------------------------------------------------- + Version 153: * Remove BOOST_VERSION checks diff --git a/include/boost/beast/core/detail/type_traits.hpp b/include/boost/beast/core/detail/type_traits.hpp index c85cfe73..f07697c9 100644 --- a/include/boost/beast/core/detail/type_traits.hpp +++ b/include/boost/beast/core/detail/type_traits.hpp @@ -437,6 +437,18 @@ buffers_range(Buffers const& buffers) return buffers_range_adaptor{buffers}; } +/* If this static assert goes off, it means that the completion + handler you provided to an asynchronous initiating function did + not have the right signature. Check the parameter types for your + completion handler and make sure they match the list of types + expected by the initiating function, +*/ +#define BOOST_BEAST_HANDLER_INIT(type, sig) \ + static_assert(is_completion_handler< \ + BOOST_ASIO_HANDLER_TYPE(type, sig), sig>::value, \ + "CompletionHandler signature requirements not met"); \ + boost::asio::async_completion init{handler} + } // detail } // beast } // boost diff --git a/include/boost/beast/core/impl/buffered_read_stream.ipp b/include/boost/beast/core/impl/buffered_read_stream.ipp index 139c66a7..09f76345 100644 --- a/include/boost/beast/core/impl/buffered_read_stream.ipp +++ b/include/boost/beast/core/impl/buffered_read_stream.ipp @@ -233,8 +233,8 @@ async_read_some( if(buffer_.size() == 0 && capacity_ == 0) return next_layer_.async_read_some(buffers, std::forward(handler)); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); read_some_op{ std::move(init.completion_handler), *this, buffers}( diff --git a/include/boost/beast/http/impl/file_body_win32.ipp b/include/boost/beast/http/impl/file_body_win32.ipp index 9e4cfaf8..a0d8e606 100644 --- a/include/boost/beast/http/impl/file_body_win32.ipp +++ b/include/boost/beast/http/impl/file_body_win32.ipp @@ -564,8 +564,8 @@ async_write_some( basic_file_body, Fields>& sr, WriteHandler&& handler) { - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); detail::write_some_win32_op< Protocol, BOOST_ASIO_HANDLER_TYPE(WriteHandler, diff --git a/include/boost/beast/http/impl/read.ipp b/include/boost/beast/http/impl/read.ipp index df0eb690..4a847a2a 100644 --- a/include/boost/beast/http/impl/read.ipp +++ b/include/boost/beast/http/impl/read.ipp @@ -526,8 +526,8 @@ async_read_some( boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); BOOST_ASSERT(! parser.is_done()); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); detail::read_some_op{ @@ -614,8 +614,8 @@ async_read_header( boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); parser.eager(false); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); detail::read_op{ @@ -702,9 +702,8 @@ async_read( boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); parser.eager(true); - boost::asio::async_completion< - ReadHandler, - void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); detail::read_op{ @@ -794,9 +793,8 @@ async_read( "Body requirements not met"); static_assert(is_body_reader::value, "BodyReader requirements not met"); - boost::asio::async_completion< - ReadHandler, - void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); detail::read_msg_op< AsyncReadStream, DynamicBuffer, diff --git a/include/boost/beast/http/impl/write.ipp b/include/boost/beast/http/impl/write.ipp index 10cd26ef..6ef13864 100644 --- a/include/boost/beast/http/impl/write.ipp +++ b/include/boost/beast/http/impl/write.ipp @@ -471,9 +471,8 @@ async_write_some_impl( serializer& sr, WriteHandler&& handler) { - boost::asio::async_completion< - WriteHandler, - void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); detail::write_some_op< AsyncWriteStream, BOOST_ASIO_HANDLER_TYPE(WriteHandler, @@ -629,9 +628,8 @@ async_write_header( static_assert(is_body_writer::value, "BodyWriter requirements not met"); sr.split(true); - boost::asio::async_completion< - WriteHandler, - void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); detail::write_op< AsyncWriteStream, BOOST_ASIO_HANDLER_TYPE(WriteHandler, @@ -706,9 +704,8 @@ async_write( static_assert(is_body_writer::value, "BodyWriter requirements not met"); sr.split(false); - boost::asio::async_completion< - WriteHandler, - void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); detail::write_op< AsyncWriteStream, BOOST_ASIO_HANDLER_TYPE(WriteHandler, @@ -780,9 +777,8 @@ async_write( "Body requirements not met"); static_assert(is_body_writer::value, "BodyWriter requirements not met"); - boost::asio::async_completion< - WriteHandler, - void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); detail::write_msg_op< AsyncWriteStream, BOOST_ASIO_HANDLER_TYPE(WriteHandler, diff --git a/include/boost/beast/websocket/impl/accept.ipp b/include/boost/beast/websocket/impl/accept.ipp index 0dff87d2..21c920f8 100644 --- a/include/boost/beast/websocket/impl/accept.ipp +++ b/include/boost/beast/websocket/impl/accept.ipp @@ -544,8 +544,8 @@ async_accept( { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + AcceptHandler, void(error_code)); reset(); accept_op< decltype(&default_decorate_res), @@ -573,8 +573,8 @@ async_accept_ex( static_assert(detail::is_response_decorator< ResponseDecorator>::value, "ResponseDecorator requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + AcceptHandler, void(error_code)); reset(); accept_op< ResponseDecorator, @@ -604,8 +604,8 @@ async_accept( static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + AcceptHandler, void(error_code)); reset(); accept_op< decltype(&default_decorate_res), @@ -640,8 +640,8 @@ async_accept_ex( static_assert(detail::is_response_decorator< ResponseDecorator>::value, "ResponseDecorator requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + AcceptHandler, void(error_code)); reset(); accept_op< ResponseDecorator, @@ -666,8 +666,8 @@ async_accept( { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + AcceptHandler, void(error_code)); reset(); using boost::asio::asio_handler_is_continuation; response_op< @@ -698,8 +698,8 @@ async_accept_ex( static_assert(detail::is_response_decorator< ResponseDecorator>::value, "ResponseDecorator requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + AcceptHandler, void(error_code)); reset(); using boost::asio::asio_handler_is_continuation; response_op< diff --git a/include/boost/beast/websocket/impl/close.ipp b/include/boost/beast/websocket/impl/close.ipp index 17697139..b925ba8d 100644 --- a/include/boost/beast/websocket/impl/close.ipp +++ b/include/boost/beast/websocket/impl/close.ipp @@ -435,8 +435,8 @@ async_close(close_reason const& cr, CloseHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + CloseHandler, void(error_code)); close_op{ std::move(init.completion_handler), *this, cr}( diff --git a/include/boost/beast/websocket/impl/handshake.ipp b/include/boost/beast/websocket/impl/handshake.ipp index edab6542..644ca5c2 100644 --- a/include/boost/beast/websocket/impl/handshake.ipp +++ b/include/boost/beast/websocket/impl/handshake.ipp @@ -160,8 +160,8 @@ async_handshake(string_view host, { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + HandshakeHandler, void(error_code)); handshake_op{ std::move(init.completion_handler), *this, nullptr, host, @@ -181,8 +181,8 @@ async_handshake(response_type& res, { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + HandshakeHandler, void(error_code)); handshake_op{ std::move(init.completion_handler), *this, &res, host, @@ -205,8 +205,8 @@ async_handshake_ex(string_view host, static_assert(detail::is_request_decorator< RequestDecorator>::value, "RequestDecorator requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + HandshakeHandler, void(error_code)); handshake_op{ std::move(init.completion_handler), *this, nullptr, host, @@ -230,8 +230,8 @@ async_handshake_ex(response_type& res, static_assert(detail::is_request_decorator< RequestDecorator>::value, "RequestDecorator requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + HandshakeHandler, void(error_code)); handshake_op{ std::move(init.completion_handler), *this, &res, host, diff --git a/include/boost/beast/websocket/impl/ping.ipp b/include/boost/beast/websocket/impl/ping.ipp index f4067548..25303aa8 100644 --- a/include/boost/beast/websocket/impl/ping.ipp +++ b/include/boost/beast/websocket/impl/ping.ipp @@ -237,8 +237,8 @@ async_ping(ping_data const& payload, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code)); ping_op{ std::move(init.completion_handler), *this, @@ -255,8 +255,8 @@ async_pong(ping_data const& payload, WriteHandler&& handler) { static_assert(is_async_stream::value, "AsyncStream requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code)); ping_op{ std::move(init.completion_handler), *this, diff --git a/include/boost/beast/websocket/impl/read.ipp b/include/boost/beast/websocket/impl/read.ipp index b27149bd..60999ef6 100644 --- a/include/boost/beast/websocket/impl/read.ipp +++ b/include/boost/beast/websocket/impl/read.ipp @@ -895,8 +895,8 @@ async_read(DynamicBuffer& buffer, ReadHandler&& handler) static_assert( boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); - boost::asio::async_completion< - ReadHandler, void(error_code, std::size_t)> init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); read_op< DynamicBuffer, BOOST_ASIO_HANDLER_TYPE( @@ -983,8 +983,8 @@ async_read_some( static_assert( boost::asio::is_dynamic_buffer::value, "DynamicBuffer requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); read_op< DynamicBuffer, BOOST_ASIO_HANDLER_TYPE( @@ -1368,8 +1368,8 @@ async_read_some( static_assert(boost::asio::is_mutable_buffer_sequence< MutableBufferSequence>::value, "MutableBufferSequence requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); read_some_op{ std::move(init.completion_handler), *this, buffers}( diff --git a/include/boost/beast/websocket/impl/write.ipp b/include/boost/beast/websocket/impl/write.ipp index eccde945..ab71aba9 100644 --- a/include/boost/beast/websocket/impl/write.ipp +++ b/include/boost/beast/websocket/impl/write.ipp @@ -814,8 +814,8 @@ async_write_some(bool fin, static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); write_some_op{ std::move(init.completion_handler), *this, fin, bs}( @@ -870,8 +870,8 @@ async_write( static_assert(boost::asio::is_const_buffer_sequence< ConstBufferSequence>::value, "ConstBufferSequence requirements not met"); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); write_some_op{ std::move(init.completion_handler), *this, true, bs}( diff --git a/test/extras/include/boost/beast/test/stream.hpp b/test/extras/include/boost/beast/test/stream.hpp index a75bbde4..8a2730d7 100644 --- a/test/extras/include/boost/beast/test/stream.hpp +++ b/test/extras/include/boost/beast/test/stream.hpp @@ -479,8 +479,8 @@ async_read_some( using boost::asio::buffer_copy; using boost::asio::buffer_size; BOOST_ASSERT(buffer_size(buffers) > 0); - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + ReadHandler, void(error_code, std::size_t)); if(in_->fc) { error_code ec; @@ -598,8 +598,8 @@ async_write_some(ConstBufferSequence const& buffers, "ConstBufferSequence requirements not met"); using boost::asio::buffer_copy; using boost::asio::buffer_size; - boost::asio::async_completion init{handler}; + BOOST_BEAST_HANDLER_INIT( + WriteHandler, void(error_code, std::size_t)); auto out = out_.lock(); if(! out) return boost::asio::post(