add built-in time-out to async_shutdown

This commit is contained in:
arvidn 2020-04-10 11:29:46 +02:00 committed by Arvid Norberg
parent c825320df8
commit 61d2c8c1f5
1 changed files with 29 additions and 17 deletions

View File

@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/aux_/socket_type.hpp" #include "libtorrent/aux_/socket_type.hpp"
#include "libtorrent/aux_/openssl.hpp" #include "libtorrent/aux_/openssl.hpp"
#include "libtorrent/deadline_timer.hpp"
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
#include <boost/asio/ssl/context.hpp> #include <boost/asio/ssl/context.hpp>
@ -139,18 +140,32 @@ namespace aux {
} }
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
namespace {
void nop(std::shared_ptr<void>) {} struct socket_closer
void on_close_socket(socket_type* s, std::shared_ptr<void>)
{ {
COMPLETE_ASYNC("on_close_socket"); socket_closer(io_service& e
error_code ec; , std::shared_ptr<void> holder
s->close(ec); , socket_type* s)
} : h(std::move(holder))
, t(std::make_shared<deadline_timer>(e))
, sock(s)
{
t->expires_after(seconds(3));
t->async_wait(*this);
}
} // anonymous namespace void operator()(error_code const&)
{
COMPLETE_ASYNC("on_close_socket");
error_code ec;
sock->close(ec);
t->cancel();
}
std::shared_ptr<void> h;
std::shared_ptr<deadline_timer> t;
socket_type* sock;
};
#endif #endif
// the second argument is a shared pointer to an object that // the second argument is a shared pointer to an object that
@ -167,16 +182,13 @@ namespace aux {
#define MAYBE_ASIO_DEBUGGING #define MAYBE_ASIO_DEBUGGING
#endif #endif
static char const buffer[] = ""; // we call ASIO_DEBUGGING twice, because the socket_closer callback will be
// chasing the async_shutdown by a write is a trick to close the socket as // called twice
// soon as we've sent the close_notify, without having to wait to receive a
// response from the other end
// https://stackoverflow.com/questions/32046034/what-is-the-proper-way-to-securely-disconnect-an-asio-ssl-socket
#define CASE(t) case socket_type_int_impl<ssl_stream<t>>::value: \ #define CASE(t) case socket_type_int_impl<ssl_stream<t>>::value: \
MAYBE_ASIO_DEBUGGING \ MAYBE_ASIO_DEBUGGING \
s.get<ssl_stream<t>>()->async_shutdown(std::bind(&nop, holder)); \ MAYBE_ASIO_DEBUGGING \
s.get<ssl_stream<t>>()->async_write_some(boost::asio::buffer(buffer), std::bind(&on_close_socket, &s, holder)); \ s.get<ssl_stream<t>>()->async_shutdown( \
socket_closer(s.get_io_service(), std::move(holder), &s)); \
break; break;
switch (s.type()) switch (s.type())