mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-31 20:58:07 -06:00
Add preliminary support of libtorrent v1.2
libtorrent v1.2 should be built with deprecated features enabled.
This commit is contained in:
@@ -4,12 +4,14 @@ add_library(qbt_base STATIC
|
||||
# headers
|
||||
bittorrent/addtorrentparams.h
|
||||
bittorrent/cachestatus.h
|
||||
bittorrent/filepriority.h
|
||||
bittorrent/downloadpriority.h
|
||||
bittorrent/infohash.h
|
||||
bittorrent/magneturi.h
|
||||
bittorrent/peerinfo.h
|
||||
bittorrent/private/bandwidthscheduler.h
|
||||
bittorrent/private/libtorrentfwd.h
|
||||
bittorrent/private/filterparserthread.h
|
||||
bittorrent/private/portforwarderimpl.h
|
||||
bittorrent/private/resumedatasavingmanager.h
|
||||
bittorrent/private/speedmonitor.h
|
||||
bittorrent/private/statistics.h
|
||||
@@ -77,12 +79,13 @@ types.h
|
||||
unicodestrings.h
|
||||
|
||||
# sources
|
||||
bittorrent/filepriority.cpp
|
||||
bittorrent/downloadpriority.cpp
|
||||
bittorrent/infohash.cpp
|
||||
bittorrent/magneturi.cpp
|
||||
bittorrent/peerinfo.cpp
|
||||
bittorrent/private/bandwidthscheduler.cpp
|
||||
bittorrent/private/filterparserthread.cpp
|
||||
bittorrent/private/portforwarderimpl.cpp
|
||||
bittorrent/private/resumedatasavingmanager.cpp
|
||||
bittorrent/private/speedmonitor.cpp
|
||||
bittorrent/private/statistics.cpp
|
||||
|
||||
@@ -3,12 +3,14 @@ HEADERS += \
|
||||
$$PWD/asyncfilestorage.h \
|
||||
$$PWD/bittorrent/addtorrentparams.h \
|
||||
$$PWD/bittorrent/cachestatus.h \
|
||||
$$PWD/bittorrent/filepriority.h \
|
||||
$$PWD/bittorrent/downloadpriority.h \
|
||||
$$PWD/bittorrent/infohash.h \
|
||||
$$PWD/bittorrent/magneturi.h \
|
||||
$$PWD/bittorrent/peerinfo.h \
|
||||
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
||||
$$PWD/bittorrent/private/filterparserthread.h \
|
||||
$$PWD/bittorrent/private/libtorrentfwd.h \
|
||||
$$PWD/bittorrent/private/portforwarderimpl.h \
|
||||
$$PWD/bittorrent/private/resumedatasavingmanager.h \
|
||||
$$PWD/bittorrent/private/speedmonitor.h \
|
||||
$$PWD/bittorrent/private/statistics.h \
|
||||
@@ -76,12 +78,13 @@ HEADERS += \
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/asyncfilestorage.cpp \
|
||||
$$PWD/bittorrent/filepriority.cpp \
|
||||
$$PWD/bittorrent/downloadpriority.cpp \
|
||||
$$PWD/bittorrent/infohash.cpp \
|
||||
$$PWD/bittorrent/magneturi.cpp \
|
||||
$$PWD/bittorrent/peerinfo.cpp \
|
||||
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
||||
$$PWD/bittorrent/private/filterparserthread.cpp \
|
||||
$$PWD/bittorrent/private/portforwarderimpl.cpp \
|
||||
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
|
||||
$$PWD/bittorrent/private/speedmonitor.cpp \
|
||||
$$PWD/bittorrent/private/statistics.cpp \
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QVector>
|
||||
|
||||
#include "../tristatebool.h"
|
||||
#include "downloadpriority.h"
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
@@ -47,7 +48,7 @@ namespace BitTorrent
|
||||
bool firstLastPiecePriority = false;
|
||||
TriStateBool addForced;
|
||||
TriStateBool addPaused;
|
||||
QVector<int> filePriorities; // used if TorrentInfo is set
|
||||
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
|
||||
bool ignoreShareLimits = false;
|
||||
bool skipChecking = false;
|
||||
TriStateBool createSubfolder;
|
||||
|
||||
@@ -26,18 +26,18 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "filepriority.h"
|
||||
#include "downloadpriority.h"
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
bool isValidFilePriority(const BitTorrent::FilePriority priority)
|
||||
bool isValidDownloadPriority(const DownloadPriority priority)
|
||||
{
|
||||
switch (priority) {
|
||||
case BitTorrent::FilePriority::Ignored:
|
||||
case BitTorrent::FilePriority::Normal:
|
||||
case BitTorrent::FilePriority::High:
|
||||
case BitTorrent::FilePriority::Maximum:
|
||||
case BitTorrent::FilePriority::Mixed:
|
||||
case BitTorrent::DownloadPriority::Ignored:
|
||||
case BitTorrent::DownloadPriority::Normal:
|
||||
case BitTorrent::DownloadPriority::High:
|
||||
case BitTorrent::DownloadPriority::Maximum:
|
||||
case BitTorrent::DownloadPriority::Mixed:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -30,14 +30,15 @@
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
enum class FilePriority : int
|
||||
enum class DownloadPriority : int
|
||||
{
|
||||
Ignored = 0,
|
||||
Normal = 1,
|
||||
High = 6,
|
||||
Maximum = 7,
|
||||
|
||||
Mixed = -1
|
||||
};
|
||||
|
||||
bool isValidFilePriority(BitTorrent::FilePriority priority);
|
||||
bool isValidDownloadPriority(DownloadPriority priority);
|
||||
}
|
||||
@@ -42,18 +42,18 @@ InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash)
|
||||
: m_valid(true)
|
||||
, m_nativeHash(nativeHash)
|
||||
{
|
||||
const QByteArray raw = QByteArray::fromRawData(nativeHash.data(), libtorrent::sha1_hash::size);
|
||||
const QByteArray raw = QByteArray::fromRawData(nativeHash.data(), length());
|
||||
m_hashString = QString::fromLatin1(raw.toHex());
|
||||
}
|
||||
|
||||
InfoHash::InfoHash(const QString &hashString)
|
||||
: m_valid(false)
|
||||
{
|
||||
if (hashString.size() != (libtorrent::sha1_hash::size * 2))
|
||||
if (hashString.size() != (length() * 2))
|
||||
return;
|
||||
|
||||
const QByteArray raw = QByteArray::fromHex(hashString.toLatin1());
|
||||
if (raw.size() != libtorrent::sha1_hash::size) // QByteArray::fromHex() will skip over invalid characters
|
||||
if (raw.size() != length()) // QByteArray::fromHex() will skip over invalid characters
|
||||
return;
|
||||
|
||||
m_valid = true;
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#define BITTORRENT_INFOHASH_H
|
||||
|
||||
#include <libtorrent/sha1_hash.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace BitTorrent
|
||||
@@ -42,6 +44,15 @@ namespace BitTorrent
|
||||
InfoHash(const QString &hashString);
|
||||
InfoHash(const InfoHash &other) = default;
|
||||
|
||||
static constexpr int length()
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
return libtorrent::sha1_hash::size;
|
||||
#else
|
||||
return libtorrent::sha1_hash::size();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
operator libtorrent::sha1_hash() const;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "infohash.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isBitTorrentInfoHash(const QString &string)
|
||||
@@ -44,8 +46,8 @@ namespace
|
||||
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
|
||||
// 2. 32 chars Base32 encoded string
|
||||
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
|
||||
const int SHA1_HEX_SIZE = libtorrent::sha1_hash::size * 2;
|
||||
const int SHA1_BASE32_SIZE = libtorrent::sha1_hash::size * 1.6;
|
||||
const int SHA1_HEX_SIZE = BitTorrent::InfoHash::length() * 2;
|
||||
const int SHA1_BASE32_SIZE = BitTorrent::InfoHash::length() * 1.6;
|
||||
|
||||
return ((((string.size() == SHA1_HEX_SIZE))
|
||||
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
|
||||
@@ -75,7 +77,7 @@ MagnetUri::MagnetUri(const QString &source)
|
||||
m_name = QString::fromStdString(m_addTorrentParams.name);
|
||||
|
||||
for (const std::string &tracker : m_addTorrentParams.trackers)
|
||||
m_trackers.append(TrackerEntry(tracker));
|
||||
m_trackers.append(libtorrent::announce_entry {tracker});
|
||||
|
||||
for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
|
||||
m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed)));
|
||||
|
||||
@@ -60,17 +60,17 @@ PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeIn
|
||||
|
||||
bool PeerInfo::fromDHT() const
|
||||
{
|
||||
return (m_nativeInfo.source & libt::peer_info::dht);
|
||||
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::dht);
|
||||
}
|
||||
|
||||
bool PeerInfo::fromPeX() const
|
||||
{
|
||||
return (m_nativeInfo.source & libt::peer_info::pex);
|
||||
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::pex);
|
||||
}
|
||||
|
||||
bool PeerInfo::fromLSD() const
|
||||
{
|
||||
return (m_nativeInfo.source & libt::peer_info::lsd);
|
||||
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::lsd);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
@@ -82,102 +82,102 @@ QString PeerInfo::country() const
|
||||
|
||||
bool PeerInfo::isInteresting() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::interesting);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::interesting);
|
||||
}
|
||||
|
||||
bool PeerInfo::isChocked() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::choked);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::choked);
|
||||
}
|
||||
|
||||
bool PeerInfo::isRemoteInterested() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::remote_interested);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::remote_interested);
|
||||
}
|
||||
|
||||
bool PeerInfo::isRemoteChocked() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::remote_choked);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::remote_choked);
|
||||
}
|
||||
|
||||
bool PeerInfo::isSupportsExtensions() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::supports_extensions);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::supports_extensions);
|
||||
}
|
||||
|
||||
bool PeerInfo::isLocalConnection() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::local_connection);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::local_connection);
|
||||
}
|
||||
|
||||
bool PeerInfo::isHandshake() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::handshake);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::handshake);
|
||||
}
|
||||
|
||||
bool PeerInfo::isConnecting() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::connecting);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::connecting);
|
||||
}
|
||||
|
||||
bool PeerInfo::isOnParole() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::on_parole);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::on_parole);
|
||||
}
|
||||
|
||||
bool PeerInfo::isSeed() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::seed);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::seed);
|
||||
}
|
||||
|
||||
bool PeerInfo::optimisticUnchoke() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::optimistic_unchoke);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::optimistic_unchoke);
|
||||
}
|
||||
|
||||
bool PeerInfo::isSnubbed() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::snubbed);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::snubbed);
|
||||
}
|
||||
|
||||
bool PeerInfo::isUploadOnly() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::upload_only);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::upload_only);
|
||||
}
|
||||
|
||||
bool PeerInfo::isEndgameMode() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::endgame_mode);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::endgame_mode);
|
||||
}
|
||||
|
||||
bool PeerInfo::isHolepunched() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::holepunched);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::holepunched);
|
||||
}
|
||||
|
||||
bool PeerInfo::useI2PSocket() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::i2p_socket);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::i2p_socket);
|
||||
}
|
||||
|
||||
bool PeerInfo::useUTPSocket() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::utp_socket);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::utp_socket);
|
||||
}
|
||||
|
||||
bool PeerInfo::useSSLSocket() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::ssl_socket);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::ssl_socket);
|
||||
}
|
||||
|
||||
bool PeerInfo::isRC4Encrypted() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::rc4_encrypted);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::rc4_encrypted);
|
||||
}
|
||||
|
||||
bool PeerInfo::isPlaintextEncrypted() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::plaintext_encrypted);
|
||||
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::plaintext_encrypted);
|
||||
}
|
||||
|
||||
PeerAddress PeerInfo::address() const
|
||||
@@ -220,8 +220,9 @@ QBitArray PeerInfo::pieces() const
|
||||
{
|
||||
QBitArray result(m_nativeInfo.pieces.size());
|
||||
|
||||
for (int i = 0; i < m_nativeInfo.pieces.size(); ++i)
|
||||
result.setBit(i, m_nativeInfo.pieces.get_bit(i));
|
||||
int i = 0;
|
||||
for (const bool bit : m_nativeInfo.pieces)
|
||||
result.setBit(i++, bit);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -397,5 +398,5 @@ QString PeerInfo::flagsDescription() const
|
||||
|
||||
int PeerInfo::downloadingPieceIndex() const
|
||||
{
|
||||
return m_nativeInfo.downloading_piece_index;
|
||||
return static_cast<int>(m_nativeInfo.downloading_piece_index);
|
||||
}
|
||||
|
||||
81
src/base/bittorrent/private/libtorrentfwd.h
Normal file
81
src/base/bittorrent/private/libtorrentfwd.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
namespace libtorrent
|
||||
{
|
||||
class entry;
|
||||
class session;
|
||||
struct ip_filter;
|
||||
struct settings_pack;
|
||||
struct torrent_handle;
|
||||
|
||||
class alert;
|
||||
struct add_torrent_alert;
|
||||
struct external_ip_alert;
|
||||
struct fastresume_rejected_alert;
|
||||
struct file_completed_alert;
|
||||
struct file_error_alert;
|
||||
struct file_rename_failed_alert;
|
||||
struct file_renamed_alert;
|
||||
struct listen_failed_alert;
|
||||
struct listen_succeeded_alert;
|
||||
struct metadata_received_alert;
|
||||
struct peer_ban_alert;
|
||||
struct peer_blocked_alert;
|
||||
struct portmap_alert;
|
||||
struct portmap_error_alert;
|
||||
struct save_resume_data_alert;
|
||||
struct save_resume_data_failed_alert;
|
||||
struct session_stats_alert;
|
||||
struct state_update_alert;
|
||||
struct stats_alert;
|
||||
struct storage_moved_alert;
|
||||
struct storage_moved_failed_alert;
|
||||
struct torrent_alert;
|
||||
struct torrent_checked_alert;
|
||||
struct torrent_delete_failed_alert;
|
||||
struct torrent_deleted_alert;
|
||||
struct torrent_finished_alert;
|
||||
struct torrent_paused_alert;
|
||||
struct torrent_removed_alert;
|
||||
struct torrent_resumed_alert;
|
||||
struct tracker_error_alert;
|
||||
struct tracker_reply_alert;
|
||||
struct tracker_warning_alert;
|
||||
struct url_seed_alert;
|
||||
}
|
||||
|
||||
namespace lt = libtorrent;
|
||||
#else
|
||||
#include <libtorrent/fwd.hpp>
|
||||
#endif
|
||||
114
src/base/bittorrent/private/portforwarderimpl.cpp
Normal file
114
src/base/bittorrent/private/portforwarderimpl.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "portforwarderimpl.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/settingsstorage.h"
|
||||
|
||||
const QString KEY_ENABLED = QStringLiteral("Network/PortForwardingEnabled");
|
||||
|
||||
PortForwarderImpl::PortForwarderImpl(libtorrent::session *provider, QObject *parent)
|
||||
: Net::PortForwarder {parent}
|
||||
, m_active {SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool()}
|
||||
, m_provider {provider}
|
||||
{
|
||||
if (m_active)
|
||||
start();
|
||||
}
|
||||
|
||||
PortForwarderImpl::~PortForwarderImpl()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
bool PortForwarderImpl::isEnabled() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
void PortForwarderImpl::setEnabled(const bool enabled)
|
||||
{
|
||||
if (m_active != enabled) {
|
||||
if (enabled)
|
||||
start();
|
||||
else
|
||||
stop();
|
||||
|
||||
m_active = enabled;
|
||||
SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarderImpl::addPort(const quint16 port)
|
||||
{
|
||||
if (!m_mappedPorts.contains(port)) {
|
||||
m_mappedPorts.insert(port, {});
|
||||
if (isEnabled())
|
||||
m_mappedPorts[port] = {m_provider->add_port_mapping(lt::session::tcp, port, port)};
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarderImpl::deletePort(const quint16 port)
|
||||
{
|
||||
if (m_mappedPorts.contains(port)) {
|
||||
if (isEnabled()) {
|
||||
for (const LTPortMapping &portMapping : m_mappedPorts[port])
|
||||
m_provider->delete_port_mapping(portMapping);
|
||||
}
|
||||
m_mappedPorts.remove(port);
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarderImpl::start()
|
||||
{
|
||||
qDebug("Enabling UPnP / NAT-PMP");
|
||||
lt::settings_pack settingsPack = m_provider->get_settings();
|
||||
settingsPack.set_bool(lt::settings_pack::enable_upnp, true);
|
||||
settingsPack.set_bool(lt::settings_pack::enable_natpmp, true);
|
||||
m_provider->apply_settings(settingsPack);
|
||||
for (auto i = m_mappedPorts.begin(); i != m_mappedPorts.end(); ++i) {
|
||||
// quint16 port = i.key();
|
||||
i.value() = {m_provider->add_port_mapping(lt::session::tcp, i.key(), i.key())};
|
||||
}
|
||||
LogMsg(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
||||
}
|
||||
|
||||
void PortForwarderImpl::stop()
|
||||
{
|
||||
qDebug("Disabling UPnP / NAT-PMP");
|
||||
lt::settings_pack settingsPack = m_provider->get_settings();
|
||||
settingsPack.set_bool(lt::settings_pack::enable_upnp, false);
|
||||
settingsPack.set_bool(lt::settings_pack::enable_natpmp, false);
|
||||
m_provider->apply_settings(settingsPack);
|
||||
LogMsg(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
||||
}
|
||||
65
src/base/bittorrent/private/portforwarderimpl.h
Normal file
65
src/base/bittorrent/private/portforwarderimpl.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||
* and distribute the linked executables. You must obey the GNU General Public
|
||||
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||
* modify file(s), you may extend this exception to your version of the file(s),
|
||||
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <QHash>
|
||||
|
||||
#include "base/net/portforwarder.h"
|
||||
#include "libtorrentfwd.h"
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using LTPortMapping = int;
|
||||
#else
|
||||
#include <libtorrent/portmap.hpp>
|
||||
using LTPortMapping = lt::port_mapping_t;
|
||||
#endif
|
||||
|
||||
class PortForwarderImpl : public Net::PortForwarder
|
||||
{
|
||||
Q_DISABLE_COPY(PortForwarderImpl)
|
||||
|
||||
public:
|
||||
explicit PortForwarderImpl(lt::session *provider, QObject *parent = nullptr);
|
||||
~PortForwarderImpl() override;
|
||||
|
||||
bool isEnabled() const override;
|
||||
void setEnabled(bool enabled) override;
|
||||
|
||||
void addPort(quint16 port) override;
|
||||
void deletePort(quint16 port) override;
|
||||
|
||||
private:
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
bool m_active;
|
||||
libtorrent::session *m_provider;
|
||||
QHash<quint16, std::vector<LTPortMapping>> m_mappedPorts;
|
||||
};
|
||||
@@ -62,13 +62,13 @@
|
||||
#include <libtorrent/session_stats.hpp>
|
||||
#include <libtorrent/session_status.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include "base/algorithm.h"
|
||||
#include "base/exceptions.h"
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/net/portforwarder.h"
|
||||
#include "base/net/proxyconfigurationmanager.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/torrentfileguard.h"
|
||||
@@ -82,6 +82,7 @@
|
||||
#include "magneturi.h"
|
||||
#include "private/bandwidthscheduler.h"
|
||||
#include "private/filterparserthread.h"
|
||||
#include "private/portforwarderimpl.h"
|
||||
#include "private/resumedatasavingmanager.h"
|
||||
#include "private/statistics.h"
|
||||
#include "torrenthandle.h"
|
||||
@@ -106,6 +107,16 @@ using namespace BitTorrent;
|
||||
|
||||
namespace
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using LTSessionFlags = int;
|
||||
using LTStatusFlags = int;
|
||||
using LTString = std::string;
|
||||
#else
|
||||
using LTSessionFlags = lt::session_flags_t;
|
||||
using LTStatusFlags = lt::status_flags_t;
|
||||
using LTString = lt::string_view;
|
||||
#endif
|
||||
|
||||
bool readFile(const QString &path, QByteArray &buf);
|
||||
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri);
|
||||
|
||||
@@ -134,13 +145,19 @@ namespace
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename LTStr>
|
||||
QString fromLTString(const LTStr &str)
|
||||
{
|
||||
return QString::fromUtf8(str.data(), static_cast<int>(str.size()));
|
||||
}
|
||||
|
||||
template <typename Entry>
|
||||
QSet<QString> entryListToSetImpl(const Entry &entry)
|
||||
{
|
||||
Q_ASSERT(entry.type() == Entry::list_t);
|
||||
QSet<QString> output;
|
||||
for (int i = 0; i < entry.list_size(); ++i) {
|
||||
const QString tag = QString::fromStdString(entry.list_string_value_at(i));
|
||||
const QString tag = fromLTString(entry.list_string_value_at(i));
|
||||
if (Session::isValidTag(tag))
|
||||
output.insert(tag);
|
||||
else
|
||||
@@ -405,7 +422,7 @@ Session::Session(QObject *parent)
|
||||
pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true);
|
||||
configure(pack);
|
||||
|
||||
m_nativeSession = new libt::session(pack, 0);
|
||||
m_nativeSession = new lt::session {pack, LTSessionFlags {0}};
|
||||
m_nativeSession->set_alert_notify([this]()
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection);
|
||||
@@ -490,7 +507,7 @@ Session::Session(QObject *parent)
|
||||
}
|
||||
|
||||
// initialize PortForwarder instance
|
||||
Net::PortForwarder::initInstance(m_nativeSession);
|
||||
new PortForwarderImpl {m_nativeSession};
|
||||
|
||||
initMetrics();
|
||||
m_statsUpdateTimer.start();
|
||||
@@ -936,7 +953,7 @@ Session::~Session()
|
||||
|
||||
// We must delete PortForwarderImpl before
|
||||
// we delete libtorrent::session
|
||||
Net::PortForwarder::freeInstance();
|
||||
delete Net::PortForwarder::instance();
|
||||
|
||||
qDebug("Deleting the session");
|
||||
delete m_nativeSession;
|
||||
@@ -1665,7 +1682,7 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
|
||||
const libt::torrent_handle torrent = m_nativeSession->find_torrent(hash);
|
||||
if (!torrent.is_valid()) return false;
|
||||
|
||||
if (!torrent.status(0).has_metadata) {
|
||||
if (!torrent.status(LTStatusFlags {0}).has_metadata) {
|
||||
// if hidden torrent is still loading metadata...
|
||||
--m_extraLimit;
|
||||
adjustLimits();
|
||||
@@ -1930,11 +1947,21 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
|
||||
if (!fromMagnetUri) {
|
||||
if (params.restored) {
|
||||
// Set torrent fast resume data
|
||||
p.resume_data = {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
|
||||
p.resume_data = std::vector<char> {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
|
||||
p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
|
||||
}
|
||||
else {
|
||||
p.file_priorities = {params.filePriorities.begin(), params.filePriorities.end()};
|
||||
Q_ASSERT(p.file_priorities.empty());
|
||||
std::transform(params.filePriorities.cbegin(), params.filePriorities.cend()
|
||||
, std::back_inserter(p.file_priorities), [](DownloadPriority priority)
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
return static_cast<boost::uint8_t>(priority);
|
||||
#else
|
||||
return static_cast<lt::download_priority_t>(
|
||||
static_cast<lt::download_priority_t::underlying_type>(priority));
|
||||
#endif
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3966,7 +3993,11 @@ void Session::handlePortmapAlert(const libt::portmap_alert *p)
|
||||
void Session::handlePeerBlockedAlert(const libt::peer_blocked_alert *p)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
#if LIBTORRENT_VERSION_NUM < 10200
|
||||
const std::string ip = p->ip.to_string(ec);
|
||||
#else
|
||||
const std::string ip = p->endpoint.address().to_string(ec);
|
||||
#endif
|
||||
QString reason;
|
||||
switch (p->reason) {
|
||||
case libt::peer_blocked_alert::ip_filter:
|
||||
@@ -4182,31 +4213,31 @@ namespace
|
||||
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
|
||||
|
||||
torrentParams.savePath = Profile::instance().fromPortablePath(
|
||||
Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath"))));
|
||||
Utils::Fs::fromNativePath(fromLTString(fast.dict_find_string_value("qBt-savePath"))));
|
||||
|
||||
std::string ratioLimitString = fast.dict_find_string_value("qBt-ratioLimit");
|
||||
LTString ratioLimitString = fast.dict_find_string_value("qBt-ratioLimit");
|
||||
if (ratioLimitString.empty())
|
||||
torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
|
||||
else
|
||||
torrentParams.ratioLimit = QString::fromStdString(ratioLimitString).toDouble();
|
||||
torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble();
|
||||
torrentParams.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
|
||||
// **************************************************************************************
|
||||
// Workaround to convert legacy label to category
|
||||
// TODO: Should be removed in future
|
||||
torrentParams.category = QString::fromStdString(fast.dict_find_string_value("qBt-label"));
|
||||
torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-label"));
|
||||
if (torrentParams.category.isEmpty())
|
||||
// **************************************************************************************
|
||||
torrentParams.category = QString::fromStdString(fast.dict_find_string_value("qBt-category"));
|
||||
torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-category"));
|
||||
// auto because the return type depends on the #if above.
|
||||
const auto tagsEntry = fast.dict_find_list("qBt-tags");
|
||||
if (isList(tagsEntry))
|
||||
torrentParams.tags = entryListToSet(tagsEntry);
|
||||
torrentParams.name = QString::fromStdString(fast.dict_find_string_value("qBt-name"));
|
||||
torrentParams.name = fromLTString(fast.dict_find_string_value("qBt-name"));
|
||||
torrentParams.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
|
||||
torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
|
||||
torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder");
|
||||
|
||||
magnetUri = MagnetUri(QString::fromStdString(fast.dict_find_string_value("qBt-magnetUri")));
|
||||
magnetUri = MagnetUri(fromLTString(fast.dict_find_string_value("qBt-magnetUri")));
|
||||
const bool isAutoManaged = fast.dict_find_int_value("auto_managed");
|
||||
const bool isPaused = fast.dict_find_int_value("paused");
|
||||
torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged));
|
||||
|
||||
@@ -47,54 +47,12 @@
|
||||
#include "base/settingvalue.h"
|
||||
#include "base/tristatebool.h"
|
||||
#include "base/types.h"
|
||||
#include "private/libtorrentfwd.h"
|
||||
#include "addtorrentparams.h"
|
||||
#include "cachestatus.h"
|
||||
#include "sessionstatus.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class session;
|
||||
struct torrent_handle;
|
||||
class entry;
|
||||
struct ip_filter;
|
||||
struct settings_pack;
|
||||
|
||||
class alert;
|
||||
struct torrent_alert;
|
||||
struct state_update_alert;
|
||||
struct stats_alert;
|
||||
struct add_torrent_alert;
|
||||
struct torrent_checked_alert;
|
||||
struct torrent_finished_alert;
|
||||
struct torrent_removed_alert;
|
||||
struct torrent_deleted_alert;
|
||||
struct torrent_delete_failed_alert;
|
||||
struct torrent_paused_alert;
|
||||
struct torrent_resumed_alert;
|
||||
struct save_resume_data_alert;
|
||||
struct save_resume_data_failed_alert;
|
||||
struct file_renamed_alert;
|
||||
struct storage_moved_alert;
|
||||
struct storage_moved_failed_alert;
|
||||
struct metadata_received_alert;
|
||||
struct file_error_alert;
|
||||
struct file_completed_alert;
|
||||
struct tracker_error_alert;
|
||||
struct tracker_reply_alert;
|
||||
struct tracker_warning_alert;
|
||||
struct portmap_error_alert;
|
||||
struct portmap_alert;
|
||||
struct peer_blocked_alert;
|
||||
struct peer_ban_alert;
|
||||
struct fastresume_rejected_alert;
|
||||
struct url_seed_alert;
|
||||
struct listen_succeeded_alert;
|
||||
struct listen_failed_alert;
|
||||
struct external_ip_alert;
|
||||
struct session_stats_alert;
|
||||
}
|
||||
|
||||
class QThread;
|
||||
class QTimer;
|
||||
class QStringList;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <libtorrent/create_torrent.hpp>
|
||||
#include <libtorrent/storage.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
@@ -47,6 +48,12 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using CreateFlags = int;
|
||||
#else
|
||||
using CreateFlags = lt::create_flags_t;
|
||||
#endif
|
||||
|
||||
// do not include files and folders whose
|
||||
// name starts with a .
|
||||
bool fileFilter(const std::string &f)
|
||||
@@ -131,7 +138,7 @@ void TorrentCreatorThread::run()
|
||||
if (isInterruptionRequested()) return;
|
||||
|
||||
libt::create_torrent newTorrent(fs, m_params.pieceSize, -1
|
||||
, (m_params.isAlignmentOptimized ? libt::create_torrent::optimize_alignment : 0));
|
||||
, (m_params.isAlignmentOptimized ? libt::create_torrent::optimize_alignment : CreateFlags {}));
|
||||
|
||||
// Add url seeds
|
||||
for (QString seed : asConst(m_params.urlSeeds)) {
|
||||
@@ -203,5 +210,5 @@ int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const i
|
||||
libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
||||
|
||||
return libt::create_torrent(fs, pieceSize, -1
|
||||
, (isAlignmentOptimized ? libt::create_torrent::optimize_alignment : 0)).num_pieces();
|
||||
, (isAlignmentOptimized ? libt::create_torrent::optimize_alignment : CreateFlags {})).num_pieces();
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
#include <libtorrent/time.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QBitArray>
|
||||
#include <QDateTime>
|
||||
@@ -69,6 +70,28 @@ using namespace BitTorrent;
|
||||
|
||||
namespace
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using LTDownloadPriority = int;
|
||||
using LTDownloadPriorityUnderlyingType = int;
|
||||
using LTQueuePosition = int;
|
||||
#else
|
||||
using LTDownloadPriority = lt::download_priority_t;
|
||||
using LTDownloadPriorityUnderlyingType = lt::download_priority_t::underlying_type;
|
||||
using LTQueuePosition = lt::queue_position_t;
|
||||
#endif
|
||||
|
||||
std::vector<LTDownloadPriority> toLTDownloadPriorities(const QVector<DownloadPriority> &priorities)
|
||||
{
|
||||
std::vector<LTDownloadPriority> out;
|
||||
std::transform(priorities.cbegin(), priorities.cend()
|
||||
, std::back_inserter(out), [](BitTorrent::DownloadPriority priority)
|
||||
{
|
||||
return static_cast<LTDownloadPriority>(
|
||||
static_cast<LTDownloadPriorityUnderlyingType>(priority));
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
using ListType = libt::entry::list_type;
|
||||
|
||||
ListType setToEntryList(const QSet<QString> &input)
|
||||
@@ -635,11 +658,21 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const
|
||||
return res;
|
||||
}
|
||||
|
||||
QVector<int> TorrentHandle::filePriorities() const
|
||||
QVector<DownloadPriority> TorrentHandle::filePriorities() const
|
||||
{
|
||||
const std::vector<int> fp = m_nativeHandle.file_priorities();
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
const std::vector<LTDownloadPriority> fp = m_nativeHandle.file_priorities();
|
||||
#else
|
||||
const std::vector<LTDownloadPriority> fp = m_nativeHandle.get_file_priorities();
|
||||
#endif
|
||||
|
||||
return QVector<int>::fromStdVector(fp);
|
||||
QVector<DownloadPriority> ret;
|
||||
std::transform(fp.cbegin(), fp.cend(), std::back_inserter(ret), [](LTDownloadPriority priority)
|
||||
{
|
||||
return static_cast<DownloadPriority>(
|
||||
static_cast<std::underlying_type<DownloadPriority>::type>(priority));
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentHandle::info() const
|
||||
@@ -838,18 +871,22 @@ bool TorrentHandle::hasError() const
|
||||
|
||||
bool TorrentHandle::hasFilteredPieces() const
|
||||
{
|
||||
const std::vector<int> pp = m_nativeHandle.piece_priorities();
|
||||
return std::any_of(pp.cbegin(), pp.cend(), [](const int priority)
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
const std::vector<LTDownloadPriority> pp = m_nativeHandle.piece_priorities();
|
||||
#else
|
||||
const std::vector<LTDownloadPriority> pp = m_nativeHandle.get_piece_priorities();
|
||||
#endif
|
||||
return std::any_of(pp.cbegin(), pp.cend(), [](const LTDownloadPriority priority)
|
||||
{
|
||||
return (priority == 0);
|
||||
return (priority == LTDownloadPriority {0});
|
||||
});
|
||||
}
|
||||
|
||||
int TorrentHandle::queuePosition() const
|
||||
{
|
||||
if (m_nativeStatus.queue_position < 0) return 0;
|
||||
if (m_nativeStatus.queue_position < LTQueuePosition {0}) return 0;
|
||||
|
||||
return m_nativeStatus.queue_position + 1;
|
||||
return static_cast<int>(m_nativeStatus.queue_position) + 1;
|
||||
}
|
||||
|
||||
QString TorrentHandle::error() const
|
||||
@@ -1244,7 +1281,7 @@ void TorrentHandle::setFirstLastPiecePriority(const bool enabled)
|
||||
setFirstLastPiecePriorityImpl(enabled);
|
||||
}
|
||||
|
||||
void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVector<int> &updatedFilePrio)
|
||||
void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVector<DownloadPriority> &updatedFilePrio)
|
||||
{
|
||||
// Download first and last pieces first for every file in the torrent
|
||||
|
||||
@@ -1253,17 +1290,24 @@ void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVec
|
||||
return;
|
||||
}
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
const std::vector<LTDownloadPriority> filePriorities = !updatedFilePrio.isEmpty() ? toLTDownloadPriorities(updatedFilePrio)
|
||||
: nativeHandle().file_priorities();
|
||||
std::vector<LTDownloadPriority> piecePriorities = nativeHandle().piece_priorities();
|
||||
#else
|
||||
const std::vector<LTDownloadPriority> filePriorities = !updatedFilePrio.isEmpty() ? toLTDownloadPriorities(updatedFilePrio)
|
||||
: nativeHandle().get_file_priorities();
|
||||
std::vector<LTDownloadPriority> piecePriorities = nativeHandle().get_piece_priorities();
|
||||
#endif
|
||||
// Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it
|
||||
// we might get the old/wrong values, so we rely on `updatedFilePrio` in this case.
|
||||
const std::vector<int> filePriorities = !updatedFilePrio.isEmpty() ? updatedFilePrio.toStdVector() : nativeHandle().file_priorities();
|
||||
std::vector<int> piecePriorities = nativeHandle().piece_priorities();
|
||||
for (int index = 0; index < static_cast<int>(filePriorities.size()); ++index) {
|
||||
const int filePrio = filePriorities[index];
|
||||
if (filePrio <= 0)
|
||||
const LTDownloadPriority filePrio = filePriorities[index];
|
||||
if (filePrio <= LTDownloadPriority {0})
|
||||
continue;
|
||||
|
||||
// Determine the priority to set
|
||||
const int newPrio = enabled ? 7 : filePrio;
|
||||
const int newPrio = enabled ? LTDownloadPriority {7} : filePrio;
|
||||
const TorrentInfo::PieceRange extremities = info().filePieces(index);
|
||||
|
||||
// worst case: AVI index = 1% of total file size (at the end of the file)
|
||||
@@ -1349,8 +1393,11 @@ void TorrentHandle::renameFile(int index, const QString &name)
|
||||
bool TorrentHandle::saveTorrentFile(const QString &path)
|
||||
{
|
||||
if (!m_torrentInfo.isValid()) return false;
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
const libt::create_torrent torrentCreator = libt::create_torrent(*(m_torrentInfo.nativeInfo()), true);
|
||||
#else
|
||||
const libt::create_torrent torrentCreator = libt::create_torrent(*(m_torrentInfo.nativeInfo()));
|
||||
#endif
|
||||
const libt::entry torrentEntry = torrentCreator.generate();
|
||||
|
||||
QVector<char> out;
|
||||
@@ -1572,7 +1619,7 @@ void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data
|
||||
resumeData["qBt-name"] = m_name.toStdString();
|
||||
resumeData["qBt-seedStatus"] = m_hasSeedStatus;
|
||||
resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled;
|
||||
resumeData["qBt-queuePosition"] = (nativeHandle().queue_position() + 1); // qBt starts queue at 1
|
||||
resumeData["qBt-queuePosition"] = (static_cast<int>(nativeHandle().queue_position()) + 1); // qBt starts queue at 1
|
||||
resumeData["qBt-hasRootFolder"] = m_hasRootFolder;
|
||||
|
||||
m_session->handleTorrentResumeDataReady(this, resumeData);
|
||||
@@ -1916,7 +1963,7 @@ QString TorrentHandle::toMagnetUri() const
|
||||
return QString::fromStdString(libt::make_magnet_uri(m_nativeHandle));
|
||||
}
|
||||
|
||||
void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
||||
void TorrentHandle::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
||||
{
|
||||
if (!hasMetadata()) return;
|
||||
if (priorities.size() != filesCount()) return;
|
||||
@@ -1927,23 +1974,25 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
||||
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
||||
// 'torrent_finished_alert' and eg show tray notifications
|
||||
const QVector<qreal> progress = filesProgress();
|
||||
const QVector<int> oldPriorities = filePriorities();
|
||||
const QVector<DownloadPriority> oldPriorities = filePriorities();
|
||||
for (int i = 0; i < oldPriorities.size(); ++i) {
|
||||
if ((oldPriorities[i] == 0) && (priorities[i] > 0) && (progress[i] < 1.0)) {
|
||||
if ((oldPriorities[i] == DownloadPriority::Ignored)
|
||||
&& (priorities[i] > DownloadPriority::Ignored)
|
||||
&& (progress[i] < 1.0)) {
|
||||
m_hasSeedStatus = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Changing files priorities...";
|
||||
m_nativeHandle.prioritize_files(priorities.toStdVector());
|
||||
m_nativeHandle.prioritize_files(toLTDownloadPriorities(priorities));
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely...";
|
||||
const QString spath = savePath(true);
|
||||
for (int i = 0; i < priorities.size(); ++i) {
|
||||
const QString filepath = filePath(i);
|
||||
// Move unwanted files to a .unwanted subfolder
|
||||
if (priorities[i] == 0) {
|
||||
if (priorities[i] == DownloadPriority::Ignored) {
|
||||
const QString oldAbsPath = QDir(spath).absoluteFilePath(filepath);
|
||||
const QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath);
|
||||
// Make sure the file does not already exists
|
||||
@@ -1976,7 +2025,7 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
||||
}
|
||||
|
||||
// Move wanted files back to their original folder
|
||||
if (priorities[i] > 0) {
|
||||
if (priorities[i] > DownloadPriority::Ignored) {
|
||||
const QString parentRelPath = Utils::Fs::branchPath(filepath);
|
||||
if (QDir(parentRelPath).dirName() == ".unwanted") {
|
||||
const QString oldName = Utils::Fs::fileName(filepath);
|
||||
|
||||
@@ -42,7 +42,9 @@
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "private/libtorrentfwd.h"
|
||||
#include "private/speedmonitor.h"
|
||||
#include "downloadpriority.h"
|
||||
#include "infohash.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
@@ -53,29 +55,6 @@ class QDateTime;
|
||||
class QStringList;
|
||||
class QUrl;
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class alert;
|
||||
struct fastresume_rejected_alert;
|
||||
struct file_completed_alert;
|
||||
struct file_renamed_alert;
|
||||
struct file_rename_failed_alert;
|
||||
struct metadata_received_alert;
|
||||
struct save_resume_data_alert;
|
||||
struct save_resume_data_failed_alert;
|
||||
struct stats_alert;
|
||||
struct storage_moved_alert;
|
||||
struct storage_moved_failed_alert;
|
||||
struct torrent_checked_alert;
|
||||
struct torrent_finished_alert;
|
||||
struct torrent_paused_alert;
|
||||
struct torrent_resumed_alert;
|
||||
struct torrent_status;
|
||||
struct tracker_error_alert;
|
||||
struct tracker_reply_alert;
|
||||
struct tracker_warning_alert;
|
||||
}
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class PeerInfo;
|
||||
@@ -103,7 +82,7 @@ namespace BitTorrent
|
||||
int uploadLimit;
|
||||
int downloadLimit;
|
||||
// for new torrents
|
||||
QVector<int> filePriorities;
|
||||
QVector<DownloadPriority> filePriorities;
|
||||
// for restored torrents
|
||||
qreal ratioLimit;
|
||||
int seedingTimeLimit;
|
||||
@@ -258,7 +237,7 @@ namespace BitTorrent
|
||||
qlonglong fileSize(int index) const;
|
||||
QStringList absoluteFilePaths() const;
|
||||
QStringList absoluteFilePathsUnwanted() const;
|
||||
QVector<int> filePriorities() const;
|
||||
QVector<DownloadPriority> filePriorities() const;
|
||||
|
||||
TorrentInfo info() const;
|
||||
bool isSeed() const;
|
||||
@@ -337,7 +316,7 @@ namespace BitTorrent
|
||||
void forceRecheck();
|
||||
void renameFile(int index, const QString &name);
|
||||
bool saveTorrentFile(const QString &path);
|
||||
void prioritizeFiles(const QVector<int> &priorities);
|
||||
void prioritizeFiles(const QVector<DownloadPriority> &priorities);
|
||||
void setRatioLimit(qreal limit);
|
||||
void setSeedingTimeLimit(int limit);
|
||||
void setUploadLimit(int limit);
|
||||
@@ -410,7 +389,7 @@ namespace BitTorrent
|
||||
bool addTracker(const TrackerEntry &tracker);
|
||||
bool addUrlSeed(const QUrl &urlSeed);
|
||||
bool removeUrlSeed(const QUrl &urlSeed);
|
||||
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<int> &updatedFilePrio = {});
|
||||
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<DownloadPriority> &updatedFilePrio = {});
|
||||
|
||||
Session *const m_session;
|
||||
libtorrent::torrent_handle m_nativeHandle;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "torrentinfo.h"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <libtorrent/error_code.hpp>
|
||||
|
||||
#include <QByteArray>
|
||||
@@ -42,12 +43,27 @@
|
||||
#include "infohash.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using LTPieceIndex = int;
|
||||
using LTFileIndex = int;
|
||||
#else
|
||||
using LTPieceIndex = lt::piece_index_t;
|
||||
using LTFileIndex = lt::file_index_t;
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
|
||||
TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo)
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
m_nativeInfo = boost::const_pointer_cast<libt::torrent_info>(nativeInfo);
|
||||
#else
|
||||
m_nativeInfo = std::const_pointer_cast<libt::torrent_info>(nativeInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
TorrentInfo::TorrentInfo(const TorrentInfo &other)
|
||||
@@ -190,7 +206,7 @@ int TorrentInfo::pieceLength() const
|
||||
int TorrentInfo::pieceLength(const int index) const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->piece_size(index);
|
||||
return m_nativeInfo->piece_size(LTPieceIndex {index});
|
||||
}
|
||||
|
||||
int TorrentInfo::piecesCount() const
|
||||
@@ -202,7 +218,8 @@ int TorrentInfo::piecesCount() const
|
||||
QString TorrentInfo::filePath(const int index) const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
return Utils::Fs::fromNativePath(QString::fromStdString(m_nativeInfo->files().file_path(index)));
|
||||
return Utils::Fs::fromNativePath(
|
||||
QString::fromStdString(m_nativeInfo->files().file_path(LTFileIndex {index})));
|
||||
}
|
||||
|
||||
QStringList TorrentInfo::filePaths() const
|
||||
@@ -222,19 +239,20 @@ QString TorrentInfo::fileName(const int index) const
|
||||
QString TorrentInfo::origFilePath(const int index) const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
return Utils::Fs::fromNativePath(QString::fromStdString(m_nativeInfo->orig_files().file_path(index)));
|
||||
return Utils::Fs::fromNativePath(
|
||||
QString::fromStdString(m_nativeInfo->orig_files().file_path(LTFileIndex {index})));
|
||||
}
|
||||
|
||||
qlonglong TorrentInfo::fileSize(const int index) const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->files().file_size(index);
|
||||
return m_nativeInfo->files().file_size(LTFileIndex {index});
|
||||
}
|
||||
|
||||
qlonglong TorrentInfo::fileOffset(const int index) const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->files().file_offset(index);
|
||||
return m_nativeInfo->files().file_offset(LTFileIndex {index});
|
||||
}
|
||||
|
||||
QList<TrackerEntry> TorrentInfo::trackers() const
|
||||
@@ -285,11 +303,12 @@ QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
|
||||
return {};
|
||||
|
||||
const std::vector<libt::file_slice> files(
|
||||
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex)));
|
||||
nativeInfo()->map_block(LTPieceIndex {pieceIndex}, 0
|
||||
, nativeInfo()->piece_size(LTPieceIndex {pieceIndex})));
|
||||
QVector<int> res;
|
||||
res.reserve(int(files.size()));
|
||||
std::transform(files.begin(), files.end(), std::back_inserter(res),
|
||||
[](const libt::file_slice &s) { return s.file_index; });
|
||||
[](const libt::file_slice &s) { return static_cast<int>(s.file_index); });
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -304,7 +323,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
|
||||
hashes.reserve(count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
hashes += { m_nativeInfo->hash_for_piece_ptr(i), libtorrent::sha1_hash::size };
|
||||
hashes += {m_nativeInfo->hash_for_piece_ptr(LTPieceIndex {i}), InfoHash::length()};
|
||||
|
||||
return hashes;
|
||||
}
|
||||
@@ -333,8 +352,8 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
|
||||
}
|
||||
|
||||
const libt::file_storage &files = nativeInfo()->files();
|
||||
const auto fileSize = files.file_size(fileIndex);
|
||||
const auto fileOffset = files.file_offset(fileIndex);
|
||||
const auto fileSize = files.file_size(LTFileIndex {fileIndex});
|
||||
const auto fileOffset = files.file_offset(LTFileIndex {fileIndex});
|
||||
return makeInterval(static_cast<int>(fileOffset / pieceLength()),
|
||||
static_cast<int>((fileOffset + fileSize - 1) / pieceLength()));
|
||||
}
|
||||
|
||||
@@ -30,12 +30,14 @@
|
||||
#define BITTORRENT_TORRENTINFO_H
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/indexrange.h"
|
||||
#include "private/libtorrentfwd.h"
|
||||
|
||||
class QByteArray;
|
||||
class QDateTime;
|
||||
@@ -53,8 +55,13 @@ namespace BitTorrent
|
||||
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
|
||||
|
||||
public:
|
||||
typedef boost::shared_ptr<const libtorrent::torrent_info> NativeConstPtr;
|
||||
typedef boost::shared_ptr<libtorrent::torrent_info> NativePtr;
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using NativeConstPtr = boost::shared_ptr<const libtorrent::torrent_info>;
|
||||
using NativePtr = boost::shared_ptr<libtorrent::torrent_info>;
|
||||
#else
|
||||
using NativeConstPtr = std::shared_ptr<const libtorrent::torrent_info>;
|
||||
using NativePtr = std::shared_ptr<libtorrent::torrent_info>;
|
||||
#endif
|
||||
|
||||
explicit TorrentInfo(NativeConstPtr nativeInfo = {});
|
||||
TorrentInfo(const TorrentInfo &other);
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
|
||||
#include "trackerentry.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
@@ -48,6 +52,19 @@ QString TrackerEntry::url() const
|
||||
return QString::fromStdString(m_nativeEntry.url);
|
||||
}
|
||||
|
||||
bool TrackerEntry::isWorking() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
return m_nativeEntry.is_working();
|
||||
#else
|
||||
return std::any_of(m_nativeEntry.endpoints.begin(), m_nativeEntry.endpoints.end()
|
||||
, [](const lt::announce_endpoint &endpoint)
|
||||
{
|
||||
return endpoint.is_working();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
int TrackerEntry::tier() const
|
||||
{
|
||||
return m_nativeEntry.tier;
|
||||
@@ -57,7 +74,7 @@ TrackerEntry::Status TrackerEntry::status() const
|
||||
{
|
||||
// libtorrent::announce_entry::is_working() returns
|
||||
// true when the tracker hasn't been tried yet.
|
||||
if (m_nativeEntry.verified && m_nativeEntry.is_working())
|
||||
if (m_nativeEntry.verified && isWorking())
|
||||
return Working;
|
||||
if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating)
|
||||
return Updating;
|
||||
@@ -72,6 +89,36 @@ void TrackerEntry::setTier(const int value)
|
||||
m_nativeEntry.tier = value;
|
||||
}
|
||||
|
||||
int TrackerEntry::numSeeds() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
return nativeEntry().scrape_complete;
|
||||
#else
|
||||
// FIXME: Handle all possible endpoints.
|
||||
return nativeEntry().endpoints.empty() ? -1 : nativeEntry().endpoints[0].scrape_complete;
|
||||
#endif
|
||||
}
|
||||
|
||||
int TrackerEntry::numLeeches() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
return nativeEntry().scrape_incomplete;
|
||||
#else
|
||||
// FIXME: Handle all possible endpoints.
|
||||
return nativeEntry().endpoints.empty() ? -1 : nativeEntry().endpoints[0].scrape_incomplete;
|
||||
#endif
|
||||
}
|
||||
|
||||
int TrackerEntry::numDownloaded() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
return nativeEntry().scrape_downloaded;
|
||||
#else
|
||||
// FIXME: Handle all possible endpoints.
|
||||
return nativeEntry().endpoints.empty() ? -1 : nativeEntry().endpoints[0].scrape_downloaded;
|
||||
#endif
|
||||
}
|
||||
|
||||
libtorrent::announce_entry TrackerEntry::nativeEntry() const
|
||||
{
|
||||
return m_nativeEntry;
|
||||
|
||||
@@ -53,11 +53,16 @@ namespace BitTorrent
|
||||
TrackerEntry &operator=(const TrackerEntry &other) = default;
|
||||
|
||||
QString url() const;
|
||||
bool isWorking() const;
|
||||
Status status() const;
|
||||
|
||||
int tier() const;
|
||||
void setTier(int value);
|
||||
|
||||
int numSeeds() const;
|
||||
int numLeeches() const;
|
||||
int numDownloaded() const;
|
||||
|
||||
libtorrent::announce_entry nativeEntry() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -28,110 +28,21 @@
|
||||
|
||||
#include "portforwarder.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/settingsstorage.h"
|
||||
|
||||
static const QString KEY_ENABLED = QStringLiteral("Network/PortForwardingEnabled");
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace Net;
|
||||
|
||||
PortForwarder::PortForwarder(libtorrent::session *provider, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_active(false)
|
||||
, m_provider(provider)
|
||||
Net::PortForwarder::PortForwarder(QObject *parent)
|
||||
: QObject {parent}
|
||||
{
|
||||
if (SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool())
|
||||
start();
|
||||
Q_ASSERT(!m_instance);
|
||||
m_instance = this;
|
||||
}
|
||||
|
||||
PortForwarder::~PortForwarder()
|
||||
Net::PortForwarder::~PortForwarder()
|
||||
{
|
||||
stop();
|
||||
m_instance = nullptr;
|
||||
}
|
||||
|
||||
void PortForwarder::initInstance(libtorrent::session *const provider)
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new PortForwarder(provider);
|
||||
}
|
||||
|
||||
void PortForwarder::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PortForwarder *PortForwarder::instance()
|
||||
Net::PortForwarder *Net::PortForwarder::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
bool PortForwarder::isEnabled() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
void PortForwarder::setEnabled(const bool enabled)
|
||||
{
|
||||
if (m_active != enabled) {
|
||||
if (enabled)
|
||||
start();
|
||||
else
|
||||
stop();
|
||||
|
||||
SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarder::addPort(const quint16 port)
|
||||
{
|
||||
if (!m_mappedPorts.contains(port)) {
|
||||
m_mappedPorts.insert(port, 0);
|
||||
if (m_active)
|
||||
m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port);
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarder::deletePort(const quint16 port)
|
||||
{
|
||||
if (m_mappedPorts.contains(port)) {
|
||||
if (m_active)
|
||||
m_provider->delete_port_mapping(m_mappedPorts[port]);
|
||||
m_mappedPorts.remove(port);
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarder::start()
|
||||
{
|
||||
qDebug("Enabling UPnP / NAT-PMP");
|
||||
libt::settings_pack settingsPack = m_provider->get_settings();
|
||||
settingsPack.set_bool(libt::settings_pack::enable_upnp, true);
|
||||
settingsPack.set_bool(libt::settings_pack::enable_natpmp, true);
|
||||
m_provider->apply_settings(settingsPack);
|
||||
for (auto i = m_mappedPorts.begin(); i != m_mappedPorts.end(); ++i) {
|
||||
// quint16 port = i.key();
|
||||
i.value() = m_provider->add_port_mapping(libt::session::tcp, i.key(), i.key());
|
||||
}
|
||||
m_active = true;
|
||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
||||
}
|
||||
|
||||
void PortForwarder::stop()
|
||||
{
|
||||
qDebug("Disabling UPnP / NAT-PMP");
|
||||
libt::settings_pack settingsPack = m_provider->get_settings();
|
||||
settingsPack.set_bool(libt::settings_pack::enable_upnp, false);
|
||||
settingsPack.set_bool(libt::settings_pack::enable_natpmp, false);
|
||||
m_provider->apply_settings(settingsPack);
|
||||
m_active = false;
|
||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
||||
}
|
||||
|
||||
PortForwarder *PortForwarder::m_instance = nullptr;
|
||||
Net::PortForwarder *Net::PortForwarder::m_instance = nullptr;
|
||||
|
||||
@@ -29,43 +29,27 @@
|
||||
#ifndef NET_PORTFORWARDER_H
|
||||
#define NET_PORTFORWARDER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class session;
|
||||
}
|
||||
|
||||
namespace Net
|
||||
{
|
||||
class PortForwarder : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(PortForwarder)
|
||||
|
||||
public:
|
||||
static void initInstance(libtorrent::session *const provider);
|
||||
static void freeInstance();
|
||||
explicit PortForwarder(QObject *parent = nullptr);
|
||||
~PortForwarder() override;
|
||||
|
||||
static PortForwarder *instance();
|
||||
|
||||
bool isEnabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
virtual bool isEnabled() const = 0;
|
||||
virtual void setEnabled(bool enabled) = 0;
|
||||
|
||||
void addPort(quint16 port);
|
||||
void deletePort(quint16 port);
|
||||
virtual void addPort(quint16 port) = 0;
|
||||
virtual void deletePort(quint16 port) = 0;
|
||||
|
||||
private:
|
||||
explicit PortForwarder(libtorrent::session *const provider, QObject *parent = nullptr);
|
||||
~PortForwarder();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
bool m_active;
|
||||
libtorrent::session *m_provider;
|
||||
QHash<quint16, int> m_mappedPorts;
|
||||
|
||||
static PortForwarder *m_instance;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user