Skip to content

Commit

Permalink
Make async_handshake::operator() not be a coroutine
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jens-diewald committed Feb 11, 2023
1 parent 88ce93c commit b437f7a
Showing 1 changed file with 33 additions and 47 deletions.
80 changes: 33 additions & 47 deletions include/boost/wintls/detail/async_handshake.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,21 @@

#include <boost/wintls/detail/sspi_handshake.hpp>

#include <boost/asio/coroutine.hpp>

namespace boost {
namespace wintls {
namespace detail {

template <typename NextLayer>
struct async_handshake : boost::asio::coroutine {
template<typename NextLayer>
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 <typename Self>
template<typename Self>
void operator()(Self& self, boost::system::error_code ec = {}, std::size_t length = 0) {
if (ec) {
self.complete(ec);
Expand All @@ -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;
Expand All @@ -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());
}
}
Expand Down

0 comments on commit b437f7a

Please sign in to comment.