Add support for Magnet Links

This commit is contained in:
Emil Axelsson
2017-11-07 00:00:26 +01:00
parent 3d8c7ad0a4
commit 8da01993cd
5 changed files with 70 additions and 17 deletions

View File

@@ -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)

View File

@@ -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<std::string>(KeyTorrentFile);
_identifier = dict.value<std::string>(KeyIdentifier);
_magnetLink = dict.value<std::string>(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;

View File

@@ -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;
};

View File

@@ -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<libtorrent::alert*> 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<lt::torrent_finished_alert>(a)) {
LINFO(a->message());
}
if (lt::alert_cast<lt::torrent_error_alert>(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<libtorrent::torrent_info>(torrentFile, ec, 0);
_session->add_torrent(p, ec);
}
std::vector<libtorrent::torrent_handle> 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) {

View File

@@ -27,6 +27,7 @@
#include <string>
#include <memory>
#include <thread>
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<libtorrent::session> _session;
std::thread _torrentThread;
};
} // namespace openspace