diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index c67a21ff8..2219a1892 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -509,14 +510,18 @@ SessionImpl::SessionImpl(QObject *parent) } ) , m_resumeDataStorageType(BITTORRENT_SESSION_KEY(u"ResumeDataStorageType"_qs), ResumeDataStorageType::Legacy) - , m_seedingLimitTimer {new QTimer {this}} - , m_resumeDataTimer {new QTimer {this}} - , m_ioThread {new QThread {this}} - , m_recentErroredTorrentsTimer {new QTimer {this}} + , m_seedingLimitTimer {new QTimer(this)} + , m_resumeDataTimer {new QTimer(this)} + , m_ioThread {new QThread(this)} + , m_asyncWorker {new QThreadPool(this)} + , m_recentErroredTorrentsTimer {new QTimer(this)} #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - , m_networkManager {new QNetworkConfigurationManager {this}} + , m_networkManager {new QNetworkConfigurationManager(this)} #endif { + // It is required to perform async access to libtorrent sequentially + m_asyncWorker->setMaxThreadCount(1); + if (port() < 0) m_port = Utils::Random::rand(1024, 65535); @@ -597,6 +602,9 @@ SessionImpl::~SessionImpl() saveStatistics(); + m_asyncWorker->clear(); + m_asyncWorker->waitForDone(); + // We must delete FilterParserThread // before we delete lt::session delete m_filterParser; @@ -2230,21 +2238,26 @@ bool SessionImpl::hasRunningSeed() const void SessionImpl::banIP(const QString &ip) { - QStringList bannedIPs = m_bannedIPs; - if (!bannedIPs.contains(ip)) + if (m_bannedIPs.get().contains(ip)) + return; + + lt::error_code ec; + const lt::address addr = lt::make_address(ip.toLatin1().constData(), ec); + Q_ASSERT(!ec); + if (ec) + return; + + invokeAsync([session = m_nativeSession, addr] { - lt::ip_filter filter = m_nativeSession->get_ip_filter(); - lt::error_code ec; - const lt::address addr = lt::make_address(ip.toLatin1().constData(), ec); - Q_ASSERT(!ec); - if (ec) return; + lt::ip_filter filter = session->get_ip_filter(); filter.add_rule(addr, addr, lt::ip_filter::blocked); - m_nativeSession->set_ip_filter(filter); + session->set_ip_filter(std::move(filter)); + }); - bannedIPs << ip; - bannedIPs.sort(); - m_bannedIPs = bannedIPs; - } + QStringList bannedIPs = m_bannedIPs; + bannedIPs.append(ip); + bannedIPs.sort(); + m_bannedIPs = bannedIPs; } // Delete a torrent from the session, given its hash @@ -2809,6 +2822,11 @@ void SessionImpl::findIncompleteFiles(const TorrentInfo &torrentInfo, const Path }); } +void SessionImpl::invokeAsync(std::function func) +{ + m_asyncWorker->start(std::move(func)); +} + // Add a torrent to libtorrent session in hidden mode // and force it to download its metadata bool SessionImpl::downloadMetadata(const MagnetUri &magnetUri) diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 69a93e25c..0e599982e 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -59,6 +59,7 @@ class QNetworkConfigurationManager; #endif class QString; class QThread; +class QThreadPool; class QTimer; class QUrl; @@ -431,6 +432,8 @@ namespace BitTorrent void findIncompleteFiles(const TorrentInfo &torrentInfo, const Path &savePath , const Path &downloadPath, const PathList &filePaths = {}) const; + void invokeAsync(std::function func); + private slots: void configureDeferred(); void readAlerts(); @@ -694,6 +697,7 @@ namespace BitTorrent QPointer m_tracker; QThread *m_ioThread = nullptr; + QThreadPool *m_asyncWorker = nullptr; ResumeDataStorage *m_resumeDataStorage = nullptr; FileSearcher *m_fileSearcher = nullptr;