Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for resuming magnet links #2702

Merged
merged 11 commits into from
Feb 24, 2022
1 change: 0 additions & 1 deletion libtransmission/magnet-metainfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down
1 change: 1 addition & 0 deletions libtransmission/magnet-metainfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class tr_magnet_metainfo
{
return info_hash_;
}

auto const& name() const
{
return name_;
Expand Down
16 changes: 14 additions & 2 deletions libtransmission/session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions libtransmission/torrent-ctor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
sweetppro marked this conversation as resolved.
Show resolved Hide resolved
}
return tr_saveFile(filename, magnet, error);
}

/***
****
***/
Expand Down
3 changes: 3 additions & 0 deletions libtransmission/torrent-magnet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
5 changes: 5 additions & 0 deletions libtransmission/torrent-metainfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ struct tr_torrent_metainfo : public tr_magnet_metainfo
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");
Expand Down
25 changes: 20 additions & 5 deletions libtransmission/torrent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
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
{
tor->setLocalError(
tr_strvJoin("Unable to save torrent file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
// 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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
13 changes: 13 additions & 0 deletions libtransmission/torrent.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -463,11 +465,21 @@ struct tr_torrent : public tr_completion::torrent_view
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();
Expand Down Expand Up @@ -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);