fixup: unix socket implementation changes (#2707)
* Use std::unique_ptr for bindAddress * fixup: unix socket implementation changes Assortment of changes and comments from #2574 - actually assign variables in the tr_rpc_address union for ipv4 and ipv6 - use std::size() instead of std::string.length() - add [[maybe_unused]] to bindUnixSocket() args for Windows - fix error log for windows to to actually print a string instead of an enum int - use C++ style cast for ecvonnlistener_new_bind() - refactor rpc URL log line to only substitute a single string - remove redundant tr_rpc+address_is_valid() check * change TrUnixSocketPrefix to std::string_view This allows for removing runtime overhead of strlen() in a few places. Co-authored-by: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Co-authored-by: LaserEyess <LaserEyess@users.noreply.github.com>
This commit is contained in:
parent
2c7e167436
commit
3bc21fe8a6
|
@ -58,16 +58,16 @@ using namespace std::literals;
|
|||
|
||||
static char constexpr MyName[] = "RPC Server";
|
||||
|
||||
static char constexpr TrUnixSocketPrefix[] = "unix:";
|
||||
static auto constexpr TrUnixSocketPrefix = "unix:"sv;
|
||||
|
||||
/* The maximum size of a unix socket path is defined per-platform based on sockaddr_un.sun_path.
|
||||
* On Windows the fallback is the length of the unix prefix. Subtracting one at the end is for
|
||||
* double counting null terminators from sun_path and TrUnixSocketPrefix. */
|
||||
#ifdef _WIN32
|
||||
auto inline constexpr TrUnixAddrStrLen = size_t{ sizeof(TrUnixSocketPrefix) };
|
||||
auto inline constexpr TrUnixAddrStrLen = size_t{ std::size(TrUnixSocketPrefix) };
|
||||
#else
|
||||
auto inline constexpr TrUnixAddrStrLen = size_t{ sizeof(((struct sockaddr_un*)nullptr)->sun_path) + sizeof(TrUnixSocketPrefix) -
|
||||
1 };
|
||||
auto inline constexpr TrUnixAddrStrLen = size_t{ sizeof(((struct sockaddr_un*)nullptr)->sun_path) +
|
||||
std::size(TrUnixSocketPrefix) };
|
||||
#endif
|
||||
|
||||
enum tr_rpc_address_type
|
||||
|
@ -82,13 +82,17 @@ struct tr_rpc_address
|
|||
tr_rpc_address_type type;
|
||||
union
|
||||
{
|
||||
struct in6_addr;
|
||||
struct in_addr;
|
||||
struct in_addr addr4;
|
||||
struct in6_addr addr6;
|
||||
char unixSocketPath[TrUnixAddrStrLen];
|
||||
} addr;
|
||||
};
|
||||
|
||||
static tr_rpc_address constexpr tr_rpc_inaddr_any = { TR_RPC_AF_INET, { INADDR_ANY } };
|
||||
void set_inaddr_any()
|
||||
{
|
||||
type = TR_RPC_AF_INET;
|
||||
addr.addr4 = { INADDR_ANY };
|
||||
}
|
||||
};
|
||||
|
||||
#define MY_REALM "Transmission"
|
||||
|
||||
|
@ -96,9 +100,9 @@ static tr_rpc_address constexpr tr_rpc_inaddr_any = { TR_RPC_AF_INET, { INADDR_A
|
|||
|
||||
static int constexpr DeflateLevel = 6; // medium / default
|
||||
|
||||
static bool constexpr tr_rpc_address_is_valid(tr_rpc_address const* a)
|
||||
static bool constexpr tr_rpc_address_is_valid(tr_rpc_address const& a)
|
||||
{
|
||||
return a != nullptr && (a->type == TR_RPC_AF_INET || a->type == TR_RPC_AF_INET6 || a->type == TR_RPC_AF_UNIX);
|
||||
return a.type == TR_RPC_AF_INET || a.type == TR_RPC_AF_INET6 || a.type == TR_RPC_AF_UNIX;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -588,20 +592,20 @@ static auto constexpr ServerStartRetryDelayIncrement = int{ 5 };
|
|||
static auto constexpr ServerStartRetryDelayStep = int{ 3 };
|
||||
static auto constexpr ServerStartRetryMaxDelay = int{ 60 };
|
||||
|
||||
static char const* tr_rpc_address_to_string(tr_rpc_address const* addr, char* buf, size_t buflen)
|
||||
static 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)
|
||||
switch (addr.type)
|
||||
{
|
||||
case TR_RPC_AF_INET:
|
||||
return evutil_inet_ntop(AF_INET, &addr->addr, buf, buflen);
|
||||
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);
|
||||
return evutil_inet_ntop(AF_INET6, &addr.addr, buf, buflen);
|
||||
|
||||
case TR_RPC_AF_UNIX:
|
||||
tr_strlcpy(buf, addr->addr.unixSocketPath, buflen);
|
||||
tr_strlcpy(buf, addr.addr.unixSocketPath, buflen);
|
||||
return buf;
|
||||
|
||||
default:
|
||||
|
@ -611,70 +615,79 @@ static char const* tr_rpc_address_to_string(tr_rpc_address const* addr, char* bu
|
|||
|
||||
static std::string tr_rpc_address_with_port(tr_rpc_server const* server)
|
||||
{
|
||||
tr_rpc_address const* addr = server->bindAddress;
|
||||
|
||||
char addr_buf[TrUnixAddrStrLen];
|
||||
tr_rpc_address_to_string(addr, addr_buf, sizeof(addr_buf));
|
||||
tr_rpc_address_to_string(*server->bindAddress, addr_buf, sizeof(addr_buf));
|
||||
|
||||
std::string addr_port_str{ addr_buf };
|
||||
if (addr->type != TR_RPC_AF_UNIX)
|
||||
if (server->bindAddress->type != TR_RPC_AF_UNIX)
|
||||
{
|
||||
addr_port_str.append(":" + std::to_string(tr_rpcGetPort(server)));
|
||||
}
|
||||
return addr_port_str;
|
||||
}
|
||||
|
||||
static bool tr_rpc_address_from_string(tr_rpc_address* dst, std::string_view src)
|
||||
static bool tr_rpc_address_from_string(tr_rpc_address& dst, std::string_view src)
|
||||
{
|
||||
if (tr_strvStartsWith(src, TrUnixSocketPrefix))
|
||||
{
|
||||
if (src.length() >= TrUnixAddrStrLen)
|
||||
if (std::size(src) >= TrUnixAddrStrLen)
|
||||
{
|
||||
tr_logAddNamedError(
|
||||
MyName,
|
||||
_("Unix socket path must be fewer than %zu characters (including \"%s\" prefix)"),
|
||||
_("Unix socket path must be fewer than %zu characters (including \"%" TR_PRIsv "\" prefix)"),
|
||||
TrUnixAddrStrLen - 1,
|
||||
TrUnixSocketPrefix);
|
||||
TR_PRIsv_ARG(TrUnixSocketPrefix));
|
||||
return false;
|
||||
}
|
||||
|
||||
dst->type = TR_RPC_AF_UNIX;
|
||||
tr_strlcpy(dst->addr.unixSocketPath, std::string{ src }.c_str(), TrUnixAddrStrLen);
|
||||
dst.type = TR_RPC_AF_UNIX;
|
||||
tr_strlcpy(dst.addr.unixSocketPath, std::string{ src }.c_str(), TrUnixAddrStrLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (evutil_inet_pton(AF_INET, std::string{ src }.c_str(), &dst->addr) == 1)
|
||||
if (evutil_inet_pton(AF_INET, std::string{ src }.c_str(), &dst.addr) == 1)
|
||||
{
|
||||
dst->type = TR_RPC_AF_INET;
|
||||
dst.type = TR_RPC_AF_INET;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (evutil_inet_pton(AF_INET6, std::string{ src }.c_str(), &dst->addr) == 1)
|
||||
if (evutil_inet_pton(AF_INET6, std::string{ src }.c_str(), &dst.addr) == 1)
|
||||
{
|
||||
dst->type = TR_RPC_AF_INET6;
|
||||
dst.type = TR_RPC_AF_INET6;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool bindUnixSocket(struct event_base* base, struct evhttp* httpd, char const* path, int socket_mode)
|
||||
static bool bindUnixSocket(
|
||||
[[maybe_unused]] struct event_base* base,
|
||||
[[maybe_unused]] struct evhttp* httpd,
|
||||
[[maybe_unused]] char const* path,
|
||||
[[maybe_unused]] int socket_mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
tr_logAddNamedError(
|
||||
MyName,
|
||||
_("Unix sockets are not supported on Windows. Please change \"%s\" in your configuration file."),
|
||||
TR_KEY_rpc_bind_address);
|
||||
tr_quark_get_string(TR_KEY_rpc_bind_address, nullptr));
|
||||
return false;
|
||||
#else
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
tr_strlcpy(addr.sun_path, path + strlen(TrUnixSocketPrefix), sizeof(addr.sun_path));
|
||||
tr_strlcpy(addr.sun_path, path + std::size(TrUnixSocketPrefix), sizeof(addr.sun_path));
|
||||
|
||||
unlink(addr.sun_path);
|
||||
|
||||
struct evconnlistener*
|
||||
lev = evconnlistener_new_bind(base, nullptr, nullptr, LEV_OPT_CLOSE_ON_FREE, -1, (struct sockaddr*)&addr, sizeof(addr));
|
||||
struct evconnlistener* lev = evconnlistener_new_bind(
|
||||
base,
|
||||
nullptr,
|
||||
nullptr,
|
||||
LEV_OPT_CLOSE_ON_FREE,
|
||||
-1,
|
||||
reinterpret_cast<sockaddr const*>(&addr),
|
||||
sizeof(addr));
|
||||
|
||||
if (lev == nullptr)
|
||||
{
|
||||
|
@ -797,7 +810,7 @@ static void stopServer(tr_rpc_server* server)
|
|||
|
||||
if (server->bindAddress->type == TR_RPC_AF_UNIX)
|
||||
{
|
||||
unlink(address + strlen(TrUnixSocketPrefix));
|
||||
unlink(address + std::size(TrUnixSocketPrefix));
|
||||
}
|
||||
|
||||
tr_logAddNamedDbg(MyName, "Stopped listening on %s", tr_rpc_address_with_port(server).c_str());
|
||||
|
@ -985,7 +998,7 @@ bool tr_rpcIsPasswordEnabled(tr_rpc_server const* server)
|
|||
char const* tr_rpcGetBindAddress(tr_rpc_server const* server)
|
||||
{
|
||||
static char addr_buf[TrUnixAddrStrLen];
|
||||
return tr_rpc_address_to_string(server->bindAddress, addr_buf, sizeof(addr_buf));
|
||||
return tr_rpc_address_to_string(*server->bindAddress, addr_buf, sizeof(addr_buf));
|
||||
}
|
||||
|
||||
bool tr_rpcGetAntiBruteForceEnabled(tr_rpc_server const* server)
|
||||
|
@ -1024,9 +1037,9 @@ static void missing_settings_key(tr_quark const q)
|
|||
|
||||
tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant* settings)
|
||||
: compressor{ libdeflate_alloc_compressor(DeflateLevel), libdeflate_free_compressor }
|
||||
, bindAddress(std::make_unique<struct tr_rpc_address>())
|
||||
, session{ session_in }
|
||||
{
|
||||
auto address = tr_rpc_address{};
|
||||
auto boolVal = bool{};
|
||||
auto i = int64_t{};
|
||||
auto sv = std::string_view{};
|
||||
|
@ -1183,42 +1196,28 @@ tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant* settings)
|
|||
if (!tr_variantDictFindStrView(settings, key, &sv))
|
||||
{
|
||||
missing_settings_key(key);
|
||||
address = tr_rpc_inaddr_any;
|
||||
bindAddress->set_inaddr_any();
|
||||
}
|
||||
else
|
||||
else if (!tr_rpc_address_from_string(*bindAddress, sv))
|
||||
{
|
||||
if (!tr_rpc_address_from_string(&address, sv))
|
||||
{
|
||||
tr_logAddNamedError(MyName, _("%" TR_PRIsv " is not a valid address, falling back to 0.0.0.0."), TR_PRIsv_ARG(sv));
|
||||
address = tr_rpc_inaddr_any;
|
||||
}
|
||||
else if (address.type != TR_RPC_AF_INET && address.type != TR_RPC_AF_INET6 && address.type != TR_RPC_AF_UNIX)
|
||||
{
|
||||
tr_logAddNamedError(
|
||||
MyName,
|
||||
_("%" TR_PRIsv
|
||||
" is not an IPv4 address, an IPv6 address, or a unix socket path. RPC listeners must be one of the previously mentioned types. Falling back to 0.0.0.0."),
|
||||
TR_PRIsv_ARG(sv));
|
||||
address = tr_rpc_inaddr_any;
|
||||
}
|
||||
tr_logAddNamedError(
|
||||
MyName,
|
||||
_("%" TR_PRIsv
|
||||
" is not an IPv4 address, an IPv6 address, or a unix socket path. RPC listeners must be one of the previously mentioned types. Falling back to 0.0.0.0."),
|
||||
TR_PRIsv_ARG(sv));
|
||||
bindAddress->set_inaddr_any();
|
||||
}
|
||||
|
||||
if (address.type == TR_RPC_AF_UNIX)
|
||||
if (bindAddress->type == TR_RPC_AF_UNIX)
|
||||
{
|
||||
this->isWhitelistEnabled = false;
|
||||
this->isHostWhitelistEnabled = false;
|
||||
}
|
||||
|
||||
this->bindAddress = (tr_rpc_address*)tr_memdup(&address, sizeof(tr_rpc_address));
|
||||
|
||||
if (this->isEnabled)
|
||||
{
|
||||
|
||||
tr_logAddNamedInfo(
|
||||
MyName,
|
||||
_("Serving RPC and Web requests on %s%s"),
|
||||
tr_rpc_address_with_port(this).c_str(),
|
||||
this->url.c_str());
|
||||
auto const rpc_uri = tr_rpc_address_with_port(this) + this->url;
|
||||
tr_logAddNamedInfo(MyName, _("Serving RPC and Web requests on %s"), rpc_uri.c_str());
|
||||
tr_runInEventThread(session, startServer, this);
|
||||
|
||||
if (this->isWhitelistEnabled)
|
||||
|
@ -1244,7 +1243,4 @@ tr_rpc_server::~tr_rpc_server()
|
|||
TR_ASSERT(tr_amInEventThread(this->session));
|
||||
|
||||
stopServer(this);
|
||||
|
||||
tr_free(this->bindAddress);
|
||||
this->bindAddress = nullptr;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
std::string whitelistStr;
|
||||
std::string url;
|
||||
|
||||
struct tr_rpc_address* bindAddress;
|
||||
std::unique_ptr<struct tr_rpc_address> bindAddress;
|
||||
|
||||
struct event* start_retry_timer = nullptr;
|
||||
struct evhttp* httpd = nullptr;
|
||||
|
|
Loading…
Reference in New Issue