feat: add `preferred-transport` to settings.json (#5939)
This commit is contained in:
parent
9a82372e95
commit
85a120faea
|
@ -78,7 +78,7 @@ Here is a sample of the three basic types: respectively Boolean, Number and Stri
|
|||
* **encryption:** Number (0 = Prefer unencrypted connections, 1 = Prefer encrypted connections, 2 = Require encrypted connections; default = 1) [Encryption](https://wiki.vuze.com/w/Message_Stream_Encryption) preference. Encryption may help get around some ISP filtering, but at the cost of slightly higher CPU use.
|
||||
* **lazy-bitfield-enabled:** Boolean (default = true) May help get around some ISP filtering. [Vuze specification](https://wiki.vuze.com/w/Commandline_options#Network_Options).
|
||||
* **lpd-enabled:** Boolean (default = false) Enable [Local Peer Discovery (LPD)](https://en.wikipedia.org/wiki/Local_Peer_Discovery).
|
||||
* **message-level:** Number (0 = None, 1 = Critical, 2 = Error, 3 = Warn, 4 = Info, 5 = Debug, 6 = Trace, default = 2) Set verbosity of Transmission's log messages.
|
||||
* **message-level:** Number (0 = None, 1 = Critical, 2 = Error, 3 = Warn, 4 = Info, 5 = Debug, 6 = Trace; default = 2) Set verbosity of Transmission's log messages.
|
||||
* **pex-enabled:** Boolean (default = true) Enable [Peer Exchange (PEX)](https://en.wikipedia.org/wiki/Peer_exchange).
|
||||
* **pidfile:** String Path to file in which daemon PID will be stored (transmission-daemon only)
|
||||
* **prefetch-enabled:** Boolean (default = true). When enabled, Transmission will hint to the OS which piece data it's about to read from disk in order to satisfy requests from peers. On Linux, this is done by passing `POSIX_FADV_WILLNEED` to [posix_fadvise()](https://www.kernel.org/doc/man-pages/online/pages/man2/posix_fadvise.2.html). On macOS, this is done by passing `F_RDADVISE` to [fcntl()](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html).
|
||||
|
@ -89,9 +89,10 @@ Here is a sample of the three basic types: respectively Boolean, Number and Stri
|
|||
* **script-torrent-done-filename:** String (default = "") Path to script.
|
||||
* **script-torrent-done-seeding-enabled:** Boolean (default = false) Run a script when a torrent is done seeding. Environmental variables are passed in as detailed on the [Scripts](./Scripts.md) page
|
||||
* **script-torrent-done-seeding-filename:** String (default = "") Path to script.
|
||||
* **tcp-enabled:** Boolean (default = true) Optionally disable TCP connection to other peers. Never disable TCP when you also disable UTP, because then your client would not be able to communicate. Disabling TCP might also break webseeds. Unless you have a good reason, you should not set this to false.
|
||||
* **tcp-enabled:** Boolean (default = true) Optionally disable TCP connection to other peers. Never disable TCP when you also disable µTP, because then your client would not be able to communicate. Disabling TCP might also break webseeds. Unless you have a good reason, you should not set this to false.
|
||||
* **torrent-added-verify-mode:** String ("fast", "full", default: "fast") Whether newly-added torrents' local data should be fully verified when added, or wait and verify them on-demand later. See [#2626](https://github.com/transmission/transmission/pull/2626) for more discussion.
|
||||
* **utp-enabled:** Boolean (default = true) Enable [Micro Transport Protocol (µTP)](https://en.wikipedia.org/wiki/Micro_Transport_Protocol)
|
||||
* **preferred-transport:** String ("utp" = Prefer µTP, "tcp" = Prefer TCP; default = "utp") Choose your preferred transport protocol (has no effect if one of them is disabled).
|
||||
|
||||
#### Peers
|
||||
* **bind-address-ipv4:** String (default = "0.0.0.0") Where to listen for peer connections. When no valid IPv4 address is provided, Transmission will bind to "0.0.0.0".
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
|
@ -19,6 +20,8 @@
|
|||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include <small/map.hpp>
|
||||
|
||||
#include "libtransmission/transmission.h"
|
||||
|
||||
#include "libtransmission/bandwidth.h"
|
||||
|
@ -124,11 +127,12 @@ std::shared_ptr<tr_peerIo> tr_peerIo::new_outgoing(
|
|||
bool is_seed,
|
||||
bool utp)
|
||||
{
|
||||
auto const& [addr, port] = socket_address;
|
||||
using preferred_key_t = std::underlying_type_t<tr_preferred_transport>;
|
||||
auto const preferred = session->preferred_transport();
|
||||
|
||||
TR_ASSERT(!tr_peer_socket::limit_reached(session));
|
||||
TR_ASSERT(session != nullptr);
|
||||
TR_ASSERT(addr.is_valid());
|
||||
TR_ASSERT(socket_address.is_valid());
|
||||
TR_ASSERT(utp || session->allowsTCP());
|
||||
|
||||
if (!socket_address.is_valid_for_peers())
|
||||
|
@ -137,27 +141,49 @@ std::shared_ptr<tr_peerIo> tr_peerIo::new_outgoing(
|
|||
}
|
||||
|
||||
auto peer_io = tr_peerIo::create(session, parent, &info_hash, false, is_seed);
|
||||
|
||||
auto const func = small::max_size_map<preferred_key_t, std::function<bool()>, TR_NUM_PREFERRED_TRANSPORT>{
|
||||
{ TR_PREFER_UTP,
|
||||
[&]()
|
||||
{
|
||||
#ifdef WITH_UTP
|
||||
if (utp)
|
||||
{
|
||||
auto* const sock = utp_create_socket(session->utp_context);
|
||||
utp_set_userdata(sock, peer_io.get());
|
||||
peer_io->set_socket(tr_peer_socket{ socket_address, sock });
|
||||
if (utp)
|
||||
{
|
||||
auto* const sock = utp_create_socket(session->utp_context);
|
||||
utp_set_userdata(sock, peer_io.get());
|
||||
peer_io->set_socket(tr_peer_socket{ socket_address, sock });
|
||||
|
||||
auto const [ss, sslen] = socket_address.to_sockaddr();
|
||||
if (utp_connect(sock, reinterpret_cast<sockaddr const*>(&ss), sslen) == 0)
|
||||
{
|
||||
return peer_io;
|
||||
}
|
||||
}
|
||||
auto const [ss, sslen] = socket_address.to_sockaddr();
|
||||
if (utp_connect(sock, reinterpret_cast<sockaddr const*>(&ss), sslen) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
} },
|
||||
{ TR_PREFER_TCP,
|
||||
[&]()
|
||||
{
|
||||
if (!peer_io->socket_.is_valid())
|
||||
{
|
||||
if (auto sock = tr_netOpenPeerSocket(session, socket_address, is_seed); sock.is_valid())
|
||||
{
|
||||
peer_io->set_socket(std::move(sock));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} }
|
||||
};
|
||||
|
||||
if (!peer_io->socket_.is_valid())
|
||||
if (func.at(preferred)())
|
||||
{
|
||||
if (auto sock = tr_netOpenPeerSocket(session, socket_address, is_seed); sock.is_valid())
|
||||
return peer_io;
|
||||
}
|
||||
for (preferred_key_t i = 0U; i < TR_NUM_PREFERRED_TRANSPORT; ++i)
|
||||
{
|
||||
if (i != preferred && func.at(i)())
|
||||
{
|
||||
peer_io->set_socket(std::move(sock));
|
||||
return peer_io;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,14 @@ enum ReadState
|
|||
READ_ERR
|
||||
};
|
||||
|
||||
enum tr_preferred_transport : uint8_t
|
||||
{
|
||||
// More preferred transports goes on top
|
||||
TR_PREFER_UTP,
|
||||
TR_PREFER_TCP,
|
||||
TR_NUM_PREFERRED_TRANSPORT
|
||||
};
|
||||
|
||||
class tr_peerIo final : public std::enable_shared_from_this<tr_peerIo>
|
||||
{
|
||||
using DH = tr_message_stream_encryption::DH;
|
||||
|
|
|
@ -1349,7 +1349,7 @@ std::vector<tr_pex> tr_peerMgrGetPeers(tr_torrent const* tor, uint8_t address_ty
|
|||
for (auto const* const info : infos)
|
||||
{
|
||||
auto const& socket_address = info->listen_socket_address();
|
||||
auto const& addr = socket_address.address();
|
||||
[[maybe_unused]] auto const& addr = socket_address.address();
|
||||
|
||||
TR_ASSERT(addr.is_valid());
|
||||
TR_ASSERT(addr.type == address_type);
|
||||
|
|
|
@ -16,7 +16,7 @@ using namespace std::literals;
|
|||
namespace
|
||||
{
|
||||
|
||||
auto constexpr MyStatic = std::array<std::string_view, 404>{ ""sv,
|
||||
auto constexpr MyStatic = std::array<std::string_view, 405>{ ""sv,
|
||||
"activeTorrentCount"sv,
|
||||
"activity-date"sv,
|
||||
"activityDate"sv,
|
||||
|
@ -247,6 +247,7 @@ auto constexpr MyStatic = std::array<std::string_view, 404>{ ""sv,
|
|||
"port-forwarding-enabled"sv,
|
||||
"port-is-open"sv,
|
||||
"preallocation"sv,
|
||||
"preferred-transport"sv,
|
||||
"prefetch-enabled"sv,
|
||||
"primary-mime-type"sv,
|
||||
"priorities"sv,
|
||||
|
|
|
@ -252,6 +252,7 @@ enum
|
|||
TR_KEY_port_forwarding_enabled,
|
||||
TR_KEY_port_is_open,
|
||||
TR_KEY_preallocation,
|
||||
TR_KEY_preferred_transport,
|
||||
TR_KEY_prefetch_enabled,
|
||||
TR_KEY_primary_mime_type,
|
||||
TR_KEY_priorities,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "libtransmission/log.h" // for tr_log_level
|
||||
#include "libtransmission/net.h" // for tr_port, tr_tos_t
|
||||
#include "libtransmission/peer-io.h" // tr_preferred_transport
|
||||
#include "libtransmission/quark.h"
|
||||
|
||||
struct tr_variant;
|
||||
|
@ -76,6 +77,7 @@ struct tr_variant;
|
|||
V(TR_KEY_umask, umask, tr_mode_t, 022, "") \
|
||||
V(TR_KEY_upload_slots_per_torrent, upload_slots_per_torrent, size_t, 8U, "") \
|
||||
V(TR_KEY_utp_enabled, utp_enabled, bool, true, "") \
|
||||
V(TR_KEY_preferred_transport, preferred_transport, tr_preferred_transport, TR_PREFER_UTP, "") \
|
||||
V(TR_KEY_torrent_added_verify_mode, torrent_added_verify_mode, tr_verify_added_mode, TR_VERIFY_ADDED_FAST, "")
|
||||
|
||||
struct tr_session_settings
|
||||
|
|
|
@ -783,6 +783,11 @@ public:
|
|||
|
||||
[[nodiscard]] bool allowsUTP() const noexcept;
|
||||
|
||||
[[nodiscard]] constexpr auto preferred_transport() const noexcept
|
||||
{
|
||||
return settings_.preferred_transport;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto allowsPrefetch() const noexcept
|
||||
{
|
||||
return settings_.is_prefetch_enabled;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "libtransmission/log.h" // for tr_log_level
|
||||
#include "libtransmission/net.h" // for tr_port
|
||||
#include "libtransmission/peer-io.h" // tr_preferred_transport
|
||||
#include "libtransmission/utils.h" // for tr_strv_strip(), tr_strlower()
|
||||
#include "libtransmission/variant.h"
|
||||
|
||||
|
@ -52,6 +53,12 @@ auto constexpr VerifyModeKeys = std::array<std::pair<std::string_view, tr_verify
|
|||
{ "fast", TR_VERIFY_ADDED_FAST },
|
||||
{ "full", TR_VERIFY_ADDED_FULL },
|
||||
} };
|
||||
|
||||
auto constexpr PreferredTransportKeys = std::
|
||||
array<std::pair<std::string_view, tr_preferred_transport>, TR_NUM_PREFERRED_TRANSPORT>{ {
|
||||
{ "utp", TR_PREFER_UTP },
|
||||
{ "tcp", TR_PREFER_TCP },
|
||||
} };
|
||||
} // namespace
|
||||
|
||||
namespace libtransmission
|
||||
|
@ -260,6 +267,54 @@ tr_variant VariantConverter::save<tr_preallocation_mode>(tr_preallocation_mode c
|
|||
|
||||
// ---
|
||||
|
||||
template<>
|
||||
std::optional<tr_preferred_transport> VariantConverter::load<tr_preferred_transport>(tr_variant const& src)
|
||||
{
|
||||
static constexpr auto Keys = PreferredTransportKeys;
|
||||
|
||||
if (auto const* val = src.get_if<std::string_view>(); val != nullptr)
|
||||
{
|
||||
auto const needle = tr_strlower(tr_strv_strip(*val));
|
||||
|
||||
for (auto const& [name, value] : Keys)
|
||||
{
|
||||
if (name == needle)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto const* val = src.get_if<int64_t>(); val != nullptr)
|
||||
{
|
||||
for (auto const& [name, value] : Keys)
|
||||
{
|
||||
if (value == *val)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
tr_variant VariantConverter::save<tr_preferred_transport>(tr_preferred_transport const& val)
|
||||
{
|
||||
for (auto const& [key, value] : PreferredTransportKeys)
|
||||
{
|
||||
if (value == val)
|
||||
{
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int64_t>(val);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
template<>
|
||||
std::optional<size_t> VariantConverter::load<size_t>(tr_variant const& src)
|
||||
{
|
||||
|
|
|
@ -411,3 +411,44 @@ TEST_F(SettingsTest, canSaveVerify)
|
|||
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
|
||||
EXPECT_EQ("full", val);
|
||||
}
|
||||
|
||||
TEST_F(SettingsTest, canLoadPreferredTransport)
|
||||
{
|
||||
static auto constexpr Key = TR_KEY_preferred_transport;
|
||||
auto constexpr ExpectedValue = TR_PREFER_TCP;
|
||||
|
||||
auto settings = std::make_unique<tr_session_settings>();
|
||||
auto const default_value = settings->preferred_transport;
|
||||
ASSERT_NE(ExpectedValue, default_value);
|
||||
|
||||
auto var = tr_variant{};
|
||||
tr_variantInitDict(&var, 1);
|
||||
tr_variantDictAddInt(&var, Key, ExpectedValue);
|
||||
settings->load(var);
|
||||
EXPECT_EQ(ExpectedValue, settings->preferred_transport);
|
||||
var.clear();
|
||||
|
||||
settings = std::make_unique<tr_session_settings>();
|
||||
tr_variantInitDict(&var, 1);
|
||||
tr_variantDictAddStrView(&var, Key, "tcp");
|
||||
settings->load(var);
|
||||
EXPECT_EQ(ExpectedValue, settings->preferred_transport);
|
||||
}
|
||||
|
||||
TEST_F(SettingsTest, canSavePreferredTransport)
|
||||
{
|
||||
static auto constexpr Key = TR_KEY_preferred_transport;
|
||||
static auto constexpr ExpectedValue = TR_PREFER_TCP;
|
||||
|
||||
auto settings = tr_session_settings{};
|
||||
auto const default_value = settings.preferred_transport;
|
||||
ASSERT_NE(ExpectedValue, default_value);
|
||||
|
||||
auto var = tr_variant{};
|
||||
tr_variantInitDict(&var, 100);
|
||||
settings.preferred_transport = ExpectedValue;
|
||||
var = settings.settings();
|
||||
auto val = std::string_view{};
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val));
|
||||
EXPECT_EQ("tcp", val);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue