From 4406a3f173dea3196543103ebbf7ec80ee38f1c4 Mon Sep 17 00:00:00 2001 From: Maxime Thiebaut <46688461+0xThiebaut@users.noreply.github.com> Date: Sat, 8 Feb 2025 09:12:50 +0100 Subject: [PATCH] Add announce_port support The `announce_port` setting permits to overwrite the port passed along to trackers as the `&port=` parameter. If left as the default, the listening port is used. This setting is only meant for very special cases where a seed's listening port differs from the effectively exposed port (e.g., through external NAT-PMP). See https://github.com/arvidn/libtorrent/pull/7771 for an example use-case. This PR adds the relevant setting alongside the existing `announce_ip` setting. PR #21692. --- src/base/bittorrent/session.h | 2 ++ src/base/bittorrent/sessionimpl.cpp | 19 +++++++++++++++++++ src/base/bittorrent/sessionimpl.h | 3 +++ src/gui/advancedsettings.cpp | 10 ++++++++++ src/gui/advancedsettings.h | 2 +- src/webui/api/appcontroller.cpp | 3 +++ src/webui/www/private/views/preferences.html | 15 +++++++++++++++ 7 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index 118b02d35..f5c062172 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -392,6 +392,8 @@ namespace BitTorrent virtual void setIncludeOverheadInLimits(bool include) = 0; virtual QString announceIP() const = 0; virtual void setAnnounceIP(const QString &ip) = 0; + virtual int announcePort() const = 0; + virtual void setAnnouncePort(int port) = 0; virtual int maxConcurrentHTTPAnnounces() const = 0; virtual void setMaxConcurrentHTTPAnnounces(int value) = 0; virtual bool isReannounceWhenAddressChangedEnabled() const = 0; diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 0275dea4e..b5801244c 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -445,6 +445,7 @@ SessionImpl::SessionImpl(QObject *parent) , m_ignoreLimitsOnLAN(BITTORRENT_SESSION_KEY(u"IgnoreLimitsOnLAN"_s), false) , m_includeOverheadInLimits(BITTORRENT_SESSION_KEY(u"IncludeOverheadInLimits"_s), false) , m_announceIP(BITTORRENT_SESSION_KEY(u"AnnounceIP"_s)) + , m_announcePort(BITTORRENT_SESSION_KEY(u"AnnouncePort"_s), 0) , m_maxConcurrentHTTPAnnounces(BITTORRENT_SESSION_KEY(u"MaxConcurrentHTTPAnnounces"_s), 50) , m_isReannounceWhenAddressChangedEnabled(BITTORRENT_SESSION_KEY(u"ReannounceWhenAddressChanged"_s), false) , m_stopTrackerTimeout(BITTORRENT_SESSION_KEY(u"StopTrackerTimeout"_s), 2) @@ -2004,6 +2005,10 @@ lt::settings_pack SessionImpl::loadLTSettings() const settingsPack.set_bool(lt::settings_pack::rate_limit_ip_overhead, includeOverheadInLimits()); // IP address to announce to trackers settingsPack.set_str(lt::settings_pack::announce_ip, announceIP().toStdString()); +#if LIBTORRENT_VERSION_NUM >= 20011 + // Port to announce to trackers + settingsPack.set_int(lt::settings_pack::announce_port, announcePort()); +#endif // Max concurrent HTTP announces settingsPack.set_int(lt::settings_pack::max_concurrent_http_announces, maxConcurrentHTTPAnnounces()); // Stop tracker timeout @@ -4879,6 +4884,20 @@ void SessionImpl::setAnnounceIP(const QString &ip) } } +int SessionImpl::announcePort() const +{ + return m_announcePort; +} + +void SessionImpl::setAnnouncePort(const int port) +{ + if (port != m_announcePort) + { + m_announcePort = port; + configureDeferred(); + } +} + int SessionImpl::maxConcurrentHTTPAnnounces() const { return m_maxConcurrentHTTPAnnounces; diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index 9ac416e70..960f0cd99 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -361,6 +361,8 @@ namespace BitTorrent void setIncludeOverheadInLimits(bool include) override; QString announceIP() const override; void setAnnounceIP(const QString &ip) override; + int announcePort() const override; + void setAnnouncePort(int port) override; int maxConcurrentHTTPAnnounces() const override; void setMaxConcurrentHTTPAnnounces(int value) override; bool isReannounceWhenAddressChangedEnabled() const override; @@ -670,6 +672,7 @@ namespace BitTorrent CachedSettingValue m_ignoreLimitsOnLAN; CachedSettingValue m_includeOverheadInLimits; CachedSettingValue m_announceIP; + CachedSettingValue m_announcePort; CachedSettingValue m_maxConcurrentHTTPAnnounces; CachedSettingValue m_isReannounceWhenAddressChangedEnabled; CachedSettingValue m_stopTrackerTimeout; diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp index 27da9beba..deb4cb5d3 100644 --- a/src/gui/advancedsettings.cpp +++ b/src/gui/advancedsettings.cpp @@ -163,6 +163,7 @@ namespace ANNOUNCE_ALL_TRACKERS, ANNOUNCE_ALL_TIERS, ANNOUNCE_IP, + ANNOUNCE_PORT, MAX_CONCURRENT_HTTP_ANNOUNCES, STOP_TRACKER_TIMEOUT, PEER_TURNOVER, @@ -309,6 +310,8 @@ void AdvancedSettings::saveAdvancedSettings() const // Construct a QHostAddress to filter malformed strings const QHostAddress addr(m_lineEditAnnounceIP.text().trimmed()); session->setAnnounceIP(addr.toString()); + // Announce Port + session->setAnnouncePort(m_spinBoxAnnouncePort.value()); // Max concurrent HTTP announces session->setMaxConcurrentHTTPAnnounces(m_spinBoxMaxConcurrentHTTPAnnounces.value()); // Stop tracker timeout @@ -801,6 +804,13 @@ void AdvancedSettings::loadAdvancedSettings() addRow(ANNOUNCE_IP, (tr("IP address reported to trackers (requires restart)") + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#announce_ip", u"(?)")) , &m_lineEditAnnounceIP); + // Announce port + m_spinBoxAnnouncePort.setMinimum(0); + m_spinBoxAnnouncePort.setMaximum(65535); + m_spinBoxAnnouncePort.setValue(session->announcePort()); + addRow(ANNOUNCE_PORT, (tr("Port reported to trackers (requires restart) [0: listening port]") + + u' ' + makeLink(u"https://www.libtorrent.org/reference-Settings.html#announce_port", u"(?)")) + , &m_spinBoxAnnouncePort); // Max concurrent HTTP announces m_spinBoxMaxConcurrentHTTPAnnounces.setMaximum(std::numeric_limits::max()); m_spinBoxMaxConcurrentHTTPAnnounces.setValue(session->maxConcurrentHTTPAnnounces()); diff --git a/src/gui/advancedsettings.h b/src/gui/advancedsettings.h index 5c81745be..316e68849 100644 --- a/src/gui/advancedsettings.h +++ b/src/gui/advancedsettings.h @@ -73,7 +73,7 @@ private: m_spinBoxOutgoingPortsMin, m_spinBoxOutgoingPortsMax, m_spinBoxUPnPLeaseDuration, m_spinBoxPeerToS, m_spinBoxListRefresh, m_spinBoxTrackerPort, m_spinBoxSendBufferWatermark, m_spinBoxSendBufferLowWatermark, m_spinBoxSendBufferWatermarkFactor, m_spinBoxConnectionSpeed, m_spinBoxSocketSendBufferSize, m_spinBoxSocketReceiveBufferSize, m_spinBoxSocketBacklogSize, - m_spinBoxMaxConcurrentHTTPAnnounces, m_spinBoxStopTrackerTimeout, m_spinBoxSessionShutdownTimeout, + m_spinBoxAnnouncePort, m_spinBoxMaxConcurrentHTTPAnnounces, m_spinBoxStopTrackerTimeout, m_spinBoxSessionShutdownTimeout, m_spinBoxSavePathHistoryLength, m_spinBoxPeerTurnover, m_spinBoxPeerTurnoverCutoff, m_spinBoxPeerTurnoverInterval, m_spinBoxRequestQueueSize; QCheckBox m_checkBoxOsCache, m_checkBoxRecheckCompleted, m_checkBoxResolveCountries, m_checkBoxResolveHosts, m_checkBoxProgramNotifications, m_checkBoxTorrentAddedNotifications, m_checkBoxReannounceWhenAddressChanged, m_checkBoxTrackerFavicon, m_checkBoxTrackerStatus, diff --git a/src/webui/api/appcontroller.cpp b/src/webui/api/appcontroller.cpp index a391c8dc9..95bb6e0d0 100644 --- a/src/webui/api/appcontroller.cpp +++ b/src/webui/api/appcontroller.cpp @@ -473,6 +473,7 @@ void AppController::preferencesAction() data[u"announce_to_all_trackers"_s] = session->announceToAllTrackers(); data[u"announce_to_all_tiers"_s] = session->announceToAllTiers(); data[u"announce_ip"_s] = session->announceIP(); + data[u"announce_port"_s] = session->announcePort(); data[u"max_concurrent_http_announces"_s] = session->maxConcurrentHTTPAnnounces(); data[u"stop_tracker_timeout"_s] = session->stopTrackerTimeout(); // Peer Turnover @@ -1144,6 +1145,8 @@ void AppController::setPreferencesAction() const QHostAddress announceAddr {it.value().toString().trimmed()}; session->setAnnounceIP(announceAddr.isNull() ? QString {} : announceAddr.toString()); } + if (hasKey(u"announce_port"_s)) + session->setAnnouncePort(it.value().toInt()); if (hasKey(u"max_concurrent_http_announces"_s)) session->setMaxConcurrentHTTPAnnounces(it.value().toInt()); if (hasKey(u"stop_tracker_timeout"_s)) diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index 78b2afa6a..7dc1f3d42 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -1621,6 +1621,14 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD + + + + + + + + @@ -2593,6 +2601,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD $("announceAllTrackers").checked = pref.announce_to_all_trackers; $("announceAllTiers").checked = pref.announce_to_all_tiers; $("announceIP").value = pref.announce_ip; + $("announcePort").value = pref.announce_port; $("maxConcurrentHTTPAnnounces").value = pref.max_concurrent_http_announces; $("stopTrackerTimeout").value = pref.stop_tracker_timeout; $("peerTurnover").value = pref.peer_turnover; @@ -3061,6 +3070,12 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD settings["announce_to_all_trackers"] = $("announceAllTrackers").checked; settings["announce_to_all_tiers"] = $("announceAllTiers").checked; settings["announce_ip"] = $("announceIP").value; + const announcePort = Number($("announcePort").value); + if (Number.isNaN(announcePort) || (announcePort < 0) || (announcePort > 65535)) { + alert("QBT_TR(The announce port must be between 0 and 65535.)QBT_TR[CONTEXT=OptionsDialog]"); + return; + } + settings["announce_port"] = announcePort; settings["max_concurrent_http_announces"] = Number($("maxConcurrentHTTPAnnounces").value); settings["stop_tracker_timeout"] = Number($("stopTrackerTimeout").value); settings["peer_turnover"] = Number($("peerTurnover").value);