refactor: fold session UDP innards into C++ class (#3794)

* Use std::unique_ptr to manage UDP core object

N.B.: it's no longer valid to call socket adjustments quirks from
tr_sessionSetUTPEnabled() because the corresponding object may be
not created yet. We have to create (or re-create) it explicitly
(like it's done in tr_sessionSetDHTEnabled()) or just set
is_utp_enabled_ flag of the session and assume that socket
adjustments will be done later when the object is constructed.
This commit is contained in:
Dmitry Antipov 2022-09-21 21:25:53 +03:00 committed by GitHub
parent b2b82a952c
commit 243ab1058d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 208 additions and 184 deletions

View File

@ -191,7 +191,6 @@
A2725D5D0DE7507C003445E7 /* TrackerTableView.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2725D5C0DE7507C003445E7 /* TrackerTableView.mm */; };
A27F0F330E19AD9800B2DB97 /* TorrentGroup.mm in Sources */ = {isa = PBXBuildFile; fileRef = A27F0F320E19AD9800B2DB97 /* TorrentGroup.mm */; };
A284214412DA663E00FBDDBB /* tr-udp.cc in Sources */ = {isa = PBXBuildFile; fileRef = A284214212DA663E00FBDDBB /* tr-udp.cc */; };
A284214512DA663E00FBDDBB /* tr-udp.h in Headers */ = {isa = PBXBuildFile; fileRef = A284214312DA663E00FBDDBB /* tr-udp.h */; };
A28F4F770E085BDC003A3882 /* ColorTextField.mm in Sources */ = {isa = PBXBuildFile; fileRef = A28F4F760E085BDC003A3882 /* ColorTextField.mm */; };
A292A6E80DFB45FC004B9C0A /* webseed.cc in Sources */ = {isa = PBXBuildFile; fileRef = A292A6E50DFB45EC004B9C0A /* webseed.cc */; };
A29304ED15D7465100B1F726 /* style.css in Resources */ = {isa = PBXBuildFile; fileRef = A29304EC15D7465100B1F726 /* style.css */; };
@ -928,7 +927,6 @@
A28393FD10D54A79005C0240 /* de */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
A28393FF10D54A96005C0240 /* de */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
A284214212DA663E00FBDDBB /* tr-udp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "tr-udp.cc"; sourceTree = "<group>"; };
A284214312DA663E00FBDDBB /* tr-udp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "tr-udp.h"; sourceTree = "<group>"; };
A28B3A2D160E1BC900D4A2BC /* pt_PT */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pt_PT; path = pt_PT.lproj/Localizable.strings; sourceTree = "<group>"; };
A28E1DDF0CFFD8EC00E16385 /* ButtonToolbarItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ButtonToolbarItem.h; sourceTree = "<group>"; };
A28F4F750E085BDC003A3882 /* ColorTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorTextField.h; sourceTree = "<group>"; };
@ -1720,7 +1718,6 @@
C1425B341EE9C5EA001DB85F /* tr-macros.h */,
888A256631B3DE536FEB8B01 /* tr-strbuf.h */,
A284214212DA663E00FBDDBB /* tr-udp.cc */,
A284214312DA663E00FBDDBB /* tr-udp.h */,
A2679292130E00A000CB7464 /* tr-utp.cc */,
A2679293130E00A000CB7464 /* tr-utp.h */,
BEFC1DF50C07861A00B0BB3C /* transmission.h */,
@ -2208,7 +2205,6 @@
2856E0656A49F2665D69E760 /* benc.h in Headers */,
E975121263DD973CAF4AEBA0 /* timer.h in Headers */,
E975121263DD973CAF4AEBA2 /* timer-ev.h in Headers */,
A284214512DA663E00FBDDBB /* tr-udp.h in Headers */,
C1077A4F183EB29600634C22 /* error.h in Headers */,
A2679295130E00A000CB7464 /* tr-utp.h in Headers */,
A23F29A1132A447400E9A83B /* announcer-common.h in Headers */,

View File

@ -201,7 +201,6 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS
torrents.h
tr-dht.h
tr-lpd.h
tr-udp.h
tr-utp.h
trevent.h
upnp.h

View File

