From 8da01993cd0cd5f6bc0f60cb1d9d8a0f1bcd149b Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Tue, 7 Nov 2017 00:00:26 +0100 Subject: [PATCH] Add support for Magnet Links --- assets/missions/newhorizons/spice/spice.asset | 3 +- modules/sync/syncs/torrentsynchronization.cpp | 37 ++++++++++++++---- modules/sync/syncs/torrentsynchronization.h | 4 +- modules/sync/torrentclient.cpp | 38 ++++++++++++++++--- modules/sync/torrentclient.h | 5 ++- 5 files changed, 70 insertions(+), 17 deletions(-) diff --git a/assets/missions/newhorizons/spice/spice.asset b/assets/missions/newhorizons/spice/spice.asset index 60eb057390..e02942a3d6 100644 --- a/assets/missions/newhorizons/spice/spice.asset +++ b/assets/missions/newhorizons/spice/spice.asset @@ -2,7 +2,8 @@ local kernelsPath = asset.syncedResource({ Type = "TorrentSynchronization", - TorrentFile = asset.localResource("new_horizons_kernels.torrent") + Identifier = "new_horizons", + Magnet = "magnet:?xt=urn:btih:4af38bdd42c5b29a0ef1ce4ab274cd91c017b8cc&dn=new_horizons" }) --AssetHelper.registerSpiceKernels(asset, kernels) \ No newline at end of file diff --git a/modules/sync/syncs/torrentsynchronization.cpp b/modules/sync/syncs/torrentsynchronization.cpp index 570f59bef0..790d89c2bc 100644 --- a/modules/sync/syncs/torrentsynchronization.cpp +++ b/modules/sync/syncs/torrentsynchronization.cpp @@ -37,8 +37,8 @@ namespace { const char* _loggerCat = "TorrentSynchronization"; - - const char* KeyTorrentFile = "TorrentFile"; + const char* KeyIdentifier = "Identifier"; + const char* KeyMagnet = "Magnet"; } namespace openspace { @@ -52,7 +52,8 @@ TorrentSynchronization::TorrentSynchronization(const ghoul::Dictionary& dict) "TorrentSynchroniztion" ); - _torrentFilePath = dict.value(KeyTorrentFile); + _identifier = dict.value(KeyIdentifier); + _magnetLink = dict.value(KeyMagnet); // Configure synchronization based on global settings in SyncModule // TODO: For testability and decreaing deps, make it possible to inject this instead. @@ -69,31 +70,51 @@ documentation::Documentation TorrentSynchronization::Documentation() { "torrent_synchronization", { { - KeyTorrentFile, + KeyIdentifier, new StringVerifier, Optional::No, - "An absolute path to a torrent file" + "A unique identifier for this torrent" }, + { + KeyMagnet, + new StringVerifier, + Optional::No, + "A magnet link identifying the torrent" + } } }; } +std::string TorrentSynchronization::uniformResourceName() const { + size_t begin = _magnetLink.find("=urn") + 1; + size_t end = _magnetLink.find('&', begin); + std::string xs = _magnetLink.substr(begin, end == std::string::npos ? end : (end - begin)); + std::transform(xs.begin(), xs.end(), xs.begin(), [](char x) { + if (x == ':') return '.'; + return x; + }); + return xs; +} + std::string TorrentSynchronization::directory() { ghoul::filesystem::Directory d( _synchronizationRoot + ghoul::filesystem::FileSystem::PathSeparator + "torrent" + ghoul::filesystem::FileSystem::PathSeparator + - "test" + _identifier + + ghoul::filesystem::FileSystem::PathSeparator + + uniformResourceName() ); return FileSys.absPath(d); } void TorrentSynchronization::synchronize() { - _torrentClient->addTorrent(_torrentFilePath, directory()); - + _torrentClient->addMagnetLink(_magnetLink, directory()); + bool hasSyncFile(); + void createSyncFile(); resolve(); return; diff --git a/modules/sync/syncs/torrentsynchronization.h b/modules/sync/syncs/torrentsynchronization.h index f37555e6a7..1a5c3fc515 100644 --- a/modules/sync/syncs/torrentsynchronization.h +++ b/modules/sync/syncs/torrentsynchronization.h @@ -48,7 +48,9 @@ public: void synchronize() override; private: - std::string _torrentFilePath; + std::string uniformResourceName() const; + std::string _identifier; + std::string _magnetLink; std::string _synchronizationRoot; TorrentClient* _torrentClient; }; diff --git a/modules/sync/torrentclient.cpp b/modules/sync/torrentclient.cpp index f4e101869b..046cd5b75a 100644 --- a/modules/sync/torrentclient.cpp +++ b/modules/sync/torrentclient.cpp @@ -71,15 +71,32 @@ void TorrentClient::initialize() { libtorrent::error_code ec; _session->listen_on(std::make_pair(20280, 20290), ec); _session->start_upnp(); + + _torrentThread = std::thread([this]() { + while (true) { + std::vector alerts; + _session->pop_alerts(&alerts); + + for (lt::alert const* a : alerts) { + LINFO(a->message()); + // if we receive the finished alert or an error, we're done + if (lt::alert_cast(a)) { + LINFO(a->message()); + } + if (lt::alert_cast(a)) { + LINFO(a->message()); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + }); } - -int TorrentClient::addTorrent(std::string torrentFile, std::string destination) { +int TorrentClient::addTorrentFile(std::string torrentFile, std::string destination) { if (!_session) { LERROR("Torrent session not initialized when adding torrent"); return -1; } - libtorrent::error_code ec; libtorrent::add_torrent_params p; @@ -87,11 +104,20 @@ int TorrentClient::addTorrent(std::string torrentFile, std::string destination) p.ti = std::make_shared(torrentFile, ec, 0); _session->add_torrent(p, ec); +} - std::vector handles = _session->get_torrents(); - libtorrent::torrent_status s = handles[0].status(); +int TorrentClient::addMagnetLink(std::string magnetLink, std::string destination) { + if (!_session) { + LERROR("Torrent session not initialized when adding torrent"); + return -1; + } + libtorrent::error_code ec; + libtorrent::add_torrent_params p; - LINFO("Torrent: " << s.total_wanted_done << " out of " << s.total_wanted); + p.save_path = destination; + p.url = magnetLink; + + _session->add_torrent(p, ec); } void TorrentClient::removeTorrent(int id) { diff --git a/modules/sync/torrentclient.h b/modules/sync/torrentclient.h index aee9020baf..f448827f7b 100644 --- a/modules/sync/torrentclient.h +++ b/modules/sync/torrentclient.h @@ -27,6 +27,7 @@ #include #include +#include namespace libtorrent { class session; @@ -44,10 +45,12 @@ public: TorrentClient(); ~TorrentClient(); void initialize(); - int addTorrent(std::string torrentFile, std::string destination); + int addTorrentFile(std::string torrentFile, std::string destination); + int addMagnetLink(std::string magnetLink, std::string destination); void removeTorrent(int id); private: std::unique_ptr _session; + std::thread _torrentThread; }; } // namespace openspace