Skip to content

Commit

Permalink
fixup: dedup tr_rpc_address with tr_address (#5523)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
LaserEyess committed Jun 19, 2023
1 parent ddac059 commit 23a52fa
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 100 deletions.
190 changes: 92 additions & 98 deletions libtransmission/rpc-server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()
[[nodiscard]] constexpr auto is_unix_addr() const noexcept
{
type = TR_RPC_AF_INET;
addr.addr4 = { INADDR_ANY };
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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions libtransmission/rpc-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

struct evhttp;
struct tr_variant;
struct tr_rpc_address;
class tr_rpc_address;
struct libdeflate_compressor;

namespace libtransmission
Expand Down Expand Up @@ -153,7 +153,7 @@ class tr_rpc_server
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;
Expand Down

0 comments on commit 23a52fa

Please sign in to comment.