simplify the local service discovery logic to only deal with a single network. Instantiate LSD once per listen_socket_t instead of just once
This commit is contained in:
parent
819eea722b
commit
2c8cf4834b
|
@ -237,6 +237,8 @@ namespace aux {
|
||||||
std::shared_ptr<natpmp> natpmp_mapper;
|
std::shared_ptr<natpmp> natpmp_mapper;
|
||||||
std::shared_ptr<upnp> upnp_mapper;
|
std::shared_ptr<upnp> upnp_mapper;
|
||||||
|
|
||||||
|
std::shared_ptr<struct lsd> lsd;
|
||||||
|
|
||||||
// set to true when we receive an incoming connection from this listen
|
// set to true when we receive an incoming connection from this listen
|
||||||
// socket
|
// socket
|
||||||
bool incoming_connection = false;
|
bool incoming_connection = false;
|
||||||
|
@ -751,7 +753,7 @@ namespace aux {
|
||||||
bool verify_bound_address(address const& addr, bool utp
|
bool verify_bound_address(address const& addr, bool utp
|
||||||
, error_code& ec) override;
|
, error_code& ec) override;
|
||||||
|
|
||||||
bool has_lsd() const override { return m_lsd.get() != nullptr; }
|
bool has_lsd() const override;
|
||||||
|
|
||||||
std::vector<block_info>& block_info_storage() override { return m_block_info_storage; }
|
std::vector<block_info>& block_info_storage() override { return m_block_info_storage; }
|
||||||
|
|
||||||
|
@ -1195,8 +1197,6 @@ namespace aux {
|
||||||
// this is deducted from the connect speed
|
// this is deducted from the connect speed
|
||||||
int m_boost_connections = 0;
|
int m_boost_connections = 0;
|
||||||
|
|
||||||
std::shared_ptr<lsd> m_lsd;
|
|
||||||
|
|
||||||
#if TORRENT_ABI_VERSION == 1
|
#if TORRENT_ABI_VERSION == 1
|
||||||
struct work_thread_t
|
struct work_thread_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace libtorrent {
|
||||||
|
|
||||||
struct lsd : std::enable_shared_from_this<lsd>
|
struct lsd : std::enable_shared_from_this<lsd>
|
||||||
{
|
{
|
||||||
lsd(io_service& ios, aux::lsd_callback& cb);
|
lsd(io_service& ios, aux::lsd_callback& cb
|
||||||
|
, address const& listen_address, address const& netmask);
|
||||||
~lsd();
|
~lsd();
|
||||||
|
|
||||||
void start(error_code& ec);
|
void start(error_code& ec);
|
||||||
|
@ -55,18 +56,18 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<lsd> self() { return shared_from_this(); }
|
std::shared_ptr<lsd> self() { return shared_from_this(); }
|
||||||
|
|
||||||
void announce_impl(sha1_hash const& ih, int listen_port
|
void announce_impl(sha1_hash const& ih, int listen_port, int retry_count);
|
||||||
, int retry_count);
|
|
||||||
void resend_announce(error_code const& e, sha1_hash const& ih
|
void resend_announce(error_code const& e, sha1_hash const& ih
|
||||||
, int listen_port, int retry_count);
|
, int listen_port, int retry_count);
|
||||||
void on_announce(udp::endpoint const& from, span<char const> buffer);
|
void on_announce(error_code const& ec);
|
||||||
|
|
||||||
aux::lsd_callback& m_callback;
|
aux::lsd_callback& m_callback;
|
||||||
|
|
||||||
// the udp socket used to send and receive
|
address m_listen_address;
|
||||||
// multicast messages on
|
address m_netmask;
|
||||||
broadcast_socket m_socket;
|
|
||||||
broadcast_socket m_socket6;
|
udp::socket m_socket;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
bool should_log() const;
|
bool should_log() const;
|
||||||
void debug_log(char const* fmt, ...) const TORRENT_FORMAT(2, 3);
|
void debug_log(char const* fmt, ...) const TORRENT_FORMAT(2, 3);
|
||||||
|
@ -84,7 +85,6 @@ private:
|
||||||
int m_cookie;
|
int m_cookie;
|
||||||
|
|
||||||
bool m_disabled = false;
|
bool m_disabled = false;
|
||||||
bool m_disabled6 = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
129
src/lsd.cpp
129
src/lsd.cpp
|
@ -43,6 +43,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/debug.hpp"
|
#include "libtorrent/debug.hpp"
|
||||||
#include "libtorrent/hex.hpp" // to_hex, from_hex
|
#include "libtorrent/hex.hpp" // to_hex, from_hex
|
||||||
#include "libtorrent/aux_/numeric_cast.hpp"
|
#include "libtorrent/aux_/numeric_cast.hpp"
|
||||||
|
#include "libtorrent/enum_net.hpp"
|
||||||
|
|
||||||
|
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||||
|
#include <boost/asio/ip/multicast.hpp>
|
||||||
|
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
@ -66,10 +71,12 @@ int render_lsd_packet(char* dst, int const len, int const listen_port
|
||||||
|
|
||||||
static error_code dummy;
|
static error_code dummy;
|
||||||
|
|
||||||
lsd::lsd(io_service& ios, aux::lsd_callback& cb)
|
lsd::lsd(io_service& ios, aux::lsd_callback& cb
|
||||||
|
, address const& listen_address, address const& netmask)
|
||||||
: m_callback(cb)
|
: m_callback(cb)
|
||||||
, m_socket(udp::endpoint(make_address_v4("239.192.152.143", dummy), 6771))
|
, m_listen_address(listen_address)
|
||||||
, m_socket6(udp::endpoint(make_address_v6("ff15::efc0:988f", dummy), 6771))
|
, m_netmask(netmask)
|
||||||
|
, m_socket(ios)
|
||||||
, m_broadcast_timer(ios)
|
, m_broadcast_timer(ios)
|
||||||
, m_cookie((random(0x7fffffff) ^ std::uintptr_t(this)) & 0x7fffffff)
|
, m_cookie((random(0x7fffffff) ^ std::uintptr_t(this)) & 0x7fffffff)
|
||||||
{
|
{
|
||||||
|
@ -95,14 +102,39 @@ void lsd::debug_log(char const* fmt, ...) const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
address const lsd_multicast_addr4 = make_address_v4("239.192.152.143");
|
||||||
|
address const lsd_multicast_addr6 = make_address_v6("ff15::efc0:988f");
|
||||||
|
int const lsd_port = 6771;
|
||||||
|
}
|
||||||
|
|
||||||
void lsd::start(error_code& ec)
|
void lsd::start(error_code& ec)
|
||||||
{
|
{
|
||||||
m_socket.open(std::bind(&lsd::on_announce, self(), _1, _2)
|
using namespace boost::asio::ip::multicast;
|
||||||
, lt::get_io_service(m_broadcast_timer), ec);
|
bool const v4 = m_listen_address.is_v4();
|
||||||
|
m_socket.open(v4 ? udp::v4() : udp::v6(), ec);
|
||||||
if (ec) return;
|
if (ec) return;
|
||||||
|
|
||||||
m_socket6.open(std::bind(&lsd::on_announce, self(), _1, _2)
|
m_socket.set_option(udp::socket::reuse_address(true), ec);
|
||||||
, lt::get_io_service(m_broadcast_timer), ec);
|
if (ec) return;
|
||||||
|
|
||||||
|
m_socket.bind(udp::endpoint(address_v4::any(), lsd_port), ec);
|
||||||
|
if (ec) return;
|
||||||
|
m_socket.set_option(join_group(v4 ? lsd_multicast_addr4 : lsd_multicast_addr6), ec);
|
||||||
|
if (ec) return;
|
||||||
|
m_socket.set_option(hops(32), ec);
|
||||||
|
if (ec) return;
|
||||||
|
m_socket.set_option(enable_loopback(true), ec);
|
||||||
|
if (ec) return;
|
||||||
|
if (v4)
|
||||||
|
{
|
||||||
|
m_socket.set_option(outbound_interface(m_listen_address.to_v4()), ec);
|
||||||
|
if (ec) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_OUTSTANDING_ASYNC("lsd::on_announce");
|
||||||
|
m_socket.async_receive(boost::asio::null_buffers{}
|
||||||
|
, std::bind(&lsd::on_announce, self(), _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
lsd::~lsd() = default;
|
lsd::~lsd() = default;
|
||||||
|
@ -115,20 +147,30 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
|
||||||
void lsd::announce_impl(sha1_hash const& ih, int const listen_port
|
void lsd::announce_impl(sha1_hash const& ih, int const listen_port
|
||||||
, int retry_count)
|
, int retry_count)
|
||||||
{
|
{
|
||||||
if (m_disabled && m_disabled6) return;
|
if (m_disabled) return;
|
||||||
|
|
||||||
char msg[200];
|
char msg[200];
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
debug_log("==> LSD: ih: %s port: %u\n", aux::to_hex(ih).c_str(), listen_port);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
if (!m_disabled)
|
if (!m_disabled)
|
||||||
{
|
{
|
||||||
|
bool const v4 = m_listen_address.is_v4();
|
||||||
|
char const* v4_address = "239.192.152.143";
|
||||||
|
char const* v6_address = "[ff15::efc0:988f]";
|
||||||
|
|
||||||
int const msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, aux::to_hex(ih).c_str()
|
int const msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, aux::to_hex(ih).c_str()
|
||||||
, m_cookie, "239.192.152.143");
|
, m_cookie, v4 ? v4_address : v6_address);
|
||||||
m_socket.send(msg, msg_len, ec);
|
|
||||||
|
udp::endpoint const to(v4 ? lsd_multicast_addr4 : lsd_multicast_addr6
|
||||||
|
, lsd_port);
|
||||||
|
|
||||||
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
debug_log("==> LSD: ih: %s port: %u [iface: %s]", aux::to_hex(ih).c_str()
|
||||||
|
, listen_port, m_listen_address.to_string().c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_socket.send_to(boost::asio::buffer(msg, static_cast<std::size_t>(msg_len))
|
||||||
|
, to, {}, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
m_disabled = true;
|
m_disabled = true;
|
||||||
|
@ -142,28 +184,10 @@ void lsd::announce_impl(sha1_hash const& ih, int const listen_port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_disabled6)
|
|
||||||
{
|
|
||||||
int const msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, aux::to_hex(ih).c_str()
|
|
||||||
, m_cookie, "[ff15::efc0:988f]");
|
|
||||||
m_socket6.send(msg, msg_len, ec);
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
m_disabled6 = true;
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
|
||||||
if (should_log())
|
|
||||||
{
|
|
||||||
debug_log("*** LSD: failed to send message6: (%d) %s", ec.value()
|
|
||||||
, ec.message().c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++retry_count;
|
++retry_count;
|
||||||
if (retry_count >= 3) return;
|
if (retry_count >= 3) return;
|
||||||
|
|
||||||
if (m_disabled && m_disabled6) return;
|
if (m_disabled) return;
|
||||||
|
|
||||||
ADD_OUTSTANDING_ASYNC("lsd::resend_announce");
|
ADD_OUTSTANDING_ASYNC("lsd::resend_announce");
|
||||||
m_broadcast_timer.expires_from_now(seconds(2 * retry_count), ec);
|
m_broadcast_timer.expires_from_now(seconds(2 * retry_count), ec);
|
||||||
|
@ -180,12 +204,43 @@ void lsd::resend_announce(error_code const& e, sha1_hash const& info_hash
|
||||||
announce_impl(info_hash, listen_port, retry_count);
|
announce_impl(info_hash, listen_port, retry_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lsd::on_announce(udp::endpoint const& from, span<char const> buf)
|
void lsd::on_announce(error_code const& ec)
|
||||||
{
|
{
|
||||||
|
COMPLETE_ASYNC("lsd::on_announce");
|
||||||
|
if (ec) return;
|
||||||
|
|
||||||
|
std::array<char, 1500> buffer;
|
||||||
|
udp::endpoint from;
|
||||||
|
error_code err;
|
||||||
|
int const len = static_cast<int>(m_socket.receive_from(
|
||||||
|
boost::asio::buffer(buffer), from, {}, err));
|
||||||
|
|
||||||
|
ADD_OUTSTANDING_ASYNC("lsd::on_announce");
|
||||||
|
m_socket.async_receive(boost::asio::null_buffers{}
|
||||||
|
, std::bind(&lsd::on_announce, self(), _1));
|
||||||
|
|
||||||
|
if (!match_addr_mask(from.address(), m_listen_address, m_netmask))
|
||||||
|
{
|
||||||
|
// we don't care about this network. Ignore this packet
|
||||||
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
debug_log("<== LSD: receive from out of network: %s"
|
||||||
|
, from.address().to_string().c_str());
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
debug_log("<== LSD: receive error: %s", err.message().c_str());
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
http_parser p;
|
http_parser p;
|
||||||
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
p.incoming(buf, error);
|
p.incoming(span<char const>{buffer.data(), len}, error);
|
||||||
|
|
||||||
if (!p.header_finished() || error)
|
if (!p.header_finished() || error)
|
||||||
{
|
{
|
||||||
|
@ -273,12 +328,10 @@ void lsd::on_announce(udp::endpoint const& from, span<char const> buf)
|
||||||
|
|
||||||
void lsd::close()
|
void lsd::close()
|
||||||
{
|
{
|
||||||
m_socket.close();
|
|
||||||
m_socket6.close();
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
m_socket.close(ec);
|
||||||
m_broadcast_timer.cancel(ec);
|
m_broadcast_timer.cancel(ec);
|
||||||
m_disabled = true;
|
m_disabled = true;
|
||||||
m_disabled6 = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // libtorrent namespace
|
} // libtorrent namespace
|
||||||
|
|
|
@ -2004,6 +2004,8 @@ namespace aux {
|
||||||
remap_ports(remap_natpmp_and_upnp, *s);
|
remap_ports(remap_natpmp_and_upnp, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_lsd();
|
||||||
|
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
open_new_incoming_i2p_connection();
|
open_new_incoming_i2p_connection();
|
||||||
#endif
|
#endif
|
||||||
|
@ -5022,6 +5024,12 @@ namespace aux {
|
||||||
, [&device](std::string const& s) { return s == device; });
|
, [&device](std::string const& s) { return s == device; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool session_impl::has_lsd() const
|
||||||
|
{
|
||||||
|
return std::any_of(m_listen_sockets.begin(), m_listen_sockets.end()
|
||||||
|
, [](std::shared_ptr<listen_socket_t> const& s) { return bool(s->lsd); });
|
||||||
|
}
|
||||||
|
|
||||||
void session_impl::remove_torrent(const torrent_handle& h
|
void session_impl::remove_torrent(const torrent_handle& h
|
||||||
, remove_flags_t const options)
|
, remove_flags_t const options)
|
||||||
{
|
{
|
||||||
|
@ -5425,8 +5433,10 @@ namespace aux {
|
||||||
void session_impl::announce_lsd(sha1_hash const& ih, int port)
|
void session_impl::announce_lsd(sha1_hash const& ih, int port)
|
||||||
{
|
{
|
||||||
// use internal listen port for local peers
|
// use internal listen port for local peers
|
||||||
if (m_lsd)
|
for (auto const& s : m_listen_sockets)
|
||||||
m_lsd->announce(ih, port);
|
{
|
||||||
|
if (s->lsd) s->lsd->announce(ih, port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::on_lsd_peer(tcp::endpoint const& peer, sha1_hash const& ih)
|
void session_impl::on_lsd_peer(tcp::endpoint const& peer, sha1_hash const& ih)
|
||||||
|
@ -6638,13 +6648,20 @@ namespace aux {
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (m_lsd) return;
|
for (auto& s : m_listen_sockets)
|
||||||
|
{
|
||||||
m_lsd = std::make_shared<lsd>(m_io_service, *this);
|
if (s->lsd) continue;
|
||||||
|
s->lsd = std::make_shared<lsd>(m_io_service, *this, s->local_endpoint.address()
|
||||||
|
, s->netmask);
|
||||||
error_code ec;
|
error_code ec;
|
||||||
m_lsd->start(ec);
|
s->lsd->start(ec);
|
||||||
if (ec && m_alerts.should_post<lsd_error_alert>())
|
if (ec)
|
||||||
|
{
|
||||||
|
if (m_alerts.should_post<lsd_error_alert>())
|
||||||
m_alerts.emplace_alert<lsd_error_alert>(ec);
|
m_alerts.emplace_alert<lsd_error_alert>(ec);
|
||||||
|
s->lsd.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::start_natpmp()
|
void session_impl::start_natpmp()
|
||||||
|
@ -6726,9 +6743,12 @@ namespace aux {
|
||||||
|
|
||||||
void session_impl::stop_lsd()
|
void session_impl::stop_lsd()
|
||||||
{
|
{
|
||||||
if (m_lsd)
|
for (auto& s : m_listen_sockets)
|
||||||
m_lsd->close();
|
{
|
||||||
m_lsd.reset();
|
if (!s->lsd) continue;
|
||||||
|
s->lsd->close();
|
||||||
|
s->lsd.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::stop_natpmp()
|
void session_impl::stop_natpmp()
|
||||||
|
|
Loading…
Reference in New Issue