diff --git a/include/bitcoin/network/net/proxy.hpp b/include/bitcoin/network/net/proxy.hpp index 359963471..6377a9db1 100644 --- a/include/bitcoin/network/net/proxy.hpp +++ b/include/bitcoin/network/net/proxy.hpp @@ -59,10 +59,6 @@ class BCT_API proxy /// Stop socket, no delay, called by stop notify when iocontext is closing. virtual void stop(const code& ec) NOEXCEPT; - /// Idempotent, may be called multiple times. - /// Same as stop but provides graceful shutdown for websocket connections. - virtual void async_stop(const code& ec) NOEXCEPT; - /// Subscribe to stop notification with completion handler. /// Completion and event handlers are always invoked on the channel strand. void subscribe_stop(result_handler&& handler, diff --git a/src/channels/channel.cpp b/src/channels/channel.cpp index adf0a33de..555490a57 100644 --- a/src/channels/channel.cpp +++ b/src/channels/channel.cpp @@ -64,7 +64,7 @@ channel::~channel() NOEXCEPT // Start/stop/resume (started/paused upon create). // ---------------------------------------------------------------------------- -// This should not be called internally (invoked by stop() or async_stop()). +// This should not be called internally (invoked by stop()). void channel::stopping(const code& ec) NOEXCEPT { BC_ASSERT(stranded()); @@ -163,7 +163,7 @@ void channel::handle_expiration(const code& ec) NOEXCEPT return; } - async_stop(error::channel_expired); + stop(error::channel_expired); } void channel::stop_inactivity() NOEXCEPT @@ -202,7 +202,7 @@ void channel::handle_inactivity(const code& ec) NOEXCEPT return; } - async_stop(error::channel_inactive); + stop(error::channel_inactive); } // Properties. diff --git a/src/net/proxy.cpp b/src/net/proxy.cpp index eed015e6d..5e67212d1 100644 --- a/src/net/proxy.cpp +++ b/src/net/proxy.cpp @@ -52,26 +52,28 @@ void proxy::stop(const code& ec) NOEXCEPT if (stopped()) return; - // Stop the read loop, stop accepting new work, cancel pending work. - socket_->stop(); - - // Overruled by stop, set only for consistency. - paused_.store(true); - - boost::asio::post(strand(), - std::bind(&proxy::stopping, shared_from_this(), ec)); -} - -void proxy::async_stop(const code& ec) NOEXCEPT -{ - if (stopped()) - return; - - // Stop the read loop, stop accepting new work, cancel pending work. - // Allows for graceful ws/ssl::close, which would hang the threadpool if - // attempted within socket::stop(), as it issues a follow-on iocontext job. - // A subsequent call to socket::stop() will terminate directly. - socket_->lazy_stop(); + // Client or timer initated stop is async (graceful). + // error::channel_stopped is send in various contexts, however the only + // ones in which the channel is not stopped are those arising directly from + // socket read handlers, resulting in a stop(ec) call. This is interpreted + // as client socket cancellation, which along with timer cancellations are + // allowed to close gracefully. error::service_stopped will invoke socket + // stop() below, which will immediately terminate outstanding lazy_stop(). + if (ec == error::channel_stopped || + ec == error::channel_expired || + ec == error::channel_inactive) + { + // Stop the read loop, stop accepting new work, cancel pending work. + // Allows for graceful ws/ssl::close, which would hang threadpool if + // attempted within socket::stop(), as it issues a follow-on iocontext + // job. A subsequent call to socket::stop() will terminate directly. + socket_->lazy_stop(); + } + else + { + // Stop the read loop, stop accepting new work, cancel pending work. + socket_->stop(); + } // Overruled by stop, set only for consistency. paused_.store(true); @@ -81,7 +83,7 @@ void proxy::async_stop(const code& ec) NOEXCEPT } // protected -// This should not be called internally (invoked by stop() or async_stop()). +// This should not be called internally (invoked by stop()). void proxy::stopping(const code& ec) NOEXCEPT { BC_ASSERT(stranded());