add support for IPv6 peers from udp trackers (#1802)
add support for IPv6 peers from udp trackers
This commit is contained in:
parent
08c05b9693
commit
3f90501934
|
@ -1,3 +1,4 @@
|
||||||
|
* add support for IPv6 peers from udp trackers
|
||||||
* correctly URL encode the IPv6 argument to trackers
|
* correctly URL encode the IPv6 argument to trackers
|
||||||
* fix default file pool size on windows
|
* fix default file pool size on windows
|
||||||
* fix bug where settings_pack::file_pool_size setting was not being honored
|
* fix bug where settings_pack::file_pool_size setting was not being honored
|
||||||
|
|
|
@ -598,8 +598,15 @@ namespace libtorrent
|
||||||
resp.min_interval = 60;
|
resp.min_interval = 60;
|
||||||
resp.incomplete = detail::read_int32(buf);
|
resp.incomplete = detail::read_int32(buf);
|
||||||
resp.complete = detail::read_int32(buf);
|
resp.complete = detail::read_int32(buf);
|
||||||
int num_peers = (size - 20) / 6;
|
|
||||||
if ((size - 20) % 6 != 0)
|
std::size_t const ip_stride =
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
m_target.address().is_v6() ? 18 :
|
||||||
|
#endif
|
||||||
|
6;
|
||||||
|
|
||||||
|
int const num_peers = (size - 20) / ip_stride;
|
||||||
|
if ((size - 20) % ip_stride != 0)
|
||||||
{
|
{
|
||||||
fail(error_code(errors::invalid_tracker_response_length));
|
fail(error_code(errors::invalid_tracker_response_length));
|
||||||
return false;
|
return false;
|
||||||
|
@ -619,14 +626,31 @@ namespace libtorrent
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.peers4.reserve(num_peers);
|
#if TORRENT_USE_IPV6
|
||||||
for (int i = 0; i < num_peers; ++i)
|
if (m_target.address().is_v6())
|
||||||
{
|
{
|
||||||
ipv4_peer_entry e;
|
resp.peers6.reserve(std::size_t(num_peers));
|
||||||
memcpy(&e.ip[0], buf, 4);
|
for (int i = 0; i < num_peers; ++i)
|
||||||
buf += 4;
|
{
|
||||||
e.port = detail::read_uint16(buf);
|
ipv6_peer_entry e;
|
||||||
resp.peers4.push_back(e);
|
std::memcpy(&e.ip[0], buf, 16);
|
||||||
|
buf += 16;
|
||||||
|
e.port = detail::read_uint16(buf);
|
||||||
|
resp.peers6.push_back(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
resp.peers4.reserve(std::size_t(num_peers));
|
||||||
|
for (int i = 0; i < num_peers; ++i)
|
||||||
|
{
|
||||||
|
ipv4_peer_entry e;
|
||||||
|
memcpy(&e.ip[0], buf, 4);
|
||||||
|
buf += 4;
|
||||||
|
e.port = detail::read_uint16(buf);
|
||||||
|
resp.peers4.push_back(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<address> ip_list;
|
std::list<address> ip_list;
|
||||||
|
|
|
@ -264,7 +264,7 @@ void save_file(char const* filename, char const* data, int size)
|
||||||
|
|
||||||
bool print_alerts(lt::session& ses, char const* name
|
bool print_alerts(lt::session& ses, char const* name
|
||||||
, bool allow_disconnects, bool allow_no_torrents, bool allow_failed_fastresume
|
, bool allow_disconnects, bool allow_no_torrents, bool allow_failed_fastresume
|
||||||
, bool (*predicate)(libtorrent::alert const*), bool no_output)
|
, boost::function<bool(libtorrent::alert const*)> predicate, bool no_output)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
std::vector<torrent_handle> handles = ses.get_torrents();
|
std::vector<torrent_handle> handles = ses.get_torrents();
|
||||||
|
|
|
@ -75,7 +75,8 @@ EXPORT bool print_alerts(libtorrent::session& ses, char const* name
|
||||||
, bool allow_disconnects = false
|
, bool allow_disconnects = false
|
||||||
, bool allow_no_torrents = false
|
, bool allow_no_torrents = false
|
||||||
, bool allow_failed_fastresume = false
|
, bool allow_failed_fastresume = false
|
||||||
, bool (*)(libtorrent::alert const*) = 0
|
, boost::function<bool(libtorrent::alert const*)> predicate
|
||||||
|
= boost::function<bool(libtorrent::alert const*)>()
|
||||||
, bool no_output = false);
|
, bool no_output = false);
|
||||||
|
|
||||||
EXPORT void wait_for_listen(libtorrent::session& ses, char const* name);
|
EXPORT void wait_for_listen(libtorrent::session& ses, char const* name);
|
||||||
|
|
|
@ -312,17 +312,23 @@ TORRENT_TEST(extract_peer_missing_port)
|
||||||
, errors::invalid_tracker_response, false);
|
, errors::invalid_tracker_response, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(udp_tracker)
|
bool connect_alert(libtorrent::alert const* a, tcp::endpoint& ep)
|
||||||
{
|
{
|
||||||
int http_port = start_web_server();
|
if (peer_connect_alert const* pc = alert_cast<peer_connect_alert>(a))
|
||||||
int udp_port = start_udp_tracker();
|
ep = pc->ip;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_udp_tracker(std::string const& iface, address tracker, tcp::endpoint const& expected_peer)
|
||||||
|
{
|
||||||
|
int const udp_port = start_udp_tracker(tracker);
|
||||||
|
|
||||||
int prev_udp_announces = num_udp_announces();
|
int prev_udp_announces = num_udp_announces();
|
||||||
|
|
||||||
settings_pack pack = settings();
|
settings_pack pack = settings();
|
||||||
pack.set_bool(settings_pack::announce_to_all_trackers, true);
|
pack.set_bool(settings_pack::announce_to_all_trackers, true);
|
||||||
pack.set_bool(settings_pack::announce_to_all_tiers, true);
|
pack.set_bool(settings_pack::announce_to_all_tiers, true);
|
||||||
pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:48875");
|
pack.set_str(settings_pack::listen_interfaces, iface + ":48875");
|
||||||
|
|
||||||
boost::scoped_ptr<lt::session> s(new lt::session(pack));
|
boost::scoped_ptr<lt::session> s(new lt::session(pack));
|
||||||
|
|
||||||
|
@ -334,12 +340,9 @@ TORRENT_TEST(udp_tracker)
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
char tracker_url[200];
|
char tracker_url[200];
|
||||||
snprintf(tracker_url, sizeof(tracker_url), "http://127.0.0.1:%d/announce", http_port);
|
snprintf(tracker_url, sizeof(tracker_url), "udp://%s:%d/announce", iface.c_str(), udp_port);
|
||||||
t->add_tracker(tracker_url, 0);
|
t->add_tracker(tracker_url, 0);
|
||||||
|
|
||||||
snprintf(tracker_url, sizeof(tracker_url), "udp://127.0.0.1:%d/announce", udp_port);
|
|
||||||
t->add_tracker(tracker_url, 1);
|
|
||||||
|
|
||||||
add_torrent_params addp;
|
add_torrent_params addp;
|
||||||
addp.flags &= ~add_torrent_params::flag_paused;
|
addp.flags &= ~add_torrent_params::flag_paused;
|
||||||
addp.flags &= ~add_torrent_params::flag_auto_managed;
|
addp.flags &= ~add_torrent_params::flag_auto_managed;
|
||||||
|
@ -348,9 +351,11 @@ TORRENT_TEST(udp_tracker)
|
||||||
addp.save_path = "tmp1_tracker";
|
addp.save_path = "tmp1_tracker";
|
||||||
torrent_handle h = s->add_torrent(addp);
|
torrent_handle h = s->add_torrent(addp);
|
||||||
|
|
||||||
|
tcp::endpoint peer_ep;
|
||||||
for (int i = 0; i < 50; ++i)
|
for (int i = 0; i < 50; ++i)
|
||||||
{
|
{
|
||||||
print_alerts(*s, "s");
|
print_alerts(*s, "s", false, false, false, boost::bind(&connect_alert, _1, boost::ref(peer_ep)));
|
||||||
|
|
||||||
if (num_udp_announces() == prev_udp_announces + 1)
|
if (num_udp_announces() == prev_udp_announces + 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -370,7 +375,7 @@ TORRENT_TEST(udp_tracker)
|
||||||
|
|
||||||
for (int i = 0; i < 50; ++i)
|
for (int i = 0; i < 50; ++i)
|
||||||
{
|
{
|
||||||
print_alerts(*s, "s", true, true);
|
print_alerts(*s, "s", true, true, false, boost::bind(&connect_alert, _1, boost::ref(peer_ep)));
|
||||||
if (num_udp_announces() == prev_udp_announces + 2)
|
if (num_udp_announces() == prev_udp_announces + 2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -379,6 +384,8 @@ TORRENT_TEST(udp_tracker)
|
||||||
, int(prev_udp_announces) + 1);
|
, int(prev_udp_announces) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CHECK(peer_ep == expected_peer);
|
||||||
|
|
||||||
fprintf(stderr, "destructing session\n");
|
fprintf(stderr, "destructing session\n");
|
||||||
s.reset();
|
s.reset();
|
||||||
fprintf(stderr, "done\n");
|
fprintf(stderr, "done\n");
|
||||||
|
@ -387,6 +394,18 @@ TORRENT_TEST(udp_tracker)
|
||||||
TEST_EQUAL(num_udp_announces(), prev_udp_announces + 2);
|
TEST_EQUAL(num_udp_announces(), prev_udp_announces + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(udp_tracker_v4)
|
||||||
|
{
|
||||||
|
test_udp_tracker("127.0.0.1", address_v4::any(), ep("1.3.3.7", 1337));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
|
TORRENT_TEST(udp_tracker_v6)
|
||||||
|
{
|
||||||
|
test_udp_tracker("[::1]", address_v6::any(), ep("::1.3.3.7", 1337));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TORRENT_TEST(http_peers)
|
TORRENT_TEST(http_peers)
|
||||||
{
|
{
|
||||||
int http_port = start_web_server();
|
int http_port = start_web_server();
|
||||||
|
|
|
@ -120,9 +120,30 @@ struct udp_tracker
|
||||||
detail::write_uint32(1800, ptr); // interval
|
detail::write_uint32(1800, ptr); // interval
|
||||||
detail::write_uint32(1, ptr); // incomplete
|
detail::write_uint32(1, ptr); // incomplete
|
||||||
detail::write_uint32(1, ptr); // complete
|
detail::write_uint32(1, ptr); // complete
|
||||||
// 0 peers
|
// 1 peers
|
||||||
m_socket.send_to(boost::asio::buffer(buffer, 20), *from, 0, e);
|
#if TORRENT_USE_IPV6
|
||||||
if (e) fprintf(stderr, "%s: UDP send_to failed. ERROR: %s\n"
|
if (from->address().is_v6())
|
||||||
|
{
|
||||||
|
detail::write_uint32(0, ptr);
|
||||||
|
detail::write_uint32(0, ptr);
|
||||||
|
detail::write_uint32(0, ptr);
|
||||||
|
detail::write_uint8(1, ptr);
|
||||||
|
detail::write_uint8(3, ptr);
|
||||||
|
detail::write_uint8(3, ptr);
|
||||||
|
detail::write_uint8(7, ptr);
|
||||||
|
detail::write_uint16(1337, ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
detail::write_uint8(1, ptr);
|
||||||
|
detail::write_uint8(3, ptr);
|
||||||
|
detail::write_uint8(3, ptr);
|
||||||
|
detail::write_uint8(7, ptr);
|
||||||
|
detail::write_uint16(1337, ptr);
|
||||||
|
}
|
||||||
|
m_socket.send_to(boost::asio::buffer(buffer, ptr - buffer), *from, 0, e);
|
||||||
|
if (e) std::printf("%s: UDP send_to failed. ERROR: %s\n"
|
||||||
, time_now_string(), e.message().c_str());
|
, time_now_string(), e.message().c_str());
|
||||||
else fprintf(stderr, "%s: UDP sent response to: %s\n"
|
else fprintf(stderr, "%s: UDP sent response to: %s\n"
|
||||||
, time_now_string(), print_endpoint(*from).c_str());
|
, time_now_string(), print_endpoint(*from).c_str());
|
||||||
|
@ -142,21 +163,21 @@ struct udp_tracker
|
||||||
, boost::bind(&udp_tracker::on_udp_receive, this, _1, _2, from, buffer, size));
|
, boost::bind(&udp_tracker::on_udp_receive, this, _1, _2, from, buffer, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
udp_tracker()
|
udp_tracker(address iface)
|
||||||
: m_udp_announces(0)
|
: m_udp_announces(0)
|
||||||
, m_socket(m_ios)
|
, m_socket(m_ios)
|
||||||
, m_port(0)
|
, m_port(0)
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
m_socket.open(udp::v4(), ec);
|
m_socket.open(iface.is_v4() ? udp::v4() : udp::v6(), ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "UDP Error opening listen UDP tracker socket: %s\n", ec.message().c_str());
|
fprintf(stderr, "UDP Error opening listen UDP tracker socket: %s\n", ec.message().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_socket.bind(udp::endpoint(address_v4::any(), 0), ec);
|
m_socket.bind(udp::endpoint(iface, 0), ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "UDP Error binding UDP tracker socket to port 0: %s\n", ec.message().c_str());
|
fprintf(stderr, "UDP Error binding UDP tracker socket to port 0: %s\n", ec.message().c_str());
|
||||||
|
@ -176,6 +197,7 @@ struct udp_tracker
|
||||||
|
|
||||||
void stop()
|
void stop()
|
||||||
{
|
{
|
||||||
|
std::printf("%s: UDP tracker, stop\n", time_now_string());
|
||||||
m_abort = true;
|
m_abort = true;
|
||||||
m_socket.cancel();
|
m_socket.cancel();
|
||||||
m_socket.close();
|
m_socket.close();
|
||||||
|
@ -222,9 +244,9 @@ struct udp_tracker
|
||||||
|
|
||||||
boost::shared_ptr<udp_tracker> g_udp_tracker;
|
boost::shared_ptr<udp_tracker> g_udp_tracker;
|
||||||
|
|
||||||
int start_udp_tracker()
|
int start_udp_tracker(address iface)
|
||||||
{
|
{
|
||||||
g_udp_tracker.reset(new udp_tracker);
|
g_udp_tracker.reset(new udp_tracker(iface));
|
||||||
return g_udp_tracker->port();
|
return g_udp_tracker->port();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test.hpp" // for EXPORT
|
#include "test.hpp" // for EXPORT
|
||||||
|
#include "libtorrent/address.hpp"
|
||||||
|
|
||||||
// returns the port the udp tracker is running on
|
// returns the port the udp tracker is running on
|
||||||
int EXPORT start_udp_tracker();
|
int EXPORT start_udp_tracker(libtorrent::address iface
|
||||||
|
= libtorrent::address_v4::any());
|
||||||
|
|
||||||
// the number of udp tracker announces received
|
// the number of udp tracker announces received
|
||||||
int EXPORT num_udp_announces();
|
int EXPORT num_udp_announces();
|
||||||
|
|
Loading…
Reference in New Issue