fix issue where trackers from magnet links were not included in create_torrent()

This commit is contained in:
Arvid Norberg 2019-06-29 21:55:56 +02:00 committed by Arvid Norberg
parent 462a288bdf
commit d113816ae6
7 changed files with 83 additions and 15 deletions

View File

@ -1,3 +1,4 @@
* fix issue where trackers from magnet links were not included in create_torrent()
* make peer_info::client a byte array in python binding
* pick contiguous pieces from peers with high download rate
* fix error handling of moving storage to a drive letter that isn't mounted

View File

@ -234,6 +234,15 @@ void bind_torrent_info()
.def_readwrite("size", &file_slice::size)
;
enum_<announce_entry::tracker_source>("tracker_source")
.value("source_torrent", announce_entry::source_torrent)
.value("source_client", announce_entry::source_client)
.value("source_magnet_link", announce_entry::source_magnet_link)
.value("source_tex", announce_entry::source_tex)
;
using add_tracker1 = void (torrent_info::*)(std::string const&, int, announce_entry::tracker_source);
class_<torrent_info, std::shared_ptr<torrent_info>>("torrent_info", no_init)
.def(init<sha1_hash const&>(arg("info_hash")))
.def("__init__", make_constructor(&bencoded_constructor0))
@ -245,7 +254,7 @@ void bind_torrent_info()
.def(init<std::wstring>((arg("file"))))
#endif
.def("add_tracker", &torrent_info::add_tracker, arg("url"))
.def("add_tracker", (add_tracker1)&torrent_info::add_tracker, arg("url"), arg("tier") = 0, arg("source") = announce_entry::source_client)
.def("add_url_seed", &torrent_info::add_url_seed)
.def("add_http_seed", &torrent_info::add_http_seed)
.def("web_seeds", get_web_seeds)
@ -339,13 +348,6 @@ void bind_torrent_info()
.def("trim", &announce_entry::trim)
;
enum_<announce_entry::tracker_source>("tracker_source")
.value("source_torrent", announce_entry::source_torrent)
.value("source_client", announce_entry::source_client)
.value("source_magnet_link", announce_entry::source_magnet_link)
.value("source_tex", announce_entry::source_tex)
;
implicitly_convertible<std::shared_ptr<torrent_info>, std::shared_ptr<const torrent_info>>();
boost::python::register_ptr_to_python<std::shared_ptr<const torrent_info>>();
}

View File

