diff --git a/Jamfile b/Jamfile index 79c3c8beb..b2821e359 100755 --- a/Jamfile +++ b/Jamfile @@ -62,6 +62,7 @@ SOURCES = ut_pex.cpp logger.cpp file_pool.cpp + lsd.cpp ; KADEMLIA_SOURCES = diff --git a/include/Makefile.am b/include/Makefile.am index a55cd97be..0d27a22b6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -19,6 +19,7 @@ libtorrent/identify_client.hpp \ libtorrent/invariant_check.hpp \ libtorrent/io.hpp \ libtorrent/ip_filter.hpp \ +libtorrent/lsd.hpp \ libtorrent/peer.hpp \ libtorrent/peer_connection.hpp \ libtorrent/bt_peer_connection.hpp \ diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index d1a4d9702..8ec94ce2d 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -79,6 +79,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bandwidth_manager.hpp" #include "libtorrent/natpmp.hpp" #include "libtorrent/upnp.hpp" +#include "libtorrent/lsd.hpp" namespace libtorrent { @@ -280,12 +281,15 @@ namespace libtorrent torrent_handle find_torrent_handle(sha1_hash const& info_hash); + void announce_lsd(sha1_hash const& ih); // handles delayed alerts alert_manager m_alerts; // private: + void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); + // this is where all active sockets are stored. // the selector can sleep while there's no activity on // them @@ -395,6 +399,7 @@ namespace libtorrent #endif natpmp m_natpmp; upnp m_upnp; + lsd m_lsd; // the timer used to fire the second_tick deadline_timer m_timer; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 83caf72a0..9a9861cb6 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -575,11 +575,17 @@ namespace libtorrent // country resolution in this torrent bool m_resolve_countries; + // this announce timer is used both + // by Local service discovery and + // by the DHT. + deadline_timer m_announce_timer; + + // this is called once per announce interval + void on_announce(asio::error_code const& e); + #ifndef TORRENT_DISABLE_DHT static void on_dht_announce_response_disp(boost::weak_ptr t , std::vector const& peers); - deadline_timer m_dht_announce_timer; - void on_dht_announce(asio::error_code const& e); void on_dht_announce_response(std::vector const& peers); bool should_announce_dht() const; #endif diff --git a/src/Makefile.am b/src/Makefile.am index 0ba0cc23c..649015b78 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ stat.cpp storage.cpp torrent.cpp torrent_handle.cpp \ torrent_info.cpp tracker_manager.cpp http_connection.cpp \ http_tracker_connection.cpp udp_tracker_connection.cpp \ alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \ -logger.cpp file_pool.cpp ut_pex.cpp \ +logger.cpp file_pool.cpp ut_pex.cpp lsd.cpp \ \ kademlia/closest_nodes.cpp \ kademlia/dht_tracker.cpp \ @@ -47,6 +47,7 @@ $(top_srcdir)/include/libtorrent/identify_client.hpp \ $(top_srcdir)/include/libtorrent/invariant_check.hpp \ $(top_srcdir)/include/libtorrent/io.hpp \ $(top_srcdir)/include/libtorrent/ip_filter.hpp \ +$(top_srcdir)/include/libtorrent/lsd.hpp \ $(top_srcdir)/include/libtorrent/peer.hpp \ $(top_srcdir)/include/libtorrent/peer_connection.hpp \ $(top_srcdir)/include/libtorrent/bt_peer_connection.hpp \ diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 12fa4b674..c967313d5 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -499,6 +499,8 @@ namespace libtorrent { namespace detail , m_upnp(m_io_service, m_listen_interface.address() , m_settings.user_agent , bind(&session_impl::on_port_mapping, this, _1, _2, _3)) + , m_lsd(m_io_service, m_listen_interface.address() + , bind(&session_impl::on_lsd_peer, this, _1, _2)) , m_timer(m_io_service) , m_checker_impl(*this) { @@ -1460,14 +1462,13 @@ namespace libtorrent { namespace detail if (m_listen_socket) m_listen_socket.reset(); - bool new_listen_address = m_listen_interface.address() != new_interface.address(); - m_incoming_connection = false; m_listen_interface = new_interface; open_listen_port(); #ifndef TORRENT_DISABLE_DHT + bool new_listen_address = m_listen_interface.address() != new_interface.address(); if ((new_listen_address || m_dht_same_port) && m_dht) { if (m_dht_same_port) @@ -1479,6 +1480,7 @@ namespace libtorrent { namespace detail { m_natpmp.rebind(new_interface.address()); m_upnp.rebind(new_interface.address()); + m_lsd.rebind(new_interface.address()); } m_natpmp.set_mappings(0, m_dht_settings.service_port); m_upnp.set_mappings(0, m_dht_settings.service_port); @@ -1501,6 +1503,26 @@ namespace libtorrent { namespace detail return m_external_listen_port; } + void session_impl::announce_lsd(sha1_hash const& ih) + { + mutex_t::scoped_lock l(m_mutex); + m_lsd.announce(ih, m_external_listen_port); + } + + void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih) + { + mutex_t::scoped_lock l(m_mutex); + + boost::shared_ptr t = find_torrent(ih).lock(); + if (!t) return; + +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << to_simple_string(second_clock::universal_time()) + << ": added peer from local discovery: " << peer << "\n"; +#endif + t->get_policy().peer_from_tracker(peer, peer_id(0)); + } + void session_impl::on_port_mapping(int tcp_port, int udp_port , std::string const& errmsg) { diff --git a/src/torrent.cpp b/src/torrent.cpp index 8b17a0c3d..fbc9fbff0 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -245,9 +245,7 @@ namespace libtorrent , m_host_resolver(ses.m_io_service) , m_resolving_country(false) , m_resolve_countries(false) -#ifndef TORRENT_DISABLE_DHT - , m_dht_announce_timer(ses.m_io_service) -#endif + , m_announce_timer(ses.m_io_service) , m_policy() , m_ses(ses) , m_checker(checker) @@ -301,14 +299,9 @@ namespace libtorrent m_policy.reset(new policy(this)); init(); -#ifndef TORRENT_DISABLE_DHT - if (should_announce_dht()) - { - m_dht_announce_timer.expires_from_now(seconds(10)); - m_dht_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_dht_announce, this, _1))); - } -#endif + m_announce_timer.expires_from_now(seconds(1)); + m_announce_timer.async_wait(m_ses.m_strand.wrap( + bind(&torrent::on_announce, this, _1))); } torrent::torrent( @@ -337,9 +330,7 @@ namespace libtorrent , m_host_resolver(ses.m_io_service) , m_resolving_country(false) , m_resolve_countries(false) -#ifndef TORRENT_DISABLE_DHT - , m_dht_announce_timer(ses.m_io_service) -#endif + , m_announce_timer(ses.m_io_service) , m_policy() , m_ses(ses) , m_checker(checker) @@ -395,14 +386,9 @@ namespace libtorrent } m_policy.reset(new policy(this)); -#ifndef TORRENT_DISABLE_DHT - if (should_announce_dht()) - { - m_dht_announce_timer.expires_from_now(seconds(10)); - m_dht_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_dht_announce, this, _1))); - } -#endif + m_announce_timer.expires_from_now(seconds(1)); + m_announce_timer.async_wait(m_ses.m_strand.wrap( + bind(&torrent::on_announce, this, _1))); } #ifndef TORRENT_DISABLE_DHT @@ -480,6 +466,32 @@ namespace libtorrent m_net_interface = tcp::endpoint(address::from_string(net_interface), 0); } + void torrent::on_announce(asio::error_code const& e) + { + if (e) return; + + m_announce_timer.expires_from_now(boost::posix_time::minutes(30)); + m_announce_timer.async_wait(m_ses.m_strand.wrap( + bind(&torrent::on_announce, this, _1))); + + // announce with the local discovery service + m_ses.announce_lsd(m_torrent_file.info_hash()); + +#ifndef TORRENT_DISABLE_DHT + if (!m_ses.m_dht) return; + if (should_announce_dht()) + { + // TODO: There should be a way to abort an announce operation on the dht. + // when the torrent is destructed + boost::weak_ptr self(shared_from_this()); + assert(m_ses.m_external_listen_port > 0); + m_ses.m_dht->announce(m_torrent_file.info_hash() + , m_ses.m_external_listen_port + , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); + } +#endif + } + #ifndef TORRENT_DISABLE_DHT void torrent::on_dht_announce_response_disp(boost::weak_ptr t @@ -490,25 +502,6 @@ namespace libtorrent tor->on_dht_announce_response(peers); } - void torrent::on_dht_announce(asio::error_code const& e) - { - if (e) return; - if (should_announce_dht()) - { - m_dht_announce_timer.expires_from_now(boost::posix_time::minutes(30)); - m_dht_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_dht_announce, this, _1))); - } - if (!m_ses.m_dht) return; - // TODO: There should be a way to abort an announce operation on the dht. - // when the torrent is destructed - boost::weak_ptr self(shared_from_this()); - assert(m_ses.m_external_listen_port > 0); - m_ses.m_dht->announce(m_torrent_file.info_hash() - , m_ses.m_external_listen_port - , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); - } - void torrent::on_dht_announce_response(std::vector const& peers) { if (peers.empty()) return; @@ -2170,14 +2163,12 @@ namespace libtorrent m_next_request = second_clock::universal_time() + seconds(delay); #ifndef TORRENT_DISABLE_DHT - // only start the dht announce unless we already are already running - // the announce timer (a positive expiration time indicates - // that it's running) - if (m_dht_announce_timer.expires_from_now().is_negative() && should_announce_dht()) + // only start the announce if we want to announce with the dht + if (should_announce_dht()) { - m_dht_announce_timer.expires_from_now(boost::posix_time::seconds(1)); - m_dht_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_dht_announce, this, _1))); + m_announce_timer.expires_from_now(boost::posix_time::seconds(1)); + m_announce_timer.async_wait(m_ses.m_strand.wrap( + bind(&torrent::on_announce, this, _1))); } #endif