refactor: replace tr_boundinfo with tr_session::BoundSocket (#4103)
This commit is contained in:
parent
bf17a3baf1
commit
36edd516aa
|
@ -372,14 +372,16 @@ void Blocklist::ensureLoaded() const
|
|||
{
|
||||
// bad binary file; try to rebuild it
|
||||
in.close();
|
||||
auto src_file = std::string_view{ bin_file_ };
|
||||
src_file.remove_suffix(std::size(BinFileSuffix));
|
||||
rules_ = parseFile(src_file);
|
||||
if (!std::empty(rules_))
|
||||
auto const sz_src_file = std::string{ std::data(bin_file_), std::size(bin_file_) - std::size(BinFileSuffix) };
|
||||
if (tr_sys_path_exists(sz_src_file))
|
||||
{
|
||||
tr_logAddInfo(_("Rewriting old blocklist file format to new format"));
|
||||
tr_sys_path_remove(bin_file_);
|
||||
save(bin_file_, std::data(rules_), std::size(rules_));
|
||||
rules_ = parseFile(sz_src_file);
|
||||
if (!std::empty(rules_))
|
||||
{
|
||||
tr_logAddInfo(_("Rewriting old blocklist file format to new format"));
|
||||
tr_sys_path_remove(bin_file_);
|
||||
save(bin_file_, std::data(rules_), std::size(rules_));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -43,10 +43,6 @@
|
|||
#define IN_MULTICAST(a) (((a)&0xf0000000) == 0xe0000000)
|
||||
#endif
|
||||
|
||||
tr_address const tr_in6addr_any = { TR_AF_INET6, { IN6ADDR_ANY_INIT } };
|
||||
|
||||
tr_address const tr_inaddr_any = { TR_AF_INET, { { { { INADDR_ANY } } } } };
|
||||
|
||||
std::string tr_net_strerror(int err)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -392,13 +388,13 @@ void tr_netClosePeerSocket(tr_session* session, tr_peer_socket socket)
|
|||
}
|
||||
}
|
||||
|
||||
static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool suppress_msgs, int* err_out)
|
||||
static tr_socket_t tr_netBindTCPImpl(tr_address const& addr, tr_port port, bool suppress_msgs, int* err_out)
|
||||
{
|
||||
TR_ASSERT(tr_address_is_valid(addr));
|
||||
TR_ASSERT(tr_address_is_valid(&addr));
|
||||
|
||||
static auto constexpr Domains = std::array<int, NUM_TR_AF_INET_TYPES>{ AF_INET, AF_INET6 };
|
||||
|
||||
auto const fd = socket(Domains[addr->type], SOCK_STREAM, 0);
|
||||
auto const fd = socket(Domains[addr.type], SOCK_STREAM, 0);
|
||||
if (fd == TR_BAD_SOCKET)
|
||||
{
|
||||
*err_out = sockerrno;
|
||||
|
@ -418,7 +414,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
|
|||
|
||||
#ifdef IPV6_V6ONLY
|
||||
|
||||
if (addr->isIPv6() &&
|
||||
if (addr.isIPv6() &&
|
||||
(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char const*>(&optval), sizeof(optval)) == -1) &&
|
||||
(sockerrno != ENOPROTOOPT)) // if the kernel doesn't support it, ignore it
|
||||
{
|
||||
|
@ -429,7 +425,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
|
|||
|
||||
#endif
|
||||
|
||||
auto const [sock, addrlen] = addr->toSockaddr(port);
|
||||
auto const [sock, addrlen] = addr.toSockaddr(port);
|
||||
|
||||
if (bind(fd, (struct sockaddr*)&sock, addrlen) == -1)
|
||||
{
|
||||
|
@ -441,7 +437,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
|
|||
err == EADDRINUSE ?
|
||||
_("Couldn't bind port {port} on {address}: {error} ({error_code}) -- Is another copy of Transmission already running?") :
|
||||
_("Couldn't bind port {port} on {address}: {error} ({error_code})"),
|
||||
fmt::arg("address", addr->readable()),
|
||||
fmt::arg("address", addr.readable()),
|
||||
fmt::arg("port", port.host()),
|
||||
fmt::arg("error", tr_net_strerror(err)),
|
||||
fmt::arg("error_code", err)));
|
||||
|
@ -454,7 +450,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
|
|||
|
||||
if (!suppress_msgs)
|
||||
{
|
||||
tr_logAddDebug(fmt::format(FMT_STRING("Bound socket {:d} to port {:d} on {:s}"), fd, port.host(), addr->readable()));
|
||||
tr_logAddDebug(fmt::format(FMT_STRING("Bound socket {:d} to port {:d} on {:s}"), fd, port.host(), addr.readable()));
|
||||
}
|
||||
|
||||
#ifdef TCP_FASTOPEN
|
||||
|
@ -483,7 +479,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
|
|||
return fd;
|
||||
}
|
||||
|
||||
tr_socket_t tr_netBindTCP(tr_address const* addr, tr_port port, bool suppress_msgs)
|
||||
tr_socket_t tr_netBindTCP(tr_address const& addr, tr_port port, bool suppress_msgs)
|
||||
{
|
||||
int unused = 0;
|
||||
return tr_netBindTCPImpl(addr, port, suppress_msgs, &unused);
|
||||
|
@ -497,7 +493,7 @@ bool tr_net_hasIPv6(tr_port port)
|
|||
if (!already_done)
|
||||
{
|
||||
int err = 0;
|
||||
auto const fd = tr_netBindTCPImpl(&tr_in6addr_any, port, true, &err);
|
||||
auto const fd = tr_netBindTCPImpl(tr_address::AnyIPv4(), port, true, &err);
|
||||
|
||||
if (fd != TR_BAD_SOCKET || err != EAFNOSUPPORT) /* we support ipv6 */
|
||||
{
|
||||
|
|
|
@ -263,10 +263,17 @@ struct tr_address
|
|||
struct in6_addr addr6;
|
||||
struct in_addr addr4;
|
||||
} addr;
|
||||
};
|
||||
|
||||
extern tr_address const tr_inaddr_any;
|
||||
extern tr_address const tr_in6addr_any;
|
||||
[[nodiscard]] static auto constexpr AnyIPv4() noexcept
|
||||
{
|
||||
return tr_address{ TR_AF_INET, { { { { INADDR_ANY } } } } };
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto constexpr AnyIPv6() noexcept
|
||||
{
|
||||
return tr_address{ TR_AF_INET6, { IN6ADDR_ANY_INIT } };
|
||||
}
|
||||
};
|
||||
|
||||
bool tr_address_is_valid_for_peers(tr_address const* addr, tr_port port);
|
||||
|
||||
|
@ -281,7 +288,7 @@ constexpr bool tr_address_is_valid(tr_address const* a)
|
|||
|
||||
struct tr_session;
|
||||
|
||||
tr_socket_t tr_netBindTCP(tr_address const* addr, tr_port port, bool suppress_msgs);
|
||||
tr_socket_t tr_netBindTCP(tr_address const& addr, tr_port port, bool suppress_msgs);
|
||||
|
||||
[[nodiscard]] std::optional<std::tuple<tr_address, tr_port, tr_socket_t>> tr_netAccept(
|
||||
tr_session* session,
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
tr_port_forwarding_impl& operator=(tr_port_forwarding_impl&&) = delete;
|
||||
tr_port_forwarding_impl& operator=(tr_port_forwarding_impl const&) = delete;
|
||||
|
||||
void portChanged() override
|
||||
void localPortChanged() override
|
||||
{
|
||||
if (!is_enabled_)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,6 @@ public:
|
|||
[[nodiscard]] virtual bool isEnabled() const = 0;
|
||||
[[nodiscard]] virtual tr_port_forwarding_state state() const = 0;
|
||||
|
||||
virtual void portChanged() = 0;
|
||||
virtual void localPortChanged() = 0;
|
||||
virtual void setEnabled(bool enabled) = 0;
|
||||
};
|
||||
|
|
|
@ -65,8 +65,6 @@ using namespace std::literals;
|
|||
|
||||
std::recursive_mutex tr_session::session_mutex_;
|
||||
|
||||
static auto constexpr DefaultBindAddressIpv4 = "0.0.0.0"sv;
|
||||
static auto constexpr DefaultBindAddressIpv6 = "::"sv;
|
||||
static auto constexpr SaveIntervalSecs = 360s;
|
||||
|
||||
static void bandwidthGroupRead(tr_session* session, std::string_view config_dir);
|
||||
|
@ -257,7 +255,50 @@ void tr_sessionSetEncryption(tr_session* session, tr_encryption_mode mode)
|
|||
****
|
||||
***/
|
||||
|
||||
void tr_session::tr_bindinfo::close()
|
||||
void tr_session::onIncomingPeerConnection(tr_socket_t fd, void* vsession)
|
||||
{
|
||||
auto* session = static_cast<tr_session*>(vsession);
|
||||
|
||||
if (auto const incoming_info = tr_netAccept(session, fd); incoming_info)
|
||||
{
|
||||
auto const& [addr, port, sock] = *incoming_info;
|
||||
tr_logAddTrace(fmt::format("new incoming connection {} ({})", sock, addr.readable(port)));
|
||||
session->addIncoming(addr, port, tr_peer_socket_tcp_create(sock));
|
||||
}
|
||||
}
|
||||
|
||||
tr_session::BoundSocket::BoundSocket(
|
||||
event_base* evbase,
|
||||
tr_address const& addr,
|
||||
tr_port port,
|
||||
IncomingCallback cb,
|
||||
void* cb_data)
|
||||
: cb_{ cb }
|
||||
, cb_data_{ cb_data }
|
||||
, socket_{ tr_netBindTCP(addr, port, false) }
|
||||
{
|
||||
if (socket_ == TR_BAD_SOCKET)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tr_logAddInfo(
|
||||
fmt::format(_("Listening to incoming peer connections on {hostport}"), fmt::arg("hostport", addr.readable(port))));
|
||||
|
||||
ev_ = event_new(
|
||||
evbase,
|
||||
socket_,
|
||||
EV_READ | EV_PERSIST,
|
||||
[](evutil_socket_t fd, short /*evtype*/, void* vself)
|
||||
{
|
||||
auto* const self = static_cast<BoundSocket*>(vself);
|
||||
self->cb_(fd, self->cb_data_);
|
||||
},
|
||||
this);
|
||||
event_add(ev_, nullptr);
|
||||
}
|
||||
|
||||
tr_session::BoundSocket::~BoundSocket()
|
||||
{
|
||||
if (ev_ != nullptr)
|
||||
{
|
||||
|
@ -272,49 +313,24 @@ void tr_session::tr_bindinfo::close()
|
|||
}
|
||||
}
|
||||
|
||||
static void acceptIncomingPeer(evutil_socket_t fd, short /*what*/, void* vsession)
|
||||
{
|
||||
auto* session = static_cast<tr_session*>(vsession);
|
||||
|
||||
if (auto const incoming_info = tr_netAccept(session, fd); incoming_info)
|
||||
{
|
||||
auto const& [addr, port, sock] = *incoming_info;
|
||||
tr_logAddTrace(fmt::format("new incoming connection {} ({})", sock, addr.readable(port)));
|
||||
session->addIncoming(addr, port, tr_peer_socket_tcp_create(sock));
|
||||
}
|
||||
}
|
||||
|
||||
void tr_session::tr_bindinfo::bindAndListenForIncomingPeers(tr_session* session)
|
||||
{
|
||||
TR_ASSERT(session->allowsTCP());
|
||||
|
||||
auto const& port = session->localPeerPort();
|
||||
|
||||
socket_ = tr_netBindTCP(&addr_, port, false);
|
||||
|
||||
if (socket_ != TR_BAD_SOCKET)
|
||||
{
|
||||
tr_logAddInfo(
|
||||
fmt::format(_("Listening to incoming peer connections on {hostport}"), fmt::arg("hostport", addr_.readable(port))));
|
||||
ev_ = event_new(session->eventBase(), socket_, EV_READ | EV_PERSIST, acceptIncomingPeer, session);
|
||||
event_add(ev_, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
tr_session::PublicAddressResult tr_session::publicAddress(tr_address_type type) const noexcept
|
||||
{
|
||||
switch (type)
|
||||
if (type == TR_AF_INET)
|
||||
{
|
||||
case TR_AF_INET:
|
||||
return { bind_ipv4_.addr_, bind_ipv4_.addr_.readable() == DefaultBindAddressIpv4 };
|
||||
|
||||
case TR_AF_INET6:
|
||||
return { bind_ipv6_.addr_, bind_ipv6_.addr_.readable() == DefaultBindAddressIpv6 };
|
||||
|
||||
default:
|
||||
TR_ASSERT_MSG(false, "invalid type");
|
||||
return {};
|
||||
static auto constexpr DefaultAddr = tr_address::AnyIPv4();
|
||||
auto addr = tr_address::fromString(settings_.bind_address_ipv4).value_or(DefaultAddr);
|
||||
return { addr, addr == DefaultAddr };
|
||||
}
|
||||
|
||||
if (type == TR_AF_INET6)
|
||||
{
|
||||
static auto constexpr DefaultAddr = tr_address::AnyIPv6();
|
||||
auto addr = tr_address::fromString(settings_.bind_address_ipv6).value_or(DefaultAddr);
|
||||
return { addr, addr == DefaultAddr };
|
||||
}
|
||||
|
||||
TR_ASSERT_MSG(false, "invalid type");
|
||||
return {};
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -529,8 +545,6 @@ void tr_session::initImpl(init_data& data)
|
|||
|
||||
setSettings(client_settings, true);
|
||||
|
||||
this->udp_core_ = std::make_unique<tr_session::tr_udp_core>(*this, udpPort());
|
||||
|
||||
if (this->allowsLPD())
|
||||
{
|
||||
this->lpd_ = tr_lpd::create(lpd_mediator_, eventBase());
|
||||
|
@ -548,14 +562,25 @@ static void updateBandwidth(tr_session* session, tr_direction dir);
|
|||
void tr_session::setSettings(tr_variant* settings_dict, bool force)
|
||||
{
|
||||
TR_ASSERT(amInSessionThread());
|
||||
TR_ASSERT(tr_variantIsDict(settings_dict));
|
||||
|
||||
auto* const settings = settings_dict;
|
||||
TR_ASSERT(tr_variantIsDict(settings));
|
||||
// load the session settings
|
||||
auto new_settings = tr_session_settings{};
|
||||
new_settings.load(settings_dict);
|
||||
setSettings(std::move(new_settings), force);
|
||||
|
||||
// update the `settings_` field
|
||||
auto const old_settings = settings_;
|
||||
auto& new_settings = settings_;
|
||||
new_settings.load(settings);
|
||||
// delegate loading out the other settings
|
||||
alt_speeds_.load(settings_dict);
|
||||
rpc_server_->load(settings_dict);
|
||||
}
|
||||
|
||||
void tr_session::setSettings(tr_session_settings settings_in, bool force)
|
||||
{
|
||||
auto const lock = unique_lock();
|
||||
|
||||
std::swap(settings_, settings_in);
|
||||
auto const& new_settings = settings_;
|
||||
auto const& old_settings = settings_in;
|
||||
|
||||
// the rest of the func is session_ responding to settings changes
|
||||
|
||||
|
@ -581,51 +606,65 @@ void tr_session::setSettings(tr_variant* settings_dict, bool force)
|
|||
setDefaultTrackers(val);
|
||||
}
|
||||
|
||||
if (auto val = bool{}; tr_variantDictFindBool(settings, TR_KEY_dht_enabled, &val))
|
||||
{
|
||||
tr_sessionSetDHTEnabled(this, val);
|
||||
}
|
||||
|
||||
if (auto const& val = new_settings.utp_enabled; force || val != old_settings.utp_enabled)
|
||||
{
|
||||
tr_sessionSetUTPEnabled(this, val);
|
||||
}
|
||||
|
||||
if (auto const& val = new_settings.lpd_enabled; force || val != old_settings.lpd_enabled)
|
||||
{
|
||||
tr_sessionSetLPDEnabled(this, val);
|
||||
}
|
||||
|
||||
useBlocklist(new_settings.blocklist_enabled);
|
||||
|
||||
/// bound addresses, peer port, port forwarding
|
||||
auto local_peer_port = force && settings_.peer_port_random_on_start ? randomPort() : new_settings.peer_port;
|
||||
bool port_changed = false;
|
||||
if (force || local_peer_port_ != local_peer_port)
|
||||
{
|
||||
auto port_needs_update = force;
|
||||
local_peer_port_ = local_peer_port;
|
||||
advertised_peer_port_ = local_peer_port;
|
||||
port_changed = true;
|
||||
}
|
||||
|
||||
if (auto const& val = new_settings.bind_address_ipv4; force || val != old_settings.bind_address_ipv4)
|
||||
if (new_settings.tcp_enabled)
|
||||
{
|
||||
if (auto const& val = new_settings.bind_address_ipv4; force || port_changed || val != old_settings.bind_address_ipv4)
|
||||
{
|
||||
if (auto const addr = tr_address::fromString(val); addr && addr->isIPv4())
|
||||
{
|
||||
this->bind_ipv4_ = tr_bindinfo{ *addr };
|
||||
port_needs_update |= true;
|
||||
}
|
||||
auto const [addr, is_default] = publicAddress(TR_AF_INET);
|
||||
bound_ipv4_.emplace(eventBase(), addr, local_peer_port_, &tr_session::onIncomingPeerConnection, this);
|
||||
}
|
||||
|
||||
if (auto const& val = new_settings.bind_address_ipv6; force || val != old_settings.bind_address_ipv6)
|
||||
if (auto const& val = new_settings.bind_address_ipv6; force || port_changed || val != old_settings.bind_address_ipv6)
|
||||
{
|
||||
if (auto const addr = tr_address::fromString(val); addr && addr->isIPv6())
|
||||
{
|
||||
this->bind_ipv6_ = tr_bindinfo{ *addr };
|
||||
port_needs_update |= true;
|
||||
}
|
||||
auto const [addr, is_default] = publicAddress(TR_AF_INET6);
|
||||
bound_ipv6_.emplace(eventBase(), addr, local_peer_port_, &tr_session::onIncomingPeerConnection, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bound_ipv4_.reset();
|
||||
bound_ipv6_.reset();
|
||||
}
|
||||
|
||||
port_needs_update |= (new_settings.port_forwarding_enabled != old_settings.port_forwarding_enabled);
|
||||
if (port_changed)
|
||||
{
|
||||
port_forwarding_->localPortChanged();
|
||||
}
|
||||
|
||||
if (port_needs_update)
|
||||
bool const dht_changed = new_settings.dht_enabled != old_settings.dht_enabled;
|
||||
|
||||
if (!udp_core_ || force || port_changed || dht_changed)
|
||||
{
|
||||
udp_core_ = std::make_unique<tr_session::tr_udp_core>(*this, udpPort());
|
||||
}
|
||||
|
||||
// Sends out announce messages with advertisedPeerPort(), so this
|
||||
// section neesd be happen here after the peer port settings changes
|
||||
if (auto const& val = new_settings.lpd_enabled; force || val != old_settings.lpd_enabled)
|
||||
{
|
||||
if (val)
|
||||
{
|
||||
setPeerPort(isPortRandom() ? randomPort() : new_settings.peer_port);
|
||||
tr_sessionSetPortForwardingEnabled(this, new_settings.port_forwarding_enabled);
|
||||
lpd_ = tr_lpd::create(lpd_mediator_, eventBase());
|
||||
}
|
||||
else
|
||||
{
|
||||
lpd_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,9 +672,6 @@ void tr_session::setSettings(tr_variant* settings_dict, bool force)
|
|||
// It's a harmless call, so just call it instead of checking for settings changes
|
||||
updateBandwidth(this, TR_UP);
|
||||
updateBandwidth(this, TR_DOWN);
|
||||
|
||||
alt_speeds_.load(settings);
|
||||
rpc_server_->load(settings);
|
||||
}
|
||||
|
||||
void tr_sessionSet(tr_session* session, tr_variant* settings)
|
||||
|
@ -740,44 +776,20 @@ bool tr_sessionIsIncompleteDirEnabled(tr_session const* session)
|
|||
**** Peer Port
|
||||
***/
|
||||
|
||||
void tr_session::setPeerPort(tr_port port_in)
|
||||
{
|
||||
auto const in_session_thread = [this](tr_port port)
|
||||
{
|
||||
auto const lock = unique_lock();
|
||||
|
||||
auto& private_peer_port = settings_.peer_port;
|
||||
private_peer_port = port;
|
||||
advertised_peer_port_ = port;
|
||||
|
||||
closePeerPort();
|
||||
|
||||
if (allowsTCP())
|
||||
{
|
||||
bind_ipv4_.bindAndListenForIncomingPeers(this);
|
||||
|
||||
if (tr_net_hasIPv6(private_peer_port))
|
||||
{
|
||||
bind_ipv6_.bindAndListenForIncomingPeers(this);
|
||||
}
|
||||
}
|
||||
|
||||
port_forwarding_->portChanged();
|
||||
|
||||
for (auto* const tor : torrents())
|
||||
{
|
||||
tr_torrentChangeMyPort(tor);
|
||||
}
|
||||
};
|
||||
|
||||
runInSessionThread(in_session_thread, port_in);
|
||||
}
|
||||
|
||||
void tr_sessionSetPeerPort(tr_session* session, uint16_t hport)
|
||||
{
|
||||
TR_ASSERT(session != nullptr);
|
||||
|
||||
session->setPeerPort(tr_port::fromHost(hport));
|
||||
if (auto const port = tr_port::fromHost(hport); port != session->localPeerPort())
|
||||
{
|
||||
session->runInSessionThread(
|
||||
[session, port]()
|
||||
{
|
||||
auto settings = session->settings_;
|
||||
settings.peer_port = port;
|
||||
session->setSettings(std::move(settings), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t tr_sessionGetPeerPort(tr_session const* session)
|
||||
|
@ -1175,7 +1187,8 @@ void tr_session::closeImplPart1()
|
|||
rpc_server_.reset();
|
||||
lpd_.reset();
|
||||
port_forwarding_.reset();
|
||||
closePeerPort();
|
||||
bound_ipv6_.reset();
|
||||
bound_ipv4_.reset();
|
||||
|
||||
// tell other items to start shutting down
|
||||
udp_core_->startShutdown();
|
||||
|
@ -1389,18 +1402,16 @@ void tr_sessionSetDHTEnabled(tr_session* session, bool enabled)
|
|||
{
|
||||
TR_ASSERT(session != nullptr);
|
||||
|
||||
if (enabled == session->allowsDHT())
|
||||
if (enabled != session->allowsDHT())
|
||||
{
|
||||
return;
|
||||
session->runInSessionThread(
|
||||
[session, enabled]()
|
||||
{
|
||||
auto settings = session->settings_;
|
||||
settings.dht_enabled = enabled;
|
||||
session->setSettings(std::move(settings), false);
|
||||
});
|
||||
}
|
||||
|
||||
session->runInSessionThread(
|
||||
[session, enabled]()
|
||||
{
|
||||
session->udp_core_.reset();
|
||||
session->settings_.dht_enabled = enabled;
|
||||
session->udp_core_ = std::make_unique<tr_session::tr_udp_core>(*session, session->udpPort());
|
||||
});
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -1439,21 +1450,16 @@ void tr_sessionSetLPDEnabled(tr_session* session, bool enabled)
|
|||
{
|
||||
TR_ASSERT(session != nullptr);
|
||||
|
||||
if (enabled == session->allowsLPD())
|
||||
if (enabled != session->allowsLPD())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
session->runInSessionThread(
|
||||
[session, enabled]()
|
||||
{
|
||||
session->lpd_.reset();
|
||||
session->settings_.lpd_enabled = enabled;
|
||||
if (enabled)
|
||||
session->runInSessionThread(
|
||||
[session, enabled]()
|
||||
{
|
||||
session->lpd_ = tr_lpd::create(session->lpd_mediator_, session->eventBase());
|
||||
}
|
||||
});
|
||||
auto settings = session->settings_;
|
||||
settings.lpd_enabled = enabled;
|
||||
session->setSettings(std::move(settings), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool tr_sessionIsLPDEnabled(tr_session const* session)
|
||||
|
|
|
@ -77,25 +77,22 @@ class SessionTest;
|
|||
struct tr_session
|
||||
{
|
||||
private:
|
||||
struct tr_bindinfo
|
||||
class BoundSocket
|
||||
{
|
||||
explicit tr_bindinfo(tr_address addr)
|
||||
: addr_{ std::move(addr) }
|
||||
{
|
||||
}
|
||||
public:
|
||||
using IncomingCallback = void (*)(tr_socket_t, void*);
|
||||
BoundSocket(struct event_base*, tr_address const& addr, tr_port port, IncomingCallback cb, void* cb_data);
|
||||
BoundSocket(BoundSocket&&) = delete;
|
||||
BoundSocket(BoundSocket const&) = delete;
|
||||
BoundSocket operator=(BoundSocket&&) = delete;
|
||||
BoundSocket operator=(BoundSocket const&) = delete;
|
||||
~BoundSocket();
|
||||
|
||||
void bindAndListenForIncomingPeers(tr_session* session);
|
||||
|
||||
void close();
|
||||
|
||||
[[nodiscard]] auto readable() const
|
||||
{
|
||||
return addr_.readable();
|
||||
}
|
||||
|
||||
tr_address addr_;
|
||||
struct event* ev_ = nullptr;
|
||||
private:
|
||||
IncomingCallback cb_;
|
||||
void* cb_data_;
|
||||
tr_socket_t socket_ = TR_BAD_SOCKET;
|
||||
struct event* ev_ = nullptr;
|
||||
};
|
||||
|
||||
class AltSpeedMediator final : public tr_session_alt_speeds::Mediator
|
||||
|
@ -155,7 +152,7 @@ private:
|
|||
|
||||
[[nodiscard]] tr_address incomingPeerAddress() const override
|
||||
{
|
||||
return session_.bind_ipv4_.addr_;
|
||||
return session_.publicAddress(TR_AF_INET).address;
|
||||
}
|
||||
|
||||
[[nodiscard]] tr_port localPeerPort() const override
|
||||
|
@ -625,7 +622,15 @@ public:
|
|||
// that Transmission is running on.
|
||||
[[nodiscard]] constexpr tr_port localPeerPort() const noexcept
|
||||
{
|
||||
return settings_.peer_port;
|
||||
return local_peer_port_;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr tr_port udpPort() const noexcept
|
||||
{
|
||||
// Always use the same port number that's used for incoming TCP connections.
|
||||
// This simplifies port forwarding and reduces the chance of confusion,
|
||||
// since incoming UDP and TCP connections will use the same port number
|
||||
return localPeerPort();
|
||||
}
|
||||
|
||||
// The incoming peer port that's been opened on the public-facing
|
||||
|
@ -637,14 +642,6 @@ public:
|
|||
return advertised_peer_port_;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr tr_port udpPort() const noexcept
|
||||
{
|
||||
// Always use the same port number that's used for incoming TCP connections.
|
||||
// This simplifies port forwarding and reduces the chance of confusion,
|
||||
// since incoming UDP and TCP connections will use the same port number
|
||||
return advertisedPeerPort();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto queueEnabled(tr_direction dir) const noexcept
|
||||
{
|
||||
return dir == TR_DOWN ? settings_.download_queue_enabled : settings_.seed_queue_enabled;
|
||||
|
@ -888,21 +885,18 @@ private:
|
|||
|
||||
void setPeerPort(tr_port port);
|
||||
|
||||
void closePeerPort()
|
||||
{
|
||||
bind_ipv4_.close();
|
||||
bind_ipv6_.close();
|
||||
}
|
||||
|
||||
struct init_data;
|
||||
void initImpl(init_data&);
|
||||
void setSettings(tr_variant* settings_dict, bool force);
|
||||
void setSettings(tr_session_settings settings, bool force);
|
||||
|
||||
void closeImplPart1();
|
||||
void closeImplPart2();
|
||||
|
||||
void onNowTimer();
|
||||
|
||||
static void onIncomingPeerConnection(tr_socket_t fd, void* vsession);
|
||||
|
||||
friend class libtransmission::test::SessionTest;
|
||||
friend struct tr_bindinfo;
|
||||
|
||||
|
@ -1028,6 +1022,12 @@ private:
|
|||
tr_altSpeedFunc alt_speed_active_changed_func_ = nullptr;
|
||||
void* alt_speed_active_changed_func_user_data_ = nullptr;
|
||||
|
||||
// The local peer port that we bind a socket to for listening
|
||||
// to incoming peer connections. Usually the same as
|
||||
// `settings_.peer_port` but can differ if
|
||||
// `settings_.peer_port_random_on_start` is enabled.
|
||||
tr_port local_peer_port_;
|
||||
|
||||
// The incoming peer port that's been opened on the public-facing
|
||||
// device. This is usually the same as localPeerPort() but can differ,
|
||||
// e.g. if the public device is a router that chose to use a different
|
||||
|
@ -1048,15 +1048,17 @@ private:
|
|||
|
||||
tr_session_id session_id_;
|
||||
|
||||
tr_open_files open_files_;
|
||||
|
||||
std::vector<libtransmission::Blocklist> blocklists_;
|
||||
|
||||
/// other fields
|
||||
|
||||
// depends-on: session_thread_
|
||||
tr_bindinfo bind_ipv4_ = tr_bindinfo{ tr_inaddr_any };
|
||||
// depends-on: session_thread_, settings_.bind_address_ipv4, local_peer_port_
|
||||
std::optional<BoundSocket> bound_ipv4_;
|
||||
|
||||
// depends-on: session_thread_
|
||||
tr_bindinfo bind_ipv6_ = tr_bindinfo{ tr_in6addr_any };
|
||||
// depends-on: session_thread_, settings_.bind_address_ipv6, local_peer_port_
|
||||
std::optional<BoundSocket> bound_ipv6_;
|
||||
|
||||
public:
|
||||
// depends-on: announcer_udp_
|
||||
|
@ -1070,7 +1072,7 @@ private:
|
|||
// depends-on: top_bandwidth_
|
||||
std::vector<std::pair<tr_interned_string, std::unique_ptr<tr_bandwidth>>> bandwidth_groups_;
|
||||
|
||||
// depends-on: settings_, timer_maker_
|
||||
// depends-on: timer_maker_, settings_, local_peer_port_
|
||||
PortForwardingMediator port_forwarding_mediator_{ *this };
|
||||
std::unique_ptr<tr_port_forwarding> port_forwarding_ = tr_port_forwarding::create(port_forwarding_mediator_);
|
||||
|
||||
|
@ -1078,8 +1080,6 @@ private:
|
|||
AltSpeedMediator alt_speed_mediator_{ *this };
|
||||
tr_session_alt_speeds alt_speeds_{ alt_speed_mediator_ };
|
||||
|
||||
tr_open_files open_files_;
|
||||
|
||||
// depends-on: open_files_
|
||||
tr_torrents torrents_;
|
||||
|
||||
|
@ -1095,7 +1095,7 @@ private:
|
|||
// depends-on: timer_maker_, top_bandwidth_, torrents_, web_
|
||||
std::unique_ptr<struct tr_peerMgr, void (*)(struct tr_peerMgr*)> peer_mgr_;
|
||||
|
||||
// depends-on: peer_mgr_, torrents_
|
||||
// depends-on: peer_mgr_, advertised_peer_port_, torrents_
|
||||
LpdMediator lpd_mediator_{ *this };
|
||||
|
||||
// depends-on: lpd_mediator_
|
||||
|
|
|
@ -32,6 +32,12 @@ TEST_F(NetTest, conversionsIPv4)
|
|||
EXPECT_EQ(Port, addrport->second);
|
||||
}
|
||||
|
||||
TEST_F(NetTest, trAddress)
|
||||
{
|
||||
EXPECT_EQ("0.0.0.0", tr_address::AnyIPv4().readable());
|
||||
EXPECT_EQ("::", tr_address::AnyIPv6().readable());
|
||||
}
|
||||
|
||||
TEST_F(NetTest, compact4)
|
||||
{
|
||||
static auto constexpr ExpectedReadable = "10.10.10.5"sv;
|
||||
|
|
Loading…
Reference in New Issue