1 /* 2 * Bittorrent Client using Qt and libtorrent. 3 * Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> 4 * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> 5 * 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. 10 * 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. 15 * 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. 19 * 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. 28 */ 29 30 #pragma once 31 32 #include <functional> 33 34 #include <libtorrent/add_torrent_params.hpp> 35 #include <libtorrent/fwd.hpp> 36 #include <libtorrent/socket.hpp> 37 #include <libtorrent/torrent_handle.hpp> 38 #include <libtorrent/torrent_status.hpp> 39 40 #include <QDateTime> 41 #include <QHash> 42 #include <QMap> 43 #include <QObject> 44 #include <QQueue> 45 #include <QSet> 46 #include <QString> 47 #include <QVector> 48 49 #include "infohash.h" 50 #include "speedmonitor.h" 51 #include "torrent.h" 52 #include "torrentinfo.h" 53 54 namespace BitTorrent 55 { 56 class Session; 57 struct AddTorrentParams; 58 59 struct LoadTorrentParams 60 { 61 lt::add_torrent_params ltAddTorrentParams {}; 62 63 QString name; 64 QString category; 65 QSet<QString> tags; 66 QString savePath; 67 TorrentContentLayout contentLayout = TorrentContentLayout::Original; 68 bool firstLastPiecePriority = false; 69 bool hasSeedStatus = false; 70 bool forced = false; 71 bool paused = false; 72 73 qreal ratioLimit = Torrent::USE_GLOBAL_RATIO; 74 int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME; 75 76 bool restored = false; // is existing torrent job? 77 }; 78 79 enum class MoveStorageMode 80 { 81 KeepExistingFiles, 82 Overwrite 83 }; 84 85 enum class MaintenanceJob 86 { 87 None, 88 HandleMetadata 89 }; 90 91 struct FileErrorInfo 92 { 93 lt::error_code error; 94 lt::operation_t operation; 95 }; 96 97 class TorrentImpl final : public QObject, public Torrent 98 { 99 Q_DISABLE_COPY(TorrentImpl) 100 Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentImpl) 101 102 public: 103 TorrentImpl(Session *session, lt::session *nativeSession 104 , const lt::torrent_handle &nativeHandle, const LoadTorrentParams ¶ms); 105 ~TorrentImpl() override; 106 107 bool isValid() const; 108 109 InfoHash infoHash() const override; 110 QString name() const override; 111 QDateTime creationDate() const override; 112 QString creator() const override; 113 QString comment() const override; 114 bool isPrivate() const override; 115 qlonglong totalSize() const override; 116 qlonglong wantedSize() const override; 117 qlonglong completedSize() const override; 118 qlonglong pieceLength() const override; 119 qlonglong wastedSize() const override; 120 QString currentTracker() const override; 121 122 QString savePath(bool actual = false) const override; 123 QString rootPath(bool actual = false) const override; 124 QString contentPath(bool actual = false) const override; 125 126 bool useTempPath() const override; 127 128 bool isAutoTMMEnabled() const override; 129 void setAutoTMMEnabled(bool enabled) override; 130 QString category() const override; 131 bool belongsToCategory(const QString &category) const override; 132 bool setCategory(const QString &category) override; 133 134 QSet<QString> tags() const override; 135 bool hasTag(const QString &tag) const override; 136 bool addTag(const QString &tag) override; 137 bool removeTag(const QString &tag) override; 138 void removeAllTags() override; 139 140 int filesCount() const override; 141 int piecesCount() const override; 142 int piecesHave() const override; 143 qreal progress() const override; 144 QDateTime addedTime() const override; 145 qreal ratioLimit() const override; 146 int seedingTimeLimit() const override; 147 148 QString filePath(int index) const override; 149 QString fileName(int index) const override; 150 qlonglong fileSize(int index) const override; 151 QStringList absoluteFilePaths() const override; 152 QVector<DownloadPriority> filePriorities() const override; 153 154 TorrentInfo info() const override; 155 bool isSeed() const override; 156 bool isPaused() const override; 157 bool isQueued() const override; 158 bool isForced() const override; 159 bool isChecking() const override; 160 bool isDownloading() const override; 161 bool isUploading() const override; 162 bool isCompleted() const override; 163 bool isActive() const override; 164 bool isInactive() const override; 165 bool isErrored() const override; 166 bool isSequentialDownload() const override; 167 bool hasFirstLastPiecePriority() const override; 168 TorrentState state() const override; 169 bool hasMetadata() const override; 170 bool hasMissingFiles() const override; 171 bool hasError() const override; 172 bool hasFilteredPieces() const override; 173 int queuePosition() const override; 174 QVector<TrackerEntry> trackers() const override; 175 QVector<QUrl> urlSeeds() const override; 176 QString error() const override; 177 qlonglong totalDownload() const override; 178 qlonglong totalUpload() const override; 179 qlonglong activeTime() const override; 180 qlonglong finishedTime() const override; 181 qlonglong seedingTime() const override; 182 qlonglong eta() const override; 183 QVector<qreal> filesProgress() const override; 184 int seedsCount() const override; 185 int peersCount() const override; 186 int leechsCount() const override; 187 int totalSeedsCount() const override; 188 int totalPeersCount() const override; 189 int totalLeechersCount() const override; 190 int completeCount() const override; 191 int incompleteCount() const override; 192 QDateTime lastSeenComplete() const override; 193 QDateTime completedTime() const override; 194 qlonglong timeSinceUpload() const override; 195 qlonglong timeSinceDownload() const override; 196 qlonglong timeSinceActivity() const override; 197 int downloadLimit() const override; 198 int uploadLimit() const override; 199 bool superSeeding() const override; 200 bool isDHTDisabled() const override; 201 bool isPEXDisabled() const override; 202 bool isLSDDisabled() const override; 203 QVector<PeerInfo> peers() const override; 204 QBitArray pieces() const override; 205 QBitArray downloadingPieces() const override; 206 QVector<int> pieceAvailability() const override; 207 qreal distributedCopies() const override; 208 qreal maxRatio() const override; 209 int maxSeedingTime() const override; 210 qreal realRatio() const override; 211 int uploadPayloadRate() const override; 212 int downloadPayloadRate() const override; 213 qlonglong totalPayloadUpload() const override; 214 qlonglong totalPayloadDownload() const override; 215 int connectionsCount() const override; 216 int connectionsLimit() const override; 217 qlonglong nextAnnounce() const override; 218 QVector<qreal> availableFileFractions() const override; 219 220 void setName(const QString &name) override; 221 void setSequentialDownload(bool enable) override; 222 void setFirstLastPiecePriority(bool enabled) override; 223 void pause() override; 224 void resume(TorrentOperatingMode mode = TorrentOperatingMode::AutoManaged) override; 225 void move(QString path) override; 226 void forceReannounce(int index = -1) override; 227 void forceDHTAnnounce() override; 228 void forceRecheck() override; 229 void renameFile(int index, const QString &path) override; 230 void prioritizeFiles(const QVector<DownloadPriority> &priorities) override; 231 void setRatioLimit(qreal limit) override; 232 void setSeedingTimeLimit(int limit) override; 233 void setUploadLimit(int limit) override; 234 void setDownloadLimit(int limit) override; 235 void setSuperSeeding(bool enable) override; 236 void setDHTDisabled(bool disable) override; 237 void setPEXDisabled(bool disable) override; 238 void setLSDDisabled(bool disable) override; 239 void flushCache() const override; 240 void addTrackers(const QVector<TrackerEntry> &trackers) override; 241 void replaceTrackers(const QVector<TrackerEntry> &trackers) override; 242 void addUrlSeeds(const QVector<QUrl> &urlSeeds) override; 243 void removeUrlSeeds(const QVector<QUrl> &urlSeeds) override; 244 bool connectPeer(const PeerAddress &peerAddress) override; 245 void clearPeers() override; 246 247 QString createMagnetURI() const override; 248 249 bool needSaveResumeData() const; 250 251 // Session interface 252 lt::torrent_handle nativeHandle() const; 253 254 void handleAlert(const lt::alert *a); 255 void handleStateUpdate(const lt::torrent_status &nativeStatus); 256 void handleTempPathChanged(); 257 void handleCategorySavePathChanged(); 258 void handleAppendExtensionToggled(); 259 void saveResumeData(); 260 void handleMoveStorageJobFinished(bool hasOutstandingJob); 261 void fileSearchFinished(const QString &savePath, const QStringList &fileNames); 262 263 QString actualStorageLocation() const; 264 265 private: 266 typedef std::function<void ()> EventTrigger; 267 268 void updateStatus(); 269 void updateStatus(const lt::torrent_status &nativeStatus); 270 void updateState(); 271 272 void handleFastResumeRejectedAlert(const lt::fastresume_rejected_alert *p); 273 void handleFileCompletedAlert(const lt::file_completed_alert *p); 274 void handleFileErrorAlert(const lt::file_error_alert *p); 275 void handleFileRenamedAlert(const lt::file_renamed_alert *p); 276 void handleFileRenameFailedAlert(const lt::file_rename_failed_alert *p); 277 void handleMetadataReceivedAlert(const lt::metadata_received_alert *p); 278 void handlePerformanceAlert(const lt::performance_alert *p) const; 279 void handleSaveResumeDataAlert(const lt::save_resume_data_alert *p); 280 void handleSaveResumeDataFailedAlert(const lt::save_resume_data_failed_alert *p); 281 void handleTorrentCheckedAlert(const lt::torrent_checked_alert *p); 282 void handleTorrentFinishedAlert(const lt::torrent_finished_alert *p); 283 void handleTorrentPausedAlert(const lt::torrent_paused_alert *p); 284 void handleTorrentResumedAlert(const lt::torrent_resumed_alert *p); 285 void handleTrackerErrorAlert(const lt::tracker_error_alert *p); 286 void handleTrackerReplyAlert(const lt::tracker_reply_alert *p); 287 void handleTrackerWarningAlert(const lt::tracker_warning_alert *p); 288 289 bool isMoveInProgress() const; 290 291 void setAutoManaged(bool enable); 292 293 void adjustActualSavePath(); 294 void adjustActualSavePath_impl(); 295 void move_impl(QString path, MoveStorageMode mode); 296 void moveStorage(const QString &newPath, MoveStorageMode mode); 297 void manageIncompleteFiles(); 298 void applyFirstLastPiecePriority(bool enabled, const QVector<DownloadPriority> &updatedFilePrio = {}); 299 300 void endReceivedMetadataHandling(const QString &savePath, const QStringList &fileNames); 301 void reload(); 302 303 Session *const m_session; 304 lt::session *m_nativeSession; 305 lt::torrent_handle m_nativeHandle; 306 lt::torrent_status m_nativeStatus; 307 TorrentState m_state = TorrentState::Unknown; 308 TorrentInfo m_torrentInfo; 309 SpeedMonitor m_speedMonitor; 310 311 InfoHash m_infoHash; 312 313 // m_moveFinishedTriggers is activated only when the following conditions are met: 314 // all file rename jobs complete, all file move jobs complete 315 QQueue<EventTrigger> m_moveFinishedTriggers; 316 int m_renameCount = 0; 317 bool m_storageIsMoving = false; 318 319 MaintenanceJob m_maintenanceJob = MaintenanceJob::None; 320 321 // Until libtorrent provide an "old_name" field in `file_renamed_alert` 322 // we will rely on this workaround to remove empty leftover folders 323 QHash<lt::file_index_t, QVector<QString>> m_oldPath; 324 325 FileErrorInfo m_lastFileError; 326 QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts; 327 328 // Persistent data 329 QString m_name; 330 QString m_savePath; 331 QString m_category; 332 QSet<QString> m_tags; 333 qreal m_ratioLimit; 334 int m_seedingTimeLimit; 335 TorrentOperatingMode m_operatingMode; 336 TorrentContentLayout m_contentLayout; 337 bool m_hasSeedStatus; 338 bool m_fastresumeDataRejected = false; 339 bool m_hasMissingFiles = false; 340 bool m_hasFirstLastPiecePriority = false; 341 bool m_useAutoTMM; 342 bool m_isStopped; 343 344 bool m_unchecked = false; 345 346 lt::add_torrent_params m_ltAddTorrentParams; 347 }; 348 } 349