diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp
index a320128a4..d7fe70e48 100644
--- a/include/libtorrent/aux_/session_impl.hpp
+++ b/include/libtorrent/aux_/session_impl.hpp
@@ -328,6 +328,8 @@ namespace libtorrent
entry dht_state() const;
#endif
void on_dht_announce(error_code const& e);
+ void on_dht_name_lookup(error_code const& e
+ , std::vector
const& addresses, int port);
void on_dht_router_name_lookup(error_code const& e
, std::vector const& addresses, int port);
#endif
@@ -996,7 +998,11 @@ namespace libtorrent
// these are used when starting the DHT
// (and bootstrapping it), and then erased
- std::list m_dht_router_nodes;
+ std::vector m_dht_router_nodes;
+
+ // if a DHT node is added when there's no DHT instance, they're stored
+ // here until we start the DHT
+ std::vector m_dht_nodes;
// this announce timer is used
// by the DHT.
@@ -1009,6 +1015,10 @@ namespace libtorrent
// is updated again. This especially matters for
// small numbers.
int m_dht_interval_update_torrents;
+
+ // the number of DHT router lookups there are currently outstanding. As
+ // long as this is > 0, we'll postpone starting the DHT
+ int m_outstanding_router_lookups;
#endif
bool incoming_packet(error_code const& ec
diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp
index 1f46a361e..3608d9c4a 100644
--- a/include/libtorrent/kademlia/dht_tracker.hpp
+++ b/include/libtorrent/kademlia/dht_tracker.hpp
@@ -80,7 +80,6 @@ namespace libtorrent { namespace dht
void stop();
void add_node(udp::endpoint node);
- void add_node(std::pair const& node);
void add_router_node(udp::endpoint const& node);
entry state() const;
@@ -126,10 +125,6 @@ namespace libtorrent { namespace dht
boost::shared_ptr self()
{ return shared_from_this(); }
- void on_name_lookup(error_code const& e
- , udp::resolver::iterator host);
- void on_router_name_lookup(error_code const& e
- , udp::resolver::iterator host);
void connection_timeout(error_code const& e);
void refresh_timeout(error_code const& e);
void tick(error_code const& e);
diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp
index 549856114..06b057b02 100644
--- a/src/kademlia/dht_tracker.cpp
+++ b/src/kademlia/dht_tracker.cpp
@@ -442,22 +442,6 @@ namespace libtorrent { namespace dht
m_dht.add_node(node);
}
- void dht_tracker::add_node(std::pair const& node)
- {
- char port[7];
- snprintf(port, sizeof(port), "%d", node.second);
- udp::resolver::query q(node.first, port);
- m_host_resolver.async_resolve(q,
- boost::bind(&dht_tracker::on_name_lookup, self(), _1, _2));
- }
-
- void dht_tracker::on_name_lookup(error_code const& e
- , udp::resolver::iterator host)
- {
- if (e || host == udp::resolver::iterator()) return;
- add_node(host->endpoint());
- }
-
void dht_tracker::add_router_node(udp::endpoint const& node)
{
m_dht.add_router_node(node);
diff --git a/src/session_impl.cpp b/src/session_impl.cpp
index fb08b170d..a20e7be5f 100644
--- a/src/session_impl.cpp
+++ b/src/session_impl.cpp
@@ -416,6 +416,7 @@ namespace aux {
#ifndef TORRENT_DISABLE_DHT
, m_dht_announce_timer(m_io_service)
, m_dht_interval_update_torrents(0)
+ , m_outstanding_router_lookups(0)
#endif
, m_external_udp_port(0)
, m_udp_socket(m_io_service)
@@ -3353,6 +3354,7 @@ retry:
TORRENT_ASSERT(is_single_thread());
if (m_dht) m_dht->add_node(n);
+ else m_dht_nodes.push_back(n);
}
bool session_impl::has_dht() const
@@ -4509,11 +4511,13 @@ retry:
#ifndef TORRENT_DISABLE_DHT
// add p.dht_nodes to the DHT, if enabled
- if (m_dht && !p.dht_nodes.empty())
+ if (!p.dht_nodes.empty())
{
for (std::vector >::const_iterator i = p.dht_nodes.begin()
, end(p.dht_nodes.end()); i != end; ++i)
- m_dht->add_node(*i);
+ {
+ add_dht_node_name(*i);
+ }
}
#endif
@@ -4665,13 +4669,14 @@ retry:
#endif
#ifndef TORRENT_DISABLE_DHT
- if (m_dht && params.ti)
+ if (params.ti)
{
torrent_info::nodes_t const& nodes = params.ti->nodes();
- std::for_each(nodes.begin(), nodes.end(), boost::bind(
- static_cast const&)>(
- &dht::dht_tracker::add_node)
- , boost::ref(m_dht), _1));
+ for (std::vector >::const_iterator i = nodes.begin()
+ , end(nodes.end()); i != end; ++i)
+ {
+ add_dht_node_name(*i);
+ }
}
#endif
@@ -5413,16 +5418,27 @@ retry:
INVARIANT_CHECK;
stop_dht();
+
+ // postpone starting the DHT if we're still resolving the DHT router
+ if (m_outstanding_router_lookups > 0) return;
+
m_dht = boost::make_shared(static_cast(this)
, boost::ref(m_udp_socket), boost::cref(m_dht_settings)
, boost::ref(m_stats_counters), &startup_state);
- for (std::list::iterator i = m_dht_router_nodes.begin()
+ for (std::vector::iterator i = m_dht_router_nodes.begin()
, end(m_dht_router_nodes.end()); i != end; ++i)
{
m_dht->add_router_node(*i);
}
+ for (std::vector::iterator i = m_dht_nodes.begin()
+ , end(m_dht_nodes.end()); i != end; ++i)
+ {
+ m_dht->add_node(*i);
+ }
+ m_dht_nodes.clear();
+
m_dht->start(startup_state, boost::bind(&on_bootstrap, boost::ref(m_alerts)));
m_udp_socket.subscribe(m_dht.get());
@@ -5451,7 +5467,35 @@ retry:
void session_impl::add_dht_node_name(std::pair const& node)
{
- if (m_dht) m_dht->add_node(node);
+#if defined TORRENT_ASIO_DEBUGGING
+ add_outstanding_async("session_impl::on_dht_name_lookup");
+#endif
+ m_host_resolver.async_resolve(node.first, resolver_interface::abort_on_shutdown
+ , boost::bind(&session_impl::on_dht_name_lookup
+ , this, _1, _2, node.second));
+ }
+
+ void session_impl::on_dht_name_lookup(error_code const& e
+ , std::vector const& addresses, int port)
+ {
+#if defined TORRENT_ASIO_DEBUGGING
+ complete_async("session_impl::on_dht_name_lookup");
+#endif
+
+ if (e)
+ {
+ if (m_alerts.should_post())
+ m_alerts.emplace_alert(
+ dht_error_alert::hostname_lookup, e);
+ return;
+ }
+
+ for (std::vector::const_iterator i = addresses.begin()
+ , end(addresses.end()); i != end; ++i)
+ {
+ udp::endpoint ep(*i, port);
+ add_dht_node(ep);
+ }
}
void session_impl::add_dht_router(std::pair const& node)
@@ -5459,6 +5503,7 @@ retry:
#if defined TORRENT_ASIO_DEBUGGING
add_outstanding_async("session_impl::on_dht_router_name_lookup");
#endif
+ ++m_outstanding_router_lookups;
m_host_resolver.async_resolve(node.first, resolver_interface::abort_on_shutdown
, boost::bind(&session_impl::on_dht_router_name_lookup
, this, _1, _2, node.second));
@@ -5470,11 +5515,15 @@ retry:
#if defined TORRENT_ASIO_DEBUGGING
complete_async("session_impl::on_dht_router_name_lookup");
#endif
+ --m_outstanding_router_lookups;
+
if (e)
{
if (m_alerts.should_post())
m_alerts.emplace_alert(
dht_error_alert::hostname_lookup, e);
+
+ if (m_outstanding_router_lookups == 0) update_dht();
return;
}
@@ -5487,6 +5536,8 @@ retry:
if (m_dht) m_dht->add_router_node(ep);
m_dht_router_nodes.push_back(ep);
}
+
+ if (m_outstanding_router_lookups == 0) update_dht();
}
// callback for dht_immutable_get