Browse Source

Merge pull request #10373 from glassez/libtorrent-1.2

Add preliminary support of libtorrent v1.2
adaptive-webui-19844
Vladimir Golovnev 6 years ago committed by GitHub
parent
commit
6de02b0f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      src/base/CMakeLists.txt
  2. 7
      src/base/base.pri
  3. 3
      src/base/bittorrent/addtorrentparams.h
  4. 14
      src/base/bittorrent/downloadpriority.cpp
  5. 5
      src/base/bittorrent/downloadpriority.h
  6. 6
      src/base/bittorrent/infohash.cpp
  7. 11
      src/base/bittorrent/infohash.h
  8. 8
      src/base/bittorrent/magneturi.cpp
  9. 53
      src/base/bittorrent/peerinfo.cpp
  10. 81
      src/base/bittorrent/private/libtorrentfwd.h
  11. 114
      src/base/bittorrent/private/portforwarderimpl.cpp
  12. 65
      src/base/bittorrent/private/portforwarderimpl.h
  13. 61
      src/base/bittorrent/session.cpp
  14. 44
      src/base/bittorrent/session.h
  15. 11
      src/base/bittorrent/torrentcreatorthread.cpp
  16. 93
      src/base/bittorrent/torrenthandle.cpp
  17. 33
      src/base/bittorrent/torrenthandle.h
  18. 39
      src/base/bittorrent/torrentinfo.cpp
  19. 11
      src/base/bittorrent/torrentinfo.h
  20. 49
      src/base/bittorrent/trackerentry.cpp
  21. 5
      src/base/bittorrent/trackerentry.h
  22. 103
      src/base/net/portforwarder.cpp
  23. 30
      src/base/net/portforwarder.h
  24. 14
      src/gui/addnewtorrentdialog.cpp
  25. 16
      src/gui/properties/propertieswidget.cpp
  26. 32
      src/gui/properties/proplistdelegate.cpp
  27. 6
      src/gui/properties/trackerlistwidget.cpp
  28. 32
      src/gui/torrentcontentmodel.cpp
  29. 5
      src/gui/torrentcontentmodel.h
  30. 4
      src/gui/torrentcontentmodelfile.cpp
  31. 4
      src/gui/torrentcontentmodelfile.h
  32. 12
      src/gui/torrentcontentmodelfolder.cpp
  33. 4
      src/gui/torrentcontentmodelfolder.h
  34. 4
      src/gui/torrentcontentmodelitem.cpp
  35. 8
      src/gui/torrentcontentmodelitem.h
  36. 2
      src/webui/api/serialize/serialize_torrent.cpp
  37. 18
      src/webui/api/torrentscontroller.cpp

7
src/base/CMakeLists.txt

