From b437f7a7381878c398b6c3bd9e6a290cfc0712ad Mon Sep 17 00:00:00 2001 From: Jens Diewald Date: Sat, 11 Feb 2023 13:59:23 +0100 Subject: [PATCH] Make async_handshake::operator() not be a coroutine Again this is to simplify the code. I do not currently see a reason for the function to be a coroutine. Also add a comment about posting self.complete on the first call. --- .../boost/wintls/detail/async_handshake.hpp | 80 ++++++++----------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/include/boost/wintls/detail/async_handshake.hpp b/include/boost/wintls/detail/async_handshake.hpp index 8e35d94a..0396688b 100644 --- a/include/boost/wintls/detail/async_handshake.hpp +++ b/include/boost/wintls/detail/async_handshake.hpp @@ -12,23 +12,21 @@ #include -#include - namespace boost { namespace wintls { namespace detail { -template -struct async_handshake : boost::asio::coroutine { +template +struct async_handshake { async_handshake(NextLayer& next_layer, detail::sspi_handshake& handshake, handshake_type type) - : next_layer_(next_layer) - , handshake_(handshake) - , entry_count_(0) - , state_(state::idle) { + : next_layer_(next_layer) + , handshake_(handshake) + , entry_count_(0) + , state_(state::idle) { handshake_(type); } - template + template void operator()(Self& self, boost::system::error_code ec = {}, std::size_t length = 0) { if (ec) { self.complete(ec); @@ -40,7 +38,7 @@ struct async_handshake : boost::asio::coroutine { return entry_count_ > 1; }; - switch(state_) { + switch (state_) { case state::reading: handshake_.size_read(length); state_ = state::idle; @@ -53,45 +51,33 @@ struct async_handshake : boost::asio::coroutine { break; } - detail::sspi_handshake::state handshake_state; - BOOST_ASIO_CORO_REENTER(*this) { - while((handshake_state = handshake_()) != detail::sspi_handshake::state::done) { - if (handshake_state == detail::sspi_handshake::state::data_needed) { - BOOST_ASIO_CORO_YIELD { - state_ = state::reading; - next_layer_.async_read_some(handshake_.in_buffer(), std::move(self)); - } - continue; - } - - if (handshake_state == detail::sspi_handshake::state::data_available) { - BOOST_ASIO_CORO_YIELD { - state_ = state::writing; - net::async_write(next_layer_, handshake_.out_buffer(), std::move(self)); - } - continue; - } - - if (handshake_state == detail::sspi_handshake::state::error) { - if (!is_continuation()) { - BOOST_ASIO_CORO_YIELD { - auto e = self.get_executor(); - net::post(e, [self = std::move(self), ec, length]() mutable { self(ec, length); }); - } - } - self.complete(handshake_.last_error()); - return; - } + switch ((handshake_())) { + case detail::sspi_handshake::state::data_needed: { + state_ = state::reading; + next_layer_.async_read_some(handshake_.in_buffer(), std::move(self)); + return; } - - if (!is_continuation()) { - BOOST_ASIO_CORO_YIELD { - auto e = self.get_executor(); - net::post(e, [self = std::move(self), ec, length]() mutable { self(ec, length); }); - } + case detail::sspi_handshake::state::data_available: { + state_ = state::writing; + net::async_write(next_layer_, handshake_.out_buffer(), std::move(self)); + return; } - BOOST_ASSERT(!handshake_.last_error()); - handshake_.manual_auth(); + case detail::sspi_handshake::state::error: { + break; + } + case detail::sspi_handshake::state::done: { + BOOST_ASSERT(!handshake_.last_error()); + handshake_.manual_auth(); + break; + } + } + // If this is the first call to this function, it would cause the completion handler + // (invoked by self.complete()) to be executed on the wrong executor. + // Ensure that doesn't happen by posting the completion handler instead of calling it directly. + if (!is_continuation()) { + auto e = self.get_executor(); + net::post(e, [self = std::move(self), ec, length]() mutable { self(ec, length); }); + } else { self.complete(handshake_.last_error()); } }