@ -831,8 +831,7 @@ namespace aux {
// If the torrent doesn't have metadata, the pointer will not be
// initialized (i.e. a nullptr). The torrent may be in a state
// without metadata only if it was started without a .torrent file, e.g.
// by using the libtorrent extension of just supplying a tracker and
// info-hash.
// by being added by magnet link
std::shared_ptr<const torrent_info> torrent_file() const;
#if TORRENT_ABI_VERSION == 1

View File

@ -51,10 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/sha1_hash.hpp"
#include "libtorrent/file_storage.hpp"
#include "libtorrent/aux_/vector.hpp"
#if TORRENT_COMPLETE_TYPES_REQUIRED
#include "libtorrent/announce_entry.hpp"
#endif
namespace libtorrent {
@ -267,6 +264,8 @@ namespace libtorrent {
// lower tier will always be tried before the one with higher tier
// number. For more information, see announce_entry_.
void add_tracker(std::string const& url, int tier = 0);
void add_tracker(std::string const& url, int tier
, announce_entry::tracker_source source);
std::vector<announce_entry> const& trackers() const { return m_urls; }
// These two functions are related to `BEP 38`_ (mutable torrents). The

View File

@ -252,6 +252,14 @@ bool is_downloading_state(int const st)
if (!m_torrent_file)
m_torrent_file = (p.ti ? p.ti : std::make_shared<torrent_info>(m_info_hash));
// in case we added the torrent via magnet link, make sure to preserve any
// DHT nodes passed in on the URI in the torrent file itself
if (!m_torrent_file->is_valid())
{
for (auto const& n : p.dht_nodes)
m_torrent_file->add_node(n);
}
// --- WEB SEEDS ---
// if override web seed flag is set, don't load any web seeds from the
@ -274,10 +282,16 @@ bool is_downloading_state(int const st)
// correct URLs to end with a "/" for multi-file torrents
if (multi_file)
ensure_trailing_slash(ws.back().url);
if (!m_torrent_file->is_valid())
m_torrent_file->add_url_seed(ws.back().url);
}
for (auto const& e : p.http_seeds)
{
ws.emplace_back(e, web_seed_entry::http_seed);
if (!m_torrent_file->is_valid())
m_torrent_file->add_http_seed(e);
}
aux::random_shuffle(ws);
for (auto& w : ws) m_web_seeds.emplace_back(std::move(w));
@ -305,6 +319,11 @@ bool is_downloading_state(int const st)
if (!find_tracker(e.url))
{
m_trackers.push_back(e);
// add the tracker to the m_torrent_file here so that the trackers
// will be preserved via create_torrent() when passing in just the
// torrent_info object.
if (!m_torrent_file->is_valid())
m_torrent_file->add_tracker(e.url, e.tier, announce_entry::tracker_source(e.source));
}
}
@ -6067,7 +6086,7 @@ bool is_downloading_state(int const st)
std::shared_ptr<const torrent_info> torrent::get_torrent_copy()
{
if (!m_torrent_file->is_valid()) return std::shared_ptr<const torrent_info>();
if (!m_torrent_file->is_valid()) return {};
return m_torrent_file;
}

View File

@ -1510,6 +1510,12 @@ namespace {
}
void torrent_info::add_tracker(std::string const& url, int const tier)
{
add_tracker(url, tier, announce_entry::source_client);
}
void torrent_info::add_tracker(std::string const& url, int const tier
, announce_entry::tracker_source const source)
{
auto const i = std::find_if(m_urls.begin(), m_urls.end()
, [&url](announce_entry const& ae) { return ae.url == url; });
@ -1517,7 +1523,7 @@ namespace {
announce_entry e(url);
e.tier = std::uint8_t(tier);
e.source = announce_entry::source_client;
e.source = source;
m_urls.push_back(e);
std::sort(m_urls.begin(), m_urls.end()

View File

@ -432,6 +432,48 @@ TORRENT_TEST(trailing_whitespace)
TEST_CHECK(h.is_valid());
}
// These tests don't work because we don't hand out an incomplete torrent_info
// object. To make them work we would either have to set the correct metadata in
// the test, or change the behavior to make `h.torrent_file()` return the
// internal torrent_info object unconditionally
/*
TORRENT_TEST(preserve_trackers)
{
session ses(settings());
error_code ec;
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:abaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&tr=https://test.com/announce", ec);
p.save_path = ".";
torrent_handle h = ses.add_torrent(p);
TEST_CHECK(h.is_valid());
TEST_CHECK(h.torrent_file()->trackers().size() == 1);
TEST_CHECK(h.torrent_file()->trackers().at(0).url == "https://test.com/announce");
}
TORRENT_TEST(preserve_web_seeds)
{
session ses(settings());
error_code ec;
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:abaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&ws=https://test.com/test", ec);
p.save_path = ".";
torrent_handle h = ses.add_torrent(p);
TEST_CHECK(h.is_valid());
TEST_CHECK(h.torrent_file()->web_seeds().size() == 1);
TEST_CHECK(h.torrent_file()->web_seeds().at(0).url == "https://test.com/test");
}
TORRENT_TEST(preserve_dht_nodes)
{
session ses(settings());
error_code ec;
add_torrent_params p = parse_magnet_uri("magnet:?xt=urn:btih:abaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&dht=test:1234", ec);
p.save_path = ".";
torrent_handle h = ses.add_torrent(p);
TEST_CHECK(h.is_valid());
TEST_CHECK(h.torrent_file()->nodes().size() == 1);
TEST_CHECK(h.torrent_file()->nodes().at(0).first == "test");
TEST_CHECK(h.torrent_file()->nodes().at(0).second == 1234);
}
*/
TORRENT_TEST(invalid_tracker_escaping)
{
error_code ec;