support for resuming magnet links (#2702)

* support for resuming magnet links

magnet links are now saved as a text file the `Torrents` folder as `.magnet` files.
This commit is contained in:
SweetPPro 2022-02-24 22:52:29 +01:00 committed by GitHub
parent cc7d1c5f01
commit 943b57979f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 8 deletions

View File

@ -181,7 +181,6 @@ std::string tr_magnet_metainfo::magnet() const
bool tr_magnet_metainfo::parseMagnet(std::string_view magnet_link, tr_error** error)
{
magnet_link = tr_strvStrip(magnet_link);
if (auto const hash = parseHash(magnet_link); hash)
{
return parseMagnet(tr_strvJoin("magnet:?xt=urn:btih:", tr_sha1_to_string(*hash)));

View File

@ -27,6 +27,7 @@ public:
{
return info_hash_;
}
auto const& name() const
{
return name_;

View File

@ -2041,13 +2041,25 @@ static void sessionLoadTorrents(void* vdata)
char const* name = nullptr;
while ((name = tr_sys_dir_read_name(odir, nullptr)) != nullptr)
{
if (!tr_strvEndsWith(name, ".torrent"sv))
if (!tr_strvEndsWith(name, ".torrent"sv) && !tr_strvEndsWith(name, ".magnet"sv))
{
continue;
}
tr_buildBuf(path, dirname_sv, "/", name);
tr_ctorSetMetainfoFromFile(data->ctor, path, nullptr);
// is a magnet link?
if (!tr_ctorSetMetainfoFromFile(data->ctor, path, nullptr))
{
if (auto buf = std::vector<char>{}; tr_loadFile(buf, path))
{
tr_ctorSetMetainfoFromMagnetLink(
data->ctor,
std::string{ std::data(buf), std::size(buf) }.c_str(),
nullptr);
}
}
if (tr_torrent* const tor = tr_torrentNew(data->ctor, nullptr); tor != nullptr)
{
torrents.push_back(tor);

View File

@ -127,6 +127,20 @@ bool tr_ctorSaveContents(tr_ctor const* ctor, std::string const& filename, tr_er
return tr_saveFile(filename, { std::data(ctor->contents), std::size(ctor->contents) }, error);
}
bool tr_ctorSaveMagnetContents(tr_torrent* tor, std::string const& filename, tr_error** error)
{
TR_ASSERT(tor != nullptr);
TR_ASSERT(!std::empty(filename));
auto const magnet = tor->magnet();
if (std::empty(magnet))
{
tr_error_set(error, EINVAL, "torrent has no magnetlink to save"sv);
return false;
}
return tr_saveFile(filename, magnet, error);
}
/***
****
***/

View File

@ -278,6 +278,9 @@ static bool useNewMetainfo(tr_torrent* tor, tr_incomplete_metadata const* m, tr_
return false;
}
// remove .magnet file
tr_sys_path_remove(tor->magnetFile().c_str(), nullptr);
// tor should keep this metainfo
tor->setMetainfo(metainfo);

View File

@ -139,6 +139,11 @@ public:
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".torrent");
}
[[nodiscard]] std::string magnetFile(std::string_view torrent_dir) const
{
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".magnet");
}
[[nodiscard]] std::string resumeFile(std::string_view resume_dir) const
{
return makeFilename(resume_dir, name(), infoHashString(), BasenameFormat::Hash, ".resume");

View File

@ -767,17 +767,31 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
tr_sessionAddTorrent(session, tor);
// if we don't have a local .torrent file already, assume the torrent is new
auto const filename = tor->torrentFile();
// if we don't have a local .torrent or .magnet file already, assume the torrent is new
auto const filename = tor->hasMetadata() ? tor->torrentFile() : tor->magnetFile();
bool const is_new_torrent = !tr_sys_path_exists(filename.c_str(), nullptr);
if (is_new_torrent)
{
tr_error* error = nullptr;
if (!tr_ctorSaveContents(ctor, filename, &error))
if (tor->hasMetadata())
{
tor->setLocalError(
tr_strvJoin("Unable to save torrent file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
if (!tr_ctorSaveContents(ctor, filename, &error))
{
tor->setLocalError(
tr_strvJoin("Unable to save torrent file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
}
}
else
{
// magnet link
if (!tr_ctorSaveMagnetContents(tor, filename, &error))
{
tor->setLocalError(
tr_strvJoin("Unable to save magnet file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
}
}
tr_error_clear(&error);
}
@ -1566,6 +1580,7 @@ static void closeTorrent(void* vtor)
if (tor->isDeleting)
{
tr_torrent_metainfo::removeFile(tor->session->torrent_dir, tor->name(), tor->infoHashString(), ".torrent"sv);
tr_torrent_metainfo::removeFile(tor->session->torrent_dir, tor->name(), tor->infoHashString(), ".magnet"sv);
tr_torrent_metainfo::removeFile(tor->session->resume_dir, tor->name(), tor->infoHashString(), ".resume"sv);
}

View File

@ -53,6 +53,8 @@ void tr_ctorInitTorrentWanted(tr_ctor const* ctor, tr_torrent* tor);
bool tr_ctorSaveContents(tr_ctor const* ctor, std::string const& filename, tr_error** error);
bool tr_ctorSaveMagnetContents(tr_torrent* tor, std::string const& filename, tr_error** error);
std::string_view tr_ctorGetContents(tr_ctor const* ctor);
tr_session* tr_ctorGetSession(tr_ctor const* ctor);
@ -463,11 +465,21 @@ public:
return metainfo_.torrentFile(this->session->torrent_dir);
}
[[nodiscard]] auto magnetFile() const
{
return metainfo_.magnetFile(this->session->torrent_dir);
}
[[nodiscard]] auto resumeFile() const
{
return metainfo_.resumeFile(this->session->resume_dir);
}
[[nodiscard]] auto magnet() const
{
return metainfo_.magnet();
}
[[nodiscard]] auto const& comment() const
{
return metainfo_.comment();
@ -763,4 +775,5 @@ tr_peer_id_t const& tr_torrentGetPeerId(tr_torrent* tor);
tr_torrent_metainfo&& tr_ctorStealMetainfo(tr_ctor* ctor);
bool tr_ctorSetMetainfoFromFile(tr_ctor* ctor, std::string const& filename, tr_error** error);
bool tr_ctorSetMetainfoFromMagnetLink(tr_ctor* ctor, std::string const& filename, tr_error** error);
void tr_ctorSetLabels(tr_ctor* ctor, tr_labels_t&& labels);