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