Rename Core to Base (Closes #3733).

This commit is contained in:
Vladimir Golovnev (Glassez)
2015-09-25 11:10:05 +03:00
parent 29b0200f62
commit 9db93e5d8f
156 changed files with 303 additions and 302 deletions

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

View 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

View 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);
}

View File

@@ -0,0 +1,61 @@
/*
* 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/sha1_hash.hpp>
#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

View 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 <libtorrent/bencode.hpp>
#include <libtorrent/error_code.hpp>
#include <libtorrent/magnet_uri.hpp>
#include "base/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 = Utils::String::fromStdString(m_addTorrentParams.name);
foreach (const std::string &tracker, m_addTorrentParams.trackers)
m_trackers.append(Utils::String::fromStdString(tracker));
foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds)
m_urlSeeds.append(QUrl(urlSeed.c_str()));
}
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;
}

View 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

View File

@@ -0,0 +1,255 @@
/*
* 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 "base/net/geoipmanager.h"
#include "base/utils/string.h"
#include "base/unicodestrings.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);
}
#ifndef DISABLE_COUNTRIES_RESOLUTION
QString PeerInfo::country() const
{
return Net::GeoIPManager::instance()->lookup(address().ip);
}
#endif
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
{
return (m_nativeInfo.flags & libt::peer_info::utp_socket);
}
bool PeerInfo::useSSLSocket() const
{
return (m_nativeInfo.flags & libt::peer_info::ssl_socket);
}
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 Utils::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());
for (int i = 0; i < m_nativeInfo.pieces.size(); ++i)
result.setBit(i, m_nativeInfo.pieces.get_bit(i));
return result;
}
QString PeerInfo::connectionType() const
{
if (m_nativeInfo.flags & libt::peer_info::utp_socket)
return QString::fromUtf8(C_UTP);
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;
}

View File

@@ -0,0 +1,101 @@
/*
* 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;
#ifndef DISABLE_COUNTRIES_RESOLUTION
QString country() const;
#endif
private:
libtorrent::peer_info m_nativeInfo;
};
}
#endif // BITTORRENT_PEERINFO_H

View 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 "base/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 accommodate for external system clock changes
// eg from the user or from a timesync utility
QTimer::start(1500);
}

View 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

View 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 "base/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 filter 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 split by commas
QList<QByteArray> partsList = line.split(',');
const uint nbElem = partsList.size();
// IP Range should be split 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 filter 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 split 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 filter 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 constructor 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 constructor 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");
}

View File

@@ -0,0 +1,74 @@
/*
* Bittorrent Client using Qt 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 FILTERPARSERTHREAD_H
#define FILTERPARSERTHREAD_H
#include <QThread>
class QDataStream;
class QStringList;
namespace libtorrent
{
class session;
struct ip_filter;
}
class FilterParserThread : public QThread
{
Q_OBJECT
public:
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, 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);
signals:
void IPFilterParsed(int ruleCount);
void IPFilterError();
protected:
QString cleanupIPAddress(QString _ip);
void run();
private:
libtorrent::session *m_session;
bool m_abort;
QString m_filePath;
};
#endif // BITTORRENT_FILTERPARSERTHREAD_H

View 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();
}

View 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

View File

@@ -0,0 +1,115 @@
#include <QDateTime>
#include <libtorrent/session.hpp>
#include "base/qinisettings.h"
#include "base/preferences.h"
#include "base/bittorrent/sessionstatus.h"
#include "base/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 "base/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();
}
}

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,375 @@
/*
* 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 <QNetworkConfigurationManager>
#include "base/tristatebool.h"
#include "base/types.h"
#include "torrentinfo.h"
namespace libtorrent
{
class session;
class entry;
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_delete_failed_alert;
struct torrent_paused_alert;
struct torrent_resumed_alert;
struct save_resume_data_alert;
struct save_resume_data_failed_alert;
struct file_renamed_alert;
struct storage_moved_alert;
struct storage_moved_failed_alert;
struct metadata_received_alert;
struct file_error_alert;
struct file_completed_alert;
struct tracker_error_alert;
struct tracker_reply_alert;
struct tracker_warning_alert;
struct portmap_error_alert;
struct portmap_alert;
struct peer_blocked_alert;
struct peer_ban_alert;
struct fastresume_rejected_alert;
struct url_seed_alert;
struct listen_succeeded_alert;
struct listen_failed_alert;
struct external_ip_alert;
}
class QTimer;
class QStringList;
class QString;
class QUrl;
template<typename T> class QList;
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 addForced;
TriStateBool addPaused;
QVector<int> filePriorities; // used if TorrentInfo is set
bool ignoreShareRatio;
bool skipChecking;
AddTorrentParams();
};
struct TorrentStatusReport
{
uint nbDownloading = 0;
uint nbSeeding = 0;
uint nbCompleted = 0;
uint nbActive = 0;
uint nbInactive = 0;
uint nbPaused = 0;
uint nbResumed = 0;
uint nbErrored = 0;
};
class Session : public QObject
{
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;
bool isTempPathEnabled() const;
bool isAppendExtensionEnabled() const;
bool useAppendLabelToSavePath() const;
QString defaultSavePath() const;
QString tempPath() const;
TorrentHandle *findTorrent(const InfoHash &hash) const;
QHash<InfoHash, TorrentHandle *> torrents() const;
TorrentStatusReport torrentStatusReport() 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 &params = AddTorrentParams());
bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams &params = 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);
// TorrentHandle interface
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent);
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
void handleTorrentLabelChanged(TorrentHandle *const torrent, const QString &oldLabel);
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);
signals:
void torrentsUpdated();
void addTorrentFailed(const QString &error);
void torrentAdded(BitTorrent::TorrentHandle *const torrent);
void torrentAboutToBeRemoved(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 torrentLabelChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel);
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);
void switchToAlternativeMode(bool alternative);
// Session reconfiguration triggers
void networkOnlineStateChanged(const bool online);
void networkConfigurationChange(const QNetworkConfiguration&);
private:
explicit Session(QObject *parent = 0);
~Session();
bool hasPerTorrentRatioLimit() const;
void initResumeFolder();
// Session configuration
void setSessionSettings();
void setProxySettings(libtorrent::proxy_settings proxySettings);
void adjustLimits();
void adjustLimits(libtorrent::session_settings &sessionSettings);
const QStringList getListeningIPs();
void setListeningPort();
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 changeSpeedLimitMode_impl(bool alternative);
void setAppendLabelToSavePath(bool append);
void setAppendExtension(bool append);
void startUpTorrents();
bool addTorrent_impl(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 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 handleTorrentDeleteFailedAlert(libtorrent::torrent_delete_failed_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);
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);
AddTorrentData addDataFromParams(const AddTorrentParams &params);
// 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;
bool m_appendLabelToSavePath;
bool m_appendExtension;
uint m_refreshInterval;
MaxRatioAction m_highRatioAction;
QList<BitTorrent::TrackerEntry> m_additionalTrackers;
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;
TorrentStatusReport m_torrentStatusReport;
QMutex m_alertsMutex;
QWaitCondition m_alertsWaitCondition;
QVector<libtorrent::alert *> m_alerts;
QNetworkConfigurationManager m_networkManager;
static Session *m_instance;
};
}
#endif // BITTORRENT_SESSION_H

View File

@@ -0,0 +1,136 @@
/*
* 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;
}
int SessionStatus::downloadRate() const
{
return m_nativeStatus.download_rate;
}
int SessionStatus::uploadRate() const
{
return m_nativeStatus.upload_rate;
}
int SessionStatus::ipOverheadDownloadRate() const
{
return m_nativeStatus.ip_overhead_download_rate;
}
int SessionStatus::ipOverheadUploadRate() const
{
return m_nativeStatus.ip_overhead_upload_rate;
}
int SessionStatus::dhtDownloadRate() const
{
return m_nativeStatus.dht_download_rate;
}
int SessionStatus::dhtUploadRate() const
{
return m_nativeStatus.dht_upload_rate;
}
int SessionStatus::trackerDownloadRate() const
{
return m_nativeStatus.tracker_download_rate;
}
int SessionStatus::trackerUploadRate() const
{
return m_nativeStatus.tracker_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;
}

View File

@@ -0,0 +1,79 @@
/*
* 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;
// Additional download/upload rates
int uploadRate() const;
int downloadRate() const;
int ipOverheadUploadRate() const;
int ipOverheadDownloadRate() const;
int dhtUploadRate() const;
int dhtDownloadRate() const;
int trackerUploadRate() const;
int trackerDownloadRate() 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

View File

@@ -0,0 +1,165 @@
/*
* 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/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 "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/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 = Utils::Fs::fromNativePath(inputPath);
m_savePath = Utils::Fs::fromNativePath(savePath);
if (QFile(m_savePath).exists())
Utils::Fs::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, Utils::String::toStdString(Utils::Fs::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(Utils::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(Utils::String::toStdString(tracker.trimmed()), tier);
newline = false;
}
if (m_abort) return;
// calculate the hash for all pieces
const QString parentPath = Utils::Fs::branchPath(m_inputPath) + "/";
libt::set_piece_hashes(t, Utils::String::toStdString(Utils::Fs::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 = Utils::Fs::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(Utils::Fs::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(Utils::String::fromStdString(e.what()));
}
}

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,418 @@
/*
* 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 "base/tristatebool.h"
#include "private/speedmonitor.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 file_rename_failed_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 torrent_status;
}
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;
bool skipChecking;
TriStateBool addForced;
TriStateBool addPaused;
// for new torrents
QVector<int> filePriorities;
// for resumed torrents
qreal ratioLimit;
};
struct TrackerInfo
{
QString lastMessage;
quint32 numPeers;
TrackerInfo();
};
class TorrentState
{
public:
enum
{
Unknown = -1,
ForcedDownloading,
Downloading,
DownloadingMetadata,
Allocating,
StalledDownloading,
ForcedUploading,
Uploading,
StalledUploading,
QueuedDownloading,
QueuedUploading,
CheckingUploading,
CheckingDownloading,
QueuedForChecking,
CheckingResumeData,
PausedDownloading,
PausedUploading,
MissingFiles,
Error
};
TorrentState(int value);
operator int() const;
QString toString() const;
private:
int m_value;
};
class TorrentHandle : public QObject
{
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;
// 1. savePath() - the path where all the files and subfolders of torrent are stored (as always).
// 2. rootPath() - absolute path of torrent file tree (save path + first item from 1st torrent file path).
// 3. contentPath() - absolute path of torrent content (root path for multifile torrents, absolute file path for singlefile torrents).
//
// These methods have 'actual' parameter (defaults to false) which allow to get actual or final path variant.
//
// Examples.
// Suppose we have three torrent with following structures and save path `/home/user/torrents`:
//
// Torrent A (multifile)
//
// torrentA/
// subdir1/
// subdir2/
// file1
// file2
// file3
// file4
//
//
// Torrent B (singlefile)
//
// torrentB/
// subdir1/
// file1
//
//
// Torrent C (singlefile)
//
// file1
//
//
// Results:
// | | rootPath | contentPath |
// |---|------------------------------|--------------------------------------------|
// | A | /home/user/torrents/torrentA | /home/user/torrents/torrentA |
// | B | /home/user/torrents/torrentB | /home/user/torrents/torrentB/subdir1/file1 |
// | C | /home/user/torrents/file1 | /home/user/torrents/file1 |
QString savePath(bool actual = false) const;
QString rootPath(bool actual = false) const;
QString contentPath(bool actual = false) const;
int filesCount() const;
int piecesCount() const;
int piecesHave() const;
qreal progress() const;
QString label() const;
QDateTime addedTime() const;
qreal ratioLimit() 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 isErrored() 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 finishedTime() const;
int seedingTime() const;
qulonglong eta() const;
QVector<qreal> filesProgress() const;
int seedsCount() const;
int peersCount() const;
int leechsCount() const;
int totalSeedsCount() const;
int totalPeersCount() const;
int totalLeechersCount() const;
int completeCount() const;
int incompleteCount() const;
QDateTime lastSeenComplete() const;
QDateTime completedTime() const;
int timeSinceUpload() const;
int timeSinceDownload() const;
int timeSinceActivity() 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;
qlonglong totalPayloadUpload() const;
qlonglong 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 setFirstLastPiecePriority(bool b);
void toggleFirstLastPiecePriority();
void pause();
void resume(bool forced = false);
void move(QString path);
void forceReannounce(int index = -1);
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;
// Session interface
libtorrent::torrent_handle nativeHandle() const;
void handleAlert(libtorrent::alert *a);
void handleStateUpdate(const libtorrent::torrent_status &nativeStatus);
void handleTempPathChanged();
void handleAppendExtensionToggled();
void saveResumeData();
private:
typedef boost::function<void ()> EventTrigger;
void initialize();
void updateStatus();
void updateStatus(const libtorrent::torrent_status &nativeStatus);
void updateState();
void updateTorrentInfo();
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 handleFileRenameFailedAlert(libtorrent::file_rename_failed_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 adjustActualSavePath();
void adjustActualSavePath_impl();
void moveStorage(const QString &newPath);
void appendExtensionsToIncompleteFiles();
void removeExtensionsFromIncompleteFiles();
bool addTracker(const TrackerEntry &tracker);
bool addUrlSeed(const QUrl &urlSeed);
bool removeUrlSeed(const QUrl &urlSeed);
Session *const m_session;
libtorrent::torrent_handle m_nativeHandle;
libtorrent::torrent_status m_nativeStatus;
TorrentState m_state;
TorrentInfo m_torrentInfo;
SpeedMonitor m_speedMonitor;
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;
// m_moveFinishedTriggers is activated only when the following conditions are met:
// all file rename jobs complete, all file move jobs complete
QQueue<EventTrigger> m_moveFinishedTriggers;
int m_renameCount;
// Persistent data
QString m_name;
QString m_savePath;
QString m_label;
bool m_hasSeedStatus;
qreal m_ratioLimit;
bool m_tempPathDisabled;
bool m_hasMissingFiles;
bool m_pauseAfterRecheck;
bool m_needSaveResumeData;
QHash<QString, TrackerInfo> m_trackerInfos;
};
}
#endif // BITTORRENT_TORRENTHANDLE_H

View File

@@ -0,0 +1,223 @@
/*
* 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 "base/utils/misc.h"
#include "base/utils/fs.h"
#include "base/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(Utils::String::toStdString(Utils::Fs::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 Utils::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 Utils::String::fromStdString(m_nativeInfo->creator());
}
QString TorrentInfo::comment() const
{
if (!isValid()) return QString();
return Utils::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 Utils::Fs::fromNativePath(Utils::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 Utils::Fs::fileName(filePath(index));
}
QString TorrentInfo::origFilePath(int index) const
{
if (!isValid()) return QString();
return Utils::Fs::fromNativePath(Utils::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());
}
void TorrentInfo::renameFile(uint index, const QString &newPath)
{
if (!isValid()) return;
m_nativeInfo->rename_file(index, Utils::String::toStdString(newPath));
}
boost::intrusive_ptr<libtorrent::torrent_info> TorrentInfo::nativeInfo() const
{
return m_nativeInfo;
}

View File

@@ -0,0 +1,87 @@
/*
* 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;
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

View File

@@ -0,0 +1,257 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* 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 <vector>
#include <libtorrent/bencode.hpp>
#include <libtorrent/entry.hpp>
#include "base/preferences.h"
#include "base/http/server.h"
#include "base/utils/string.h"
#include "tracker.h"
// 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 uid() != other.uid();
}
bool Peer::operator==(const Peer &other) const
{
return uid() == other.uid();
}
QString Peer::uid() const
{
return ip + ":" + QString::number(port);
}
libtorrent::entry Peer::toEntry(bool noPeerId) const
{
libtorrent::entry::dictionary_type peerMap;
if (!noPeerId)
peerMap["id"] = libtorrent::entry(Utils::String::toStdString(peerId));
peerMap["ip"] = libtorrent::entry(Utils::String::toStdString(ip));
peerMap["port"] = libtorrent::entry(port);
return libtorrent::entry(peerMap);
}
// Tracker
Tracker::Tracker(QObject *parent)
: Http::ResponseBuilder(parent)
, m_server(new Http::Server(this, this))
{
}
Tracker::~Tracker()
{
if (m_server->isListening())
qDebug("Shutting down the embedded tracker...");
// TODO: Store the torrent list
}
bool Tracker::start()
{
const int listenPort = Preferences::instance()->getTrackerPort();
if (m_server->isListening()) {
if (m_server->serverPort() == listenPort) {
// Already listening on the right port, just return
return true;
}
// Wrong port, closing the server
m_server->close();
}
qDebug("Starting the embedded tracker...");
// Listen on the predefined port
return m_server->listen(QHostAddress::Any, listenPort);
}
Http::Response Tracker::processRequest(const Http::Request &request, const Http::Environment &env)
{
clear(); // clear response
//qDebug("Tracker received the following request:\n%s", qPrintable(parser.toString()));
// Is request a GET request?
if (request.method != "GET") {
qDebug("Tracker: Unsupported HTTP request: %s", qPrintable(request.method));
status(100, "Invalid request type");
}
else if (!request.path.startsWith("/announce", Qt::CaseInsensitive)) {
qDebug("Tracker: Unrecognized path: %s", qPrintable(request.path));
status(100, "Invalid request type");
}
else {
// OK, this is a GET request
m_request = request;
m_env = env;
respondToAnnounceRequest();
}
return response();
}
void Tracker::respondToAnnounceRequest()
{
const QStringMap &gets = m_request.gets;
TrackerAnnounceRequest annonceReq;
// IP
annonceReq.peer.ip = m_env.clientAddress.toString();
// 1. Get info_hash
if (!gets.contains("info_hash")) {
qDebug("Tracker: Missing info_hash");
status(101, "Missing info_hash");
return;
}
annonceReq.infoHash = gets.value("info_hash");
// info_hash cannot be longer than 20 bytes
/*if (annonce_req.info_hash.toLatin1().length() > 20) {
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("Tracker: Missing peer_id");
status(102, "Missing peer_id");
return;
}
annonceReq.peer.peerId = gets.value("peer_id");
// peer_id cannot be longer than 20 bytes
/*if (annonce_req.peer.peer_id.length() > 20) {
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("Tracker: Missing port");
status(103, "Missing port");
return;
}
bool ok = false;
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
annonceReq.event = "";
if (gets.contains("event")) {
annonceReq.event = gets.value("event");
qDebug("Tracker: event is %s", qPrintable(annonceReq.event));
}
// 5. Get numwant
annonceReq.numwant = 50;
if (gets.contains("numwant")) {
int tmp = gets.value("numwant").toInt();
if (tmp > 0) {
qDebug("Tracker: numwant = %d", tmp);
annonceReq.numwant = tmp;
}
}
// 6. no_peer_id (extension)
annonceReq.noPeerId = false;
if (gets.contains("no_peer_id"))
annonceReq.noPeerId = true;
// 7. TODO: support "compact" extension
// Done parsing, now let's reply
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;
}
}
else {
// Unknown torrent
if (m_torrents.size() == MAX_TORRENTS) {
// Reached max size, remove a random torrent
m_torrents.erase(m_torrents.begin());
}
}
// Register the user
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[annonceReq.peer.uid()] = annonceReq.peer;
m_torrents[annonceReq.infoHash] = peers;
// Reply
replyWithPeerList(annonceReq);
}
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
{
// Prepare the entry for bencoding
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)
peerList.push_back(p.toEntry(annonceReq.noPeerId));
}
replyDict["peers"] = libtorrent::entry(peerList);
libtorrent::entry replyEntry(replyDict);
// bencode
std::vector<char> buf;
libtorrent::bencode(std::back_inserter(buf), replyEntry);
QByteArray reply(&buf[0], static_cast<int>(buf.size()));
qDebug("Tracker: reply with the following bencoded data:\n %s", reply.constData());
// HTTP reply
print(reply, Http::CONTENT_TYPE_TXT);
}

View 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 "base/http/types.h"
#include "base/http/responsebuilder.h"
#include "base/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

View 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 <QString>
#include "base/utils/misc.h"
#include "base/utils/string.h"
#include "trackerentry.h"
using namespace BitTorrent;
TrackerEntry::TrackerEntry(const QString &url)
: m_nativeEntry(libtorrent::announce_entry(Utils::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 Utils::String::fromStdString(m_nativeEntry.url);
}
int TrackerEntry::tier() const
{
return m_nativeEntry.tier;
}
TrackerEntry::Status TrackerEntry::status() const
{
// libtorrent::announce_entry::is_working() returns
// true when the tracker hasn't been tried yet.
if (m_nativeEntry.verified && m_nativeEntry.is_working())
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;
}

View 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