avoid executing timed async task if the dht node is already removed (#2133)

This commit is contained in:
Alden Torres 2017-07-08 11:32:24 -04:00 committed by Arvid Norberg
parent de90419712
commit 80036f0377
3 changed files with 62 additions and 7 deletions

View File

@ -162,7 +162,7 @@ namespace libtorrent { namespace dht {
std::shared_ptr<dht_tracker> self()
{ return shared_from_this(); }
void connection_timeout(tracker_node& n, error_code const& e);
void connection_timeout(aux::session_listen_socket* s, error_code const& e);
void refresh_timeout(error_code const& e);
void refresh_key(error_code const& e);
void update_storage_node_ids();

View File

@ -227,3 +227,50 @@ TORRENT_TEST(dht_rate_limit)
#endif // #if !defined TORRENT_DISABLE_EXTENSIONS && !defined TORRENT_DISABLE_DHT
}
// TODO: put test here to take advantage of existing code, refactor
TORRENT_TEST(dht_delete_socket)
{
#ifndef TORRENT_DISABLE_DHT
sim::default_config cfg;
sim::simulation sim(cfg);
sim::asio::io_service dht_ios(sim, lt::address_v4::from_string("40.30.20.10"));
lt::udp_socket sock(dht_ios);
error_code ec;
sock.bind(udp::endpoint(address_v4::from_string("40.30.20.10"), 8888), ec);
obs o;
mock_socket ds;
dht_settings dhtsett;
counters cnt;
dht::dht_state state;
std::unique_ptr<lt::dht::dht_storage_interface> dht_storage(dht::dht_default_storage_constructor(dhtsett));
auto dht = std::make_shared<lt::dht::dht_tracker>(
&o, dht_ios, std::bind(&send_packet, std::ref(sock), _1, _2, _3, _4, _5)
, dhtsett, cnt, *dht_storage, state);
dht->start([](std::vector<std::pair<dht::node_entry, std::string>> const&){});
dht->new_socket(&ds);
// schedule the removal of the socket at exactly 2 second,
// this simulates the fact that the internal scheduled call
// to connection_timeout will be executed right after leaving
// the state of cancellable
asio::high_resolution_timer t1(dht_ios);
t1.expires_from_now(chrono::seconds(2));
t1.async_wait([&](error_code const&)
{
dht->delete_socket(&ds);
});
// stop the DHT
asio::high_resolution_timer t2(dht_ios);
t2.expires_from_now(chrono::seconds(3));
t2.async_wait([&](error_code const&) { dht->stop(); });
sim.run();
#endif // TORRENT_DISABLE_DHT
}

View File

@ -149,8 +149,8 @@ namespace libtorrent { namespace dht {
error_code ec;
n.first->second.connection_timer.expires_from_now(seconds(1), ec);
n.first->second.connection_timer.async_wait(
std::bind(&dht_tracker::connection_timeout, self(), std::ref(n.first->second), _1));
n.first->second.dht.bootstrap(std::vector<udp::endpoint>(), find_data::nodes_callback());
std::bind(&dht_tracker::connection_timeout, self(), n.first->first, _1));
n.first->second.dht.bootstrap({}, find_data::nodes_callback());
}
}
@ -176,7 +176,7 @@ namespace libtorrent { namespace dht {
{
n.second.connection_timer.expires_from_now(seconds(1), ec);
n.second.connection_timer.async_wait(
std::bind(&dht_tracker::connection_timeout, self(), std::ref(n.second), _1));
std::bind(&dht_tracker::connection_timeout, self(), n.first, _1));
#if TORRENT_USE_IPV6
if (n.first->get_local_endpoint().protocol() == tcp::v6())
n.second.dht.bootstrap(concat(m_state.nodes6, m_state.nodes), f);
@ -242,15 +242,21 @@ namespace libtorrent { namespace dht {
add_dht_counters(n.second.dht, c);
}
void dht_tracker::connection_timeout(tracker_node& n, error_code const& e)
void dht_tracker::connection_timeout(aux::session_listen_socket* s, error_code const& e)
{
if (e || !m_running) return;
time_duration d = n.dht.connection_timeout();
auto const it = m_nodes.find(s);
// this could happen if the task is about to be executed (and not cancellable) and
// the socket is just removed
if (it == m_nodes.end()) return; // node already destroyed
tracker_node& n = it->second;
time_duration const d = n.dht.connection_timeout();
error_code ec;
deadline_timer& timer = n.connection_timer;
timer.expires_from_now(d, ec);
timer.async_wait(std::bind(&dht_tracker::connection_timeout, self(), std::ref(n), _1));
timer.async_wait(std::bind(&dht_tracker::connection_timeout, self(), s, _1));
}
void dht_tracker::refresh_timeout(error_code const& e)
@ -644,6 +650,8 @@ namespace libtorrent { namespace dht {
bool dht_tracker::send_packet(aux::session_listen_socket* s, entry& e, udp::endpoint const& addr)
{
TORRENT_ASSERT(m_nodes.find(s) != m_nodes.end());
static char const version_str[] = {'L', 'T'
, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR};
e["v"] = std::string(version_str, version_str + 4);