File indexing completed on 2024-06-02 05:05:32
0001 /* 0002 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 0003 SPDX-FileCopyrightText: 2005 Ivan Vasic <ivasic@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 #ifndef BTTORRENTCONTROL_H 0008 #define BTTORRENTCONTROL_H 0009 0010 #include <QDateTime> 0011 #include <QObject> 0012 #include <QStringList> 0013 #include <QTimer> 0014 #include <QUrl> 0015 0016 #include "globals.h" 0017 #include "torrent.h" 0018 #include <interfaces/torrentinterface.h> 0019 #include <interfaces/trackerslist.h> 0020 #include <ktorrent_export.h> 0021 #include <util/timer.h> 0022 0023 class QString; 0024 class KJob; 0025 0026 namespace bt 0027 { 0028 class StatsFile; 0029 class Choker; 0030 class PeerSourceManager; 0031 class ChunkManager; 0032 class PeerManager; 0033 class Downloader; 0034 class Uploader; 0035 class Peer; 0036 class BitSet; 0037 class QueueManagerInterface; 0038 class TimeEstimator; 0039 class WaitJob; 0040 class MonitorInterface; 0041 class ChunkSelectorFactoryInterface; 0042 class CacheFactory; 0043 class JobQueue; 0044 class DataCheckerJob; 0045 0046 /** 0047 * @author Joris Guisson 0048 * @brief Controls just about everything 0049 * 0050 * This is the interface which any user gets to deal with. 0051 * This class controls the uploading, downloading, choking, 0052 * updating the tracker and chunk management. 0053 */ 0054 class KTORRENT_EXPORT TorrentControl : public TorrentInterface, public FilePriorityListener 0055 { 0056 Q_OBJECT 0057 public: 0058 TorrentControl(); 0059 ~TorrentControl() override; 0060 0061 /// Get the Torrent. 0062 const Torrent &getTorrent() const 0063 { 0064 return *tor; 0065 } 0066 0067 /** 0068 * Initialize the TorrentControl. 0069 * @param qman The QueueManager 0070 * @param data The data of the torrent 0071 * @param tmpdir The directory to store temporary data 0072 * @param datadir The directory to store the actual file(s) 0073 * (only used the first time we load a torrent) 0074 * @throw Error when something goes wrong 0075 */ 0076 void init(QueueManagerInterface *qman, const QByteArray &data, const QString &tmpdir, const QString &datadir); 0077 0078 /// Tell the TorrentControl obj to preallocate diskspace in the next update 0079 void setPreallocateDiskSpace(bool pa) 0080 { 0081 prealloc = pa; 0082 } 0083 0084 /// Test if the torrent has existing files, only works the first time a torrent is loaded 0085 bool hasExistingFiles() const; 0086 0087 const BitSet &downloadedChunksBitSet() const override; 0088 const BitSet &availableChunksBitSet() const override; 0089 const BitSet &excludedChunksBitSet() const override; 0090 const BitSet &onlySeedChunksBitSet() const override; 0091 bool changeTorDir(const QString &new_dir) override; 0092 bool changeOutputDir(const QString &new_dir, int flags) override; 0093 void rollback() override; 0094 void setDisplayName(const QString &n) override; 0095 TrackersList *getTrackersList() override; 0096 const TrackersList *getTrackersList() const override; 0097 QString getDataDir() const override 0098 { 0099 return outputdir; 0100 } 0101 QString getTorDir() const override 0102 { 0103 return tordir; 0104 } 0105 void setMonitor(MonitorInterface *tmo) override; 0106 Uint32 getRunningTimeDL() const override; 0107 Uint32 getRunningTimeUL() const override; 0108 Uint32 getNumFiles() const override; 0109 TorrentFileInterface &getTorrentFile(Uint32 index) override; 0110 const TorrentFileInterface &getTorrentFile(Uint32 index) const override; 0111 bool moveTorrentFiles(const QMap<TorrentFileInterface *, QString> &files) override; 0112 void recreateMissingFiles() override; 0113 void dndMissingFiles() override; 0114 TorrentFileStream::Ptr createTorrentFileStream(bt::Uint32 index, bool streaming_mode, QObject *parent) override; 0115 void addPeerSource(PeerSource *ps) override; 0116 void removePeerSource(PeerSource *ps) override; 0117 const QTextCodec *getTextCodec() const override; 0118 void changeTextCodec(QTextCodec *tc) override; 0119 Uint32 getNumWebSeeds() const override; 0120 const WebSeedInterface *getWebSeed(Uint32 i) const override; 0121 WebSeedInterface *getWebSeed(Uint32 i) override; 0122 bool addWebSeed(const QUrl &url) override; 0123 bool removeWebSeed(const QUrl &url) override; 0124 bool readyForPreview() const override; 0125 bool isMultimedia() const override; 0126 void markExistingFilesAsDownloaded() override; 0127 int getPriority() const override 0128 { 0129 return istats.priority; 0130 } 0131 void setPriority(int p) override; 0132 bool overMaxRatio() override; 0133 void setMaxShareRatio(float ratio) override; 0134 float getMaxShareRatio() const override 0135 { 0136 return stats.max_share_ratio; 0137 } 0138 bool overMaxSeedTime() override; 0139 void setMaxSeedTime(float hours) override; 0140 float getMaxSeedTime() const override 0141 { 0142 return stats.max_seed_time; 0143 } 0144 void setAllowedToStart(bool on) override; 0145 void setQueued(bool queued) override; 0146 void setChunkSelector(ChunkSelectorInterface *csel) override; 0147 void networkUp() override; 0148 bool announceAllowed() override; 0149 Job *startDataCheck(bool auto_import, bt::Uint32 from, bt::Uint32 to) override; 0150 bool hasMissingFiles(QStringList &sl) override; 0151 bool isStorageMounted(QStringList &missing) override; 0152 Uint32 getNumDHTNodes() const override; 0153 const DHTNode &getDHTNode(Uint32 i) const override; 0154 void deleteDataFiles() override; 0155 const bt::PeerID &getOwnPeerID() const override; 0156 QString getComments() const override; 0157 const JobQueue *getJobQueue() const override 0158 { 0159 return job_queue; 0160 } 0161 bool isFeatureEnabled(TorrentFeature tf) override; 0162 void setFeatureEnabled(TorrentFeature tf, bool on) override; 0163 bool checkDiskSpace(bool emit_sig = true) override; 0164 void setTrafficLimits(Uint32 up, Uint32 down) override; 0165 void getTrafficLimits(Uint32 &up, Uint32 &down) override; 0166 void setAssuredSpeeds(Uint32 up, Uint32 down) override; 0167 void getAssuredSpeeds(Uint32 &up, Uint32 &down) override; 0168 const SHA1Hash &getInfoHash() const override; 0169 void setUserModifiedFileName(const QString &n) override; 0170 int getETA() override; 0171 void setMoveWhenCompletedDir(const QString &dir) override 0172 { 0173 completed_dir = dir; 0174 saveStats(); 0175 } 0176 QString getMoveWhenCompletedDir() const override 0177 { 0178 return completed_dir; 0179 } 0180 void setSuperSeeding(bool on) override; 0181 0182 /// Create all the necessary files 0183 void createFiles(); 0184 0185 /// Get the PeerManager 0186 const PeerManager *getPeerMgr() const; 0187 0188 /** 0189 * Set a custom chunk selector factory (needs to be done for init is called) 0190 * Note: TorrentControl does not take ownership 0191 */ 0192 void setChunkSelectorFactory(ChunkSelectorFactoryInterface *csfi); 0193 0194 /// Set a custom Cache factory 0195 void setCacheFactory(CacheFactory *cf); 0196 0197 /// Get time in msec since the last Stats file save on disk 0198 TimeStamp getStatsSyncElapsedTime() 0199 { 0200 return stats_save_timer.getElapsedSinceUpdate(); 0201 } 0202 0203 public: 0204 /** 0205 * Update the object, should be called periodically. 0206 */ 0207 void update() override; 0208 0209 /** 0210 * Pause the torrent. 0211 */ 0212 void pause() override; 0213 0214 /** 0215 * Unpause the torrent. 0216 */ 0217 void unpause() override; 0218 0219 /** 0220 * Start the download of the torrent. 0221 */ 0222 void start() override; 0223 0224 /** 0225 * Stop the download, closes all connections. 0226 * @param wjob WaitJob to wait at exit for the completion of stopped requests 0227 */ 0228 void stop(WaitJob *wjob = nullptr) override; 0229 0230 /** 0231 * Update the tracker, this should normally handled internally. 0232 * We leave it public so that the user can do a manual announce. 0233 */ 0234 void updateTracker() override; 0235 0236 /** 0237 * Scrape the tracker. 0238 * */ 0239 void scrapeTracker() override; 0240 0241 /** 0242 * A scrape has finished on the tracker. 0243 * */ 0244 void trackerScrapeDone(); 0245 0246 /** 0247 * Enable or disable data check upon completion 0248 * @param on 0249 */ 0250 static void setDataCheckWhenCompleted(bool on) 0251 { 0252 completed_datacheck = on; 0253 } 0254 0255 /** 0256 * Set the minimum amount of diskspace in MB. When there is less then this free, torrents will be stopped. 0257 * @param m 0258 */ 0259 static void setMinimumDiskSpace(Uint32 m) 0260 { 0261 min_diskspace = m; 0262 } 0263 0264 protected: 0265 /// Called when a data check is finished by DataCheckerJob 0266 void afterDataCheck(DataCheckerJob *job, const BitSet &result); 0267 void beforeDataCheck(); 0268 void preallocFinished(const QString &error, bool completed); 0269 void allJobsDone(); 0270 bool preallocate(); 0271 0272 private: 0273 void onNewPeer(Peer *p); 0274 void onPeerRemoved(Peer *p); 0275 void doChoking(); 0276 void onIOError(const QString &msg); 0277 /// Update the stats of the torrent. 0278 void updateStats(); 0279 void corrupted(Uint32 chunk); 0280 void moveDataFilesFinished(KJob *j); 0281 void moveDataFilesWithMapFinished(KJob *j); 0282 void downloaded(Uint32 chunk); 0283 void moveToCompletedDir(); 0284 void emitFinished(); 0285 0286 void updateTracker(const QString &ev, bool last_succes = true); 0287 void updateStatus() override; 0288 void saveStats(); 0289 void loadStats(); 0290 void loadOutputDir(); 0291 void loadEncoding(); 0292 void getSeederInfo(Uint32 &total, Uint32 &connected_to) const; 0293 void getLeecherInfo(Uint32 &total, Uint32 &connected_to) const; 0294 void continueStart(); 0295 void handleError(const QString &err) override; 0296 void initInternal(QueueManagerInterface *qman, const QString &tmpdir, const QString &ddir); 0297 void checkExisting(QueueManagerInterface *qman); 0298 void setupDirs(const QString &tmpdir, const QString &ddir); 0299 void setupStats(); 0300 void setupData(); 0301 void setUploadProps(Uint32 limit, Uint32 rate); 0302 void setDownloadProps(Uint32 limit, Uint32 rate); 0303 void downloadPriorityChanged(TorrentFile *tf, Priority newpriority, Priority oldpriority) override; 0304 void updateRunningTimes(); 0305 0306 Q_SIGNALS: 0307 void dataCheckFinished(); 0308 0309 private: 0310 JobQueue *job_queue; 0311 QueueManagerInterface *m_qman; 0312 Torrent *tor; 0313 PeerSourceManager *psman; 0314 ChunkManager *cman; 0315 PeerManager *pman; 0316 Downloader *downloader; 0317 Uploader *uploader; 0318 Choker *choke; 0319 TimeEstimator *m_eta; 0320 MonitorInterface *tmon; 0321 CacheFactory *cache_factory; 0322 QString move_data_files_destination_path; 0323 Timer choker_update_timer; 0324 Timer stats_save_timer; 0325 Timer stalled_timer; 0326 Timer wanted_update_timer; 0327 QString tordir; 0328 QString old_tordir; 0329 QString outputdir; 0330 QString error_msg; 0331 QString completed_dir; 0332 bool prealloc; 0333 TimeStamp last_diskspace_check; 0334 bool loading_stats; 0335 0336 struct InternalStats { 0337 QDateTime time_started_dl; 0338 QDateTime time_started_ul; 0339 Uint32 running_time_dl; 0340 Uint32 running_time_ul; 0341 Uint64 prev_bytes_dl; 0342 Uint64 prev_bytes_ul; 0343 Uint64 session_bytes_uploaded; 0344 bool io_error; 0345 bool custom_output_name; 0346 Uint16 port; 0347 int priority; 0348 bool dht_on; 0349 bool diskspace_warning_emitted; 0350 }; 0351 0352 Uint32 upload_gid; // group ID for upload 0353 Uint32 upload_limit; 0354 Uint32 download_gid; // group ID for download 0355 Uint32 download_limit; 0356 0357 Uint32 assured_download_speed; 0358 Uint32 assured_upload_speed; 0359 0360 InternalStats istats; 0361 StatsFile *stats_file; 0362 0363 TorrentFileStream::WPtr stream; 0364 0365 static bool completed_datacheck; 0366 static Uint32 min_diskspace; 0367 0368 friend class DataCheckerJob; 0369 friend class PreallocationJob; 0370 friend class JobQueue; 0371 }; 0372 0373 } 0374 0375 #endif