mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 11:39:49 -06:00
Remove torrent-based synchronization
This commit is contained in:
@@ -24,8 +24,6 @@
|
||||
|
||||
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
option(OPENSPACE_MODULE_SYNC_USE_LIBTORRENT "Use libtorrent" OFF)
|
||||
|
||||
set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncmodule.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncs/httpsynchronization.h
|
||||
@@ -42,48 +40,4 @@ set(SOURCE_FILES
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
if (OPENSPACE_MODULE_SYNC_USE_LIBTORRENT)
|
||||
set(HEADER_FILES
|
||||
${HEADER_FILES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/torrentclient.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncs/torrentsynchronization.h
|
||||
)
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/torrentclient.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncs/torrentsynchronization.cpp
|
||||
)
|
||||
endif ()
|
||||
|
||||
|
||||
create_new_module("Sync" sync_module ${HEADER_FILES} ${SOURCE_FILES})
|
||||
|
||||
#####
|
||||
# Libtorrent
|
||||
#####
|
||||
|
||||
if (OPENSPACE_MODULE_SYNC_USE_LIBTORRENT)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(LIBTORRENT_encryption OFF CACHE BOOL "Use OpenSSL Encryption" FORCE)
|
||||
set(LIBTORRENT_shared OFF CACHE BOOL "Use Libtorrent as shared library" FORCE)
|
||||
|
||||
include_external_library(
|
||||
${sync_module}
|
||||
torrent-rasterbar
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext/libtorrent
|
||||
)
|
||||
target_include_directories(
|
||||
${sync_module}
|
||||
SYSTEM PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext/libtorrent/include
|
||||
)
|
||||
|
||||
target_compile_definitions(openspace-module-sync PUBLIC SYNC_USE_LIBTORRENT)
|
||||
|
||||
mark_as_advanced(LIBTORRENT_build_examples LIBTORRENT_build_tests
|
||||
LIBTORRENT_deprecated-functions LIBTORRENT_dht LIBTORRENT_encryption
|
||||
LIBTORRENT_exceptions LIBTORRENT_exceptions LIBTORRENT_libiconv
|
||||
LIBTORRENT_logging LIBTORRENT_shared LIBTORRENT_static_runtime
|
||||
)
|
||||
endif () # OPENSPACE_MODULE_SYNC_USE_LIBTORRENT
|
||||
Submodule modules/sync/ext/libtorrent deleted from 22477e7430
@@ -25,7 +25,6 @@
|
||||
#include <modules/sync/syncmodule.h>
|
||||
|
||||
#include <modules/sync/syncs/httpsynchronization.h>
|
||||
#include <modules/sync/syncs/torrentsynchronization.h>
|
||||
#include <modules/sync/syncs/urlsynchronization.h>
|
||||
#include <modules/sync/tasks/syncassettask.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
@@ -87,19 +86,6 @@ void SyncModule::internalInitialize(const ghoul::Dictionary& configuration) {
|
||||
}
|
||||
);
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
fSynchronization->registerClass(
|
||||
"TorrentSynchronization",
|
||||
[this](bool, const ghoul::Dictionary& dictionary) {
|
||||
return new TorrentSynchronization(
|
||||
dictionary,
|
||||
_synchronizationRoot,
|
||||
_torrentClient
|
||||
);
|
||||
}
|
||||
);
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
fSynchronization->registerClass(
|
||||
"UrlSynchronization",
|
||||
[this](bool, const ghoul::Dictionary& dictionary) {
|
||||
@@ -113,17 +99,6 @@ void SyncModule::internalInitialize(const ghoul::Dictionary& configuration) {
|
||||
auto fTask = FactoryManager::ref().factory<Task>();
|
||||
ghoul_assert(fTask, "No task factory existed");
|
||||
fTask->registerClass<SyncAssetTask>("SyncAssetTask");
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
_torrentClient.initialize();
|
||||
global::callback::deinitialize.emplace_back([&]() { _torrentClient.deinitialize(); });
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void SyncModule::internalDeinitialize() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
_torrentClient.deinitialize();
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
std::string SyncModule::synchronizationRoot() const {
|
||||
@@ -140,10 +115,7 @@ std::vector<std::string> SyncModule::httpSynchronizationRepositories() const {
|
||||
|
||||
std::vector<documentation::Documentation> SyncModule::documentations() const {
|
||||
return {
|
||||
HttpSynchronization::Documentation(),
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentSynchronization::Documentation()
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
HttpSynchronization::Documentation()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
#include <modules/sync/torrentclient.h>
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class SyncModule : public OpenSpaceModule {
|
||||
@@ -44,20 +40,12 @@ public:
|
||||
void addHttpSynchronizationRepository(std::string repository);
|
||||
std::vector<std::string> httpSynchronizationRepositories() const;
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentClient& torrentClient();
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
std::vector<documentation::Documentation> documentations() const override;
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary& configuration) override;
|
||||
void internalDeinitialize() override;
|
||||
|
||||
private:
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentClient _torrentClient;
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
std::vector<std::string> _synchronizationRepositories;
|
||||
std::string _synchronizationRoot;
|
||||
};
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/sync/syncs/torrentsynchronization.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyIdentifier = "Identifier";
|
||||
constexpr const char* KeyMagnet = "Magnet";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TorrentSynchronization::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"TorrentSynchronization",
|
||||
"torrent_synchronization",
|
||||
{
|
||||
{
|
||||
KeyIdentifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"A unique identifier for this torrent"
|
||||
},
|
||||
{
|
||||
KeyMagnet,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"A magnet link identifying the torrent"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TorrentSynchronization::TorrentSynchronization(const ghoul::Dictionary& dict,
|
||||
std::string synchronizationRoot,
|
||||
TorrentClient& torrentClient)
|
||||
: ResourceSynchronization(dict)
|
||||
, _synchronizationRoot(std::move(synchronizationRoot))
|
||||
, _torrentClient(torrentClient)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dict,
|
||||
"TorrentSynchronization"
|
||||
);
|
||||
|
||||
_identifier = dict.value<std::string>(KeyIdentifier);
|
||||
_magnetLink = dict.value<std::string>(KeyMagnet);
|
||||
}
|
||||
|
||||
TorrentSynchronization::~TorrentSynchronization() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
std::string TorrentSynchronization::uniformResourceName() const {
|
||||
const size_t begin = _magnetLink.find("=urn") + 1;
|
||||
const 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) { return (x == ':') ? '.' : x; }
|
||||
);
|
||||
return xs;
|
||||
}
|
||||
|
||||
std::string TorrentSynchronization::directory() {
|
||||
ghoul::filesystem::Directory d(
|
||||
_synchronizationRoot +
|
||||
ghoul::filesystem::FileSystem::PathSeparator +
|
||||
"torrent" +
|
||||
ghoul::filesystem::FileSystem::PathSeparator +
|
||||
_identifier +
|
||||
ghoul::filesystem::FileSystem::PathSeparator +
|
||||
uniformResourceName()
|
||||
);
|
||||
|
||||
return FileSys.absPath(d);
|
||||
}
|
||||
|
||||
void TorrentSynchronization::start() {
|
||||
if (_enabled) {
|
||||
return;
|
||||
}
|
||||
begin();
|
||||
|
||||
if (hasSyncFile()) {
|
||||
resolve();
|
||||
}
|
||||
|
||||
_enabled = true;
|
||||
try {
|
||||
_torrentId = _torrentClient.addMagnetLink(
|
||||
_magnetLink,
|
||||
directory(),
|
||||
[this](TorrentClient::TorrentProgress p) {
|
||||
updateTorrentProgress(p);
|
||||
}
|
||||
);
|
||||
} catch (const TorrentError& e) {
|
||||
LERRORC(name(), e.message);
|
||||
if (!isResolved()) {
|
||||
reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentSynchronization::cancel() {
|
||||
if (_enabled) {
|
||||
_torrentClient.removeTorrent(_torrentId);
|
||||
_enabled = false;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentSynchronization::clear() {
|
||||
cancel();
|
||||
// TODO: Remove all files from directory.
|
||||
}
|
||||
|
||||
bool TorrentSynchronization::hasSyncFile() {
|
||||
const std::string& path = directory() + ".ossync";
|
||||
return FileSys.fileExists(path);
|
||||
}
|
||||
|
||||
void TorrentSynchronization::createSyncFile() {
|
||||
const std::string& directoryName = directory();
|
||||
const std::string& filepath = directoryName + ".ossync";
|
||||
|
||||
FileSys.createDirectory(directoryName, ghoul::filesystem::FileSystem::Recursive::Yes);
|
||||
|
||||
std::ofstream syncFile(filepath, std::ofstream::out);
|
||||
syncFile << "Synchronized";
|
||||
syncFile.close();
|
||||
}
|
||||
|
||||
size_t TorrentSynchronization::nSynchronizedBytes() {
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
return _progress.nDownloadedBytes;
|
||||
}
|
||||
|
||||
size_t TorrentSynchronization::nTotalBytes() {
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
return _progress.nTotalBytes;
|
||||
}
|
||||
|
||||
bool TorrentSynchronization::nTotalBytesIsKnown() {
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
return _progress.nTotalBytesKnown;
|
||||
}
|
||||
|
||||
void TorrentSynchronization::updateTorrentProgress(
|
||||
TorrentClient::TorrentProgress progress)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
_progress = progress;
|
||||
if (progress.finished && (state() == State::Syncing)) {
|
||||
createSyncFile();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,77 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SYNC___TORRENTSYNCHRONIZATION___H__
|
||||
#define __OPENSPACE_MODULE_SYNC___TORRENTSYNCHRONIZATION___H__
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
|
||||
#include <openspace/util/resourcesynchronization.h>
|
||||
|
||||
#include <modules/sync/torrentclient.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class TorrentSynchronizationJob;
|
||||
|
||||
class TorrentSynchronization : public ResourceSynchronization {
|
||||
public:
|
||||
TorrentSynchronization(const ghoul::Dictionary& dict, std::string synchronizationRoot,
|
||||
TorrentClient& client);
|
||||
|
||||
virtual ~TorrentSynchronization();
|
||||
|
||||
std::string directory() override;
|
||||
void start() override;
|
||||
void cancel() override;
|
||||
void clear() override;
|
||||
|
||||
size_t nSynchronizedBytes() override;
|
||||
size_t nTotalBytes() override;
|
||||
bool nTotalBytesIsKnown() override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
void updateTorrentProgress(TorrentClient::TorrentProgress p);
|
||||
std::string uniformResourceName() const;
|
||||
bool hasSyncFile();
|
||||
void createSyncFile();
|
||||
|
||||
std::atomic_bool _enabled = false;
|
||||
|
||||
TorrentClient::TorrentId _torrentId = 0;
|
||||
TorrentClient::TorrentProgress _progress;
|
||||
std::mutex _progressMutex;
|
||||
std::string _identifier;
|
||||
std::string _magnetLink;
|
||||
std::string _synchronizationRoot;
|
||||
TorrentClient& _torrentClient;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SYNC___TORRENTSYNCHRONIZATION___H__
|
||||
@@ -1,271 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/sync/torrentclient.h>
|
||||
|
||||
#include <openspace/openspace.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4265)
|
||||
#pragma warning (disable : 4996)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/alert_types.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "TorrentClient";
|
||||
constexpr const std::chrono::milliseconds PollInterval(1000);
|
||||
} // namespace
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
namespace openspace {
|
||||
|
||||
TorrentError::TorrentError(std::string msg)
|
||||
: RuntimeError(std::move(msg), "TorrentClient")
|
||||
{}
|
||||
|
||||
void TorrentClient::initialize() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
libtorrent::settings_pack settings;
|
||||
settings.set_str(
|
||||
libtorrent::settings_pack::user_agent,
|
||||
"OpenSpace/" + std::string(OPENSPACE_VERSION_NUMBER)
|
||||
);
|
||||
|
||||
settings.set_str(
|
||||
libtorrent::settings_pack::listen_interfaces,
|
||||
"0.0.0.0:6881,0.0.0.0:20280,0.0.0.0:20285,0.0.0.0:20290"
|
||||
);
|
||||
settings.set_bool(libtorrent::settings_pack::allow_multiple_connections_per_ip, true);
|
||||
settings.set_bool(libtorrent::settings_pack::enable_upnp, true);
|
||||
//settings.set_bool(libtorrent::settings_pack::ignore_limits_on_local_network, true);
|
||||
settings.set_int(libtorrent::settings_pack::connection_speed, 20);
|
||||
settings.set_int(libtorrent::settings_pack::active_downloads, -1);
|
||||
settings.set_int(libtorrent::settings_pack::active_seeds, -1);
|
||||
settings.set_int(libtorrent::settings_pack::active_limit, 30);
|
||||
|
||||
settings.set_str(
|
||||
libtorrent::settings_pack::dht_bootstrap_nodes,
|
||||
"router.utorrent.com,dht.transmissionbt.com,router.bittorrent.com,\
|
||||
router.bitcomet.com"
|
||||
);
|
||||
settings.set_int(libtorrent::settings_pack::dht_announce_interval, 15);
|
||||
|
||||
_session.apply_settings(settings);
|
||||
|
||||
libtorrent::error_code ec;
|
||||
|
||||
_isInitialized = true;
|
||||
_isActive = true;
|
||||
|
||||
_torrentThread = std::thread([this]() {
|
||||
while (_isActive) {
|
||||
pollAlerts();
|
||||
std::unique_lock<std::mutex> lock(_abortMutex);
|
||||
_abortNotifier.wait_for(lock, PollInterval);
|
||||
}
|
||||
});
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::deinitialize() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
if (!_isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isActive = false;
|
||||
_abortNotifier.notify_all();
|
||||
if (_torrentThread.joinable()) {
|
||||
_torrentThread.join();
|
||||
}
|
||||
|
||||
const std::vector<lt::torrent_handle>& handles = _session.get_torrents();
|
||||
for (const lt::torrent_handle& h : handles) {
|
||||
_session.remove_torrent(h);
|
||||
}
|
||||
_torrents.clear();
|
||||
|
||||
_session.abort();
|
||||
_isInitialized = false;
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::pollAlerts() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
// Libtorrent does not seem to reliably generate alerts for all added torrents.
|
||||
// To make sure that the program does not keep waiting for already finished
|
||||
// downsloads, we go through the whole list of torrents when polling.
|
||||
// However, in theory, the commented code below should be more efficient:
|
||||
/*
|
||||
std::vector<libtorrent::alert*> alerts;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
_session->pop_alerts(&alerts);
|
||||
}
|
||||
for (lt::alert* a : alerts) {
|
||||
if (const lt::torrent_alert* alert =
|
||||
dynamic_cast<lt::torrent_alert*>(a))
|
||||
{
|
||||
notify(alert->handle.id());
|
||||
}
|
||||
}
|
||||
*/
|
||||
std::vector<lt::torrent_handle> handles;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
handles = _session.get_torrents();
|
||||
}
|
||||
for (const lt::torrent_handle& h : handles) {
|
||||
notify(h.id());
|
||||
}
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
TorrentClient::TorrentId TorrentClient::addTorrentFile(
|
||||
[[ maybe_unused ]] const std::string& torrentFile,
|
||||
[[maybe_unused]] const std::string& destination,
|
||||
[[maybe_unused]] TorrentProgressCallback cb)
|
||||
{
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
if (!_isInitialized) {
|
||||
LERROR("Torrent session not initialized when adding torrent");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libtorrent::error_code ec;
|
||||
libtorrent::add_torrent_params p;
|
||||
p.save_path = destination;
|
||||
p.ti = std::make_shared<libtorrent::torrent_info>(torrentFile, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", torrentFile, ec.message()));
|
||||
}
|
||||
const libtorrent::torrent_handle h = _session.add_torrent(p, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", torrentFile, ec.message()));
|
||||
}
|
||||
|
||||
TorrentId id = h.id();
|
||||
_torrents.emplace(id, Torrent{ id, h, std::move(cb) });
|
||||
return id;
|
||||
#else // SYNC_USE_LIBTORRENT
|
||||
throw TorrentError("SyncModule is compiled without libtorrent support");
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
TorrentClient::TorrentId TorrentClient::addMagnetLink(
|
||||
[[maybe_unused]] const std::string& magnetLink,
|
||||
[[maybe_unused]] const std::string& destination,
|
||||
[[maybe_unused]] TorrentProgressCallback cb)
|
||||
{
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
// TODO: register callback!
|
||||
if (!_isInitialized) {
|
||||
LERROR("Torrent session not initialized when adding torrent");
|
||||
return -1;
|
||||
}
|
||||
libtorrent::error_code ec;
|
||||
libtorrent::add_torrent_params p = libtorrent::parse_magnet_uri(magnetLink, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", magnetLink, ec.message()));
|
||||
}
|
||||
p.save_path = destination;
|
||||
p.storage_mode = libtorrent::storage_mode_allocate;
|
||||
const libtorrent::torrent_handle h = _session.add_torrent(p, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", magnetLink, ec.message()));
|
||||
}
|
||||
|
||||
TorrentId id = h.id();
|
||||
_torrents.emplace(id, Torrent{ id, h, std::move(cb) });
|
||||
return id;
|
||||
#else // SYNC_USE_LIBTORRENT
|
||||
throw TorrentError("SyncModule is compiled without libtorrent support");
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::removeTorrent([[maybe_unused]] TorrentId id) {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
const auto it = _torrents.find(id);
|
||||
if (it == _torrents.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const libtorrent::torrent_handle h = it->second.handle;
|
||||
_session.remove_torrent(h);
|
||||
|
||||
_torrents.erase(it);
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::notify([[maybe_unused]] TorrentId id) {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentProgressCallback callback;
|
||||
TorrentProgress progress;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
const auto it = _torrents.find(id);
|
||||
if (it == _torrents.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const libtorrent::torrent_handle h = it->second.handle;
|
||||
const libtorrent::torrent_status status = h.status();
|
||||
|
||||
progress.finished = status.is_finished;
|
||||
progress.nTotalBytesKnown = status.total_wanted > 0;
|
||||
progress.nTotalBytes = status.total_wanted;
|
||||
progress.nDownloadedBytes = status.total_wanted_done;
|
||||
|
||||
callback = it->second.callback;
|
||||
}
|
||||
|
||||
callback(progress);
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,125 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_SYNC___TORRENTCLIENT___H__
|
||||
#define __OPENSPACE_MODULE_SYNC___TORRENTCLIENT___H__
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
|
||||
#include <ghoul/misc/exception.h>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4265)
|
||||
#pragma warning (disable : 4996)
|
||||
#endif // _MSC_VER
|
||||
|
||||
// libtorrent defines a class with the name 'defer', which messes with out #define of the
|
||||
// defer macro in ghoul/misc/defer.h
|
||||
#undef defer
|
||||
|
||||
#include <libtorrent/torrent_handle.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
#else // SYNC_USE_LIBTORRENT
|
||||
// Dummy definition to make TorrentClient compile, these is not actually used if
|
||||
// SYNC_USE_LIBTORRENT is FALSE
|
||||
namespace libtorrent {
|
||||
using torrent_handle = void*;
|
||||
using session = void*;
|
||||
} // namespace libtorrent
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
namespace openspace {
|
||||
|
||||
struct TorrentError : public ghoul::RuntimeError {
|
||||
explicit TorrentError(std::string msg);
|
||||
};
|
||||
|
||||
class TorrentClient {
|
||||
public:
|
||||
struct TorrentProgress {
|
||||
bool finished = false;
|
||||
bool nTotalBytesKnown = false;
|
||||
size_t nTotalBytes = 0;
|
||||
size_t nDownloadedBytes = 0;
|
||||
};
|
||||
|
||||
using TorrentProgressCallback = std::function<void(TorrentProgress)>;
|
||||
using TorrentId = int32_t;
|
||||
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
|
||||
TorrentId addTorrentFile(const std::string& torrentFile,
|
||||
const std::string& destination, TorrentProgressCallback cb);
|
||||
|
||||
TorrentId addMagnetLink(const std::string& magnetLink, const std::string& destination,
|
||||
TorrentProgressCallback cb);
|
||||
|
||||
void removeTorrent(TorrentId id);
|
||||
|
||||
private:
|
||||
struct Torrent {
|
||||
TorrentId id;
|
||||
libtorrent::torrent_handle handle;
|
||||
TorrentProgressCallback callback;
|
||||
};
|
||||
|
||||
void notify(TorrentId id);
|
||||
void pollAlerts();
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
libtorrent::session _session;
|
||||
bool _isInitialized = false;
|
||||
std::atomic_bool _isActive = false;
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
std::thread _torrentThread;
|
||||
std::condition_variable _abortNotifier;
|
||||
std::mutex _abortMutex;
|
||||
std::mutex _mutex;
|
||||
|
||||
std::unordered_map<TorrentId, Torrent> _torrents;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SYNC___TORRENTCLIENT___H__
|
||||
Reference in New Issue
Block a user