@ -31,7 +31,6 @@
#include "peer-mgr.h" /* tr_peerMgrCompactToPex() */
#include "session.h"
#include "tr-assert.h"
#include "tr-udp.h"
#include "utils.h"
#include "web-utils.h"
@ -57,31 +56,10 @@ static void tau_sockaddr_setport(struct sockaddr* sa, tr_port port)
}
}
static int tau_sendto(tr_session const* session, struct evutil_addrinfo* ai, tr_port port, void const* buf, size_t buflen)
void tr_session::tau_sendto(struct evutil_addrinfo* ai, tr_port port, void const* buf, size_t buflen) const
{
auto sockfd = tr_socket_t{};
if (ai->ai_addr->sa_family == AF_INET)
{
sockfd = session->udp_socket;
}
else if (ai->ai_addr->sa_family == AF_INET6)
{
sockfd = session->udp6_socket;
}
else
{
sockfd = TR_BAD_SOCKET;
}
if (sockfd == TR_BAD_SOCKET)
{
errno = EAFNOSUPPORT;
return -1;
}
tau_sockaddr_setport(ai->ai_addr, port);
return sendto(sockfd, static_cast<char const*>(buf), buflen, 0, ai->ai_addr, ai->ai_addrlen);
udp_core_->sendto(buf, buflen, ai->ai_addr, ai->ai_addrlen);
}
static uint32_t announce_ip(tr_session const* session)
@ -497,7 +475,7 @@ static void tau_tracker_send_request(struct tau_tracker* tracker, void const* pa
logdbg(tracker->key, fmt::format("sending request w/connection id {}", tracker->connection_id));
evbuffer_add_hton_64(buf, tracker->connection_id);
evbuffer_add_reference(buf, payload, payload_len, nullptr, nullptr);
(void)tau_sendto(tracker->session, tracker->addr.get(), tracker->port, evbuffer_pullup(buf, -1), evbuffer_get_length(buf));
tracker->session->tau_sendto(tracker->addr.get(), tracker->port, evbuffer_pullup(buf, -1), evbuffer_get_length(buf));
evbuffer_free(buf);
}
@ -681,12 +659,7 @@ static void tau_tracker_upkeep_ex(struct tau_tracker* tracker, bool timeout_reqs
evbuffer_add_hton_64(buf, 0x41727101980LL);
evbuffer_add_hton_32(buf, TAU_ACTION_CONNECT);
evbuffer_add_hton_32(buf, tracker->connection_transaction_id);
(void)tau_sendto(
tracker->session,
tracker->addr.get(),
tracker->port,
evbuffer_pullup(buf, -1),
evbuffer_get_length(buf));
tracker->session->tau_sendto(tracker->addr.get(), tracker->port, evbuffer_pullup(buf, -1), evbuffer_get_length(buf));
evbuffer_free(buf);
return;
}
@ -825,9 +798,9 @@ void tr_tracker_udp_start_shutdown(tr_session* session)
/* @brief process an incoming udp message if it's a tracker response.
* @return true if msg was a tracker response; false otherwise */
bool tau_handle_message(tr_session* session, uint8_t const* msg, size_t msglen)
bool tr_session::tau_handle_message(uint8_t const* msg, size_t msglen) const
{
if (session == nullptr || session->announcer_udp == nullptr)
if (announcer_udp == nullptr)
{
return false;
}
@ -849,10 +822,9 @@ bool tau_handle_message(tr_session* session, uint8_t const* msg, size_t msglen)
}
/* extract the transaction_id and look for a match */
struct tr_announcer_udp* const tau = session->announcer_udp;
tau_transaction_t const transaction_id = evbuffer_read_ntoh_32(buf);
for (auto& tracker : tau->trackers)
for (auto& tracker : announcer_udp->trackers)
{
// is it a connection response?
if (tracker.connecting_at != 0 && transaction_id == tracker.connection_transaction_id)

View File

@ -21,6 +21,7 @@
#include <cerrno>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef _WIN32

View File

@ -56,7 +56,6 @@
#include "tr-dht.h" /* tr_dhtUpkeep() */
#include "tr-lpd.h"
#include "tr-strbuf.h"
#include "tr-udp.h"
#include "tr-utp.h"
#include "trevent.h"
#include "utils.h"
@ -632,8 +631,6 @@ tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled
/* initialize the bare skeleton of the session object */
auto* const session = new tr_session{ config_dir };
session->udp_socket = TR_BAD_SOCKET;
session->udp6_socket = TR_BAD_SOCKET;
session->cache = std::make_unique<Cache>(session->torrents(), 1024 * 1024 * 2);
bandwidthGroupRead(session, config_dir);
@ -750,7 +747,7 @@ void tr_session::initImpl(init_data& data)
tr_sessionSet(this, &settings);
tr_udpInit(this);
this->udp_core_ = std::make_unique<tr_session::tr_udp_core>(*this);
this->web = tr_web::create(this->web_mediator_);
@ -1879,7 +1876,7 @@ void tr_session::closeImplFinish()
/* we had to wait until UDP trackers were closed before closing these: */
tr_tracker_udp_close(this);
tr_udpUninit(this);
this->udp_core_.reset();
stats().saveIfDirty();
tr_peerMgrFree(peerMgr);
@ -2081,9 +2078,9 @@ void tr_sessionSetDHTEnabled(tr_session* session, bool enabled)
session,
[session, enabled]()
{
tr_udpUninit(session);
session->udp_core_.reset();
session->is_dht_enabled_ = enabled;
tr_udpInit(session);
session->udp_core_ = std::make_unique<tr_session::tr_udp_core>(*session);
});
}
@ -2115,21 +2112,9 @@ void tr_sessionSetUTPEnabled(tr_session* session, bool enabled)
{
return;
}
tr_runInEventThread(
session,
[session, enabled]()
{
session->is_utp_enabled_ = enabled;
tr_udpSetSocketBuffers(session);
tr_udpSetSocketTOS(session);
// But don't call tr_utpClose --
// see reset_timer in tr-utp.c for an explanation.
});
}
/***
****
***/
session->is_utp_enabled_ = enabled;
}
void tr_sessionSetLPDEnabled(tr_session* session, bool enabled)
{

View File

@ -478,13 +478,52 @@ public:
struct tr_event_handle* events = nullptr;
/* The UDP sockets used for the DHT and uTP. */
tr_port udp_port;
tr_socket_t udp_socket = TR_BAD_SOCKET;
tr_socket_t udp6_socket = TR_BAD_SOCKET;
unsigned char* udp6_bound = nullptr;
struct event* udp_event = nullptr;
struct event* udp6_event = nullptr;
// UDP connectivity used for the DHT and uTP
class tr_udp_core
{
public:
tr_udp_core(tr_session& session);
~tr_udp_core();
void set_socket_buffers();
void set_socket_tos()
{
session_.setSocketTOS(udp_socket_, TR_AF_INET);
session_.setSocketTOS(udp6_socket_, TR_AF_INET6);
}
void sendto(void const* buf, size_t buflen, struct sockaddr const* to, socklen_t const tolen) const;
[[nodiscard]] constexpr auto port() const noexcept
{
return udp_port_;
}
[[nodiscard]] constexpr auto udp_socket() const noexcept
{
return udp_socket_;
}
[[nodiscard]] constexpr auto udp6_socket() const noexcept
{
return udp6_socket_;
}
private:
tr_port udp_port_ = {};
tr_session& session_;
struct event* udp_event_ = nullptr;
struct event* udp6_event_ = nullptr;
unsigned char* udp6_bound_ = nullptr;
tr_socket_t udp_socket_ = TR_BAD_SOCKET;
tr_socket_t udp6_socket_ = TR_BAD_SOCKET;
void rebind_ipv6(bool);
};
std::unique_ptr<tr_udp_core> udp_core_;
/* The open port on the local machine for incoming peer requests */
tr_port private_peer_port;
@ -958,6 +997,10 @@ private:
public:
struct struct_utp_context* utp_context = nullptr;
std::unique_ptr<libtransmission::Timer> utp_timer;
// These UDP announcer quirks are tightly hooked with session
bool tau_handle_message(uint8_t const* msg, size_t msglen) const;
void tau_sendto(struct evutil_addrinfo* ai, tr_port port, void const* buf, size_t buflen) const;
};
constexpr bool tr_isPriority(tr_priority_t p)

