mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-02-03 02:14:16 +00:00
Fix race condition where there was a chance to allow all ips between reparsings of the ip filter.
This commit is contained in:
parent
14513cd81f
commit
431658bee6
@ -33,17 +33,13 @@
|
|||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include <libtorrent/session.hpp>
|
|
||||||
#include <libtorrent/ip_filter.hpp>
|
|
||||||
|
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "filterparserthread.h"
|
#include "filterparserthread.h"
|
||||||
|
|
||||||
namespace libt = libtorrent;
|
namespace libt = libtorrent;
|
||||||
|
|
||||||
FilterParserThread::FilterParserThread(libt::session *s, QObject *parent)
|
FilterParserThread::FilterParserThread(QObject *parent)
|
||||||
: QThread(parent)
|
: QThread(parent)
|
||||||
, m_session(s)
|
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -55,10 +51,10 @@ FilterParserThread::~FilterParserThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser for eMule ip filter in DAT format
|
// Parser for eMule ip filter in DAT format
|
||||||
int FilterParserThread::parseDATFilterFile(QString filePath, libt::ip_filter &filter)
|
int FilterParserThread::parseDATFilterFile()
|
||||||
{
|
{
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
QFile file(filePath);
|
QFile file(m_filePath);
|
||||||
if (!file.exists()) return ruleCount;
|
if (!file.exists()) return ruleCount;
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
@ -136,7 +132,7 @@ int FilterParserThread::parseDATFilterFile(QString filePath, libt::ip_filter &fi
|
|||||||
|
|
||||||
// Now Add to the filter
|
// Now Add to the filter
|
||||||
try {
|
try {
|
||||||
filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
|
m_filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
|
||||||
++ruleCount;
|
++ruleCount;
|
||||||
}
|
}
|
||||||
catch(std::exception &) {
|
catch(std::exception &) {
|
||||||
@ -149,10 +145,10 @@ int FilterParserThread::parseDATFilterFile(QString filePath, libt::ip_filter &fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser for PeerGuardian ip filter in p2p format
|
// Parser for PeerGuardian ip filter in p2p format
|
||||||
int FilterParserThread::parseP2PFilterFile(QString filePath, libt::ip_filter &filter)
|
int FilterParserThread::parseP2PFilterFile()
|
||||||
{
|
{
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
QFile file(filePath);
|
QFile file(m_filePath);
|
||||||
if (!file.exists()) return ruleCount;
|
if (!file.exists()) return ruleCount;
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
@ -219,7 +215,7 @@ int FilterParserThread::parseP2PFilterFile(QString filePath, libt::ip_filter &fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
|
m_filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
|
||||||
++ruleCount;
|
++ruleCount;
|
||||||
}
|
}
|
||||||
catch(std::exception &) {
|
catch(std::exception &) {
|
||||||
@ -257,10 +253,10 @@ int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser for PeerGuardian ip filter in p2p format
|
// Parser for PeerGuardian ip filter in p2p format
|
||||||
int FilterParserThread::parseP2BFilterFile(QString filePath, libt::ip_filter &filter)
|
int FilterParserThread::parseP2BFilterFile()
|
||||||
{
|
{
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
QFile file(filePath);
|
QFile file(m_filePath);
|
||||||
if (!file.exists()) return ruleCount;
|
if (!file.exists()) return ruleCount;
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
@ -298,7 +294,7 @@ int FilterParserThread::parseP2BFilterFile(QString filePath, libt::ip_filter &fi
|
|||||||
libt::address_v4 last(ntohl(end));
|
libt::address_v4 last(ntohl(end));
|
||||||
// Apply to bittorrent session
|
// Apply to bittorrent session
|
||||||
try {
|
try {
|
||||||
filter.add_rule(first, last, libt::ip_filter::blocked);
|
m_filter.add_rule(first, last, libt::ip_filter::blocked);
|
||||||
++ruleCount;
|
++ruleCount;
|
||||||
}
|
}
|
||||||
catch(std::exception &) {}
|
catch(std::exception &) {}
|
||||||
@ -348,7 +344,7 @@ int FilterParserThread::parseP2BFilterFile(QString filePath, libt::ip_filter &fi
|
|||||||
libt::address_v4 last(ntohl(end));
|
libt::address_v4 last(ntohl(end));
|
||||||
// Apply to bittorrent session
|
// Apply to bittorrent session
|
||||||
try {
|
try {
|
||||||
filter.add_rule(first, last, libt::ip_filter::blocked);
|
m_filter.add_rule(first, last, libt::ip_filter::blocked);
|
||||||
++ruleCount;
|
++ruleCount;
|
||||||
}
|
}
|
||||||
catch(std::exception &) {}
|
catch(std::exception &) {}
|
||||||
@ -369,7 +365,7 @@ int FilterParserThread::parseP2BFilterFile(QString filePath, libt::ip_filter &fi
|
|||||||
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
||||||
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
||||||
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
||||||
void FilterParserThread::processFilterFile(QString filePath)
|
void FilterParserThread::processFilterFile(const QString &filePath)
|
||||||
{
|
{
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
// Already parsing a filter, m_abort first
|
// Already parsing a filter, m_abort first
|
||||||
@ -379,10 +375,16 @@ void FilterParserThread::processFilterFile(QString filePath)
|
|||||||
|
|
||||||
m_abort = false;
|
m_abort = false;
|
||||||
m_filePath = filePath;
|
m_filePath = filePath;
|
||||||
|
m_filter = libt::ip_filter();
|
||||||
// Run it
|
// Run it
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libt::ip_filter FilterParserThread::IPfilter()
|
||||||
|
{
|
||||||
|
return m_filter;
|
||||||
|
}
|
||||||
|
|
||||||
QString FilterParserThread::cleanupIPAddress(QString _ip)
|
QString FilterParserThread::cleanupIPAddress(QString _ip)
|
||||||
{
|
{
|
||||||
_ip = _ip.trimmed();
|
_ip = _ip.trimmed();
|
||||||
@ -417,25 +419,23 @@ QString FilterParserThread::cleanupIPAddress(QString _ip)
|
|||||||
void FilterParserThread::run()
|
void FilterParserThread::run()
|
||||||
{
|
{
|
||||||
qDebug("Processing filter file");
|
qDebug("Processing filter file");
|
||||||
libt::ip_filter filter = m_session->get_ip_filter();
|
|
||||||
int ruleCount = 0;
|
int ruleCount = 0;
|
||||||
if (m_filePath.endsWith(".p2p", Qt::CaseInsensitive)) {
|
if (m_filePath.endsWith(".p2p", Qt::CaseInsensitive)) {
|
||||||
// PeerGuardian p2p file
|
// PeerGuardian p2p file
|
||||||
ruleCount = parseP2PFilterFile(m_filePath, filter);
|
ruleCount = parseP2PFilterFile();
|
||||||
}
|
}
|
||||||
else if (m_filePath.endsWith(".p2b", Qt::CaseInsensitive)) {
|
else if (m_filePath.endsWith(".p2b", Qt::CaseInsensitive)) {
|
||||||
// PeerGuardian p2b file
|
// PeerGuardian p2b file
|
||||||
ruleCount = parseP2BFilterFile(m_filePath, filter);
|
ruleCount = parseP2BFilterFile();
|
||||||
}
|
}
|
||||||
else if (m_filePath.endsWith(".dat", Qt::CaseInsensitive)) {
|
else if (m_filePath.endsWith(".dat", Qt::CaseInsensitive)) {
|
||||||
// eMule DAT format
|
// eMule DAT format
|
||||||
ruleCount = parseDATFilterFile(m_filePath, filter);
|
ruleCount = parseDATFilterFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_session->set_ip_filter(filter);
|
|
||||||
emit IPFilterParsed(ruleCount);
|
emit IPFilterParsed(ruleCount);
|
||||||
}
|
}
|
||||||
catch(std::exception &) {
|
catch(std::exception &) {
|
||||||
|
@ -33,23 +33,20 @@
|
|||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <libtorrent/ip_filter.hpp>
|
||||||
|
|
||||||
class QDataStream;
|
class QDataStream;
|
||||||
class QStringList;
|
class QStringList;
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
class session;
|
|
||||||
struct ip_filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FilterParserThread : public QThread
|
class FilterParserThread : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FilterParserThread(libtorrent::session *s, QObject *parent = 0);
|
FilterParserThread(QObject *parent = 0);
|
||||||
~FilterParserThread();
|
~FilterParserThread();
|
||||||
void processFilterFile(QString filePath);
|
void processFilterFile(const QString &filePath);
|
||||||
|
libtorrent::ip_filter IPfilter();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void IPFilterParsed(int ruleCount);
|
void IPFilterParsed(int ruleCount);
|
||||||
@ -60,14 +57,14 @@ protected:
|
|||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int parseDATFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
int parseDATFilterFile();
|
||||||
int parseP2PFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
int parseP2PFilterFile();
|
||||||
int getlineInStream(QDataStream &stream, std::string &name, char delim);
|
int getlineInStream(QDataStream &stream, std::string &name, char delim);
|
||||||
int parseP2BFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
int parseP2BFilterFile();
|
||||||
|
|
||||||
libtorrent::session *m_session;
|
|
||||||
bool m_abort;
|
bool m_abort;
|
||||||
QString m_filePath;
|
QString m_filePath;
|
||||||
|
libtorrent::ip_filter m_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITTORRENT_FILTERPARSERTHREAD_H
|
#endif // BITTORRENT_FILTERPARSERTHREAD_H
|
||||||
|
@ -385,10 +385,16 @@ Session::Session(QObject *parent)
|
|||||||
.arg(encryption() == 0 ? tr("ON") : encryption() == 1 ? tr("FORCED") : tr("OFF"))
|
.arg(encryption() == 0 ? tr("ON") : encryption() == 1 ? tr("FORCED") : tr("OFF"))
|
||||||
, Log::INFO);
|
, Log::INFO);
|
||||||
|
|
||||||
if (isIPFilteringEnabled())
|
if (isIPFilteringEnabled()) {
|
||||||
|
// Manually banned IPs are handled in that function too(in the slots)
|
||||||
enableIPFilter();
|
enableIPFilter();
|
||||||
// Add the banned IPs
|
}
|
||||||
processBannedIPs();
|
else {
|
||||||
|
// Add the banned IPs
|
||||||
|
libt::ip_filter filter;
|
||||||
|
processBannedIPs(filter);
|
||||||
|
m_nativeSession->set_ip_filter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
m_categories = map_cast(m_storedCategories);
|
m_categories = map_cast(m_storedCategories);
|
||||||
if (isSubcategoriesEnabled()) {
|
if (isSubcategoriesEnabled()) {
|
||||||
@ -891,10 +897,9 @@ void Session::configure()
|
|||||||
qDebug("Session configured");
|
qDebug("Session configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::processBannedIPs()
|
void Session::processBannedIPs(libt::ip_filter &filter)
|
||||||
{
|
{
|
||||||
// First, import current filter
|
// First, import current filter
|
||||||
libt::ip_filter filter = m_nativeSession->get_ip_filter();
|
|
||||||
foreach (const QString &ip, m_bannedIPs.value()) {
|
foreach (const QString &ip, m_bannedIPs.value()) {
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
|
libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
|
||||||
@ -902,8 +907,6 @@ void Session::processBannedIPs()
|
|||||||
if (!ec)
|
if (!ec)
|
||||||
filter.add_rule(addr, addr, libt::ip_filter::blocked);
|
filter.add_rule(addr, addr, libt::ip_filter::blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nativeSession->set_ip_filter(filter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||||
@ -3028,13 +3031,12 @@ void Session::configureDeferred()
|
|||||||
void Session::enableIPFilter()
|
void Session::enableIPFilter()
|
||||||
{
|
{
|
||||||
qDebug("Enabling IPFilter");
|
qDebug("Enabling IPFilter");
|
||||||
// 1. Clear existing ban list
|
// 1. Parse the IP filter
|
||||||
// 2. Add manual ban list
|
// 2. In the slot add the manually banned IPs to the provided libtorrent::ip_filter
|
||||||
// 3. Add 3rd party ban list
|
// 3. Set the ip_filter in one go so there isn't a time window where there isn't an ip_filter
|
||||||
m_nativeSession->set_ip_filter(libt::ip_filter());
|
// set between clearing the old one and setting the new one.
|
||||||
processBannedIPs();
|
|
||||||
if (!m_filterParser) {
|
if (!m_filterParser) {
|
||||||
m_filterParser = new FilterParserThread(m_nativeSession, this);
|
m_filterParser = new FilterParserThread(this);
|
||||||
connect(m_filterParser.data(), SIGNAL(IPFilterParsed(int)), SLOT(handleIPFilterParsed(int)));
|
connect(m_filterParser.data(), SIGNAL(IPFilterParsed(int)), SLOT(handleIPFilterParsed(int)));
|
||||||
connect(m_filterParser.data(), SIGNAL(IPFilterError()), SLOT(handleIPFilterError()));
|
connect(m_filterParser.data(), SIGNAL(IPFilterError()), SLOT(handleIPFilterError()));
|
||||||
}
|
}
|
||||||
@ -3045,7 +3047,6 @@ void Session::enableIPFilter()
|
|||||||
void Session::disableIPFilter()
|
void Session::disableIPFilter()
|
||||||
{
|
{
|
||||||
qDebug("Disabling IPFilter");
|
qDebug("Disabling IPFilter");
|
||||||
m_nativeSession->set_ip_filter(libt::ip_filter());
|
|
||||||
if (m_filterParser) {
|
if (m_filterParser) {
|
||||||
disconnect(m_filterParser.data(), 0, this, 0);
|
disconnect(m_filterParser.data(), 0, this, 0);
|
||||||
delete m_filterParser;
|
delete m_filterParser;
|
||||||
@ -3054,7 +3055,9 @@ void Session::disableIPFilter()
|
|||||||
// Add the banned IPs after the IPFilter disabling
|
// Add the banned IPs after the IPFilter disabling
|
||||||
// which creates an empty filter and overrides all previously
|
// which creates an empty filter and overrides all previously
|
||||||
// applied bans.
|
// applied bans.
|
||||||
processBannedIPs();
|
libt::ip_filter filter;
|
||||||
|
processBannedIPs(filter);
|
||||||
|
m_nativeSession->set_ip_filter(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::recursiveTorrentDownload(const InfoHash &hash)
|
void Session::recursiveTorrentDownload(const InfoHash &hash)
|
||||||
@ -3191,12 +3194,21 @@ void Session::refresh()
|
|||||||
|
|
||||||
void Session::handleIPFilterParsed(int ruleCount)
|
void Session::handleIPFilterParsed(int ruleCount)
|
||||||
{
|
{
|
||||||
|
if (!m_filterParser) {
|
||||||
|
libt::ip_filter filter = m_filterParser->IPfilter();
|
||||||
|
processBannedIPs(filter);
|
||||||
|
m_nativeSession->set_ip_filter(filter);
|
||||||
|
}
|
||||||
Logger::instance()->addMessage(tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount));
|
Logger::instance()->addMessage(tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount));
|
||||||
emit IPFilterParsed(false, ruleCount);
|
emit IPFilterParsed(false, ruleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::handleIPFilterError()
|
void Session::handleIPFilterError()
|
||||||
{
|
{
|
||||||
|
libt::ip_filter filter;
|
||||||
|
processBannedIPs(filter);
|
||||||
|
m_nativeSession->set_ip_filter(filter);
|
||||||
|
|
||||||
Logger::instance()->addMessage(tr("Error: Failed to parse the provided IP filter."), Log::CRITICAL);
|
Logger::instance()->addMessage(tr("Error: Failed to parse the provided IP filter."), Log::CRITICAL);
|
||||||
emit IPFilterParsed(true, 0);
|
emit IPFilterParsed(true, 0);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ namespace libtorrent
|
|||||||
struct torrent_handle;
|
struct torrent_handle;
|
||||||
class entry;
|
class entry;
|
||||||
struct add_torrent_params;
|
struct add_torrent_params;
|
||||||
|
struct ip_filter;
|
||||||
struct pe_settings;
|
struct pe_settings;
|
||||||
#if LIBTORRENT_VERSION_NUM < 10100
|
#if LIBTORRENT_VERSION_NUM < 10100
|
||||||
struct session_settings;
|
struct session_settings;
|
||||||
@ -449,7 +450,7 @@ namespace BitTorrent
|
|||||||
void adjustLimits(libtorrent::settings_pack &settingsPack);
|
void adjustLimits(libtorrent::settings_pack &settingsPack);
|
||||||
#endif
|
#endif
|
||||||
void adjustLimits();
|
void adjustLimits();
|
||||||
void processBannedIPs();
|
void processBannedIPs(libtorrent::ip_filter &filter);
|
||||||
const QStringList getListeningIPs();
|
const QStringList getListeningIPs();
|
||||||
void configureListeningInterface();
|
void configureListeningInterface();
|
||||||
void changeSpeedLimitMode_impl(bool alternative);
|
void changeSpeedLimitMode_impl(bool alternative);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user