mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-02 21:52:32 -06:00
Redesign main core classes.
This commit is contained in:
64
src/core/bittorrent/cachestatus.cpp
Normal file
64
src/core/bittorrent/cachestatus.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 "cachestatus.h"
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
CacheStatus::CacheStatus(const libtorrent::cache_status &nativeStatus)
|
||||
: m_nativeStatus(nativeStatus)
|
||||
{
|
||||
}
|
||||
|
||||
int CacheStatus::totalUsedBuffers() const
|
||||
{
|
||||
return m_nativeStatus.total_used_buffers;
|
||||
}
|
||||
|
||||
qreal CacheStatus::readRatio() const
|
||||
{
|
||||
if (m_nativeStatus.blocks_read > 0)
|
||||
return (static_cast<qreal>(m_nativeStatus.blocks_read_hit) / m_nativeStatus.blocks_read);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CacheStatus::jobQueueLength() const
|
||||
{
|
||||
return m_nativeStatus.job_queue_length;
|
||||
}
|
||||
|
||||
int CacheStatus::averageJobTime() const
|
||||
{
|
||||
return m_nativeStatus.average_job_time;
|
||||
}
|
||||
|
||||
qlonglong CacheStatus::queuedBytes() const
|
||||
{
|
||||
return m_nativeStatus.queued_bytes;
|
||||
}
|
||||
53
src/core/bittorrent/cachestatus.h
Normal file
53
src/core/bittorrent/cachestatus.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_CACHESTATUS_H
|
||||
#define BITTORRENT_CACHESTATUS_H
|
||||
|
||||
#include <libtorrent/disk_io_thread.hpp>
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class CacheStatus
|
||||
{
|
||||
public:
|
||||
CacheStatus(const libtorrent::cache_status &nativeStatus);
|
||||
|
||||
int totalUsedBuffers() const;
|
||||
qreal readRatio() const;
|
||||
int jobQueueLength() const;
|
||||
int averageJobTime() const;
|
||||
qlonglong queuedBytes() const;
|
||||
|
||||
private:
|
||||
libtorrent::cache_status m_nativeStatus;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_CACHESTATUS_H
|
||||
98
src/core/bittorrent/infohash.cpp
Normal file
98
src/core/bittorrent/infohash.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 <QHash>
|
||||
#include "infohash.h"
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
InfoHash::InfoHash()
|
||||
: m_valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash)
|
||||
: m_valid(true)
|
||||
, m_nativeHash(nativeHash)
|
||||
{
|
||||
char out[(libtorrent::sha1_hash::size * 2) + 1];
|
||||
libtorrent::to_hex((char const*)&m_nativeHash[0], libtorrent::sha1_hash::size, out);
|
||||
m_hashString = QString(out);
|
||||
}
|
||||
|
||||
InfoHash::InfoHash(const QString &hashString)
|
||||
: m_valid(false)
|
||||
, m_hashString(hashString)
|
||||
{
|
||||
QByteArray raw = m_hashString.toLatin1();
|
||||
if (raw.size() == 40)
|
||||
m_valid = libtorrent::from_hex(raw.constData(), 40, (char*)&m_nativeHash[0]);
|
||||
}
|
||||
|
||||
|
||||
InfoHash::InfoHash(const InfoHash &other)
|
||||
: m_valid(other.m_valid)
|
||||
, m_nativeHash(other.m_nativeHash)
|
||||
, m_hashString(other.m_hashString)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool InfoHash::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
|
||||
InfoHash::operator libtorrent::sha1_hash() const
|
||||
{
|
||||
return m_nativeHash;
|
||||
}
|
||||
|
||||
|
||||
InfoHash::operator QString() const
|
||||
{
|
||||
return m_hashString;
|
||||
}
|
||||
|
||||
|
||||
bool InfoHash::operator==(const InfoHash &other) const
|
||||
{
|
||||
return (m_nativeHash == other.m_nativeHash);
|
||||
}
|
||||
|
||||
|
||||
bool InfoHash::operator!=(const InfoHash &other) const
|
||||
{
|
||||
return (m_nativeHash != other.m_nativeHash);
|
||||
}
|
||||
|
||||
uint qHash(const InfoHash &key, uint seed)
|
||||
{
|
||||
return qHash(static_cast<QString>(key), seed);
|
||||
}
|
||||
67
src/core/bittorrent/infohash.h
Normal file
67
src/core/bittorrent/infohash.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_INFOHASH_H
|
||||
#define BITTORRENT_INFOHASH_H
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
#include <libtorrent/peer_id.hpp>
|
||||
#else
|
||||
#include <libtorrent/sha1_hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash
|
||||
{
|
||||
public:
|
||||
InfoHash();
|
||||
InfoHash(const libtorrent::sha1_hash &nativeHash);
|
||||
InfoHash(const QString &hashString);
|
||||
InfoHash(const InfoHash &other);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
operator libtorrent::sha1_hash() const;
|
||||
operator QString() const;
|
||||
bool operator==(const InfoHash &other) const;
|
||||
bool operator!=(const InfoHash &other) const;
|
||||
|
||||
private:
|
||||
bool m_valid;
|
||||
libtorrent::sha1_hash m_nativeHash;
|
||||
QString m_hashString;
|
||||
};
|
||||
}
|
||||
|
||||
uint qHash(const BitTorrent::InfoHash &key, uint seed);
|
||||
|
||||
#endif // BITTORRENT_INFOHASH_H
|
||||
95
src/core/bittorrent/magneturi.cpp
Normal file
95
src/core/bittorrent/magneturi.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/error_code.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
#include "core/utils/string.h"
|
||||
#include "magneturi.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
|
||||
MagnetUri::MagnetUri(const QString &url)
|
||||
: m_valid(false)
|
||||
, m_url(url)
|
||||
{
|
||||
if (url.isEmpty()) return;
|
||||
|
||||
libt::error_code ec;
|
||||
libt::parse_magnet_uri(url.toUtf8().constData(), m_addTorrentParams, ec);
|
||||
if (ec) return;
|
||||
|
||||
m_valid = true;
|
||||
m_hash = m_addTorrentParams.info_hash;
|
||||
m_name = String::fromStdString(m_addTorrentParams.name);
|
||||
|
||||
foreach (const std::string &tracker, m_addTorrentParams.trackers)
|
||||
m_trackers.append(String::fromStdString(tracker));
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 10000
|
||||
foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds)
|
||||
m_urlSeeds.append(QUrl(urlSeed.c_str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MagnetUri::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
InfoHash MagnetUri::hash() const
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
QString MagnetUri::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QList<TrackerEntry> MagnetUri::trackers() const
|
||||
{
|
||||
return m_trackers;
|
||||
}
|
||||
|
||||
QList<QUrl> MagnetUri::urlSeeds() const
|
||||
{
|
||||
return m_urlSeeds;
|
||||
}
|
||||
|
||||
QString MagnetUri::url() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
libtorrent::add_torrent_params MagnetUri::addTorrentParams() const
|
||||
{
|
||||
return m_addTorrentParams;
|
||||
}
|
||||
68
src/core/bittorrent/magneturi.h
Normal file
68
src/core/bittorrent/magneturi.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_MAGNETURI_H
|
||||
#define BITTORRENT_MAGNETURI_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
|
||||
#include <libtorrent/add_torrent_params.hpp>
|
||||
|
||||
#include "infohash.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class MagnetUri
|
||||
{
|
||||
public:
|
||||
explicit MagnetUri(const QString &url = QString());
|
||||
|
||||
bool isValid() const;
|
||||
InfoHash hash() const;
|
||||
QString name() const;
|
||||
QList<TrackerEntry> trackers() const;
|
||||
QList<QUrl> urlSeeds() const;
|
||||
QString url() const;
|
||||
|
||||
libtorrent::add_torrent_params addTorrentParams() const;
|
||||
|
||||
private:
|
||||
bool m_valid;
|
||||
QString m_url;
|
||||
InfoHash m_hash;
|
||||
QString m_name;
|
||||
QList<TrackerEntry> m_trackers;
|
||||
QList<QUrl> m_urlSeeds;
|
||||
libtorrent::add_torrent_params m_addTorrentParams;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_MAGNETURI_H
|
||||
271
src/core/bittorrent/peerinfo.cpp
Normal file
271
src/core/bittorrent/peerinfo.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 <libtorrent/version.hpp>
|
||||
|
||||
#include "core/utils/string.h"
|
||||
#include "peerinfo.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
|
||||
// PeerAddress
|
||||
|
||||
PeerAddress::PeerAddress()
|
||||
: port(0)
|
||||
{
|
||||
}
|
||||
|
||||
PeerAddress::PeerAddress(QHostAddress ip, ushort port)
|
||||
: ip(ip)
|
||||
, port(port)
|
||||
{
|
||||
}
|
||||
|
||||
// PeerInfo
|
||||
|
||||
PeerInfo::PeerInfo(const libt::peer_info &nativeInfo)
|
||||
: m_nativeInfo(nativeInfo)
|
||||
{
|
||||
}
|
||||
|
||||
bool PeerInfo::fromDHT() const
|
||||
{
|
||||
return (m_nativeInfo.source & libt::peer_info::dht);
|
||||
}
|
||||
|
||||
bool PeerInfo::fromPeX() const
|
||||
{
|
||||
return (m_nativeInfo.source & libt::peer_info::pex);
|
||||
}
|
||||
|
||||
bool PeerInfo::fromLSD() const
|
||||
{
|
||||
return (m_nativeInfo.source & libt::peer_info::lsd);
|
||||
}
|
||||
|
||||
QString PeerInfo::country() const
|
||||
{
|
||||
return QString(QByteArray(m_nativeInfo.country, 2));
|
||||
}
|
||||
|
||||
|
||||
bool PeerInfo::isInteresting() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::interesting);
|
||||
}
|
||||
|
||||
bool PeerInfo::isChocked() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::choked);
|
||||
}
|
||||
|
||||
bool PeerInfo::isRemoteInterested() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::remote_interested);
|
||||
}
|
||||
|
||||
bool PeerInfo::isRemoteChocked() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::remote_choked);
|
||||
}
|
||||
|
||||
|
||||
bool PeerInfo::isSupportsExtensions() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::supports_extensions);
|
||||
}
|
||||
|
||||
bool PeerInfo::isLocalConnection() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::local_connection);
|
||||
}
|
||||
|
||||
bool PeerInfo::isHandshake() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::handshake);
|
||||
}
|
||||
|
||||
|
||||
bool PeerInfo::isConnecting() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::connecting);
|
||||
}
|
||||
|
||||
bool PeerInfo::isQueued() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::queued);
|
||||
}
|
||||
|
||||
|
||||
bool PeerInfo::isOnParole() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::on_parole);
|
||||
}
|
||||
|
||||
bool PeerInfo::isSeed() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::seed);
|
||||
}
|
||||
|
||||
bool PeerInfo::optimisticUnchoke() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::optimistic_unchoke);
|
||||
}
|
||||
|
||||
|
||||
bool PeerInfo::isSnubbed() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::snubbed);
|
||||
}
|
||||
|
||||
bool PeerInfo::isUploadOnly() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::upload_only);
|
||||
}
|
||||
|
||||
bool PeerInfo::isEndgameMode() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::endgame_mode);
|
||||
}
|
||||
|
||||
|
||||
bool PeerInfo::isHolepunched() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::holepunched);
|
||||
}
|
||||
|
||||
bool PeerInfo::useI2PSocket() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::i2p_socket);
|
||||
}
|
||||
|
||||
bool PeerInfo::useUTPSocket() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return (m_nativeInfo.connection_type & libt::peer_info::bittorrent_utp);
|
||||
#else
|
||||
return (m_nativeInfo.flags & libt::peer_info::utp_socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PeerInfo::useSSLSocket() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return false;
|
||||
#else
|
||||
return (m_nativeInfo.flags & libt::peer_info::ssl_socket);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PeerInfo::isRC4Encrypted() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::rc4_encrypted);
|
||||
}
|
||||
|
||||
bool PeerInfo::isPlaintextEncrypted() const
|
||||
{
|
||||
return (m_nativeInfo.flags & libt::peer_info::plaintext_encrypted);
|
||||
}
|
||||
|
||||
|
||||
PeerAddress PeerInfo::address() const
|
||||
{
|
||||
return PeerAddress(QHostAddress(QString::fromStdString(m_nativeInfo.ip.address().to_string())),
|
||||
m_nativeInfo.ip.port());
|
||||
}
|
||||
|
||||
QString PeerInfo::client() const
|
||||
{
|
||||
return String::fromStdString(m_nativeInfo.client);
|
||||
}
|
||||
|
||||
|
||||
qreal PeerInfo::progress() const
|
||||
{
|
||||
return m_nativeInfo.progress;
|
||||
}
|
||||
|
||||
int PeerInfo::payloadUpSpeed() const
|
||||
{
|
||||
return m_nativeInfo.payload_up_speed;
|
||||
}
|
||||
|
||||
|
||||
int PeerInfo::payloadDownSpeed() const
|
||||
{
|
||||
return m_nativeInfo.payload_down_speed;
|
||||
}
|
||||
|
||||
qlonglong PeerInfo::totalUpload() const
|
||||
{
|
||||
return m_nativeInfo.total_upload;
|
||||
}
|
||||
|
||||
|
||||
qlonglong PeerInfo::totalDownload() const
|
||||
{
|
||||
return m_nativeInfo.total_download;
|
||||
}
|
||||
|
||||
QBitArray PeerInfo::pieces() const
|
||||
{
|
||||
QBitArray result(m_nativeInfo.pieces.size());
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
typedef size_t pieces_size_t;
|
||||
#else
|
||||
typedef int pieces_size_t;
|
||||
#endif
|
||||
for (pieces_size_t i = 0; i < m_nativeInfo.pieces.size(); ++i)
|
||||
result.setBit(i, m_nativeInfo.pieces.get_bit(i));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString PeerInfo::connectionType() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
if (m_nativeInfo.connection_type & libt::peer_info::bittorrent_utp)
|
||||
#else
|
||||
if (m_nativeInfo.flags & libt::peer_info::utp_socket)
|
||||
#endif
|
||||
return QString::fromUtf8("μTP");
|
||||
|
||||
QString connection;
|
||||
switch(m_nativeInfo.connection_type) {
|
||||
case libt::peer_info::http_seed:
|
||||
case libt::peer_info::web_seed:
|
||||
connection = "Web";
|
||||
break;
|
||||
default:
|
||||
connection = "BT";
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
99
src/core/bittorrent/peerinfo.h
Normal file
99
src/core/bittorrent/peerinfo.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_PEERINFO_H
|
||||
#define BITTORRENT_PEERINFO_H
|
||||
|
||||
#include <libtorrent/peer_info.hpp>
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QBitArray>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
struct PeerAddress
|
||||
{
|
||||
QHostAddress ip;
|
||||
ushort port;
|
||||
|
||||
PeerAddress();
|
||||
PeerAddress(QHostAddress ip, ushort port);
|
||||
};
|
||||
|
||||
class PeerInfo
|
||||
{
|
||||
public:
|
||||
PeerInfo(const libtorrent::peer_info &nativeInfo);
|
||||
|
||||
bool fromDHT() const;
|
||||
bool fromPeX() const;
|
||||
bool fromLSD() const;
|
||||
|
||||
bool isInteresting() const;
|
||||
bool isChocked() const;
|
||||
bool isRemoteInterested() const;
|
||||
bool isRemoteChocked() const;
|
||||
bool isSupportsExtensions() const;
|
||||
bool isLocalConnection() const;
|
||||
|
||||
bool isHandshake() const;
|
||||
bool isConnecting() const;
|
||||
bool isQueued() const;
|
||||
bool isOnParole() const;
|
||||
bool isSeed() const;
|
||||
|
||||
bool optimisticUnchoke() const;
|
||||
bool isSnubbed() const;
|
||||
bool isUploadOnly() const;
|
||||
bool isEndgameMode() const;
|
||||
bool isHolepunched() const;
|
||||
|
||||
bool useI2PSocket() const;
|
||||
bool useUTPSocket() const;
|
||||
bool useSSLSocket() const;
|
||||
|
||||
bool isRC4Encrypted() const;
|
||||
bool isPlaintextEncrypted() const;
|
||||
|
||||
PeerAddress address() const;
|
||||
QString client() const;
|
||||
qreal progress() const;
|
||||
int payloadUpSpeed() const;
|
||||
int payloadDownSpeed() const;
|
||||
qlonglong totalUpload() const;
|
||||
qlonglong totalDownload() const;
|
||||
QBitArray pieces() const;
|
||||
QString connectionType() const;
|
||||
QString country() const;
|
||||
|
||||
private:
|
||||
libtorrent::peer_info m_nativeInfo;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_PEERINFO_H
|
||||
96
src/core/bittorrent/private/bandwidthscheduler.cpp
Normal file
96
src/core/bittorrent/private/bandwidthscheduler.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QTime>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "core/preferences.h"
|
||||
#include "bandwidthscheduler.h"
|
||||
|
||||
BandwidthScheduler::BandwidthScheduler(QObject *parent)
|
||||
: QTimer(parent)
|
||||
{
|
||||
Q_ASSERT(Preferences::instance()->isSchedulerEnabled());
|
||||
// Single shot, we call start() again manually
|
||||
setSingleShot(true);
|
||||
// Connect Signals/Slots
|
||||
connect(this, SIGNAL(timeout()), this, SLOT(start()));
|
||||
}
|
||||
|
||||
void BandwidthScheduler::start()
|
||||
{
|
||||
const Preferences* const pref = Preferences::instance();
|
||||
Q_ASSERT(pref->isSchedulerEnabled());
|
||||
bool alt_bw_enabled = pref->isAltBandwidthEnabled();
|
||||
|
||||
QTime start = pref->getSchedulerStartTime();
|
||||
QTime end = pref->getSchedulerEndTime();
|
||||
QTime now = QTime::currentTime();
|
||||
int sched_days = pref->getSchedulerDays();
|
||||
int day = QDateTime::currentDateTime().toLocalTime().date().dayOfWeek();
|
||||
bool new_mode = false;
|
||||
bool reverse = false;
|
||||
|
||||
if (start > end) {
|
||||
QTime temp = start;
|
||||
start = end;
|
||||
end = temp;
|
||||
reverse = true;
|
||||
}
|
||||
|
||||
if ((start <= now) && (end >= now)) {
|
||||
switch(sched_days) {
|
||||
case EVERY_DAY:
|
||||
new_mode = true;
|
||||
break;
|
||||
case WEEK_ENDS:
|
||||
if ((day == 6) || (day == 7))
|
||||
new_mode = true;
|
||||
break;
|
||||
case WEEK_DAYS:
|
||||
if ((day != 6) && (day != 7))
|
||||
new_mode = true;
|
||||
break;
|
||||
default:
|
||||
if (day == (sched_days - 2))
|
||||
new_mode = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
new_mode = !new_mode;
|
||||
|
||||
if (new_mode != alt_bw_enabled)
|
||||
emit switchToAlternativeMode(new_mode);
|
||||
|
||||
// Timeout regularly to accomodate for external system clock changes
|
||||
// eg from the user or from a timesync utility
|
||||
QTimer::start(1500);
|
||||
}
|
||||
50
src/core/bittorrent/private/bandwidthscheduler.h
Normal file
50
src/core/bittorrent/private/bandwidthscheduler.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef BANDWIDTHSCHEDULER_H
|
||||
#define BANDWIDTHSCHEDULER_H
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
class BandwidthScheduler : public QTimer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BandwidthScheduler(QObject *parent = 0);
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
|
||||
signals:
|
||||
void switchToAlternativeMode(bool alternative);
|
||||
};
|
||||
|
||||
#endif // BANDWIDTHSCHEDULER_H
|
||||
439
src/core/bittorrent/private/filterparserthread.cpp
Normal file
439
src/core/bittorrent/private/filterparserthread.cpp
Normal file
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libt.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QFile>
|
||||
#include <QHostAddress>
|
||||
#include <QDataStream>
|
||||
#include <QStringList>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/ip_filter.hpp>
|
||||
|
||||
#include "core/logger.h"
|
||||
#include "filterparserthread.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
|
||||
FilterParserThread::FilterParserThread(libt::session *s, QObject *parent)
|
||||
: QThread(parent)
|
||||
, m_session(s)
|
||||
, m_abort(false)
|
||||
{
|
||||
}
|
||||
|
||||
FilterParserThread::~FilterParserThread()
|
||||
{
|
||||
m_abort = true;
|
||||
wait();
|
||||
}
|
||||
|
||||
// Parser for eMule ip filter in DAT format
|
||||
int FilterParserThread::parseDATFilterFile(QString m_filePath, libt::ip_filter &filter)
|
||||
{
|
||||
int ruleCount = 0;
|
||||
QFile file(m_filePath);
|
||||
if (!file.exists()) return ruleCount;
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
Logger::instance()->addMessage(tr("I/O Error: Could not open ip filer file in read mode."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !m_abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine();
|
||||
// Ignoring empty lines
|
||||
line = line.trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if (line.startsWith('#') || line.startsWith("//")) continue;
|
||||
|
||||
// Line should be splitted by commas
|
||||
QList<QByteArray> partsList = line.split(',');
|
||||
const uint nbElem = partsList.size();
|
||||
|
||||
// IP Range should be splitted by a dash
|
||||
QList<QByteArray> IPs = partsList.first().split('-');
|
||||
if (IPs.size() != 2) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Line was %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
const QString strStartIP = cleanupIPAddress(IPs.at(0));
|
||||
if (strStartIP.isEmpty()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libt::address startAddr = libt::address::from_string(qPrintable(strStartIP), ec);
|
||||
if (ec) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString strEndIP = cleanupIPAddress(IPs.at(1));
|
||||
if (strEndIP.isEmpty()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
libt::address endAddr = libt::address::from_string(qPrintable(strEndIP), ec);
|
||||
if (ec) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (startAddr.is_v4() != endAddr.is_v4()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("One IP is IPv4 and the other is IPv6!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there is an access value (apparently not mandatory)
|
||||
int nbAccess = 0;
|
||||
if (nbElem > 1) {
|
||||
// There is possibly one
|
||||
nbAccess = partsList.at(1).trimmed().toInt();
|
||||
}
|
||||
|
||||
if (nbAccess > 127) {
|
||||
// Ignoring this rule because access value is too high
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now Add to the filter
|
||||
try {
|
||||
filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
}
|
||||
catch(std::exception &) {
|
||||
qDebug("Bad line in filter file, avoided crash...");
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
int FilterParserThread::parseP2PFilterFile(QString m_filePath, libt::ip_filter &filter)
|
||||
{
|
||||
int ruleCount = 0;
|
||||
QFile file(m_filePath);
|
||||
if (!file.exists()) return ruleCount;
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
Logger::instance()->addMessage(tr("I/O Error: Could not open ip filer file in read mode."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !m_abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine().trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if (line.startsWith('#') || line.startsWith("//")) continue;
|
||||
|
||||
// Line is splitted by :
|
||||
QList<QByteArray> partsList = line.split(':');
|
||||
if (partsList.size() < 2) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get IP range
|
||||
QList<QByteArray> IPs = partsList.last().split('-');
|
||||
if (IPs.size() != 2) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
QString strStartIP = cleanupIPAddress(IPs.at(0));
|
||||
if (strStartIP.isEmpty()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
libt::address startAddr = libt::address::from_string(qPrintable(strStartIP), ec);
|
||||
if (ec) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
QString strEndIP = cleanupIPAddress(IPs.at(1));
|
||||
if (strEndIP.isEmpty()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("End IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
libt::address endAddr = libt::address::from_string(qPrintable(strEndIP), ec);
|
||||
if (ec) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("End IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (startAddr.is_v4() != endAddr.is_v4()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
}
|
||||
catch(std::exception &) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name, char delim)
|
||||
{
|
||||
char c;
|
||||
int total_read = 0;
|
||||
int read;
|
||||
do {
|
||||
read = stream.readRawData(&c, 1);
|
||||
total_read += read;
|
||||
if (read > 0) {
|
||||
if (c != delim) {
|
||||
name += c;
|
||||
}
|
||||
else {
|
||||
// Delim found
|
||||
return total_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(read > 0);
|
||||
|
||||
return total_read;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
int FilterParserThread::parseP2BFilterFile(QString m_filePath, libt::ip_filter &filter)
|
||||
{
|
||||
int ruleCount = 0;
|
||||
QFile file(m_filePath);
|
||||
if (!file.exists()) return ruleCount;
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
Logger::instance()->addMessage(tr("I/O Error: Could not open ip filer file in read mode."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
QDataStream stream(&file);
|
||||
// Read header
|
||||
char buf[7];
|
||||
unsigned char version;
|
||||
if (!stream.readRawData(buf, sizeof(buf))
|
||||
|| memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7)
|
||||
|| !stream.readRawData((char*)&version, sizeof(version))) {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
if ((version == 1) || (version == 2)) {
|
||||
qDebug ("p2b version 1 or 2");
|
||||
unsigned int start, end;
|
||||
|
||||
std::string name;
|
||||
while(getlineInStream(stream, name, '\0') && !m_abort) {
|
||||
if (!stream.readRawData((char*)&start, sizeof(start))
|
||||
|| !stream.readRawData((char*)&end, sizeof(end))) {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
libt::address_v4 first(ntohl(start));
|
||||
libt::address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
try {
|
||||
filter.add_rule(first, last, libt::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
}
|
||||
catch(std::exception &) {}
|
||||
}
|
||||
}
|
||||
else if (version == 3) {
|
||||
qDebug ("p2b version 3");
|
||||
unsigned int namecount;
|
||||
if (!stream.readRawData((char*)&namecount, sizeof(namecount))) {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
namecount = ntohl(namecount);
|
||||
// Reading names although, we don't really care about them
|
||||
for (unsigned int i = 0; i < namecount; ++i) {
|
||||
std::string name;
|
||||
if (!getlineInStream(stream, name, '\0')) {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
if (m_abort) return ruleCount;
|
||||
}
|
||||
|
||||
// Reading the ranges
|
||||
unsigned int rangecount;
|
||||
if (!stream.readRawData((char*)&rangecount, sizeof(rangecount))) {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
rangecount = ntohl(rangecount);
|
||||
unsigned int name, start, end;
|
||||
for (unsigned int i = 0; i < rangecount; ++i) {
|
||||
if (!stream.readRawData((char*)&name, sizeof(name))
|
||||
|| !stream.readRawData((char*)&start, sizeof(start))
|
||||
|| !stream.readRawData((char*)&end, sizeof(end))) {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
libt::address_v4 first(ntohl(start));
|
||||
libt::address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
try {
|
||||
filter.add_rule(first, last, libt::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
}
|
||||
catch(std::exception &) {}
|
||||
|
||||
if (m_abort) return ruleCount;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger::instance()->addMessage(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
}
|
||||
|
||||
file.close();
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
// Process ip filter file
|
||||
// Supported formats:
|
||||
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
||||
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
||||
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
||||
void FilterParserThread::processFilterFile(QString _filePath)
|
||||
{
|
||||
if (isRunning()) {
|
||||
// Already parsing a filter, m_abort first
|
||||
m_abort = true;
|
||||
wait();
|
||||
}
|
||||
|
||||
m_abort = false;
|
||||
m_filePath = _filePath;
|
||||
// Run it
|
||||
start();
|
||||
}
|
||||
|
||||
void FilterParserThread::processFilterList(libt::session *s, const QStringList &IPs)
|
||||
{
|
||||
// First, import current filter
|
||||
libt::ip_filter filter = s->get_ip_filter();
|
||||
foreach (const QString &ip, IPs) {
|
||||
qDebug("Manual ban of peer %s", ip.toLocal8Bit().constData());
|
||||
boost::system::error_code ec;
|
||||
libt::address addr = libt::address::from_string(ip.toLocal8Bit().constData(), ec);
|
||||
Q_ASSERT(!ec);
|
||||
if (!ec)
|
||||
filter.add_rule(addr, addr, libt::ip_filter::blocked);
|
||||
}
|
||||
|
||||
s->set_ip_filter(filter);
|
||||
}
|
||||
|
||||
QString FilterParserThread::cleanupIPAddress(QString _ip)
|
||||
{
|
||||
QHostAddress ip(_ip.trimmed());
|
||||
if (ip.isNull()) return QString();
|
||||
|
||||
return ip.toString();
|
||||
}
|
||||
|
||||
void FilterParserThread::run()
|
||||
{
|
||||
qDebug("Processing filter file");
|
||||
libt::ip_filter filter = m_session->get_ip_filter();
|
||||
int ruleCount = 0;
|
||||
if (m_filePath.endsWith(".p2p", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2p file
|
||||
ruleCount = parseP2PFilterFile(m_filePath, filter);
|
||||
}
|
||||
else if (m_filePath.endsWith(".p2b", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2b file
|
||||
ruleCount = parseP2BFilterFile(m_filePath, filter);
|
||||
}
|
||||
else if (m_filePath.endsWith(".dat", Qt::CaseInsensitive)) {
|
||||
// eMule DAT format
|
||||
ruleCount = parseDATFilterFile(m_filePath, filter);
|
||||
}
|
||||
|
||||
if (m_abort) return;
|
||||
|
||||
try {
|
||||
m_session->set_ip_filter(filter);
|
||||
emit IPFilterParsed(ruleCount);
|
||||
}
|
||||
catch(std::exception &) {
|
||||
emit IPFilterError();
|
||||
}
|
||||
|
||||
qDebug("IP Filter thread: finished parsing, filter applied");
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -32,38 +32,30 @@
|
||||
#define FILTERPARSERTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QDataStream>
|
||||
#include <QStringList>
|
||||
|
||||
namespace libtorrent {
|
||||
class session;
|
||||
struct ip_filter;
|
||||
class QDataStream;
|
||||
class QStringList;
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class session;
|
||||
struct ip_filter;
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
// P2B Stuff
|
||||
#include <string.h>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
// End of P2B stuff
|
||||
|
||||
class FilterParserThread : public QThread {
|
||||
class FilterParserThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FilterParserThread(QObject* parent, libtorrent::session *s);
|
||||
FilterParserThread(libtorrent::session *s, QObject *parent = 0);
|
||||
~FilterParserThread();
|
||||
|
||||
int parseDATFilterFile(QString filePath, libtorrent::ip_filter& filter);
|
||||
int parseP2PFilterFile(QString filePath, libtorrent::ip_filter& filter);
|
||||
int getlineInStream(QDataStream& stream, string& name, char delim);
|
||||
int parseP2BFilterFile(QString filePath, libtorrent::ip_filter& filter);
|
||||
int parseDATFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
||||
int parseP2PFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
||||
int getlineInStream(QDataStream &stream, std::string &name, char delim);
|
||||
int parseP2BFilterFile(QString filePath, libtorrent::ip_filter &filter);
|
||||
void processFilterFile(QString _filePath);
|
||||
static void processFilterList(libtorrent::session *s, const QStringList& IPs);
|
||||
static void processFilterList(libtorrent::session *s, const QStringList &IPs);
|
||||
|
||||
signals:
|
||||
void IPFilterParsed(int ruleCount);
|
||||
@@ -74,9 +66,9 @@ protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
libtorrent::session *s;
|
||||
bool abort;
|
||||
QString filePath;
|
||||
libtorrent::session *m_session;
|
||||
bool m_abort;
|
||||
QString m_filePath;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // BITTORRENT_FILTERPARSERTHREAD_H
|
||||
83
src/core/bittorrent/private/sessionprivate.h
Normal file
83
src/core/bittorrent/private/sessionprivate.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef SESSIONPRIVATE_H
|
||||
#define SESSIONPRIVATE_H
|
||||
|
||||
class QString;
|
||||
class QUrl;
|
||||
template<typename T> class QList;
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class entry;
|
||||
}
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentHandle;
|
||||
class TrackerEntry;
|
||||
}
|
||||
|
||||
struct SessionPrivate
|
||||
{
|
||||
virtual bool isQueueingEnabled() const = 0;
|
||||
virtual bool isTempPathEnabled() const = 0;
|
||||
virtual bool isAppendExtensionEnabled() const = 0;
|
||||
virtual bool useAppendLabelToSavePath() const = 0;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
virtual bool isResolveCountriesEnabled() const = 0;
|
||||
#endif
|
||||
virtual QString defaultSavePath() const = 0;
|
||||
virtual QString tempPath() const = 0;
|
||||
virtual qreal globalMaxRatio() const = 0;
|
||||
|
||||
virtual void handleTorrentRatioLimitChanged(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentSavePathChanged(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentMetadataReceived(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentPaused(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentResumed(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentChecked(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentFinished(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentTrackersAdded(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &newTrackers) = 0;
|
||||
virtual void handleTorrentTrackersRemoved(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &deletedTrackers) = 0;
|
||||
virtual void handleTorrentTrackersChanged(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentUrlSeedsAdded(BitTorrent::TorrentHandle *const torrent, const QList<QUrl> &newUrlSeeds) = 0;
|
||||
virtual void handleTorrentUrlSeedsRemoved(BitTorrent::TorrentHandle *const torrent, const QList<QUrl> &urlSeeds) = 0;
|
||||
virtual void handleTorrentResumeDataReady(BitTorrent::TorrentHandle *const torrent, const libtorrent::entry &data) = 0;
|
||||
virtual void handleTorrentResumeDataFailed(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||
virtual void handleTorrentTrackerReply(BitTorrent::TorrentHandle *const torrent, const QString &trackerUrl) = 0;
|
||||
virtual void handleTorrentTrackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &trackerUrl) = 0;
|
||||
virtual void handleTorrentTrackerError(BitTorrent::TorrentHandle *const torrent, const QString &trackerUrl) = 0;
|
||||
virtual void handleTorrentTrackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent, const QString &trackerUrl) = 0;
|
||||
|
||||
protected:
|
||||
~SessionPrivate() {}
|
||||
};
|
||||
|
||||
#endif // SESSIONPRIVATE_H
|
||||
56
src/core/bittorrent/private/speedmonitor.cpp
Normal file
56
src/core/bittorrent/private/speedmonitor.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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 <QList>
|
||||
#include "speedmonitor.h"
|
||||
|
||||
void SpeedMonitor::addSample(const SpeedSample &sample)
|
||||
{
|
||||
m_speedSamples.push_back(sample);
|
||||
m_sum += sample;
|
||||
if (m_speedSamples.size() > MAX_SAMPLES) {
|
||||
m_sum -= m_speedSamples.front();
|
||||
m_speedSamples.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
SpeedSampleAvg SpeedMonitor::average() const
|
||||
{
|
||||
if (m_speedSamples.empty())
|
||||
return SpeedSampleAvg();
|
||||
|
||||
qreal k = qreal(1.) / m_speedSamples.size();
|
||||
return SpeedSampleAvg(m_sum.download * k, m_sum.upload * k);
|
||||
}
|
||||
|
||||
void SpeedMonitor::reset()
|
||||
{
|
||||
m_sum = SpeedSample();
|
||||
m_speedSamples.clear();
|
||||
}
|
||||
84
src/core/bittorrent/private/speedmonitor.h
Normal file
84
src/core/bittorrent/private/speedmonitor.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SPEEDMONITOR_H
|
||||
#define SPEEDMONITOR_H
|
||||
|
||||
template<typename T> class QList;
|
||||
|
||||
template<typename T>
|
||||
struct Sample
|
||||
{
|
||||
Sample()
|
||||
: download()
|
||||
, upload()
|
||||
{
|
||||
}
|
||||
|
||||
Sample(T dl, T ul)
|
||||
: download(dl)
|
||||
, upload(ul)
|
||||
{
|
||||
}
|
||||
|
||||
Sample<T> &operator+=(const Sample<T> &other)
|
||||
{
|
||||
download += other.download;
|
||||
upload += other.upload;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Sample<T> &operator-=(const Sample<T> &other)
|
||||
{
|
||||
download -= other.download;
|
||||
upload -= other.upload;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T download;
|
||||
T upload;
|
||||
};
|
||||
|
||||
typedef Sample<qlonglong> SpeedSample;
|
||||
typedef Sample<qreal> SpeedSampleAvg;
|
||||
|
||||
class SpeedMonitor
|
||||
{
|
||||
public:
|
||||
void addSample(const SpeedSample &sample);
|
||||
SpeedSampleAvg average() const;
|
||||
void reset();
|
||||
|
||||
private:
|
||||
static const int MAX_SAMPLES = 30;
|
||||
QList<SpeedSample> m_speedSamples;
|
||||
SpeedSample m_sum;
|
||||
};
|
||||
|
||||
#endif // SPEEDMONITOR_H
|
||||
115
src/core/bittorrent/private/statistics.cpp
Normal file
115
src/core/bittorrent/private/statistics.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <QDateTime>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
#include "core/qinisettings.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/bittorrent/sessionstatus.h"
|
||||
#include "core/bittorrent/session.h"
|
||||
#include "statistics.h"
|
||||
|
||||
static const qint64 SAVE_INTERVAL = 15 * 60 * 1000;
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
|
||||
Statistics::Statistics(Session *session)
|
||||
: QObject(session)
|
||||
, m_session(session)
|
||||
, m_sessionUL(0)
|
||||
, m_sessionDL(0)
|
||||
, m_lastWrite(0)
|
||||
, m_dirty(false)
|
||||
{
|
||||
load();
|
||||
connect(&m_timer, SIGNAL(timeout()), this, SLOT(gather()));
|
||||
m_timer.start(60 * 1000);
|
||||
}
|
||||
|
||||
Statistics::~Statistics()
|
||||
{
|
||||
if (m_dirty)
|
||||
m_lastWrite = 0;
|
||||
save();
|
||||
}
|
||||
|
||||
quint64 Statistics::getAlltimeDL() const
|
||||
{
|
||||
return m_alltimeDL + m_sessionDL;
|
||||
}
|
||||
|
||||
quint64 Statistics::getAlltimeUL() const
|
||||
{
|
||||
return m_alltimeUL + m_sessionUL;
|
||||
}
|
||||
|
||||
void Statistics::gather()
|
||||
{
|
||||
SessionStatus ss = m_session->status();
|
||||
if (ss.totalDownload() > m_sessionDL) {
|
||||
m_sessionDL = ss.totalDownload();
|
||||
m_dirty = true;
|
||||
}
|
||||
if (ss.totalUpload() > m_sessionUL) {
|
||||
m_sessionUL = ss.totalUpload();
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
void Statistics::save() const
|
||||
{
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
if (!m_dirty || ((now - m_lastWrite) < SAVE_INTERVAL))
|
||||
return;
|
||||
|
||||
QIniSettings s("qBittorrent", "qBittorrent-data");
|
||||
QVariantHash v;
|
||||
v.insert("AlltimeDL", m_alltimeDL + m_sessionDL);
|
||||
v.insert("AlltimeUL", m_alltimeUL + m_sessionUL);
|
||||
s.setValue("Stats/AllStats", v);
|
||||
m_dirty = false;
|
||||
m_lastWrite = now;
|
||||
}
|
||||
|
||||
void Statistics::load()
|
||||
{
|
||||
// Temp code. Versions v3.1.4 and v3.1.5 saved the data in the qbittorrent.ini file.
|
||||
// This code reads the data from there, writes it to the new file, and removes the keys
|
||||
// from the old file. This code should be removed after some time has passed.
|
||||
// e.g. When we reach v3.3.0
|
||||
// Don't forget to remove:
|
||||
// 1. Preferences::getStats()
|
||||
// 2. Preferences::removeStats()
|
||||
// 3. #include "core/preferences.h"
|
||||
Preferences* const pref = Preferences::instance();
|
||||
QIniSettings s("qBittorrent", "qBittorrent-data");
|
||||
QVariantHash v = pref->getStats();
|
||||
|
||||
// Let's test if the qbittorrent.ini holds the key
|
||||
if (!v.isEmpty()) {
|
||||
m_dirty = true;
|
||||
|
||||
// If the user has used qbt > 3.1.5 and then reinstalled/used
|
||||
// qbt < 3.1.6, there will be stats in qbittorrent-data.ini too
|
||||
// so we need to merge those 2.
|
||||
if (s.contains("Stats/AllStats")) {
|
||||
QVariantHash tmp = s.value("Stats/AllStats").toHash();
|
||||
v["AlltimeDL"] = v["AlltimeDL"].toULongLong() + tmp["AlltimeDL"].toULongLong();
|
||||
v["AlltimeUL"] = v["AlltimeUL"].toULongLong() + tmp["AlltimeUL"].toULongLong();
|
||||
}
|
||||
}
|
||||
else {
|
||||
v = s.value("Stats/AllStats").toHash();
|
||||
}
|
||||
|
||||
m_alltimeDL = v["AlltimeDL"].toULongLong();
|
||||
m_alltimeUL = v["AlltimeUL"].toULongLong();
|
||||
|
||||
if (m_dirty) {
|
||||
save();
|
||||
pref->removeStats();
|
||||
}
|
||||
}
|
||||
41
src/core/bittorrent/private/statistics.h
Normal file
41
src/core/bittorrent/private/statistics.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef STATISTICS_H
|
||||
#define STATISTICS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
namespace BitTorrent { class Session; }
|
||||
|
||||
class Statistics : QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(Statistics)
|
||||
|
||||
public:
|
||||
Statistics(BitTorrent::Session *session);
|
||||
~Statistics();
|
||||
|
||||
quint64 getAlltimeDL() const;
|
||||
quint64 getAlltimeUL() const;
|
||||
|
||||
private slots:
|
||||
void gather();
|
||||
|
||||
private:
|
||||
void save() const;
|
||||
void load();
|
||||
|
||||
private:
|
||||
BitTorrent::Session *m_session;
|
||||
// Will overflow at 15.9 EiB
|
||||
quint64 m_alltimeUL;
|
||||
quint64 m_alltimeDL;
|
||||
qint64 m_sessionUL;
|
||||
qint64 m_sessionDL;
|
||||
mutable qint64 m_lastWrite;
|
||||
mutable bool m_dirty;
|
||||
|
||||
QTimer m_timer;
|
||||
};
|
||||
|
||||
#endif // STATISTICS_H
|
||||
53
src/core/bittorrent/private/torrenthandleprivate.h
Normal file
53
src/core/bittorrent/private/torrenthandleprivate.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef TORRENTHANDLEPRIVATE_H
|
||||
#define TORRENTHANDLEPRIVATE_H
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class alert;
|
||||
struct torrent_status;
|
||||
}
|
||||
|
||||
struct TorrentHandlePrivate
|
||||
{
|
||||
virtual void handleAlert(libtorrent::alert *) = 0;
|
||||
virtual void handleStateUpdate(const libtorrent::torrent_status &) = 0;
|
||||
virtual void handleDefaultSavePathChanged() = 0;
|
||||
virtual void handleTempPathChanged() = 0;
|
||||
virtual void handleAppendExtensionToggled() = 0;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
virtual void handleResolveCountriesToggled() = 0;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
~TorrentHandlePrivate() {}
|
||||
};
|
||||
|
||||
#endif // TORRENTHANDLEPRIVATE_H
|
||||
2440
src/core/bittorrent/session.cpp
Normal file
2440
src/core/bittorrent/session.cpp
Normal file
File diff suppressed because it is too large
Load Diff
365
src/core/bittorrent/session.h
Normal file
365
src/core/bittorrent/session.h
Normal file
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_SESSION_H
|
||||
#define BITTORRENT_SESSION_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QVector>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "core/tristatebool.h"
|
||||
#include "core/types.h"
|
||||
#include "private/sessionprivate.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class session;
|
||||
struct add_torrent_params;
|
||||
struct pe_settings;
|
||||
struct proxy_settings;
|
||||
struct session_settings;
|
||||
struct session_status;
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTimer;
|
||||
class QStringList;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class FilterParserThread;
|
||||
class BandwidthScheduler;
|
||||
class Statistics;
|
||||
|
||||
typedef QPair<QString, QString> QStringPair;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash;
|
||||
class CacheStatus;
|
||||
class SessionStatus;
|
||||
class TorrentHandle;
|
||||
class Tracker;
|
||||
class MagnetUri;
|
||||
class TrackerEntry;
|
||||
struct AddTorrentData;
|
||||
|
||||
struct AddTorrentParams
|
||||
{
|
||||
QString name;
|
||||
QString label;
|
||||
QString savePath;
|
||||
bool disableTempPath; // e.g. for imported torrents
|
||||
bool sequential;
|
||||
TriStateBool addPaused;
|
||||
QVector<int> filePriorities; // used if TorrentInfo is set
|
||||
bool ignoreShareRatio;
|
||||
bool skipChecking;
|
||||
|
||||
AddTorrentParams();
|
||||
};
|
||||
|
||||
struct TorrentStatusReport
|
||||
{
|
||||
uint nbDownloading;
|
||||
uint nbSeeding;
|
||||
uint nbCompleted;
|
||||
uint nbActive;
|
||||
uint nbInactive;
|
||||
uint nbPaused;
|
||||
uint nbResumed;
|
||||
|
||||
TorrentStatusReport();
|
||||
};
|
||||
|
||||
class Session : public QObject, public SessionPrivate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(Session)
|
||||
|
||||
public:
|
||||
static void initInstance();
|
||||
static void freeInstance();
|
||||
static Session *instance();
|
||||
|
||||
bool isDHTEnabled() const;
|
||||
bool isLSDEnabled() const;
|
||||
bool isPexEnabled() const;
|
||||
bool isQueueingEnabled() const;
|
||||
qreal globalMaxRatio() const;
|
||||
|
||||
TorrentHandle *findTorrent(const InfoHash &hash) const;
|
||||
QHash<InfoHash, TorrentHandle *> torrents() const;
|
||||
bool hasActiveTorrents() const;
|
||||
bool hasUnfinishedTorrents() const;
|
||||
SessionStatus status() const;
|
||||
CacheStatus cacheStatus() const;
|
||||
quint64 getAlltimeDL() const;
|
||||
quint64 getAlltimeUL() const;
|
||||
int downloadRateLimit() const;
|
||||
int uploadRateLimit() const;
|
||||
bool isListening() const;
|
||||
|
||||
void changeSpeedLimitMode(bool alternative);
|
||||
void setDownloadRateLimit(int rate);
|
||||
void setUploadRateLimit(int rate);
|
||||
void setGlobalMaxRatio(qreal ratio);
|
||||
void enableIPFilter(const QString &filterPath, bool force = false);
|
||||
void disableIPFilter();
|
||||
void banIP(const QString &ip);
|
||||
|
||||
bool isKnownTorrent(const InfoHash &hash) const;
|
||||
bool addTorrent(QString source, const AddTorrentParams ¶ms = AddTorrentParams());
|
||||
bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams ¶ms = AddTorrentParams());
|
||||
bool deleteTorrent(const QString &hash, bool deleteLocalFiles = false);
|
||||
bool loadMetadata(const QString &magnetUri);
|
||||
bool cancelLoadMetadata(const InfoHash &hash);
|
||||
|
||||
void recursiveTorrentDownload(const InfoHash &hash);
|
||||
void increaseTorrentsPriority(const QStringList &hashes);
|
||||
void decreaseTorrentsPriority(const QStringList &hashes);
|
||||
void topTorrentsPriority(const QStringList &hashes);
|
||||
void bottomTorrentsPriority(const QStringList &hashes);
|
||||
|
||||
signals:
|
||||
void torrentsUpdated(const BitTorrent::TorrentStatusReport &torrentStatusReport = BitTorrent::TorrentStatusReport());
|
||||
void addTorrentFailed(const QString &error);
|
||||
void torrentAdded(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentStatusUpdated(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentPaused(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentResumed(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentFinished(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentFinishedChecking(BitTorrent::TorrentHandle *const torrent);
|
||||
void torrentSavePathChanged(BitTorrent::TorrentHandle *const torrent);
|
||||
void allTorrentsFinished();
|
||||
void metadataLoaded(const BitTorrent::TorrentInfo &info);
|
||||
void torrentMetadataLoaded(BitTorrent::TorrentHandle *const torrent);
|
||||
void fullDiskError(BitTorrent::TorrentHandle *const torrent, const QString &msg);
|
||||
void trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker);
|
||||
void trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker);
|
||||
void trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker);
|
||||
void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent);
|
||||
void recursiveTorrentDownloadPossible(BitTorrent::TorrentHandle *const torrent);
|
||||
void speedLimitModeChanged(bool alternative);
|
||||
void ipFilterParsed(bool error, int ruleCount);
|
||||
void trackersAdded(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
||||
void trackersRemoved(BitTorrent::TorrentHandle *const torrent, const QList<BitTorrent::TrackerEntry> &trackers);
|
||||
void trackersChanged(BitTorrent::TorrentHandle *const torrent);
|
||||
void trackerlessStateChanged(BitTorrent::TorrentHandle *const torrent, bool trackerless);
|
||||
void downloadFromUrlFailed(const QString &url, const QString &reason);
|
||||
void downloadFromUrlFinished(const QString &url);
|
||||
|
||||
private slots:
|
||||
void configure();
|
||||
void readAlerts();
|
||||
void refresh();
|
||||
void processBigRatios();
|
||||
void generateResumeData(bool final = false);
|
||||
void handleIPFilterParsed(int ruleCount);
|
||||
void handleIPFilterError();
|
||||
void handleDownloadFinished(const QString &url, const QString &filePath);
|
||||
void handleDownloadFailed(const QString &url, const QString &reason);
|
||||
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
|
||||
|
||||
private:
|
||||
explicit Session(QObject *parent = 0);
|
||||
~Session();
|
||||
|
||||
bool hasPerTorrentRatioLimit() const;
|
||||
|
||||
void initResumeFolder();
|
||||
void loadState();
|
||||
void saveState();
|
||||
|
||||
// Session configuration
|
||||
void setSessionSettings();
|
||||
void setProxySettings(libtorrent::proxy_settings proxySettings);
|
||||
void adjustLimits();
|
||||
void adjustLimits(libtorrent::session_settings &sessionSettings);
|
||||
void setListeningPort(int port);
|
||||
void setDefaultSavePath(const QString &path);
|
||||
void setDefaultTempPath(const QString &path = QString());
|
||||
void preAllocateAllFiles(bool b);
|
||||
void setMaxConnectionsPerTorrent(int max);
|
||||
void setMaxUploadsPerTorrent(int max);
|
||||
void enableLSD(bool enable);
|
||||
void enableDHT(bool enable);
|
||||
|
||||
void setAppendLabelToSavePath(bool append);
|
||||
void setAppendExtension(bool append);
|
||||
|
||||
void startUpTorrents();
|
||||
bool addTorrent_impl(const AddTorrentData &addData, const MagnetUri &magnetUri,
|
||||
const TorrentInfo &torrentInfo = TorrentInfo(),
|
||||
const QByteArray &fastresumeData = QByteArray());
|
||||
|
||||
void updateRatioTimer();
|
||||
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
||||
void exportTorrentFiles(QString path);
|
||||
void saveTorrentResumeData(TorrentHandle *const torrent);
|
||||
|
||||
void handleAlert(libtorrent::alert *a);
|
||||
void dispatchTorrentAlert(libtorrent::alert *a);
|
||||
void handleAddTorrentAlert(libtorrent::add_torrent_alert *p);
|
||||
void handleStateUpdateAlert(libtorrent::state_update_alert *p);
|
||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p);
|
||||
void handleFileErrorAlert(libtorrent::file_error_alert *p);
|
||||
void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p);
|
||||
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p);
|
||||
void handlePortmapWarningAlert(libtorrent::portmap_error_alert *p);
|
||||
void handlePortmapAlert(libtorrent::portmap_alert *p);
|
||||
void handlePeerBlockedAlert(libtorrent::peer_blocked_alert *p);
|
||||
void handlePeerBanAlert(libtorrent::peer_ban_alert *p);
|
||||
void handleUrlSeedAlert(libtorrent::url_seed_alert *p);
|
||||
void handleListenSucceededAlert(libtorrent::listen_succeeded_alert *p);
|
||||
void handleListenFailedAlert(libtorrent::listen_failed_alert *p);
|
||||
void handleExternalIPAlert(libtorrent::external_ip_alert *p);
|
||||
|
||||
bool isTempPathEnabled() const;
|
||||
bool isAppendExtensionEnabled() const;
|
||||
bool useAppendLabelToSavePath() const;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
bool isResolveCountriesEnabled() const;
|
||||
#endif
|
||||
QString defaultSavePath() const;
|
||||
QString tempPath() const;
|
||||
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent);
|
||||
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
|
||||
void handleTorrentMetadataReceived(TorrentHandle *const torrent);
|
||||
void handleTorrentPaused(TorrentHandle *const torrent);
|
||||
void handleTorrentResumed(TorrentHandle *const torrent);
|
||||
void handleTorrentChecked(TorrentHandle *const torrent);
|
||||
void handleTorrentFinished(TorrentHandle *const torrent);
|
||||
void handleTorrentTrackersAdded(TorrentHandle *const torrent, const QList<TrackerEntry> &newTrackers);
|
||||
void handleTorrentTrackersRemoved(TorrentHandle *const torrent, const QList<TrackerEntry> &deletedTrackers);
|
||||
void handleTorrentTrackersChanged(TorrentHandle *const torrent);
|
||||
void handleTorrentUrlSeedsAdded(TorrentHandle *const torrent, const QList<QUrl> &newUrlSeeds);
|
||||
void handleTorrentUrlSeedsRemoved(TorrentHandle *const torrent, const QList<QUrl> &urlSeeds);
|
||||
void handleTorrentResumeDataReady(TorrentHandle *const torrent, const libtorrent::entry &data);
|
||||
void handleTorrentResumeDataFailed(TorrentHandle *const torrent);
|
||||
void handleTorrentTrackerReply(TorrentHandle *const torrent, const QString &trackerUrl);
|
||||
void handleTorrentTrackerWarning(TorrentHandle *const torrent, const QString &trackerUrl);
|
||||
void handleTorrentTrackerError(TorrentHandle *const torrent, const QString &trackerUrl);
|
||||
void handleTorrentTrackerAuthenticationRequired(TorrentHandle *const torrent, const QString &trackerUrl);
|
||||
|
||||
void saveResumeData();
|
||||
bool writeResumeDataFile(TorrentHandle *const torrent, const libtorrent::entry &data);
|
||||
|
||||
void dispatchAlerts(std::auto_ptr<libtorrent::alert> alertPtr);
|
||||
void getPendingAlerts(QVector<libtorrent::alert *> &out, ulong time = 0);
|
||||
|
||||
// BitTorrent
|
||||
libtorrent::session *m_nativeSession;
|
||||
|
||||
bool m_LSDEnabled;
|
||||
bool m_DHTEnabled;
|
||||
bool m_PeXEnabled;
|
||||
bool m_queueingEnabled;
|
||||
bool m_torrentExportEnabled;
|
||||
bool m_finishedTorrentExportEnabled;
|
||||
bool m_preAllocateAll;
|
||||
qreal m_globalMaxRatio;
|
||||
int m_numResumeData;
|
||||
int m_extraLimit;
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
bool m_geoipDBLoaded;
|
||||
bool m_resolveCountries;
|
||||
#endif
|
||||
bool m_appendLabelToSavePath;
|
||||
bool m_appendExtension;
|
||||
uint m_refreshInterval;
|
||||
MaxRatioAction m_highRatioAction;
|
||||
QString m_defaultSavePath;
|
||||
QString m_tempPath;
|
||||
QString m_filterPath;
|
||||
QString m_resumeFolderPath;
|
||||
QFile m_resumeFolderLock;
|
||||
QHash<InfoHash, QString> m_savePathsToRemove;
|
||||
|
||||
QTimer *m_refreshTimer;
|
||||
QTimer *m_bigRatioTimer;
|
||||
QTimer *m_resumeDataTimer;
|
||||
Statistics *m_statistics;
|
||||
// IP filtering
|
||||
QPointer<FilterParserThread> m_filterParser;
|
||||
QPointer<BandwidthScheduler> m_bwScheduler;
|
||||
// Tracker
|
||||
QPointer<Tracker> m_tracker;
|
||||
|
||||
QHash<InfoHash, TorrentInfo> m_loadedMetadata;
|
||||
QHash<InfoHash, TorrentHandle *> m_torrents;
|
||||
QHash<InfoHash, AddTorrentData> m_addingTorrents;
|
||||
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
||||
|
||||
QMutex m_alertsMutex;
|
||||
QWaitCondition m_alertsWaitCondition;
|
||||
QVector<libtorrent::alert *> m_alerts;
|
||||
|
||||
static Session *m_instance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_SESSION_H
|
||||
96
src/core/bittorrent/sessionstatus.cpp
Normal file
96
src/core/bittorrent/sessionstatus.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 "sessionstatus.h"
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
SessionStatus::SessionStatus(const libtorrent::session_status &nativeStatus)
|
||||
: m_nativeStatus(nativeStatus)
|
||||
{
|
||||
}
|
||||
|
||||
bool SessionStatus::hasIncomingConnections() const
|
||||
{
|
||||
return m_nativeStatus.has_incoming_connections;
|
||||
}
|
||||
|
||||
int SessionStatus::payloadDownloadRate() const
|
||||
{
|
||||
return m_nativeStatus.payload_download_rate;
|
||||
}
|
||||
|
||||
int SessionStatus::payloadUploadRate() const
|
||||
{
|
||||
return m_nativeStatus.payload_upload_rate;
|
||||
}
|
||||
|
||||
qlonglong SessionStatus::totalDownload() const
|
||||
{
|
||||
return m_nativeStatus.total_download;
|
||||
}
|
||||
|
||||
qlonglong SessionStatus::totalUpload() const
|
||||
{
|
||||
return m_nativeStatus.total_upload;
|
||||
}
|
||||
|
||||
qlonglong SessionStatus::totalPayloadDownload() const
|
||||
{
|
||||
return m_nativeStatus.total_payload_download;
|
||||
}
|
||||
|
||||
qlonglong SessionStatus::totalPayloadUpload() const
|
||||
{
|
||||
return m_nativeStatus.total_payload_upload;
|
||||
}
|
||||
|
||||
qlonglong SessionStatus::totalWasted() const
|
||||
{
|
||||
return (m_nativeStatus.total_redundant_bytes + m_nativeStatus.total_failed_bytes);
|
||||
}
|
||||
|
||||
int SessionStatus::diskReadQueue() const
|
||||
{
|
||||
return m_nativeStatus.disk_read_queue;
|
||||
}
|
||||
|
||||
int SessionStatus::diskWriteQueue() const
|
||||
{
|
||||
return m_nativeStatus.disk_write_queue;
|
||||
}
|
||||
|
||||
int SessionStatus::dhtNodes() const
|
||||
{
|
||||
return m_nativeStatus.dht_nodes;
|
||||
}
|
||||
|
||||
int SessionStatus::peersCount() const
|
||||
{
|
||||
return m_nativeStatus.num_peers;
|
||||
}
|
||||
69
src/core/bittorrent/sessionstatus.h
Normal file
69
src/core/bittorrent/sessionstatus.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_SESSIONSTATUS_H
|
||||
#define BITTORRENT_SESSIONSTATUS_H
|
||||
|
||||
#include <libtorrent/session_status.hpp>
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class SessionStatus
|
||||
{
|
||||
public:
|
||||
SessionStatus(const libtorrent::session_status &nativeStatus);
|
||||
|
||||
bool hasIncomingConnections() const;
|
||||
|
||||
// Return current download rate for the BT
|
||||
// session. Payload means that it only take into
|
||||
// account "useful" part of the rate
|
||||
int payloadDownloadRate() const;
|
||||
|
||||
// Return current upload rate for the BT
|
||||
// session. Payload means that it only take into
|
||||
// account "useful" part of the rate
|
||||
int payloadUploadRate() const;
|
||||
|
||||
qlonglong totalDownload() const;
|
||||
qlonglong totalUpload() const;
|
||||
qlonglong totalPayloadDownload() const;
|
||||
qlonglong totalPayloadUpload() const;
|
||||
qlonglong totalWasted() const;
|
||||
int diskReadQueue() const;
|
||||
int diskWriteQueue() const;
|
||||
int dhtNodes() const;
|
||||
int peersCount() const;
|
||||
|
||||
private:
|
||||
libtorrent::session_status m_nativeStatus;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_SESSIONSTATUS_H
|
||||
166
src/core/bittorrent/torrentcreatorthread.cpp
Normal file
166
src/core/bittorrent/torrentcreatorthread.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/file.hpp>
|
||||
#include <libtorrent/storage.hpp>
|
||||
#include <libtorrent/hasher.hpp>
|
||||
#include <libtorrent/file_pool.hpp>
|
||||
#include <libtorrent/create_torrent.hpp>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "torrentcreatorthread.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
|
||||
// do not include files and folders whose
|
||||
// name starts with a .
|
||||
bool fileFilter(const std::string &f)
|
||||
{
|
||||
return (libt::filename(f)[0] != '.');
|
||||
}
|
||||
|
||||
TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
|
||||
: QThread(parent)
|
||||
{
|
||||
}
|
||||
|
||||
TorrentCreatorThread::~TorrentCreatorThread()
|
||||
{
|
||||
m_abort = true;
|
||||
wait();
|
||||
}
|
||||
|
||||
void TorrentCreatorThread::create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
|
||||
const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize)
|
||||
{
|
||||
m_inputPath = fsutils::fromNativePath(inputPath);
|
||||
m_savePath = fsutils::fromNativePath(savePath);
|
||||
if (QFile(m_savePath).exists())
|
||||
fsutils::forceRemove(m_savePath);
|
||||
m_trackers = trackers;
|
||||
m_urlSeeds = urlSeeds;
|
||||
m_comment = comment;
|
||||
m_private = isPrivate;
|
||||
m_pieceSize = pieceSize;
|
||||
m_abort = false;
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces)
|
||||
{
|
||||
emit updateProgress(static_cast<int>((numHashes * 100.) / numPieces));
|
||||
}
|
||||
|
||||
void TorrentCreatorThread::abortCreation()
|
||||
{
|
||||
m_abort = true;
|
||||
}
|
||||
|
||||
void TorrentCreatorThread::run()
|
||||
{
|
||||
emit updateProgress(0);
|
||||
|
||||
QString creator_str("qBittorrent " VERSION);
|
||||
try {
|
||||
libt::file_storage fs;
|
||||
// Adding files to the torrent
|
||||
libt::add_files(fs, String::toStdString(fsutils::toNativePath(m_inputPath)), fileFilter);
|
||||
if (m_abort) return;
|
||||
|
||||
libt::create_torrent t(fs, m_pieceSize);
|
||||
|
||||
// Add url seeds
|
||||
foreach (const QString &seed, m_urlSeeds)
|
||||
t.add_url_seed(String::toStdString(seed.trimmed()));
|
||||
|
||||
int tier = 0;
|
||||
bool newline = false;
|
||||
foreach (const QString &tracker, m_trackers) {
|
||||
if (tracker.isEmpty()) {
|
||||
if (newline)
|
||||
continue;
|
||||
++tier;
|
||||
newline = true;
|
||||
continue;
|
||||
}
|
||||
t.add_tracker(String::toStdString(tracker.trimmed()), tier);
|
||||
newline = false;
|
||||
}
|
||||
if (m_abort) return;
|
||||
|
||||
// calculate the hash for all pieces
|
||||
const QString parentPath = fsutils::branchPath(m_inputPath) + "/";
|
||||
libt::set_piece_hashes(t, String::toStdString(fsutils::toNativePath(parentPath)), boost::bind(&TorrentCreatorThread::sendProgressSignal, this, _1, t.num_pieces()));
|
||||
// Set qBittorrent as creator and add user comment to
|
||||
// torrent_info structure
|
||||
t.set_creator(creator_str.toUtf8().constData());
|
||||
t.set_comment(m_comment.toUtf8().constData());
|
||||
// Is private ?
|
||||
t.set_priv(m_private);
|
||||
if (m_abort) return;
|
||||
|
||||
// create the torrent and print it to out
|
||||
qDebug("Saving to %s", qPrintable(m_savePath));
|
||||
#ifdef _MSC_VER
|
||||
wchar_t *savePathW = new wchar_t[m_savePath.length() + 1];
|
||||
int len = fsutils::toNativePath(m_savePath).toWCharArray(savePathW);
|
||||
savePathW[len] = L'\0';
|
||||
std::ofstream outfile(savePathW, std::ios_base::out | std::ios_base::binary);
|
||||
delete[] savePathW;
|
||||
#else
|
||||
std::ofstream outfile(fsutils::toNativePath(m_savePath).toLocal8Bit().constData(), std::ios_base::out | std::ios_base::binary);
|
||||
#endif
|
||||
if (outfile.fail())
|
||||
throw std::exception();
|
||||
|
||||
libt::bencode(std::ostream_iterator<char>(outfile), t.generate());
|
||||
outfile.close();
|
||||
|
||||
emit updateProgress(100);
|
||||
emit creationSuccess(m_savePath, parentPath);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
emit creationFailure(String::fromStdString(e.what()));
|
||||
}
|
||||
}
|
||||
73
src/core/bittorrent/torrentcreatorthread.h
Normal file
73
src/core/bittorrent/torrentcreatorthread.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_TORRENTCREATORTHREAD_H
|
||||
#define BITTORRENT_TORRENTCREATORTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QStringList>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TorrentCreatorThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TorrentCreatorThread(QObject *parent = 0);
|
||||
~TorrentCreatorThread();
|
||||
|
||||
void create(const QString &inputPath, const QString &savePath, const QStringList &trackers,
|
||||
const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize);
|
||||
void abortCreation();
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void creationFailure(const QString &msg);
|
||||
void creationSuccess(const QString &path, const QString &branchPath);
|
||||
void updateProgress(int progress);
|
||||
|
||||
private:
|
||||
void sendProgressSignal(int numHashes, int numPieces);
|
||||
|
||||
QString m_inputPath;
|
||||
QString m_savePath;
|
||||
QStringList m_trackers;
|
||||
QStringList m_urlSeeds;
|
||||
QString m_comment;
|
||||
bool m_private;
|
||||
int m_pieceSize;
|
||||
bool m_abort;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_TORRENTCREATORTHREAD_H
|
||||
1887
src/core/bittorrent/torrenthandle.cpp
Normal file
1887
src/core/bittorrent/torrenthandle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
380
src/core/bittorrent/torrenthandle.h
Normal file
380
src/core/bittorrent/torrenthandle.h
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_TORRENTHANDLE_H
|
||||
#define BITTORRENT_TORRENTHANDLE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QQueue>
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
|
||||
#include <libtorrent/torrent_handle.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include "core/tristatebool.h"
|
||||
#include "private/speedmonitor.h"
|
||||
#include "private/torrenthandleprivate.h"
|
||||
#include "infohash.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
class QBitArray;
|
||||
class QStringList;
|
||||
template<typename T, typename U> struct QPair;
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class alert;
|
||||
struct stats_alert;
|
||||
struct torrent_checked_alert;
|
||||
struct torrent_finished_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_completed_alert;
|
||||
struct tracker_error_alert;
|
||||
struct tracker_reply_alert;
|
||||
struct tracker_warning_alert;
|
||||
struct fastresume_rejected_alert;
|
||||
}
|
||||
|
||||
struct SessionPrivate;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
struct PeerAddress;
|
||||
class Session;
|
||||
class PeerInfo;
|
||||
class TrackerEntry;
|
||||
struct AddTorrentParams;
|
||||
|
||||
struct AddTorrentData
|
||||
{
|
||||
bool resumed;
|
||||
// for both new and resumed torrents
|
||||
QString name;
|
||||
QString label;
|
||||
QString savePath;
|
||||
bool disableTempPath;
|
||||
bool sequential;
|
||||
bool hasSeedStatus;
|
||||
// for new torrents
|
||||
TriStateBool addPaused;
|
||||
QVector<int> filePriorities;
|
||||
bool ignoreShareRatio;
|
||||
// for resumed torrents
|
||||
QDateTime addedTime;
|
||||
qreal ratioLimit;
|
||||
|
||||
AddTorrentData();
|
||||
AddTorrentData(const AddTorrentParams &in);
|
||||
};
|
||||
|
||||
struct TrackerInfo
|
||||
{
|
||||
QString lastMessage;
|
||||
quint32 numPeers;
|
||||
|
||||
TrackerInfo();
|
||||
};
|
||||
|
||||
class TorrentState
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
Unknown = -1,
|
||||
|
||||
Error,
|
||||
|
||||
Uploading,
|
||||
PausedUploading,
|
||||
QueuedUploading,
|
||||
StalledUploading,
|
||||
CheckingUploading,
|
||||
ForcedUploading,
|
||||
|
||||
Allocating,
|
||||
|
||||
DownloadingMetadata,
|
||||
Downloading,
|
||||
PausedDownloading,
|
||||
QueuedDownloading,
|
||||
StalledDownloading,
|
||||
CheckingDownloading,
|
||||
ForcedDownloading
|
||||
};
|
||||
|
||||
TorrentState(int value);
|
||||
|
||||
operator int() const;
|
||||
QString toString() const;
|
||||
|
||||
private:
|
||||
int m_value;
|
||||
};
|
||||
|
||||
class TorrentHandle : public QObject, public TorrentHandlePrivate
|
||||
{
|
||||
Q_DISABLE_COPY(TorrentHandle)
|
||||
|
||||
public:
|
||||
static const qreal USE_GLOBAL_RATIO;
|
||||
static const qreal NO_RATIO_LIMIT;
|
||||
|
||||
static const qreal MAX_RATIO;
|
||||
|
||||
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
|
||||
const AddTorrentData &data);
|
||||
~TorrentHandle();
|
||||
|
||||
bool isValid() const;
|
||||
InfoHash hash() const;
|
||||
QString name() const;
|
||||
QDateTime creationDate() const;
|
||||
QString creator() const;
|
||||
QString comment() const;
|
||||
bool isPrivate() const;
|
||||
qlonglong totalSize() const;
|
||||
qlonglong wantedSize() const;
|
||||
qlonglong completedSize() const;
|
||||
qlonglong incompletedSize() const;
|
||||
qlonglong pieceLength() const;
|
||||
qlonglong wastedSize() const;
|
||||
QString currentTracker() const;
|
||||
QString actualSavePath() const;
|
||||
QString savePath() const;
|
||||
QString rootPath() const;
|
||||
QString savePathParsed() const;
|
||||
int filesCount() const;
|
||||
int piecesCount() const;
|
||||
qreal progress() const;
|
||||
QString label() const;
|
||||
QDateTime addedTime() const;
|
||||
qreal ratioLimit() const;
|
||||
|
||||
QString firstFileSavePath() const;
|
||||
QString filePath(int index) const;
|
||||
QString fileName(int index) const;
|
||||
qlonglong fileSize(int index) const;
|
||||
QStringList absoluteFilePaths() const;
|
||||
QStringList absoluteFilePathsUnwanted() const;
|
||||
QPair<int, int> fileExtremityPieces(int index) const;
|
||||
QVector<int> filePriorities() const;
|
||||
|
||||
TorrentInfo info() const;
|
||||
bool isSeed() const;
|
||||
bool isPaused() const;
|
||||
bool isResumed() const;
|
||||
bool isQueued() const;
|
||||
bool isForced() const;
|
||||
bool isChecking() const;
|
||||
bool isDownloading() const;
|
||||
bool isUploading() const;
|
||||
bool isCompleted() const;
|
||||
bool isActive() const;
|
||||
bool isInactive() const;
|
||||
bool isSequentialDownload() const;
|
||||
bool hasFirstLastPiecePriority() const;
|
||||
TorrentState state() const;
|
||||
bool hasMetadata() const;
|
||||
bool hasMissingFiles() const;
|
||||
bool hasError() const;
|
||||
bool hasFilteredPieces() const;
|
||||
int queuePosition() const;
|
||||
QList<TrackerEntry> trackers() const;
|
||||
QHash<QString, TrackerInfo> trackerInfos() const;
|
||||
QList<QUrl> urlSeeds() const;
|
||||
QString error() const;
|
||||
qlonglong totalDownload() const;
|
||||
qlonglong totalUpload() const;
|
||||
int activeTime() const;
|
||||
int seedingTime() const;
|
||||
qulonglong eta() const;
|
||||
QVector<qreal> filesProgress() const;
|
||||
int seedsCount() const;
|
||||
int peersCount() const;
|
||||
int leechsCount() const;
|
||||
int completeCount() const;
|
||||
int incompleteCount() const;
|
||||
QDateTime lastSeenComplete() const;
|
||||
QDateTime completedTime() const;
|
||||
int timeSinceUpload() const;
|
||||
int timeSinceDownload() const;
|
||||
int downloadLimit() const;
|
||||
int uploadLimit() const;
|
||||
bool superSeeding() const;
|
||||
QList<PeerInfo> peers() const;
|
||||
QBitArray pieces() const;
|
||||
QBitArray downloadingPieces() const;
|
||||
QVector<int> pieceAvailability() const;
|
||||
qreal distributedCopies() const;
|
||||
qreal maxRatio(bool *usesGlobalRatio = 0) const;
|
||||
qreal realRatio() const;
|
||||
int uploadPayloadRate() const;
|
||||
int downloadPayloadRate() const;
|
||||
int totalPayloadUpload() const;
|
||||
int totalPayloadDownload() const;
|
||||
int connectionsCount() const;
|
||||
int connectionsLimit() const;
|
||||
qlonglong nextAnnounce() const;
|
||||
|
||||
void setName(const QString &name);
|
||||
void setLabel(const QString &label);
|
||||
void setSequentialDownload(bool b);
|
||||
void toggleSequentialDownload();
|
||||
void toggleFirstLastPiecePriority();
|
||||
void setFirstLastPiecePriority(bool b);
|
||||
void pause();
|
||||
void resume(bool forced = false);
|
||||
void move(QString path);
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
void forceReannounce();
|
||||
#else
|
||||
void forceReannounce(int index = -1);
|
||||
#endif
|
||||
void forceDHTAnnounce();
|
||||
void forceRecheck();
|
||||
void setTrackerLogin(const QString &username, const QString &password);
|
||||
void renameFile(int index, const QString &name);
|
||||
bool saveTorrentFile(const QString &path);
|
||||
void prioritizeFiles(const QVector<int> &priorities);
|
||||
void setFilePriority(int index, int priority);
|
||||
void setRatioLimit(qreal limit);
|
||||
void setUploadLimit(int limit);
|
||||
void setDownloadLimit(int limit);
|
||||
void setSuperSeeding(bool enable);
|
||||
void flushCache();
|
||||
void addTrackers(const QList<TrackerEntry> &trackers);
|
||||
void replaceTrackers(QList<TrackerEntry> trackers);
|
||||
void addUrlSeeds(const QList<QUrl> &urlSeeds);
|
||||
void removeUrlSeeds(const QList<QUrl> &urlSeeds);
|
||||
bool connectPeer(const PeerAddress &peerAddress);
|
||||
|
||||
QString toMagnetUri() const;
|
||||
|
||||
bool needSaveResumeData() const;
|
||||
void saveResumeData();
|
||||
|
||||
libtorrent::torrent_handle nativeHandle() const;
|
||||
|
||||
private:
|
||||
typedef boost::function<void ()> MoveStorageTrigger;
|
||||
|
||||
void initialize();
|
||||
void updateStatus();
|
||||
void updateStatus(const libtorrent::torrent_status &nativeStatus);
|
||||
void updateState();
|
||||
void updateTorrentInfo();
|
||||
|
||||
void handleAlert(libtorrent::alert *a);
|
||||
void handleStateUpdate(const libtorrent::torrent_status &nativeStatus);
|
||||
void handleDefaultSavePathChanged();
|
||||
void handleTempPathChanged();
|
||||
void handleAppendExtensionToggled();
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
void handleResolveCountriesToggled();
|
||||
#endif
|
||||
|
||||
void handleStorageMovedAlert(libtorrent::storage_moved_alert *p);
|
||||
void handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert *p);
|
||||
void handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p);
|
||||
void handleTrackerWarningAlert(libtorrent::tracker_warning_alert *p);
|
||||
void handleTrackerErrorAlert(libtorrent::tracker_error_alert *p);
|
||||
void handleTorrentCheckedAlert(libtorrent::torrent_checked_alert *p);
|
||||
void handleTorrentFinishedAlert(libtorrent::torrent_finished_alert *p);
|
||||
void handleTorrentPausedAlert(libtorrent::torrent_paused_alert *p);
|
||||
void handleTorrentResumedAlert(libtorrent::torrent_resumed_alert *p);
|
||||
void handleSaveResumeDataAlert(libtorrent::save_resume_data_alert *p);
|
||||
void handleSaveResumeDataFailedAlert(libtorrent::save_resume_data_failed_alert *p);
|
||||
void handleFastResumeRejectedAlert(libtorrent::fastresume_rejected_alert *p);
|
||||
void handleFileRenamedAlert(libtorrent::file_renamed_alert *p);
|
||||
void handleFileCompletedAlert(libtorrent::file_completed_alert *p);
|
||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p);
|
||||
void handleStatsAlert(libtorrent::stats_alert *p);
|
||||
|
||||
bool isMoveInProgress() const;
|
||||
bool useTempPath() const;
|
||||
QString nativeActualSavePath() const;
|
||||
|
||||
void resolveCountries(bool b);
|
||||
void adjustSavePath();
|
||||
void adjustActualSavePath();
|
||||
void moveStorage(const QString &newPath);
|
||||
void appendExtensionsToIncompleteFiles();
|
||||
void removeExtensionsFromIncompleteFiles();
|
||||
bool addTracker(const TrackerEntry &tracker);
|
||||
bool addUrlSeed(const QUrl &urlSeed);
|
||||
bool removeUrlSeed(const QUrl &urlSeed);
|
||||
|
||||
SessionPrivate *const m_session;
|
||||
libtorrent::torrent_handle m_nativeHandle;
|
||||
libtorrent::torrent_status m_nativeStatus;
|
||||
TorrentState m_state;
|
||||
TorrentInfo m_torrentInfo;
|
||||
SpeedMonitor m_speedMonitor;
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
QString m_nativeName;
|
||||
QString m_nativeSavePath;
|
||||
#endif
|
||||
|
||||
InfoHash m_hash;
|
||||
|
||||
QString m_oldPath;
|
||||
QString m_newPath;
|
||||
// m_queuedPath is where files should be moved to,
|
||||
// when current moving is completed
|
||||
QString m_queuedPath;
|
||||
QQueue<MoveStorageTrigger> m_moveStorageTriggers;
|
||||
|
||||
// Persistent data
|
||||
QString m_name;
|
||||
QDateTime m_addedTime;
|
||||
QString m_savePath;
|
||||
QString m_label;
|
||||
bool m_hasSeedStatus;
|
||||
qreal m_ratioLimit;
|
||||
bool m_tempPathDisabled;
|
||||
bool m_hasMissingFiles;
|
||||
|
||||
bool m_useDefaultSavePath;
|
||||
bool m_pauseAfterRecheck;
|
||||
bool m_needSaveResumeData;
|
||||
QHash<QString, TrackerInfo> m_trackerInfos;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_TORRENTHANDLE_H
|
||||
230
src/core/bittorrent/torrentinfo.cpp
Normal file
230
src/core/bittorrent/torrentinfo.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 <QString>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
#include <QDateTime>
|
||||
|
||||
#include <libtorrent/error_code.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
#include "core/misc.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "infohash.h"
|
||||
#include "trackerentry.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
|
||||
TorrentInfo::TorrentInfo(boost::intrusive_ptr<const libt::torrent_info> nativeInfo)
|
||||
: m_nativeInfo(const_cast<libt::torrent_info *>(nativeInfo.get()))
|
||||
{
|
||||
}
|
||||
|
||||
TorrentInfo::TorrentInfo(const TorrentInfo &other)
|
||||
: m_nativeInfo(other.m_nativeInfo)
|
||||
{
|
||||
}
|
||||
|
||||
TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
||||
{
|
||||
m_nativeInfo = other.m_nativeInfo;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString &error)
|
||||
{
|
||||
error.clear();
|
||||
libt::error_code ec;
|
||||
TorrentInfo info(new libt::torrent_info(String::toStdString(fsutils::toNativePath(path)), ec));
|
||||
if (ec) {
|
||||
error = QString::fromUtf8(ec.message().c_str());
|
||||
qDebug("Cannot load .torrent file: %s", qPrintable(error));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path)
|
||||
{
|
||||
QString error;
|
||||
return loadFromFile(path, error);
|
||||
}
|
||||
|
||||
bool TorrentInfo::isValid() const
|
||||
{
|
||||
return (m_nativeInfo && m_nativeInfo->is_valid() && (m_nativeInfo->num_files() > 0));
|
||||
}
|
||||
|
||||
InfoHash TorrentInfo::hash() const
|
||||
{
|
||||
if (!isValid()) return InfoHash();
|
||||
return m_nativeInfo->info_hash();
|
||||
}
|
||||
|
||||
QString TorrentInfo::name() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(m_nativeInfo->name());
|
||||
}
|
||||
|
||||
QDateTime TorrentInfo::creationDate() const
|
||||
{
|
||||
if (!isValid()) return QDateTime();
|
||||
boost::optional<time_t> t = m_nativeInfo->creation_date();
|
||||
return t ? QDateTime::fromTime_t(*t) : QDateTime();
|
||||
}
|
||||
|
||||
QString TorrentInfo::creator() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(m_nativeInfo->creator());
|
||||
}
|
||||
|
||||
QString TorrentInfo::comment() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(m_nativeInfo->comment());
|
||||
}
|
||||
|
||||
bool TorrentInfo::isPrivate() const
|
||||
{
|
||||
if (!isValid()) return false;
|
||||
return m_nativeInfo->priv();
|
||||
}
|
||||
|
||||
qlonglong TorrentInfo::totalSize() const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->total_size();
|
||||
}
|
||||
|
||||
int TorrentInfo::filesCount() const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->num_files();
|
||||
}
|
||||
|
||||
int TorrentInfo::pieceLength() const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->piece_length();
|
||||
}
|
||||
|
||||
int TorrentInfo::piecesCount() const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->num_pieces();
|
||||
}
|
||||
|
||||
QString TorrentInfo::filePath(int index) const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return fsutils::fromNativePath(String::fromStdString(m_nativeInfo->files().file_path(index)));
|
||||
}
|
||||
|
||||
QStringList TorrentInfo::filePaths() const
|
||||
{
|
||||
QStringList list;
|
||||
for (int i = 0; i < filesCount(); ++i)
|
||||
list << filePath(i);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QString TorrentInfo::fileName(int index) const
|
||||
{
|
||||
return fsutils::fileName(filePath(index));
|
||||
}
|
||||
|
||||
QString TorrentInfo::origFilePath(int index) const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return fsutils::fromNativePath(String::fromStdString(m_nativeInfo->orig_files().file_path(index)));
|
||||
}
|
||||
|
||||
qlonglong TorrentInfo::fileSize(int index) const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->files().file_size(index);
|
||||
}
|
||||
|
||||
qlonglong TorrentInfo::fileOffset(int index) const
|
||||
{
|
||||
if (!isValid()) return -1;
|
||||
return m_nativeInfo->file_at(index).offset;
|
||||
}
|
||||
|
||||
QList<TrackerEntry> TorrentInfo::trackers() const
|
||||
{
|
||||
if (!isValid()) return QList<TrackerEntry>();
|
||||
|
||||
QList<TrackerEntry> trackers;
|
||||
foreach (const libt::announce_entry &tracker, m_nativeInfo->trackers())
|
||||
trackers.append(tracker);
|
||||
|
||||
return trackers;
|
||||
}
|
||||
|
||||
QList<QUrl> TorrentInfo::urlSeeds() const
|
||||
{
|
||||
if (!isValid()) return QList<QUrl>();
|
||||
|
||||
QList<QUrl> urlSeeds;
|
||||
foreach (const libt::web_seed_entry &webSeed, m_nativeInfo->web_seeds())
|
||||
if (webSeed.type == libt::web_seed_entry::url_seed)
|
||||
urlSeeds.append(QUrl(webSeed.url.c_str()));
|
||||
|
||||
return urlSeeds;
|
||||
}
|
||||
|
||||
QByteArray TorrentInfo::metadata() const
|
||||
{
|
||||
if (!isValid()) return QByteArray();
|
||||
return QByteArray(m_nativeInfo->metadata().get(), m_nativeInfo->metadata_size());
|
||||
}
|
||||
|
||||
QString TorrentInfo::toMagnetUri() const
|
||||
{
|
||||
if (!isValid()) return QString();
|
||||
return String::fromStdString(libt::make_magnet_uri(*m_nativeInfo));
|
||||
}
|
||||
|
||||
void TorrentInfo::renameFile(uint index, const QString &newPath)
|
||||
{
|
||||
if (!isValid()) return;
|
||||
m_nativeInfo->rename_file(index, String::toStdString(newPath));
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> TorrentInfo::nativeInfo() const
|
||||
{
|
||||
return m_nativeInfo;
|
||||
}
|
||||
88
src/core/bittorrent/torrentinfo.h
Normal file
88
src/core/bittorrent/torrentinfo.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_TORRENTINFO_H
|
||||
#define BITTORRENT_TORRENTINFO_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
class QString;
|
||||
class QUrl;
|
||||
class QDateTime;
|
||||
class QStringList;
|
||||
class QByteArray;
|
||||
template<typename T> class QList;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash;
|
||||
class TrackerEntry;
|
||||
|
||||
class TorrentInfo
|
||||
{
|
||||
public:
|
||||
explicit TorrentInfo(boost::intrusive_ptr<const libtorrent::torrent_info> nativeInfo = boost::intrusive_ptr<const libtorrent::torrent_info>());
|
||||
TorrentInfo(const TorrentInfo &other);
|
||||
|
||||
static TorrentInfo loadFromFile(const QString &path, QString &error);
|
||||
static TorrentInfo loadFromFile(const QString &path);
|
||||
|
||||
TorrentInfo &operator=(const TorrentInfo &other);
|
||||
|
||||
bool isValid() const;
|
||||
InfoHash hash() const;
|
||||
QString name() const;
|
||||
QDateTime creationDate() const;
|
||||
QString creator() const;
|
||||
QString comment() const;
|
||||
bool isPrivate() const;
|
||||
qlonglong totalSize() const;
|
||||
int filesCount() const;
|
||||
int pieceLength() const;
|
||||
int piecesCount() const;
|
||||
QString filePath(int index) const;
|
||||
QStringList filePaths() const;
|
||||
QString fileName(int index) const;
|
||||
QString origFilePath(int index) const;
|
||||
qlonglong fileSize(int index) const;
|
||||
qlonglong fileOffset(int index) const;
|
||||
QList<TrackerEntry> trackers() const;
|
||||
QList<QUrl> urlSeeds() const;
|
||||
QByteArray metadata() const;
|
||||
QString toMagnetUri() const;
|
||||
|
||||
void renameFile(uint index, const QString &newPath);
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> nativeInfo() const;
|
||||
|
||||
private:
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> m_nativeInfo;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_TORRENTINFO_H
|
||||
@@ -31,59 +31,68 @@
|
||||
|
||||
#include <vector>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/entry.hpp>
|
||||
|
||||
#include "preferences.h"
|
||||
#include "http/server.h"
|
||||
#include "qtracker.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/http/server.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "tracker.h"
|
||||
|
||||
// QPeer
|
||||
bool QPeer::operator!=(const QPeer &other) const
|
||||
// static limits
|
||||
static const int MAX_TORRENTS = 100;
|
||||
static const int MAX_PEERS_PER_TORRENT = 1000;
|
||||
static const int ANNOUNCE_INTERVAL = 1800; // 30min
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
// Peer
|
||||
bool Peer::operator!=(const Peer &other) const
|
||||
{
|
||||
return qhash() != other.qhash();
|
||||
return uid() != other.uid();
|
||||
}
|
||||
|
||||
bool QPeer::operator==(const QPeer &other) const
|
||||
bool Peer::operator==(const Peer &other) const
|
||||
{
|
||||
return qhash() == other.qhash();
|
||||
return uid() == other.uid();
|
||||
}
|
||||
|
||||
QString QPeer::qhash() const
|
||||
QString Peer::uid() const
|
||||
{
|
||||
return ip + ":" + QString::number(port);
|
||||
}
|
||||
|
||||
libtorrent::entry QPeer::toEntry(bool no_peer_id) const
|
||||
libtorrent::entry Peer::toEntry(bool noPeerId) const
|
||||
{
|
||||
libtorrent::entry::dictionary_type peer_map;
|
||||
if (!no_peer_id)
|
||||
peer_map["id"] = libtorrent::entry(peer_id.toStdString());
|
||||
peer_map["ip"] = libtorrent::entry(ip.toStdString());
|
||||
peer_map["port"] = libtorrent::entry(port);
|
||||
libtorrent::entry::dictionary_type peerMap;
|
||||
if (!noPeerId)
|
||||
peerMap["id"] = libtorrent::entry(String::toStdString(peerId));
|
||||
peerMap["ip"] = libtorrent::entry(String::toStdString(ip));
|
||||
peerMap["port"] = libtorrent::entry(port);
|
||||
|
||||
return libtorrent::entry(peer_map);
|
||||
return libtorrent::entry(peerMap);
|
||||
}
|
||||
|
||||
// QTracker
|
||||
// Tracker
|
||||
|
||||
QTracker::QTracker(QObject *parent)
|
||||
Tracker::Tracker(QObject *parent)
|
||||
: Http::ResponseBuilder(parent)
|
||||
, m_server(new Http::Server(this, this))
|
||||
{
|
||||
}
|
||||
|
||||
QTracker::~QTracker()
|
||||
Tracker::~Tracker()
|
||||
{
|
||||
if (m_server->isListening())
|
||||
qDebug("Shutting down the embedded tracker...");
|
||||
// TODO: Store the torrent list
|
||||
}
|
||||
|
||||
bool QTracker::start()
|
||||
bool Tracker::start()
|
||||
{
|
||||
const int listen_port = Preferences::instance()->getTrackerPort();
|
||||
const int listenPort = Preferences::instance()->getTrackerPort();
|
||||
|
||||
if (m_server->isListening()) {
|
||||
if (m_server->serverPort() == listen_port) {
|
||||
if (m_server->serverPort() == listenPort) {
|
||||
// Already listening on the right port, just return
|
||||
return true;
|
||||
}
|
||||
@@ -93,21 +102,21 @@ bool QTracker::start()
|
||||
|
||||
qDebug("Starting the embedded tracker...");
|
||||
// Listen on the predefined port
|
||||
return m_server->listen(QHostAddress::Any, listen_port);
|
||||
return m_server->listen(QHostAddress::Any, listenPort);
|
||||
}
|
||||
|
||||
Http::Response QTracker::processRequest(const Http::Request &request, const Http::Environment &env)
|
||||
Http::Response Tracker::processRequest(const Http::Request &request, const Http::Environment &env)
|
||||
{
|
||||
clear(); // clear response
|
||||
|
||||
//qDebug("QTracker received the following request:\n%s", qPrintable(parser.toString()));
|
||||
//qDebug("Tracker received the following request:\n%s", qPrintable(parser.toString()));
|
||||
// Is request a GET request?
|
||||
if (request.method != "GET") {
|
||||
qDebug("QTracker: Unsupported HTTP request: %s", qPrintable(request.method));
|
||||
qDebug("Tracker: Unsupported HTTP request: %s", qPrintable(request.method));
|
||||
status(100, "Invalid request type");
|
||||
}
|
||||
else if (!request.path.startsWith("/announce", Qt::CaseInsensitive)) {
|
||||
qDebug("QTracker: Unrecognized path: %s", qPrintable(request.path));
|
||||
qDebug("Tracker: Unrecognized path: %s", qPrintable(request.path));
|
||||
status(100, "Invalid request type");
|
||||
}
|
||||
else {
|
||||
@@ -120,85 +129,85 @@ Http::Response QTracker::processRequest(const Http::Request &request, const Http
|
||||
return response();
|
||||
}
|
||||
|
||||
void QTracker::respondToAnnounceRequest()
|
||||
void Tracker::respondToAnnounceRequest()
|
||||
{
|
||||
const QStringMap &gets = m_request.gets;
|
||||
TrackerAnnounceRequest annonce_req;
|
||||
TrackerAnnounceRequest annonceReq;
|
||||
|
||||
// IP
|
||||
annonce_req.peer.ip = m_env.clientAddress.toString();
|
||||
annonceReq.peer.ip = m_env.clientAddress.toString();
|
||||
|
||||
// 1. Get info_hash
|
||||
if (!gets.contains("info_hash")) {
|
||||
qDebug("QTracker: Missing info_hash");
|
||||
qDebug("Tracker: Missing info_hash");
|
||||
status(101, "Missing info_hash");
|
||||
return;
|
||||
}
|
||||
annonce_req.info_hash = gets.value("info_hash");
|
||||
annonceReq.infoHash = gets.value("info_hash");
|
||||
// info_hash cannot be longer than 20 bytes
|
||||
/*if (annonce_req.info_hash.toLatin1().length() > 20) {
|
||||
qDebug("QTracker: Info_hash is not 20 byte long: %s (%d)", qPrintable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
|
||||
qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qPrintable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
|
||||
status(150, "Invalid infohash");
|
||||
return;
|
||||
}*/
|
||||
|
||||
// 2. Get peer ID
|
||||
if (!gets.contains("peer_id")) {
|
||||
qDebug("QTracker: Missing peer_id");
|
||||
qDebug("Tracker: Missing peer_id");
|
||||
status(102, "Missing peer_id");
|
||||
return;
|
||||
}
|
||||
annonce_req.peer.peer_id = gets.value("peer_id");
|
||||
annonceReq.peer.peerId = gets.value("peer_id");
|
||||
// peer_id cannot be longer than 20 bytes
|
||||
/*if (annonce_req.peer.peer_id.length() > 20) {
|
||||
qDebug("QTracker: peer_id is not 20 byte long: %s", qPrintable(annonce_req.peer.peer_id));
|
||||
qDebug("Tracker: peer_id is not 20 byte long: %s", qPrintable(annonce_req.peer.peer_id));
|
||||
status(151, "Invalid peerid");
|
||||
return;
|
||||
}*/
|
||||
|
||||
// 3. Get port
|
||||
if (!gets.contains("port")) {
|
||||
qDebug("QTracker: Missing port");
|
||||
qDebug("Tracker: Missing port");
|
||||
status(103, "Missing port");
|
||||
return;
|
||||
}
|
||||
bool ok = false;
|
||||
annonce_req.peer.port = gets.value("port").toInt(&ok);
|
||||
if (!ok || annonce_req.peer.port < 1 || annonce_req.peer.port > 65535) {
|
||||
qDebug("QTracker: Invalid port number (%d)", annonce_req.peer.port);
|
||||
annonceReq.peer.port = gets.value("port").toInt(&ok);
|
||||
if (!ok || annonceReq.peer.port < 1 || annonceReq.peer.port > 65535) {
|
||||
qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port);
|
||||
status(103, "Missing port");
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. Get event
|
||||
annonce_req.event = "";
|
||||
annonceReq.event = "";
|
||||
if (gets.contains("event")) {
|
||||
annonce_req.event = gets.value("event");
|
||||
qDebug("QTracker: event is %s", qPrintable(annonce_req.event));
|
||||
annonceReq.event = gets.value("event");
|
||||
qDebug("Tracker: event is %s", qPrintable(annonceReq.event));
|
||||
}
|
||||
|
||||
// 5. Get numwant
|
||||
annonce_req.numwant = 50;
|
||||
annonceReq.numwant = 50;
|
||||
if (gets.contains("numwant")) {
|
||||
int tmp = gets.value("numwant").toInt();
|
||||
if (tmp > 0) {
|
||||
qDebug("QTracker: numwant = %d", tmp);
|
||||
annonce_req.numwant = tmp;
|
||||
qDebug("Tracker: numwant = %d", tmp);
|
||||
annonceReq.numwant = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// 6. no_peer_id (extension)
|
||||
annonce_req.no_peer_id = false;
|
||||
annonceReq.noPeerId = false;
|
||||
if (gets.contains("no_peer_id"))
|
||||
annonce_req.no_peer_id = true;
|
||||
annonceReq.noPeerId = true;
|
||||
|
||||
// 7. TODO: support "compact" extension
|
||||
|
||||
// Done parsing, now let's reply
|
||||
if (m_torrents.contains(annonce_req.info_hash)) {
|
||||
if (annonce_req.event == "stopped") {
|
||||
qDebug("QTracker: Peer stopped downloading, deleting it from the list");
|
||||
m_torrents[annonce_req.info_hash].remove(annonce_req.peer.qhash());
|
||||
if (m_torrents.contains(annonceReq.infoHash)) {
|
||||
if (annonceReq.event == "stopped") {
|
||||
qDebug("Tracker: Peer stopped downloading, deleting it from the list");
|
||||
m_torrents[annonceReq.infoHash].remove(annonceReq.peer.uid());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -210,36 +219,36 @@ void QTracker::respondToAnnounceRequest()
|
||||
}
|
||||
}
|
||||
// Register the user
|
||||
PeerList peers = m_torrents.value(annonce_req.info_hash);
|
||||
PeerList peers = m_torrents.value(annonceReq.infoHash);
|
||||
if (peers.size() == MAX_PEERS_PER_TORRENT) {
|
||||
// Too many peers, remove a random one
|
||||
peers.erase(peers.begin());
|
||||
}
|
||||
peers[annonce_req.peer.qhash()] = annonce_req.peer;
|
||||
m_torrents[annonce_req.info_hash] = peers;
|
||||
peers[annonceReq.peer.uid()] = annonceReq.peer;
|
||||
m_torrents[annonceReq.infoHash] = peers;
|
||||
|
||||
// Reply
|
||||
replyWithPeerList(annonce_req);
|
||||
replyWithPeerList(annonceReq);
|
||||
}
|
||||
|
||||
void QTracker::replyWithPeerList(const TrackerAnnounceRequest &annonce_req)
|
||||
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
|
||||
{
|
||||
// Prepare the entry for bencoding
|
||||
libtorrent::entry::dictionary_type reply_dict;
|
||||
reply_dict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
|
||||
QList<QPeer> peers = m_torrents.value(annonce_req.info_hash).values();
|
||||
libtorrent::entry::list_type peer_list;
|
||||
foreach (const QPeer &p, peers) {
|
||||
libtorrent::entry::dictionary_type replyDict;
|
||||
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
|
||||
QList<Peer> peers = m_torrents.value(annonceReq.infoHash).values();
|
||||
libtorrent::entry::list_type peerList;
|
||||
foreach (const Peer &p, peers) {
|
||||
//if (p != annonce_req.peer)
|
||||
peer_list.push_back(p.toEntry(annonce_req.no_peer_id));
|
||||
peerList.push_back(p.toEntry(annonceReq.noPeerId));
|
||||
}
|
||||
reply_dict["peers"] = libtorrent::entry(peer_list);
|
||||
libtorrent::entry reply_entry(reply_dict);
|
||||
replyDict["peers"] = libtorrent::entry(peerList);
|
||||
libtorrent::entry replyEntry(replyDict);
|
||||
// bencode
|
||||
std::vector<char> buf;
|
||||
libtorrent::bencode(std::back_inserter(buf), reply_entry);
|
||||
libtorrent::bencode(std::back_inserter(buf), replyEntry);
|
||||
QByteArray reply(&buf[0], static_cast<int>(buf.size()));
|
||||
qDebug("QTracker: reply with the following bencoded data:\n %s", reply.constData());
|
||||
qDebug("Tracker: reply with the following bencoded data:\n %s", reply.constData());
|
||||
|
||||
// HTTP reply
|
||||
print(reply, Http::CONTENT_TYPE_TXT);
|
||||
103
src/core/bittorrent/tracker.h
Normal file
103
src/core/bittorrent/tracker.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_TRACKER_H
|
||||
#define BITTORRENT_TRACKER_H
|
||||
|
||||
#include <QHash>
|
||||
#include "core/http/types.h"
|
||||
#include "core/http/responsebuilder.h"
|
||||
#include "core/http/irequesthandler.h"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class entry;
|
||||
}
|
||||
|
||||
namespace Http
|
||||
{
|
||||
class Server;
|
||||
}
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
struct Peer
|
||||
{
|
||||
QString ip;
|
||||
QString peerId;
|
||||
int port;
|
||||
|
||||
bool operator!=(const Peer &other) const;
|
||||
bool operator==(const Peer &other) const;
|
||||
QString uid() const;
|
||||
libtorrent::entry toEntry(bool noPeerId) const;
|
||||
};
|
||||
|
||||
struct TrackerAnnounceRequest
|
||||
{
|
||||
QString infoHash;
|
||||
QString event;
|
||||
int numwant;
|
||||
Peer peer;
|
||||
// Extensions
|
||||
bool noPeerId;
|
||||
};
|
||||
|
||||
typedef QHash<QString, Peer> PeerList;
|
||||
typedef QHash<QString, PeerList> TorrentList;
|
||||
|
||||
/* Basic Bittorrent tracker implementation in Qt */
|
||||
/* Following http://wiki.theory.org/BitTorrent_Tracker_Protocol */
|
||||
class Tracker : public Http::ResponseBuilder, public Http::IRequestHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(Tracker)
|
||||
|
||||
public:
|
||||
explicit Tracker(QObject *parent = 0);
|
||||
~Tracker();
|
||||
|
||||
bool start();
|
||||
Http::Response processRequest(const Http::Request &request, const Http::Environment &env);
|
||||
|
||||
private:
|
||||
void respondToAnnounceRequest();
|
||||
void replyWithPeerList(const TrackerAnnounceRequest &annonceReq);
|
||||
|
||||
Http::Server *m_server;
|
||||
TorrentList m_torrents;
|
||||
|
||||
Http::Request m_request;
|
||||
Http::Environment m_env;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_TRACKER_H
|
||||
93
src/core/bittorrent/trackerentry.cpp
Normal file
93
src/core/bittorrent/trackerentry.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 <QString>
|
||||
|
||||
#include "core/misc.h"
|
||||
#include "core/utils/string.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
TrackerEntry::TrackerEntry(const QString &url)
|
||||
: m_nativeEntry(libtorrent::announce_entry(String::toStdString(url)))
|
||||
{
|
||||
}
|
||||
|
||||
TrackerEntry::TrackerEntry(const libtorrent::announce_entry &nativeEntry)
|
||||
: m_nativeEntry(nativeEntry)
|
||||
{
|
||||
}
|
||||
|
||||
TrackerEntry::TrackerEntry(const TrackerEntry &other)
|
||||
: m_nativeEntry(other.m_nativeEntry)
|
||||
{
|
||||
}
|
||||
|
||||
QString TrackerEntry::url() const
|
||||
{
|
||||
return String::fromStdString(m_nativeEntry.url);
|
||||
}
|
||||
|
||||
int TrackerEntry::tier() const
|
||||
{
|
||||
return m_nativeEntry.tier;
|
||||
}
|
||||
|
||||
TrackerEntry::Status TrackerEntry::status() const
|
||||
{
|
||||
if (m_nativeEntry.verified)
|
||||
return Working;
|
||||
else if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating)
|
||||
return Updating;
|
||||
else if (m_nativeEntry.fails == 0)
|
||||
return NotContacted;
|
||||
else
|
||||
return NotWorking;
|
||||
}
|
||||
|
||||
void TrackerEntry::setTier(int value)
|
||||
{
|
||||
m_nativeEntry.tier = value;
|
||||
}
|
||||
|
||||
TrackerEntry &TrackerEntry::operator=(const TrackerEntry &other)
|
||||
{
|
||||
this->m_nativeEntry = other.m_nativeEntry;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TrackerEntry::operator==(const TrackerEntry &other)
|
||||
{
|
||||
return (QUrl(url()) == QUrl(other.url()));
|
||||
}
|
||||
|
||||
libtorrent::announce_entry TrackerEntry::nativeEntry() const
|
||||
{
|
||||
return m_nativeEntry;
|
||||
}
|
||||
68
src/core/bittorrent/trackerentry.h
Normal file
68
src/core/bittorrent/trackerentry.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef BITTORRENT_TRACKERENTRY_H
|
||||
#define BITTORRENT_TRACKERENTRY_H
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
class QString;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class TrackerEntry
|
||||
{
|
||||
public:
|
||||
enum Status
|
||||
{
|
||||
NotContacted,
|
||||
Working,
|
||||
Updating,
|
||||
NotWorking
|
||||
};
|
||||
|
||||
TrackerEntry(const QString &url);
|
||||
TrackerEntry(const libtorrent::announce_entry &nativeEntry);
|
||||
TrackerEntry(const TrackerEntry &other);
|
||||
|
||||
QString url() const;
|
||||
int tier() const;
|
||||
Status status() const;
|
||||
|
||||
void setTier(int value);
|
||||
TrackerEntry &operator=(const TrackerEntry &other);
|
||||
bool operator==(const TrackerEntry &other);
|
||||
|
||||
libtorrent::announce_entry nativeEntry() const;
|
||||
|
||||
private:
|
||||
libtorrent::announce_entry m_nativeEntry;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BITTORRENT_TRACKERENTRY_H
|
||||
@@ -1,16 +1,13 @@
|
||||
include(qtlibtorrent/qtlibtorrent.pri)
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/types.h \
|
||||
$$PWD/misc.h \
|
||||
$$PWD/fs_utils.h \
|
||||
$$PWD/downloadthread.h \
|
||||
$$PWD/torrentpersistentdata.h \
|
||||
$$PWD/tristatebool.h \
|
||||
$$PWD/filesystemwatcher.h \
|
||||
$$PWD/scannedfoldersmodel.h \
|
||||
$$PWD/qinisettings.h \
|
||||
$$PWD/logger.h \
|
||||
$$PWD/preferences.h \
|
||||
$$PWD/qtracker.h \
|
||||
$$PWD/iconprovider.h \
|
||||
$$PWD/http/irequesthandler.h \
|
||||
$$PWD/http/connection.h \
|
||||
$$PWD/http/requestparser.h \
|
||||
@@ -19,24 +16,66 @@ HEADERS += \
|
||||
$$PWD/http/types.h \
|
||||
$$PWD/http/responsebuilder.h \
|
||||
$$PWD/net/dnsupdater.h \
|
||||
$$PWD/net/downloadmanager.h \
|
||||
$$PWD/net/downloadhandler.h \
|
||||
$$PWD/net/portforwarder.h \
|
||||
$$PWD/net/reverseresolution.h \
|
||||
$$PWD/net/smtp.h
|
||||
$$PWD/net/smtp.h \
|
||||
$$PWD/bittorrent/infohash.h \
|
||||
$$PWD/bittorrent/session.h \
|
||||
$$PWD/bittorrent/sessionstatus.h \
|
||||
$$PWD/bittorrent/cachestatus.h \
|
||||
$$PWD/bittorrent/magneturi.h \
|
||||
$$PWD/bittorrent/torrentinfo.h \
|
||||
$$PWD/bittorrent/torrenthandle.h \
|
||||
$$PWD/bittorrent/peerinfo.h \
|
||||
$$PWD/bittorrent/trackerentry.h \
|
||||
$$PWD/bittorrent/tracker.h \
|
||||
$$PWD/bittorrent/torrentcreatorthread.h \
|
||||
$$PWD/bittorrent/private/sessionprivate.h \
|
||||
$$PWD/bittorrent/private/torrenthandleprivate.h \
|
||||
$$PWD/bittorrent/private/speedmonitor.h \
|
||||
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
||||
$$PWD/bittorrent/private/filterparserthread.h \
|
||||
$$PWD/bittorrent/private/statistics.h \
|
||||
$$PWD/utils/string.h \
|
||||
$$PWD/torrentfilter.h \
|
||||
$$PWD/scanfoldersmodel.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/downloadthread.cpp \
|
||||
$$PWD/scannedfoldersmodel.cpp \
|
||||
$$PWD/torrentpersistentdata.cpp \
|
||||
$$PWD/filesystemwatcher.cpp \
|
||||
$$PWD/misc.cpp \
|
||||
$$PWD/fs_utils.cpp \
|
||||
$$PWD/tristatebool.cpp \
|
||||
$$PWD/filesystemwatcher.cpp \
|
||||
$$PWD/logger.cpp \
|
||||
$$PWD/preferences.cpp \
|
||||
$$PWD/qtracker.cpp \
|
||||
$$PWD/iconprovider.cpp \
|
||||
$$PWD/http/connection.cpp \
|
||||
$$PWD/http/requestparser.cpp \
|
||||
$$PWD/http/responsegenerator.cpp \
|
||||
$$PWD/http/server.cpp \
|
||||
$$PWD/http/responsebuilder.cpp \
|
||||
$$PWD/net/dnsupdater.cpp \
|
||||
$$PWD/net/downloadmanager.cpp \
|
||||
$$PWD/net/downloadhandler.cpp \
|
||||
$$PWD/net/portforwarder.cpp \
|
||||
$$PWD/net/reverseresolution.cpp \
|
||||
$$PWD/net/smtp.cpp
|
||||
$$PWD/net/smtp.cpp \
|
||||
$$PWD/bittorrent/infohash.cpp \
|
||||
$$PWD/bittorrent/session.cpp \
|
||||
$$PWD/bittorrent/sessionstatus.cpp \
|
||||
$$PWD/bittorrent/cachestatus.cpp \
|
||||
$$PWD/bittorrent/magneturi.cpp \
|
||||
$$PWD/bittorrent/torrentinfo.cpp \
|
||||
$$PWD/bittorrent/torrenthandle.cpp \
|
||||
$$PWD/bittorrent/peerinfo.cpp \
|
||||
$$PWD/bittorrent/trackerentry.cpp \
|
||||
$$PWD/bittorrent/tracker.cpp \
|
||||
$$PWD/bittorrent/torrentcreatorthread.cpp \
|
||||
$$PWD/bittorrent/private/speedmonitor.cpp \
|
||||
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
||||
$$PWD/bittorrent/private/filterparserthread.cpp \
|
||||
$$PWD/bittorrent/private/statistics.cpp \
|
||||
$$PWD/utils/string.cpp \
|
||||
$$PWD/torrentfilter.cpp \
|
||||
$$PWD/scanfoldersmodel.cpp
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
#include "core/preferences.h"
|
||||
#include "core/bittorrent/torrentinfo.h"
|
||||
#include "core/bittorrent/magneturi.h"
|
||||
#include "filesystemwatcher.h"
|
||||
|
||||
#ifndef CIFS_MAGIC_NUMBER
|
||||
#define CIFS_MAGIC_NUMBER 0xFF534D42
|
||||
@@ -30,8 +32,6 @@
|
||||
const int WATCH_INTERVAL = 10000; // 10 sec
|
||||
const int MAX_PARTIAL_RETRIES = 5;
|
||||
|
||||
#include "filesystemwatcher.h"
|
||||
|
||||
FileSystemWatcher::FileSystemWatcher(QObject *parent)
|
||||
: QFileSystemWatcher(parent)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ void FileSystemWatcher::processPartialTorrents()
|
||||
if (!QFile::exists(torrentPath)) {
|
||||
m_partialTorrents.remove(torrentPath);
|
||||
}
|
||||
else if (fsutils::isValidTorrentFile(torrentPath)) {
|
||||
else if (BitTorrent::TorrentInfo::loadFromFile(torrentPath).isValid()) {
|
||||
noLongerPartial << torrentPath;
|
||||
m_partialTorrents.remove(torrentPath);
|
||||
}
|
||||
@@ -197,11 +197,11 @@ void FileSystemWatcher::addTorrentsFromDir(const QDir &dir, QStringList &torrent
|
||||
if (fileAbsPath.endsWith(".magnet")) {
|
||||
QFile f(fileAbsPath);
|
||||
if (f.open(QIODevice::ReadOnly)
|
||||
&& !misc::magnetUriToHash(QString::fromLocal8Bit(f.readAll())).isEmpty()) {
|
||||
&& !BitTorrent::MagnetUri(QString::fromLocal8Bit(f.readAll())).isValid()) {
|
||||
torrents << fileAbsPath;
|
||||
}
|
||||
}
|
||||
else if (fsutils::isValidTorrentFile(fileAbsPath)) {
|
||||
else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid()) {
|
||||
torrents << fileAbsPath;
|
||||
}
|
||||
else if (!m_partialTorrents.contains(fileAbsPath)) {
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
void removePath(const QString &path);
|
||||
|
||||
signals:
|
||||
void torrentsAdded(QStringList &pathList);
|
||||
void torrentsAdded(const QStringList &pathList);
|
||||
|
||||
protected slots:
|
||||
void scanLocalFolder(QString path);
|
||||
|
||||
@@ -36,11 +36,7 @@
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#ifdef DISABLE_GUI
|
||||
#include <QCoreApplication>
|
||||
#else
|
||||
#include <QApplication>
|
||||
#endif
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
@@ -110,17 +106,6 @@ QString fsutils::folderName(const QString& file_path) {
|
||||
return path.left(slash_index);
|
||||
}
|
||||
|
||||
bool fsutils::isValidTorrentFile(const QString& torrent_path) {
|
||||
try {
|
||||
boost::intrusive_ptr<libtorrent::torrent_info> t = new torrent_info(fsutils::toNativePath(torrent_path).toUtf8().constData());
|
||||
if (!t->is_valid() || t->num_files() == 0)
|
||||
return false;
|
||||
} catch(std::exception&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an empty folder tree.
|
||||
*
|
||||
@@ -233,38 +218,6 @@ bool fsutils::sameFiles(const QString& path1, const QString& path2) {
|
||||
return same;
|
||||
}
|
||||
|
||||
QString fsutils::updateLabelInSavePath(const QString& defaultSavePath, const QString& save_path, const QString& old_label, const QString& new_label) {
|
||||
if (old_label == new_label) return fsutils::fromNativePath(save_path);
|
||||
QString defaultPath = fsutils::fromNativePath(defaultSavePath);
|
||||
QString path = fsutils::fromNativePath(save_path);
|
||||
qDebug("UpdateLabelInSavePath(%s, %s, %s)", qPrintable(path), qPrintable(old_label), qPrintable(new_label));
|
||||
if (!path.startsWith(defaultPath)) return path;
|
||||
QString new_save_path = path;
|
||||
new_save_path.remove(defaultPath);
|
||||
QStringList path_parts = new_save_path.split("/", QString::SkipEmptyParts);
|
||||
if (path_parts.empty()) {
|
||||
if (!new_label.isEmpty())
|
||||
path_parts << new_label;
|
||||
} else {
|
||||
if (old_label.isEmpty() || path_parts.first() != old_label) {
|
||||
if (path_parts.first() != new_label)
|
||||
path_parts.prepend(new_label);
|
||||
} else {
|
||||
if (new_label.isEmpty()) {
|
||||
path_parts.removeAt(0);
|
||||
} else {
|
||||
if (path_parts.first() != new_label)
|
||||
path_parts.replace(0, new_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
new_save_path = defaultPath;
|
||||
if (!new_save_path.endsWith("/")) new_save_path += "/";
|
||||
new_save_path += path_parts.join("/");
|
||||
qDebug("New save path is %s", qPrintable(new_save_path));
|
||||
return new_save_path;
|
||||
}
|
||||
|
||||
QString fsutils::toValidFileSystemName(QString filename) {
|
||||
qDebug("toValidFSName: %s", qPrintable(filename));
|
||||
const QRegExp regex("[\\\\/:?\"*<>|]");
|
||||
@@ -513,15 +466,6 @@ QString fsutils::searchEngineLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::BTBackupLocation() {
|
||||
const QString location = fsutils::expandPathAbs(QDesktopServicesDataLocation()
|
||||
+ "BT_backup");
|
||||
QDir locationDir(location);
|
||||
if (!locationDir.exists())
|
||||
locationDir.mkpath(locationDir.absolutePath());
|
||||
return location;
|
||||
}
|
||||
|
||||
QString fsutils::cacheLocation() {
|
||||
QString location = fsutils::expandPathAbs(QDesktopServicesCacheLocation());
|
||||
QDir locationDir(location);
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace fsutils
|
||||
QString folderName(const QString& file_path);
|
||||
qint64 computePathSize(const QString& path);
|
||||
bool sameFiles(const QString& path1, const QString& path2);
|
||||
QString updateLabelInSavePath(const QString &defaultSavePath, const QString &save_path, const QString& old_label, const QString& new_label);
|
||||
QString toValidFileSystemName(QString filename);
|
||||
bool isValidFileSystemName(const QString& filename);
|
||||
long long freeDiskSpaceOnPath(QString path);
|
||||
@@ -54,7 +53,6 @@ namespace fsutils
|
||||
bool sameFileNames(const QString& first, const QString& second);
|
||||
QString expandPath(const QString& path);
|
||||
QString expandPathAbs(const QString& path);
|
||||
bool isValidTorrentFile(const QString& path);
|
||||
bool smartRemoveEmptyFolderTree(const QString& dir_path);
|
||||
bool forceRemove(const QString& file_path);
|
||||
|
||||
@@ -64,7 +62,6 @@ namespace fsutils
|
||||
QString QDesktopServicesDownloadLocation();
|
||||
/* End of Qt4 code */
|
||||
QString searchEngineLocation();
|
||||
QString BTBackupLocation();
|
||||
QString cacheLocation();
|
||||
|
||||
}
|
||||
|
||||
64
src/core/iconprovider.cpp
Normal file
64
src/core/iconprovider.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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 <QString>
|
||||
#include "iconprovider.h"
|
||||
|
||||
IconProvider::IconProvider(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
IconProvider::~IconProvider() {}
|
||||
|
||||
void IconProvider::initInstance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new IconProvider;
|
||||
}
|
||||
|
||||
void IconProvider::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
IconProvider *IconProvider::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
QString IconProvider::getIconPath(const QString &iconId)
|
||||
{
|
||||
return ":/icons/oxygen/" + iconId + ".png";
|
||||
}
|
||||
|
||||
IconProvider *IconProvider::m_instance = 0;
|
||||
55
src/core/iconprovider.h
Normal file
55
src/core/iconprovider.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2011 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ICONPROVIDER_H
|
||||
#define ICONPROVIDER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QString;
|
||||
|
||||
class IconProvider : public QObject
|
||||
{
|
||||
Q_DISABLE_COPY(IconProvider)
|
||||
|
||||
public:
|
||||
static void initInstance();
|
||||
static void freeInstance();
|
||||
static IconProvider *instance();
|
||||
|
||||
virtual QString getIconPath(const QString &iconId);
|
||||
|
||||
protected:
|
||||
explicit IconProvider(QObject *parent = 0);
|
||||
~IconProvider();
|
||||
|
||||
static IconProvider *m_instance;
|
||||
};
|
||||
|
||||
#endif // ICONPROVIDER_H
|
||||
@@ -44,15 +44,18 @@ Logger::Logger()
|
||||
|
||||
Logger::~Logger() {}
|
||||
|
||||
Logger * Logger::instance()
|
||||
Logger *Logger::instance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new Logger;
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void Logger::drop()
|
||||
void Logger::initInstance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new Logger;
|
||||
}
|
||||
|
||||
void Logger::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
|
||||
@@ -53,9 +53,9 @@ class Logger : public QObject
|
||||
Q_DISABLE_COPY(Logger)
|
||||
|
||||
public:
|
||||
static Logger* instance();
|
||||
static void drop();
|
||||
~Logger();
|
||||
static void initInstance();
|
||||
static void freeInstance();
|
||||
static Logger *instance();
|
||||
|
||||
void addMessage(const QString &message, const Log::MsgType &type = Log::NORMAL);
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
@@ -72,6 +72,8 @@ signals:
|
||||
|
||||
private:
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
static Logger* m_instance;
|
||||
QVector<Log::Msg> m_messages;
|
||||
QVector<Log::Peer> m_peers;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -28,8 +28,6 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QUrl>
|
||||
@@ -71,14 +69,7 @@ const int UNLEN = 256;
|
||||
#endif
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
#include <libtorrent/peer_id.hpp>
|
||||
#else
|
||||
#include <libtorrent/sha1_hash.hpp>
|
||||
#endif
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
using namespace libtorrent;
|
||||
#include "misc.h"
|
||||
|
||||
static struct { const char *source; const char *comment; } units[] = {
|
||||
QT_TRANSLATE_NOOP3("misc", "B", "bytes"),
|
||||
@@ -88,35 +79,8 @@ static struct { const char *source; const char *comment; } units[] = {
|
||||
QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)")
|
||||
};
|
||||
|
||||
QString misc::toQString(const std::string &str)
|
||||
{
|
||||
return QString::fromLocal8Bit(str.c_str());
|
||||
}
|
||||
|
||||
QString misc::toQString(const char* str)
|
||||
{
|
||||
return QString::fromLocal8Bit(str);
|
||||
}
|
||||
|
||||
QString misc::toQStringU(const std::string &str)
|
||||
{
|
||||
return QString::fromUtf8(str.c_str());
|
||||
}
|
||||
|
||||
QString misc::toQStringU(const char* str)
|
||||
{
|
||||
return QString::fromUtf8(str);
|
||||
}
|
||||
|
||||
QString misc::toQString(const libtorrent::sha1_hash &hash)
|
||||
{
|
||||
char out[41];
|
||||
libtorrent::to_hex((char const*)&hash[0], libtorrent::sha1_hash::size, out);
|
||||
return QString(out);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
void misc::shutdownComputer(shutDownAction action)
|
||||
void misc::shutdownComputer(ShutDownAction action)
|
||||
{
|
||||
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB)
|
||||
// Use dbus to power off / suspend the system
|
||||
@@ -378,28 +342,6 @@ QString misc::bcLinkToMagnet(QString bc_link)
|
||||
return magnet;
|
||||
}
|
||||
|
||||
QString misc::magnetUriToName(const QString& magnet_uri)
|
||||
{
|
||||
add_torrent_params p;
|
||||
error_code ec;
|
||||
parse_magnet_uri(magnet_uri.toUtf8().constData(), p, ec);
|
||||
|
||||
if (ec)
|
||||
return QString::null;
|
||||
return toQStringU(p.name);
|
||||
}
|
||||
|
||||
QString misc::magnetUriToHash(const QString& magnet_uri)
|
||||
{
|
||||
add_torrent_params p;
|
||||
error_code ec;
|
||||
parse_magnet_uri(magnet_uri.toUtf8().constData(), p, ec);
|
||||
|
||||
if (ec)
|
||||
return QString::null;
|
||||
return toQString(p.info_hash);
|
||||
}
|
||||
|
||||
// Take a number of seconds and return an user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
QString misc::userFriendlyDuration(qlonglong seconds)
|
||||
@@ -530,11 +472,6 @@ QString misc::parseHtmlLinks(const QString &raw_text)
|
||||
return result;
|
||||
}
|
||||
|
||||
QString misc::toQString(time_t t)
|
||||
{
|
||||
return QDateTime::fromTime_t(t).toString(Qt::DefaultLocaleLongDate);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
bool misc::naturalSort(QString left, QString right, bool &result) // uses lessThan comparison
|
||||
{ // Return value indicates if functions was successful
|
||||
@@ -624,18 +561,6 @@ bool misc::slowEquals(const QByteArray &a, const QByteArray &b)
|
||||
return (diff == 0);
|
||||
}
|
||||
|
||||
void misc::loadBencodedFile(const QString &filename, std::vector<char> &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec)
|
||||
{
|
||||
QFile file(filename);
|
||||
if (!file.open(QIODevice::ReadOnly)) return;
|
||||
const qint64 content_size = file.bytesAvailable();
|
||||
if (content_size <= 0) return;
|
||||
buffer.resize(content_size);
|
||||
file.read(&buffer[0], content_size);
|
||||
// bdecode
|
||||
lazy_bdecode(&buffer[0], &buffer[0] + buffer.size(), entry, ec);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Trick to get a portable sleep() function
|
||||
class SleeperThread: public QThread {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -39,37 +39,18 @@
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
#ifndef DISABLE_GUI
|
||||
#include <QIcon>
|
||||
#endif
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/error_code.hpp>
|
||||
|
||||
namespace libtorrent {
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
class big_number;
|
||||
typedef big_number sha1_hash;
|
||||
#else
|
||||
class sha1_hash;
|
||||
#endif
|
||||
struct lazy_entry;
|
||||
}
|
||||
namespace BitTorrent { class TorrentHandle; }
|
||||
|
||||
const qlonglong MAX_ETA = 8640000;
|
||||
enum shutDownAction { NO_SHUTDOWN, SHUTDOWN_COMPUTER, SUSPEND_COMPUTER, HIBERNATE_COMPUTER };
|
||||
enum ShutDownAction { NO_SHUTDOWN, SHUTDOWN_COMPUTER, SUSPEND_COMPUTER, HIBERNATE_COMPUTER };
|
||||
|
||||
/* Miscellaneaous functions that can be useful */
|
||||
namespace misc
|
||||
{
|
||||
QString toQString(const std::string &str);
|
||||
QString toQString(const char* str);
|
||||
QString toQStringU(const std::string &str);
|
||||
QString toQStringU(const char* str);
|
||||
QString toQString(const libtorrent::sha1_hash &hash);
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
void shutdownComputer(shutDownAction action = SHUTDOWN_COMPUTER);
|
||||
void shutdownComputer(ShutDownAction action = SHUTDOWN_COMPUTER);
|
||||
#endif
|
||||
|
||||
QString parseHtmlLinks(const QString &raw_text);
|
||||
@@ -87,8 +68,7 @@ namespace misc
|
||||
// value must be given in bytes
|
||||
QString friendlyUnit(qreal val, bool is_speed = false);
|
||||
bool isPreviewable(const QString& extension);
|
||||
QString magnetUriToName(const QString& magnet_uri);
|
||||
QString magnetUriToHash(const QString& magnet_uri);
|
||||
|
||||
QString bcLinkToMagnet(QString bc_link);
|
||||
// Take a number of seconds and return an user-friendly
|
||||
// time duration like "1d 2h 10m".
|
||||
@@ -100,7 +80,6 @@ namespace misc
|
||||
QList<int> intListfromStringList(const QStringList &l);
|
||||
QList<bool> boolListfromStringList(const QStringList &l);
|
||||
|
||||
QString toQString(time_t t);
|
||||
QString accurateDoubleToString(const double &n, const int &precision);
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
@@ -110,8 +89,6 @@ namespace misc
|
||||
// Implements constant-time comparison to protect against timing attacks
|
||||
// Taken from https://crackstation.net/hashing-security.htm
|
||||
bool slowEquals(const QByteArray &a, const QByteArray &b);
|
||||
void loadBencodedFile(const QString &filename, std::vector<char> &buffer, libtorrent::lazy_entry &entry, libtorrent::error_code &ec);
|
||||
|
||||
void msleep(unsigned long msecs);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,12 +33,13 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkCookie>
|
||||
#include <QUrl>
|
||||
#include <QDebug>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "fs_utils.h"
|
||||
#include "misc.h"
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "downloadmanager.h"
|
||||
#include "downloadhandler.h"
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QUrl;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Net
|
||||
|
||||
160
src/core/net/portforwarder.cpp
Normal file
160
src/core/net/portforwarder.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 <QDebug>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
#include <libtorrent/upnp.hpp>
|
||||
#include <libtorrent/natpmp.hpp>
|
||||
#endif
|
||||
|
||||
#include "core/logger.h"
|
||||
#include "core/preferences.h"
|
||||
#include "portforwarder.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace Net;
|
||||
|
||||
PortForwarder::PortForwarder(libtorrent::session *provider, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_active(false)
|
||||
, m_provider(provider)
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
, m_upnp(0)
|
||||
, m_natpmp(0)
|
||||
#endif
|
||||
{
|
||||
configure();
|
||||
connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure()));
|
||||
}
|
||||
|
||||
PortForwarder::~PortForwarder()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void PortForwarder::initInstance(libtorrent::session *const provider)
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new PortForwarder(provider);
|
||||
}
|
||||
|
||||
void PortForwarder::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PortForwarder *PortForwarder::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void PortForwarder::addPort(qint16 port)
|
||||
{
|
||||
if (!m_mappedPorts.contains(port)) {
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
m_mappedPorts.insert(port, qMakePair(0, 0));
|
||||
#else
|
||||
m_mappedPorts.insert(port, 0);
|
||||
#endif
|
||||
if (m_active) {
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
m_mappedPorts[port].first = m_upnp->add_mapping(libt::upnp::tcp, port, port);
|
||||
m_mappedPorts[port].second = m_natpmp->add_mapping(libt::natpmp::tcp, port, port);
|
||||
#else
|
||||
m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarder::deletePort(qint16 port)
|
||||
{
|
||||
if (m_mappedPorts.contains(port)) {
|
||||
if (m_active) {
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
m_upnp->delete_mapping(m_mappedPorts[port].first);
|
||||
m_natpmp->delete_mapping(m_mappedPorts[port].second);
|
||||
#else
|
||||
m_provider->delete_port_mapping(m_mappedPorts[port]);
|
||||
#endif
|
||||
}
|
||||
m_mappedPorts.remove(port);
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarder::configure()
|
||||
{
|
||||
bool enable = Preferences::instance()->isUPnPEnabled();
|
||||
if (m_active != enable) {
|
||||
if (enable)
|
||||
start();
|
||||
else
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void PortForwarder::start()
|
||||
{
|
||||
qDebug("Enabling UPnP / NAT-PMP");
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
m_upnp = m_provider->start_upnp();
|
||||
m_natpmp = m_provider->start_natpmp();
|
||||
foreach (qint16 port, m_mappedPorts.keys()) {
|
||||
m_mappedPorts[port].first = m_upnp->add_mapping(libt::upnp::tcp, port, port);
|
||||
m_mappedPorts[port].second = m_natpmp->add_mapping(libt::natpmp::tcp, port, port);
|
||||
}
|
||||
#else
|
||||
m_provider->start_upnp();
|
||||
m_provider->start_natpmp();
|
||||
foreach (qint16 port, m_mappedPorts.keys())
|
||||
m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port);
|
||||
#endif
|
||||
m_active = true;
|
||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
||||
}
|
||||
|
||||
void PortForwarder::stop()
|
||||
{
|
||||
qDebug("Disabling UPnP / NAT-PMP");
|
||||
m_provider->stop_upnp();
|
||||
m_provider->stop_natpmp();
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
m_upnp = 0;
|
||||
m_natpmp = 0;
|
||||
#endif
|
||||
m_active = false;
|
||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
||||
}
|
||||
|
||||
PortForwarder *PortForwarder::m_instance = 0;
|
||||
84
src/core/net/portforwarder.h
Normal file
84
src/core/net/portforwarder.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef NET_PORTFORWARDER_H
|
||||
#define NET_PORTFORWARDER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
class upnp;
|
||||
class natpmp;
|
||||
#endif
|
||||
class session;
|
||||
}
|
||||
|
||||
namespace Net
|
||||
{
|
||||
class PortForwarder : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(PortForwarder)
|
||||
|
||||
public:
|
||||
static void initInstance(libtorrent::session *const provider);
|
||||
static void freeInstance();
|
||||
static PortForwarder *instance();
|
||||
|
||||
void addPort(qint16 port);
|
||||
void deletePort(qint16 port);
|
||||
|
||||
private slots:
|
||||
void configure();
|
||||
|
||||
private:
|
||||
explicit PortForwarder(libtorrent::session *const provider, QObject *parent = 0);
|
||||
~PortForwarder();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
bool m_active;
|
||||
libtorrent::session *m_provider;
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
libtorrent::upnp *m_upnp;
|
||||
libtorrent::natpmp *m_natpmp;
|
||||
QHash<qint16, QPair<int, int> > m_mappedPorts;
|
||||
#else
|
||||
QHash<qint16, int> m_mappedPorts;
|
||||
#endif
|
||||
|
||||
static PortForwarder *m_instance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NET_PORTFORWARDER_H
|
||||
@@ -116,15 +116,18 @@ Preferences::~Preferences()
|
||||
save();
|
||||
}
|
||||
|
||||
Preferences * Preferences::instance()
|
||||
Preferences *Preferences::instance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new Preferences;
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void Preferences::drop()
|
||||
void Preferences::initInstance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new Preferences;
|
||||
}
|
||||
|
||||
void Preferences::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
@@ -132,12 +135,11 @@ void Preferences::drop()
|
||||
}
|
||||
}
|
||||
|
||||
void Preferences::save()
|
||||
bool Preferences::save()
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
|
||||
if (!dirty)
|
||||
return;
|
||||
if (!dirty) return false;
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
// QSettings delete the file before writing it out. This can result in problems
|
||||
@@ -160,7 +162,7 @@ void Preferences::save()
|
||||
settings->sync(); // Important to get error status
|
||||
if (settings->status() == QSettings::AccessError) {
|
||||
delete settings;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
QString new_path = settings->fileName();
|
||||
delete settings;
|
||||
@@ -173,7 +175,7 @@ void Preferences::save()
|
||||
delete settings;
|
||||
#endif
|
||||
|
||||
emit changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
const QVariant Preferences::value(const QString &key, const QVariant &defaultValue) const
|
||||
@@ -950,12 +952,12 @@ void Preferences::setGlobalMaxRatio(qreal ratio)
|
||||
setValue("Preferences/Bittorrent/MaxRatio", ratio);
|
||||
}
|
||||
|
||||
int Preferences::getMaxRatioAction() const
|
||||
MaxRatioAction Preferences::getMaxRatioAction() const
|
||||
{
|
||||
return value("Preferences/Bittorrent/MaxRatioAction", PAUSE_ACTION).toInt();
|
||||
return value("Preferences/Bittorrent/MaxRatioAction", MaxRatioAction::Pause).toInt();
|
||||
}
|
||||
|
||||
void Preferences::setMaxRatioAction(int act)
|
||||
void Preferences::setMaxRatioAction(MaxRatioAction act)
|
||||
{
|
||||
setValue("Preferences/Bittorrent/MaxRatioAction", act);
|
||||
}
|
||||
@@ -2477,3 +2479,9 @@ void Preferences::setHostNameCookies(const QString &host_name, const QList<QByte
|
||||
hosts_table.insert(host_name, raw_cookies);
|
||||
setValue("Rss/hosts_cookies", hosts_table);
|
||||
}
|
||||
|
||||
void Preferences::apply()
|
||||
{
|
||||
if (save())
|
||||
emit changed();
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include "core/types.h"
|
||||
|
||||
enum scheduler_days
|
||||
{
|
||||
EVERY_DAY,
|
||||
@@ -57,12 +59,6 @@ enum scheduler_days
|
||||
SUN
|
||||
};
|
||||
|
||||
enum maxRatioAction
|
||||
{
|
||||
PAUSE_ACTION,
|
||||
REMOVE_ACTION
|
||||
};
|
||||
|
||||
namespace Proxy
|
||||
{
|
||||
enum ProxyType
|
||||
@@ -101,7 +97,9 @@ class Preferences: public QObject
|
||||
Q_DISABLE_COPY(Preferences)
|
||||
|
||||
private:
|
||||
explicit Preferences();
|
||||
Preferences();
|
||||
~Preferences();
|
||||
|
||||
static Preferences* m_instance;
|
||||
QHash<QString, QVariant> m_data;
|
||||
int m_randomPort;
|
||||
@@ -111,16 +109,16 @@ private:
|
||||
const QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
|
||||
void setValue(const QString &key, const QVariant &value);
|
||||
|
||||
private slots:
|
||||
bool save();
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
public slots:
|
||||
void save();
|
||||
|
||||
public:
|
||||
static void initInstance();
|
||||
static void freeInstance();
|
||||
static Preferences* instance();
|
||||
static void drop();
|
||||
~Preferences();
|
||||
|
||||
// General options
|
||||
QString getLocale() const;
|
||||
@@ -276,8 +274,8 @@ public:
|
||||
void setEncryptionSetting(int val);
|
||||
qreal getGlobalMaxRatio() const;
|
||||
void setGlobalMaxRatio(qreal ratio);
|
||||
int getMaxRatioAction() const;
|
||||
void setMaxRatioAction(int act);
|
||||
MaxRatioAction getMaxRatioAction() const;
|
||||
void setMaxRatioAction(MaxRatioAction act);
|
||||
|
||||
// IP Filter
|
||||
bool isFilteringEnabled() const;
|
||||
@@ -536,6 +534,8 @@ public slots:
|
||||
void setStatusFilterState(bool checked);
|
||||
void setLabelFilterState(bool checked);
|
||||
void setTrackerFilterState(bool checked);
|
||||
|
||||
void apply();
|
||||
};
|
||||
|
||||
#endif // PREFERENCES_H
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#ifndef BANDWIDTHSCHEDULER_H
|
||||
#define BANDWIDTHSCHEDULER_H
|
||||
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
#include <QDateTime>
|
||||
#include "core/preferences.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
class BandwidthScheduler: public QTimer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BandwidthScheduler(QObject *parent): QTimer(parent) {
|
||||
Q_ASSERT(Preferences::instance()->isSchedulerEnabled());
|
||||
// Signal shot, we call start() again manually
|
||||
setSingleShot(true);
|
||||
// Connect Signals/Slots
|
||||
connect(this, SIGNAL(timeout()), this, SLOT(start()));
|
||||
}
|
||||
|
||||
public slots:
|
||||
void start() {
|
||||
const Preferences* const pref = Preferences::instance();
|
||||
Q_ASSERT(pref->isSchedulerEnabled());
|
||||
bool alt_bw_enabled = pref->isAltBandwidthEnabled();
|
||||
|
||||
QTime start = pref->getSchedulerStartTime();
|
||||
QTime end = pref->getSchedulerEndTime();
|
||||
QTime now = QTime::currentTime();
|
||||
int sched_days = pref->getSchedulerDays();
|
||||
int day = QDateTime::currentDateTime().toLocalTime().date().dayOfWeek();
|
||||
bool new_mode = false;
|
||||
bool reverse = false;
|
||||
|
||||
if (start > end) {
|
||||
QTime temp = start;
|
||||
start = end;
|
||||
end = temp;
|
||||
reverse = true;
|
||||
}
|
||||
|
||||
if (start <= now && end >= now) {
|
||||
switch(sched_days) {
|
||||
case EVERY_DAY:
|
||||
new_mode = true;
|
||||
break;
|
||||
case WEEK_ENDS:
|
||||
if (day == 6 || day == 7)
|
||||
new_mode = true;
|
||||
break;
|
||||
case WEEK_DAYS:
|
||||
if (day != 6 && day != 7)
|
||||
new_mode = true;
|
||||
break;
|
||||
default:
|
||||
if (day == sched_days - 2)
|
||||
new_mode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
new_mode = !new_mode;
|
||||
|
||||
if (new_mode != alt_bw_enabled)
|
||||
emit switchToAlternativeMode(new_mode);
|
||||
|
||||
// Timeout regularly to accomodate for external system clock changes
|
||||
// eg from the user or from a timesync utility
|
||||
QTimer::start(1500);
|
||||
}
|
||||
|
||||
signals:
|
||||
void switchToAlternativeMode(bool alternative);
|
||||
};
|
||||
|
||||
#endif // BANDWIDTHSCHEDULER_H
|
||||
@@ -1,394 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "filterparserthread.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/ip_filter.hpp>
|
||||
|
||||
FilterParserThread::FilterParserThread(QObject* parent, libtorrent::session *s) : QThread(parent), s(s), abort(false) {
|
||||
|
||||
}
|
||||
|
||||
FilterParserThread::~FilterParserThread() {
|
||||
abort = true;
|
||||
wait();
|
||||
}
|
||||
|
||||
// Parser for eMule ip filter in DAT format
|
||||
int FilterParserThread::parseDATFilterFile(QString filePath, libtorrent::ip_filter& filter) {
|
||||
int ruleCount = 0;
|
||||
QFile file(filePath);
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine();
|
||||
// Ignoring empty lines
|
||||
line = line.trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if (line.startsWith('#') || line.startsWith("//")) continue;
|
||||
|
||||
// Line should be splitted by commas
|
||||
QList<QByteArray> partsList = line.split(',');
|
||||
const uint nbElem = partsList.size();
|
||||
|
||||
// IP Range should be splitted by a dash
|
||||
QList<QByteArray> IPs = partsList.first().split('-');
|
||||
if (IPs.size() != 2) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Line was %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
const QString strStartIP = cleanupIPAddress(IPs.at(0));
|
||||
if (strStartIP.isEmpty()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec);
|
||||
if (ec) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
const QString strEndIP = cleanupIPAddress(IPs.at(1));
|
||||
if (strEndIP.isEmpty()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec);
|
||||
if (ec) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP));
|
||||
continue;
|
||||
}
|
||||
if (startAddr.is_v4() != endAddr.is_v4()) {
|
||||
qDebug("Ipfilter.dat: line %d is malformed.", nbLine);
|
||||
qDebug("One IP is IPv4 and the other is IPv6!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there is an access value (apparently not mandatory)
|
||||
int nbAccess = 0;
|
||||
if (nbElem > 1) {
|
||||
// There is possibly one
|
||||
nbAccess = partsList.at(1).trimmed().toInt();
|
||||
}
|
||||
|
||||
if (nbAccess > 127) {
|
||||
// Ignoring this rule because access value is too high
|
||||
continue;
|
||||
}
|
||||
// Now Add to the filter
|
||||
try {
|
||||
filter.add_rule(startAddr, endAddr, libtorrent::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
}catch(exception) {
|
||||
qDebug("Bad line in filter file, avoided crash...");
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
int FilterParserThread::parseP2PFilterFile(QString filePath, libtorrent::ip_filter& filter) {
|
||||
int ruleCount = 0;
|
||||
QFile file(filePath);
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
unsigned int nbLine = 0;
|
||||
while (!file.atEnd() && !abort) {
|
||||
++nbLine;
|
||||
QByteArray line = file.readLine().trimmed();
|
||||
if (line.isEmpty()) continue;
|
||||
// Ignoring commented lines
|
||||
if (line.startsWith('#') || line.startsWith("//")) continue;
|
||||
// Line is splitted by :
|
||||
QList<QByteArray> partsList = line.split(':');
|
||||
if (partsList.size() < 2) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
continue;
|
||||
}
|
||||
// Get IP range
|
||||
QList<QByteArray> IPs = partsList.last().split('-');
|
||||
if (IPs.size() != 2) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
boost::system::error_code ec;
|
||||
QString strStartIP = cleanupIPAddress(IPs.at(0));
|
||||
if (strStartIP.isEmpty()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec);
|
||||
if (ec) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Start IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
QString strEndIP = cleanupIPAddress(IPs.at(1));
|
||||
if (strEndIP.isEmpty()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("End IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec);
|
||||
if (ec) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("End IP is invalid: %s", qPrintable(strStartIP));
|
||||
continue;
|
||||
}
|
||||
if (startAddr.is_v4() != endAddr.is_v4()) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
filter.add_rule(startAddr, endAddr, libtorrent::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
} catch(std::exception&) {
|
||||
qDebug("p2p file: line %d is malformed.", nbLine);
|
||||
qDebug("Line was: %s", line.constData());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
int FilterParserThread::getlineInStream(QDataStream& stream, string& name, char delim) {
|
||||
char c;
|
||||
int total_read = 0;
|
||||
int read;
|
||||
do {
|
||||
read = stream.readRawData(&c, 1);
|
||||
total_read += read;
|
||||
if (read > 0) {
|
||||
if (c != delim) {
|
||||
name += c;
|
||||
} else {
|
||||
// Delim found
|
||||
return total_read;
|
||||
}
|
||||
}
|
||||
} while(read > 0);
|
||||
return total_read;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
int FilterParserThread::parseP2BFilterFile(QString filePath, libtorrent::ip_filter& filter) {
|
||||
int ruleCount = 0;
|
||||
QFile file(filePath);
|
||||
if (file.exists()) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
QDataStream stream(&file);
|
||||
// Read header
|
||||
char buf[7];
|
||||
unsigned char version;
|
||||
if (
|
||||
!stream.readRawData(buf, sizeof(buf)) ||
|
||||
memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) ||
|
||||
!stream.readRawData((char*)&version, sizeof(version))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
if (version==1 || version==2) {
|
||||
qDebug ("p2b version 1 or 2");
|
||||
unsigned int start, end;
|
||||
|
||||
string name;
|
||||
while(getlineInStream(stream, name, '\0') && !abort) {
|
||||
if (
|
||||
!stream.readRawData((char*)&start, sizeof(start)) ||
|
||||
!stream.readRawData((char*)&end, sizeof(end))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
libtorrent::address_v4 first(ntohl(start));
|
||||
libtorrent::address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
try {
|
||||
filter.add_rule(first, last, libtorrent::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
} catch(std::exception&) {}
|
||||
}
|
||||
}
|
||||
else if (version==3) {
|
||||
qDebug ("p2b version 3");
|
||||
unsigned int namecount;
|
||||
if (!stream.readRawData((char*)&namecount, sizeof(namecount))) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
namecount=ntohl(namecount);
|
||||
// Reading names although, we don't really care about them
|
||||
for (unsigned int i=0; i<namecount; i++) {
|
||||
string name;
|
||||
if (!getlineInStream(stream, name, '\0')) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
if (abort) return ruleCount;
|
||||
}
|
||||
// Reading the ranges
|
||||
unsigned int rangecount;
|
||||
if (!stream.readRawData((char*)&rangecount, sizeof(rangecount))) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
rangecount=ntohl(rangecount);
|
||||
|
||||
unsigned int name, start, end;
|
||||
|
||||
for (unsigned int i=0; i<rangecount; i++) {
|
||||
if (
|
||||
!stream.readRawData((char*)&name, sizeof(name)) ||
|
||||
!stream.readRawData((char*)&start, sizeof(start)) ||
|
||||
!stream.readRawData((char*)&end, sizeof(end))
|
||||
) {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
// Network byte order to Host byte order
|
||||
// asio address_v4 contructor expects it
|
||||
// that way
|
||||
libtorrent::address_v4 first(ntohl(start));
|
||||
libtorrent::address_v4 last(ntohl(end));
|
||||
// Apply to bittorrent session
|
||||
try {
|
||||
filter.add_rule(first, last, libtorrent::ip_filter::blocked);
|
||||
++ruleCount;
|
||||
} catch(std::exception&) {}
|
||||
if (abort) return ruleCount;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl;
|
||||
return ruleCount;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return ruleCount;
|
||||
}
|
||||
|
||||
// Process ip filter file
|
||||
// Supported formats:
|
||||
// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format
|
||||
// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format
|
||||
// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format
|
||||
void FilterParserThread::processFilterFile(QString _filePath) {
|
||||
if (isRunning()) {
|
||||
// Already parsing a filter, abort first
|
||||
abort = true;
|
||||
wait();
|
||||
}
|
||||
abort = false;
|
||||
filePath = _filePath;
|
||||
// Run it
|
||||
start();
|
||||
}
|
||||
|
||||
void FilterParserThread::processFilterList(libtorrent::session *s, const QStringList& IPs) {
|
||||
// First, import current filter
|
||||
libtorrent::ip_filter filter = s->get_ip_filter();
|
||||
foreach (const QString &ip, IPs) {
|
||||
qDebug("Manual ban of peer %s", ip.toLocal8Bit().constData());
|
||||
boost::system::error_code ec;
|
||||
libtorrent::address addr = libtorrent::address::from_string(ip.toLocal8Bit().constData(), ec);
|
||||
Q_ASSERT(!ec);
|
||||
if (!ec)
|
||||
filter.add_rule(addr, addr, libtorrent::ip_filter::blocked);
|
||||
}
|
||||
s->set_ip_filter(filter);
|
||||
}
|
||||
|
||||
QString FilterParserThread::cleanupIPAddress(QString _ip) {
|
||||
QHostAddress ip(_ip.trimmed());
|
||||
if (ip.isNull()) {
|
||||
return QString();
|
||||
}
|
||||
return ip.toString();
|
||||
}
|
||||
|
||||
void FilterParserThread::run() {
|
||||
qDebug("Processing filter file");
|
||||
libtorrent::ip_filter filter = s->get_ip_filter();
|
||||
int ruleCount = 0;
|
||||
if (filePath.endsWith(".p2p", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2p file
|
||||
ruleCount = parseP2PFilterFile(filePath, filter);
|
||||
} else {
|
||||
if (filePath.endsWith(".p2b", Qt::CaseInsensitive)) {
|
||||
// PeerGuardian p2b file
|
||||
ruleCount = parseP2BFilterFile(filePath, filter);
|
||||
} else {
|
||||
// Default: eMule DAT format
|
||||
ruleCount = parseDATFilterFile(filePath, filter);
|
||||
}
|
||||
}
|
||||
if (abort)
|
||||
return;
|
||||
try {
|
||||
s->set_ip_filter(filter);
|
||||
emit IPFilterParsed(ruleCount);
|
||||
} catch(std::exception&) {
|
||||
emit IPFilterError();
|
||||
}
|
||||
qDebug("IP Filter thread: finished parsing, filter applied");
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,352 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
#ifndef __BITTORRENT_H__
|
||||
#define __BITTORRENT_H__
|
||||
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include <QUrl>
|
||||
#include <QStringList>
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
#include <QNetworkCookie>
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include "qtorrenthandle.h"
|
||||
#include "trackerinfos.h"
|
||||
#include "core/misc.h"
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
#include "rssdownloadrule.h"
|
||||
#endif
|
||||
|
||||
namespace libtorrent {
|
||||
struct add_torrent_params;
|
||||
struct pe_settings;
|
||||
struct proxy_settings;
|
||||
class session;
|
||||
struct session_status;
|
||||
|
||||
class alert;
|
||||
struct torrent_finished_alert;
|
||||
struct save_resume_data_alert;
|
||||
struct file_renamed_alert;
|
||||
struct torrent_deleted_alert;
|
||||
struct storage_moved_alert;
|
||||
struct storage_moved_failed_alert;
|
||||
struct metadata_received_alert;
|
||||
struct file_error_alert;
|
||||
struct file_completed_alert;
|
||||
struct torrent_paused_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 torrent_checked_alert;
|
||||
struct external_ip_alert;
|
||||
struct state_update_alert;
|
||||
struct stats_alert;
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
class upnp;
|
||||
class natpmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
class DownloadThread;
|
||||
class FilterParserThread;
|
||||
class BandwidthScheduler;
|
||||
class ScanFoldersModel;
|
||||
class TorrentSpeedMonitor;
|
||||
class TorrentStatistics;
|
||||
class QAlertDispatcher;
|
||||
|
||||
enum TorrentExportFolder {
|
||||
RegularTorrentExportFolder,
|
||||
FinishedTorrentExportFolder
|
||||
};
|
||||
|
||||
class QTracker;
|
||||
|
||||
class QBtSession : public QObject {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(QBtSession)
|
||||
|
||||
public:
|
||||
static const qreal MAX_RATIO;
|
||||
|
||||
private:
|
||||
explicit QBtSession();
|
||||
static QBtSession* m_instance;
|
||||
|
||||
public:
|
||||
static QBtSession* instance();
|
||||
static void drop();
|
||||
~QBtSession();
|
||||
QTorrentHandle getTorrentHandle(const QString &hash) const;
|
||||
std::vector<libtorrent::torrent_handle> getTorrents() const;
|
||||
qreal getPayloadDownloadRate() const;
|
||||
qreal getPayloadUploadRate() const;
|
||||
libtorrent::session_status getSessionStatus() const;
|
||||
int getListenPort() const;
|
||||
qreal getRealRatio(const libtorrent::torrent_status &status) const;
|
||||
QHash<QString, TrackerInfos> getTrackersInfo(const QString &hash) const;
|
||||
bool hasActiveTorrents() const;
|
||||
bool hasDownloadingTorrents() const;
|
||||
//int getMaximumActiveDownloads() const;
|
||||
//int getMaximumActiveTorrents() const;
|
||||
inline libtorrent::session* getSession() const { return s; }
|
||||
inline bool useTemporaryFolder() const { return !defaultTempPath.isEmpty(); }
|
||||
inline QString getDefaultSavePath() const { return defaultSavePath; }
|
||||
inline ScanFoldersModel* getScanFoldersModel() const { return m_scanFolders; }
|
||||
inline bool isDHTEnabled() const { return DHTEnabled; }
|
||||
inline bool isLSDEnabled() const { return LSDEnabled; }
|
||||
inline bool isPexEnabled() const { return PeXEnabled; }
|
||||
inline bool isQueueingEnabled() const { return queueingEnabled; }
|
||||
quint64 getAlltimeDL() const;
|
||||
quint64 getAlltimeUL() const;
|
||||
void postTorrentUpdate();
|
||||
|
||||
public slots:
|
||||
QTorrentHandle addTorrent(QString path, bool fromScanDir = false, QString from_url = QString(), bool resumed = false, bool imported = false);
|
||||
QTorrentHandle addMagnetUri(QString magnet_uri, bool resumed=false, bool fromScanDir=false, const QString &filePath=QString());
|
||||
void loadSessionState();
|
||||
void saveSessionState();
|
||||
void downloadFromUrl(const QString &url, const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||
void deleteTorrent(const QString &hash, bool delete_local_files = false);
|
||||
void startUpTorrents();
|
||||
void recheckTorrent(const QString &hash);
|
||||
void useAlternativeSpeedsLimit(bool alternative);
|
||||
qlonglong getETA(const QString& hash, const libtorrent::torrent_status &status) const;
|
||||
/* Needed by Web UI */
|
||||
void pauseAllTorrents();
|
||||
void pauseTorrent(const QString &hash);
|
||||
void resumeTorrent(const QString &hash, const bool force = false);
|
||||
void resumeAllTorrents();
|
||||
/* End Web UI */
|
||||
void preAllocateAllFiles(bool b);
|
||||
void saveFastResumeData();
|
||||
void enableIPFilter(const QString &filter_path, bool force=false);
|
||||
void disableIPFilter();
|
||||
void setQueueingEnabled(bool enable);
|
||||
void handleDownloadFailure(QString url, QString reason);
|
||||
void handleMagnetRedirect(const QString &url_new, const QString &url_old);
|
||||
#ifndef DISABLE_GUI
|
||||
void downloadUrlAndSkipDialog(QString url, QString save_path=QString(), QString label=QString(),
|
||||
const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>(),
|
||||
const RssDownloadRule::AddPausedState &aps = RssDownloadRule::USE_GLOBAL);
|
||||
#else
|
||||
void downloadUrlAndSkipDialog(QString url, QString save_path=QString(), QString label=QString(),
|
||||
const QList<QNetworkCookie>& cookies = QList<QNetworkCookie>());
|
||||
#endif
|
||||
// Session configuration - Setters
|
||||
void setListeningPort(int port);
|
||||
void setMaxConnectionsPerTorrent(int max);
|
||||
void setMaxUploadsPerTorrent(int max);
|
||||
void setDownloadRateLimit(long rate);
|
||||
void setUploadRateLimit(long rate);
|
||||
void setGlobalMaxRatio(qreal ratio);
|
||||
qreal getGlobalMaxRatio() const { return global_ratio_limit; }
|
||||
void setMaxRatioPerTorrent(const QString &hash, qreal ratio);
|
||||
qreal getMaxRatioPerTorrent(const QString &hash, bool *usesGlobalRatio) const;
|
||||
void removeRatioPerTorrent(const QString &hash);
|
||||
void setDefaultSavePath(const QString &savepath);
|
||||
void setDefaultTempPath(const QString &temppath);
|
||||
void setAppendLabelToSavePath(bool append);
|
||||
void appendLabelToTorrentSavePath(const QTorrentHandle &h);
|
||||
void changeLabelInTorrentSavePath(const QTorrentHandle &h, QString old_label, QString new_label);
|
||||
void appendqBextensionToTorrent(const QTorrentHandle &h, bool append);
|
||||
void setAppendqBExtension(bool append);
|
||||
void setDownloadLimit(QString hash, long val);
|
||||
void setUploadLimit(QString hash, long val);
|
||||
void enableUPnP(bool b);
|
||||
void enableLSD(bool b);
|
||||
void enableDHT(bool b);
|
||||
void processDownloadedFile(QString, QString);
|
||||
#ifndef DISABLE_GUI
|
||||
void addMagnetSkipAddDlg(const QString& uri, const QString& save_path = QString(), const QString& label = QString(),
|
||||
const RssDownloadRule::AddPausedState &aps = RssDownloadRule::USE_GLOBAL, const QString &uri_old = QString());
|
||||
#else
|
||||
void addMagnetSkipAddDlg(const QString& uri, const QString& save_path = QString(), const QString& label = QString(), const QString &uri_old = QString());
|
||||
#endif
|
||||
void addMagnetInteractive(const QString& uri);
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
void banIP(QString ip);
|
||||
void recursiveTorrentDownload(const QTorrentHandle &h);
|
||||
void unhideMagnet(const QString &hash);
|
||||
void addTrackersAndUrlSeeds(const QString &hash, const QStringList &trackers, const QStringList& urlSeeds);
|
||||
|
||||
private:
|
||||
void applyEncryptionSettings(libtorrent::pe_settings se);
|
||||
void setProxySettings(libtorrent::proxy_settings proxySettings);
|
||||
void setSessionSettings(const libtorrent::session_settings &sessionSettings);
|
||||
QString getSavePath(const QString &hash, bool fromScanDir = false, QString filePath = QString::null, bool imported = false);
|
||||
bool loadFastResumeData(const QString &hash, std::vector<char> &buf);
|
||||
void loadTorrentSettings(QTorrentHandle &h);
|
||||
void loadTorrentTempData(QTorrentHandle &h, QString savePath, bool magnet);
|
||||
void initializeAddTorrentParams(const QString &hash, libtorrent::add_torrent_params &p);
|
||||
void updateRatioTimer();
|
||||
void recoverPersistentData(const QString &hash, const std::vector<char> &buf);
|
||||
void backupPersistentData(const QString &hash, boost::shared_ptr<libtorrent::entry> data);
|
||||
void handleAlert(libtorrent::alert* a);
|
||||
void handleTorrentFinishedAlert(libtorrent::torrent_finished_alert* p);
|
||||
void handleSaveResumeDataAlert(libtorrent::save_resume_data_alert* p);
|
||||
void handleFileRenamedAlert(libtorrent::file_renamed_alert* p);
|
||||
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert* p);
|
||||
void handleStorageMovedAlert(libtorrent::storage_moved_alert* p);
|
||||
void handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert* p);
|
||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert* p);
|
||||
void handleFileErrorAlert(libtorrent::file_error_alert* p);
|
||||
void handleFileCompletedAlert(libtorrent::file_completed_alert* p);
|
||||
void handleTorrentPausedAlert(libtorrent::torrent_paused_alert* p);
|
||||
void handleTrackerErrorAlert(libtorrent::tracker_error_alert* p);
|
||||
void handleTrackerReplyAlert(libtorrent::tracker_reply_alert* p);
|
||||
void handleTrackerWarningAlert(libtorrent::tracker_warning_alert* p);
|
||||
void handlePortmapWarningAlert(libtorrent::portmap_error_alert* p);
|
||||
void handlePortmapAlert(libtorrent::portmap_alert* p);
|
||||
void handlePeerBlockedAlert(libtorrent::peer_blocked_alert* p);
|
||||
void handlePeerBanAlert(libtorrent::peer_ban_alert* p);
|
||||
void handleFastResumeRejectedAlert(libtorrent::fastresume_rejected_alert* p);
|
||||
void handleUrlSeedAlert(libtorrent::url_seed_alert* p);
|
||||
void handleListenSucceededAlert(libtorrent::listen_succeeded_alert *p);
|
||||
void handleListenFailedAlert(libtorrent::listen_failed_alert *p);
|
||||
void handleTorrentCheckedAlert(libtorrent::torrent_checked_alert* p);
|
||||
void handleExternalIPAlert(libtorrent::external_ip_alert *p);
|
||||
void handleStateUpdateAlert(libtorrent::state_update_alert *p);
|
||||
void handleStatsAlert(libtorrent::stats_alert *p);
|
||||
|
||||
private slots:
|
||||
void addTorrentsFromScanFolder(QStringList&);
|
||||
void readAlerts();
|
||||
void processBigRatios();
|
||||
void exportTorrentFiles(QString path);
|
||||
void saveTempFastResumeData();
|
||||
void sendNotificationEmail(const QTorrentHandle &h);
|
||||
void autoRunExternalProgram(const QTorrentHandle &h);
|
||||
void mergeTorrents(const QTorrentHandle &h, const boost::intrusive_ptr<libtorrent::torrent_info> t);
|
||||
void mergeTorrents(const QTorrentHandle &h, const QString &magnet_uri);
|
||||
void mergeTorrents_impl(const QTorrentHandle &h, const QStringList &trackers, const QStringList& urlSeeds);
|
||||
void exportTorrentFile(const QTorrentHandle &h, TorrentExportFolder folder = RegularTorrentExportFolder);
|
||||
void handleIPFilterParsed(int ruleCount);
|
||||
void handleIPFilterError();
|
||||
void configureSession();
|
||||
|
||||
signals:
|
||||
void addedTorrent(const QTorrentHandle& h);
|
||||
void torrentAboutToBeRemoved(const QTorrentHandle &h);
|
||||
void pausedTorrent(const QTorrentHandle& h);
|
||||
void resumedTorrent(const QTorrentHandle& h);
|
||||
void finishedTorrent(const QTorrentHandle& h);
|
||||
void fullDiskError(const QTorrentHandle& h, QString msg);
|
||||
void trackerSuccess(const QString &hash, const QString &tracker);
|
||||
void trackerError(const QString &hash, const QString &tracker);
|
||||
void trackerWarning(const QString &hash, const QString &tracker);
|
||||
void trackerAuthenticationRequired(const QTorrentHandle& h);
|
||||
void newDownloadedTorrent(QString path, QString url);
|
||||
void newDownloadedTorrentFromRss(QString url);
|
||||
void newMagnetLink(const QString& link);
|
||||
void updateFileSize(const QString &hash);
|
||||
void downloadFromUrlFailure(QString url, QString reason);
|
||||
void torrentFinishedChecking(const QTorrentHandle& h);
|
||||
void metadataReceived(const QTorrentHandle &h);
|
||||
void savePathChanged(const QTorrentHandle &h);
|
||||
void alternativeSpeedsModeChanged(bool alternative);
|
||||
void recursiveTorrentDownloadPossible(const QTorrentHandle &h);
|
||||
void ipFilterParsed(bool error, int ruleCount);
|
||||
void metadataReceivedHidden(const QTorrentHandle &h);
|
||||
void stateUpdate(const std::vector<libtorrent::torrent_status> &statuses);
|
||||
void statsReceived(const libtorrent::stats_alert&);
|
||||
void trackersAdded(const QStringList &trackers, const QString &hash);
|
||||
void trackerlessChange(bool trackerless, const QString &hash);
|
||||
void reloadTrackersAndUrlSeeds(const QTorrentHandle &h);
|
||||
|
||||
private:
|
||||
// Bittorrent
|
||||
libtorrent::session *s;
|
||||
QPointer<BandwidthScheduler> bd_scheduler;
|
||||
QMap<QUrl, QPair<QString, QString> > savepathLabel_fromurl; // Use QMap for compatibility with Qt < 4.7: qHash(QUrl)
|
||||
#ifndef DISABLE_GUI
|
||||
QMap<QUrl, RssDownloadRule::AddPausedState> addpaused_fromurl;
|
||||
#endif
|
||||
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
|
||||
QHash<QString, QString> savePathsToRemove;
|
||||
QStringList torrentsToPausedAfterChecking;
|
||||
QTimer resumeDataTimer;
|
||||
// Ratio
|
||||
QPointer<QTimer> BigRatioTimer;
|
||||
// HTTP
|
||||
DownloadThread* downloader;
|
||||
// File System
|
||||
ScanFoldersModel *m_scanFolders;
|
||||
// Settings
|
||||
bool preAllocateAll;
|
||||
qreal global_ratio_limit;
|
||||
int high_ratio_action;
|
||||
bool LSDEnabled;
|
||||
bool DHTEnabled;
|
||||
bool PeXEnabled;
|
||||
bool queueingEnabled;
|
||||
bool appendLabelToSavePath;
|
||||
bool m_torrentExportEnabled;
|
||||
bool m_finishedTorrentExportEnabled;
|
||||
bool appendqBExtension;
|
||||
QString defaultSavePath;
|
||||
QString defaultTempPath;
|
||||
// IP filtering
|
||||
QPointer<FilterParserThread> filterParser;
|
||||
QString filterPath;
|
||||
QList<QUrl> url_skippingDlg;
|
||||
// GeoIP
|
||||
#ifndef DISABLE_GUI
|
||||
bool geoipDBLoaded;
|
||||
bool resolve_countries;
|
||||
#endif
|
||||
// Tracker
|
||||
QPointer<QTracker> m_tracker;
|
||||
TorrentSpeedMonitor *m_speedMonitor;
|
||||
shutDownAction m_shutdownAct;
|
||||
// Port forwarding
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
libtorrent::upnp *m_upnp;
|
||||
libtorrent::natpmp *m_natpmp;
|
||||
#endif
|
||||
QAlertDispatcher* m_alertDispatcher;
|
||||
TorrentStatistics* m_torrentStatistics;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,17 +0,0 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += $$PWD/qbtsession.h \
|
||||
$$PWD/qtorrenthandle.h \
|
||||
$$PWD/bandwidthscheduler.h \
|
||||
$$PWD/trackerinfos.h \
|
||||
$$PWD/torrentspeedmonitor.h \
|
||||
$$PWD/filterparserthread.h \
|
||||
$$PWD/alertdispatcher.h \
|
||||
$$PWD/torrentstatistics.h
|
||||
|
||||
SOURCES += $$PWD/qbtsession.cpp \
|
||||
$$PWD/qtorrenthandle.cpp \
|
||||
$$PWD/torrentspeedmonitor.cpp \
|
||||
$$PWD/alertdispatcher.cpp \
|
||||
$$PWD/torrentstatistics.cpp \
|
||||
$$PWD/filterparserthread.cpp
|
||||
@@ -1,856 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QByteArray>
|
||||
#include <math.h>
|
||||
#include "core/fs_utils.h"
|
||||
#include "core/misc.h"
|
||||
#include "core/preferences.h"
|
||||
#include "qtorrenthandle.h"
|
||||
#include "core/torrentpersistentdata.h"
|
||||
#include "qbtsession.h"
|
||||
#include <libtorrent/version.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/entry.hpp>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
using namespace libtorrent;
|
||||
using namespace std;
|
||||
|
||||
static QPair<int, int> get_file_extremity_pieces(const torrent_info& t, int file_index)
|
||||
{
|
||||
const int num_pieces = t.num_pieces();
|
||||
const int piece_size = t.piece_length();
|
||||
const file_entry& file = t.file_at(file_index);
|
||||
|
||||
// Determine the first and last piece of the file
|
||||
int first_piece = floor((file.offset + 1) / (float) piece_size);
|
||||
Q_ASSERT(first_piece >= 0 && first_piece < num_pieces);
|
||||
|
||||
int num_pieces_in_file = ceil(file.size / (float) piece_size);
|
||||
int last_piece = first_piece + num_pieces_in_file - 1;
|
||||
Q_ASSERT(last_piece >= 0 && last_piece < num_pieces);
|
||||
|
||||
return qMakePair(first_piece, last_piece);
|
||||
}
|
||||
|
||||
QTorrentHandle::QTorrentHandle(const torrent_handle& h): torrent_handle(h)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
|
||||
QString QTorrentHandle::hash() const
|
||||
{
|
||||
return misc::toQString(torrent_handle::info_hash());
|
||||
}
|
||||
|
||||
QString QTorrentHandle::name() const
|
||||
{
|
||||
QString name = TorrentPersistentData::instance()->getName(hash());
|
||||
if (name.isEmpty()) {
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
name = misc::toQStringU(torrent_handle::name());
|
||||
#else
|
||||
name = misc::toQStringU(status(query_name).name);
|
||||
#endif
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::creation_date() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
boost::optional<time_t> t = torrent_handle::get_torrent_info().creation_date();
|
||||
#else
|
||||
boost::optional<time_t> t = torrent_handle::torrent_file()->creation_date();
|
||||
#endif
|
||||
return t ? misc::toQString(*t) : "";
|
||||
}
|
||||
|
||||
qlonglong QTorrentHandle::creation_date_unix() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
boost::optional<time_t> t = torrent_handle::get_torrent_info().creation_date();
|
||||
#else
|
||||
boost::optional<time_t> t = torrent_handle::torrent_file()->creation_date();
|
||||
#endif
|
||||
return t ? *t : -1;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::current_tracker() const
|
||||
{
|
||||
return misc::toQString(status(0x0).current_tracker);
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_paused() const
|
||||
{
|
||||
return is_paused(status(0x0));
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_queued() const
|
||||
{
|
||||
return is_queued(status(0x0));
|
||||
}
|
||||
|
||||
size_type QTorrentHandle::total_size() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().total_size();
|
||||
#else
|
||||
return torrent_handle::torrent_file()->total_size();
|
||||
#endif
|
||||
}
|
||||
|
||||
size_type QTorrentHandle::piece_length() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().piece_length();
|
||||
#else
|
||||
return torrent_handle::torrent_file()->piece_length();
|
||||
#endif
|
||||
}
|
||||
|
||||
int QTorrentHandle::num_pieces() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().num_pieces();
|
||||
#else
|
||||
return torrent_handle::torrent_file()->num_pieces();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QTorrentHandle::first_last_piece_first() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
torrent_info const* t = &get_torrent_info();
|
||||
#else
|
||||
boost::intrusive_ptr<torrent_info const> t = torrent_file();
|
||||
#endif
|
||||
|
||||
// Get int first media file
|
||||
int index = 0;
|
||||
for (index = 0; index < t->num_files(); ++index) {
|
||||
QString path = misc::toQStringU(t->file_at(index).path);
|
||||
const QString ext = fsutils::fileExtension(path);
|
||||
if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (index >= t->num_files()) // No media file
|
||||
return false;
|
||||
|
||||
QPair<int, int> extremities = get_file_extremity_pieces(*t, index);
|
||||
|
||||
return (torrent_handle::piece_priority(extremities.first) == 7)
|
||||
&& (torrent_handle::piece_priority(extremities.second) == 7);
|
||||
}
|
||||
|
||||
QString QTorrentHandle::save_path() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return fsutils::fromNativePath(misc::toQStringU(torrent_handle::save_path()));
|
||||
#else
|
||||
return fsutils::fromNativePath(misc::toQStringU(status(torrent_handle::query_save_path).save_path));
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::save_path_parsed() const
|
||||
{
|
||||
QString p;
|
||||
if (has_metadata() && num_files() == 1) {
|
||||
p = firstFileSavePath();
|
||||
}
|
||||
else {
|
||||
p = fsutils::fromNativePath(TorrentPersistentData::instance()->getSavePath(hash()));
|
||||
if (p.isEmpty())
|
||||
p = save_path();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
QStringList QTorrentHandle::url_seeds() const
|
||||
{
|
||||
QStringList res;
|
||||
try {
|
||||
const std::set<std::string> existing_seeds = torrent_handle::url_seeds();
|
||||
|
||||
std::set<std::string>::const_iterator it = existing_seeds.begin();
|
||||
std::set<std::string>::const_iterator itend = existing_seeds.end();
|
||||
for (; it != itend; ++it) {
|
||||
qDebug("URL Seed: %s", it->c_str());
|
||||
res << misc::toQString(*it);
|
||||
}
|
||||
} catch(std::exception &e) {
|
||||
std::cout << "ERROR: Failed to convert the URL seed" << std::endl;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// get the size of the torrent without the filtered files
|
||||
size_type QTorrentHandle::actual_size() const
|
||||
{
|
||||
return status(query_accurate_download_counters).total_wanted;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_filtered_pieces() const
|
||||
{
|
||||
const std::vector<int> piece_priorities = torrent_handle::piece_priorities();
|
||||
foreach (const int priority, piece_priorities)
|
||||
if (priority == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int QTorrentHandle::num_files() const
|
||||
{
|
||||
if (!has_metadata())
|
||||
return -1;
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().num_files();
|
||||
#else
|
||||
return torrent_handle::torrent_file()->num_files();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::filename_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files());
|
||||
#else
|
||||
Q_ASSERT(index < (unsigned int)torrent_handle::torrent_file()->num_files());
|
||||
#endif
|
||||
return fsutils::fileName(filepath_at(index));
|
||||
}
|
||||
|
||||
size_type QTorrentHandle::filesize_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
Q_ASSERT(index < (unsigned int)torrent_handle::get_torrent_info().num_files());
|
||||
return torrent_handle::get_torrent_info().files().file_size(index);
|
||||
#else
|
||||
Q_ASSERT(index < (unsigned int)torrent_handle::torrent_file()->num_files());
|
||||
return torrent_handle::torrent_file()->files().file_size(index);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::filepath_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return filepath_at(torrent_handle::get_torrent_info(), index);
|
||||
#else
|
||||
return filepath_at(*torrent_handle::torrent_file(), index);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::orig_filepath_at(unsigned int index) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return fsutils::fromNativePath(misc::toQStringU(torrent_handle::get_torrent_info().orig_files().file_path(index)));
|
||||
#else
|
||||
return fsutils::fromNativePath(misc::toQStringU(torrent_handle::torrent_file()->orig_files().file_path(index)));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
torrent_status::state_t QTorrentHandle::state() const
|
||||
{
|
||||
return status(0x0).state;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::creator() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return misc::toQStringU(torrent_handle::get_torrent_info().creator());
|
||||
#else
|
||||
return misc::toQStringU(torrent_handle::torrent_file()->creator());
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::comment() const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return misc::toQStringU(torrent_handle::get_torrent_info().comment());
|
||||
#else
|
||||
return misc::toQStringU(torrent_handle::torrent_file()->comment());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_checking() const
|
||||
{
|
||||
return is_checking(status(0x0));
|
||||
}
|
||||
|
||||
// Return a list of absolute paths corresponding
|
||||
// to all files in a torrent
|
||||
QStringList QTorrentHandle::absolute_files_path() const
|
||||
{
|
||||
QDir saveDir(save_path());
|
||||
QStringList res;
|
||||
for (int i = 0; i<num_files(); ++i)
|
||||
res << fsutils::expandPathAbs(saveDir.absoluteFilePath(filepath_at(i)));
|
||||
return res;
|
||||
}
|
||||
|
||||
QStringList QTorrentHandle::absolute_files_path_uneeded() const
|
||||
{
|
||||
QDir saveDir(save_path());
|
||||
QStringList res;
|
||||
std::vector<int> fp = torrent_handle::file_priorities();
|
||||
for (uint i = 0; i < fp.size(); ++i) {
|
||||
if (fp[i] == 0) {
|
||||
const QString file_path = fsutils::expandPathAbs(saveDir.absoluteFilePath(filepath_at(i)));
|
||||
if (file_path.contains(".unwanted"))
|
||||
res << file_path;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_missing_files() const
|
||||
{
|
||||
const QStringList paths = absolute_files_path();
|
||||
foreach (const QString &path, paths)
|
||||
if (!QFile::exists(path)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int QTorrentHandle::queue_position() const
|
||||
{
|
||||
return queue_position(status(0x0));
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_seed() const
|
||||
{
|
||||
// Affected by bug http://code.rasterbar.com/libtorrent/ticket/402
|
||||
//return torrent_handle::is_seed();
|
||||
// May suffer from approximation problems
|
||||
//return (progress() == 1.);
|
||||
// This looks safe
|
||||
return is_seed(status(0x0));
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_sequential_download() const
|
||||
{
|
||||
return status(0x0).sequential_download;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::priv() const
|
||||
{
|
||||
if (!has_metadata())
|
||||
return false;
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
return torrent_handle::get_torrent_info().priv();
|
||||
#else
|
||||
return torrent_handle::torrent_file()->priv();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QTorrentHandle::firstFileSavePath() const
|
||||
{
|
||||
Q_ASSERT(has_metadata());
|
||||
QString fsave_path = fsutils::fromNativePath(TorrentPersistentData::instance()->getSavePath(hash()));
|
||||
if (fsave_path.isEmpty())
|
||||
fsave_path = save_path();
|
||||
if (!fsave_path.endsWith("/"))
|
||||
fsave_path += "/";
|
||||
fsave_path += filepath_at(0);
|
||||
// Remove .!qB extension
|
||||
if (fsave_path.endsWith(".!qB", Qt::CaseInsensitive))
|
||||
fsave_path.chop(4);
|
||||
return fsave_path;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::root_path() const
|
||||
{
|
||||
if (num_files() < 2)
|
||||
return save_path();
|
||||
QString first_filepath = filepath_at(0);
|
||||
const int slashIndex = first_filepath.indexOf("/");
|
||||
if (slashIndex >= 0)
|
||||
return QDir(save_path()).absoluteFilePath(first_filepath.left(slashIndex));
|
||||
return save_path();
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_error() const
|
||||
{
|
||||
return has_error(status(0x0));
|
||||
}
|
||||
|
||||
QString QTorrentHandle::error() const
|
||||
{
|
||||
return misc::toQString(status(0x0).error);
|
||||
}
|
||||
|
||||
void QTorrentHandle::downloading_pieces(bitfield &bf) const
|
||||
{
|
||||
std::vector<partial_piece_info> queue;
|
||||
torrent_handle::get_download_queue(queue);
|
||||
|
||||
std::vector<partial_piece_info>::const_iterator it = queue.begin();
|
||||
std::vector<partial_piece_info>::const_iterator itend = queue.end();
|
||||
for (; it!= itend; ++it)
|
||||
bf.set_bit(it->piece_index);
|
||||
return;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_metadata() const
|
||||
{
|
||||
return status(0x0).has_metadata;
|
||||
}
|
||||
|
||||
void QTorrentHandle::file_progress(std::vector<size_type>& fp) const
|
||||
{
|
||||
torrent_handle::file_progress(fp, torrent_handle::piece_granularity);
|
||||
}
|
||||
|
||||
QTorrentState QTorrentHandle::torrentState() const
|
||||
{
|
||||
QTorrentState state = QTorrentState::Unknown;
|
||||
libtorrent::torrent_status s = status(torrent_handle::query_accurate_download_counters);
|
||||
|
||||
if (is_paused(s)) {
|
||||
if (has_error(s))
|
||||
state = QTorrentState::Error;
|
||||
else
|
||||
state = is_seed(s) ? QTorrentState::PausedUploading : QTorrentState::PausedDownloading;
|
||||
}
|
||||
else {
|
||||
if (QBtSession::instance()->isQueueingEnabled() && is_queued(s)) {
|
||||
state = is_seed(s) ? QTorrentState::QueuedUploading : QTorrentState::QueuedDownloading;
|
||||
}
|
||||
else {
|
||||
switch (s.state) {
|
||||
case torrent_status::finished:
|
||||
case torrent_status::seeding:
|
||||
state = s.upload_payload_rate > 0 ? QTorrentState::Uploading : QTorrentState::StalledUploading;
|
||||
break;
|
||||
case torrent_status::allocating:
|
||||
case torrent_status::checking_files:
|
||||
case torrent_status::queued_for_checking:
|
||||
case torrent_status::checking_resume_data:
|
||||
state = is_seed(s) ? QTorrentState::CheckingUploading : QTorrentState::CheckingDownloading;
|
||||
break;
|
||||
case torrent_status::downloading:
|
||||
case torrent_status::downloading_metadata:
|
||||
state = s.download_payload_rate > 0 ? QTorrentState::Downloading : QTorrentState::StalledDownloading;
|
||||
break;
|
||||
default:
|
||||
qWarning("Unrecognized torrent status, should not happen!!! status was %d", this->state());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
qulonglong QTorrentHandle::eta() const
|
||||
{
|
||||
libtorrent::torrent_status s = status(torrent_handle::query_accurate_download_counters);
|
||||
return QBtSession::instance()->getETA(hash(), s);
|
||||
}
|
||||
|
||||
void QTorrentHandle::toggleSequentialDownload()
|
||||
{
|
||||
if (is_valid() && has_metadata()) {
|
||||
bool was_sequential = is_sequential_download();
|
||||
set_sequential_download(!was_sequential);
|
||||
if (!was_sequential)
|
||||
prioritize_first_last_piece(true);
|
||||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::toggleFirstLastPiecePrio()
|
||||
{
|
||||
if (is_valid() && has_metadata())
|
||||
prioritize_first_last_piece(!first_last_piece_first());
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_forced() const
|
||||
{
|
||||
return is_forced(status(0x0));
|
||||
}
|
||||
|
||||
//
|
||||
// Setters
|
||||
//
|
||||
|
||||
void QTorrentHandle::pause() const
|
||||
{
|
||||
torrent_handle::auto_managed(false);
|
||||
torrent_handle::pause();
|
||||
if (!TorrentPersistentData::instance()->getHasMissingFiles(this->hash()))
|
||||
torrent_handle::save_resume_data();
|
||||
}
|
||||
|
||||
void QTorrentHandle::resume(const bool force) const
|
||||
{
|
||||
if (has_error())
|
||||
torrent_handle::clear_error();
|
||||
torrent_handle::set_upload_mode(false);
|
||||
|
||||
const QString torrent_hash = hash();
|
||||
TorrentPersistentData* const TorPersistent = TorrentPersistentData::instance();
|
||||
bool has_persistant_error = TorPersistent->hasError(torrent_hash);
|
||||
TorPersistent->setErrorState(torrent_hash, false);
|
||||
bool temp_path_enabled = Preferences::instance()->isTempPathEnabled();
|
||||
if (has_persistant_error && temp_path_enabled) {
|
||||
// Torrent was supposed to be seeding, checking again in final destination
|
||||
qDebug("Resuming a torrent with error...");
|
||||
const QString final_save_path = TorPersistent->getSavePath(torrent_hash);
|
||||
qDebug("Torrent final path is: %s", qPrintable(final_save_path));
|
||||
if (!final_save_path.isEmpty())
|
||||
move_storage(final_save_path);
|
||||
}
|
||||
torrent_handle::auto_managed(!force);
|
||||
torrent_handle::resume();
|
||||
if (has_persistant_error && temp_path_enabled)
|
||||
// Force recheck
|
||||
torrent_handle::force_recheck();
|
||||
}
|
||||
|
||||
void QTorrentHandle::remove_url_seed(const QString& seed) const
|
||||
{
|
||||
torrent_handle::remove_url_seed(seed.toStdString());
|
||||
}
|
||||
|
||||
void QTorrentHandle::add_url_seed(const QString& seed) const
|
||||
{
|
||||
const std::string str_seed = seed.toStdString();
|
||||
qDebug("calling torrent_handle::add_url_seed(%s)", str_seed.c_str());
|
||||
torrent_handle::add_url_seed(str_seed);
|
||||
}
|
||||
|
||||
void QTorrentHandle::set_tracker_login(const QString& username, const QString& password) const
|
||||
{
|
||||
torrent_handle::set_tracker_login(std::string(username.toLocal8Bit().constData()), std::string(password.toLocal8Bit().constData()));
|
||||
}
|
||||
|
||||
void QTorrentHandle::move_storage(const QString& new_path) const
|
||||
{
|
||||
QString hashstr = hash();
|
||||
|
||||
if (TorrentTempData::isMoveInProgress(hashstr)) {
|
||||
qDebug("enqueue move storage to %s", qPrintable(new_path));
|
||||
TorrentTempData::enqueueMove(hashstr, new_path);
|
||||
}
|
||||
else {
|
||||
QString old_path = save_path();
|
||||
|
||||
qDebug("move storage: %s to %s", qPrintable(old_path), qPrintable(new_path));
|
||||
|
||||
if (QDir(old_path) == QDir(new_path))
|
||||
return;
|
||||
|
||||
TorrentTempData::startMove(hashstr, old_path, new_path);
|
||||
|
||||
// Create destination directory if necessary
|
||||
// or move_storage() will fail...
|
||||
QDir().mkpath(new_path);
|
||||
// Actually move the storage
|
||||
torrent_handle::move_storage(fsutils::toNativePath(new_path).toUtf8().constData());
|
||||
}
|
||||
}
|
||||
|
||||
bool QTorrentHandle::save_torrent_file(const QString& path) const
|
||||
{
|
||||
if (!has_metadata()) return false;
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
torrent_info const* t = &get_torrent_info();
|
||||
#else
|
||||
boost::intrusive_ptr<torrent_info const> t = torrent_file();
|
||||
#endif
|
||||
|
||||
entry meta = bdecode(t->metadata().get(),
|
||||
t->metadata().get() + t->metadata_size());
|
||||
entry torrent_entry(entry::dictionary_t);
|
||||
torrent_entry["info"] = meta;
|
||||
if (!torrent_handle::trackers().empty())
|
||||
torrent_entry["announce"] = torrent_handle::trackers().front().url;
|
||||
|
||||
vector<char> out;
|
||||
bencode(back_inserter(out), torrent_entry);
|
||||
QFile torrent_file(path);
|
||||
if (!out.empty() && torrent_file.open(QIODevice::WriteOnly)) {
|
||||
torrent_file.write(&out[0], out.size());
|
||||
torrent_file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QTorrentHandle::file_priority(int index, int priority) const
|
||||
{
|
||||
vector<int> priorities = torrent_handle::file_priorities();
|
||||
if (priorities[index] != priority) {
|
||||
priorities[index] = priority;
|
||||
prioritize_files(priorities);
|
||||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::prioritize_files(const vector<int> &files) const
|
||||
{
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
torrent_info const& info = torrent_handle::get_torrent_info();
|
||||
#else
|
||||
boost::intrusive_ptr<torrent_info const> info_ptr = torrent_handle::torrent_file();
|
||||
torrent_info const& info = *info_ptr;
|
||||
#endif
|
||||
if ((int)files.size() != info.num_files()) return;
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
bool was_seed = is_seed();
|
||||
qDebug() << Q_FUNC_INFO << "Changing files priorities...";
|
||||
torrent_handle::prioritize_files(files);
|
||||
qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely...";
|
||||
|
||||
QString spath = save_path();
|
||||
|
||||
for (uint i = 0; i < files.size(); ++i) {
|
||||
QString filepath = filepath_at(info, i);
|
||||
// Move unwanted files to a .unwanted subfolder
|
||||
if (files[i] == 0) {
|
||||
QString old_abspath = QDir(spath).absoluteFilePath(filepath);
|
||||
QString parent_abspath = fsutils::branchPath(old_abspath);
|
||||
// Make sure the file does not already exists
|
||||
if (QDir(parent_abspath).dirName() != ".unwanted") {
|
||||
QString unwanted_abspath = parent_abspath + "/.unwanted";
|
||||
QString new_abspath = unwanted_abspath + "/" + fsutils::fileName(filepath);
|
||||
qDebug() << "Unwanted path is" << unwanted_abspath;
|
||||
if (QFile::exists(new_abspath)) {
|
||||
qWarning() << "File" << new_abspath << "already exists at destination.";
|
||||
continue;
|
||||
}
|
||||
bool created = QDir().mkpath(unwanted_abspath);
|
||||
#ifdef Q_OS_WIN
|
||||
qDebug() << "unwanted folder was created:" << created;
|
||||
if (created) {
|
||||
// Hide the folder on Windows
|
||||
qDebug() << "Hiding folder (Windows)";
|
||||
wstring win_path = fsutils::toNativePath(unwanted_abspath).toStdWString();
|
||||
DWORD dwAttrs = GetFileAttributesW(win_path.c_str());
|
||||
bool ret = SetFileAttributesW(win_path.c_str(), dwAttrs | FILE_ATTRIBUTE_HIDDEN);
|
||||
Q_ASSERT(ret != 0); Q_UNUSED(ret);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(created);
|
||||
#endif
|
||||
QString parent_path = fsutils::branchPath(filepath);
|
||||
if (!parent_path.isEmpty() && !parent_path.endsWith("/"))
|
||||
parent_path += "/";
|
||||
rename_file(i, parent_path + ".unwanted/" + fsutils::fileName(filepath));
|
||||
}
|
||||
}
|
||||
// Move wanted files back to their original folder
|
||||
if (files[i] > 0) {
|
||||
QString parent_relpath = fsutils::branchPath(filepath);
|
||||
if (QDir(parent_relpath).dirName() == ".unwanted") {
|
||||
QString old_name = fsutils::fileName(filepath);
|
||||
QString new_relpath = fsutils::branchPath(parent_relpath);
|
||||
if (new_relpath.isEmpty())
|
||||
rename_file(i, old_name);
|
||||
else
|
||||
rename_file(i, QDir(new_relpath).filePath(old_name));
|
||||
// Remove .unwanted directory if empty
|
||||
qDebug() << "Attempting to remove .unwanted folder at " << QDir(spath + "/" + new_relpath).absoluteFilePath(".unwanted");
|
||||
QDir(spath + "/" + new_relpath).rmdir(".unwanted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (was_seed && !is_seed()) {
|
||||
qDebug() << "Torrent is no longer SEEDING";
|
||||
// Save seed status
|
||||
TorrentPersistentData::instance()->saveSeedStatus(*this);
|
||||
// Move to temp folder if necessary
|
||||
const Preferences* const pref = Preferences::instance();
|
||||
if (pref->isTempPathEnabled()) {
|
||||
QString tmp_path = pref->getTempPath();
|
||||
qDebug() << "tmp folder is enabled, move torrent to " << tmp_path << " from " << spath;
|
||||
move_storage(tmp_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const
|
||||
{
|
||||
// Determine the priority to set
|
||||
int prio = b ? 7 : torrent_handle::file_priority(file_index);
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10000
|
||||
torrent_info const* tf = &get_torrent_info();
|
||||
#else
|
||||
boost::intrusive_ptr<torrent_info const> tf = torrent_file();
|
||||
#endif
|
||||
|
||||
QPair<int, int> extremities = get_file_extremity_pieces(*tf, file_index);
|
||||
piece_priority(extremities.first, prio);
|
||||
piece_priority(extremities.second, prio);
|
||||
}
|
||||
|
||||
void QTorrentHandle::prioritize_first_last_piece(bool b) const
|
||||
{
|
||||
if (!has_metadata()) return;
|
||||
// Download first and last pieces first for all media files in the torrent
|
||||
const uint nbfiles = num_files();
|
||||
for (uint index = 0; index < nbfiles; ++index) {
|
||||
const QString path = filepath_at(index);
|
||||
const QString ext = fsutils::fileExtension(path);
|
||||
if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) {
|
||||
qDebug() << "File" << path << "is previewable, toggle downloading of first/last pieces first";
|
||||
prioritize_first_last_piece(index, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QTorrentHandle::rename_file(int index, const QString& name) const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << index << name;
|
||||
torrent_handle::rename_file(index, std::string(fsutils::toNativePath(name).toUtf8().constData()));
|
||||
}
|
||||
|
||||
//
|
||||
// Operators
|
||||
//
|
||||
|
||||
bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const
|
||||
{
|
||||
return info_hash() == new_h.info_hash();
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_paused(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.paused && !status.auto_managed;
|
||||
}
|
||||
|
||||
int QTorrentHandle::queue_position(const libtorrent::torrent_status &status)
|
||||
{
|
||||
if (status.queue_position < 0)
|
||||
return -1;
|
||||
return status.queue_position + 1;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_queued(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.paused && status.auto_managed;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_seed(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.state == torrent_status::finished
|
||||
|| status.state == torrent_status::seeding;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_checking(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.state == torrent_status::checking_files
|
||||
|| status.state == torrent_status::checking_resume_data;
|
||||
}
|
||||
|
||||
bool QTorrentHandle::has_error(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return status.paused && !status.error.empty();
|
||||
}
|
||||
|
||||
float QTorrentHandle::progress(const libtorrent::torrent_status &status)
|
||||
{
|
||||
if (!status.total_wanted)
|
||||
return 0.;
|
||||
if (status.total_wanted_done == status.total_wanted)
|
||||
return 1.;
|
||||
float progress = (float) status.total_wanted_done / (float) status.total_wanted;
|
||||
Q_ASSERT(progress >= 0.f && progress <= 1.f);
|
||||
return progress;
|
||||
}
|
||||
|
||||
QString QTorrentHandle::filepath_at(const libtorrent::torrent_info &info, unsigned int index)
|
||||
{
|
||||
return fsutils::fromNativePath(misc::toQStringU(info.files().file_path(index)));
|
||||
|
||||
}
|
||||
|
||||
bool QTorrentHandle::is_forced(const libtorrent::torrent_status &status)
|
||||
{
|
||||
return !status.paused && !status.auto_managed;
|
||||
}
|
||||
|
||||
|
||||
QTorrentState::QTorrentState(int value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
QString QTorrentState::toString() const
|
||||
{
|
||||
switch (m_value) {
|
||||
case Error:
|
||||
return "error";
|
||||
case Uploading:
|
||||
return "uploading";
|
||||
case PausedUploading:
|
||||
return "pausedUP";
|
||||
case QueuedUploading:
|
||||
return "queuedUP";
|
||||
case StalledUploading:
|
||||
return "stalledUP";
|
||||
case CheckingUploading:
|
||||
return "checkingUP";
|
||||
case Downloading:
|
||||
return "downloading";
|
||||
case PausedDownloading:
|
||||
return "pausedDL";
|
||||
case QueuedDownloading:
|
||||
return "queuedDL";
|
||||
case StalledDownloading:
|
||||
return "stalledDL";
|
||||
case CheckingDownloading:
|
||||
return "checkingDL";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
QTorrentState::operator int() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef QTORRENTHANDLE_H
|
||||
#define QTORRENTHANDLE_H
|
||||
|
||||
#include <libtorrent/torrent_handle.hpp>
|
||||
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStringList;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class QTorrentState
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
Unknown = -1,
|
||||
|
||||
Error,
|
||||
|
||||
Uploading,
|
||||
PausedUploading,
|
||||
QueuedUploading,
|
||||
StalledUploading,
|
||||
CheckingUploading,
|
||||
|
||||
Downloading,
|
||||
PausedDownloading,
|
||||
QueuedDownloading,
|
||||
StalledDownloading,
|
||||
CheckingDownloading
|
||||
};
|
||||
|
||||
QTorrentState(int value);
|
||||
|
||||
operator int() const;
|
||||
QString toString() const;
|
||||
|
||||
private:
|
||||
int m_value;
|
||||
};
|
||||
|
||||
// A wrapper for torrent_handle in libtorrent
|
||||
// to interact well with Qt types
|
||||
class QTorrentHandle: public libtorrent::torrent_handle
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
|
||||
QTorrentHandle() {}
|
||||
explicit QTorrentHandle(const libtorrent::torrent_handle& h);
|
||||
|
||||
//
|
||||
// Getters
|
||||
//
|
||||
QString hash() const;
|
||||
QString name() const;
|
||||
QString current_tracker() const;
|
||||
bool is_paused() const;
|
||||
bool has_filtered_pieces() const;
|
||||
libtorrent::size_type total_size() const;
|
||||
libtorrent::size_type piece_length() const;
|
||||
int num_pieces() const;
|
||||
QString save_path() const;
|
||||
QString save_path_parsed() const;
|
||||
QStringList url_seeds() const;
|
||||
libtorrent::size_type actual_size() const;
|
||||
int num_files() const;
|
||||
int queue_position() const;
|
||||
bool is_queued() const;
|
||||
QString filename_at(unsigned int index) const;
|
||||
libtorrent::size_type filesize_at(unsigned int index) const;
|
||||
QString filepath_at(unsigned int index) const;
|
||||
QString orig_filepath_at(unsigned int index) const;
|
||||
libtorrent::torrent_status::state_t state() const;
|
||||
QString creator() const;
|
||||
QString comment() const;
|
||||
QStringList absolute_files_path() const;
|
||||
QStringList absolute_files_path_uneeded() const;
|
||||
bool has_missing_files() const;
|
||||
bool is_seed() const;
|
||||
bool is_checking() const;
|
||||
bool is_sequential_download() const;
|
||||
QString creation_date() const;
|
||||
qlonglong creation_date_unix() const;
|
||||
bool priv() const;
|
||||
bool first_last_piece_first() const;
|
||||
QString root_path() const;
|
||||
QString firstFileSavePath() const;
|
||||
bool has_error() const;
|
||||
QString error() const;
|
||||
void downloading_pieces(libtorrent::bitfield& bf) const;
|
||||
bool has_metadata() const;
|
||||
void file_progress(std::vector<libtorrent::size_type>& fp) const;
|
||||
QTorrentState torrentState() const;
|
||||
qulonglong eta() const;
|
||||
void toggleSequentialDownload();
|
||||
void toggleFirstLastPiecePrio();
|
||||
bool is_forced() const;
|
||||
|
||||
//
|
||||
// Setters
|
||||
//
|
||||
void pause() const;
|
||||
void resume(const bool force = false) const;
|
||||
void remove_url_seed(const QString& seed) const;
|
||||
void add_url_seed(const QString& seed) const;
|
||||
void set_tracker_login(const QString& username, const QString& password) const;
|
||||
void move_storage(const QString& path) const;
|
||||
void prioritize_first_last_piece(bool b) const;
|
||||
void rename_file(int index, const QString& name) const;
|
||||
bool save_torrent_file(const QString& path) const;
|
||||
void prioritize_files(const std::vector<int>& files) const;
|
||||
void file_priority(int index, int priority) const;
|
||||
|
||||
//
|
||||
// Operators
|
||||
//
|
||||
bool operator ==(const QTorrentHandle& new_h) const;
|
||||
|
||||
static bool is_paused(const libtorrent::torrent_status &status);
|
||||
static int queue_position(const libtorrent::torrent_status &status);
|
||||
static bool is_queued(const libtorrent::torrent_status &status);
|
||||
static bool is_seed(const libtorrent::torrent_status &status);
|
||||
static bool is_checking(const libtorrent::torrent_status &status);
|
||||
static bool has_error(const libtorrent::torrent_status &status);
|
||||
static float progress(const libtorrent::torrent_status &status);
|
||||
static QString filepath_at(const libtorrent::torrent_info &info, unsigned int index);
|
||||
static bool is_forced(const libtorrent::torrent_status &status);
|
||||
|
||||
private:
|
||||
void prioritize_first_last_piece(int file_index, bool b) const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef QTRACKER_H
|
||||
#define QTRACKER_H
|
||||
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <QHash>
|
||||
#include "http/types.h"
|
||||
#include "http/responsebuilder.h"
|
||||
#include "http/irequesthandler.h"
|
||||
|
||||
struct QPeer
|
||||
{
|
||||
QString ip;
|
||||
QString peer_id;
|
||||
int port;
|
||||
|
||||
bool operator!=(const QPeer &other) const;
|
||||
bool operator==(const QPeer &other) const;
|
||||
QString qhash() const;
|
||||
libtorrent::entry toEntry(bool no_peer_id) const;
|
||||
};
|
||||
|
||||
struct TrackerAnnounceRequest
|
||||
{
|
||||
QString info_hash;
|
||||
QString event;
|
||||
int numwant;
|
||||
QPeer peer;
|
||||
// Extensions
|
||||
bool no_peer_id;
|
||||
};
|
||||
|
||||
// static limits
|
||||
const int MAX_TORRENTS = 100;
|
||||
const int MAX_PEERS_PER_TORRENT = 1000;
|
||||
const int ANNOUNCE_INTERVAL = 1800; // 30min
|
||||
|
||||
typedef QHash<QString, QPeer> PeerList;
|
||||
typedef QHash<QString, PeerList> TorrentList;
|
||||
|
||||
namespace Http { class Server; }
|
||||
|
||||
/* Basic Bittorrent tracker implementation in Qt */
|
||||
/* Following http://wiki.theory.org/BitTorrent_Tracker_Protocol */
|
||||
class QTracker : public Http::ResponseBuilder, public Http::IRequestHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(QTracker)
|
||||
|
||||
public:
|
||||
explicit QTracker(QObject *parent = 0);
|
||||
~QTracker();
|
||||
|
||||
bool start();
|
||||
Http::Response processRequest(const Http::Request &request, const Http::Environment &env);
|
||||
|
||||
private:
|
||||
void respondToAnnounceRequest();
|
||||
void replyWithPeerList(const TrackerAnnounceRequest &annonce_req);
|
||||
|
||||
Http::Server *m_server;
|
||||
TorrentList m_torrents;
|
||||
|
||||
Http::Request m_request;
|
||||
Http::Environment m_env;
|
||||
};
|
||||
|
||||
#endif // QTRACKER_H
|
||||
@@ -38,7 +38,8 @@
|
||||
#include "fs_utils.h"
|
||||
#include "preferences.h"
|
||||
#include "filesystemwatcher.h"
|
||||
#include "scannedfoldersmodel.h"
|
||||
#include "bittorrent/session.h"
|
||||
#include "scanfoldersmodel.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -67,11 +68,26 @@ public:
|
||||
|
||||
ScanFoldersModel *ScanFoldersModel::m_instance = 0;
|
||||
|
||||
ScanFoldersModel *ScanFoldersModel::instance(QObject *parent)
|
||||
bool ScanFoldersModel::initInstance(QObject *parent)
|
||||
{
|
||||
//Q_ASSERT(!parent != !m_instance);
|
||||
if (!m_instance)
|
||||
if (!m_instance) {
|
||||
m_instance = new ScanFoldersModel(parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScanFoldersModel::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ScanFoldersModel *ScanFoldersModel::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
@@ -79,6 +95,8 @@ ScanFoldersModel::ScanFoldersModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_fsWatcher(0)
|
||||
{
|
||||
configure();
|
||||
connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure()));
|
||||
}
|
||||
|
||||
ScanFoldersModel::~ScanFoldersModel()
|
||||
@@ -153,7 +171,7 @@ ScanFoldersModel::PathStatus ScanFoldersModel::addPath(const QString &path, bool
|
||||
|
||||
if (!m_fsWatcher) {
|
||||
m_fsWatcher = new FileSystemWatcher(this);
|
||||
connect(m_fsWatcher, SIGNAL(torrentsAdded(QStringList&)), this, SIGNAL(torrentsAdded(QStringList&)));
|
||||
connect(m_fsWatcher, SIGNAL(torrentsAdded(const QStringList &)), this, SLOT(addTorrentsToSession(const QStringList &)));
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||
@@ -231,3 +249,47 @@ void ScanFoldersModel::makePersistent()
|
||||
pref->setScanDirs(paths);
|
||||
pref->setDownloadInScanDirs(downloadInFolderInfo);
|
||||
}
|
||||
|
||||
void ScanFoldersModel::configure()
|
||||
{
|
||||
Preferences *const pref = Preferences::instance();
|
||||
|
||||
int i = 0;
|
||||
QList<bool> downloadInDirList = pref->getDownloadInScanDirs();
|
||||
foreach (const QString &dir, pref->getScanDirs()) {
|
||||
bool downloadInDir = downloadInDirList.value(i, false);
|
||||
addPath(dir, downloadInDir);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void ScanFoldersModel::addTorrentsToSession(const QStringList &pathList)
|
||||
{
|
||||
foreach (const QString &file, pathList) {
|
||||
qDebug("File %s added", qPrintable(file));
|
||||
if (file.endsWith(".magnet")) {
|
||||
QFile f(file);
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
BitTorrent::Session::instance()->addTorrent(QString::fromLocal8Bit(f.readAll()));
|
||||
f.remove();
|
||||
}
|
||||
else {
|
||||
qDebug("Failed to open magnet file: %s", qPrintable(f.errorString()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
BitTorrent::AddTorrentParams params;
|
||||
if (downloadInTorrentFolder(file))
|
||||
params.savePath = QFileInfo(file).dir().path();
|
||||
|
||||
BitTorrent::TorrentInfo torrentInfo = BitTorrent::TorrentInfo::loadFromFile(file);
|
||||
if (torrentInfo.isValid()) {
|
||||
BitTorrent::Session::instance()->addTorrent(torrentInfo, params);
|
||||
fsutils::forceRemove(file);
|
||||
}
|
||||
else {
|
||||
qDebug("Ignoring incomplete torrent file: %s", qPrintable(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef SCANNEDFOLDERSMODEL_H
|
||||
#define SCANNEDFOLDERSMODEL_H
|
||||
#ifndef SCANFOLDERSMODEL_H
|
||||
#define SCANFOLDERSMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QList>
|
||||
@@ -55,14 +55,15 @@ public:
|
||||
AlreadyInList
|
||||
};
|
||||
|
||||
static ScanFoldersModel *instance(QObject *parent = 0);
|
||||
virtual ~ScanFoldersModel();
|
||||
static bool initInstance(QObject *parent = 0);
|
||||
static void freeInstance();
|
||||
static ScanFoldersModel *instance();
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
|
||||
// TODO: removePaths(); singular version becomes private helper functions;
|
||||
// also: remove functions should take modelindexes
|
||||
@@ -74,12 +75,14 @@ public:
|
||||
bool downloadInTorrentFolder(const QString &filePath) const;
|
||||
void makePersistent();
|
||||
|
||||
signals:
|
||||
// The absolute paths of new torrent files in the scanned directories.
|
||||
void torrentsAdded(QStringList &pathList);
|
||||
private slots:
|
||||
void configure();
|
||||
void addTorrentsToSession(const QStringList &pathList);
|
||||
|
||||
private:
|
||||
explicit ScanFoldersModel(QObject *parent = 0);
|
||||
~ScanFoldersModel();
|
||||
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
|
||||
static ScanFoldersModel *m_instance;
|
||||
class PathData;
|
||||
@@ -89,4 +92,4 @@ private:
|
||||
FileSystemWatcher *m_fsWatcher;
|
||||
};
|
||||
|
||||
#endif // SCANNEDFOLDERSMODEL_H
|
||||
#endif // SCANFOLDERSMODEL_H
|
||||
159
src/core/torrentfilter.cpp
Normal file
159
src/core/torrentfilter.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 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 "bittorrent/torrenthandle.h"
|
||||
#include "torrentfilter.h"
|
||||
|
||||
const QString TorrentFilter::AnyLabel;
|
||||
const QStringSet TorrentFilter::AnyHash = (QStringSet() << QString());
|
||||
|
||||
const TorrentFilter TorrentFilter::DownloadingTorrent(TorrentFilter::Downloading);
|
||||
const TorrentFilter TorrentFilter::SeedingTorrent(TorrentFilter::Seeding);
|
||||
const TorrentFilter TorrentFilter::CompletedTorrent(TorrentFilter::Completed);
|
||||
const TorrentFilter TorrentFilter::PausedTorrent(TorrentFilter::Paused);
|
||||
const TorrentFilter TorrentFilter::ResumedTorrent(TorrentFilter::Resumed);
|
||||
const TorrentFilter TorrentFilter::ActiveTorrent(TorrentFilter::Active);
|
||||
const TorrentFilter TorrentFilter::InactiveTorrent(TorrentFilter::Inactive);
|
||||
|
||||
using BitTorrent::TorrentHandle;
|
||||
using BitTorrent::TorrentState;
|
||||
|
||||
TorrentFilter::TorrentFilter()
|
||||
: m_type(All)
|
||||
{
|
||||
}
|
||||
|
||||
TorrentFilter::TorrentFilter(Type type, QStringSet hashSet, QString label)
|
||||
: m_type(type)
|
||||
, m_label(label)
|
||||
, m_hashSet(hashSet)
|
||||
{
|
||||
}
|
||||
|
||||
TorrentFilter::TorrentFilter(QString filter, QStringSet hashSet, QString label)
|
||||
: m_type(All)
|
||||
, m_label(label)
|
||||
, m_hashSet(hashSet)
|
||||
{
|
||||
setTypeByName(filter);
|
||||
}
|
||||
|
||||
bool TorrentFilter::setType(Type type)
|
||||
{
|
||||
if (m_type != type) {
|
||||
m_type = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TorrentFilter::setTypeByName(const QString &filter)
|
||||
{
|
||||
Type type = All;
|
||||
|
||||
if (filter == "downloading")
|
||||
type = Downloading;
|
||||
else if (filter == "seeding")
|
||||
type = Seeding;
|
||||
else if (filter == "completed")
|
||||
type = Completed;
|
||||
else if (filter == "paused")
|
||||
type = Paused;
|
||||
else if (filter == "resumed")
|
||||
type = Resumed;
|
||||
else if (filter == "active")
|
||||
type = Active;
|
||||
else if (filter == "inactive")
|
||||
type = Inactive;
|
||||
|
||||
return setType(type);
|
||||
}
|
||||
|
||||
bool TorrentFilter::setHashSet(const QStringSet &hashSet)
|
||||
{
|
||||
if (m_hashSet != hashSet) {
|
||||
m_hashSet = hashSet;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TorrentFilter::setLabel(const QString &label)
|
||||
{
|
||||
if (m_label != label) {
|
||||
m_label = label;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TorrentFilter::match(TorrentHandle *const torrent) const
|
||||
{
|
||||
if (!torrent) return false;
|
||||
|
||||
return (matchState(torrent) && matchHash(torrent) && matchLabel(torrent));
|
||||
}
|
||||
|
||||
bool TorrentFilter::matchState(BitTorrent::TorrentHandle *const torrent) const
|
||||
{
|
||||
switch (m_type) {
|
||||
case All:
|
||||
return true;
|
||||
case Downloading:
|
||||
return torrent->isDownloading();
|
||||
case Seeding:
|
||||
return torrent->isUploading();
|
||||
case Completed:
|
||||
return torrent->isCompleted();
|
||||
case Paused:
|
||||
return torrent->isPaused();
|
||||
case Resumed:
|
||||
return torrent->isResumed();
|
||||
case Active:
|
||||
return torrent->isActive();
|
||||
case Inactive:
|
||||
return torrent->isInactive();
|
||||
default: // All
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool TorrentFilter::matchHash(BitTorrent::TorrentHandle *const torrent) const
|
||||
{
|
||||
if (m_hashSet == AnyHash) return true;
|
||||
else return m_hashSet.contains(torrent->hash());
|
||||
}
|
||||
|
||||
bool TorrentFilter::matchLabel(BitTorrent::TorrentHandle *const torrent) const
|
||||
{
|
||||
if (m_label == AnyLabel) return true;
|
||||
else return (torrent->label() == m_label);
|
||||
}
|
||||
93
src/core/torrentfilter.h
Normal file
93
src/core/torrentfilter.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef TORRENTFILTER_H
|
||||
#define TORRENTFILTER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QSet>
|
||||
|
||||
typedef QSet<QString> QStringSet;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
|
||||
class TorrentHandle;
|
||||
class TorrentState;
|
||||
|
||||
}
|
||||
|
||||
class TorrentFilter
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
All,
|
||||
Downloading,
|
||||
Seeding,
|
||||
Completed,
|
||||
Resumed,
|
||||
Paused,
|
||||
Active,
|
||||
Inactive
|
||||
};
|
||||
|
||||
static const QString AnyLabel;
|
||||
static const QStringSet AnyHash;
|
||||
|
||||
static const TorrentFilter DownloadingTorrent;
|
||||
static const TorrentFilter SeedingTorrent;
|
||||
static const TorrentFilter CompletedTorrent;
|
||||
static const TorrentFilter PausedTorrent;
|
||||
static const TorrentFilter ResumedTorrent;
|
||||
static const TorrentFilter ActiveTorrent;
|
||||
static const TorrentFilter InactiveTorrent;
|
||||
|
||||
TorrentFilter();
|
||||
// label: pass empty string for "no label" or null string (QString()) for "any label"
|
||||
TorrentFilter(Type type, QStringSet hashSet = AnyHash, QString label = AnyLabel);
|
||||
TorrentFilter(QString filter, QStringSet hashSet = AnyHash, QString label = AnyLabel);
|
||||
|
||||
bool setType(Type type);
|
||||
bool setTypeByName(const QString &filter);
|
||||
bool setHashSet(const QStringSet &hashSet);
|
||||
bool setLabel(const QString &label);
|
||||
|
||||
bool match(BitTorrent::TorrentHandle *const torrent) const;
|
||||
|
||||
private:
|
||||
bool matchState(BitTorrent::TorrentHandle *const torrent) const;
|
||||
bool matchHash(BitTorrent::TorrentHandle *const torrent) const;
|
||||
bool matchLabel(BitTorrent::TorrentHandle *const torrent) const;
|
||||
|
||||
Type m_type;
|
||||
QString m_label;
|
||||
QStringSet m_hashSet;
|
||||
};
|
||||
|
||||
#endif // TORRENTFILTER_H
|
||||
@@ -1,527 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include "torrentpersistentdata.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QVariant>
|
||||
|
||||
#include "qinisettings.h"
|
||||
#include "misc.h"
|
||||
#include "qtorrenthandle.h"
|
||||
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
QHash<QString, TorrentTempData::TorrentData> TorrentTempData::data = QHash<QString, TorrentTempData::TorrentData>();
|
||||
QHash<QString, TorrentTempData::TorrentMoveState> TorrentTempData::torrentMoveStates = QHash<QString, TorrentTempData::TorrentMoveState>();
|
||||
QHash<QString, bool> HiddenData::data = QHash<QString, bool>();
|
||||
unsigned int HiddenData::metadata_counter = 0;
|
||||
TorrentPersistentData* TorrentPersistentData::m_instance = 0;
|
||||
|
||||
TorrentTempData::TorrentData::TorrentData()
|
||||
: sequential(false)
|
||||
, seed(false)
|
||||
, add_paused(Preferences::instance()->addTorrentsInPause())
|
||||
{
|
||||
}
|
||||
|
||||
TorrentTempData::TorrentMoveState::TorrentMoveState(QString oldPath, QString newPath)
|
||||
: oldPath(oldPath)
|
||||
, newPath(newPath)
|
||||
{
|
||||
}
|
||||
|
||||
bool TorrentTempData::hasTempData(const QString &hash)
|
||||
{
|
||||
return data.contains(hash);
|
||||
}
|
||||
|
||||
void TorrentTempData::deleteTempData(const QString &hash)
|
||||
{
|
||||
data.remove(hash);
|
||||
}
|
||||
|
||||
void TorrentTempData::setFilesPriority(const QString &hash, const std::vector<int> &pp)
|
||||
{
|
||||
data[hash].files_priority = pp;
|
||||
}
|
||||
|
||||
void TorrentTempData::setFilesPath(const QString &hash, const QStringList &path_list)
|
||||
{
|
||||
data[hash].path_list = path_list;
|
||||
}
|
||||
|
||||
void TorrentTempData::setSavePath(const QString &hash, const QString &save_path)
|
||||
{
|
||||
data[hash].save_path = save_path;
|
||||
}
|
||||
|
||||
void TorrentTempData::setLabel(const QString &hash, const QString &label)
|
||||
{
|
||||
data[hash].label = label;
|
||||
}
|
||||
|
||||
void TorrentTempData::setSequential(const QString &hash, const bool &sequential)
|
||||
{
|
||||
data[hash].sequential = sequential;
|
||||
}
|
||||
|
||||
bool TorrentTempData::isSequential(const QString &hash)
|
||||
{
|
||||
return data.value(hash).sequential;
|
||||
}
|
||||
|
||||
void TorrentTempData::setSeedingMode(const QString &hash, const bool &seed)
|
||||
{
|
||||
data[hash].seed = seed;
|
||||
}
|
||||
|
||||
bool TorrentTempData::isSeedingMode(const QString &hash)
|
||||
{
|
||||
return data.value(hash).seed;
|
||||
}
|
||||
|
||||
QString TorrentTempData::getSavePath(const QString &hash)
|
||||
{
|
||||
return data.value(hash).save_path;
|
||||
}
|
||||
|
||||
QStringList TorrentTempData::getFilesPath(const QString &hash)
|
||||
{
|
||||
return data.value(hash).path_list;
|
||||
}
|
||||
|
||||
QString TorrentTempData::getLabel(const QString &hash)
|
||||
{
|
||||
return data.value(hash).label;
|
||||
}
|
||||
|
||||
void TorrentTempData::getFilesPriority(const QString &hash, std::vector<int> &fp)
|
||||
{
|
||||
fp = data.value(hash).files_priority;
|
||||
}
|
||||
|
||||
bool TorrentTempData::isMoveInProgress(const QString &hash)
|
||||
{
|
||||
return torrentMoveStates.find(hash) != torrentMoveStates.end();
|
||||
}
|
||||
|
||||
void TorrentTempData::enqueueMove(const QString &hash, const QString &queuedPath)
|
||||
{
|
||||
QHash<QString, TorrentMoveState>::iterator i = torrentMoveStates.find(hash);
|
||||
if (i == torrentMoveStates.end()) {
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
i->queuedPath = queuedPath;
|
||||
}
|
||||
|
||||
void TorrentTempData::startMove(const QString &hash, const QString &oldPath, const QString& newPath)
|
||||
{
|
||||
QHash<QString, TorrentMoveState>::iterator i = torrentMoveStates.find(hash);
|
||||
if (i != torrentMoveStates.end()) {
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
torrentMoveStates.insert(hash, TorrentMoveState(oldPath, newPath));
|
||||
}
|
||||
|
||||
void TorrentTempData::finishMove(const QString &hash)
|
||||
{
|
||||
QHash<QString, TorrentMoveState>::iterator i = torrentMoveStates.find(hash);
|
||||
if (i == torrentMoveStates.end()) {
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
torrentMoveStates.erase(i);
|
||||
}
|
||||
|
||||
QString TorrentTempData::getOldPath(const QString &hash)
|
||||
{
|
||||
QHash<QString, TorrentMoveState>::iterator i = torrentMoveStates.find(hash);
|
||||
if (i == torrentMoveStates.end()) {
|
||||
Q_ASSERT(false);
|
||||
return QString();
|
||||
}
|
||||
return i->oldPath;
|
||||
}
|
||||
|
||||
QString TorrentTempData::getNewPath(const QString &hash)
|
||||
{
|
||||
QHash<QString, TorrentMoveState>::iterator i = torrentMoveStates.find(hash);
|
||||
if (i == torrentMoveStates.end()) {
|
||||
Q_ASSERT(false);
|
||||
return QString();
|
||||
}
|
||||
return i->newPath;
|
||||
}
|
||||
|
||||
QString TorrentTempData::getQueuedPath(const QString &hash)
|
||||
{
|
||||
QHash<QString, TorrentMoveState>::iterator i = torrentMoveStates.find(hash);
|
||||
if (i == torrentMoveStates.end()) {
|
||||
Q_ASSERT(false);
|
||||
return QString();
|
||||
}
|
||||
return i->queuedPath;
|
||||
}
|
||||
|
||||
void TorrentTempData::setAddPaused(const QString &hash, const bool &paused)
|
||||
{
|
||||
data[hash].add_paused = paused;
|
||||
}
|
||||
|
||||
bool TorrentTempData::isAddPaused(const QString &hash)
|
||||
{
|
||||
return data.value(hash).add_paused;
|
||||
}
|
||||
|
||||
void HiddenData::addData(const QString &hash)
|
||||
{
|
||||
data[hash] = false;
|
||||
}
|
||||
|
||||
bool HiddenData::hasData(const QString &hash)
|
||||
{
|
||||
return data.contains(hash);
|
||||
}
|
||||
|
||||
void HiddenData::deleteData(const QString &hash)
|
||||
{
|
||||
if (data.value(hash, false))
|
||||
metadata_counter--;
|
||||
data.remove(hash);
|
||||
}
|
||||
|
||||
int HiddenData::getSize()
|
||||
{
|
||||
return data.size();
|
||||
}
|
||||
|
||||
int HiddenData::getDownloadingSize()
|
||||
{
|
||||
return data.size() - metadata_counter;
|
||||
}
|
||||
|
||||
void HiddenData::gotMetadata(const QString &hash)
|
||||
{
|
||||
if (!data.contains(hash))
|
||||
return;
|
||||
data[hash] = true;
|
||||
metadata_counter++;
|
||||
}
|
||||
|
||||
TorrentPersistentData::TorrentPersistentData()
|
||||
: m_data(QIniSettings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume")).value("torrents").toHash())
|
||||
, dirty(false)
|
||||
{
|
||||
timer.setSingleShot(true);
|
||||
timer.setInterval(5 * 1000);
|
||||
connect(&timer, SIGNAL(timeout()), SLOT(save()));
|
||||
}
|
||||
|
||||
TorrentPersistentData::~TorrentPersistentData()
|
||||
{
|
||||
save();
|
||||
}
|
||||
|
||||
void TorrentPersistentData::save()
|
||||
{
|
||||
if (!dirty)
|
||||
return;
|
||||
|
||||
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent-resume"));
|
||||
settings.setValue("torrents", m_data);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
const QVariant TorrentPersistentData::value(const QString &key, const QVariant &defaultValue) const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
return m_data.value(key, defaultValue);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::setValue(const QString &key, const QVariant &value)
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
if (m_data.value(key) == value)
|
||||
return;
|
||||
dirty = true;
|
||||
timer.start();
|
||||
m_data.insert(key, value);
|
||||
}
|
||||
|
||||
TorrentPersistentData* TorrentPersistentData::instance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new TorrentPersistentData;
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void TorrentPersistentData::drop()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool TorrentPersistentData::isKnownTorrent(QString hash) const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
return m_data.contains(hash);
|
||||
}
|
||||
|
||||
QStringList TorrentPersistentData::knownTorrents() const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
return m_data.keys();
|
||||
}
|
||||
|
||||
void TorrentPersistentData::setRatioLimit(const QString &hash, const qreal &ratio)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["max_ratio"] = ratio;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
qreal TorrentPersistentData::getRatioLimit(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("max_ratio", USE_GLOBAL_RATIO).toReal();
|
||||
}
|
||||
|
||||
bool TorrentPersistentData::hasPerTorrentRatioLimit() const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
QHash<QString, QVariant>::ConstIterator it = m_data.constBegin();
|
||||
QHash<QString, QVariant>::ConstIterator itend = m_data.constEnd();
|
||||
for (; it != itend; ++it)
|
||||
if (it.value().toHash().value("max_ratio", USE_GLOBAL_RATIO).toReal() >= 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void TorrentPersistentData::setAddedDate(const QString &hash, const QDateTime &time)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
if (!torrent.contains("add_date")) {
|
||||
torrent["add_date"] = time;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
}
|
||||
|
||||
QDateTime TorrentPersistentData::getAddedDate(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
QDateTime dt = torrent.value("add_date").toDateTime();
|
||||
if (!dt.isValid())
|
||||
dt = QDateTime::currentDateTime();
|
||||
return dt;
|
||||
}
|
||||
|
||||
void TorrentPersistentData::setErrorState(const QString &hash, const bool has_error)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["has_error"] = has_error;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
bool TorrentPersistentData::hasError(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("has_error", false).toBool();
|
||||
}
|
||||
|
||||
QDateTime TorrentPersistentData::getSeedDate(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("seed_date").toDateTime();
|
||||
}
|
||||
|
||||
void TorrentPersistentData::deletePersistentData(const QString &hash)
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
if (m_data.contains(hash)) {
|
||||
m_data.remove(hash);
|
||||
dirty = true;
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentPersistentData::saveTorrentPersistentData(const QTorrentHandle &h, const QString &save_path, const bool is_magnet)
|
||||
{
|
||||
Q_ASSERT(h.is_valid());
|
||||
QString hash = h.hash();
|
||||
qDebug("Saving persistent data for %s", qPrintable(hash));
|
||||
// Save persistent data
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["is_magnet"] = is_magnet;
|
||||
if (is_magnet)
|
||||
torrent["magnet_uri"] = misc::toQString(make_magnet_uri(h));
|
||||
torrent["seed"] = h.is_seed();
|
||||
torrent["priority"] = h.queue_position();
|
||||
if (save_path.isEmpty()) {
|
||||
qDebug("TorrentPersistantData: save path is %s", qPrintable(h.save_path()));
|
||||
torrent["save_path"] = h.save_path();
|
||||
}
|
||||
else {
|
||||
qDebug("TorrentPersistantData: overriding save path is %s", qPrintable(save_path));
|
||||
torrent["save_path"] = save_path; // Override torrent save path (e.g. because it is a temp dir)
|
||||
}
|
||||
// Label
|
||||
torrent["label"] = TorrentTempData::getLabel(hash);
|
||||
// Save data
|
||||
setValue(hash, torrent);
|
||||
qDebug("TorrentPersistentData: Saving save_path %s, hash: %s", qPrintable(h.save_path()), qPrintable(hash));
|
||||
// Set Added date
|
||||
setAddedDate(hash, QDateTime::currentDateTime());
|
||||
// Finally, remove temp data
|
||||
TorrentTempData::deleteTempData(hash);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::saveSavePath(const QString &hash, const QString &save_path)
|
||||
{
|
||||
Q_ASSERT(!hash.isEmpty());
|
||||
qDebug("TorrentPersistentData::saveSavePath(%s)", qPrintable(save_path));
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["save_path"] = save_path;
|
||||
setValue(hash, torrent);
|
||||
qDebug("TorrentPersistentData: Saving save_path: %s, hash: %s", qPrintable(save_path), qPrintable(hash));
|
||||
}
|
||||
|
||||
void TorrentPersistentData::saveLabel(const QString &hash, const QString &label)
|
||||
{
|
||||
Q_ASSERT(!hash.isEmpty());
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["label"] = label;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::saveName(const QString &hash, const QString &name)
|
||||
{
|
||||
Q_ASSERT(!hash.isEmpty());
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["name"] = name;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::savePriority(const QTorrentHandle &h)
|
||||
{
|
||||
QString hash = h.hash();
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["priority"] = h.queue_position();
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::savePriority(const QString &hash, const int &queue_pos)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["priority"] = queue_pos;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::saveSeedStatus(const QTorrentHandle &h)
|
||||
{
|
||||
QString hash = h.hash();
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
bool was_seed = torrent.value("seed", false).toBool();
|
||||
if (was_seed != h.is_seed()) {
|
||||
torrent["seed"] = !was_seed;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentPersistentData::saveSeedStatus(const QString &hash, const bool seedStatus)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["seed"] = seedStatus;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
void TorrentPersistentData::setHasMissingFiles(const QString& hash, bool missing)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
torrent["has_missing_files"] = missing;
|
||||
setValue(hash, torrent);
|
||||
}
|
||||
|
||||
QString TorrentPersistentData::getSavePath(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
//qDebug("TorrentPersistentData: getSavePath %s", data["save_path"].toString().toLocal8Bit().data());
|
||||
return torrent.value("save_path").toString();
|
||||
}
|
||||
|
||||
QString TorrentPersistentData::getLabel(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("label", "").toString();
|
||||
}
|
||||
|
||||
QString TorrentPersistentData::getName(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("name", "").toString();
|
||||
}
|
||||
|
||||
int TorrentPersistentData::getPriority(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("priority", -1).toInt();
|
||||
}
|
||||
|
||||
bool TorrentPersistentData::isSeed(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("seed", false).toBool();
|
||||
}
|
||||
|
||||
bool TorrentPersistentData::isMagnet(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("is_magnet", false).toBool();
|
||||
}
|
||||
|
||||
QString TorrentPersistentData::getMagnetUri(const QString &hash) const
|
||||
{
|
||||
const QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
Q_ASSERT(torrent.value("is_magnet", false).toBool());
|
||||
return torrent.value("magnet_uri").toString();
|
||||
}
|
||||
|
||||
bool TorrentPersistentData::getHasMissingFiles(const QString& hash)
|
||||
{
|
||||
QHash<QString, QVariant> torrent = value(hash).toHash();
|
||||
return torrent.value("has_missing_files").toBool();
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef TORRENTPERSISTENTDATA_H
|
||||
#define TORRENTPERSISTENTDATA_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QReadWriteLock>
|
||||
#include <vector>
|
||||
#include "preferences.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDateTime;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class QTorrentHandle;
|
||||
|
||||
class TorrentTempData
|
||||
{
|
||||
// This class stores strings w/o modifying separators
|
||||
public:
|
||||
static bool hasTempData(const QString &hash);
|
||||
static void deleteTempData(const QString &hash);
|
||||
static void setFilesPriority(const QString &hash, const std::vector<int> &pp);
|
||||
static void setFilesPath(const QString &hash, const QStringList &path_list);
|
||||
static void setSavePath(const QString &hash, const QString &save_path);
|
||||
static void setLabel(const QString &hash, const QString &label);
|
||||
static void setSequential(const QString &hash, const bool &sequential);
|
||||
static bool isSequential(const QString &hash);
|
||||
static void setSeedingMode(const QString &hash, const bool &seed);
|
||||
static bool isSeedingMode(const QString &hash);
|
||||
static QString getSavePath(const QString &hash);
|
||||
static QStringList getFilesPath(const QString &hash);
|
||||
static QString getLabel(const QString &hash);
|
||||
static void getFilesPriority(const QString &hash, std::vector<int> &fp);
|
||||
static bool isMoveInProgress(const QString &hash);
|
||||
static void enqueueMove(const QString &hash, const QString &queuedPath);
|
||||
static void startMove(const QString &hash, const QString &oldPath, const QString& newPath);
|
||||
static void finishMove(const QString &hash);
|
||||
static QString getOldPath(const QString &hash);
|
||||
static QString getNewPath(const QString &hash);
|
||||
static QString getQueuedPath(const QString &hash);
|
||||
static void setAddPaused(const QString &hash, const bool &paused);
|
||||
static bool isAddPaused(const QString &hash);
|
||||
|
||||
private:
|
||||
struct TorrentData
|
||||
{
|
||||
TorrentData();
|
||||
std::vector<int> files_priority;
|
||||
QStringList path_list;
|
||||
QString save_path;
|
||||
QString label;
|
||||
bool sequential;
|
||||
bool seed;
|
||||
bool add_paused;
|
||||
};
|
||||
|
||||
struct TorrentMoveState
|
||||
{
|
||||
TorrentMoveState(QString oldPath, QString newPath);
|
||||
// the moving occurs from oldPath to newPath
|
||||
// queuedPath is where files should be moved to, when current moving is completed
|
||||
QString oldPath;
|
||||
QString newPath;
|
||||
QString queuedPath;
|
||||
};
|
||||
|
||||
static QHash<QString, TorrentData> data;
|
||||
static QHash<QString, TorrentMoveState> torrentMoveStates;
|
||||
};
|
||||
|
||||
class HiddenData
|
||||
{
|
||||
public:
|
||||
static void addData(const QString &hash);
|
||||
static bool hasData(const QString &hash);
|
||||
static void deleteData(const QString &hash);
|
||||
static int getSize();
|
||||
static int getDownloadingSize();
|
||||
static void gotMetadata(const QString &hash);
|
||||
|
||||
private:
|
||||
static QHash<QString, bool> data;
|
||||
static unsigned int metadata_counter;
|
||||
};
|
||||
|
||||
class TorrentPersistentData: QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TorrentPersistentData)
|
||||
|
||||
public:
|
||||
enum RatioLimit
|
||||
{
|
||||
USE_GLOBAL_RATIO = -2,
|
||||
NO_RATIO_LIMIT = -1
|
||||
};
|
||||
|
||||
static TorrentPersistentData* instance();
|
||||
static void drop();
|
||||
~TorrentPersistentData();
|
||||
|
||||
bool isKnownTorrent(QString hash) const;
|
||||
QStringList knownTorrents() const;
|
||||
void setRatioLimit(const QString &hash, const qreal &ratio);
|
||||
qreal getRatioLimit(const QString &hash) const;
|
||||
bool hasPerTorrentRatioLimit() const;
|
||||
void setAddedDate(const QString &hash, const QDateTime &time);
|
||||
QDateTime getAddedDate(const QString &hash) const;
|
||||
void setErrorState(const QString &hash, const bool has_error);
|
||||
bool hasError(const QString &hash) const;
|
||||
QDateTime getSeedDate(const QString &hash) const;
|
||||
void deletePersistentData(const QString &hash);
|
||||
void saveTorrentPersistentData(const QTorrentHandle &h, const QString &save_path = QString::null, const bool is_magnet = false);
|
||||
|
||||
// Setters
|
||||
void saveSavePath(const QString &hash, const QString &save_path);
|
||||
void saveLabel(const QString &hash, const QString &label);
|
||||
void saveName(const QString &hash, const QString &name);
|
||||
void savePriority(const QTorrentHandle &h);
|
||||
void savePriority(const QString &hash, const int &queue_pos);
|
||||
void saveSeedStatus(const QTorrentHandle &h);
|
||||
void saveSeedStatus(const QString &hash, const bool seedStatus);
|
||||
void setHasMissingFiles(const QString &hash, bool missing);
|
||||
|
||||
// Getters
|
||||
QString getSavePath(const QString &hash) const;
|
||||
QString getLabel(const QString &hash) const;
|
||||
QString getName(const QString &hash) const;
|
||||
int getPriority(const QString &hash) const;
|
||||
bool isSeed(const QString &hash) const;
|
||||
bool isMagnet(const QString &hash) const;
|
||||
QString getMagnetUri(const QString &hash) const;
|
||||
bool getHasMissingFiles(const QString& hash);
|
||||
public slots:
|
||||
void save();
|
||||
|
||||
private:
|
||||
TorrentPersistentData();
|
||||
static TorrentPersistentData* m_instance;
|
||||
QHash<QString, QVariant> m_data;
|
||||
bool dirty;
|
||||
QTimer timer;
|
||||
mutable QReadWriteLock lock;
|
||||
const QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
|
||||
void setValue(const QString &key, const QVariant &value);
|
||||
|
||||
};
|
||||
|
||||
#endif // TORRENTPERSISTENTDATA_H
|
||||
60
src/core/tristatebool.cpp
Normal file
60
src/core/tristatebool.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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 "tristatebool.h"
|
||||
|
||||
TriStateBool::TriStateBool()
|
||||
: m_value(Undefined)
|
||||
{
|
||||
}
|
||||
|
||||
TriStateBool::TriStateBool(bool b)
|
||||
{
|
||||
m_value = (b ? True : False);
|
||||
}
|
||||
|
||||
TriStateBool::TriStateBool(TriStateBool::ValueType value)
|
||||
: m_value(Undefined)
|
||||
{
|
||||
switch (value) {
|
||||
case Undefined:
|
||||
case True:
|
||||
case False:
|
||||
m_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
TriStateBool::operator bool() const
|
||||
{
|
||||
return (m_value == True);
|
||||
}
|
||||
|
||||
TriStateBool::operator ValueType() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
53
src/core/tristatebool.h
Normal file
53
src/core/tristatebool.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef TRISTATEBOOL_H
|
||||
#define TRISTATEBOOL_H
|
||||
|
||||
class TriStateBool
|
||||
{
|
||||
public:
|
||||
enum ValueType
|
||||
{
|
||||
Undefined = -1,
|
||||
False = 0,
|
||||
True = 1
|
||||
};
|
||||
|
||||
TriStateBool();
|
||||
TriStateBool(bool b);
|
||||
TriStateBool(ValueType value);
|
||||
|
||||
operator ValueType() const;
|
||||
operator bool() const;
|
||||
|
||||
private:
|
||||
ValueType m_value;
|
||||
};
|
||||
|
||||
#endif // TRISTATEBOOL_H
|
||||
63
src/core/types.h
Normal file
63
src/core/types.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
#define BEGIN_SCOPED_ENUM(name) class name\
|
||||
{\
|
||||
int m_val;\
|
||||
\
|
||||
public:\
|
||||
name() {}\
|
||||
name(int val) : m_val(val) {}\
|
||||
operator int() const { return m_val; }\
|
||||
operator QVariant() const { return m_val; }\
|
||||
\
|
||||
enum
|
||||
|
||||
#define END_SCOPED_ENUM ; };
|
||||
|
||||
|
||||
BEGIN_SCOPED_ENUM(MaxRatioAction)
|
||||
{
|
||||
Pause,
|
||||
Remove
|
||||
}
|
||||
END_SCOPED_ENUM
|
||||
|
||||
BEGIN_SCOPED_ENUM(TorrentExportFolder)
|
||||
{
|
||||
Regular,
|
||||
Finished
|
||||
}
|
||||
END_SCOPED_ENUM
|
||||
|
||||
#endif // TYPES_H
|
||||
43
src/core/utils/string.cpp
Normal file
43
src/core/utils/string.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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 <QByteArray>
|
||||
#include <QString>
|
||||
#include "string.h"
|
||||
|
||||
QString String::fromStdString(const std::string &str)
|
||||
{
|
||||
return QString::fromUtf8(str.c_str());
|
||||
}
|
||||
|
||||
std::string String::toStdString(const QString &str)
|
||||
{
|
||||
QByteArray utf8 = str.toUtf8();
|
||||
return std::string(utf8.constData(), utf8.length());
|
||||
}
|
||||
43
src/core/utils/string.h
Normal file
43
src/core/utils/string.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_STRING_H
|
||||
#define UTILS_STRING_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class QString;
|
||||
|
||||
namespace String
|
||||
{
|
||||
QString fromStdString(const std::string &str);
|
||||
std::string toStdString(const QString &str);
|
||||
}
|
||||
|
||||
#endif // UTILS_STRING_H
|
||||
Reference in New Issue
Block a user