View File

@ -275,6 +275,9 @@ int tr_dhtInit(tr_session* ss)
bool have_id = false;
auto nodes = std::vector<uint8_t>{};
auto nodes6 = std::vector<uint8_t>{};
auto udp_socket = ss->udp_core_->udp_socket();
auto udp6_socket = ss->udp_core_->udp6_socket();
if (ok)
{
auto sv = std::string_view{};
@ -286,13 +289,13 @@ int tr_dhtInit(tr_session* ss)
size_t raw_len = 0U;
uint8_t const* raw = nullptr;
if (ss->udp_socket != TR_BAD_SOCKET && tr_variantDictFindRaw(&benc, TR_KEY_nodes, &raw, &raw_len) && raw_len % 6 == 0)
if (udp_socket != TR_BAD_SOCKET && tr_variantDictFindRaw(&benc, TR_KEY_nodes, &raw, &raw_len) && raw_len % 6 == 0)
{
nodes.assign(raw, raw + raw_len);
}
if (ss->udp6_socket != TR_BAD_SOCKET && tr_variantDictFindRaw(&benc, TR_KEY_nodes6, &raw, &raw_len) &&
raw_len % 18 == 0)
if (udp6_socket != TR_BAD_SOCKET && tr_variantDictFindRaw(&benc, TR_KEY_nodes6, &raw, &raw_len) && raw_len % 18 == 0)
{
nodes6.assign(raw, raw + raw_len);
}
@ -312,7 +315,7 @@ int tr_dhtInit(tr_session* ss)
tr_rand_buffer(std::data(myid), std::size(myid));
}
if (int const rc = dht_init(ss->udp_socket, ss->udp6_socket, std::data(myid), nullptr); rc < 0)
if (int const rc = dht_init(udp_socket, udp6_socket, std::data(myid), nullptr); rc < 0)
{
auto const errcode = errno;
tr_logAddDebug(fmt::format("DHT initialization failed: {} ({})", tr_strerror(errcode), errcode));
@ -456,9 +459,11 @@ static void getstatus(getstatus_closure* const closure)
int tr_dhtStatus(tr_session* session, int af, int* setme_node_count)
{
auto closure = getstatus_closure{ af, -1, -1 };
auto udp_socket = session->udp_core_->udp_socket();
auto udp6_socket = session->udp_core_->udp6_socket();
if (!tr_dhtEnabled(session) || (af == AF_INET && session->udp_socket == TR_BAD_SOCKET) ||
(af == AF_INET6 && session->udp6_socket == TR_BAD_SOCKET))
if (!tr_dhtEnabled(session) || (af == AF_INET && udp_socket == TR_BAD_SOCKET) ||
(af == AF_INET6 && udp6_socket == TR_BAD_SOCKET))
{
if (setme_node_count != nullptr)
{
@ -485,7 +490,7 @@ int tr_dhtStatus(tr_session* session, int af, int* setme_node_count)
tr_port tr_dhtPort(tr_session const* ss)
{
return tr_dhtEnabled(ss) ? ss->udp_port : tr_port{};
return tr_dhtEnabled(ss) ? ss->udp_core_->port() : tr_port{};
}
bool tr_dhtAddNode(tr_session* ss, tr_address const* address, tr_port port, bool bootstrap)

View File

@ -25,7 +25,6 @@
#include "tr-assert.h"
#include "tr-dht.h"
#include "tr-utp.h"
#include "tr-udp.h"
#include "utils.h"
/* Since we use a single UDP socket in order to implement multiple
@ -92,51 +91,44 @@ static void set_socket_buffers(tr_socket_t fd, bool large)
}
}
void tr_udpSetSocketBuffers(tr_session const* session)
void tr_session::tr_udp_core::set_socket_buffers()
{
bool const utp = session->allowsUTP();
bool const utp = session_.allowsUTP();
if (session->udp_socket != TR_BAD_SOCKET)
if (udp_socket_ != TR_BAD_SOCKET)
{
set_socket_buffers(session->udp_socket, utp);
::set_socket_buffers(udp_socket_, utp);
}
if (session->udp6_socket != TR_BAD_SOCKET)
if (udp6_socket_ != TR_BAD_SOCKET)
{
set_socket_buffers(session->udp6_socket, utp);
::set_socket_buffers(udp6_socket_, utp);
}
}
void tr_udpSetSocketTOS(tr_session* session)
{
session->setSocketTOS(session->udp_socket, TR_AF_INET);
session->setSocketTOS(session->udp6_socket, TR_AF_INET6);
}
/* BEP-32 has a rather nice explanation of why we need to bind to one
IPv6 address, if I may say so myself. */
// TODO: remove goto, it prevents reducing scope of local variables
static void rebind_ipv6(tr_session* ss, bool force)
void tr_session::tr_udp_core::rebind_ipv6(bool force)
{
struct sockaddr_in6 sin6;
unsigned char const* ipv6 = tr_globalIPv6(ss);
unsigned char const* ipv6 = tr_globalIPv6(&session_);
int rc = -1;
int one = 1;
/* We currently have no way to enable or disable IPv6 after initialisation.
No way to fix that without some surgery to the DHT code itself. */
if (ipv6 == nullptr || (!force && ss->udp6_socket == TR_BAD_SOCKET))
if (ipv6 == nullptr || (!force && udp6_socket_ == TR_BAD_SOCKET))
{
if (ss->udp6_bound != nullptr)
if (udp6_bound_ != nullptr)
{
free(ss->udp6_bound);
ss->udp6_bound = nullptr;
free(udp6_bound_);
udp6_bound_ = nullptr;
}
return;
}
if (ss->udp6_bound != nullptr && memcmp(ipv6, ss->udp6_bound, 16) == 0)
if (udp6_bound_ != nullptr && memcmp(ipv6, udp6_bound_, 16) == 0)
{
return;
}
@ -162,7 +154,7 @@ static void rebind_ipv6(tr_session* ss, bool force)
memcpy(&sin6.sin6_addr, ipv6, 16);
}
sin6.sin6_port = ss->udp_port.network();
sin6.sin6_port = udp_port_.network();
rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
@ -171,14 +163,14 @@ static void rebind_ipv6(tr_session* ss, bool force)
goto FAIL;
}
if (ss->udp6_socket == TR_BAD_SOCKET)
if (udp6_socket_ == TR_BAD_SOCKET)
{
ss->udp6_socket = s;
udp6_socket_ = s;
}
else
{
/* FIXME: dup2 doesn't work for sockets on Windows */
rc = dup2(s, ss->udp6_socket);
rc = dup2(s, udp6_socket_);
if (rc == -1)
{
@ -188,14 +180,14 @@ static void rebind_ipv6(tr_session* ss, bool force)
tr_netCloseSocket(s);
}
if (ss->udp6_bound == nullptr)
if (udp6_bound_ == nullptr)
{
ss->udp6_bound = static_cast<unsigned char*>(malloc(16));
udp6_bound_ = static_cast<unsigned char*>(malloc(16));
}
if (ss->udp6_bound != nullptr)
if (udp6_bound_ != nullptr)
{
memcpy(ss->udp6_bound, ipv6, 16);
memcpy(udp6_bound_, ipv6, 16);
}
return;
@ -217,10 +209,10 @@ FAIL:
tr_netCloseSocket(s);
}
if (ss->udp6_bound != nullptr)
if (udp6_bound_ != nullptr)
{
free(ss->udp6_bound);
ss->udp6_bound = nullptr;
free(udp6_bound_);
udp6_bound_ = nullptr;
}
}
@ -256,7 +248,7 @@ static void event_callback(evutil_socket_t s, [[maybe_unused]] short type, void*
}
else if (rc >= 8 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] <= 3)
{
if (!tau_handle_message(session, std::data(buf), rc))
if (!session->tau_handle_message(std::data(buf), rc))
{
tr_logAddTrace("Couldn't parse UDP tracker packet.");
}
@ -274,26 +266,24 @@ static void event_callback(evutil_socket_t s, [[maybe_unused]] short type, void*
}
}
void tr_udpInit(tr_session* ss)
tr_session::tr_udp_core::tr_udp_core(tr_session& session)
: session_{ session }
{
TR_ASSERT(ss->udp_socket == TR_BAD_SOCKET);
TR_ASSERT(ss->udp6_socket == TR_BAD_SOCKET);
ss->udp_port = ss->peerPort();
if (std::empty(ss->udp_port))
udp_port_ = session_.peerPort();
if (std::empty(udp_port_))
{
return;
}
ss->udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
udp_socket_ = socket(PF_INET, SOCK_DGRAM, 0);
if (ss->udp_socket == TR_BAD_SOCKET)
if (udp_socket_ == TR_BAD_SOCKET)
{
tr_logAddWarn(_("Couldn't create IPv4 socket"));
}
else
{
auto const [public_addr, is_default] = ss->publicAddress(TR_AF_INET);
auto const [public_addr, is_default] = session_.publicAddress(TR_AF_INET);
auto sin = sockaddr_in{};
sin.sin_family = AF_INET;
@ -302,25 +292,25 @@ void tr_udpInit(tr_session* ss)
memcpy(&sin.sin_addr, &public_addr.addr.addr4, sizeof(struct in_addr));
}
sin.sin_port = ss->udp_port.network();
int const rc = bind(ss->udp_socket, (struct sockaddr*)&sin, sizeof(sin));
sin.sin_port = udp_port_.network();
int const rc = bind(udp_socket_, (struct sockaddr*)&sin, sizeof(sin));
if (rc == -1)
{
auto const error_code = errno;
tr_logAddWarn(fmt::format(
_("Couldn't bind IPv4 socket {address}: {error} ({error_code})"),
fmt::arg("address", public_addr.readable(ss->udp_port)),
fmt::arg("address", public_addr.readable(udp_port_)),
fmt::arg("error", tr_strerror(error_code)),
fmt::arg("error_code", error_code)));
tr_netCloseSocket(ss->udp_socket);
ss->udp_socket = TR_BAD_SOCKET;
tr_netCloseSocket(udp_socket_);
udp_socket_ = TR_BAD_SOCKET;
}
else
{
ss->udp_event = event_new(ss->eventBase(), ss->udp_socket, EV_READ | EV_PERSIST, event_callback, ss);
udp_event_ = event_new(session_.eventBase(), udp_socket_, EV_READ | EV_PERSIST, event_callback, &session_);
if (ss->udp_event == nullptr)
if (udp_event_ == nullptr)
{
tr_logAddWarn(_("Couldn't allocate IPv4 event"));
}
@ -331,70 +321,131 @@ void tr_udpInit(tr_session* ss)
if (tr_globalIPv6(nullptr) != nullptr)
{
rebind_ipv6(ss, true);
rebind_ipv6(true);
}
if (ss->udp6_socket != TR_BAD_SOCKET)
if (udp6_socket_ != TR_BAD_SOCKET)
{
ss->udp6_event = event_new(ss->eventBase(), ss->udp6_socket, EV_READ | EV_PERSIST, event_callback, ss);
udp6_event_ = event_new(session_.eventBase(), udp6_socket_, EV_READ | EV_PERSIST, event_callback, &session_);
if (ss->udp6_event == nullptr)
if (udp6_event_ == nullptr)
{
tr_logAddWarn(_("Couldn't allocate IPv6 event"));
}
}
tr_udpSetSocketBuffers(ss);
set_socket_buffers();
set_socket_tos();
tr_udpSetSocketTOS(ss);
if (ss->allowsDHT())
if (session_.allowsDHT())
{
tr_dhtInit(ss);
tr_dhtInit(&session_);
}
if (ss->udp_event != nullptr)
if (udp_event_ != nullptr)
{
event_add(ss->udp_event, nullptr);
event_add(udp_event_, nullptr);
}
if (ss->udp6_event != nullptr)
if (udp6_event_ != nullptr)
{
event_add(ss->udp6_event, nullptr);
event_add(udp6_event_, nullptr);
}
}
void tr_udpUninit(tr_session* ss)
tr_session::tr_udp_core::~tr_udp_core()
{
tr_dhtUninit(ss);
tr_dhtUninit(&session_);
if (ss->udp_socket != TR_BAD_SOCKET)
if (udp_socket_ != TR_BAD_SOCKET)
{
tr_netCloseSocket(ss->udp_socket);
ss->udp_socket = TR_BAD_SOCKET;
tr_netCloseSocket(udp_socket_);
udp_socket_ = TR_BAD_SOCKET;
}
if (ss->udp_event != nullptr)
if (udp_event_ != nullptr)
{
event_free(ss->udp_event);
ss->udp_event = nullptr;
event_free(udp_event_);
udp_event_ = nullptr;
}
if (ss->udp6_socket != TR_BAD_SOCKET)
if (udp6_socket_ != TR_BAD_SOCKET)
{
tr_netCloseSocket(ss->udp6_socket);
ss->udp6_socket = TR_BAD_SOCKET;
tr_netCloseSocket(udp6_socket_);
udp6_socket_ = TR_BAD_SOCKET;
}
if (ss->udp6_event != nullptr)
if (udp6_event_ != nullptr)
{
event_free(ss->udp6_event);
ss->udp6_event = nullptr;
event_free(udp6_event_);
udp6_event_ = nullptr;
}
if (ss->udp6_bound != nullptr)
if (udp6_bound_ != nullptr)
{
free(ss->udp6_bound);
ss->udp6_bound = nullptr;
free(udp6_bound_);
udp6_bound_ = nullptr;
}
}
void tr_session::tr_udp_core::sendto(void const* buf, size_t buflen, struct sockaddr const* to, socklen_t const tolen) const
{
int error = 0;
std::array<char, std::max(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1> peer = {};
if (to->sa_family == AF_INET)
{
if (udp_socket_ != TR_BAD_SOCKET)
{
if (::sendto(udp_socket_, static_cast<char const*>(buf), buflen, 0, to, tolen) == -1)
error = -1;
}
else
{
error = -1;
errno = EBADF;
}
if (error == -1)
{
evutil_inet_ntop(
AF_INET,
&((reinterpret_cast<struct sockaddr_in const*>(to))->sin_addr),
std::data(peer),
std::size(peer));
}
}
else if (to->sa_family == AF_INET6)
{
if (udp6_socket_ != TR_BAD_SOCKET)
{
if (::sendto(udp6_socket_, static_cast<char const*>(buf), buflen, 0, to, tolen) == -1)
error = -1;
}
else
{
error = -1;
errno = EBADF;
}
if (error == -1)
{
evutil_inet_ntop(
AF_INET6,
&((reinterpret_cast<struct sockaddr_in6 const*>(to))->sin6_addr),
std::data(peer),
std::size(peer));
}
}
else
{
error = -1;
errno = EAFNOSUPPORT;
}
if (error == -1)
{
tr_logAddWarn(fmt::format(
"Couldn't send to {address}: {errno} ({error})",
fmt::arg("address", std::data(peer)),
fmt::arg("errno", errno),
fmt::arg("error", tr_strerror(errno))));
}
}

View File

@ -1,21 +0,0 @@
// This file Copyright © 2010 Juliusz Chroboczek.
// It may be used under the MIT (SPDX: MIT) license.
// License text can be found in the licenses/ folder.
#pragma once
#ifndef __TRANSMISSION__
#error only libtransmission should #include this header.
#endif
#include <cstddef> // size_t
#include <cstdint> // uint8_t
struct tr_session;
void tr_udpInit(tr_session*);
void tr_udpUninit(tr_session*);
void tr_udpSetSocketBuffers(tr_session const*);
void tr_udpSetSocketTOS(tr_session*);
bool tau_handle_message(tr_session* session, uint8_t const* msg, size_t msglen);

View File

@ -108,14 +108,7 @@ static void utp_send_to(
struct sockaddr const* const to,
socklen_t const tolen)
{
if (to->sa_family == AF_INET && ss->udp_socket != TR_BAD_SOCKET)
{
(void)sendto(ss->udp_socket, reinterpret_cast<char const*>(buf), buflen, 0, to, tolen);
}
else if (to->sa_family == AF_INET6 && ss->udp6_socket != TR_BAD_SOCKET)
{
(void)sendto(ss->udp6_socket, reinterpret_cast<char const*>(buf), buflen, 0, to, tolen);
}
ss->udp_core_->sendto(buf, buflen, to, tolen);
}
#ifdef TR_UTP_TRACE