diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 72209a63a..ece6b8f4d 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -237,6 +237,20 @@ namespace template LowerLimited lowerLimited(T limit, T ret) { return LowerLimited(limit, ret); } + + template + std::function clampValue(const T lower, const T upper) + { + // TODO: change return type to `auto` when using C++14 + return [lower, upper](const T value) -> T + { + if (value < lower) + return lower; + if (value > upper) + return upper; + return value; + }; + } } // Session @@ -263,6 +277,11 @@ Session::Session(QObject *parent) , m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), 0) , m_diskCacheTTL(BITTORRENT_SESSION_KEY("DiskCacheTTL"), 60) , m_useOSCache(BITTORRENT_SESSION_KEY("UseOSCache"), true) + , m_guidedReadCacheEnabled(BITTORRENT_SESSION_KEY("GuidedReadCache"), true) + , m_isSuggestMode(BITTORRENT_SESSION_KEY("SuggestMode"), false) + , m_sendBufferWatermark(BITTORRENT_SESSION_KEY("SendBufferWatermark"), 500) + , m_sendBufferLowWatermark(BITTORRENT_SESSION_KEY("SendBufferLowWatermark"), 10) + , m_sendBufferWatermarkFactor(BITTORRENT_SESSION_KEY("SendBufferWatermarkFactor"), 50) , m_isAnonymousModeEnabled(BITTORRENT_SESSION_KEY("AnonymousModeEnabled"), false) , m_isQueueingEnabled(BITTORRENT_SESSION_KEY("QueueingSystemEnabled"), true) , m_maxActiveDownloads(BITTORRENT_SESSION_KEY("MaxActiveDownloads"), 3, lowerLimited(-1)) @@ -282,6 +301,9 @@ Session::Session(QObject *parent) , m_maxUploadsPerTorrent(BITTORRENT_SESSION_KEY("MaxUploadsPerTorrent"), -1, lowerLimited(0, -1)) , m_isUTPEnabled(BITTORRENT_SESSION_KEY("uTPEnabled"), true) , m_isUTPRateLimited(BITTORRENT_SESSION_KEY("uTPRateLimited"), true) + , m_utpMixedMode(BITTORRENT_SESSION_KEY("uTPMixedMode"), MixedModeAlgorithm::Proportional + , clampValue(MixedModeAlgorithm::TCP, MixedModeAlgorithm::Proportional)) + , m_multiConnectionsPerIpEnabled(BITTORRENT_SESSION_KEY("MultiConnectionsPerIp"), false) , m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false) , m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers")) , m_globalMaxRatio(BITTORRENT_SESSION_KEY("GlobalMaxRatio"), -1, [](qreal r) { return r < 0 ? -1. : r;}) @@ -309,6 +331,10 @@ Session::Session(QObject *parent) , m_encryption(BITTORRENT_SESSION_KEY("Encryption"), 0) , m_isForceProxyEnabled(BITTORRENT_SESSION_KEY("ForceProxy"), true) , m_isProxyPeerConnectionsEnabled(BITTORRENT_SESSION_KEY("ProxyPeerConnections"), false) + , m_chokingAlgorithm(BITTORRENT_SESSION_KEY("ChokingAlgorithm"), ChokingAlgorithm::FixedSlots + , clampValue(ChokingAlgorithm::FixedSlots, ChokingAlgorithm::RateBased)) + , m_seedChokingAlgorithm(BITTORRENT_SESSION_KEY("SeedChokingAlgorithm"), SeedChokingAlgorithm::FastestUpload + , clampValue(SeedChokingAlgorithm::RoundRobin, SeedChokingAlgorithm::AntiLeech)) , m_storedCategories(BITTORRENT_SESSION_KEY("Categories")) , m_storedTags(BITTORRENT_SESSION_KEY("Tags")) , m_maxRatioAction(BITTORRENT_SESSION_KEY("MaxRatioAction"), Pause) @@ -377,7 +403,6 @@ Session::Session(QObject *parent) sessionSettings.auto_scrape_min_interval = 900; // 15 minutes sessionSettings.connection_speed = 20; // default is 10 sessionSettings.no_connect_privileged_ports = false; - sessionSettings.seed_choking_algorithm = libt::session_settings::fastest_upload; // Disk cache pool is rarely tested in libtorrent and doesn't free buffers // Soon to be deprecated there // More info: https://github.com/arvidn/libtorrent/issues/2251 @@ -408,7 +433,6 @@ Session::Session(QObject *parent) pack.set_int(libt::settings_pack::auto_scrape_min_interval, 900); // 15 minutes pack.set_int(libt::settings_pack::connection_speed, 20); // default is 10 pack.set_bool(libt::settings_pack::no_connect_privileged_ports, false); - pack.set_int(libt::settings_pack::seed_choking_algorithm, libt::settings_pack::fastest_upload); // Disk cache pool is rarely tested in libtorrent and doesn't free buffers // Soon to be deprecated there // More info: https://github.com/arvidn/libtorrent/issues/2251 @@ -1272,6 +1296,12 @@ void Session::configure(libtorrent::settings_pack &settingsPack) : libt::settings_pack::disable_os_cache; settingsPack.set_int(libt::settings_pack::disk_io_read_mode, mode); settingsPack.set_int(libt::settings_pack::disk_io_write_mode, mode); + settingsPack.set_bool(libt::settings_pack::guided_read_cache, isGuidedReadCacheEnabled()); + settingsPack.set_bool(libt::settings_pack::suggest_mode, isSuggestModeEnabled()); + + settingsPack.set_int(libt::settings_pack::send_buffer_watermark, sendBufferWatermark() * 1024); + settingsPack.set_int(libt::settings_pack::send_buffer_low_watermark, sendBufferLowWatermark() * 1024); + settingsPack.set_int(libt::settings_pack::send_buffer_watermark_factor, sendBufferWatermarkFactor()); settingsPack.set_bool(libt::settings_pack::anonymous_mode, isAnonymousModeEnabled()); @@ -1313,9 +1343,17 @@ void Session::configure(libtorrent::settings_pack &settingsPack) // uTP settingsPack.set_bool(libt::settings_pack::enable_incoming_utp, isUTPEnabled()); settingsPack.set_bool(libt::settings_pack::enable_outgoing_utp, isUTPEnabled()); - settingsPack.set_int(libt::settings_pack::mixed_mode_algorithm, isUTPRateLimited() - ? libt::settings_pack::prefer_tcp - : libt::settings_pack::peer_proportional); + switch (utpMixedMode()) { + case MixedModeAlgorithm::TCP: + default: + settingsPack.set_int(libt::settings_pack::mixed_mode_algorithm, libt::settings_pack::prefer_tcp); + break; + case MixedModeAlgorithm::Proportional: + settingsPack.set_int(libt::settings_pack::mixed_mode_algorithm, libt::settings_pack::peer_proportional); + break; + } + + settingsPack.set_bool(libt::settings_pack::allow_multiple_connections_per_ip, multiConnectionsPerIpEnabled()); settingsPack.set_bool(libt::settings_pack::apply_ip_filter_to_trackers, isTrackerFilteringEnabled()); @@ -1323,6 +1361,29 @@ void Session::configure(libtorrent::settings_pack &settingsPack) if (isDHTEnabled()) settingsPack.set_str(libt::settings_pack::dht_bootstrap_nodes, "dht.libtorrent.org:25401,router.bittorrent.com:6881,router.utorrent.com:6881,dht.transmissionbt.com:6881,dht.aelitis.com:6881"); settingsPack.set_bool(libt::settings_pack::enable_lsd, isLSDEnabled()); + + switch (chokingAlgorithm()) { + case ChokingAlgorithm::FixedSlots: + default: + settingsPack.set_int(libt::settings_pack::choking_algorithm, libt::settings_pack::fixed_slots_choker); + break; + case ChokingAlgorithm::RateBased: + settingsPack.set_int(libt::settings_pack::choking_algorithm, libt::settings_pack::rate_based_choker); + break; + } + + switch (seedChokingAlgorithm()) { + case SeedChokingAlgorithm::RoundRobin: + settingsPack.set_int(libt::settings_pack::seed_choking_algorithm, libt::settings_pack::round_robin); + break; + case SeedChokingAlgorithm::FastestUpload: + default: + settingsPack.set_int(libt::settings_pack::seed_choking_algorithm, libt::settings_pack::fastest_upload); + break; + case SeedChokingAlgorithm::AntiLeech: + settingsPack.set_int(libt::settings_pack::seed_choking_algorithm, libt::settings_pack::anti_leech); + break; + } } void Session::configurePeerClasses() @@ -1493,6 +1554,12 @@ void Session::configure(libtorrent::session_settings &sessionSettings) : libt::session_settings::disable_os_cache; sessionSettings.disk_io_read_mode = mode; sessionSettings.disk_io_write_mode = mode; + sessionSettings.guided_read_cache = isGuidedReadCacheEnabled(); + sessionSettings.suggest_mode = isSuggestModeEnabled(); + + sessionSettings.send_buffer_watermark = sendBufferWatermark() * 1024; + sessionSettings.send_buffer_low_watermark = sendBufferLowWatermark() * 1024; + sessionSettings.send_buffer_watermark_factor = sendBufferWatermarkFactor(); sessionSettings.anonymous_mode = isAnonymousModeEnabled(); @@ -1539,9 +1606,17 @@ void Session::configure(libtorrent::session_settings &sessionSettings) sessionSettings.enable_outgoing_utp = isUTPEnabled(); // uTP rate limiting sessionSettings.rate_limit_utp = isUTPRateLimited(); - sessionSettings.mixed_mode_algorithm = isUTPRateLimited() - ? libt::session_settings::prefer_tcp - : libt::session_settings::peer_proportional; + switch (utpMixedMode()) { + case MixedModeAlgorithm::TCP: + default: + sessionSettings.mixed_mode_algorithm = libt::session_settings::prefer_tcp; + break; + case MixedModeAlgorithm::Proportional: + sessionSettings.mixed_mode_algorithm = libt::session_settings::peer_proportional; + break; + } + + sessionSettings.allow_multiple_connections_per_ip = multiConnectionsPerIpEnabled(); sessionSettings.apply_ip_filter_to_trackers = isTrackerFilteringEnabled(); @@ -1562,6 +1637,29 @@ void Session::configure(libtorrent::session_settings &sessionSettings) m_nativeSession->start_lsd(); else m_nativeSession->stop_lsd(); + + switch (chokingAlgorithm()) { + case ChokingAlgorithm::FixedSlots: + default: + sessionSettings.choking_algorithm = libt::session_settings::fixed_slots_choker; + break; + case ChokingAlgorithm::RateBased: + sessionSettings.choking_algorithm = libt::session_settings::rate_based_choker; + break; + } + + switch (seedChokingAlgorithm()) { + case SeedChokingAlgorithm::RoundRobin: + sessionSettings.seed_choking_algorithm = libt::session_settings::round_robin; + break; + case SeedChokingAlgorithm::FastestUpload: + default: + sessionSettings.seed_choking_algorithm = libt::session_settings::fastest_upload; + break; + case SeedChokingAlgorithm::AntiLeech: + sessionSettings.seed_choking_algorithm = libt::session_settings::anti_leech; + break; + } } #endif @@ -2649,6 +2747,32 @@ void Session::setProxyPeerConnectionsEnabled(bool enabled) } } +ChokingAlgorithm Session::chokingAlgorithm() const +{ + return m_chokingAlgorithm; +} + +void Session::setChokingAlgorithm(ChokingAlgorithm mode) +{ + if (mode == m_chokingAlgorithm) return; + + m_chokingAlgorithm = mode; + configureDeferred(); +} + +SeedChokingAlgorithm Session::seedChokingAlgorithm() const +{ + return m_seedChokingAlgorithm; +} + +void Session::setSeedChokingAlgorithm(SeedChokingAlgorithm mode) +{ + if (mode == m_seedChokingAlgorithm) return; + + m_seedChokingAlgorithm = mode; + configureDeferred(); +} + bool Session::isAddTrackersEnabled() const { return m_isAddTrackersEnabled; @@ -2851,6 +2975,71 @@ void Session::setUseOSCache(bool use) } } +bool Session::isGuidedReadCacheEnabled() const +{ + return m_guidedReadCacheEnabled; +} + +void Session::setGuidedReadCacheEnabled(bool enabled) +{ + if (enabled == m_guidedReadCacheEnabled) return; + + m_guidedReadCacheEnabled = enabled; + configureDeferred(); +} + +bool Session::isSuggestModeEnabled() const +{ + return m_isSuggestMode; +} + +void Session::setSuggestMode(bool mode) +{ + if (mode == m_isSuggestMode) return; + + m_isSuggestMode = mode; + configureDeferred(); +} + +int Session::sendBufferWatermark() const +{ + return m_sendBufferWatermark; +} + +void Session::setSendBufferWatermark(int value) +{ + if (value == m_sendBufferWatermark) return; + + m_sendBufferWatermark = value; + configureDeferred(); +} + +int Session::sendBufferLowWatermark() const +{ + return m_sendBufferLowWatermark; +} + +void Session::setSendBufferLowWatermark(int value) +{ + if (value == m_sendBufferLowWatermark) return; + + m_sendBufferLowWatermark = value; + configureDeferred(); +} + +int Session::sendBufferWatermarkFactor() const +{ + return m_sendBufferWatermarkFactor; +} + +void Session::setSendBufferWatermarkFactor(int value) +{ + if (value == m_sendBufferWatermarkFactor) return; + + m_sendBufferWatermarkFactor = value; + configureDeferred(); +} + bool Session::isAnonymousModeEnabled() const { return m_isAnonymousModeEnabled; @@ -3081,6 +3270,32 @@ void Session::setUTPRateLimited(bool limited) } } +MixedModeAlgorithm Session::utpMixedMode() const +{ + return m_utpMixedMode; +} + +void Session::setUtpMixedMode(MixedModeAlgorithm mode) +{ + if (mode == m_utpMixedMode) return; + + m_utpMixedMode = mode; + configureDeferred(); +} + +bool Session::multiConnectionsPerIpEnabled() const +{ + return m_multiConnectionsPerIpEnabled; +} + +void Session::setMultiConnectionsPerIpEnabled(bool enabled) +{ + if (enabled == m_multiConnectionsPerIpEnabled) return; + + m_multiConnectionsPerIpEnabled = enabled; + configureDeferred(); +} + bool Session::isTrackerFilteringEnabled() const { return m_isTrackerFilteringEnabled; diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index ba17d5df8..8ba11b640 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -151,6 +151,38 @@ namespace BitTorrent uint nbErrored = 0; }; + class SessionSettingsEnums + { + Q_GADGET + + public: + // TODO: remove `SessionSettingsEnums` wrapper when we can use `Q_ENUM_NS` directly (QT >= 5.8 only) + enum class ChokingAlgorithm : int + { + FixedSlots = 0, + RateBased = 1 + }; + Q_ENUM(ChokingAlgorithm) + + enum class SeedChokingAlgorithm : int + { + RoundRobin = 0, + FastestUpload = 1, + AntiLeech = 2 + }; + Q_ENUM(SeedChokingAlgorithm) + + enum class MixedModeAlgorithm : int + { + TCP = 0, + Proportional = 1 + }; + Q_ENUM(MixedModeAlgorithm) + }; + using ChokingAlgorithm = SessionSettingsEnums::ChokingAlgorithm; + using SeedChokingAlgorithm = SessionSettingsEnums::SeedChokingAlgorithm; + using MixedModeAlgorithm = SessionSettingsEnums::MixedModeAlgorithm; + #if LIBTORRENT_VERSION_NUM >= 10100 struct SessionMetricIndices { @@ -317,6 +349,10 @@ namespace BitTorrent void setForceProxyEnabled(bool enabled); bool isProxyPeerConnectionsEnabled() const; void setProxyPeerConnectionsEnabled(bool enabled); + ChokingAlgorithm chokingAlgorithm() const; + void setChokingAlgorithm(ChokingAlgorithm mode); + SeedChokingAlgorithm seedChokingAlgorithm() const; + void setSeedChokingAlgorithm(SeedChokingAlgorithm mode); bool isAddTrackersEnabled() const; void setAddTrackersEnabled(bool enabled); QString additionalTrackers() const; @@ -333,6 +369,16 @@ namespace BitTorrent void setDiskCacheTTL(int ttl); bool useOSCache() const; void setUseOSCache(bool use); + bool isGuidedReadCacheEnabled() const; + void setGuidedReadCacheEnabled(bool enabled); + bool isSuggestModeEnabled() const; + void setSuggestMode(bool mode); + int sendBufferWatermark() const; + void setSendBufferWatermark(int value); + int sendBufferLowWatermark() const; + void setSendBufferLowWatermark(int value); + int sendBufferWatermarkFactor() const; + void setSendBufferWatermarkFactor(int value); bool isAnonymousModeEnabled() const; void setAnonymousModeEnabled(bool enabled); bool isQueueingSystemEnabled() const; @@ -371,6 +417,10 @@ namespace BitTorrent void setUTPEnabled(bool enabled); bool isUTPRateLimited() const; void setUTPRateLimited(bool limited); + MixedModeAlgorithm utpMixedMode() const; + void setUtpMixedMode(MixedModeAlgorithm mode); + bool multiConnectionsPerIpEnabled() const; + void setMultiConnectionsPerIpEnabled(bool enabled); bool isTrackerFilteringEnabled() const; void setTrackerFilteringEnabled(bool enabled); QStringList bannedIPs() const; @@ -576,6 +626,11 @@ namespace BitTorrent CachedSettingValue m_diskCacheSize; CachedSettingValue m_diskCacheTTL; CachedSettingValue m_useOSCache; + CachedSettingValue m_guidedReadCacheEnabled; + CachedSettingValue m_isSuggestMode; + CachedSettingValue m_sendBufferWatermark; + CachedSettingValue m_sendBufferLowWatermark; + CachedSettingValue m_sendBufferWatermarkFactor; CachedSettingValue m_isAnonymousModeEnabled; CachedSettingValue m_isQueueingEnabled; CachedSettingValue m_maxActiveDownloads; @@ -595,6 +650,8 @@ namespace BitTorrent CachedSettingValue m_maxUploadsPerTorrent; CachedSettingValue m_isUTPEnabled; CachedSettingValue m_isUTPRateLimited; + CachedSettingValue m_utpMixedMode; + CachedSettingValue m_multiConnectionsPerIpEnabled; CachedSettingValue m_isAddTrackersEnabled; CachedSettingValue m_additionalTrackers; CachedSettingValue m_globalMaxRatio; @@ -622,6 +679,8 @@ namespace BitTorrent CachedSettingValue m_encryption; CachedSettingValue m_isForceProxyEnabled; CachedSettingValue m_isProxyPeerConnectionsEnabled; + CachedSettingValue m_chokingAlgorithm; + CachedSettingValue m_seedChokingAlgorithm; CachedSettingValue m_storedCategories; CachedSettingValue m_storedTags; CachedSettingValue m_maxRatioAction; diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp index dd35a9511..aa6963640 100644 --- a/src/gui/advancedsettings.cpp +++ b/src/gui/advancedsettings.cpp @@ -78,14 +78,23 @@ enum AdvSettingsRows DISK_CACHE, DISK_CACHE_TTL, OS_CACHE, + GUIDED_READ_CACHE, + SUGGEST_MODE, + SEND_BUF_WATERMARK, + SEND_BUF_LOW_WATERMARK, + SEND_BUF_WATERMARK_FACTOR, // ports MAX_HALF_OPEN, OUTGOING_PORT_MIN, OUTGOING_PORT_MAX, + UTP_MIX_MODE, + MULTI_CONNECTIONS_PER_IP, // embedded tracker TRACKER_STATUS, TRACKER_PORT, // seeding + CHOKING_ALGORITHM, + SEED_CHOKING_ALGORITHM, SUPER_SEEDING, // tracker ANNOUNCE_ALL_TRACKERS, @@ -127,11 +136,23 @@ void AdvancedSettings::saveAdvancedSettings() session->setDiskCacheTTL(spin_cache_ttl.value()); // Enable OS cache session->setUseOSCache(cb_os_cache.isChecked()); + // Guided read cache + session->setGuidedReadCacheEnabled(cbGuidedReadCache.isChecked()); + // Suggest mode + session->setSuggestMode(cbSuggestMode.isChecked()); + // Send buffer watermark + session->setSendBufferWatermark(spinSendBufferWatermark.value()); + session->setSendBufferLowWatermark(spinSendBufferLowWatermark.value()); + session->setSendBufferWatermarkFactor(spinSendBufferWatermarkFactor.value()); // Save resume data interval session->setSaveResumeDataInterval(spin_save_resume_data_interval.value()); // Outgoing ports session->setOutgoingPortsMin(outgoing_ports_min.value()); session->setOutgoingPortsMax(outgoing_ports_max.value()); + // uTP-TCP mixed mode + session->setUtpMixedMode(static_cast(comboUtpMixedMode.currentIndex())); + // multiple connections per IP + session->setMultiConnectionsPerIpEnabled(cbMultiConnectionsPerIp.isChecked()); // Recheck torrents on completion pref->recheckTorrentsOnCompletion(cb_recheck_completed.isChecked()); // Transfer list refresh interval @@ -178,6 +199,11 @@ void AdvancedSettings::saveAdvancedSettings() // Tracker session->setTrackerEnabled(cb_tracker_status.isChecked()); pref->setTrackerPort(spin_tracker_port.value()); + // Choking algorithm + session->setChokingAlgorithm(static_cast(comboChokingAlgorithm.currentIndex())); + // Seed choking algorithm + session->setSeedChokingAlgorithm(static_cast(comboSeedChokingAlgorithm.currentIndex())); + #if defined(Q_OS_WIN) || defined(Q_OS_MAC) pref->setUpdateCheckEnabled(cb_update_check.isChecked()); #endif @@ -278,6 +304,28 @@ void AdvancedSettings::loadAdvancedSettings() // Enable OS cache cb_os_cache.setChecked(session->useOSCache()); addRow(OS_CACHE, tr("Enable OS cache"), &cb_os_cache); + // Guided read cache + cbGuidedReadCache.setChecked(session->isGuidedReadCacheEnabled()); + addRow(GUIDED_READ_CACHE, tr("Guided read cache"), &cbGuidedReadCache); + // Suggest mode + cbSuggestMode.setChecked(session->isSuggestModeEnabled()); + addRow(SUGGEST_MODE, tr("Send upload piece suggestions"), &cbSuggestMode); + // Send buffer watermark + spinSendBufferWatermark.setMinimum(1); + spinSendBufferWatermark.setMaximum(INT_MAX); + spinSendBufferWatermark.setSuffix(tr(" KiB")); + spinSendBufferWatermark.setValue(session->sendBufferWatermark()); + addRow(SEND_BUF_WATERMARK, tr("Send buffer watermark"), &spinSendBufferWatermark); + spinSendBufferLowWatermark.setMinimum(1); + spinSendBufferLowWatermark.setMaximum(INT_MAX); + spinSendBufferLowWatermark.setSuffix(tr(" KiB")); + spinSendBufferLowWatermark.setValue(session->sendBufferLowWatermark()); + addRow(SEND_BUF_LOW_WATERMARK, tr("Send buffer low watermark"), &spinSendBufferLowWatermark); + spinSendBufferWatermarkFactor.setMinimum(1); + spinSendBufferWatermarkFactor.setMaximum(INT_MAX); + spinSendBufferWatermarkFactor.setSuffix(" %"); + spinSendBufferWatermarkFactor.setValue(session->sendBufferWatermarkFactor()); + addRow(SEND_BUF_WATERMARK_FACTOR, tr("Send buffer watermark factor"), &spinSendBufferWatermarkFactor); // Save resume data interval spin_save_resume_data_interval.setMinimum(1); spin_save_resume_data_interval.setMaximum(1440); @@ -294,6 +342,13 @@ void AdvancedSettings::loadAdvancedSettings() outgoing_ports_max.setMaximum(65535); outgoing_ports_max.setValue(session->outgoingPortsMax()); addRow(OUTGOING_PORT_MAX, tr("Outgoing ports (Max) [0: Disabled]"), &outgoing_ports_max); + // uTP-TCP mixed mode + comboUtpMixedMode.addItems({"Prefer TCP", "Peer proportional (throttles TCP)"}); + comboUtpMixedMode.setCurrentIndex(static_cast(session->utpMixedMode())); + addRow(UTP_MIX_MODE, tr("uTP-TCP mixed mode algorithm"), &comboUtpMixedMode); + // multiple connections per IP + cbMultiConnectionsPerIp.setChecked(session->multiConnectionsPerIpEnabled()); + addRow(MULTI_CONNECTIONS_PER_IP, tr("Allow multiple connections from the same IP address"), &cbMultiConnectionsPerIp); // Recheck completed torrents cb_recheck_completed.setChecked(pref->recheckTorrentsOnCompletion()); addRow(RECHECK_COMPLETED, tr("Recheck torrents on completion"), &cb_recheck_completed); @@ -371,6 +426,15 @@ void AdvancedSettings::loadAdvancedSettings() spin_tracker_port.setMaximum(65535); spin_tracker_port.setValue(pref->getTrackerPort()); addRow(TRACKER_PORT, tr("Embedded tracker port"), &spin_tracker_port); + // Choking algorithm + comboChokingAlgorithm.addItems({"Fixed slots", "Upload rate based"}); + comboChokingAlgorithm.setCurrentIndex(static_cast(session->chokingAlgorithm())); + addRow(CHOKING_ALGORITHM, tr("Upload slots behavior"), &comboChokingAlgorithm); + // Seed choking algorithm + comboSeedChokingAlgorithm.addItems({"Round-robin", "Fastest upload", "Anti-leech"}); + comboSeedChokingAlgorithm.setCurrentIndex(static_cast(session->seedChokingAlgorithm())); + addRow(SEED_CHOKING_ALGORITHM, tr("Upload choking algorithm"), &comboSeedChokingAlgorithm); + #if defined(Q_OS_WIN) || defined(Q_OS_MAC) cb_update_check.setChecked(pref->isUpdateCheckEnabled()); addRow(UPDATE_CHECK, tr("Check for software updates"), &cb_update_check); diff --git a/src/gui/advancedsettings.h b/src/gui/advancedsettings.h index 57ae1b643..d780db5e5 100644 --- a/src/gui/advancedsettings.h +++ b/src/gui/advancedsettings.h @@ -29,15 +29,14 @@ #ifndef ADVANCEDSETTINGS_H #define ADVANCEDSETTINGS_H +#include +#include #include #include -#include -#include #include -#include +#include #include - class WheelEventEater: public QObject { Q_OBJECT @@ -76,11 +75,13 @@ private: template void addRow(int row, const QString &rowText, T* widget); QLabel labelQbtLink, labelLibtorrentLink; - QSpinBox spin_cache, spin_save_resume_data_interval, outgoing_ports_min, outgoing_ports_max, spin_list_refresh, spin_maxhalfopen, spin_tracker_port, spin_cache_ttl; + QSpinBox spin_cache, spin_save_resume_data_interval, outgoing_ports_min, outgoing_ports_max, spin_list_refresh, spin_maxhalfopen, spin_tracker_port, spin_cache_ttl, + spinSendBufferWatermark, spinSendBufferLowWatermark, spinSendBufferWatermarkFactor; QCheckBox cb_os_cache, cb_recheck_completed, cb_resolve_countries, cb_resolve_hosts, cb_super_seeding, cb_program_notifications, cb_torrent_added_notifications, cb_tracker_favicon, cb_tracker_status, - cb_confirm_torrent_recheck, cb_confirm_remove_all_tags, cb_listen_ipv6, cb_announce_all_trackers; - QComboBox combo_iface, combo_iface_address; + cb_confirm_torrent_recheck, cb_confirm_remove_all_tags, cb_listen_ipv6, cb_announce_all_trackers, cbGuidedReadCache, cbMultiConnectionsPerIp, + cbSuggestMode; + QComboBox combo_iface, combo_iface_address, comboUtpMixedMode, comboChokingAlgorithm, comboSeedChokingAlgorithm; QLineEdit txtAnnounceIP; // OS dependent settings