1 /* 2 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 3 SPDX-FileCopyrightText: 2005 Ivan Vasic <ivasic@gmail.com> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 #ifndef BTTORRENTCONTROL_H 8 #define BTTORRENTCONTROL_H 9 10 #include <QDateTime> 11 #include <QObject> 12 #include <QTimer> 13 #include <QUrl> 14 15 #include "globals.h" 16 #include "torrent.h" 17 #include <interfaces/torrentinterface.h> 18 #include <interfaces/trackerslist.h> 19 #include <ktorrent_export.h> 20 #include <util/timer.h> 21 22 class QStringList; 23 class QString; 24 class KJob; 25 26 namespace bt 27 { 28 class StatsFile; 29 class Choker; 30 class PeerSourceManager; 31 class ChunkManager; 32 class PeerManager; 33 class Downloader; 34 class Uploader; 35 class Peer; 36 class BitSet; 37 class QueueManagerInterface; 38 class TimeEstimator; 39 class WaitJob; 40 class MonitorInterface; 41 class ChunkSelectorFactoryInterface; 42 class CacheFactory; 43 class JobQueue; 44 class DataCheckerJob; 45 46 /** 47 * @author Joris Guisson 48 * @brief Controls just about everything 49 * 50 * This is the interface which any user gets to deal with. 51 * This class controls the uploading, downloading, choking, 52 * updating the tracker and chunk management. 53 */ 54 class KTORRENT_EXPORT TorrentControl : public TorrentInterface, public FilePriorityListener 55 { 56 Q_OBJECT 57 public: 58 TorrentControl(); 59 ~TorrentControl() override; 60 61 /// Get the Torrent. getTorrent()62 const Torrent &getTorrent() const 63 { 64 return *tor; 65 } 66 67 /** 68 * Initialize the TorrentControl. 69 * @param qman The QueueManager 70 * @param data The data of the torrent 71 * @param tmpdir The directory to store temporary data 72 * @param datadir The directory to store the actual file(s) 73 * (only used the first time we load a torrent) 74 * @throw Error when something goes wrong 75 */ 76 void init(QueueManagerInterface *qman, const QByteArray &data, const QString &tmpdir, const QString &datadir); 77 78 /// Tell the TorrentControl obj to preallocate diskspace in the next update setPreallocateDiskSpace(bool pa)79 void setPreallocateDiskSpace(bool pa) 80 { 81 prealloc = pa; 82 } 83 84 /// Test if the torrent has existing files, only works the first time a torrent is loaded 85 bool hasExistingFiles() const; 86 87 const BitSet &downloadedChunksBitSet() const override; 88 const BitSet &availableChunksBitSet() const override; 89 const BitSet &excludedChunksBitSet() const override; 90 const BitSet &onlySeedChunksBitSet() const override; 91 bool changeTorDir(const QString &new_dir) override; 92 bool changeOutputDir(const QString &new_dir, int flags) override; 93 void rollback() override; 94 void setDisplayName(const QString &n) override; 95 TrackersList *getTrackersList() override; 96 const TrackersList *getTrackersList() const override; getDataDir()97 QString getDataDir() const override 98 { 99 return outputdir; 100 } getTorDir()101 QString getTorDir() const override 102 { 103 return tordir; 104 } 105 void setMonitor(MonitorInterface *tmo) override; 106 Uint32 getRunningTimeDL() const override; 107 Uint32 getRunningTimeUL() const override; 108 Uint32 getNumFiles() const override; 109 TorrentFileInterface &getTorrentFile(Uint32 index) override; 110 const TorrentFileInterface &getTorrentFile(Uint32 index) const override; 111 bool moveTorrentFiles(const QMap<TorrentFileInterface *, QString> &files) override; 112 void recreateMissingFiles() override; 113 void dndMissingFiles() override; 114 TorrentFileStream::Ptr createTorrentFileStream(bt::Uint32 index, bool streaming_mode, QObject *parent) override; 115 void addPeerSource(PeerSource *ps) override; 116 void removePeerSource(PeerSource *ps) override; 117 const QTextCodec *getTextCodec() const override; 118 void changeTextCodec(QTextCodec *tc) override; 119 Uint32 getNumWebSeeds() const override; 120 const WebSeedInterface *getWebSeed(Uint32 i) const override; 121 WebSeedInterface *getWebSeed(Uint32 i) override; 122 bool addWebSeed(const QUrl &url) override; 123 bool removeWebSeed(const QUrl &url) override; 124 bool readyForPreview() const override; 125 bool isMultimedia() const override; 126 void markExistingFilesAsDownloaded() override; getPriority()127 int getPriority() const override 128 { 129 return istats.priority; 130 } 131 void setPriority(int p) override; 132 bool overMaxRatio() override; 133 void setMaxShareRatio(float ratio) override; getMaxShareRatio()134 float getMaxShareRatio() const override 135 { 136 return stats.max_share_ratio; 137 } 138 bool overMaxSeedTime() override; 139 void setMaxSeedTime(float hours) override; getMaxSeedTime()140 float getMaxSeedTime() const override 141 { 142 return stats.max_seed_time; 143 } 144 void setAllowedToStart(bool on) override; 145 void setQueued(bool queued) override; 146 void setChunkSelector(ChunkSelectorInterface *csel) override; 147 void networkUp() override; 148 bool announceAllowed() override; 149 Job *startDataCheck(bool auto_import, bt::Uint32 from, bt::Uint32 to) override; 150 bool hasMissingFiles(QStringList &sl) override; 151 bool isStorageMounted(QStringList &missing) override; 152 Uint32 getNumDHTNodes() const override; 153 const DHTNode &getDHTNode(Uint32 i) const override; 154 void deleteDataFiles() override; 155 const bt::PeerID &getOwnPeerID() const override; 156 QString getComments() const override; getJobQueue()157 const JobQueue *getJobQueue() const override 158 { 159 return job_queue; 160 } 161 bool isFeatureEnabled(TorrentFeature tf) override; 162 void setFeatureEnabled(TorrentFeature tf, bool on) override; 163 bool checkDiskSpace(bool emit_sig = true) override; 164 void setTrafficLimits(Uint32 up, Uint32 down) override; 165 void getTrafficLimits(Uint32 &up, Uint32 &down) override; 166 void setAssuredSpeeds(Uint32 up, Uint32 down) override; 167 void getAssuredSpeeds(Uint32 &up, Uint32 &down) override; 168 const SHA1Hash &getInfoHash() const override; 169 void setUserModifiedFileName(const QString &n) override; 170 int getETA() override; setMoveWhenCompletedDir(const QString & dir)171 void setMoveWhenCompletedDir(const QString &dir) override 172 { 173 completed_dir = dir; 174 saveStats(); 175 } getMoveWhenCompletedDir()176 QString getMoveWhenCompletedDir() const override 177 { 178 return completed_dir; 179 } 180 void setSuperSeeding(bool on) override; 181 182 /// Create all the necessary files 183 void createFiles(); 184 185 /// Get the PeerManager 186 const PeerManager *getPeerMgr() const; 187 188 /** 189 * Set a custom chunk selector factory (needs to be done for init is called) 190 * Note: TorrentControl does not take ownership 191 */ 192 void setChunkSelectorFactory(ChunkSelectorFactoryInterface *csfi); 193 194 /// Set a custom Cache factory 195 void setCacheFactory(CacheFactory *cf); 196 197 /// Get time in msec since the last Stats file save on disk getStatsSyncElapsedTime()198 TimeStamp getStatsSyncElapsedTime() 199 { 200 return stats_save_timer.getElapsedSinceUpdate(); 201 } 202 203 public: 204 /** 205 * Update the object, should be called periodically. 206 */ 207 void update() override; 208 209 /** 210 * Pause the torrent. 211 */ 212 void pause() override; 213 214 /** 215 * Unpause the torrent. 216 */ 217 void unpause() override; 218 219 /** 220 * Start the download of the torrent. 221 */ 222 void start() override; 223 224 /** 225 * Stop the download, closes all connections. 226 * @param wjob WaitJob to wait at exit for the completion of stopped requests 227 */ 228 void stop(WaitJob *wjob = nullptr) override; 229 230 /** 231 * Update the tracker, this should normally handled internally. 232 * We leave it public so that the user can do a manual announce. 233 */ 234 void updateTracker() override; 235 236 /** 237 * Scrape the tracker. 238 * */ 239 void scrapeTracker() override; 240 241 /** 242 * A scrape has finished on the tracker. 243 * */ 244 void trackerScrapeDone(); 245 246 /** 247 * Enable or disable data check upon completion 248 * @param on 249 */ setDataCheckWhenCompleted(bool on)250 static void setDataCheckWhenCompleted(bool on) 251 { 252 completed_datacheck = on; 253 } 254 255 /** 256 * Set the minimum amount of diskspace in MB. When there is less then this free, torrents will be stopped. 257 * @param m 258 */ setMinimumDiskSpace(Uint32 m)259 static void setMinimumDiskSpace(Uint32 m) 260 { 261 min_diskspace = m; 262 } 263 264 protected: 265 /// Called when a data check is finished by DataCheckerJob 266 void afterDataCheck(DataCheckerJob *job, const BitSet &result); 267 void beforeDataCheck(); 268 void preallocFinished(const QString &error, bool completed); 269 void allJobsDone(); 270 bool preallocate(); 271 272 private: 273 void onNewPeer(Peer *p); 274 void onPeerRemoved(Peer *p); 275 void doChoking(); 276 void onIOError(const QString &msg); 277 /// Update the stats of the torrent. 278 void updateStats(); 279 void corrupted(Uint32 chunk); 280 void moveDataFilesFinished(KJob *j); 281 void moveDataFilesWithMapFinished(KJob *j); 282 void downloaded(Uint32 chunk); 283 void moveToCompletedDir(); 284 void emitFinished(); 285 286 void updateTracker(const QString &ev, bool last_succes = true); 287 void updateStatus() override; 288 void saveStats(); 289 void loadStats(); 290 void loadOutputDir(); 291 void loadEncoding(); 292 void getSeederInfo(Uint32 &total, Uint32 &connected_to) const; 293 void getLeecherInfo(Uint32 &total, Uint32 &connected_to) const; 294 void continueStart(); 295 void handleError(const QString &err) override; 296 void initInternal(QueueManagerInterface *qman, const QString &tmpdir, const QString &ddir); 297 void checkExisting(QueueManagerInterface *qman); 298 void setupDirs(const QString &tmpdir, const QString &ddir); 299 void setupStats(); 300 void setupData(); 301 void setUploadProps(Uint32 limit, Uint32 rate); 302 void setDownloadProps(Uint32 limit, Uint32 rate); 303 void downloadPriorityChanged(TorrentFile *tf, Priority newpriority, Priority oldpriority) override; 304 void updateRunningTimes(); 305 306 Q_SIGNALS: 307 void dataCheckFinished(); 308 309 private: 310 JobQueue *job_queue; 311 QueueManagerInterface *m_qman; 312 Torrent *tor; 313 PeerSourceManager *psman; 314 ChunkManager *cman; 315 PeerManager *pman; 316 Downloader *downloader; 317 Uploader *uploader; 318 Choker *choke; 319 TimeEstimator *m_eta; 320 MonitorInterface *tmon; 321 CacheFactory *cache_factory; 322 QString move_data_files_destination_path; 323 Timer choker_update_timer; 324 Timer stats_save_timer; 325 Timer stalled_timer; 326 Timer wanted_update_timer; 327 QString tordir; 328 QString old_tordir; 329 QString outputdir; 330 QString error_msg; 331 QString completed_dir; 332 bool prealloc; 333 TimeStamp last_diskspace_check; 334 bool loading_stats; 335 336 struct InternalStats { 337 QDateTime time_started_dl; 338 QDateTime time_started_ul; 339 Uint32 running_time_dl; 340 Uint32 running_time_ul; 341 Uint64 prev_bytes_dl; 342 Uint64 prev_bytes_ul; 343 Uint64 session_bytes_uploaded; 344 bool io_error; 345 bool custom_output_name; 346 Uint16 port; 347 int priority; 348 bool dht_on; 349 bool diskspace_warning_emitted; 350 }; 351 352 Uint32 upload_gid; // group ID for upload 353 Uint32 upload_limit; 354 Uint32 download_gid; // group ID for download 355 Uint32 download_limit; 356 357 Uint32 assured_download_speed; 358 Uint32 assured_upload_speed; 359 360 InternalStats istats; 361 StatsFile *stats_file; 362 363 TorrentFileStream::WPtr stream; 364 365 static bool completed_datacheck; 366 static Uint32 min_diskspace; 367 368 friend class DataCheckerJob; 369 friend class PreallocationJob; 370 friend class JobQueue; 371 }; 372 373 } 374 375 #endif 376