qBittorrent/src/base/bittorrent/torrenthandle.h

472 lines
16 KiB
C
Raw Normal View History

2015-04-19 18:17:47 +03:00
/*
* 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 <functional>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/torrent_status.hpp>
#include <QHash>
#include <QObject>
2015-04-19 18:17:47 +03:00
#include <QQueue>
#include <QSet>
#include <QString>
2015-04-19 18:17:47 +03:00
#include <QVector>
#include "private/speedmonitor.h"
#include "infohash.h"
#include "torrentinfo.h"
extern const QString QB_EXT;
2015-04-19 18:17:47 +03:00
class QBitArray;
class QDateTime;
2015-04-19 18:17:47 +03:00
class QStringList;
class QUrl;
2015-04-19 18:17:47 +03:00
namespace libtorrent
{
class alert;
struct fastresume_rejected_alert;
struct file_completed_alert;
struct file_renamed_alert;
struct file_rename_failed_alert;
struct metadata_received_alert;
struct save_resume_data_alert;
struct save_resume_data_failed_alert;
2015-04-19 18:17:47 +03:00
struct stats_alert;
struct storage_moved_alert;
struct storage_moved_failed_alert;
2015-04-19 18:17:47 +03:00
struct torrent_checked_alert;
struct torrent_finished_alert;
struct torrent_paused_alert;
struct torrent_resumed_alert;
struct torrent_status;
2015-04-19 18:17:47 +03:00
struct tracker_error_alert;
struct tracker_reply_alert;
struct tracker_warning_alert;
}
namespace BitTorrent
{
class PeerInfo;
class Session;
2015-04-19 18:17:47 +03:00
class TrackerEntry;
struct AddTorrentParams;
struct PeerAddress;
2015-04-19 18:17:47 +03:00
struct CreateTorrentParams
2015-04-19 18:17:47 +03:00
{
bool restored; // is existing torrent job?
// for both new and restored torrents
2015-04-19 18:17:47 +03:00
QString name;
QString category;
QSet<QString> tags;
2015-04-19 18:17:47 +03:00
QString savePath;
bool disableTempPath;
bool sequential;
bool firstLastPiecePriority;
2015-04-19 18:17:47 +03:00
bool hasSeedStatus;
bool skipChecking;
bool hasRootFolder;
bool forced;
bool paused;
int uploadLimit;
int downloadLimit;
2015-06-04 11:03:19 +03:00
// for new torrents
2015-04-19 18:17:47 +03:00
QVector<int> filePriorities;
// for restored torrents
2015-04-19 18:17:47 +03:00
qreal ratioLimit;
int seedingTimeLimit;
2016-01-01 16:28:40 +03:00
CreateTorrentParams();
2018-12-16 10:51:36 +03:00
explicit CreateTorrentParams(const AddTorrentParams &params);
2015-04-19 18:17:47 +03:00
};
struct TrackerInfo
{
QString lastMessage;
2016-01-01 16:28:40 +03:00
quint32 numPeers = 0;
2015-04-19 18:17:47 +03:00
};
enum class TorrentState
2015-04-19 18:17:47 +03:00
{
Unknown = -1,
2015-04-19 18:17:47 +03:00
ForcedDownloading,
Downloading,
DownloadingMetadata,
Allocating,
StalledDownloading,
2015-06-20 09:05:53 +03:00
ForcedUploading,
Uploading,
StalledUploading,
2015-06-20 09:05:53 +03:00
CheckingResumeData,
QueuedDownloading,
QueuedUploading,
2015-06-30 11:03:46 +03:00
CheckingUploading,
CheckingDownloading,
2015-06-20 09:05:53 +03:00
PausedDownloading,
PausedUploading,
2015-04-19 18:17:47 +03:00
Moving,
MissingFiles,
Error
2015-04-19 18:17:47 +03:00
};
class TorrentHandle : public QObject
2015-04-19 18:17:47 +03:00
{
Q_DISABLE_COPY(TorrentHandle)
2018-09-19 23:59:08 +03:00
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentHandle)
2015-04-19 18:17:47 +03:00
public:
static const qreal USE_GLOBAL_RATIO;
static const qreal NO_RATIO_LIMIT;
static const int USE_GLOBAL_SEEDING_TIME;
static const int NO_SEEDING_TIME_LIMIT;
2015-04-19 18:17:47 +03:00
static const qreal MAX_RATIO;
static const int MAX_SEEDING_TIME;
2015-04-19 18:17:47 +03:00
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
const CreateTorrentParams &params);
2015-04-19 18:17:47 +03:00
~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 A* (Torrent A in "strip root folder" mode)
//
//
// Torrent B (singlefile)
//
// torrentB/
// subdir1/
// file1
//
//
// Torrent C (singlefile)
//
// file1
//
//
// Results:
// | | rootPath | contentPath |
// |---|------------------------------|--------------------------------------------|
// | A | /home/user/torrents/torrentA | /home/user/torrents/torrentA |
// | A*| <empty> | /home/user/torrents |
// | 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;
2017-08-04 22:29:17 +03:00
bool useTempPath() const;
2016-05-08 22:47:50 +03:00
bool isAutoTMMEnabled() const;
void setAutoTMMEnabled(bool enabled);
QString category() const;
bool belongsToCategory(const QString &category) const;
bool setCategory(const QString &category);
QSet<QString> tags() const;
bool hasTag(const QString &tag) const;
bool addTag(const QString &tag);
bool removeTag(const QString &tag);
void removeAllTags();
bool hasRootFolder() const;
2015-04-19 18:17:47 +03:00
int filesCount() const;
int piecesCount() const;
2015-06-17 00:42:25 +03:00
int piecesHave() const;
2015-04-19 18:17:47 +03:00
qreal progress() const;
QDateTime addedTime() const;
qreal ratioLimit() const;
int seedingTimeLimit() const;
2015-04-19 18:17:47 +03:00
QString filePath(int index) const;
QString fileName(int index) const;
qlonglong fileSize(int index) const;
QStringList absoluteFilePaths() const;
QStringList absoluteFilePathsUnwanted() 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;
2015-11-11 09:51:22 +03:00
bool isErrored() const;
2015-04-19 18:17:47 +03:00
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;
2015-06-17 00:42:25 +03:00
int finishedTime() const;
2015-04-19 18:17:47 +03:00
int seedingTime() const;
qulonglong eta() const;
QVector<qreal> filesProgress() const;
int seedsCount() const;
int peersCount() const;
int leechsCount() const;
2015-06-17 00:42:25 +03:00
int totalSeedsCount() const;
int totalPeersCount() const;
int totalLeechersCount() const;
2015-04-19 18:17:47 +03:00
int completeCount() const;
int incompleteCount() const;
QDateTime lastSeenComplete() const;
QDateTime completedTime() const;
int timeSinceUpload() const;
int timeSinceDownload() const;
2015-06-07 15:03:30 +03:00
int timeSinceActivity() const;
2015-04-19 18:17:47 +03:00
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() const;
int maxSeedingTime() const;
2015-04-19 18:17:47 +03:00
qreal realRatio() const;
int uploadPayloadRate() const;
int downloadPayloadRate() const;
qlonglong totalPayloadUpload() const;
qlonglong totalPayloadDownload() const;
2015-04-19 18:17:47 +03:00
int connectionsCount() const;
int connectionsLimit() const;
qlonglong nextAnnounce() const;
void setName(const QString &name);
void setSequentialDownload(bool b);
void toggleSequentialDownload();
void setFirstLastPiecePriority(bool enabled);
void toggleFirstLastPiecePriority();
2015-04-19 18:17:47 +03:00
void pause();
void resume(bool forced = false);
void move(QString path);
void forceReannounce(int index = -1);
void forceDHTAnnounce();
void forceRecheck();
void renameFile(int index, const QString &name);
bool saveTorrentFile(const QString &path);
void prioritizeFiles(const QVector<int> &priorities);
void setRatioLimit(qreal limit);
void setSeedingTimeLimit(int limit);
2015-04-19 18:17:47 +03:00
void setUploadLimit(int limit);
void setDownloadLimit(int limit);
void setSuperSeeding(bool enable);
void flushCache();
void addTrackers(const QList<TrackerEntry> &trackers);
void replaceTrackers(const QList<TrackerEntry> &trackers);
2015-04-19 18:17:47 +03:00
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
2015-04-19 18:17:47 +03:00
libtorrent::torrent_handle nativeHandle() const;
void handleAlert(const libtorrent::alert *a);
void handleStateUpdate(const libtorrent::torrent_status &nativeStatus);
void handleTempPathChanged();
void handleCategorySavePathChanged();
void handleAppendExtensionToggled();
2018-08-23 14:55:27 +03:00
void saveResumeData();
/**
* @brief fraction of file pieces that are available at least from one peer
*
* This is not the same as torrrent availability, it is just a fraction of pieces
* that can be downloaded right now. It varies between 0 to 1.
*/
QVector<qreal> availableFileFractions() const;
2015-04-19 18:17:47 +03:00
private:
typedef std::function<void ()> EventTrigger;
2015-04-19 18:17:47 +03:00
void updateStatus();
void updateStatus(const libtorrent::torrent_status &nativeStatus);
void updateState();
void updateTorrentInfo();
void handleStorageMovedAlert(const libtorrent::storage_moved_alert *p);
void handleStorageMovedFailedAlert(const libtorrent::storage_moved_failed_alert *p);
void handleTrackerReplyAlert(const libtorrent::tracker_reply_alert *p);
void handleTrackerWarningAlert(const libtorrent::tracker_warning_alert *p);
void handleTrackerErrorAlert(const libtorrent::tracker_error_alert *p);
void handleTorrentCheckedAlert(const libtorrent::torrent_checked_alert *p);
void handleTorrentFinishedAlert(const libtorrent::torrent_finished_alert *p);
void handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p);
void handleTorrentResumedAlert(const libtorrent::torrent_resumed_alert *p);
void handleSaveResumeDataAlert(const libtorrent::save_resume_data_alert *p);
void handleSaveResumeDataFailedAlert(const libtorrent::save_resume_data_failed_alert *p);
void handleFastResumeRejectedAlert(const libtorrent::fastresume_rejected_alert *p);
void handleFileRenamedAlert(const libtorrent::file_renamed_alert *p);
void handleFileRenameFailedAlert(const libtorrent::file_rename_failed_alert *p);
void handleFileCompletedAlert(const libtorrent::file_completed_alert *p);
void handleMetadataReceivedAlert(const libtorrent::metadata_received_alert *p);
void handleStatsAlert(const libtorrent::stats_alert *p);
2015-04-19 18:17:47 +03:00
void resume_impl(bool forced);
2015-04-19 18:17:47 +03:00
bool isMoveInProgress() const;
QString nativeActualSavePath() const;
void adjustActualSavePath();
void adjustActualSavePath_impl();
void move_impl(QString path, bool overwrite);
void moveStorage(const QString &newPath, bool overwrite);
void manageIncompleteFiles();
2015-04-19 18:17:47 +03:00
bool addTracker(const TrackerEntry &tracker);
bool addUrlSeed(const QUrl &urlSeed);
bool removeUrlSeed(const QUrl &urlSeed);
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<int> &updatedFilePrio = {});
2015-04-19 18:17:47 +03:00
Session *const m_session;
2015-04-19 18:17:47 +03:00
libtorrent::torrent_handle m_nativeHandle;
libtorrent::torrent_status m_nativeStatus;
TorrentState m_state;
2015-04-19 18:17:47 +03:00
TorrentInfo m_torrentInfo;
SpeedMonitor m_speedMonitor;
InfoHash m_hash;
struct
{
QString oldPath;
QString newPath;
// queuedPath is where files should be moved to,
// when current moving is completed
QString queuedPath;
bool queuedOverwrite = true;
} m_moveStorageInfo;
// 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;
2015-04-19 18:17:47 +03:00
2016-05-08 22:47:50 +03:00
bool m_useAutoTMM;
2015-04-19 18:17:47 +03:00
// Persistent data
QString m_name;
QString m_savePath;
QString m_category;
QSet<QString> m_tags;
2015-04-19 18:17:47 +03:00
bool m_hasSeedStatus;
qreal m_ratioLimit;
int m_seedingTimeLimit;
2015-04-19 18:17:47 +03:00
bool m_tempPathDisabled;
bool m_hasMissingFiles;
bool m_hasRootFolder;
bool m_needsToSetFirstLastPiecePriority;
bool m_needsToStartForced;
2015-04-19 18:17:47 +03:00
QHash<QString, TrackerInfo> m_trackerInfos;
enum StartupState
{
NotStarted,
Starting,
Started
};
StartupState m_startupState = NotStarted;
bool m_unchecked = false;
2015-04-19 18:17:47 +03:00
};
}
Q_DECLARE_METATYPE(BitTorrent::TorrentState)
2015-04-19 18:17:47 +03:00
#endif // BITTORRENT_TORRENTHANDLE_H