/* * Bittorrent Client using Qt and libtorrent. * Copyright (C) 2015 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * In addition, as a special exception, the copyright holders give permission to * link this program with the OpenSSL project's "OpenSSL" library (or with * modified versions of it that use the same license as the "OpenSSL" library), * and distribute the linked executables. You must obey the GNU General Public * License in all respects for all of the code used other than "OpenSSL". If you * modify file(s), you may extend this exception to your version of the file(s), * but you are not obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ #ifndef BITTORRENT_SESSION_H #define BITTORRENT_SESSION_H #include #include #include #include #include #include #include #include #include #include "base/tristatebool.h" #include "base/types.h" #include "torrentinfo.h" namespace libtorrent { class session; struct torrent_handle; class entry; struct add_torrent_params; struct pe_settings; struct session_settings; struct session_status; #if LIBTORRENT_VERSION_NUM < 10100 struct proxy_settings; #else namespace aux { struct proxy_settings; } typedef aux::proxy_settings proxy_settings; #endif class alert; struct torrent_alert; struct state_update_alert; struct stats_alert; struct add_torrent_alert; struct torrent_checked_alert; struct torrent_finished_alert; struct torrent_removed_alert; struct torrent_deleted_alert; struct torrent_delete_failed_alert; struct torrent_paused_alert; struct torrent_resumed_alert; struct save_resume_data_alert; struct save_resume_data_failed_alert; struct file_renamed_alert; struct storage_moved_alert; struct storage_moved_failed_alert; struct metadata_received_alert; struct file_error_alert; struct file_completed_alert; struct tracker_error_alert; struct tracker_reply_alert; struct tracker_warning_alert; struct portmap_error_alert; struct portmap_alert; struct peer_blocked_alert; struct peer_ban_alert; struct fastresume_rejected_alert; struct url_seed_alert; struct listen_succeeded_alert; struct listen_failed_alert; struct external_ip_alert; } class QThread; class QTimer; class QStringList; class QString; class QUrl; template class QList; class FilterParserThread; class BandwidthScheduler; class Statistics; class ResumeDataSavingManager; class SettingsStorage; enum MaxRatioAction { Pause, Remove }; enum TorrentExportFolder { Regular, Finished }; namespace BitTorrent { class InfoHash; class CacheStatus; class SessionStatus; class TorrentHandle; class Tracker; class MagnetUri; class TrackerEntry; struct AddTorrentData; struct AddTorrentParams { QString name; QString category; QString savePath; bool disableTempPath = false; // e.g. for imported torrents bool sequential = false; TriStateBool addForced; TriStateBool addPaused; QVector filePriorities; // used if TorrentInfo is set bool ignoreShareRatio = false; bool skipChecking = false; }; struct TorrentStatusReport { uint nbDownloading = 0; uint nbSeeding = 0; uint nbCompleted = 0; uint nbActive = 0; uint nbInactive = 0; uint nbPaused = 0; uint nbResumed = 0; uint nbErrored = 0; }; class Session : public QObject { Q_OBJECT Q_DISABLE_COPY(Session) public: static void initInstance(); static void freeInstance(); static Session *instance(); bool isDHTEnabled() const; bool isLSDEnabled() const; bool isPexEnabled() const; bool isQueueingEnabled() const; qreal globalMaxRatio() const; bool isAppendExtensionEnabled() const; QString defaultSavePath() const; void setDefaultSavePath(QString path); QString tempPath() const; void setTempPath(QString path); bool isTempPathEnabled() const; void setTempPathEnabled(bool enabled); static bool isValidCategoryName(const QString &name); // returns category itself and all top level categories static QStringList expandCategory(const QString &category); QStringList categories() const; QString categorySavePath(const QString &categoryName) const; bool addCategory(const QString &name, const QString &savePath = ""); bool editCategory(const QString &name, const QString &savePath); bool removeCategory(const QString &name); bool isSubcategoriesEnabled() const; void setSubcategoriesEnabled(bool value); // Advanced Saving Management subsystem (ASM) // // Each torrent can be either in Simple mode or in Advanced mode // In Simple mode torrent has explicit save path // In Advanced Mode torrent has implicit save path (based on Default // save path and Category save path) // In Advanced Mode torrent save path can be changed in following cases: // 1. Default save path changed // 2. Torrent category save path changed // 3. Torrent category changed // (unless otherwise is specified) bool isASMDisabledByDefault() const; void setASMDisabledByDefault(bool value); bool isDisableASMWhenCategoryChanged() const; void setDisableASMWhenCategoryChanged(bool value); bool isDisableASMWhenDefaultSavePathChanged() const; void setDisableASMWhenDefaultSavePathChanged(bool value); bool isDisableASMWhenCategorySavePathChanged() const; void setDisableASMWhenCategorySavePathChanged(bool value); bool isAddTorrentPaused() const; void setAddTorrentPaused(bool value); TorrentHandle *findTorrent(const InfoHash &hash) const; QHash torrents() const; TorrentStatusReport torrentStatusReport() const; bool hasActiveTorrents() const; bool hasUnfinishedTorrents() const; SessionStatus status() const; CacheStatus cacheStatus() const; quint64 getAlltimeDL() const; quint64 getAlltimeUL() const; int downloadRateLimit() const; int uploadRateLimit() const; bool isListening() const; MaxRatioAction maxRatioAction() const; void setMaxRatioAction(MaxRatioAction act); void changeSpeedLimitMode(bool alternative); void setDownloadRateLimit(int rate); void setUploadRateLimit(int rate); void setGlobalMaxRatio(qreal ratio); void enableIPFilter(const QString &filterPath, bool force = false); void disableIPFilter(); void banIP(const QString &ip); bool isKnownTorrent(const InfoHash &hash) const; bool addTorrent(QString source, const AddTorrentParams ¶ms = AddTorrentParams()); bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams ¶ms = AddTorrentParams()); bool deleteTorrent(const QString &hash, bool deleteLocalFiles = false); bool loadMetadata(const MagnetUri &magnetUri); bool cancelLoadMetadata(const InfoHash &hash); void recursiveTorrentDownload(const InfoHash &hash); void increaseTorrentsPriority(const QStringList &hashes); void decreaseTorrentsPriority(const QStringList &hashes); void topTorrentsPriority(const QStringList &hashes); void bottomTorrentsPriority(const QStringList &hashes); // TorrentHandle interface void handleTorrentRatioLimitChanged(TorrentHandle *const torrent); void handleTorrentSavePathChanged(TorrentHandle *const torrent); void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory); void handleTorrentSavingModeChanged(TorrentHandle *const torrent); void handleTorrentMetadataReceived(TorrentHandle *const torrent); void handleTorrentPaused(TorrentHandle *const torrent); void handleTorrentResumed(TorrentHandle *const torrent); void handleTorrentChecked(TorrentHandle *const torrent); void handleTorrentFinished(TorrentHandle *const torrent); void handleTorrentTrackersAdded(TorrentHandle *const torrent, const QList &newTrackers); void handleTorrentTrackersRemoved(TorrentHandle *const torrent, const QList &deletedTrackers); void handleTorrentTrackersChanged(TorrentHandle *const torrent); void handleTorrentUrlSeedsAdded(TorrentHandle *const torrent, const QList &newUrlSeeds); void handleTorrentUrlSeedsRemoved(TorrentHandle *const torrent, const QList &urlSeeds); void handleTorrentResumeDataReady(TorrentHandle *const torrent, const libtorrent::entry &data); void handleTorrentResumeDataFailed(TorrentHandle *const torrent); void handleTorrentTrackerReply(TorrentHandle *const torrent, const QString &trackerUrl); void handleTorrentTrackerWarning(TorrentHandle *const torrent, const QString &trackerUrl); void handleTorrentTrackerError(TorrentHandle *const torrent, const QString &trackerUrl); void handleTorrentTrackerAuthenticationRequired(TorrentHandle *const torrent, const QString &trackerUrl); signals: void torrentsUpdated(); void addTorrentFailed(const QString &error); void torrentAdded(BitTorrent::TorrentHandle *const torrent); void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent); void torrentPaused(BitTorrent::TorrentHandle *const torrent); void torrentResumed(BitTorrent::TorrentHandle *const torrent); void torrentFinished(BitTorrent::TorrentHandle *const torrent); void torrentFinishedChecking(BitTorrent::TorrentHandle *const torrent); void torrentSavePathChanged(BitTorrent::TorrentHandle *const torrent); void torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory); void torrentSavingModeChanged(BitTorrent::TorrentHandle *const torrent); void allTorrentsFinished(); void metadataLoaded(const BitTorrent::TorrentInfo &info); void torrentMetadataLoaded(BitTorrent::TorrentHandle *const torrent); void fullDiskError(BitTorrent::TorrentHandle *const torrent, const QString &msg); void trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker); void trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker); void trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker); void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent); void recursiveTorrentDownloadPossible(BitTorrent::TorrentHandle *const torrent); void speedLimitModeChanged(bool alternative); void ipFilterParsed(bool error, int ruleCount); void trackersAdded(BitTorrent::TorrentHandle *const torrent, const QList &trackers); void trackersRemoved(BitTorrent::TorrentHandle *const torrent, const QList &trackers); void trackersChanged(BitTorrent::TorrentHandle *const torrent); void trackerlessStateChanged(BitTorrent::TorrentHandle *const torrent, bool trackerless); void downloadFromUrlFailed(const QString &url, const QString &reason); void downloadFromUrlFinished(const QString &url); void categoryAdded(const QString &categoryName); void categoryRemoved(const QString &categoryName); void subcategoriesSupportChanged(); private slots: void configure(); void readAlerts(); void refresh(); void processBigRatios(); void generateResumeData(bool final = false); void handleIPFilterParsed(int ruleCount); void handleIPFilterError(); void handleDownloadFinished(const QString &url, const QString &filePath); void handleDownloadFailed(const QString &url, const QString &reason); void handleRedirectedToMagnet(const QString &url, const QString &magnetUri); void switchToAlternativeMode(bool alternative); // Session reconfiguration triggers void networkOnlineStateChanged(const bool online); void networkConfigurationChange(const QNetworkConfiguration&); private: explicit Session(QObject *parent = 0); ~Session(); bool hasPerTorrentRatioLimit() const; void initResumeFolder(); // Session configuration void setSessionSettings(); void setProxySettings(libtorrent::proxy_settings proxySettings); void adjustLimits(); void adjustLimits(libtorrent::session_settings &sessionSettings); const QStringList getListeningIPs(); void setListeningPort(); void preAllocateAllFiles(bool b); void setMaxConnectionsPerTorrent(int max); void setMaxUploadsPerTorrent(int max); void enableLSD(bool enable); void enableDHT(bool enable); void changeSpeedLimitMode_impl(bool alternative); void setAppendExtension(bool append); void startUpTorrents(); bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri, const TorrentInfo &torrentInfo = TorrentInfo(), const QByteArray &fastresumeData = QByteArray()); void updateRatioTimer(); void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular); void saveTorrentResumeData(TorrentHandle *const torrent); void handleAlert(libtorrent::alert *a); void dispatchTorrentAlert(libtorrent::alert *a); void handleAddTorrentAlert(libtorrent::add_torrent_alert *p); void handleStateUpdateAlert(libtorrent::state_update_alert *p); void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p); void handleFileErrorAlert(libtorrent::file_error_alert *p); void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p); void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p); void handleTorrentDeleteFailedAlert(libtorrent::torrent_delete_failed_alert *p); void handlePortmapWarningAlert(libtorrent::portmap_error_alert *p); void handlePortmapAlert(libtorrent::portmap_alert *p); void handlePeerBlockedAlert(libtorrent::peer_blocked_alert *p); void handlePeerBanAlert(libtorrent::peer_ban_alert *p); void handleUrlSeedAlert(libtorrent::url_seed_alert *p); void handleListenSucceededAlert(libtorrent::listen_succeeded_alert *p); void handleListenFailedAlert(libtorrent::listen_failed_alert *p); void handleExternalIPAlert(libtorrent::external_ip_alert *p); void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle); void saveResumeData(); void dispatchAlerts(std::auto_ptr alertPtr); void getPendingAlerts(QVector &out, ulong time = 0); SettingsStorage *m_settings; // BitTorrent libtorrent::session *m_nativeSession; bool m_LSDEnabled; bool m_DHTEnabled; bool m_PeXEnabled; bool m_queueingEnabled; bool m_torrentExportEnabled; bool m_finishedTorrentExportEnabled; bool m_preAllocateAll; qreal m_globalMaxRatio; int m_numResumeData; int m_extraLimit; bool m_appendExtension; uint m_refreshInterval; MaxRatioAction m_maxRatioAction; QList m_additionalTrackers; QString m_defaultSavePath; QString m_tempPath; QString m_filterPath; QString m_resumeFolderPath; QFile m_resumeFolderLock; QHash m_savePathsToRemove; QTimer *m_refreshTimer; QTimer *m_bigRatioTimer; QTimer *m_resumeDataTimer; Statistics *m_statistics; // IP filtering QPointer m_filterParser; QPointer m_bwScheduler; // Tracker QPointer m_tracker; // fastresume data writing thread QThread *m_ioThread; ResumeDataSavingManager *m_resumeDataSavingManager; QHash m_loadedMetadata; QHash m_torrents; QHash m_addingTorrents; QHash m_downloadedTorrents; TorrentStatusReport m_torrentStatusReport; QStringMap m_categories; QMutex m_alertsMutex; QWaitCondition m_alertsWaitCondition; QVector m_alerts; QNetworkConfigurationManager m_networkManager; static Session *m_instance; }; } #endif // BITTORRENT_SESSION_H