mirror of
https://github.com/transmission/transmission
synced 2024-12-25 01:03:01 +00:00
fixup: dedup tr_rpc_address with tr_address (#5523)
* fixup: dedup tr_rpc_address with tr_address tr_rpc_address was duplicating a lot of work that tr_address was doing a lot better. Fall back to using tr_address for ipv4/ipv6 connections and make a tr_unix_addr for handling unix sockets. * remove unnecessary functions
This commit is contained in:
parent
ddac05954b
commit
23a52fa1c5
2 changed files with 96 additions and 102 deletions
|
@ -77,40 +77,102 @@ auto inline constexpr TrUnixAddrStrLen = size_t{ sizeof(((struct sockaddr_un*)nu
|
|||
|
||||
enum tr_rpc_address_type
|
||||
{
|
||||
TR_RPC_AF_INET,
|
||||
TR_RPC_AF_INET6,
|
||||
TR_RPC_AF_UNIX
|
||||
TR_RPC_INET_ADDR,
|
||||
TR_RPC_UNIX_ADDR
|
||||
};
|
||||
|
||||
class tr_unix_addr
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] std::string to_string() const
|
||||
{
|
||||
return std::empty(unix_socket_path_) ? unix_socket_path_ : std::string(TrUnixSocketPrefix);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool from_string(std::string_view src)
|
||||
{
|
||||
if (!tr_strvStartsWith(TrUnixSocketPrefix, src))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::size(src) >= TrUnixAddrStrLen)
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Unix socket path must be fewer than {count} characters (including '{prefix}' prefix)"),
|
||||
fmt::arg("count", TrUnixAddrStrLen - 1),
|
||||
fmt::arg("prefix", TrUnixSocketPrefix)));
|
||||
return false;
|
||||
}
|
||||
unix_socket_path_ = src;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string unix_socket_path_ = {};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
struct tr_rpc_address
|
||||
class tr_rpc_address
|
||||
{
|
||||
tr_rpc_address_type type;
|
||||
union
|
||||
public:
|
||||
tr_rpc_address()
|
||||
: inet_addr_(tr_address::any_ipv4())
|
||||
{
|
||||
struct in_addr addr4;
|
||||
struct in6_addr addr6;
|
||||
std::array<char, TrUnixAddrStrLen> unixSocketPath;
|
||||
} addr;
|
||||
|
||||
void set_inaddr_any()
|
||||
{
|
||||
type = TR_RPC_AF_INET;
|
||||
addr.addr4 = { INADDR_ANY };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto is_unix_addr() const noexcept
|
||||
{
|
||||
return type_ == TR_RPC_UNIX_ADDR;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto is_inet_addr() const noexcept
|
||||
{
|
||||
return type_ == TR_RPC_INET_ADDR;
|
||||
}
|
||||
|
||||
bool from_string(std::string_view src)
|
||||
{
|
||||
if (auto address = tr_address::from_string(src); address.has_value())
|
||||
{
|
||||
type_ = TR_RPC_INET_ADDR;
|
||||
inet_addr_ = address.value();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (unix_addr_.from_string(src))
|
||||
{
|
||||
type_ = TR_RPC_UNIX_ADDR;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string to_string(tr_port port = {}) const
|
||||
{
|
||||
if (type_ == TR_RPC_UNIX_ADDR)
|
||||
{
|
||||
return unix_addr_.to_string();
|
||||
}
|
||||
|
||||
if (port.empty())
|
||||
{
|
||||
return { inet_addr_.display_name() };
|
||||
}
|
||||
return { inet_addr_.display_name(port) };
|
||||
}
|
||||
|
||||
private:
|
||||
tr_rpc_address_type type_ = TR_RPC_INET_ADDR;
|
||||
struct tr_address inet_addr_;
|
||||
class tr_unix_addr unix_addr_;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
int constexpr DeflateLevel = 6; // medium / default
|
||||
|
||||
#ifdef TR_ENABLE_ASSERTS
|
||||
bool constexpr tr_rpc_address_is_valid(tr_rpc_address const& a)
|
||||
{
|
||||
return a.type == TR_RPC_AF_INET || a.type == TR_RPC_AF_INET6 || a.type == TR_RPC_AF_UNIX;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---
|
||||
|
||||
void send_simple_response(struct evhttp_request* req, int code, char const* text = nullptr)
|
||||
|
@ -534,73 +596,6 @@ auto constexpr ServerStartRetryCount = int{ 10 };
|
|||
auto constexpr ServerStartRetryDelayIncrement = 5s;
|
||||
auto constexpr ServerStartRetryMaxDelay = 60s;
|
||||
|
||||
char const* tr_rpc_address_to_string(tr_rpc_address const& addr, char* buf, size_t buflen)
|
||||
{
|
||||
TR_ASSERT(tr_rpc_address_is_valid(addr));
|
||||
|
||||
switch (addr.type)
|
||||
{
|
||||
case TR_RPC_AF_INET:
|
||||
return evutil_inet_ntop(AF_INET, &addr.addr, buf, buflen);
|
||||
|
||||
case TR_RPC_AF_INET6:
|
||||
return evutil_inet_ntop(AF_INET6, &addr.addr, buf, buflen);
|
||||
|
||||
case TR_RPC_AF_UNIX:
|
||||
tr_strlcpy(buf, std::data(addr.addr.unixSocketPath), buflen);
|
||||
return buf;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string tr_rpc_address_with_port(tr_rpc_server const* server)
|
||||
{
|
||||
auto addr_buf = std::array<char, TrUnixAddrStrLen>{};
|
||||
tr_rpc_address_to_string(*server->bind_address_, std::data(addr_buf), std::size(addr_buf));
|
||||
|
||||
std::string addr_port_str = std::data(addr_buf);
|
||||
if (server->bind_address_->type != TR_RPC_AF_UNIX)
|
||||
{
|
||||
addr_port_str.append(":" + std::to_string(server->port().host()));
|
||||
}
|
||||
return addr_port_str;
|
||||
}
|
||||
|
||||
bool tr_rpc_address_from_string(tr_rpc_address& dst, std::string_view src)
|
||||
{
|
||||
if (tr_strvStartsWith(src, TrUnixSocketPrefix))
|
||||
{
|
||||
if (std::size(src) >= TrUnixAddrStrLen)
|
||||
{
|
||||
tr_logAddError(fmt::format(
|
||||
_("Unix socket path must be fewer than {count} characters (including '{prefix}' prefix)"),
|
||||
fmt::arg("count", TrUnixAddrStrLen - 1),
|
||||
fmt::arg("prefix", TrUnixSocketPrefix)));
|
||||
return false;
|
||||
}
|
||||
|
||||
dst.type = TR_RPC_AF_UNIX;
|
||||
tr_strlcpy(std::data(dst.addr.unixSocketPath), std::string{ src }.c_str(), std::size(dst.addr.unixSocketPath));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (evutil_inet_pton(AF_INET, std::string{ src }.c_str(), &dst.addr) == 1)
|
||||
{
|
||||
dst.type = TR_RPC_AF_INET;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (evutil_inet_pton(AF_INET6, std::string{ src }.c_str(), &dst.addr) == 1)
|
||||
{
|
||||
dst.type = TR_RPC_AF_INET6;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bindUnixSocket(
|
||||
[[maybe_unused]] struct event_base* base,
|
||||
[[maybe_unused]] struct evhttp* httpd,
|
||||
|
@ -679,11 +674,11 @@ void start_server(tr_rpc_server* server)
|
|||
auto const address = server->get_bind_address();
|
||||
auto const port = server->port();
|
||||
|
||||
bool const success = server->bind_address_->type == TR_RPC_AF_UNIX ?
|
||||
bool const success = server->bind_address_->is_unix_addr() ?
|
||||
bindUnixSocket(base, httpd, address.c_str(), server->socket_mode_) :
|
||||
(evhttp_bind_socket(httpd, address.c_str(), port.host()) != -1);
|
||||
|
||||
auto const addr_port_str = tr_rpc_address_with_port(server);
|
||||
auto const addr_port_str = server->bind_address_->to_string(port);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
@ -732,14 +727,14 @@ void stop_server(tr_rpc_server* server)
|
|||
|
||||
httpd.reset();
|
||||
|
||||
if (server->bind_address_->type == TR_RPC_AF_UNIX)
|
||||
if (server->bind_address_->is_unix_addr())
|
||||
{
|
||||
unlink(address.c_str() + std::size(TrUnixSocketPrefix));
|
||||
}
|
||||
|
||||
tr_logAddInfo(fmt::format(
|
||||
_("Stopped listening for RPC and Web requests on '{address}'"),
|
||||
fmt::arg("address", tr_rpc_address_with_port(server))));
|
||||
fmt::arg("address", server->bind_address_->to_string(server->port()))));
|
||||
}
|
||||
|
||||
void restart_server(tr_rpc_server* const server)
|
||||
|
@ -838,8 +833,7 @@ void tr_rpc_server::set_password_enabled(bool enabled)
|
|||
|
||||
std::string tr_rpc_server::get_bind_address() const
|
||||
{
|
||||
auto buf = std::array<char, TrUnixAddrStrLen>{};
|
||||
return tr_rpc_address_to_string(*this->bind_address_, std::data(buf), std::size(buf));
|
||||
return bind_address_->to_string();
|
||||
}
|
||||
|
||||
void tr_rpc_server::set_anti_brute_force_enabled(bool enabled) noexcept
|
||||
|
@ -857,7 +851,7 @@ void tr_rpc_server::set_anti_brute_force_enabled(bool enabled) noexcept
|
|||
tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant* settings)
|
||||
: compressor{ libdeflate_alloc_compressor(DeflateLevel), libdeflate_free_compressor }
|
||||
, web_client_dir_{ tr_getWebClientDir(session_in) }
|
||||
, bind_address_(std::make_unique<struct tr_rpc_address>())
|
||||
, bind_address_(std::make_unique<class tr_rpc_address>())
|
||||
, session{ session_in }
|
||||
{
|
||||
load(settings);
|
||||
|
@ -887,23 +881,23 @@ void tr_rpc_server::load(tr_variant* src)
|
|||
this->set_username(username_);
|
||||
this->set_password(salted_password_);
|
||||
|
||||
if (!tr_rpc_address_from_string(*bind_address_, bind_address_str_))
|
||||
if (!bind_address_->from_string(bind_address_str_))
|
||||
{
|
||||
// NOTE: bind_address_ is default initialized to INADDR_ANY
|
||||
tr_logAddWarn(fmt::format(
|
||||
_("The '{key}' setting is '{value}' but must be an IPv4 or IPv6 address or a Unix socket path. Using default value '0.0.0.0'"),
|
||||
fmt::format("key", tr_quark_get_string_view(TR_KEY_rpc_bind_address)),
|
||||
fmt::format("value", bind_address_str_)));
|
||||
bind_address_->set_inaddr_any();
|
||||
}
|
||||
|
||||
if (bind_address_->type == TR_RPC_AF_UNIX)
|
||||
if (bind_address_->is_unix_addr())
|
||||
{
|
||||
this->set_whitelist_enabled(false);
|
||||
this->is_host_whitelist_enabled_ = false;
|
||||
}
|
||||
if (this->is_enabled())
|
||||
{
|
||||
auto const rpc_uri = tr_rpc_address_with_port(this) + this->url_;
|
||||
auto const rpc_uri = bind_address_->to_string(this->port()) + this->url_;
|
||||
tr_logAddInfo(fmt::format(_("Serving RPC and Web requests on {address}"), fmt::arg("address", rpc_uri)));
|
||||
session->runInSessionThread(start_server, this);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
struct evhttp;
|
||||
struct tr_variant;
|
||||
struct tr_rpc_address;
|
||||
class tr_rpc_address;
|
||||
struct libdeflate_compressor;
|
||||
|
||||
namespace libtransmission
|
||||
|
@ -153,7 +153,7 @@ public:
|
|||
std::vector<std::string> whitelist_;
|
||||
std::string const web_client_dir_;
|
||||
|
||||
std::unique_ptr<struct tr_rpc_address> bind_address_;
|
||||
std::unique_ptr<class tr_rpc_address> bind_address_;
|
||||
|
||||
std::unique_ptr<libtransmission::Timer> start_retry_timer;
|
||||
libtransmission::evhelpers::evhttp_unique_ptr httpd;
|
||||
|
|
Loading…
Reference in a new issue