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:
parent
b2b82a952c
commit
243ab1058d
|
@ -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 */,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <cerrno>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue