refactor: tr_address cleanup (#3422)

* refactor: remove tr_address_compare()

* refactor: remove tr_address_to_string()

* refactor: remove NUM_TR_AF_INET_TYPES

* refactor: replace tr_sessionGetPublicAddress with tr_session::getPublicAddress()

* refactor: tr_peerIo() takes tr_address by value

* refactor: replace tr_sessionIsAddressBlocked with tr_session::isAddressBlocked()

* refactor: tr_peerMgrAddIncoming now takes tr_address by value

* refactor: replace tr_address_is_valid_for_peers() with tr_address.isValidForPeers()

* refactor: tr_netOpenPeerSocket takes tr_address by value

* refactor: remove tr_generateAllowedSet()

* refactor: setup_sockaddr takes a tr_address by value

* refactor: tr_netBindTCP() takes a tr_address by value

* refactor: tr_dhtAddNode() takes a tr_address by value

* refactor: remove tr_address_from_string()

* refactor: rename tr_address.isValidForPeers() to .isValidPeerAddress()

* refactor: replace tr_address_from_sockaddr_storage() with tr_address::fromSockaddrStorage()

* refactor: minor cleanup to tr_address::readable()
This commit is contained in:
Charles Kerr 2022-07-08 13:23:41 -05:00 committed by GitHub
parent 745adf8332
commit 9a44eeaa27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 217 additions and 432 deletions

View File

@ -184,7 +184,7 @@ void tr_announcerParseHttpAnnounceResponse(tr_announce_response& response, std::
{
BasicHandler::EndDict(context);
if (tr_address_is_valid_for_peers(&pex_.addr, pex_.port))
if (pex_.addr.isValidPeerAddress(pex_.port))
{
response_.pex.push_back(pex_);
pex_ = {};
@ -251,7 +251,10 @@ void tr_announcerParseHttpAnnounceResponse(tr_announce_response& response, std::
}
else if (key == "ip")
{
tr_address_from_string(&pex_.addr, value);
if (auto const addr = tr_address::fromString(value))
{
pex_.addr = *addr;
}
}
else if (key == "peer id")
{

View File

@ -155,9 +155,9 @@ bool BlocklistFile::parseLine1(std::string_view line, struct IPv4Range* range)
{
return false;
}
if (auto addr = tr_address{}; tr_address_from_string(&addr, line.substr(0, pos)))
if (auto const addr = tr_address::fromString(line.substr(0, pos)); addr)
{
range->begin_ = ntohl(addr.addr.addr4.s_addr);
range->begin_ = ntohl(addr->addr.addr4.s_addr);
}
else
{
@ -166,9 +166,9 @@ bool BlocklistFile::parseLine1(std::string_view line, struct IPv4Range* range)
line = line.substr(pos + 1);
// parse the trailing 'y.y.y.y'
if (auto addr = tr_address{}; tr_address_from_string(&addr, line))
if (auto const addr = tr_address::fromString(line); addr)
{
range->end_ = ntohl(addr.addr.addr4.s_addr);
range->end_ = ntohl(addr->addr.addr4.s_addr);
}
else
{
@ -193,9 +193,9 @@ bool BlocklistFile::parseLine2(std::string_view line, struct IPv4Range* range)
return false;
}
if (auto addr = tr_address{}; tr_address_from_string(&addr, line.substr(0, pos)))
if (auto const addr = tr_address::fromString(line.substr(0, pos)); addr)
{
range->begin_ = ntohl(addr.addr.addr4.s_addr);
range->begin_ = ntohl(addr->addr.addr4.s_addr);
}
else
{
@ -209,9 +209,9 @@ bool BlocklistFile::parseLine2(std::string_view line, struct IPv4Range* range)
return false;
}
if (auto addr = tr_address{}; tr_address_from_string(&addr, line.substr(0, pos)))
if (auto const addr = tr_address::fromString(line.substr(0, pos)); addr)
{
range->end_ = ntohl(addr.addr.addr4.s_addr);
range->end_ = ntohl(addr->addr.addr4.s_addr);
}
else
{

View File

@ -61,86 +61,6 @@ std::string tr_net_strerror(int err)
#endif
}
char const* tr_address_and_port_to_string(char* buf, size_t buflen, tr_address const* addr, tr_port port)
{
char addr_buf[INET6_ADDRSTRLEN];
tr_address_to_string_with_buf(addr, addr_buf, sizeof(addr_buf));
*fmt::format_to_n(buf, buflen - 1, FMT_STRING("[{:s}]:{:d}"), addr_buf, port.host()).out = '\0';
return buf;
}
char const* tr_address_to_string_with_buf(tr_address const* addr, char* buf, size_t buflen)
{
TR_ASSERT(tr_address_is_valid(addr));
return addr->type == TR_AF_INET ? evutil_inet_ntop(AF_INET, &addr->addr, buf, buflen) :
evutil_inet_ntop(AF_INET6, &addr->addr, buf, buflen);
}
/*
* Non-threadsafe version of tr_address_to_string_with_buf()
* and uses a static memory area for a buffer.
* This function is suitable to be called from libTransmission's networking code,
* which is single-threaded.
*/
char const* tr_address_to_string(tr_address const* addr)
{
static char buf[INET6_ADDRSTRLEN];
return tr_address_to_string_with_buf(addr, buf, sizeof(buf));
}
bool tr_address_from_string(tr_address* dst, char const* src)
{
if (evutil_inet_pton(AF_INET, src, &dst->addr) == 1)
{
dst->type = TR_AF_INET;
return true;
}
if (evutil_inet_pton(AF_INET6, src, &dst->addr) == 1)
{
dst->type = TR_AF_INET6;
return true;
}
return false;
}
bool tr_address_from_string(tr_address* dst, std::string_view src)
{
// inet_pton() requires zero-terminated strings,
// so make a zero-terminated copy here on the stack.
auto buf = std::array<char, TR_ADDRSTRLEN>{};
if (std::size(src) >= std::size(buf))
{
// shouldn't ever be that large; malformed address
return false;
}
*std::copy(std::begin(src), std::end(src), std::begin(buf)) = '\0';
return tr_address_from_string(dst, std::data(buf));
}
/*
* Compare two tr_address structures.
* Returns:
* <0 if a < b
* >0 if a > b
* 0 if a == b
*/
int tr_address_compare(tr_address const* a, tr_address const* b) noexcept
{
// IPv6 addresses are always "greater than" IPv4
if (a->type != b->type)
{
return a->type == TR_AF_INET ? 1 : -1;
}
return a->type == TR_AF_INET ? memcmp(&a->addr.addr4, &b->addr.addr4, sizeof(a->addr.addr4)) :
memcmp(&a->addr.addr6.s6_addr, &b->addr.addr6.s6_addr, sizeof(a->addr.addr6.s6_addr));
}
/***********************************************************************
* TCP sockets
**********************************************************************/
@ -247,38 +167,36 @@ void tr_netSetCongestionControl([[maybe_unused]] tr_socket_t s, [[maybe_unused]]
#endif
}
bool tr_address_from_sockaddr_storage(tr_address* setme_addr, tr_port* setme_port, struct sockaddr_storage const* from)
std::optional<std::pair<tr_address, tr_port>> tr_address::fromSockaddrStorage(sockaddr_storage from)
{
if (from->ss_family == AF_INET)
if (from.ss_family == AF_INET)
{
auto const* const sin = (struct sockaddr_in const*)from;
setme_addr->type = TR_AF_INET;
setme_addr->addr.addr4.s_addr = sin->sin_addr.s_addr;
*setme_port = tr_port::fromNetwork(sin->sin_port);
return true;
auto const* const sin = reinterpret_cast<sockaddr_in const*>(&from);
auto tmp = tr_address{};
tmp.type = TR_AF_INET;
tmp.addr.addr4.s_addr = sin->sin_addr.s_addr;
return std::make_pair(tmp, tr_port::fromNetwork(sin->sin_port));
}
if (from->ss_family == AF_INET6)
if (from.ss_family == AF_INET6)
{
auto const* const sin6 = (struct sockaddr_in6 const*)from;
setme_addr->type = TR_AF_INET6;
setme_addr->addr.addr6 = sin6->sin6_addr;
*setme_port = tr_port::fromNetwork(sin6->sin6_port);
return true;
auto const* const sin6 = reinterpret_cast<sockaddr_in6 const*>(&from);
auto tmp = tr_address{};
tmp.type = TR_AF_INET6;
tmp.addr.addr6 = sin6->sin6_addr;
return std::make_pair(tmp, tr_port::fromNetwork(sin6->sin6_port));
}
return false;
return {};
}
static socklen_t setup_sockaddr(tr_address const* addr, tr_port port, struct sockaddr_storage* sockaddr)
static socklen_t setup_sockaddr(tr_address addr, tr_port port, struct sockaddr_storage* sockaddr)
{
TR_ASSERT(tr_address_is_valid(addr));
if (addr->type == TR_AF_INET)
if (addr.type == TR_AF_INET)
{
sockaddr_in sock4 = {};
sock4.sin_family = AF_INET;
sock4.sin_addr.s_addr = addr->addr.addr4.s_addr;
sock4.sin_addr.s_addr = addr.addr.addr4.s_addr;
sock4.sin_port = port.network();
memcpy(sockaddr, &sock4, sizeof(sock4));
return sizeof(struct sockaddr_in);
@ -288,7 +206,7 @@ static socklen_t setup_sockaddr(tr_address const* addr, tr_port port, struct soc
sock6.sin6_family = AF_INET6;
sock6.sin6_port = port.network();
sock6.sin6_flowinfo = 0;
sock6.sin6_addr = addr->addr.addr6;
sock6.sin6_addr = addr.addr.addr6;
memcpy(sockaddr, &sock6, sizeof(sock6));
return sizeof(struct sockaddr_in6);
}
@ -341,17 +259,15 @@ static tr_socket_t createSocket(tr_session* session, int domain, int type)
return sockfd;
}
struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const* addr, tr_port port, bool client_is_seed)
struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address addr, tr_port port, bool client_is_seed)
{
TR_ASSERT(tr_address_is_valid(addr));
if (!tr_address_is_valid_for_peers(addr, port))
if (!addr.isValidPeerAddress(port))
{
return {};
}
static auto constexpr Domains = std::array<int, NUM_TR_AF_INET_TYPES>{ AF_INET, AF_INET6 };
auto const s = createSocket(session, Domains[addr->type], SOCK_STREAM);
static auto constexpr Domains = std::array<int, 2>{ AF_INET, AF_INET6 };
auto const s = createSocket(session, Domains[addr.type], SOCK_STREAM);
if (s == TR_BAD_SOCKET)
{
return {};
@ -372,8 +288,7 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
socklen_t const addrlen = setup_sockaddr(addr, port, &sock);
// set source address
tr_address const* const source_addr = tr_sessionGetPublicAddress(session, addr->type, nullptr);
TR_ASSERT(source_addr != nullptr);
auto const [source_addr, is_default_addr] = session->getPublicAddress(addr.type);
struct sockaddr_storage source_sock;
socklen_t const sourcelen = setup_sockaddr(source_addr, {}, &source_sock);
@ -381,7 +296,7 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
{
tr_logAddWarn(fmt::format(
_("Couldn't set source address {address} on {socket}: {error} ({error_code})"),
fmt::arg("address", source_addr->readable()),
fmt::arg("address", source_addr.readable()),
fmt::arg("socket", s),
fmt::arg("error", tr_net_strerror(sockerrno)),
fmt::arg("error_code", sockerrno)));
@ -398,12 +313,12 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
{
int const tmperrno = sockerrno;
if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH) || addr->type == TR_AF_INET)
if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH) || addr.type == TR_AF_INET)
{
tr_logAddWarn(fmt::format(
_("Couldn't connect socket {socket} to {address}:{port}: {error} ({error_code})"),
fmt::arg("socket", s),
fmt::arg("address", addr->readable()),
fmt::arg("address", addr.readable()),
fmt::arg("port", port.host()),
fmt::arg("error", tr_net_strerror(tmperrno)),
fmt::arg("error_code", tmperrno)));
@ -416,22 +331,16 @@ struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const
ret = tr_peer_socket_tcp_create(s);
}
char addrstr[TR_ADDRSTRLEN];
tr_address_and_port_to_string(addrstr, sizeof(addrstr), addr, port);
tr_logAddTrace(fmt::format("New OUTGOING connection {} ({})", s, addrstr));
tr_logAddTrace(fmt::format("New OUTGOING connection {} ({})", s, addr.readable(port)));
return ret;
}
struct tr_peer_socket tr_netOpenPeerUTPSocket(
tr_session* session,
tr_address const* addr,
tr_port port,
bool /*client_is_seed*/)
struct tr_peer_socket tr_netOpenPeerUTPSocket(tr_session* session, tr_address addr, tr_port port, bool /*client_is_seed*/)
{
auto ret = tr_peer_socket{};
if (session->utp_context != nullptr && tr_address_is_valid_for_peers(addr, port))
if (session->utp_context != nullptr && addr.isValidPeerAddress(port))
{
struct sockaddr_storage ss;
socklen_t const sslen = setup_sockaddr(addr, port, &ss);
@ -476,14 +385,12 @@ void tr_netClosePeerSocket(tr_session* session, tr_peer_socket socket)
}
}
static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool suppressMsgs, int* errOut)
static tr_socket_t tr_netBindTCPImpl(tr_address addr, tr_port port, bool suppressMsgs, int* errOut)
{
TR_ASSERT(tr_address_is_valid(addr));
static int const domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
static auto constexpr Domains = std::array<int, 2>{ AF_INET, AF_INET6 };
struct sockaddr_storage sock;
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)
{
*errOut = sockerrno;
@ -503,7 +410,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
#ifdef IPV6_V6ONLY
if ((addr->type == TR_AF_INET6) &&
if ((addr.type == TR_AF_INET6) &&
(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
{
@ -526,7 +433,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)));
@ -539,7 +446,7 @@ static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool
if (!suppressMsgs)
{
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
@ -568,7 +475,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 suppressMsgs)
tr_socket_t tr_netBindTCP(tr_address addr, tr_port port, bool suppressMsgs)
{
int unused = 0;
return tr_netBindTCPImpl(addr, port, suppressMsgs, &unused);
@ -582,7 +489,7 @@ bool tr_net_hasIPv6(tr_port port)
if (!alreadyDone)
{
int err = 0;
auto const fd = tr_netBindTCPImpl(&tr_in6addr_any, port, true, &err);
auto const fd = tr_netBindTCPImpl(tr_in6addr_any, port, true, &err);
if (fd != TR_BAD_SOCKET || err != EAFNOSUPPORT) /* we support ipv6 */
{
@ -600,11 +507,9 @@ bool tr_net_hasIPv6(tr_port port)
return result;
}
tr_socket_t tr_netAccept(tr_session* session, tr_socket_t listening_sockfd, tr_address* addr, tr_port* port)
std::optional<std::tuple<tr_socket_t, tr_address, tr_port>> tr_netAccept(tr_session* session, tr_socket_t listening_sockfd)
{
TR_ASSERT(tr_isSession(session));
TR_ASSERT(addr != nullptr);
TR_ASSERT(port != nullptr);
// accept the incoming connection
struct sockaddr_storage sock;
@ -612,20 +517,21 @@ tr_socket_t tr_netAccept(tr_session* session, tr_socket_t listening_sockfd, tr_a
auto const sockfd = accept(listening_sockfd, (struct sockaddr*)&sock, &len);
if (sockfd == TR_BAD_SOCKET)
{
return TR_BAD_SOCKET;
return {};
}
// get the address and port,
// make the socket unblocking,
// and confirm we don't have too many peers
if (!tr_address_from_sockaddr_storage(addr, port, &sock) || evutil_make_socket_nonblocking(sockfd) == -1 ||
!session->incPeerCount())
auto const addrport = tr_address::fromSockaddrStorage(sock);
if (!addrport || evutil_make_socket_nonblocking(sockfd) == -1 || !session->incPeerCount())
{
tr_netCloseSocket(sockfd);
return TR_BAD_SOCKET;
return {};
}
return sockfd;
auto const& [addr, port] = *addrport;
return std::make_tuple(sockfd, addr, port);
}
void tr_netCloseSocket(tr_socket_t sockfd)
@ -800,12 +706,11 @@ unsigned char const* tr_globalIPv6(tr_session const* session)
/* We have some sort of address, now make sure that we return
our bound address if non-default. */
bool is_default = false;
auto const* ipv6_bindaddr = tr_sessionGetPublicAddress(session, TR_AF_INET6, &is_default);
if (ipv6_bindaddr != nullptr && !is_default)
auto const [ipv6_bindaddr, is_default] = session->getPublicAddress(TR_AF_INET6);
if (!is_default)
{
/* Explicitly bound. Return that address. */
memcpy(ipv6, ipv6_bindaddr->addr.addr6.s6_addr, 16);
memcpy(ipv6, ipv6_bindaddr.addr.addr6.s6_addr, 16);
}
return ipv6;
@ -853,10 +758,10 @@ static bool isMartianAddr(struct tr_address const* a)
}
}
bool tr_address_is_valid_for_peers(tr_address const* addr, tr_port port)
[[nodiscard]] bool tr_address::isValidPeerAddress(tr_port port) const noexcept
{
return !std::empty(port) && tr_address_is_valid(addr) && !isIPv6LinkLocalAddress(addr) && !isIPv4MappedAddress(addr) &&
!isMartianAddr(addr);
return !std::empty(port) && tr_address_is_valid(this) && !isIPv6LinkLocalAddress(this) && !isIPv4MappedAddress(this) &&
!isMartianAddr(this);
}
struct tr_peer_socket tr_peer_socket_tcp_create(tr_socket_t const handle)
@ -891,50 +796,53 @@ std::pair<tr_port, uint8_t const*> tr_port::fromCompact(uint8_t const* compact)
/// tr_address
std::optional<tr_address> tr_address::fromString(std::string_view address_str)
std::optional<tr_address> tr_address::fromString(std::string_view addrstr)
{
auto const addrstr_sz = tr_strbuf<char, 64>{ addrstr };
auto addr = tr_address{};
if (!tr_address_from_string(&addr, address_str))
if (evutil_inet_pton(AF_INET, addrstr_sz, &addr.addr) == 1)
{
return {};
addr.type = TR_AF_INET;
return addr;
}
return addr;
if (evutil_inet_pton(AF_INET6, addrstr_sz, &addr.addr) == 1)
{
addr.type = TR_AF_INET6;
return addr;
}
return {};
}
template<typename OutputIt>
OutputIt tr_address::readable(OutputIt out) const
std::string_view tr_address::readable(char* out, size_t outlen, tr_port port) const
{
if (std::empty(port))
{
return isIPv4() ? evutil_inet_ntop(AF_INET, &addr, out, outlen) : evutil_inet_ntop(AF_INET6, &addr, out, outlen);
}
auto buf = std::array<char, INET6_ADDRSTRLEN>{};
tr_address_to_string_with_buf(this, std::data(buf), std::size(buf));
return fmt::format_to(out, FMT_STRING("{:s}"), std::data(buf));
}
template char* tr_address::readable<char*>(char*) const;
std::string tr_address::readable() const
{
auto buf = std::string{};
buf.reserve(INET6_ADDRSTRLEN);
this->readable(std::back_inserter(buf));
return buf;
auto const addr_sv = readable(std::data(buf), std::size(buf));
auto const [end, size] = fmt::format_to_n(out, outlen - 1, FMT_STRING("[{:s}]:{:d}"), addr_sv, port.host());
return { out, size };
}
template<typename OutputIt>
OutputIt tr_address::readable(OutputIt out, tr_port port) const
{
auto buf = std::array<char, INET6_ADDRSTRLEN>{};
tr_address_to_string_with_buf(this, std::data(buf), std::size(buf));
return fmt::format_to(out, FMT_STRING("[{:s}]:{:d}"), std::data(buf), port.host());
auto addrbuf = std::array<char, TR_ADDRSTRLEN + 16>{};
auto const addr_sv = readable(std::data(addrbuf), std::size(addrbuf), port);
return std::copy(std::begin(addr_sv), std::end(addr_sv), out);
}
template char* tr_address::readable<char*>(char*, tr_port) const;
std::string tr_address::readable(tr_port port) const
[[nodiscard]] std::string tr_address::readable(tr_port port) const
{
auto buf = std::string{};
buf.reserve(INET6_ADDRSTRLEN + 9);
buf.reserve(INET6_ADDRSTRLEN + 16);
this->readable(std::back_inserter(buf), port);
return buf;
}
@ -966,5 +874,12 @@ std::pair<tr_address, uint8_t const*> tr_address::fromCompact6(uint8_t const* co
int tr_address::compare(tr_address const& that) const noexcept // <=>
{
return tr_address_compare(this, &that);
// IPv6 addresses are always "greater than" IPv4
if (type != that.type)
{
return type == TR_AF_INET ? 1 : -1;
}
return type == TR_AF_INET ? memcmp(&addr.addr4, &that.addr.addr4, sizeof(addr.addr4)) :
memcmp(&addr.addr6.s6_addr, &that.addr.addr6.s6_addr, sizeof(addr.addr6.s6_addr));
}

View File

@ -66,13 +66,10 @@ enum tr_address_type
{
TR_AF_INET,
TR_AF_INET6,
NUM_TR_AF_INET_TYPES
};
struct tr_address;
[[nodiscard]] int tr_address_compare(tr_address const* a, tr_address const* b) noexcept;
/**
* Literally just a port number.
*
@ -152,19 +149,27 @@ private:
struct tr_address
{
[[nodiscard]] static std::optional<tr_address> fromString(std::string_view str);
[[nodiscard]] static std::optional<std::pair<tr_address, tr_port>> fromSockaddrStorage(sockaddr_storage);
[[nodiscard]] static std::pair<tr_address, uint8_t const*> fromCompact4(uint8_t const* compact) noexcept;
[[nodiscard]] static std::pair<tr_address, uint8_t const*> fromCompact6(uint8_t const* compact) noexcept;
[[nodiscard]] bool isValidPeerAddress(tr_port) const noexcept;
// human-readable formatting
template<typename OutputIt>
OutputIt readable(OutputIt out) const;
OutputIt readable(OutputIt out, tr_port port = {}) const;
std::string_view readable(char* out, size_t outlen, tr_port port = {}) const;
[[nodiscard]] std::string readable(tr_port port = {}) const;
template<typename OutputIt>
OutputIt readable(OutputIt out, tr_port) const;
[[nodiscard]] constexpr auto isIPv4() const noexcept
{
return type == TR_AF_INET;
}
[[nodiscard]] std::string readable() const;
[[nodiscard]] std::string readable(tr_port) const;
[[nodiscard]] constexpr auto isIPv6() const noexcept
{
return type == TR_AF_INET6;
}
// comparisons
@ -196,20 +201,6 @@ struct tr_address
extern tr_address const tr_inaddr_any;
extern tr_address const tr_in6addr_any;
char const* tr_address_to_string(tr_address const* addr);
char const* tr_address_to_string_with_buf(tr_address const* addr, char* buf, size_t buflen);
char const* tr_address_and_port_to_string(char* buf, size_t buflen, tr_address const* addr, tr_port port);
bool tr_address_from_string(tr_address* setme, char const* string);
bool tr_address_from_string(tr_address* dst, std::string_view src);
bool tr_address_from_sockaddr_storage(tr_address* setme, tr_port* port, struct sockaddr_storage const* src);
bool tr_address_is_valid_for_peers(tr_address const* addr, tr_port port);
constexpr bool tr_address_is_valid(tr_address const* a)
{
return a != nullptr && (a->type == TR_AF_INET || a->type == TR_AF_INET6);
@ -221,9 +212,9 @@ 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 suppressMsgs);
tr_socket_t tr_netBindTCP(tr_address addr, tr_port port, bool suppressMsgs);
tr_socket_t tr_netAccept(tr_session* session, tr_socket_t bound, tr_address* setme_addr, tr_port* setme_port);
std::optional<std::tuple<tr_socket_t, tr_address, tr_port>> tr_netAccept(tr_session*, tr_socket_t listening_sockfd);
void tr_netSetCongestionControl(tr_socket_t s, char const* algorithm);

View File

@ -560,7 +560,7 @@ static uint64 utp_callback(utp_callback_arguments* args)
static tr_peerIo* tr_peerIoNew(
tr_session* session,
tr_bandwidth* parent,
tr_address const* addr,
tr_address addr,
tr_port port,
time_t current_time,
tr_sha1_digest_t const* torrent_hash,
@ -580,11 +580,11 @@ static tr_peerIo* tr_peerIoNew(
if (socket.type == TR_PEER_SOCKET_TYPE_TCP)
{
session->setSocketTOS(socket.handle.tcp, addr->type);
session->setSocketTOS(socket.handle.tcp, addr.type);
maybeSetCongestionAlgorithm(socket.handle.tcp, session->peerCongestionAlgorithm());
}
auto* io = new tr_peerIo{ session, torrent_hash, is_incoming, *addr, port, is_seed, current_time, parent };
auto* io = new tr_peerIo{ session, torrent_hash, is_incoming, addr, port, is_seed, current_time, parent };
io->socket = socket;
io->bandwidth().setPeer(io);
tr_logAddTraceIo(io, fmt::format("bandwidth is {}; its parent is {}", fmt::ptr(&io->bandwidth()), fmt::ptr(parent)));
@ -631,13 +631,12 @@ void tr_peerIoUtpInit([[maybe_unused]] struct_utp_context* ctx)
tr_peerIo* tr_peerIoNewIncoming(
tr_session* session,
tr_bandwidth* parent,
tr_address const* addr,
tr_address addr,
tr_port port,
time_t current_time,
struct tr_peer_socket const socket)
{
TR_ASSERT(session != nullptr);
TR_ASSERT(tr_address_is_valid(addr));
return tr_peerIoNew(session, parent, addr, port, current_time, nullptr, true, false, socket);
}
@ -645,7 +644,7 @@ tr_peerIo* tr_peerIoNewIncoming(
tr_peerIo* tr_peerIoNewOutgoing(
tr_session* session,
tr_bandwidth* parent,
tr_address const* addr,
tr_address addr,
tr_port port,
time_t current_time,
tr_sha1_digest_t const& torrent_hash,
@ -653,7 +652,6 @@ tr_peerIo* tr_peerIoNewOutgoing(
bool utp)
{
TR_ASSERT(session != nullptr);
TR_ASSERT(tr_address_is_valid(addr));
auto socket = tr_peer_socket{};
@ -911,7 +909,7 @@ int tr_peerIoReconnect(tr_peerIo* io)
io_close_socket(io);
auto const [addr, port] = io->socketAddress();
io->socket = tr_netOpenPeerSocket(session, &addr, port, io->isSeed());
io->socket = tr_netOpenPeerSocket(session, addr, port, io->isSeed());
if (io->socket.type != TR_PEER_SOCKET_TYPE_TCP)
{

View File

@ -80,7 +80,7 @@ public:
tr_session* session_in,
tr_sha1_digest_t const* torrent_hash,
bool is_incoming,
tr_address const& addr,
tr_address addr,
tr_port port,
bool is_seed,
time_t current_time,
@ -244,7 +244,7 @@ void tr_peerIoUtpInit(struct_utp_context* ctx);
tr_peerIo* tr_peerIoNewOutgoing(
tr_session* session,
tr_bandwidth* parent,
struct tr_address const* addr,
tr_address addr,
tr_port port,
time_t current_time,
tr_sha1_digest_t const& torrent_hash,
@ -254,7 +254,7 @@ tr_peerIo* tr_peerIoNewOutgoing(
tr_peerIo* tr_peerIoNewIncoming(
tr_session* session,
tr_bandwidth* parent,
struct tr_address const* addr,
tr_address addr,
tr_port port,
time_t current_time,
struct tr_peer_socket const socket);

View File

@ -107,7 +107,7 @@ struct peer_atom
return *blocklisted_;
}
auto const value = tr_sessionIsAddressBlocked(session, &addr);
auto const value = session->isAddressBlocked(addr);
blocklisted_ = value;
return value;
}
@ -1175,19 +1175,19 @@ static bool on_handshake_done(tr_handshake_result const& result)
return success;
}
void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address const* addr, tr_port port, struct tr_peer_socket const socket)
void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address addr, tr_port port, struct tr_peer_socket const socket)
{
TR_ASSERT(tr_isSession(manager->session));
auto const lock = manager->unique_lock();
tr_session* session = manager->session;
if (tr_sessionIsAddressBlocked(session, addr))
if (session->isAddressBlocked(addr))
{
tr_logAddTrace(fmt::format("Banned IP address '{}' tried to connect to us", tr_address_to_string(addr)));
tr_logAddTrace(fmt::format("Banned IP address '{}' tried to connect to us", addr.readable()));
tr_netClosePeerSocket(session, socket);
}
else if (manager->incoming_handshakes.contains(*addr))
else if (manager->incoming_handshakes.contains(addr))
{
tr_netClosePeerSocket(session, socket);
}
@ -1198,7 +1198,7 @@ void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address const* addr, tr_port
tr_peerIoUnref(io); /* balanced by the implicit ref in tr_peerIoNewIncoming() */
manager->incoming_handshakes.add(*addr, handshake);
manager->incoming_handshakes.add(addr, handshake);
}
}
@ -1224,9 +1224,8 @@ size_t tr_peerMgrAddPex(tr_torrent* tor, uint8_t from, tr_pex const* pex, size_t
for (tr_pex const* const end = pex + n_pex; pex != end; ++pex)
{
if (tr_isPex(pex) && /* safeguard against corrupt data */
!tr_sessionIsAddressBlocked(s->manager->session, &pex->addr) &&
tr_address_is_valid_for_peers(&pex->addr, pex->port))
if (tr_isPex(pex) && // safeguard against corrupt data
!s->manager->session->isAddressBlocked(pex->addr) && pex->addr.isValidPeerAddress(pex->port))
{
ensureAtomExists(s, pex->addr, pex->port, pex->flags, from);
++n_used;
@ -1631,7 +1630,7 @@ namespace peer_stat_helpers
auto const [addr, port] = peer->socketAddress();
tr_address_to_string_with_buf(&addr, stats.addr, sizeof(stats.addr));
addr.readable(stats.addr, sizeof(stats.addr));
stats.client = peer->client.c_str();
stats.port = port.host();
stats.from = atom->fromFirst;
@ -2754,7 +2753,7 @@ void initiateConnection(tr_peerMgr* mgr, tr_swarm* s, peer_atom& atom)
tr_peerIo* const io = tr_peerIoNewOutgoing(
mgr->session,
&mgr->session->top_bandwidth_,
&atom.addr,
atom.addr,
atom.port,
tr_time(),
s->tor->infoHash(),

View File

@ -124,7 +124,7 @@ void tr_peerMgrClientSentRequests(tr_torrent* torrent, tr_peer* peer, tr_block_s
size_t tr_peerMgrCountActiveRequestsToPeer(tr_torrent const* torrent, tr_peer const* peer);
void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address const* addr, tr_port port, struct tr_peer_socket const socket);
void tr_peerMgrAddIncoming(tr_peerMgr* manager, tr_address addr, tr_port port, struct tr_peer_socket const socket);
std::vector<tr_pex> tr_peerMgrCompactToPex(void const* compact, size_t compactLen, uint8_t const* added_f, size_t added_f_len);

View File

@ -985,89 +985,6 @@ static void protocolSendHaveNone(tr_peerMsgsImpl* msgs)
msgs->pokeBatchPeriod(ImmediatePriorityIntervalSecs);
}
/**
*** ALLOWED FAST SET
*** For explanation, see http://www.bittorrent.org/beps/bep_0006.html
**/
#if 0
size_t tr_generateAllowedSet(tr_piece_index_t* setmePieces, size_t desiredSetSize, size_t pieceCount, uint8_t const* infohash,
tr_address const* addr)
{
TR_ASSERT(setmePieces != nullptr);
TR_ASSERT(desiredSetSize <= pieceCount);
TR_ASSERT(desiredSetSize != 0);
TR_ASSERT(pieceCount != 0);
TR_ASSERT(infohash != nullptr);
TR_ASSERT(addr != nullptr);
size_t setSize = 0;
if (addr->type == TR_AF_INET)
{
uint8_t w[SHA_DIGEST_LENGTH + 4];
uint8_t* walk = w;
uint8_t x[SHA_DIGEST_LENGTH];
uint32_t ui32 = ntohl(htonl(addr->addr.addr4.s_addr) & 0xffffff00); /* (1) */
memcpy(w, &ui32, sizeof(uint32_t));
walk += sizeof(uint32_t);
memcpy(walk, infohash, SHA_DIGEST_LENGTH); /* (2) */
walk += SHA_DIGEST_LENGTH;
tr_sha1(x, w, walk - w, nullptr); /* (3) */
TR_ASSERT(sizeof(w) == walk - w);
while (setSize < desiredSetSize)
{
for (int i = 0; i < 5 && setSize < desiredSetSize; ++i) /* (4) */
{
uint32_t j = i * 4; /* (5) */
uint32_t y = ntohl(*(uint32_t*)(x + j)); /* (6) */
uint32_t index = y % pieceCount; /* (7) */
bool found = false;
for (size_t k = 0; !found && k < setSize; ++k) /* (8) */
{
found = setmePieces[k] == index;
}
if (!found)
{
setmePieces[setSize++] = index; /* (9) */
}
}
tr_sha1(x, x, sizeof(x), nullptr); /* (3) */
}
}
return setSize;
}
static void updateFastSet(tr_peerMsgs*)
{
bool const fext = msgs->io->supportsFEXT();
bool const peerIsNeedy = msgs->peer->progress < 0.10;
if (fext && peerIsNeedy && !msgs->haveFastSet)
{
tr_info const* inf = &msgs->torrent->info;
size_t const numwant = std::min(MAX_FAST_SET_SIZE, inf->pieceCount);
/* build the fast set */
msgs->fastsetSize = tr_generateAllowedSet(msgs->fastset, numwant, inf->pieceCount, inf->hash, msgs->io->address());
msgs->haveFastSet = true;
/* send it to the peer */
for (size_t i = 0; i < msgs->fastsetSize; ++i)
{
protocolSendAllowedFast(msgs, msgs->fastset[i]);
}
}
}
#endif
/**
*** INTEREST
**/
@ -1902,7 +1819,7 @@ static ReadState readBtMessage(tr_peerMsgsImpl* msgs, struct evbuffer* inbuf, si
if (auto const dht_port = tr_port::fromNetwork(nport); !std::empty(dht_port))
{
msgs->dht_port = dht_port;
tr_dhtAddNode(msgs->session, &msgs->io->address(), msgs->dht_port, false);
tr_dhtAddNode(msgs->session, msgs->io->address(), msgs->dht_port, false);
}
}
break;

View File

@ -80,11 +80,4 @@ tr_peerMsgs* tr_peerMsgsNew(
tr_peer_callback callback,
void* callback_data);
size_t tr_generateAllowedSet(
tr_piece_index_t* setmePieces,
size_t desiredSetSize,
size_t pieceCount,
uint8_t const* infohash,
struct tr_address const* addr);
/* @} */

View File

@ -35,10 +35,9 @@ struct tr_peer_socket tr_peer_socket_tcp_create(tr_socket_t const handle);
struct tr_peer_socket tr_peer_socket_utp_create(struct UTPSocket* const handle);
struct tr_session;
struct tr_address;
struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address const* addr, tr_port port, bool clientIsSeed);
struct tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_address addr, tr_port port, bool clientIsSeed);
struct tr_peer_socket tr_netOpenPeerUTPSocket(tr_session* session, tr_address const* addr, tr_port port, bool clientIsSeed);
struct tr_peer_socket tr_netOpenPeerUTPSocket(tr_session* session, tr_address addr, tr_port port, bool clientIsSeed);
void tr_netClosePeerSocket(tr_session* session, tr_peer_socket socket);

View File

@ -96,12 +96,7 @@ static void natPulse(tr_shared* s, bool do_check)
fmt::arg("private_port", session->private_peer_port.host())));
}
s->upnpStatus = tr_upnpPulse(
s->upnp,
private_peer_port,
is_enabled,
do_check,
tr_address_to_string(&session->bind_ipv4->addr));
s->upnpStatus = tr_upnpPulse(s->upnp, private_peer_port, is_enabled, do_check, session->bind_ipv4->addr.readable());
auto const new_status = tr_sharedTraversalStatus(s);

View File

@ -147,11 +147,11 @@ std::optional<std::string> tr_session::WebMediator::publicAddress() const
{
for (auto const type : { TR_AF_INET, TR_AF_INET6 })
{
auto is_default_value = bool{};
tr_address const* addr = tr_sessionGetPublicAddress(session_, type, &is_default_value);
if (addr != nullptr && !is_default_value)
auto const [addr, is_default_value] = session_->getPublicAddress(type);
if (!is_default_value)
{
return addr->readable();
return addr.readable();
}
}
@ -236,21 +236,15 @@ static void free_incoming_peer_port(tr_session* session)
session->bind_ipv6 = nullptr;
}
static void accept_incoming_peer(evutil_socket_t fd, short /*what*/, void* vsession)
static void accept_incoming_peer(evutil_socket_t listening_sockfd, short /*what*/, void* vsession)
{
auto* session = static_cast<tr_session*>(vsession);
auto clientAddr = tr_address{};
auto clientPort = tr_port{};
auto const clientSocket = tr_netAccept(session, fd, &clientAddr, &clientPort);
if (clientSocket != TR_BAD_SOCKET)
if (auto const accepted = tr_netAccept(session, listening_sockfd); accepted)
{
char addrstr[TR_ADDRSTRLEN];
tr_address_and_port_to_string(addrstr, sizeof(addrstr), &clientAddr, clientPort);
tr_logAddTrace(fmt::format("new incoming connection {} ({})", clientSocket, addrstr));
tr_peerMgrAddIncoming(session->peerMgr, &clientAddr, clientPort, tr_peer_socket_tcp_create(clientSocket));
auto const& [sock, addr, port] = *accepted;
tr_logAddTrace(fmt::format("new incoming connection {} ({})", sock, addr.readable(port)));
tr_peerMgrAddIncoming(session->peerMgr, addr, port, tr_peer_socket_tcp_create(sock));
}
}
@ -258,7 +252,7 @@ static void open_incoming_peer_port(tr_session* session)
{
/* bind an ipv4 port to listen for incoming peers... */
auto* b = session->bind_ipv4;
b->socket = tr_netBindTCP(&b->addr, session->private_peer_port, false);
b->socket = tr_netBindTCP(b->addr, session->private_peer_port, false);
if (b->socket != TR_BAD_SOCKET)
{
@ -270,7 +264,7 @@ static void open_incoming_peer_port(tr_session* session)
if (tr_net_hasIPv6(session->private_peer_port))
{
b = session->bind_ipv6;
b->socket = tr_netBindTCP(&b->addr, session->private_peer_port, false);
b->socket = tr_netBindTCP(b->addr, session->private_peer_port, false);
if (b->socket != TR_BAD_SOCKET)
{
@ -280,33 +274,12 @@ static void open_incoming_peer_port(tr_session* session)
}
}
tr_address const* tr_sessionGetPublicAddress(tr_session const* session, int tr_af_type, bool* is_default_value)
std::pair<tr_address, bool> tr_session::getPublicAddress(tr_address_type type) const
{
char const* default_value = "";
tr_bindinfo const* bindinfo = nullptr;
switch (tr_af_type)
{
case TR_AF_INET:
bindinfo = session->bind_ipv4;
default_value = TR_DEFAULT_BIND_ADDRESS_IPV4;
break;
case TR_AF_INET6:
bindinfo = session->bind_ipv6;
default_value = TR_DEFAULT_BIND_ADDRESS_IPV6;
break;
default:
break;
}
if (is_default_value != nullptr && bindinfo != nullptr)
{
*is_default_value = bindinfo->addr.readable() == default_value;
}
return bindinfo != nullptr ? &bindinfo->addr : nullptr;
auto const* const bindinfo = type == TR_AF_INET6 ? bind_ipv6 : bind_ipv4;
char const* const default_value = type == TR_AF_INET6 ? TR_DEFAULT_BIND_ADDRESS_IPV6 : TR_DEFAULT_BIND_ADDRESS_IPV4;
auto const is_default_value = bindinfo->addr.readable() == default_value;
return std::make_pair(bindinfo->addr, is_default_value);
}
/***
@ -464,8 +437,8 @@ void tr_sessionGetSettings(tr_session const* s, tr_variant* d)
tr_variantDictAddBool(d, TR_KEY_speed_limit_up_enabled, tr_sessionIsSpeedLimited(s, TR_UP));
tr_variantDictAddStr(d, TR_KEY_umask, fmt::format("{:#o}", s->umask));
tr_variantDictAddInt(d, TR_KEY_upload_slots_per_torrent, s->uploadSlotsPerTorrent);
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv4, tr_address_to_string(&s->bind_ipv4->addr));
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv6, tr_address_to_string(&s->bind_ipv6->addr));
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv4, s->bind_ipv4->addr.readable());
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv6, s->bind_ipv6->addr.readable());
tr_variantDictAddBool(d, TR_KEY_start_added_torrents, !tr_sessionGetPaused(s));
tr_variantDictAddBool(d, TR_KEY_trash_original_torrent_files, tr_sessionGetDeleteSource(s));
tr_variantDictAddInt(d, TR_KEY_anti_brute_force_threshold, tr_sessionGetAntiBruteForceThreshold(s));
@ -958,19 +931,25 @@ static void sessionSetImpl(struct init_data* const data)
free_incoming_peer_port(session);
if (!tr_variantDictFindStrView(settings, TR_KEY_bind_address_ipv4, &sv) || !tr_address_from_string(&b.addr, sv) ||
b.addr.type != TR_AF_INET)
b.addr = tr_inaddr_any;
if (tr_variantDictFindStrView(settings, TR_KEY_bind_address_ipv4, &sv))
{
b.addr = tr_inaddr_any;
if (auto const addr = tr_address::fromString(sv); addr && addr->isIPv4())
{
b.addr = *addr;
}
}
b.socket = TR_BAD_SOCKET;
session->bind_ipv4 = static_cast<struct tr_bindinfo*>(tr_memdup(&b, sizeof(struct tr_bindinfo)));
if (!tr_variantDictFindStrView(settings, TR_KEY_bind_address_ipv6, &sv) || !tr_address_from_string(&b.addr, sv) ||
b.addr.type != TR_AF_INET6)
b.addr = tr_in6addr_any;
if (tr_variantDictFindStrView(settings, TR_KEY_bind_address_ipv6, &sv))
{
b.addr = tr_in6addr_any;
if (auto const addr = tr_address::fromString(sv); addr && addr->isIPv6())
{
b.addr = *addr;
}
}
b.socket = TR_BAD_SOCKET;
@ -2491,10 +2470,10 @@ size_t tr_blocklistSetContent(tr_session* session, char const* contentFilename)
return ruleCount;
}
bool tr_sessionIsAddressBlocked(tr_session const* session, tr_address const* addr)
[[nodiscard]] bool tr_session::isAddressBlocked(tr_address addr) const noexcept
{
auto const& src = session->blocklists;
return std::any_of(std::begin(src), std::end(src), [&addr](auto& blocklist) { return blocklist->hasAddress(*addr); });
auto const& src = blocklists;
return std::any_of(std::begin(src), std::end(src), [&addr](auto& blocklist) { return blocklist->hasAddress(addr); });
}
void tr_blocklistSetURL(tr_session* session, char const* url)

View File

@ -255,6 +255,10 @@ public:
tr_netSetTOS(sock, peer_socket_tos_, type);
}
[[nodiscard]] std::pair<tr_address, bool /*is default value*/> getPublicAddress(tr_address_type) const;
[[nodiscard]] bool isAddressBlocked(tr_address) const noexcept;
[[nodiscard]] constexpr bool incPeerCount() noexcept
{
if (this->peerCount >= this->peerLimit)
@ -469,10 +473,6 @@ bool tr_sessionAllowsDHT(tr_session const* session);
bool tr_sessionAllowsLPD(tr_session const* session);
bool tr_sessionIsAddressBlocked(tr_session const* session, struct tr_address const* addr);
struct tr_address const* tr_sessionGetPublicAddress(tr_session const* session, int tr_af_type, bool* is_default_value);
struct tr_bindsockets* tr_sessionGetBindSockets(tr_session*);
int tr_sessionCountTorrents(tr_session const* session);

View File

@ -203,7 +203,7 @@ static void dht_bootstrap(void* closure)
addr.type = TR_AF_INET;
memcpy(&addr.addr.addr4, &cl->nodes[i * 6], 4);
auto const [port, out] = tr_port::fromCompact(&cl->nodes[i * 6 + 4]);
tr_dhtAddNode(cl->session, &addr, port, true);
tr_dhtAddNode(cl->session, addr, port, true);
}
if (i < num6 && !bootstrap_done(cl->session, AF_INET6))
@ -213,7 +213,7 @@ static void dht_bootstrap(void* closure)
addr.type = TR_AF_INET6;
memcpy(&addr.addr.addr6, &cl->nodes6[i * 18], 16);
auto const [port, out] = tr_port::fromCompact(&cl->nodes6[i * 18 + 16]);
tr_dhtAddNode(cl->session, &addr, port, true);
tr_dhtAddNode(cl->session, addr, port, true);
}
/* Our DHT code is able to take up to 9 nodes in a row without
@ -528,9 +528,9 @@ tr_port tr_dhtPort(tr_session* ss)
return tr_dhtEnabled(ss) ? ss->udp_port : tr_port{};
}
bool tr_dhtAddNode(tr_session* ss, tr_address const* address, tr_port port, bool bootstrap)
bool tr_dhtAddNode(tr_session* ss, tr_address address, tr_port port, bool bootstrap)
{
int af = address->type == TR_AF_INET ? AF_INET : AF_INET6;
int af = address.type == TR_AF_INET ? AF_INET : AF_INET6;
if (!tr_dhtEnabled(ss))
{
@ -545,23 +545,23 @@ bool tr_dhtAddNode(tr_session* ss, tr_address const* address, tr_port port, bool
return false;
}
if (address->type == TR_AF_INET)
if (address.type == TR_AF_INET)
{
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, &address->addr.addr4, 4);
memcpy(&sin.sin_addr, &address.addr.addr4, 4);
sin.sin_port = port.network();
dht_ping_node((struct sockaddr*)&sin, sizeof(sin));
return true;
}
if (address->type == TR_AF_INET6)
if (address.type == TR_AF_INET6)
{
struct sockaddr_in6 sin6;
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, &address->addr.addr6, 16);
memcpy(&sin6.sin6_addr, &address.addr.addr6, 16);
sin6.sin6_port = port.network();
dht_ping_node((struct sockaddr*)&sin6, sizeof(sin6));
return true;

View File

@ -10,7 +10,7 @@
#include "transmission.h"
#include "net.h" // tr_port
#include "net.h" // tr_address, tr_port
enum
{
@ -27,6 +27,6 @@ bool tr_dhtEnabled(tr_session const*);
tr_port tr_dhtPort(tr_session*);
int tr_dhtStatus(tr_session*, int af, int* setme_nodeCount);
char const* tr_dhtPrintableStatus(int status);
bool tr_dhtAddNode(tr_session*, tr_address const*, tr_port, bool bootstrap);
bool tr_dhtAddNode(tr_session*, tr_address, tr_port, bool bootstrap);
void tr_dhtUpkeep(tr_session*);
void tr_dhtCallback(unsigned char* buf, int buflen, struct sockaddr* from, socklen_t fromlen, void* sv);

View File

@ -290,14 +290,13 @@ void tr_udpInit(tr_session* ss)
}
else
{
auto is_default = bool{};
tr_address const* public_addr = tr_sessionGetPublicAddress(ss, TR_AF_INET, &is_default);
auto const [public_addr, is_default] = ss->getPublicAddress(TR_AF_INET);
auto sin = sockaddr_in{};
sin.sin_family = AF_INET;
if (public_addr != nullptr && !is_default)
if (!is_default)
{
memcpy(&sin.sin_addr, &public_addr->addr.addr4, sizeof(struct in_addr));
memcpy(&sin.sin_addr, &public_addr.addr.addr4, sizeof(struct in_addr));
}
sin.sin_port = ss->udp_port.network();
@ -308,7 +307,7 @@ void tr_udpInit(tr_session* ss)
auto const error_code = errno;
tr_logAddWarn(fmt::format(
_("Couldn't bind IPv4 socket {address}: {error} ({error_code})"),
fmt::arg("address", public_addr != nullptr ? public_addr->readable(ss->udp_port) : "?"),
fmt::arg("address", public_addr.readable(ss->udp_port)),
fmt::arg("error", tr_strerror(error_code)),
fmt::arg("error_code", error_code)));
tr_netCloseSocket(ss->udp_socket);

View File

@ -76,28 +76,28 @@ static auto constexpr UtpIntervalUs = int{ 500000 };
static void utp_on_accept(tr_session* const session, UTPSocket* const s)
{
struct sockaddr_storage from_storage;
auto* const from = (struct sockaddr*)&from_storage;
socklen_t fromlen = sizeof(from_storage);
tr_address addr;
tr_port port;
if (!tr_sessionIsUTPEnabled(session))
{
utp_close(s);
return;
}
struct sockaddr_storage from_storage;
auto* const from = (struct sockaddr*)&from_storage;
socklen_t fromlen = sizeof(from_storage);
utp_getpeername(s, from, &fromlen);
if (!tr_address_from_sockaddr_storage(&addr, &port, &from_storage))
if (auto const addrport = tr_address::fromSockaddrStorage(from_storage); addrport)
{
auto const& [addr, port] = *addrport;
tr_peerMgrAddIncoming(session->peerMgr, addr, port, tr_peer_socket_utp_create(s));
}
else
{
tr_logAddWarn(_("Unknown socket family"));
utp_close(s);
return;
}
tr_peerMgrAddIncoming(session->peerMgr, &addr, port, tr_peer_socket_utp_create(s));
}
static void utp_send_to(

View File

@ -240,11 +240,9 @@ enum
UPNP_IGD_INVALID = 3
};
static auto* discoverThreadfunc(char* bindaddr)
static auto* discoverThreadfunc(std::string bindaddr)
{
auto* const ret = tr_upnpDiscover(2000, bindaddr);
tr_free(bindaddr);
return ret;
return tr_upnpDiscover(2000, bindaddr.c_str());
}
template<typename T>
@ -253,17 +251,17 @@ static bool isFutureReady(std::future<T> const& future)
return future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, bool doPortCheck, char const* bindaddr)
tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, bool doPortCheck, std::string bindaddr)
{
if (isEnabled && handle->state == UpnpState::WILL_DISCOVER)
{
TR_ASSERT(!handle->discover_future);
auto task = std::packaged_task<UPNPDev*(char*)>{ discoverThreadfunc };
auto task = std::packaged_task<UPNPDev*(std::string)>{ discoverThreadfunc };
handle->discover_future = task.get_future();
handle->state = UpnpState::DISCOVERING;
std::thread(std::move(task), tr_strdup(bindaddr)).detach();
std::thread(std::move(task), std::move(bindaddr)).detach();
}
if (isEnabled && handle->state == UpnpState::DISCOVERING && handle->discover_future &&

View File

@ -18,12 +18,14 @@
#include "net.h" // tr_port
#include <string>
struct tr_upnp;
tr_upnp* tr_upnpInit(void);
void tr_upnpClose(tr_upnp*);
tr_port_forwarding tr_upnpPulse(tr_upnp*, tr_port port, bool isEnabled, bool doPortCheck, char const*);
tr_port_forwarding tr_upnpPulse(tr_upnp*, tr_port port, bool isEnabled, bool doPortCheck, std::string addr);
/* @} */

View File

@ -33,8 +33,7 @@ using namespace std::literals;
bool tr_addressIsIP(char const* str)
{
tr_address tmp;
return tr_address_from_string(&tmp, str);
return tr_address::fromString(str).has_value();
}
char const* tr_webGetResponseStr(long code)
@ -271,16 +270,15 @@ std::string_view getSiteName(std::string_view host)
return host;
}
// psl needs a zero-terminated hostname
auto const szhost = tr_urlbuf{ host };
// is it an IP?
auto addr = tr_address{};
if (tr_address_from_string(&addr, std::data(szhost)))
if (auto const addr = tr_address::fromString(host); addr)
{
return host;
}
// psl needs a zero-terminated hostname
auto const szhost = tr_urlbuf{ host };
// is it a registered name?
if (isAsciiNonUpperCase(host))
{

View File

@ -57,10 +57,10 @@ protected:
#endif
bool addressIsBlocked(char const* address_str)
bool addressIsBlocked(std::string_view address_str)
{
struct tr_address addr = {};
return !tr_address_from_string(&addr, address_str) || tr_sessionIsAddressBlocked(session_, &addr);
auto const addr = tr_address::fromString(address_str);
return addr && session_->isAddressBlocked(*addr);
}
};

View File

@ -14,7 +14,6 @@ TEST(PeerMsgs, placeholder)
#if 0
auto infohash = tr_sha1_digest_t{};
struct tr_address addr;
tr_piece_index_t pieceCount = 1313;
size_t numwant;
size_t numgot;
@ -23,15 +22,15 @@ TEST(PeerMsgs, placeholder)
memset(std::data(infohash), 0xaa, std::size(infohash));
tr_address_from_string(&addr, "80.4.4.200");
auto const addr = tr_address::fromString("80.4.4.200");
numwant = 7;
numgot = tr_generateAllowedSet(buf, numwant, pieceCount, infohash, &addr);
numgot = tr_generateAllowedSet(buf, numwant, pieceCount, infohash, *addr);
check_uint(numgot, ==, numwant);
check_mem(buf, ==, pieces, numgot);
numwant = 9;
numgot = tr_generateAllowedSet(buf, numwant, pieceCount, infohash, &addr);
numgot = tr_generateAllowedSet(buf, numwant, pieceCount, infohash, *addr);
check_uint(numgot, ==, numwant);
check_mem(buf, ==, pieces, numgot);