@ -4,12 +4,14 @@ add_library(qbt_base STATIC
# headers # headers
bittorrent/addtorrentparams.h bittorrent/addtorrentparams.h
bittorrent/cachestatus.h bittorrent/cachestatus.h
bittorrent/filepriority.h bittorrent/downloadpriority.h
bittorrent/infohash.h bittorrent/infohash.h
bittorrent/magneturi.h bittorrent/magneturi.h
bittorrent/peerinfo.h bittorrent/peerinfo.h
bittorrent/private/bandwidthscheduler.h bittorrent/private/bandwidthscheduler.h
bittorrent/private/libtorrentfwd.h
bittorrent/private/filterparserthread.h bittorrent/private/filterparserthread.h
bittorrent/private/portforwarderimpl.h
bittorrent/private/resumedatasavingmanager.h bittorrent/private/resumedatasavingmanager.h
bittorrent/private/speedmonitor.h bittorrent/private/speedmonitor.h
bittorrent/private/statistics.h bittorrent/private/statistics.h
@ -77,12 +79,13 @@ types.h
unicodestrings.h unicodestrings.h
# sources # sources
bittorrent/filepriority.cpp bittorrent/downloadpriority.cpp
bittorrent/infohash.cpp bittorrent/infohash.cpp
bittorrent/magneturi.cpp bittorrent/magneturi.cpp
bittorrent/peerinfo.cpp bittorrent/peerinfo.cpp
bittorrent/private/bandwidthscheduler.cpp bittorrent/private/bandwidthscheduler.cpp
bittorrent/private/filterparserthread.cpp bittorrent/private/filterparserthread.cpp
bittorrent/private/portforwarderimpl.cpp
bittorrent/private/resumedatasavingmanager.cpp bittorrent/private/resumedatasavingmanager.cpp
bittorrent/private/speedmonitor.cpp bittorrent/private/speedmonitor.cpp
bittorrent/private/statistics.cpp bittorrent/private/statistics.cpp

7
src/base/base.pri

@ -3,12 +3,14 @@ HEADERS += \
$$PWD/asyncfilestorage.h \ $$PWD/asyncfilestorage.h \
$$PWD/bittorrent/addtorrentparams.h \ $$PWD/bittorrent/addtorrentparams.h \
$$PWD/bittorrent/cachestatus.h \ $$PWD/bittorrent/cachestatus.h \
$$PWD/bittorrent/filepriority.h \ $$PWD/bittorrent/downloadpriority.h \
$$PWD/bittorrent/infohash.h \ $$PWD/bittorrent/infohash.h \
$$PWD/bittorrent/magneturi.h \ $$PWD/bittorrent/magneturi.h \
$$PWD/bittorrent/peerinfo.h \ $$PWD/bittorrent/peerinfo.h \
$$PWD/bittorrent/private/bandwidthscheduler.h \ $$PWD/bittorrent/private/bandwidthscheduler.h \
$$PWD/bittorrent/private/filterparserthread.h \ $$PWD/bittorrent/private/filterparserthread.h \
$$PWD/bittorrent/private/libtorrentfwd.h \
$$PWD/bittorrent/private/portforwarderimpl.h \
$$PWD/bittorrent/private/resumedatasavingmanager.h \ $$PWD/bittorrent/private/resumedatasavingmanager.h \
$$PWD/bittorrent/private/speedmonitor.h \ $$PWD/bittorrent/private/speedmonitor.h \
$$PWD/bittorrent/private/statistics.h \ $$PWD/bittorrent/private/statistics.h \
@ -76,12 +78,13 @@ HEADERS += \
SOURCES += \ SOURCES += \
$$PWD/asyncfilestorage.cpp \ $$PWD/asyncfilestorage.cpp \
$$PWD/bittorrent/filepriority.cpp \ $$PWD/bittorrent/downloadpriority.cpp \
$$PWD/bittorrent/infohash.cpp \ $$PWD/bittorrent/infohash.cpp \
$$PWD/bittorrent/magneturi.cpp \ $$PWD/bittorrent/magneturi.cpp \
$$PWD/bittorrent/peerinfo.cpp \ $$PWD/bittorrent/peerinfo.cpp \
$$PWD/bittorrent/private/bandwidthscheduler.cpp \ $$PWD/bittorrent/private/bandwidthscheduler.cpp \
$$PWD/bittorrent/private/filterparserthread.cpp \ $$PWD/bittorrent/private/filterparserthread.cpp \
$$PWD/bittorrent/private/portforwarderimpl.cpp \
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \ $$PWD/bittorrent/private/resumedatasavingmanager.cpp \
$$PWD/bittorrent/private/speedmonitor.cpp \ $$PWD/bittorrent/private/speedmonitor.cpp \
$$PWD/bittorrent/private/statistics.cpp \ $$PWD/bittorrent/private/statistics.cpp \

3
src/base/bittorrent/addtorrentparams.h

@ -33,6 +33,7 @@
#include <QVector> #include <QVector>
#include "../tristatebool.h" #include "../tristatebool.h"
#include "downloadpriority.h"
namespace BitTorrent namespace BitTorrent
{ {
@ -47,7 +48,7 @@ namespace BitTorrent
bool firstLastPiecePriority = false; bool firstLastPiecePriority = false;
TriStateBool addForced; TriStateBool addForced;
TriStateBool addPaused; TriStateBool addPaused;
QVector<int> filePriorities; // used if TorrentInfo is set QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
bool ignoreShareLimits = false; bool ignoreShareLimits = false;
bool skipChecking = false; bool skipChecking = false;
TriStateBool createSubfolder; TriStateBool createSubfolder;

14
src/base/bittorrent/filepriority.cpp → src/base/bittorrent/downloadpriority.cpp

@ -26,18 +26,18 @@
* exception statement from your version. * exception statement from your version.
*/ */
#include "filepriority.h" #include "downloadpriority.h"
namespace BitTorrent namespace BitTorrent
{ {
bool isValidFilePriority(const BitTorrent::FilePriority priority) bool isValidDownloadPriority(const DownloadPriority priority)
{ {
switch (priority) { switch (priority) {
case BitTorrent::FilePriority::Ignored: case BitTorrent::DownloadPriority::Ignored:
case BitTorrent::FilePriority::Normal: case BitTorrent::DownloadPriority::Normal:
case BitTorrent::FilePriority::High: case BitTorrent::DownloadPriority::High:
case BitTorrent::FilePriority::Maximum: case BitTorrent::DownloadPriority::Maximum:
case BitTorrent::FilePriority::Mixed: case BitTorrent::DownloadPriority::Mixed:
return true; return true;
default: default:
return false; return false;

5
src/base/bittorrent/filepriority.h → src/base/bittorrent/downloadpriority.h

@ -30,14 +30,15 @@
namespace BitTorrent namespace BitTorrent
{ {
enum class FilePriority : int enum class DownloadPriority : int
{ {
Ignored = 0, Ignored = 0,
Normal = 1, Normal = 1,
High = 6, High = 6,
Maximum = 7, Maximum = 7,
Mixed = -1 Mixed = -1
}; };
bool isValidFilePriority(BitTorrent::FilePriority priority); bool isValidDownloadPriority(DownloadPriority priority);
} }

6
src/base/bittorrent/infohash.cpp

@ -42,18 +42,18 @@ InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash)
: m_valid(true) : m_valid(true)
, m_nativeHash(nativeHash) , 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()); m_hashString = QString::fromLatin1(raw.toHex());
} }
InfoHash::InfoHash(const QString &hashString) InfoHash::InfoHash(const QString &hashString)
: m_valid(false) : m_valid(false)
{ {
if (hashString.size() != (libtorrent::sha1_hash::size * 2)) if (hashString.size() != (length() * 2))
return; return;
const QByteArray raw = QByteArray::fromHex(hashString.toLatin1()); 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; return;
m_valid = true; m_valid = true;

11
src/base/bittorrent/infohash.h

@ -30,6 +30,8 @@
#define BITTORRENT_INFOHASH_H #define BITTORRENT_INFOHASH_H
#include <libtorrent/sha1_hash.hpp> #include <libtorrent/sha1_hash.hpp>
#include <libtorrent/version.hpp>
#include <QString> #include <QString>
namespace BitTorrent namespace BitTorrent
@ -42,6 +44,15 @@ namespace BitTorrent
InfoHash(const QString &hashString); InfoHash(const QString &hashString);
InfoHash(const InfoHash &other) = default; 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; bool isValid() const;
operator libtorrent::sha1_hash() const; operator libtorrent::sha1_hash() const;

8
src/base/bittorrent/magneturi.cpp

@ -35,6 +35,8 @@
#include <QRegularExpression> #include <QRegularExpression>
#include "infohash.h"
namespace namespace
{ {
bool isBitTorrentInfoHash(const QString &string) bool isBitTorrentInfoHash(const QString &string)
@ -44,8 +46,8 @@ namespace
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters) // == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
// 2. 32 chars Base32 encoded string // 2. 32 chars Base32 encoded string
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding) // == 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_HEX_SIZE = BitTorrent::InfoHash::length() * 2;
const int SHA1_BASE32_SIZE = libtorrent::sha1_hash::size * 1.6; const int SHA1_BASE32_SIZE = BitTorrent::InfoHash::length() * 1.6;
return ((((string.size() == SHA1_HEX_SIZE)) return ((((string.size() == SHA1_HEX_SIZE))
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]")))) && !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
@ -75,7 +77,7 @@ MagnetUri::MagnetUri(const QString &source)
m_name = QString::fromStdString(m_addTorrentParams.name); m_name = QString::fromStdString(m_addTorrentParams.name);
for (const std::string &tracker : m_addTorrentParams.trackers) 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) for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed))); m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed)));

53
src/base/bittorrent/peerinfo.cpp

@ -60,17 +60,17 @@ PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeIn
bool PeerInfo::fromDHT() const 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 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 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 #ifndef DISABLE_COUNTRIES_RESOLUTION
@ -82,102 +82,102 @@ QString PeerInfo::country() const
bool PeerInfo::isInteresting() 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 PeerAddress PeerInfo::address() const
@ -220,8 +220,9 @@ QBitArray PeerInfo::pieces() const
{ {
QBitArray result(m_nativeInfo.pieces.size()); QBitArray result(m_nativeInfo.pieces.size());
for (int i = 0; i < m_nativeInfo.pieces.size(); ++i) int i = 0;
result.setBit(i, m_nativeInfo.pieces.get_bit(i)); for (const bool bit : m_nativeInfo.pieces)
result.setBit(i++, bit);
return result; return result;
} }
@ -397,5 +398,5 @@ QString PeerInfo::flagsDescription() const
int PeerInfo::downloadingPieceIndex() 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

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

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

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

61
src/base/bittorrent/session.cpp

@ -62,13 +62,13 @@
#include <libtorrent/session_stats.hpp> #include <libtorrent/session_stats.hpp>
#include <libtorrent/session_status.hpp> #include <libtorrent/session_status.hpp>
#include <libtorrent/torrent_info.hpp> #include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include "base/algorithm.h" #include "base/algorithm.h"
#include "base/exceptions.h" #include "base/exceptions.h"
#include "base/global.h" #include "base/global.h"
#include "base/logger.h" #include "base/logger.h"
#include "base/net/downloadmanager.h" #include "base/net/downloadmanager.h"
#include "base/net/portforwarder.h"
#include "base/net/proxyconfigurationmanager.h" #include "base/net/proxyconfigurationmanager.h"
#include "base/profile.h" #include "base/profile.h"
#include "base/torrentfileguard.h" #include "base/torrentfileguard.h"
@ -82,6 +82,7 @@
#include "magneturi.h" #include "magneturi.h"
#include "private/bandwidthscheduler.h" #include "private/bandwidthscheduler.h"
#include "private/filterparserthread.h" #include "private/filterparserthread.h"
#include "private/portforwarderimpl.h"
#include "private/resumedatasavingmanager.h" #include "private/resumedatasavingmanager.h"
#include "private/statistics.h" #include "private/statistics.h"
#include "torrenthandle.h" #include "torrenthandle.h"
@ -106,6 +107,16 @@ using namespace BitTorrent;
namespace 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 readFile(const QString &path, QByteArray &buf);
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri); bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri);
@ -134,13 +145,19 @@ namespace
return result; return result;
} }
template <typename LTStr>
QString fromLTString(const LTStr &str)
{
return QString::fromUtf8(str.data(), static_cast<int>(str.size()));
}
template <typename Entry> template <typename Entry>
QSet<QString> entryListToSetImpl(const Entry &entry) QSet<QString> entryListToSetImpl(const Entry &entry)
{ {
Q_ASSERT(entry.type() == Entry::list_t); Q_ASSERT(entry.type() == Entry::list_t);
QSet<QString> output; QSet<QString> output;
for (int i = 0; i < entry.list_size(); ++i) { 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)) if (Session::isValidTag(tag))
output.insert(tag); output.insert(tag);
else else
@ -405,7 +422,7 @@ Session::Session(QObject *parent)
pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true); pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true);
configure(pack); configure(pack);
m_nativeSession = new libt::session(pack, 0); m_nativeSession = new lt::session {pack, LTSessionFlags {0}};
m_nativeSession->set_alert_notify([this]() m_nativeSession->set_alert_notify([this]()
{ {
QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection);
@ -490,7 +507,7 @@ Session::Session(QObject *parent)
} }
// initialize PortForwarder instance // initialize PortForwarder instance
Net::PortForwarder::initInstance(m_nativeSession); new PortForwarderImpl {m_nativeSession};
initMetrics(); initMetrics();
m_statsUpdateTimer.start(); m_statsUpdateTimer.start();
@ -936,7 +953,7 @@ Session::~Session()
// We must delete PortForwarderImpl before // We must delete PortForwarderImpl before
// we delete libtorrent::session // we delete libtorrent::session
Net::PortForwarder::freeInstance(); delete Net::PortForwarder::instance();
qDebug("Deleting the session"); qDebug("Deleting the session");
delete m_nativeSession; delete m_nativeSession;
@ -1665,7 +1682,7 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
const libt::torrent_handle torrent = m_nativeSession->find_torrent(hash); const libt::torrent_handle torrent = m_nativeSession->find_torrent(hash);
if (!torrent.is_valid()) return false; 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... // if hidden torrent is still loading metadata...
--m_extraLimit; --m_extraLimit;
adjustLimits(); adjustLimits();
@ -1930,11 +1947,21 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
if (!fromMagnetUri) { if (!fromMagnetUri) {
if (params.restored) { if (params.restored) {
// Set torrent fast resume data // 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; p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
} }
else { 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) void Session::handlePeerBlockedAlert(const libt::peer_blocked_alert *p)
{ {
boost::system::error_code ec; boost::system::error_code ec;
#if LIBTORRENT_VERSION_NUM < 10200
const std::string ip = p->ip.to_string(ec); const std::string ip = p->ip.to_string(ec);
#else
const std::string ip = p->endpoint.address().to_string(ec);
#endif
QString reason; QString reason;
switch (p->reason) { switch (p->reason) {
case libt::peer_blocked_alert::ip_filter: case libt::peer_blocked_alert::ip_filter:
@ -4182,31 +4213,31 @@ namespace
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false; if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
torrentParams.savePath = Profile::instance().fromPortablePath( 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()) if (ratioLimitString.empty())
torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0; torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
else 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); torrentParams.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
// ************************************************************************************** // **************************************************************************************
// Workaround to convert legacy label to category // Workaround to convert legacy label to category
// TODO: Should be removed in future // 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()) 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. // auto because the return type depends on the #if above.
const auto tagsEntry = fast.dict_find_list("qBt-tags"); const auto tagsEntry = fast.dict_find_list("qBt-tags");
if (isList(tagsEntry)) if (isList(tagsEntry))
torrentParams.tags = entryListToSet(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.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled"); torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder"); 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 isAutoManaged = fast.dict_find_int_value("auto_managed");
const bool isPaused = fast.dict_find_int_value("paused"); const bool isPaused = fast.dict_find_int_value("paused");
torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged)); torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged));

44
src/base/bittorrent/session.h

@ -47,54 +47,12 @@
#include "base/settingvalue.h" #include "base/settingvalue.h"
#include "base/tristatebool.h" #include "base/tristatebool.h"
#include "base/types.h" #include "base/types.h"
#include "private/libtorrentfwd.h"
#include "addtorrentparams.h" #include "addtorrentparams.h"
#include "cachestatus.h" #include "cachestatus.h"
#include "sessionstatus.h" #include "sessionstatus.h"
#include "torrentinfo.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 QThread;
class QTimer; class QTimer;
class QStringList; class QStringList;

11
src/base/bittorrent/torrentcreatorthread.cpp

@ -34,6 +34,7 @@
#include <libtorrent/create_torrent.hpp> #include <libtorrent/create_torrent.hpp>
#include <libtorrent/storage.hpp> #include <libtorrent/storage.hpp>
#include <libtorrent/torrent_info.hpp> #include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include <QDirIterator> #include <QDirIterator>
#include <QFile> #include <QFile>
@ -47,6 +48,12 @@
namespace namespace
{ {
#if (LIBTORRENT_VERSION_NUM < 10200)
using CreateFlags = int;
#else
using CreateFlags = lt::create_flags_t;
#endif
// do not include files and folders whose // do not include files and folders whose
// name starts with a . // name starts with a .
bool fileFilter(const std::string &f) bool fileFilter(const std::string &f)
@ -131,7 +138,7 @@ void TorrentCreatorThread::run()
if (isInterruptionRequested()) return; if (isInterruptionRequested()) return;
libt::create_torrent newTorrent(fs, m_params.pieceSize, -1 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 // Add url seeds
for (QString seed : asConst(m_params.urlSeeds)) { 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); libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
return libt::create_torrent(fs, pieceSize, -1 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();
} }

93
src/base/bittorrent/torrenthandle.cpp

@ -43,6 +43,7 @@
#include <libtorrent/entry.hpp> #include <libtorrent/entry.hpp>
#include <libtorrent/magnet_uri.hpp> #include <libtorrent/magnet_uri.hpp>
#include <libtorrent/time.hpp> #include <libtorrent/time.hpp>
#include <libtorrent/version.hpp>
#include <QBitArray> #include <QBitArray>
#include <QDateTime> #include <QDateTime>
@ -69,6 +70,28 @@ using namespace BitTorrent;
namespace 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; using ListType = libt::entry::list_type;
ListType setToEntryList(const QSet<QString> &input) ListType setToEntryList(const QSet<QString> &input)
@ -635,11 +658,21 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const
return res; 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 TorrentInfo TorrentHandle::info() const
@ -838,18 +871,22 @@ bool TorrentHandle::hasError() const
bool TorrentHandle::hasFilteredPieces() const bool TorrentHandle::hasFilteredPieces() const
{ {
const std::vector<int> pp = m_nativeHandle.piece_priorities(); #if (LIBTORRENT_VERSION_NUM < 10200)
return std::any_of(pp.cbegin(), pp.cend(), [](const int priority) 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 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 QString TorrentHandle::error() const
@ -1244,7 +1281,7 @@ void TorrentHandle::setFirstLastPiecePriority(const bool enabled)
setFirstLastPiecePriorityImpl(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 // 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; 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 // 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. // 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) { for (int index = 0; index < static_cast<int>(filePriorities.size()); ++index) {
const int filePrio = filePriorities[index]; const LTDownloadPriority filePrio = filePriorities[index];
if (filePrio <= 0) if (filePrio <= LTDownloadPriority {0})
continue; continue;
// Determine the priority to set // 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); const TorrentInfo::PieceRange extremities = info().filePieces(index);
// worst case: AVI index = 1% of total file size (at the end of the file) // 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) bool TorrentHandle::saveTorrentFile(const QString &path)
{ {
if (!m_torrentInfo.isValid()) return false; if (!m_torrentInfo.isValid()) return false;
#if (LIBTORRENT_VERSION_NUM < 10200)
const libt::create_torrent torrentCreator = libt::create_torrent(*(m_torrentInfo.nativeInfo()), true); 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(); const libt::entry torrentEntry = torrentCreator.generate();
QVector<char> out; QVector<char> out;
@ -1572,7 +1619,7 @@ void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data
resumeData["qBt-name"] = m_name.toStdString(); resumeData["qBt-name"] = m_name.toStdString();
resumeData["qBt-seedStatus"] = m_hasSeedStatus; resumeData["qBt-seedStatus"] = m_hasSeedStatus;
resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled; 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; resumeData["qBt-hasRootFolder"] = m_hasRootFolder;
m_session->handleTorrentResumeDataReady(this, resumeData); m_session->handleTorrentResumeDataReady(this, resumeData);
@ -1916,7 +1963,7 @@ QString TorrentHandle::toMagnetUri() const
return QString::fromStdString(libt::make_magnet_uri(m_nativeHandle)); 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 (!hasMetadata()) return;
if (priorities.size() != filesCount()) 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 // Reset 'm_hasSeedStatus' if needed in order to react again to
// 'torrent_finished_alert' and eg show tray notifications // 'torrent_finished_alert' and eg show tray notifications
const QVector<qreal> progress = filesProgress(); const QVector<qreal> progress = filesProgress();
const QVector<int> oldPriorities = filePriorities(); const QVector<DownloadPriority> oldPriorities = filePriorities();
for (int i = 0; i < oldPriorities.size(); ++i) { 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; m_hasSeedStatus = false;
break; break;
} }
} }
qDebug() << Q_FUNC_INFO << "Changing files priorities..."; 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..."; qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely...";
const QString spath = savePath(true); const QString spath = savePath(true);
for (int i = 0; i < priorities.size(); ++i) { for (int i = 0; i < priorities.size(); ++i) {
const QString filepath = filePath(i); const QString filepath = filePath(i);
// Move unwanted files to a .unwanted subfolder // 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 oldAbsPath = QDir(spath).absoluteFilePath(filepath);
const QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath); const QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath);
// Make sure the file does not already exists // 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 // Move wanted files back to their original folder
if (priorities[i] > 0) { if (priorities[i] > DownloadPriority::Ignored) {
const QString parentRelPath = Utils::Fs::branchPath(filepath); const QString parentRelPath = Utils::Fs::branchPath(filepath);
if (QDir(parentRelPath).dirName() == ".unwanted") { if (QDir(parentRelPath).dirName() == ".unwanted") {
const QString oldName = Utils::Fs::fileName(filepath); const QString oldName = Utils::Fs::fileName(filepath);

33
src/base/bittorrent/torrenthandle.h

@ -42,7 +42,9 @@
#include <QString> #include <QString>
#include <QVector> #include <QVector>
#include "private/libtorrentfwd.h"
#include "private/speedmonitor.h" #include "private/speedmonitor.h"
#include "downloadpriority.h"
#include "infohash.h" #include "infohash.h"
#include "torrentinfo.h" #include "torrentinfo.h"
@ -53,29 +55,6 @@ class QDateTime;
class QStringList; class QStringList;
class QUrl; 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 namespace BitTorrent
{ {
class PeerInfo; class PeerInfo;
@ -103,7 +82,7 @@ namespace BitTorrent
int uploadLimit; int uploadLimit;
int downloadLimit; int downloadLimit;
// for new torrents // for new torrents
QVector<int> filePriorities; QVector<DownloadPriority> filePriorities;
// for restored torrents // for restored torrents
qreal ratioLimit; qreal ratioLimit;
int seedingTimeLimit; int seedingTimeLimit;
@ -258,7 +237,7 @@ namespace BitTorrent
qlonglong fileSize(int index) const; qlonglong fileSize(int index) const;
QStringList absoluteFilePaths() const; QStringList absoluteFilePaths() const;
QStringList absoluteFilePathsUnwanted() const; QStringList absoluteFilePathsUnwanted() const;
QVector<int> filePriorities() const; QVector<DownloadPriority> filePriorities() const;
TorrentInfo info() const; TorrentInfo info() const;
bool isSeed() const; bool isSeed() const;
@ -337,7 +316,7 @@ namespace BitTorrent
void forceRecheck(); void forceRecheck();
void renameFile(int index, const QString &name); void renameFile(int index, const QString &name);
bool saveTorrentFile(const QString &path); bool saveTorrentFile(const QString &path);
void prioritizeFiles(const QVector<int> &priorities); void prioritizeFiles(const QVector<DownloadPriority> &priorities);
void setRatioLimit(qreal limit); void setRatioLimit(qreal limit);
void setSeedingTimeLimit(int limit); void setSeedingTimeLimit(int limit);
void setUploadLimit(int limit); void setUploadLimit(int limit);
@ -410,7 +389,7 @@ namespace BitTorrent
bool addTracker(const TrackerEntry &tracker); bool addTracker(const TrackerEntry &tracker);
bool addUrlSeed(const QUrl &urlSeed); bool addUrlSeed(const QUrl &urlSeed);
bool removeUrlSeed(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; Session *const m_session;
libtorrent::torrent_handle m_nativeHandle; libtorrent::torrent_handle m_nativeHandle;

39
src/base/bittorrent/torrentinfo.cpp

@ -28,6 +28,7 @@
#include "torrentinfo.h" #include "torrentinfo.h"
#include <boost/optional.hpp>
#include <libtorrent/error_code.hpp> #include <libtorrent/error_code.hpp>
#include <QByteArray> #include <QByteArray>
@ -42,12 +43,27 @@
#include "infohash.h" #include "infohash.h"
#include "trackerentry.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; namespace libt = libtorrent;
using namespace BitTorrent; using namespace BitTorrent;
TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo) TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo)
{ {
#if (LIBTORRENT_VERSION_NUM < 10200)
m_nativeInfo = boost::const_pointer_cast<libt::torrent_info>(nativeInfo); 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) TorrentInfo::TorrentInfo(const TorrentInfo &other)
@ -190,7 +206,7 @@ int TorrentInfo::pieceLength() const
int TorrentInfo::pieceLength(const int index) const int TorrentInfo::pieceLength(const int index) const
{ {
if (!isValid()) return -1; if (!isValid()) return -1;
return m_nativeInfo->piece_size(index); return m_nativeInfo->piece_size(LTPieceIndex {index});
} }
int TorrentInfo::piecesCount() const int TorrentInfo::piecesCount() const
@ -202,7 +218,8 @@ int TorrentInfo::piecesCount() const
QString TorrentInfo::filePath(const int index) const QString TorrentInfo::filePath(const int index) const
{ {
if (!isValid()) return {}; 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 QStringList TorrentInfo::filePaths() const
@ -222,19 +239,20 @@ QString TorrentInfo::fileName(const int index) const
QString TorrentInfo::origFilePath(const int index) const QString TorrentInfo::origFilePath(const int index) const
{ {
if (!isValid()) return {}; 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 qlonglong TorrentInfo::fileSize(const int index) const
{ {
if (!isValid()) return -1; 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 qlonglong TorrentInfo::fileOffset(const int index) const
{ {
if (!isValid()) return -1; if (!isValid()) return -1;
return m_nativeInfo->files().file_offset(index); return m_nativeInfo->files().file_offset(LTFileIndex {index});
} }
QList<TrackerEntry> TorrentInfo::trackers() const QList<TrackerEntry> TorrentInfo::trackers() const
@ -285,11 +303,12 @@ QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
return {}; return {};
const std::vector<libt::file_slice> files( 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; QVector<int> res;
res.reserve(int(files.size())); res.reserve(int(files.size()));
std::transform(files.begin(), files.end(), std::back_inserter(res), 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; return res;
} }
@ -304,7 +323,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
hashes.reserve(count); hashes.reserve(count);
for (int i = 0; i < count; ++i) 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; return hashes;
} }
@ -333,8 +352,8 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
} }
const libt::file_storage &files = nativeInfo()->files(); const libt::file_storage &files = nativeInfo()->files();
const auto fileSize = files.file_size(fileIndex); const auto fileSize = files.file_size(LTFileIndex {fileIndex});
const auto fileOffset = files.file_offset(fileIndex); const auto fileOffset = files.file_offset(LTFileIndex {fileIndex});
return makeInterval(static_cast<int>(fileOffset / pieceLength()), return makeInterval(static_cast<int>(fileOffset / pieceLength()),
static_cast<int>((fileOffset + fileSize - 1) / pieceLength())); static_cast<int>((fileOffset + fileSize - 1) / pieceLength()));
} }

11
src/base/bittorrent/torrentinfo.h

@ -30,12 +30,14 @@
#define BITTORRENT_TORRENTINFO_H #define BITTORRENT_TORRENTINFO_H
#include <libtorrent/torrent_info.hpp> #include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include <QCoreApplication> #include <QCoreApplication>
#include <QList> #include <QList>
#include <QVector> #include <QVector>
#include "base/indexrange.h" #include "base/indexrange.h"
#include "private/libtorrentfwd.h"
class QByteArray; class QByteArray;
class QDateTime; class QDateTime;
@ -53,8 +55,13 @@ namespace BitTorrent
Q_DECLARE_TR_FUNCTIONS(TorrentInfo) Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
public: public:
typedef boost::shared_ptr<const libtorrent::torrent_info> NativeConstPtr; #if (LIBTORRENT_VERSION_NUM < 10200)
typedef boost::shared_ptr<libtorrent::torrent_info> NativePtr; 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 = {}); explicit TorrentInfo(NativeConstPtr nativeInfo = {});
TorrentInfo(const TorrentInfo &other); TorrentInfo(const TorrentInfo &other);

49
src/base/bittorrent/trackerentry.cpp

@ -28,6 +28,10 @@
#include "trackerentry.h" #include "trackerentry.h"
#include <algorithm>
#include <libtorrent/version.hpp>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
@ -48,6 +52,19 @@ QString TrackerEntry::url() const
return QString::fromStdString(m_nativeEntry.url); 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 int TrackerEntry::tier() const
{ {
return m_nativeEntry.tier; return m_nativeEntry.tier;
@ -57,7 +74,7 @@ TrackerEntry::Status TrackerEntry::status() const
{ {
// libtorrent::announce_entry::is_working() returns // libtorrent::announce_entry::is_working() returns
// true when the tracker hasn't been tried yet. // true when the tracker hasn't been tried yet.
if (m_nativeEntry.verified && m_nativeEntry.is_working()) if (m_nativeEntry.verified && isWorking())
return Working; return Working;
if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating) if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating)
return Updating; return Updating;
@ -72,6 +89,36 @@ void TrackerEntry::setTier(const int value)
m_nativeEntry.tier = 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 libtorrent::announce_entry TrackerEntry::nativeEntry() const
{ {
return m_nativeEntry; return m_nativeEntry;

5
src/base/bittorrent/trackerentry.h

@ -53,11 +53,16 @@ namespace BitTorrent
TrackerEntry &operator=(const TrackerEntry &other) = default; TrackerEntry &operator=(const TrackerEntry &other) = default;
QString url() const; QString url() const;
bool isWorking() const;
Status status() const; Status status() const;
int tier() const; int tier() const;
void setTier(int value); void setTier(int value);
int numSeeds() const;
int numLeeches() const;
int numDownloaded() const;
libtorrent::announce_entry nativeEntry() const; libtorrent::announce_entry nativeEntry() const;
private: private:

103
src/base/net/portforwarder.cpp

@ -28,110 +28,21 @@
#include "portforwarder.h" #include "portforwarder.h"
#include <QDebug> Net::PortForwarder::PortForwarder(QObject *parent)
: QObject {parent}
#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)
{
if (SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool())
start();
}
PortForwarder::~PortForwarder()
{ {
stop(); Q_ASSERT(!m_instance);
m_instance = this;
} }
void PortForwarder::initInstance(libtorrent::session *const provider) Net::PortForwarder::~PortForwarder()
{ {
if (!m_instance)
m_instance = new PortForwarder(provider);
}
void PortForwarder::freeInstance()
{
if (m_instance) {
delete m_instance;
m_instance = nullptr; m_instance = nullptr;
}
} }
PortForwarder *PortForwarder::instance() Net::PortForwarder *Net::PortForwarder::instance()
{ {
return m_instance; return m_instance;
} }
bool PortForwarder::isEnabled() const Net::PortForwarder *Net::PortForwarder::m_instance = nullptr;
{
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;

30
src/base/net/portforwarder.h

@ -29,43 +29,27 @@
#ifndef NET_PORTFORWARDER_H #ifndef NET_PORTFORWARDER_H
#define NET_PORTFORWARDER_H #define NET_PORTFORWARDER_H
#include <QHash>
#include <QObject> #include <QObject>
namespace libtorrent
{
class session;
}
namespace Net namespace Net
{ {
class PortForwarder : public QObject class PortForwarder : public QObject
{ {
Q_OBJECT
Q_DISABLE_COPY(PortForwarder) Q_DISABLE_COPY(PortForwarder)
public: public:
static void initInstance(libtorrent::session *const provider); explicit PortForwarder(QObject *parent = nullptr);
static void freeInstance(); ~PortForwarder() override;
static PortForwarder *instance(); static PortForwarder *instance();
bool isEnabled() const; virtual bool isEnabled() const = 0;
void setEnabled(bool enabled); virtual void setEnabled(bool enabled) = 0;
void addPort(quint16 port); virtual void addPort(quint16 port) = 0;
void deletePort(quint16 port); virtual void deletePort(quint16 port) = 0;
private: 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; static PortForwarder *m_instance;
}; };
} }

14
src/gui/addnewtorrentdialog.cpp

@ -37,7 +37,7 @@
#include <QUrl> #include <QUrl>
#include <QVector> #include <QVector>
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/magneturi.h" #include "base/bittorrent/magneturi.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
@ -420,10 +420,10 @@ void AddNewTorrentDialog::updateDiskSpaceLabel()
if (m_hasMetadata) { if (m_hasMetadata) {
if (m_contentModel) { if (m_contentModel) {
const QVector<int> priorities = m_contentModel->model()->getFilePriorities(); const QVector<BitTorrent::DownloadPriority> priorities = m_contentModel->model()->getFilePriorities();
Q_ASSERT(priorities.size() == m_torrentInfo.filesCount()); Q_ASSERT(priorities.size() == m_torrentInfo.filesCount());
for (int i = 0; i < priorities.size(); ++i) for (int i = 0; i < priorities.size(); ++i)
if (priorities[i] > 0) if (priorities[i] > BitTorrent::DownloadPriority::Ignored)
torrentSize += m_torrentInfo.fileSize(i); torrentSize += m_torrentInfo.fileSize(i);
} }
else { else {
@ -612,13 +612,13 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &)
renameSelectedFile(); renameSelectedFile();
} }
else { else {
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (act == m_ui->actionHigh) if (act == m_ui->actionHigh)
prio = BitTorrent::FilePriority::High; prio = BitTorrent::DownloadPriority::High;
else if (act == m_ui->actionMaximum) else if (act == m_ui->actionMaximum)
prio = BitTorrent::FilePriority::Maximum; prio = BitTorrent::DownloadPriority::Maximum;
else if (act == m_ui->actionNotDownloaded) else if (act == m_ui->actionNotDownloaded)
prio = BitTorrent::FilePriority::Ignored; prio = BitTorrent::DownloadPriority::Ignored;
qDebug("Setting files priority"); qDebug("Setting files priority");
for (const QModelIndex &index : selectedRows) { for (const QModelIndex &index : selectedRows) {

16
src/gui/properties/propertieswidget.cpp

@ -39,7 +39,7 @@
#include <QThread> #include <QThread>
#include <QUrl> #include <QUrl>
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "base/unicodestrings.h" #include "base/unicodestrings.h"
@ -621,13 +621,13 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
renameSelectedFile(); renameSelectedFile();
} }
else { else {
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (act == m_ui->actionHigh) if (act == m_ui->actionHigh)
prio = BitTorrent::FilePriority::High; prio = BitTorrent::DownloadPriority::High;
else if (act == m_ui->actionMaximum) else if (act == m_ui->actionMaximum)
prio = BitTorrent::FilePriority::Maximum; prio = BitTorrent::DownloadPriority::Maximum;
else if (act == m_ui->actionNotDownloaded) else if (act == m_ui->actionNotDownloaded)
prio = BitTorrent::FilePriority::Ignored; prio = BitTorrent::DownloadPriority::Ignored;
qDebug("Setting files priority"); qDebug("Setting files priority");
for (const QModelIndex &index : selectedRows) { for (const QModelIndex &index : selectedRows) {
@ -894,11 +894,7 @@ void PropertiesWidget::editWebSeed()
void PropertiesWidget::applyPriorities() void PropertiesWidget::applyPriorities()
{ {
qDebug("Saving files priorities"); m_torrent->prioritizeFiles(m_propListModel->model()->getFilePriorities());
const QVector<int> priorities = m_propListModel->model()->getFilePriorities();
// Prioritize the files
qDebug("prioritize files: %d", priorities[0]);
m_torrent->prioritizeFiles(priorities);
} }
void PropertiesWidget::filteredFilesChanged() void PropertiesWidget::filteredFilesChanged()

32
src/gui/properties/proplistdelegate.cpp

@ -40,7 +40,7 @@
#include <QProxyStyle> #include <QProxyStyle>
#endif #endif
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "base/unicodestrings.h" #include "base/unicodestrings.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/string.h" #include "base/utils/string.h"
@ -93,7 +93,7 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
newopt.maximum = 100; newopt.maximum = 100;
newopt.minimum = 0; newopt.minimum = 0;
newopt.textVisible = true; newopt.textVisible = true;
if (index.sibling(index.row(), PRIORITY).data().toInt() == static_cast<int>(BitTorrent::FilePriority::Ignored)) { if (index.sibling(index.row(), PRIORITY).data().toInt() == static_cast<int>(BitTorrent::DownloadPriority::Ignored)) {
newopt.state &= ~QStyle::State_Enabled; newopt.state &= ~QStyle::State_Enabled;
newopt.palette = progressBarDisabledPalette(); newopt.palette = progressBarDisabledPalette();
} }
@ -111,17 +111,17 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
break; break;
case PRIORITY: { case PRIORITY: {
QString text = ""; QString text = "";
switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) { switch (static_cast<BitTorrent::DownloadPriority>(index.data().toInt())) {
case BitTorrent::FilePriority::Mixed: case BitTorrent::DownloadPriority::Mixed:
text = tr("Mixed", "Mixed (priorities"); text = tr("Mixed", "Mixed (priorities");
break; break;
case BitTorrent::FilePriority::Ignored: case BitTorrent::DownloadPriority::Ignored:
text = tr("Not downloaded"); text = tr("Not downloaded");
break; break;
case BitTorrent::FilePriority::High: case BitTorrent::DownloadPriority::High:
text = tr("High", "High (priority)"); text = tr("High", "High (priority)");
break; break;
case BitTorrent::FilePriority::Maximum: case BitTorrent::DownloadPriority::Maximum:
text = tr("Maximum", "Maximum (priority)"); text = tr("Maximum", "Maximum (priority)");
break; break;
default: default:
@ -155,14 +155,14 @@ void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
{ {
auto *combobox = static_cast<QComboBox *>(editor); auto *combobox = static_cast<QComboBox *>(editor);
// Set combobox index // Set combobox index
switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) { switch (static_cast<BitTorrent::DownloadPriority>(index.data().toInt())) {
case BitTorrent::FilePriority::Ignored: case BitTorrent::DownloadPriority::Ignored:
combobox->setCurrentIndex(0); combobox->setCurrentIndex(0);
break; break;
case BitTorrent::FilePriority::High: case BitTorrent::DownloadPriority::High:
combobox->setCurrentIndex(2); combobox->setCurrentIndex(2);
break; break;
case BitTorrent::FilePriority::Maximum: case BitTorrent::DownloadPriority::Maximum:
combobox->setCurrentIndex(3); combobox->setCurrentIndex(3);
break; break;
default: default:
@ -181,7 +181,7 @@ QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewI
return nullptr; return nullptr;
} }
if (index.data().toInt() == static_cast<int>(BitTorrent::FilePriority::Mixed)) if (index.data().toInt() == static_cast<int>(BitTorrent::DownloadPriority::Mixed))
return nullptr; return nullptr;
auto *editor = new QComboBox(parent); auto *editor = new QComboBox(parent);
@ -199,16 +199,16 @@ void PropListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
int value = combobox->currentIndex(); int value = combobox->currentIndex();
qDebug("PropListDelegate: setModelData(%d)", value); qDebug("PropListDelegate: setModelData(%d)", value);
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; // NORMAL BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal; // NORMAL
switch (value) { switch (value) {
case 0: case 0:
prio = BitTorrent::FilePriority::Ignored; // IGNORED prio = BitTorrent::DownloadPriority::Ignored; // IGNORED
break; break;
case 2: case 2:
prio = BitTorrent::FilePriority::High; // HIGH prio = BitTorrent::DownloadPriority::High; // HIGH
break; break;
case 3: case 3:
prio = BitTorrent::FilePriority::Maximum; // MAX prio = BitTorrent::DownloadPriority::Maximum; // MAX
break; break;
} }

6
src/gui/properties/trackerlistwidget.cpp

@ -367,9 +367,9 @@ void TrackerListWidget::loadTrackers()
} }
item->setText(COL_PEERS, QString::number(data.numPeers)); item->setText(COL_PEERS, QString::number(data.numPeers));
item->setText(COL_SEEDS, (entry.nativeEntry().scrape_complete > -1) ? QString::number(entry.nativeEntry().scrape_complete) : tr("N/A")); item->setText(COL_SEEDS, (entry.numSeeds() > -1) ? QString::number(entry.numSeeds()) : tr("N/A"));
item->setText(COL_LEECHES, (entry.nativeEntry().scrape_incomplete > -1) ? QString::number(entry.nativeEntry().scrape_incomplete) : tr("N/A")); item->setText(COL_LEECHES, (entry.numLeeches() > -1) ? QString::number(entry.numLeeches()) : tr("N/A"));
item->setText(COL_DOWNLOADED, (entry.nativeEntry().scrape_downloaded > -1) ? QString::number(entry.nativeEntry().scrape_downloaded) : tr("N/A")); item->setText(COL_DOWNLOADED, (entry.numDownloaded() > -1) ? QString::number(entry.numDownloaded()) : tr("N/A"));
item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter)); item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter));
item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));

32
src/gui/torrentcontentmodel.cpp

@ -50,7 +50,7 @@
#include <QPixmapCache> #include <QPixmapCache>
#endif #endif
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "base/global.h" #include "base/global.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
@ -239,7 +239,7 @@ void TorrentContentModel::updateFilesProgress(const QVector<qreal> &fp)
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }
void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio) void TorrentContentModel::updateFilesPriorities(const QVector<BitTorrent::DownloadPriority> &fprio)
{ {
Q_ASSERT(m_filesIndex.size() == fprio.size()); Q_ASSERT(m_filesIndex.size() == fprio.size());
// XXX: Why is this necessary? // XXX: Why is this necessary?
@ -248,7 +248,7 @@ void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio)
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
for (int i = 0; i < fprio.size(); ++i) for (int i = 0; i < fprio.size(); ++i)
m_filesIndex[i]->setPriority(static_cast<BitTorrent::FilePriority>(fprio[i])); m_filesIndex[i]->setPriority(static_cast<BitTorrent::DownloadPriority>(fprio[i]));
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }
@ -266,12 +266,12 @@ void TorrentContentModel::updateFilesAvailability(const QVector<qreal> &fa)
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }
QVector<int> TorrentContentModel::getFilePriorities() const QVector<BitTorrent::DownloadPriority> TorrentContentModel::getFilePriorities() const
{ {
QVector<int> prio; QVector<BitTorrent::DownloadPriority> prio;
prio.reserve(m_filesIndex.size()); prio.reserve(m_filesIndex.size());
for (const TorrentContentModelFile *file : asConst(m_filesIndex)) for (const TorrentContentModelFile *file : asConst(m_filesIndex))
prio.push_back(static_cast<int>(file->priority())); prio.push_back(file->priority());
return prio; return prio;
} }
@ -279,7 +279,7 @@ bool TorrentContentModel::allFiltered() const
{ {
return std::all_of(m_filesIndex.cbegin(), m_filesIndex.cend(), [](const TorrentContentModelFile *fileItem) return std::all_of(m_filesIndex.cbegin(), m_filesIndex.cend(), [](const TorrentContentModelFile *fileItem)
{ {
return (fileItem->priority() == BitTorrent::FilePriority::Ignored); return (fileItem->priority() == BitTorrent::DownloadPriority::Ignored);
}); });
} }
@ -300,11 +300,11 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
auto *item = static_cast<TorrentContentModelItem*>(index.internalPointer()); auto *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
qDebug("setData(%s, %d", qUtf8Printable(item->name()), value.toInt()); qDebug("setData(%s, %d", qUtf8Printable(item->name()), value.toInt());
if (static_cast<int>(item->priority()) != value.toInt()) { if (static_cast<int>(item->priority()) != value.toInt()) {
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (value.toInt() == Qt::PartiallyChecked) if (value.toInt() == Qt::PartiallyChecked)
prio = BitTorrent::FilePriority::Mixed; prio = BitTorrent::DownloadPriority::Mixed;
else if (value.toInt() == Qt::Unchecked) else if (value.toInt() == Qt::Unchecked)
prio = BitTorrent::FilePriority::Ignored; prio = BitTorrent::DownloadPriority::Ignored;
item->setPriority(prio); item->setPriority(prio);
// Update folders progress in the tree // Update folders progress in the tree
@ -324,7 +324,7 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
item->setName(value.toString()); item->setName(value.toString());
break; break;
case TorrentContentModelItem::COL_PRIO: case TorrentContentModelItem::COL_PRIO:
item->setPriority(static_cast<BitTorrent::FilePriority>(value.toInt())); item->setPriority(static_cast<BitTorrent::DownloadPriority>(value.toInt()));
break; break;
default: default:
return false; return false;
@ -366,9 +366,9 @@ QVariant TorrentContentModel::data(const QModelIndex &index, int role) const
} }
if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) { if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) {
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::FilePriority::Ignored)) if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::DownloadPriority::Ignored))
return Qt::Unchecked; return Qt::Unchecked;
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::FilePriority::Mixed)) if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::DownloadPriority::Mixed))
return Qt::PartiallyChecked; return Qt::PartiallyChecked;
return Qt::Checked; return Qt::Checked;
} }
@ -503,8 +503,8 @@ void TorrentContentModel::selectAll()
{ {
for (int i = 0; i < m_rootItem->childCount(); ++i) { for (int i = 0; i < m_rootItem->childCount(); ++i) {
TorrentContentModelItem* child = m_rootItem->child(i); TorrentContentModelItem* child = m_rootItem->child(i);
if (child->priority() == BitTorrent::FilePriority::Ignored) if (child->priority() == BitTorrent::DownloadPriority::Ignored)
child->setPriority(BitTorrent::FilePriority::Normal); child->setPriority(BitTorrent::DownloadPriority::Normal);
} }
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }
@ -512,6 +512,6 @@ void TorrentContentModel::selectAll()
void TorrentContentModel::selectNone() void TorrentContentModel::selectNone()
{ {
for (int i = 0; i < m_rootItem->childCount(); ++i) for (int i = 0; i < m_rootItem->childCount(); ++i)
m_rootItem->child(i)->setPriority(BitTorrent::FilePriority::Ignored); m_rootItem->child(i)->setPriority(BitTorrent::DownloadPriority::Ignored);
emit dataChanged(index(0, 0), index(rowCount(), columnCount())); emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
} }

5
src/gui/torrentcontentmodel.h

@ -43,15 +43,16 @@ class TorrentContentModelFile;
class TorrentContentModel : public QAbstractItemModel class TorrentContentModel : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(TorrentContentModel)
public: public:
TorrentContentModel(QObject *parent = nullptr); TorrentContentModel(QObject *parent = nullptr);
~TorrentContentModel() override; ~TorrentContentModel() override;
void updateFilesProgress(const QVector<qreal> &fp); void updateFilesProgress(const QVector<qreal> &fp);
void updateFilesPriorities(const QVector<int> &fprio); void updateFilesPriorities(const QVector<BitTorrent::DownloadPriority> &fprio);
void updateFilesAvailability(const QVector<qreal> &fa); void updateFilesAvailability(const QVector<qreal> &fa);
QVector<int> getFilePriorities() const; QVector<BitTorrent::DownloadPriority> getFilePriorities() const;
bool allFiltered() const; bool allFiltered() const;
int columnCount(const QModelIndex &parent = {}) const override; int columnCount(const QModelIndex &parent = {}) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;

4
src/gui/torrentcontentmodelfile.cpp

@ -52,9 +52,9 @@ int TorrentContentModelFile::fileIndex() const
return m_fileIndex; return m_fileIndex;
} }
void TorrentContentModelFile::setPriority(BitTorrent::FilePriority newPriority, bool updateParent) void TorrentContentModelFile::setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent)
{ {
Q_ASSERT(newPriority != BitTorrent::FilePriority::Mixed); Q_ASSERT(newPriority != BitTorrent::DownloadPriority::Mixed);
if (m_priority == newPriority) if (m_priority == newPriority)
return; return;

4
src/gui/torrentcontentmodelfile.h

@ -29,7 +29,7 @@
#ifndef TORRENTCONTENTMODELFILE_H #ifndef TORRENTCONTENTMODELFILE_H
#define TORRENTCONTENTMODELFILE_H #define TORRENTCONTENTMODELFILE_H
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "torrentcontentmodelitem.h" #include "torrentcontentmodelitem.h"
class TorrentContentModelFile : public TorrentContentModelItem class TorrentContentModelFile : public TorrentContentModelItem
@ -39,7 +39,7 @@ public:
TorrentContentModelFolder *parent, int fileIndex); TorrentContentModelFolder *parent, int fileIndex);
int fileIndex() const; int fileIndex() const;
void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) override; void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) override;
void setProgress(qreal progress); void setProgress(qreal progress);
void setAvailability(qreal availability); void setAvailability(qreal availability);
ItemType itemType() const override; ItemType itemType() const override;

12
src/gui/torrentcontentmodelfolder.cpp

@ -109,10 +109,10 @@ void TorrentContentModelFolder::updatePriority()
// If all children have the same priority // If all children have the same priority
// then the folder should have the same // then the folder should have the same
// priority // priority
const BitTorrent::FilePriority prio = m_childItems.first()->priority(); const BitTorrent::DownloadPriority prio = m_childItems.first()->priority();
for (int i = 1; i < m_childItems.size(); ++i) { for (int i = 1; i < m_childItems.size(); ++i) {
if (m_childItems.at(i)->priority() != prio) { if (m_childItems.at(i)->priority() != prio) {
setPriority(BitTorrent::FilePriority::Mixed); setPriority(BitTorrent::DownloadPriority::Mixed);
return; return;
} }
} }
@ -121,7 +121,7 @@ void TorrentContentModelFolder::updatePriority()
setPriority(prio); setPriority(prio);
} }
void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority, bool updateParent) void TorrentContentModelFolder::setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent)
{ {
if (m_priority == newPriority) if (m_priority == newPriority)
return; return;
@ -133,7 +133,7 @@ void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority
m_parentItem->updatePriority(); m_parentItem->updatePriority();
// Update children // Update children
if (m_priority != BitTorrent::FilePriority::Mixed) if (m_priority != BitTorrent::DownloadPriority::Mixed)
for (TorrentContentModelItem *child : asConst(m_childItems)) for (TorrentContentModelItem *child : asConst(m_childItems))
child->setPriority(m_priority, false); child->setPriority(m_priority, false);
} }
@ -144,7 +144,7 @@ void TorrentContentModelFolder::recalculateProgress()
qulonglong tSize = 0; qulonglong tSize = 0;
qulonglong tRemaining = 0; qulonglong tRemaining = 0;
for (TorrentContentModelItem *child : asConst(m_childItems)) { for (TorrentContentModelItem *child : asConst(m_childItems)) {
if (child->priority() == BitTorrent::FilePriority::Ignored) if (child->priority() == BitTorrent::DownloadPriority::Ignored)
continue; continue;
if (child->itemType() == FolderType) if (child->itemType() == FolderType)
@ -167,7 +167,7 @@ void TorrentContentModelFolder::recalculateAvailability()
qulonglong tSize = 0; qulonglong tSize = 0;
bool foundAnyData = false; bool foundAnyData = false;
for (TorrentContentModelItem *child : asConst(m_childItems)) { for (TorrentContentModelItem *child : asConst(m_childItems)) {
if (child->priority() == BitTorrent::FilePriority::Ignored) if (child->priority() == BitTorrent::DownloadPriority::Ignored)
continue; continue;
if (child->itemType() == FolderType) if (child->itemType() == FolderType)

4
src/gui/torrentcontentmodelfolder.h

@ -29,7 +29,7 @@
#ifndef TORRENTCONTENTMODELFOLDER_H #ifndef TORRENTCONTENTMODELFOLDER_H
#define TORRENTCONTENTMODELFOLDER_H #define TORRENTCONTENTMODELFOLDER_H
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "torrentcontentmodelitem.h" #include "torrentcontentmodelitem.h"
class TorrentContentModelFolder : public TorrentContentModelItem class TorrentContentModelFolder : public TorrentContentModelItem
@ -50,7 +50,7 @@ public:
void recalculateAvailability(); void recalculateAvailability();
void updatePriority(); void updatePriority();
void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) override; void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) override;
void deleteAllChildren(); void deleteAllChildren();
const QList<TorrentContentModelItem*> &children() const; const QList<TorrentContentModelItem*> &children() const;

4
src/gui/torrentcontentmodelitem.cpp

@ -38,7 +38,7 @@ TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *pare
: m_parentItem(parent) : m_parentItem(parent)
, m_size(0) , m_size(0)
, m_remaining(0) , m_remaining(0)
, m_priority(BitTorrent::FilePriority::Normal) , m_priority(BitTorrent::DownloadPriority::Normal)
, m_progress(0) , m_progress(0)
, m_availability(-1.) , m_availability(-1.)
{ {
@ -90,7 +90,7 @@ qreal TorrentContentModelItem::availability() const
return (m_size > 0) ? m_availability : 0; return (m_size > 0) ? m_availability : 0;
} }
BitTorrent::FilePriority TorrentContentModelItem::priority() const BitTorrent::DownloadPriority TorrentContentModelItem::priority() const
{ {
Q_ASSERT(!isRootItem()); Q_ASSERT(!isRootItem());
return m_priority; return m_priority;

8
src/gui/torrentcontentmodelitem.h

@ -32,7 +32,7 @@
#include <QList> #include <QList>
#include <QVariant> #include <QVariant>
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
class TorrentContentModelFolder; class TorrentContentModelFolder;
@ -72,8 +72,8 @@ public:
qreal availability() const; qreal availability() const;
BitTorrent::FilePriority priority() const; BitTorrent::DownloadPriority priority() const;
virtual void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) = 0; virtual void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) = 0;
int columnCount() const; int columnCount() const;
QVariant data(int column) const; QVariant data(int column) const;
@ -87,7 +87,7 @@ protected:
QString m_name; QString m_name;
qulonglong m_size; qulonglong m_size;
qulonglong m_remaining; qulonglong m_remaining;
BitTorrent::FilePriority m_priority; BitTorrent::DownloadPriority m_priority;
qreal m_progress; qreal m_progress;
qreal m_availability; qreal m_availability;
}; };

