fix IPv6 tracker support by performing the second announce in more cases

This commit is contained in:
arvidn 2017-08-19 16:49:09 +02:00 committed by Arvid Norberg
parent 73e898e38e
commit fe37884bc6
4 changed files with 53 additions and 11 deletions

View File

@ -1,3 +1,4 @@
* fix IPv6 tracker support by performing the second announce in more cases
* fix utf-8 encoding check in torrent parser
* fix infinite loop when parsing maliciously crafted torrents
* fix invalid read in parse_int in bdecoder

View File

@ -101,6 +101,7 @@ namespace libtorrent
, send_stats(true)
, private_torrent(false)
, triggered_manually(false)
, second_announce(false)
#ifdef TORRENT_USE_OPENSSL
, ssl_ctx(0)
#endif
@ -168,6 +169,11 @@ namespace libtorrent
// scrape_tracker() or force_reannounce()
bool triggered_manually;
// this is set when announcing to the next address family. There are only
// two address families now, so when this is set, we won't trigger another
// automatic announce
bool second_announce;
#ifdef TORRENT_USE_OPENSSL
boost::asio::ssl::context* ssl_ctx;
#endif

View File

@ -287,9 +287,8 @@ void on_alert_notify(lt::session* ses)
});
}
// this test makes sure that a tracker whose host name resolves to both IPv6 and
// IPv4 addresses will be announced to twice, once for each address family
TORRENT_TEST(ipv6_support)
void test_ipv6_support(char const* listen_interfaces
, int const expect_v4, int const expect_v6)
{
using sim::asio::ip::address_v4;
sim_config network_cfg;
@ -335,6 +334,7 @@ TORRENT_TEST(ipv6_support)
asio::io_service ios(sim, { address_v4::from_string("10.0.0.3")
, address_v6::from_string("ffff::1337") });
lt::settings_pack sett = settings();
sett.set_str(settings_pack::listen_interfaces, listen_interfaces);
std::unique_ptr<lt::session> ses(new lt::session(sett, ios));
ses->set_alert_notify(std::bind(&on_alert_notify, ses.get()));
@ -370,9 +370,46 @@ TORRENT_TEST(ipv6_support)
sim.run();
}
TEST_EQUAL(v4_announces, expect_v4);
TEST_EQUAL(v6_announces, expect_v6);
}
// this test makes sure that a tracker whose host name resolves to both IPv6 and
// IPv4 addresses will be announced to twice, once for each address family
TORRENT_TEST(ipv6_support)
{
// 2 because there's one announce on startup and one when shutting down
TEST_EQUAL(v4_announces, 2);
TEST_EQUAL(v6_announces, 2);
test_ipv6_support("0.0.0.0:6881", 2, 2);
}
TORRENT_TEST(ipv6_support_bind_v4_v6_any)
{
test_ipv6_support("0.0.0.0:6881,[::0]:6881", 2, 2);
}
TORRENT_TEST(ipv6_support_bind_v6_any)
{
test_ipv6_support("[::0]:6881", 0, 2);
}
TORRENT_TEST(ipv6_support_bind_v4)
{
test_ipv6_support("10.0.0.3:6881", 2, 0);
}
TORRENT_TEST(ipv6_support_bind_v6)
{
test_ipv6_support("[ffff::1337]:6881", 0, 2);
}
TORRENT_TEST(ipv6_support_bind_v4_v6)
{
test_ipv6_support("10.0.0.3:6881,[ffff::1337]:6881", 2, 2);
}
TORRENT_TEST(ipv6_support_bind_v6_v4)
{
test_ipv6_support("[ffff::1337]:6881,10.0.0.3:6881", 2, 2);
}
// this runs a simulation of a torrent with tracker(s), making sure the request

View File

@ -3641,15 +3641,12 @@ namespace {
// when talking to the tracker. If there is a matching interface
// type in the tracker IP list, make another tracker request
// using that interface
// in order to avoid triggering this case over and over, don't
// do it if the bind IP for the tracker request that just completed
// matches one of the listen interfaces, since that means this
// announce was the second one
// in order to avoid triggering this case over and over, check whether
// this announce was itself triggered by this logic (second_announce)
if (((!is_any(m_ses.get_ipv6_interface().address()) && tracker_ip.is_v4())
|| (!is_any(m_ses.get_ipv4_interface().address()) && tracker_ip.is_v6()))
&& r.bind_ip != m_ses.get_ipv4_interface().address()
&& r.bind_ip != m_ses.get_ipv6_interface().address())
&& !r.second_announce)
{
std::list<address>::const_iterator i = std::find_if(tracker_ips.begin()
, tracker_ips.end(), boost::bind(&address::is_v4, _1) != tracker_ip.is_v4());
@ -3667,6 +3664,7 @@ namespace {
tracker_request req = r;
req.private_torrent = m_torrent_file->priv();
req.second_announce = true;
// tell the tracker to bind to the opposite protocol type
req.bind_ip = tracker_ip.is_v4()