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
6 changes: 6 additions & 0 deletions libtransmission/magnet-metainfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,15 @@ std::string tr_magnet_metainfo::magnet() const
return s;
}

std::string tr_magnet_metainfo::magnetLink() const
{
return magnet_link_;
}

bool tr_magnet_metainfo::parseMagnet(std::string_view magnet_link, tr_error** error)
{
magnet_link = tr_strvStrip(magnet_link);
this->setMagnetLink(magnet_link);

if (auto const hash = parseHash(magnet_link); hash)
{
Expand Down
9 changes: 9 additions & 0 deletions libtransmission/magnet-metainfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ class tr_magnet_metainfo
bool parseMagnet(std::string_view magnet_link, tr_error** error = nullptr);

std::string magnet() const;

sweetppro marked this conversation as resolved.
Show resolved Hide resolved
std::string magnetLink() const;

auto const& infoHash() const
{
return info_hash_;
}

auto const& name() const
{
return name_;
Expand Down Expand Up @@ -61,11 +64,17 @@ class tr_magnet_metainfo
{
name_ = name;
}

void setMagnetLink(std::string_view magnet_link)
{
magnet_link_ = magnet_link;
}

protected:
tr_announce_list announce_list_;
std::vector<std::string> webseed_urls_;
tr_sha1_digest_t info_hash_;
std::string info_hash_str_;
std::string name_;
std::string magnet_link_;
sweetppro marked this conversation as resolved.
Show resolved Hide resolved
};
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))
{
auto buf = std::vector<char>{};
if (!tr_loadFile(buf, path))
{
continue;
}
auto const magnet_link = std::string{ std::data(buf), std::size(buf) };
sweetppro marked this conversation as resolved.
Show resolved Hide resolved
tr_ctorSetMetainfoFromMagnetLink(data->ctor, magnet_link.c_str(), nullptr);
}

if (tr_torrent* const tor = tr_torrentNew(data->ctor, nullptr); tor != nullptr)
{
torrents.push_back(tor);
Expand Down
15 changes: 15 additions & 0 deletions libtransmission/torrent-ctor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ 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));

if (std::empty(tor->metainfo_.magnetLink()))
{
tr_error_set(error, EINVAL, "torrent has no magnetlink to save"sv);
return false;
sweetppro marked this conversation as resolved.
Show resolved Hide resolved
}

std::string magnet_link = tor->metainfo_.magnetLink();
return tr_saveFile(filename, std::string_view{ magnet_link }, error);
sweetppro marked this conversation as resolved.
Show resolved Hide resolved
}

/***
****
***/
Expand Down
4 changes: 4 additions & 0 deletions libtransmission/torrent-magnet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ static bool useNewMetainfo(tr_torrent* tor, tr_incomplete_metadata const* m, tr_
{
return false;
}

// remove .magnet file
auto const magnetFilename = tor->magnetFile();
tr_sys_path_remove(magnetFilename.c_str(), nullptr);
sweetppro marked this conversation as resolved.
Show resolved Hide resolved

// 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 @@ -138,6 +138,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
{
Expand Down
29 changes: 24 additions & 5 deletions libtransmission/torrent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -767,17 +767,35 @@ 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 .magent file already, assume the torrent is new
sweetppro marked this conversation as resolved.
Show resolved Hide resolved
auto filename = tor->torrentFile();

// is a magnet link
if (!tor->hasMetadata()) {
filename = tor->magnetFile();
}
sweetppro marked this conversation as resolved.
Show resolved Hide resolved

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 +1584,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->resume_dir, tor->name(), tor->infoHashString(), ".magnet"sv);
tr_torrent_metainfo::removeFile(tor->session->resume_dir, tor->name(), tor->infoHashString(), ".resume"sv);
}

Expand Down
8 changes: 8 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 @@ -462,6 +464,11 @@ struct tr_torrent : public tr_completion::torrent_view
{
return metainfo_.torrentFile(this->session->torrent_dir);
}

[[nodiscard]] auto resumeFile() const
{
return metainfo_.resumeFile(this->session->resume_dir);
}

[[nodiscard]] auto resumeFile() const
{
Expand Down Expand Up @@ -763,4 +770,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);