2
src/webui/api/serialize/serialize_torrent.cpp

@ -92,7 +92,7 @@ QVariantMap serialize(const BitTorrent::TorrentHandle &torrent)
ret[KEY_TORRENT_PROGRESS] = torrent.progress(); ret[KEY_TORRENT_PROGRESS] = torrent.progress();
ret[KEY_TORRENT_DLSPEED] = torrent.downloadPayloadRate(); ret[KEY_TORRENT_DLSPEED] = torrent.downloadPayloadRate();
ret[KEY_TORRENT_UPSPEED] = torrent.uploadPayloadRate(); ret[KEY_TORRENT_UPSPEED] = torrent.uploadPayloadRate();
ret[KEY_TORRENT_PRIORITY] = torrent.queuePosition(); ret[KEY_TORRENT_PRIORITY] = static_cast<int>(torrent.queuePosition());
ret[KEY_TORRENT_SEEDS] = torrent.seedsCount(); ret[KEY_TORRENT_SEEDS] = torrent.seedsCount();
ret[KEY_TORRENT_NUM_COMPLETE] = torrent.totalSeedsCount(); ret[KEY_TORRENT_NUM_COMPLETE] = torrent.totalSeedsCount();
ret[KEY_TORRENT_LEECHS] = torrent.leechsCount(); ret[KEY_TORRENT_LEECHS] = torrent.leechsCount();

