Correctly handle changing save path of torrent w/o metadata
[qBittorrent.git] / src / base / bittorrent / torrentimpl.h
blob78f33e414960cf865fb9be5172bccc1b6ce3c8b3
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #pragma once
32 #include <functional>
33 #include <memory>
35 #include <libtorrent/add_torrent_params.hpp>
36 #include <libtorrent/fwd.hpp>
37 #include <libtorrent/torrent_handle.hpp>
38 #include <libtorrent/torrent_info.hpp>
39 #include <libtorrent/torrent_status.hpp>
41 #include <QBitArray>
42 #include <QDateTime>
43 #include <QHash>
44 #include <QMap>
45 #include <QObject>
46 #include <QQueue>
47 #include <QString>
48 #include <QVector>
50 #include "base/path.h"
51 #include "base/tagset.h"
52 #include "infohash.h"
53 #include "speedmonitor.h"
54 #include "torrent.h"
55 #include "torrentcontentlayout.h"
56 #include "torrentinfo.h"
57 #include "trackerentry.h"
59 namespace BitTorrent
61 class SessionImpl;
62 struct LoadTorrentParams;
64 enum class MoveStorageMode
66 FailIfExist,
67 KeepExistingFiles,
68 Overwrite
71 enum class MoveStorageContext
73 AdjustCurrentLocation,
74 ChangeSavePath,
75 ChangeDownloadPath
78 enum class MaintenanceJob
80 None,
81 HandleMetadata
84 struct FileErrorInfo
86 lt::error_code error;
87 lt::operation_t operation = lt::operation_t::unknown;
90 class TorrentImpl final : public Torrent
92 Q_OBJECT
93 Q_DISABLE_COPY_MOVE(TorrentImpl)
95 public:
96 TorrentImpl(SessionImpl *session, lt::session *nativeSession
97 , const lt::torrent_handle &nativeHandle, const LoadTorrentParams &params);
98 ~TorrentImpl() override;
100 bool isValid() const;
102 Session *session() const override;
104 InfoHash infoHash() const override;
105 QString name() const override;
106 QDateTime creationDate() const override;
107 QString creator() const override;
108 QString comment() const override;
109 bool isPrivate() const override;
110 qlonglong totalSize() const override;
111 qlonglong wantedSize() const override;
112 qlonglong completedSize() const override;
113 qlonglong pieceLength() const override;
114 qlonglong wastedSize() const override;
115 QString currentTracker() const override;
117 bool isAutoTMMEnabled() const override;
118 void setAutoTMMEnabled(bool enabled) override;
119 Path savePath() const override;
120 void setSavePath(const Path &path) override;
121 Path downloadPath() const override;
122 void setDownloadPath(const Path &path) override;
123 Path actualStorageLocation() const override;
124 Path rootPath() const override;
125 Path contentPath() const override;
126 QString category() const override;
127 bool belongsToCategory(const QString &category) const override;
128 bool setCategory(const QString &category) override;
130 TagSet tags() const override;
131 bool hasTag(const QString &tag) const override;
132 bool addTag(const QString &tag) override;
133 bool removeTag(const QString &tag) override;
134 void removeAllTags() override;
136 int filesCount() const override;
137 int piecesCount() const override;
138 int piecesHave() const override;
139 qreal progress() const override;
140 QDateTime addedTime() const override;
141 qreal ratioLimit() const override;
142 int seedingTimeLimit() const override;
143 int inactiveSeedingTimeLimit() const override;
145 Path filePath(int index) const override;
146 Path actualFilePath(int index) const override;
147 qlonglong fileSize(int index) const override;
148 PathList filePaths() const override;
149 QVector<DownloadPriority> filePriorities() const override;
151 TorrentInfo info() const override;
152 bool isFinished() const override;
153 bool isPaused() const override;
154 bool isQueued() const override;
155 bool isForced() const override;
156 bool isChecking() const override;
157 bool isDownloading() const override;
158 bool isMoving() const override;
159 bool isUploading() const override;
160 bool isCompleted() const override;
161 bool isActive() const override;
162 bool isInactive() const override;
163 bool isErrored() const override;
164 bool isSequentialDownload() const override;
165 bool hasFirstLastPiecePriority() const override;
166 TorrentState state() const override;
167 bool hasMetadata() const override;
168 bool hasMissingFiles() const override;
169 bool hasError() const override;
170 int queuePosition() const override;
171 QVector<TrackerEntry> trackers() const override;
172 QVector<QUrl> urlSeeds() const override;
173 QString error() const override;
174 qlonglong totalDownload() const override;
175 qlonglong totalUpload() const override;
176 qlonglong activeTime() const override;
177 qlonglong finishedTime() const override;
178 qlonglong eta() const override;
179 QVector<qreal> filesProgress() const override;
180 int seedsCount() const override;
181 int peersCount() const override;
182 int leechsCount() const override;
183 int totalSeedsCount() const override;
184 int totalPeersCount() const override;
185 int totalLeechersCount() const override;
186 QDateTime lastSeenComplete() const override;
187 QDateTime completedTime() const override;
188 qlonglong timeSinceUpload() const override;
189 qlonglong timeSinceDownload() const override;
190 qlonglong timeSinceActivity() const override;
191 int downloadLimit() const override;
192 int uploadLimit() const override;
193 bool superSeeding() const override;
194 bool isDHTDisabled() const override;
195 bool isPEXDisabled() const override;
196 bool isLSDDisabled() const override;
197 QVector<PeerInfo> peers() const override;
198 QBitArray pieces() const override;
199 QBitArray downloadingPieces() const override;
200 QVector<int> pieceAvailability() const override;
201 qreal distributedCopies() const override;
202 qreal maxRatio() const override;
203 int maxSeedingTime() const override;
204 int maxInactiveSeedingTime() const override;
205 qreal realRatio() const override;
206 int uploadPayloadRate() const override;
207 int downloadPayloadRate() const override;
208 qlonglong totalPayloadUpload() const override;
209 qlonglong totalPayloadDownload() const override;
210 int connectionsCount() const override;
211 int connectionsLimit() const override;
212 qlonglong nextAnnounce() const override;
213 QVector<qreal> availableFileFractions() const override;
215 void setName(const QString &name) override;
216 void setSequentialDownload(bool enable) override;
217 void setFirstLastPiecePriority(bool enabled) override;
218 void pause() override;
219 void resume(TorrentOperatingMode mode = TorrentOperatingMode::AutoManaged) override;
220 void forceReannounce(int index = -1) override;
221 void forceDHTAnnounce() override;
222 void forceRecheck() override;
223 void renameFile(int index, const Path &path) override;
224 void prioritizeFiles(const QVector<DownloadPriority> &priorities) override;
225 void setRatioLimit(qreal limit) override;
226 void setSeedingTimeLimit(int limit) override;
227 void setInactiveSeedingTimeLimit(int limit) override;
228 void setUploadLimit(int limit) override;
229 void setDownloadLimit(int limit) override;
230 void setSuperSeeding(bool enable) override;
231 void setDHTDisabled(bool disable) override;
232 void setPEXDisabled(bool disable) override;
233 void setLSDDisabled(bool disable) override;
234 void flushCache() const override;
235 void addTrackers(QVector<TrackerEntry> trackers) override;
236 void removeTrackers(const QStringList &trackers) override;
237 void replaceTrackers(QVector<TrackerEntry> trackers) override;
238 void addUrlSeeds(const QVector<QUrl> &urlSeeds) override;
239 void removeUrlSeeds(const QVector<QUrl> &urlSeeds) override;
240 bool connectPeer(const PeerAddress &peerAddress) override;
241 void clearPeers() override;
242 void setMetadata(const TorrentInfo &torrentInfo) override;
244 StopCondition stopCondition() const override;
245 void setStopCondition(StopCondition stopCondition) override;
247 QString createMagnetURI() const override;
248 nonstd::expected<QByteArray, QString> exportToBuffer() const override;
249 nonstd::expected<void, QString> exportToFile(const Path &path) const override;
251 void fetchPeerInfo(std::function<void (QVector<PeerInfo>)> resultHandler) const override;
252 void fetchURLSeeds(std::function<void (QVector<QUrl>)> resultHandler) const override;
253 void fetchPieceAvailability(std::function<void (QVector<int>)> resultHandler) const override;
254 void fetchDownloadingPieces(std::function<void (QBitArray)> resultHandler) const override;
255 void fetchAvailableFileFractions(std::function<void (QVector<qreal>)> resultHandler) const override;
257 bool needSaveResumeData() const;
259 // Session interface
260 lt::torrent_handle nativeHandle() const;
262 void handleAlert(const lt::alert *a);
263 void handleStateUpdate(const lt::torrent_status &nativeStatus);
264 void handleCategoryOptionsChanged();
265 void handleAppendExtensionToggled();
266 void saveResumeData(lt::resume_data_flags_t flags = {});
267 void handleMoveStorageJobFinished(const Path &path, MoveStorageContext context, bool hasOutstandingJob);
268 void fileSearchFinished(const Path &savePath, const PathList &fileNames);
269 TrackerEntry updateTrackerEntry(const lt::announce_entry &announceEntry, const QHash<lt::tcp::endpoint, QMap<int, int>> &updateInfo);
270 void resetTrackerEntries();
272 private:
273 using EventTrigger = std::function<void ()>;
275 std::shared_ptr<const lt::torrent_info> nativeTorrentInfo() const;
277 void updateStatus(const lt::torrent_status &nativeStatus);
278 void updateProgress();
279 void updateState();
281 void handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p);
282 void handleFileCompletedAlert(const lt::file_completed_alert *p);
283 void handleFileErrorAlert(const lt::file_error_alert *p);
284 #ifdef QBT_USES_LIBTORRENT2
285 void handleFilePrioAlert(const lt::file_prio_alert *p);
286 #endif
287 void handleFileRenamedAlert(const lt::file_renamed_alert *p);
288 void handleFileRenameFailedAlert(const lt::file_rename_failed_alert *p);
289 void handleMetadataReceivedAlert(const lt::metadata_received_alert *p);
290 void handlePerformanceAlert(const lt::performance_alert *p) const;
291 void handleSaveResumeDataAlert(const lt::save_resume_data_alert *p);
292 void handleSaveResumeDataFailedAlert(const lt::save_resume_data_failed_alert *p);
293 void handleTorrentCheckedAlert(const lt::torrent_checked_alert *p);
294 void handleTorrentFinishedAlert(const lt::torrent_finished_alert *p);
295 void handleTorrentPausedAlert(const lt::torrent_paused_alert *p);
296 void handleTorrentResumedAlert(const lt::torrent_resumed_alert *p);
298 bool isMoveInProgress() const;
300 void setAutoManaged(bool enable);
302 Path wantedActualPath(int index, const Path &path) const;
303 void adjustStorageLocation();
304 void doRenameFile(int index, const Path &path);
305 void moveStorage(const Path &newPath, MoveStorageContext context);
306 void manageIncompleteFiles();
307 void applyFirstLastPiecePriority(bool enabled);
309 void prepareResumeData(const lt::add_torrent_params &params);
310 void endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames);
311 void reload();
313 nonstd::expected<lt::entry, QString> exportTorrent() const;
315 template <typename Func, typename Callback>
316 void invokeAsync(Func func, Callback resultHandler) const;
318 SessionImpl *const m_session = nullptr;
319 lt::session *m_nativeSession = nullptr;
320 lt::torrent_handle m_nativeHandle;
321 mutable lt::torrent_status m_nativeStatus;
322 TorrentState m_state = TorrentState::Unknown;
323 TorrentInfo m_torrentInfo;
324 PathList m_filePaths;
325 QHash<lt::file_index_t, int> m_indexMap;
326 QVector<DownloadPriority> m_filePriorities;
327 QBitArray m_completedFiles;
328 SpeedMonitor m_payloadRateMonitor;
330 InfoHash m_infoHash;
332 // m_moveFinishedTriggers is activated only when the following conditions are met:
333 // all file rename jobs complete, all file move jobs complete
334 QQueue<EventTrigger> m_moveFinishedTriggers;
335 int m_renameCount = 0;
336 bool m_storageIsMoving = false;
338 QQueue<EventTrigger> m_statusUpdatedTriggers;
340 MaintenanceJob m_maintenanceJob = MaintenanceJob::None;
342 QVector<TrackerEntry> m_trackerEntries;
343 QVector<QUrl> m_urlSeeds;
344 FileErrorInfo m_lastFileError;
346 // Persistent data
347 QString m_name;
348 Path m_savePath;
349 Path m_downloadPath;
350 QString m_category;
351 TagSet m_tags;
352 qreal m_ratioLimit;
353 int m_seedingTimeLimit;
354 int m_inactiveSeedingTimeLimit;
355 TorrentOperatingMode m_operatingMode;
356 TorrentContentLayout m_contentLayout;
357 bool m_hasFinishedStatus;
358 bool m_hasMissingFiles = false;
359 bool m_hasFirstLastPiecePriority = false;
360 bool m_useAutoTMM;
361 bool m_isStopped;
362 StopCondition m_stopCondition = StopCondition::None;
364 bool m_unchecked = false;
366 lt::add_torrent_params m_ltAddTorrentParams;
368 int m_downloadLimit = 0;
369 int m_uploadLimit = 0;
371 QBitArray m_pieces;
372 QVector<std::int64_t> m_filesProgress;