From 321d7e5b17b6e4cacf713b4f4409364a5e65873e Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Thu, 25 Apr 2024 12:18:30 +0800 Subject: [PATCH] Adjust tracker tier when adding additional trackers Closes #20102. PR #20729. --- src/base/CMakeLists.txt | 2 + src/base/bittorrent/sessionimpl.cpp | 48 +++++++-------- src/base/bittorrent/sessionimpl.h | 2 +- src/base/utils/number.cpp | 43 +++++++++++++ src/base/utils/number.h | 35 +++++++++++ src/gui/optionsdialog.ui | 2 +- src/gui/trackersadditiondialog.cpp | 10 +++- src/webui/www/private/views/preferences.html | 2 +- test/CMakeLists.txt | 1 + test/testutilsnumber.cpp | 63 ++++++++++++++++++++ 10 files changed, 180 insertions(+), 28 deletions(-) create mode 100644 src/base/utils/number.cpp create mode 100644 src/base/utils/number.h create mode 100644 test/testutilsnumber.cpp diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 4c00d5048..d764871d7 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -107,6 +107,7 @@ add_library(qbt_base STATIC utils/io.h utils/misc.h utils/net.h + utils/number.h utils/os.h utils/password.h utils/random.h @@ -201,6 +202,7 @@ add_library(qbt_base STATIC utils/io.cpp utils/misc.cpp utils/net.cpp + utils/number.cpp utils/os.cpp utils/password.cpp utils/random.cpp diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index cce3ef973..6a6c49183 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -84,6 +84,7 @@ #include "base/utils/fs.h" #include "base/utils/io.h" #include "base/utils/net.h" +#include "base/utils/number.h" #include "base/utils/random.h" #include "base/version.h" #include "bandwidthscheduler.h" @@ -2208,15 +2209,7 @@ void SessionImpl::enableBandwidthScheduler() void SessionImpl::populateAdditionalTrackers() { - m_additionalTrackerList.clear(); - - const QString trackers = additionalTrackers(); - for (QStringView tracker : asConst(QStringView(trackers).split(u'\n'))) - { - tracker = tracker.trimmed(); - if (!tracker.isEmpty()) - m_additionalTrackerList.append({.url = tracker.toString(), .tier = 0}); - } + m_additionalTrackerEntries = parseTrackerEntries(additionalTrackers()); } void SessionImpl::processShareLimits() @@ -2786,13 +2779,16 @@ bool SessionImpl::addTorrent_impl(const TorrentDescriptor &source, const AddTorr if (isAddTrackersEnabled() && !(hasMetadata && p.ti->priv())) { - p.trackers.reserve(p.trackers.size() + static_cast(m_additionalTrackerList.size())); - p.tracker_tiers.reserve(p.trackers.size() + static_cast(m_additionalTrackerList.size())); + const auto maxTierIter = std::max_element(p.tracker_tiers.cbegin(), p.tracker_tiers.cend()); + const int baseTier = (maxTierIter != p.tracker_tiers.cend()) ? (*maxTierIter + 1) : 0; + + p.trackers.reserve(p.trackers.size() + static_cast(m_additionalTrackerEntries.size())); + p.tracker_tiers.reserve(p.trackers.size() + static_cast(m_additionalTrackerEntries.size())); p.tracker_tiers.resize(p.trackers.size(), 0); - for (const TrackerEntry &trackerEntry : asConst(m_additionalTrackerList)) + for (const TrackerEntry &trackerEntry : asConst(m_additionalTrackerEntries)) { - p.trackers.push_back(trackerEntry.url.toStdString()); - p.tracker_tiers.push_back(trackerEntry.tier); + p.trackers.emplace_back(trackerEntry.url.toStdString()); + p.tracker_tiers.emplace_back(Utils::Number::clampingAdd(trackerEntry.tier, baseTier)); } } @@ -2955,13 +2951,17 @@ bool SessionImpl::downloadMetadata(const TorrentDescriptor &torrentDescr) if (isAddTrackersEnabled()) { // Use "additional trackers" when metadata retrieving (this can help when the DHT nodes are few) - p.trackers.reserve(p.trackers.size() + static_cast(m_additionalTrackerList.size())); - p.tracker_tiers.reserve(p.trackers.size() + static_cast(m_additionalTrackerList.size())); + + const auto maxTierIter = std::max_element(p.tracker_tiers.cbegin(), p.tracker_tiers.cend()); + const int baseTier = (maxTierIter != p.tracker_tiers.cend()) ? (*maxTierIter + 1) : 0; + + p.trackers.reserve(p.trackers.size() + static_cast(m_additionalTrackerEntries.size())); + p.tracker_tiers.reserve(p.trackers.size() + static_cast(m_additionalTrackerEntries.size())); p.tracker_tiers.resize(p.trackers.size(), 0); - for (const TrackerEntry &trackerEntry : asConst(m_additionalTrackerList)) + for (const TrackerEntry &trackerEntry : asConst(m_additionalTrackerEntries)) { - p.trackers.push_back(trackerEntry.url.toStdString()); - p.tracker_tiers.push_back(trackerEntry.tier); + p.trackers.emplace_back(trackerEntry.url.toStdString()); + p.tracker_tiers.emplace_back(Utils::Number::clampingAdd(trackerEntry.tier, baseTier)); } } @@ -3762,11 +3762,11 @@ QString SessionImpl::additionalTrackers() const void SessionImpl::setAdditionalTrackers(const QString &trackers) { - if (trackers != additionalTrackers()) - { - m_additionalTrackers = trackers; - populateAdditionalTrackers(); - } + if (trackers == additionalTrackers()) + return; + + m_additionalTrackers = trackers; + populateAdditionalTrackers(); } bool SessionImpl::isIPFilteringEnabled() const diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index e6e17aa29..91b986aff 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -731,7 +731,7 @@ namespace BitTorrent const bool m_wasPexEnabled = m_isPeXEnabled; int m_numResumeData = 0; - QVector m_additionalTrackerList; + QVector m_additionalTrackerEntries; QVector m_excludedFileNamesRegExpList; // Statistics diff --git a/src/base/utils/number.cpp b/src/base/utils/number.cpp new file mode 100644 index 000000000..cd4d24d72 --- /dev/null +++ b/src/base/utils/number.cpp @@ -0,0 +1,43 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Mike Tzou (Chocobo1) + * + * 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 "number.h" + +#include +#include + +int Utils::Number::clampingAdd(const int num1, const int num2) +{ + static_assert(sizeof(int64_t) > sizeof(int)); + + const int64_t intMin = std::numeric_limits::min(); + const int64_t intMax = std::numeric_limits::max(); + const int64_t sumResult = static_cast(num1) + num2; + const int64_t clampedValue = std::clamp(sumResult, intMin, intMax); + return static_cast(clampedValue); +} diff --git a/src/base/utils/number.h b/src/base/utils/number.h new file mode 100644 index 000000000..7052506a5 --- /dev/null +++ b/src/base/utils/number.h @@ -0,0 +1,35 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Mike Tzou (Chocobo1) + * + * 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 + +namespace Utils::Number +{ + // math addition that the result will never overflow/underflow + int clampingAdd(int num1, int num2); +} diff --git a/src/gui/optionsdialog.ui b/src/gui/optionsdialog.ui index 4d044e113..7035c5f63 100644 --- a/src/gui/optionsdialog.ui +++ b/src/gui/optionsdialog.ui @@ -3069,7 +3069,7 @@ Disable encryption: Only connect to peers without protocol encryption - A&utomatically add these trackers to new downloads: + A&utomatically append these trackers to new downloads: true diff --git a/src/gui/trackersadditiondialog.cpp b/src/gui/trackersadditiondialog.cpp index 344bd2fd6..fbfbdea64 100644 --- a/src/gui/trackersadditiondialog.cpp +++ b/src/gui/trackersadditiondialog.cpp @@ -36,9 +36,11 @@ #include "base/bittorrent/torrent.h" #include "base/bittorrent/trackerentry.h" +#include "base/bittorrent/trackerentrystatus.h" #include "base/global.h" #include "base/net/downloadmanager.h" #include "base/preferences.h" +#include "base/utils/number.h" #include "gui/uithememanager.h" #include "ui_trackersadditiondialog.h" @@ -74,7 +76,13 @@ TrackersAdditionDialog::~TrackersAdditionDialog() void TrackersAdditionDialog::onAccepted() const { - const QVector entries = BitTorrent::parseTrackerEntries(m_ui->textEditTrackersList->toPlainText()); + const QVector currentTrackers = m_torrent->trackers(); + const int baseTier = !currentTrackers.isEmpty() ? (currentTrackers.last().tier + 1) : 0; + + QVector entries = BitTorrent::parseTrackerEntries(m_ui->textEditTrackersList->toPlainText()); + for (BitTorrent::TrackerEntry &entry : entries) + entry.tier = Utils::Number::clampingAdd(entry.tier, baseTier); + m_torrent->addTrackers(entries); } diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index aaee0d682..3479e6d73 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -718,7 +718,7 @@
- +
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7299f8e27..e5ef618cc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,6 +18,7 @@ set(testFiles testutilsdatetime.cpp testutilsgzip.cpp testutilsio.cpp + testutilsnumber.cpp testutilsstring.cpp testutilsversion.cpp ) diff --git a/test/testutilsnumber.cpp b/test/testutilsnumber.cpp new file mode 100644 index 000000000..7a45e9782 --- /dev/null +++ b/test/testutilsnumber.cpp @@ -0,0 +1,63 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2024 Mike Tzou (Chocobo1) + * + * 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 + +#include + +#include "base/utils/number.h" + +class TestUtilsNumber final : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY_MOVE(TestUtilsNumber) + +public: + TestUtilsNumber() = default; + +private slots: + void testClampingAdd() const + { + const int intMin = std::numeric_limits::min(); + const int intMax = std::numeric_limits::max(); + + QCOMPARE(Utils::Number::clampingAdd(1, 2), 3); + QCOMPARE(Utils::Number::clampingAdd(-1, -2), -3); + + QCOMPARE(Utils::Number::clampingAdd((intMax - 1), 1), intMax); + QCOMPARE(Utils::Number::clampingAdd(intMax, 1), intMax); + QCOMPARE(Utils::Number::clampingAdd(intMax, intMax), intMax); + + QCOMPARE(Utils::Number::clampingAdd((intMin + 1), -1), intMin); + QCOMPARE(Utils::Number::clampingAdd(intMin, -1), intMin); + QCOMPARE(Utils::Number::clampingAdd(intMin, intMin), intMin); + } +}; + +QTEST_APPLESS_MAIN(TestUtilsNumber) +#include "testutilsnumber.moc"