18
src/webui/api/torrentscontroller.cpp

@ -39,7 +39,7 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QUrl> #include <QUrl>
#include "base/bittorrent/filepriority.h" #include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/peerinfo.h" #include "base/bittorrent/peerinfo.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
@ -393,9 +393,9 @@ void TorrentsController::trackersAction()
{KEY_TRACKER_STATUS, static_cast<int>(tracker.status())}, {KEY_TRACKER_STATUS, static_cast<int>(tracker.status())},
{KEY_TRACKER_PEERS_COUNT, data.numPeers}, {KEY_TRACKER_PEERS_COUNT, data.numPeers},
{KEY_TRACKER_MSG, data.lastMessage.trimmed()}, {KEY_TRACKER_MSG, data.lastMessage.trimmed()},
{KEY_TRACKER_SEEDS_COUNT, tracker.nativeEntry().scrape_complete}, {KEY_TRACKER_SEEDS_COUNT, tracker.numSeeds()},
{KEY_TRACKER_LEECHES_COUNT, tracker.nativeEntry().scrape_incomplete}, {KEY_TRACKER_LEECHES_COUNT, tracker.numLeeches()},
{KEY_TRACKER_DOWNLOADED_COUNT, tracker.nativeEntry().scrape_downloaded} {KEY_TRACKER_DOWNLOADED_COUNT, tracker.numDownloaded()}
}; };
} }
@ -446,14 +446,14 @@ void TorrentsController::filesAction()
throw APIError(APIErrorType::NotFound); throw APIError(APIErrorType::NotFound);
if (torrent->hasMetadata()) { if (torrent->hasMetadata()) {
const QVector<int> priorities = torrent->filePriorities(); const QVector<BitTorrent::DownloadPriority> priorities = torrent->filePriorities();
const QVector<qreal> fp = torrent->filesProgress(); const QVector<qreal> fp = torrent->filesProgress();
const QVector<qreal> fileAvailability = torrent->availableFileFractions(); const QVector<qreal> fileAvailability = torrent->availableFileFractions();
const BitTorrent::TorrentInfo info = torrent->info(); const BitTorrent::TorrentInfo info = torrent->info();
for (int i = 0; i < torrent->filesCount(); ++i) { for (int i = 0; i < torrent->filesCount(); ++i) {
QVariantMap fileDict; QVariantMap fileDict;
fileDict[KEY_FILE_PROGRESS] = fp[i]; fileDict[KEY_FILE_PROGRESS] = fp[i];
fileDict[KEY_FILE_PRIORITY] = priorities[i]; fileDict[KEY_FILE_PRIORITY] = static_cast<int>(priorities[i]);
fileDict[KEY_FILE_SIZE] = torrent->fileSize(i); fileDict[KEY_FILE_SIZE] = torrent->fileSize(i);
fileDict[KEY_FILE_AVAILABILITY] = fileAvailability[i]; fileDict[KEY_FILE_AVAILABILITY] = fileAvailability[i];
@ -701,11 +701,11 @@ void TorrentsController::filePrioAction()
const QString hash = params()["hash"]; const QString hash = params()["hash"];
bool ok = false; bool ok = false;
const int priority = params()["priority"].toInt(&ok); const auto priority = static_cast<BitTorrent::DownloadPriority>(params()["priority"].toInt(&ok));
if (!ok) if (!ok)
throw APIError(APIErrorType::BadParams, tr("Priority must be an integer")); throw APIError(APIErrorType::BadParams, tr("Priority must be an integer"));
if (!BitTorrent::isValidFilePriority(static_cast<BitTorrent::FilePriority>(priority))) if (!BitTorrent::isValidDownloadPriority(priority))
throw APIError(APIErrorType::BadParams, tr("Priority is not valid")); throw APIError(APIErrorType::BadParams, tr("Priority is not valid"));
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash); BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
@ -715,7 +715,7 @@ void TorrentsController::filePrioAction()
throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded")); throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded"));
const int filesCount = torrent->filesCount(); const int filesCount = torrent->filesCount();
QVector<int> priorities = torrent->filePriorities(); QVector<BitTorrent::DownloadPriority> priorities = torrent->filePriorities();
bool priorityChanged = false; bool priorityChanged = false;
for (const QString &fileID : params()["id"].split('|')) { for (const QString &fileID : params()["id"].split('|')) {
const int id = fileID.toInt(&ok); const int id = fileID.toInt(&ok);

Loading…
Cancel
Save