Update libutp to 3.4+ (TRAC-5888) (#3416)

Co-authored-by: Mike Gelfand <mikedld@mikedld.com>
This commit is contained in:
Charles Kerr
2022-07-08 10:13:22 -05:00
committed by GitHub
parent e9a7ddf7f9
commit 745adf8332
12 changed files with 280 additions and 185 deletions

2
.gitmodules vendored
View File

@@ -20,7 +20,7 @@
[submodule "third-party/libutp"]
path = third-party/libutp
url = https://github.com/transmission/libutp
branch = post-3.3-transmission
branch = post-3.4-transmission
[submodule "third-party/miniupnpc"]
path = third-party/miniupnpc
url = https://github.com/transmission/miniupnpc

View File

@@ -362,7 +362,9 @@ tr_add_external_auto_library(DHT dht dht)
tr_add_external_auto_library(PSL libpsl psl)
if(ENABLE_UTP)
tr_add_external_auto_library(UTP libutp utp)
tr_add_external_auto_library(UTP libutp utp
CMAKE_ARGS
-DLIBUTP_BUILD_PROGRAMS=OFF)
if(UTP_UPSTREAM_TARGET)
# Use C++ linker for anything that depends on static libutp

View File

@@ -240,14 +240,9 @@
A2D77453154CC72B00A62B93 /* WebSeedTableView.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2D77450154CC25700A62B93 /* WebSeedTableView.mm */; };
A2D8CFBB15F82E030056E93D /* NSStringAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CC9C0980656F00BE280E /* NSStringAdditions.mm */; };
A2DF37070C220D03006523C1 /* CreatorWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2DF37050C220D03006523C1 /* CreatorWindowController.mm */; };
A2E384DA130DFB3A001F501B /* templates.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E384D2130DFB3A001F501B /* templates.h */; };
A2E384DC130DFB3A001F501B /* utp_config.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E384D4130DFB3A001F501B /* utp_config.h */; };
A2E384DD130DFB3A001F501B /* utp_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A2E384D5130DFB3A001F501B /* utp_utils.cpp */; };
A2E384DE130DFB3A001F501B /* utp_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E384D6130DFB3A001F501B /* utp_utils.h */; };
A2E384DF130DFB3A001F501B /* utp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A2E384D7130DFB3A001F501B /* utp.cpp */; };
A2E384E0130DFB3A001F501B /* utp.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E384D8130DFB3A001F501B /* utp.h */; };
A2E384E1130DFB3A001F501B /* utypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E384D9130DFB3A001F501B /* utypes.h */; };
A2E3850C130DFCCB001F501B /* StdAfx.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E3850B130DFCCB001F501B /* StdAfx.h */; };
A2E57ABB1310822C00A7DAB1 /* StatusBarController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2E57ABA1310822C00A7DAB1 /* StatusBarController.mm */; };
A2E57AC61310831400A7DAB1 /* StatusBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = A2E57AC51310831400A7DAB1 /* StatusBar.xib */; };
A2E57B9C13109DC200A7DAB1 /* FilterBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = A2E57B9B13109DC200A7DAB1 /* FilterBar.xib */; };
@@ -336,6 +331,17 @@
C1425B361EE9C605001DB85F /* tr-assert.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B331EE9C5EA001DB85F /* tr-assert.h */; };
C1425B371EE9C705001DB85F /* tr-macros.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B341EE9C5EA001DB85F /* tr-macros.h */; };
C1425B381EE9C805001DB85F /* peer-socket.h in Headers */ = {isa = PBXBuildFile; fileRef = C1425B351EE9C5EA001DB85F /* peer-socket.h */; };
C16089EF1F092A1E00CEFC36 /* utp_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C16089E41F092A1E00CEFC36 /* utp_api.cpp */; };
C16089F01F092A1E00CEFC36 /* utp_callbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C16089E51F092A1E00CEFC36 /* utp_callbacks.cpp */; };
C16089F11F092A1E00CEFC36 /* utp_callbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = C16089E61F092A1E00CEFC36 /* utp_callbacks.h */; };
C16089F21F092A1E00CEFC36 /* utp_hash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C16089E71F092A1E00CEFC36 /* utp_hash.cpp */; };
C16089F31F092A1E00CEFC36 /* utp_hash.h in Headers */ = {isa = PBXBuildFile; fileRef = C16089E81F092A1E00CEFC36 /* utp_hash.h */; };
C16089F41F092A1E00CEFC36 /* utp_internal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C16089E91F092A1E00CEFC36 /* utp_internal.cpp */; };
C16089F51F092A1E00CEFC36 /* utp_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = C16089EA1F092A1E00CEFC36 /* utp_internal.h */; };
C16089F61F092A1E00CEFC36 /* utp_packedsockaddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C16089EB1F092A1E00CEFC36 /* utp_packedsockaddr.cpp */; };
C16089F71F092A1E00CEFC36 /* utp_packedsockaddr.h in Headers */ = {isa = PBXBuildFile; fileRef = C16089EC1F092A1E00CEFC36 /* utp_packedsockaddr.h */; };
C16089F81F092A1E00CEFC36 /* utp_templates.h in Headers */ = {isa = PBXBuildFile; fileRef = C16089ED1F092A1E00CEFC36 /* utp_templates.h */; };
C16089F91F092A1E00CEFC36 /* utp_types.h in Headers */ = {isa = PBXBuildFile; fileRef = C16089EE1F092A1E00CEFC36 /* utp_types.h */; };
C1639A741A55F4E000E42033 /* libb64.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C1639A6F1A55F4D600E42033 /* libb64.a */; };
C1639A781A55F56600E42033 /* cdecode.c in Sources */ = {isa = PBXBuildFile; fileRef = C1639A761A55F56600E42033 /* cdecode.c */; };
C1639A791A55F56600E42033 /* cencode.c in Sources */ = {isa = PBXBuildFile; fileRef = C1639A771A55F56600E42033 /* cencode.c */; };
@@ -995,15 +1001,9 @@
A2D8CFBF15FA177A0056E93D /* ru */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
A2DF37040C220D03006523C1 /* CreatorWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CreatorWindowController.h; sourceTree = "<group>"; };
A2DF37050C220D03006523C1 /* CreatorWindowController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CreatorWindowController.mm; sourceTree = "<group>"; };
A2E384D2130DFB3A001F501B /* templates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = templates.h; sourceTree = "<group>"; };
A2E384D3130DFB3A001F501B /* utp_config_example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utp_config_example.h; sourceTree = "<group>"; };
A2E384D4130DFB3A001F501B /* utp_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utp_config.h; sourceTree = "<group>"; };
A2E384D5130DFB3A001F501B /* utp_utils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = utp_utils.cpp; sourceTree = "<group>"; };
A2E384D6130DFB3A001F501B /* utp_utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utp_utils.h; sourceTree = "<group>"; };
A2E384D7130DFB3A001F501B /* utp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = utp.cpp; sourceTree = "<group>"; };
A2E384D8130DFB3A001F501B /* utp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utp.h; sourceTree = "<group>"; };
A2E384D9130DFB3A001F501B /* utypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utypes.h; sourceTree = "<group>"; };
A2E3850B130DFCCB001F501B /* StdAfx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StdAfx.h; sourceTree = "<group>"; };
A2E384D8130DFB3A001F501B /* utp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = include/libutp/utp.h; sourceTree = "<group>"; };
A2E38544130DFEE3001F501B /* libutp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libutp.a; sourceTree = BUILT_PRODUCTS_DIR; };
A2E57AB91310822C00A7DAB1 /* StatusBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StatusBarController.h; sourceTree = "<group>"; };
A2E57ABA1310822C00A7DAB1 /* StatusBarController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = StatusBarController.mm; sourceTree = "<group>"; };
@@ -1111,6 +1111,17 @@
C1425B331EE9C5EA001DB85F /* tr-assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-assert.h"; sourceTree = "<group>"; };
C1425B341EE9C5EA001DB85F /* tr-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "tr-macros.h"; sourceTree = "<group>"; };
C1425B351EE9C5EA001DB85F /* peer-socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "peer-socket.h"; sourceTree = "<group>"; };
C16089E41F092A1E00CEFC36 /* utp_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_api.cpp; path = "utp_api.cpp"; sourceTree = "<group>"; };
C16089E51F092A1E00CEFC36 /* utp_callbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_callbacks.cpp; path = "utp_callbacks.cpp"; sourceTree = "<group>"; };
C16089E61F092A1E00CEFC36 /* utp_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_callbacks.h; path = "utp_callbacks.h"; sourceTree = "<group>"; };
C16089E71F092A1E00CEFC36 /* utp_hash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_hash.cpp; path = "utp_hash.cpp"; sourceTree = "<group>"; };
C16089E81F092A1E00CEFC36 /* utp_hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_hash.h; path = "utp_hash.h"; sourceTree = "<group>"; };
C16089E91F092A1E00CEFC36 /* utp_internal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_internal.cpp; path = "utp_internal.cpp"; sourceTree = "<group>"; };
C16089EA1F092A1E00CEFC36 /* utp_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_internal.h; path = "utp_internal.h"; sourceTree = "<group>"; };
C16089EB1F092A1E00CEFC36 /* utp_packedsockaddr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_packedsockaddr.cpp; path = "utp_packedsockaddr.cpp"; sourceTree = "<group>"; };
C16089EC1F092A1E00CEFC36 /* utp_packedsockaddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_packedsockaddr.h; path = "utp_packedsockaddr.h"; sourceTree = "<group>"; };
C16089ED1F092A1E00CEFC36 /* utp_templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_templates.h; path = "utp_templates.h"; sourceTree = "<group>"; };
C16089EE1F092A1E00CEFC36 /* utp_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_types.h; path = "include/libutp/utp_types.h"; sourceTree = "<group>"; };
C1639A6F1A55F4D600E42033 /* libb64.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libb64.a; sourceTree = BUILT_PRODUCTS_DIR; };
C1639A761A55F56600E42033 /* cdecode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cdecode.c; path = src/cdecode.c; sourceTree = "<group>"; };
C1639A771A55F56600E42033 /* cencode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cencode.c; path = src/cencode.c; sourceTree = "<group>"; };
@@ -1829,15 +1840,20 @@
A2E384BF130DFA49001F501B /* libutp */ = {
isa = PBXGroup;
children = (
A2E384D2130DFB3A001F501B /* templates.h */,
A2E384D3130DFB3A001F501B /* utp_config_example.h */,
A2E384D4130DFB3A001F501B /* utp_config.h */,
C16089E41F092A1E00CEFC36 /* utp_api.cpp */,
C16089E51F092A1E00CEFC36 /* utp_callbacks.cpp */,
C16089E61F092A1E00CEFC36 /* utp_callbacks.h */,
C16089E71F092A1E00CEFC36 /* utp_hash.cpp */,
C16089E81F092A1E00CEFC36 /* utp_hash.h */,
C16089E91F092A1E00CEFC36 /* utp_internal.cpp */,
C16089EA1F092A1E00CEFC36 /* utp_internal.h */,
C16089EB1F092A1E00CEFC36 /* utp_packedsockaddr.cpp */,
C16089EC1F092A1E00CEFC36 /* utp_packedsockaddr.h */,
C16089ED1F092A1E00CEFC36 /* utp_templates.h */,
C16089EE1F092A1E00CEFC36 /* utp_types.h */,
A2E384D5130DFB3A001F501B /* utp_utils.cpp */,
A2E384D6130DFB3A001F501B /* utp_utils.h */,
A2E384D7130DFB3A001F501B /* utp.cpp */,
A2E384D8130DFB3A001F501B /* utp.h */,
A2E384D9130DFB3A001F501B /* utypes.h */,
A2E3850B130DFCCB001F501B /* StdAfx.h */,
);
name = libutp;
path = "third-party/libutp";
@@ -2236,12 +2252,14 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
A2E384DA130DFB3A001F501B /* templates.h in Headers */,
A2E384DC130DFB3A001F501B /* utp_config.h in Headers */,
C16089F31F092A1E00CEFC36 /* utp_hash.h in Headers */,
C16089F51F092A1E00CEFC36 /* utp_internal.h in Headers */,
C16089F81F092A1E00CEFC36 /* utp_templates.h in Headers */,
A2E384DE130DFB3A001F501B /* utp_utils.h in Headers */,
C16089F71F092A1E00CEFC36 /* utp_packedsockaddr.h in Headers */,
A2E384E0130DFB3A001F501B /* utp.h in Headers */,
A2E384E1130DFB3A001F501B /* utypes.h in Headers */,
A2E3850C130DFCCB001F501B /* StdAfx.h in Headers */,
C16089F91F092A1E00CEFC36 /* utp_types.h in Headers */,
C16089F11F092A1E00CEFC36 /* utp_callbacks.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2442,7 +2460,6 @@
isa = PBXNativeTarget;
buildConfigurationList = A2E384E2130DFB3A001F501B /* Build configuration list for PBXNativeTarget "utp" */;
buildPhases = (
C12F197D1E1AE6830005E93F /* ShellScript */,
A2E384CA130DFB1D001F501B /* Headers */,
A2E384CB130DFB1D001F501B /* Sources */,
A2E384CC130DFB1D001F501B /* Frameworks */,
@@ -2849,20 +2866,6 @@
shellPath = /bin/sh;
shellScript = "cd third-party/miniupnpc && rm -f miniupnp && ln -s . miniupnp\n";
};
C12F197D1E1AE6830005E93F /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
"third-party/libutp/libutp",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cd third-party/libutp && rm -f libutp && ln -s . libutp\n";
};
C12F197E1E1AE6D50005E93F /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -3085,8 +3088,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C16089F61F092A1E00CEFC36 /* utp_packedsockaddr.cpp in Sources */,
C16089EF1F092A1E00CEFC36 /* utp_api.cpp in Sources */,
C16089F21F092A1E00CEFC36 /* utp_hash.cpp in Sources */,
C16089F01F092A1E00CEFC36 /* utp_callbacks.cpp in Sources */,
C16089F41F092A1E00CEFC36 /* utp_internal.cpp in Sources */,
A2E384DD130DFB3A001F501B /* utp_utils.cpp in Sources */,
A2E384DF130DFB3A001F501B /* utp.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3588,7 +3595,7 @@
"third-party/libb64/include",
"third-party/libdeflate",
"third-party/libpsl/include",
"third-party/libutp",
"third-party/libutp/include",
"third-party/utfcpp/source",
);
OTHER_CFLAGS = (
@@ -3829,7 +3836,7 @@
"third-party/libb64/include",
"third-party/libdeflate",
"third-party/libpsl/include",
"third-party/libutp",
"third-party/libutp/include",
"third-party/utfcpp/source",
);
OTHER_CFLAGS = (
@@ -4144,7 +4151,7 @@
"third-party/libb64/include",
"third-party/libdeflate",
"third-party/libpsl/include",
"third-party/libutp",
"third-party/libutp/include",
"third-party/utfcpp/source",
);
OTHER_CFLAGS = (

View File

@@ -112,6 +112,7 @@ macro(tr_add_external_auto_library ID DIRNAME LIBNAME)
"-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS}"
"-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
"-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>"
"-DCMAKE_INSTALL_LIBDIR:STRING=lib"
${${ID}_EXT_PROJ_CMAKE_ARGS}
BUILD_BYPRODUCTS "${${ID}_LIBRARY}"
)

View File

@@ -431,15 +431,22 @@ struct tr_peer_socket tr_netOpenPeerUTPSocket(
{
auto ret = tr_peer_socket{};
if (tr_address_is_valid_for_peers(addr, port))
if (session->utp_context != nullptr && tr_address_is_valid_for_peers(addr, port))
{
struct sockaddr_storage ss;
socklen_t const sslen = setup_sockaddr(addr, port, &ss);
struct UTPSocket* const socket = UTP_Create(tr_utpSendTo, session, (struct sockaddr*)&ss, sslen);
auto* const socket = utp_create_socket(session->utp_context);
if (socket != nullptr)
{
ret = tr_peer_socket_utp_create(socket);
if (utp_connect(socket, reinterpret_cast<sockaddr*>(&ss), sslen) != -1)
{
ret = tr_peer_socket_utp_create(socket);
}
else
{
utp_close(socket);
}
}
}
@@ -459,7 +466,8 @@ void tr_netClosePeerSocket(tr_session* session, tr_peer_socket socket)
#ifdef WITH_UTP
case TR_PEER_SOCKET_TYPE_UTP:
UTP_Close(socket.handle.utp);
utp_set_userdata(socket.handle.utp, nullptr);
utp_close(socket.handle.utp);
break;
#endif

View File

@@ -417,12 +417,8 @@ static void maybeSetCongestionAlgorithm(tr_socket_t socket, std::string const& a
#ifdef WITH_UTP
/* UTP callbacks */
static void utp_on_read(void* vio, unsigned char const* buf, size_t buflen)
static void utp_on_read(tr_peerIo* const io, uint8_t const* const buf, size_t const buflen)
{
auto* io = static_cast<tr_peerIo*>(vio);
TR_ASSERT(tr_isPeerIo(io));
if (auto const rc = evbuffer_add(io->inbuf.get(), buf, buflen); rc < 0)
{
tr_logAddWarn(_("Couldn't write to peer"));
@@ -434,34 +430,8 @@ static void utp_on_read(void* vio, unsigned char const* buf, size_t buflen)
canReadWrapper(io);
}
static void utp_on_write(void* vio, unsigned char* buf, size_t buflen)
static size_t utp_get_rb_size(tr_peerIo* const io)
{
auto* io = static_cast<tr_peerIo*>(vio);
TR_ASSERT(tr_isPeerIo(io));
int rc = evbuffer_remove(io->outbuf.get(), buf, buflen);
tr_logAddTraceIo(io, fmt::format("utp_on_write sending {} bytes... evbuffer_remove returned {}", buflen, rc));
TR_ASSERT(rc == (int)buflen); /* if this fails, we've corrupted our bookkeeping somewhere */
if (rc < (long)buflen)
{
auto const errmsg = fmt::format(
_("Couldn't write {expected_size} bytes to peer; wrote {actual_size}"),
fmt::arg("expected_size", buflen),
fmt::arg("actual_size", rc));
tr_logAddWarnIo(io, errmsg);
}
didWriteWrapper(io, buflen);
}
static size_t utp_get_rb_size(void* vio)
{
auto const* const io = static_cast<tr_peerIo const*>(vio);
TR_ASSERT(tr_isPeerIo(io));
size_t bytes = io->bandwidth().clamp(TR_DOWN, UtpReadBufferSize);
tr_logAddTraceIo(io, fmt::format("utp_get_rb_size is saying it's ready to read {} bytes", bytes));
@@ -478,12 +448,8 @@ static void utp_on_writable(tr_peerIo* io)
tr_peerIoSetEnabled(io, TR_UP, n != 0 && evbuffer_get_length(io->outbuf.get()) != 0);
}
static void utp_on_state_change(void* vio, int state)
static void utp_on_state_change(tr_peerIo* const io, int const state)
{
auto* io = static_cast<tr_peerIo*>(vio);
TR_ASSERT(tr_isPeerIo(io));
if (state == UTP_STATE_CONNECT)
{
tr_logAddTraceIo(io, "utp_on_state_change -- changed to connected");
@@ -508,7 +474,6 @@ static void utp_on_state_change(void* vio, int state)
else if (state == UTP_STATE_DESTROYING)
{
tr_logAddErrorIo(io, "Impossible state UTP_STATE_DESTROYING");
return;
}
else
{
@@ -516,12 +481,8 @@ static void utp_on_state_change(void* vio, int state)
}
}
static void utp_on_error(void* vio, int errcode)
static void utp_on_error(tr_peerIo* const io, int const errcode)
{
auto* io = static_cast<tr_peerIo*>(vio);
TR_ASSERT(tr_isPeerIo(io));
tr_logAddDebugIo(io, fmt::format("utp_on_error -- errcode is {}", errcode));
if (io->gotError != nullptr)
@@ -531,60 +492,69 @@ static void utp_on_error(void* vio, int errcode)
}
}
static void utp_on_overhead(void* vio, bool send, size_t count, int /*type*/)
static void utp_on_overhead(tr_peerIo* const io, bool const send, size_t const count, int /*type*/)
{
auto* io = static_cast<tr_peerIo*>(vio);
TR_ASSERT(tr_isPeerIo(io));
tr_logAddTraceIo(io, fmt::format("utp_on_overhead -- count is {}", count));
io->bandwidth().notifyBandwidthConsumed(send ? TR_UP : TR_DOWN, count, false, tr_time_msec());
}
static auto utp_function_table = UTPFunctionTable{
utp_on_read, utp_on_write, utp_get_rb_size, utp_on_state_change, utp_on_error, utp_on_overhead,
};
/* Dummy UTP callbacks. */
/* We switch a UTP socket to use these after the associated peerIo has been
destroyed -- see io_dtor. */
static void dummy_read(void* /*closure*/, unsigned char const* /*buf*/, size_t /*buflen*/)
static uint64 utp_callback(utp_callback_arguments* args)
{
// This cannot happen, as far as I'm aware. */
tr_logAddTrace("On_read called on closed socket");
}
auto* const io = static_cast<tr_peerIo*>(utp_get_userdata(args->socket));
static void dummy_write(void* /*closure*/, unsigned char* buf, size_t buflen)
{
/* This can very well happen if we've shut down a peer connection that
had unflushed buffers.Complain and send zeroes.*/
tr_logAddTrace("On_write called on closed socket");
memset(buf, 0, buflen);
}
if (io == nullptr)
{
#ifdef TR_UTP_TRACE
if (args->callback_type != UTP_ON_STATE_CHANGE || args->u1.state != UTP_STATE_DESTROYING)
{
fmt::print(
stderr,
FMT_STRING("[utp] [{}:{}] [{}] io is null! buf={}, len={}, flags={}, send/error_code/state={}, type={}\n"),
fmt::ptr(args->context),
fmt::ptr(args->socket),
utp_callback_names[args->callback_type],
fmt::ptr(args->buf),
args->len,
args->flags,
args->u1.send,
args->u2.type);
}
#endif
return 0;
}
TR_ASSERT(tr_isPeerIo(io));
TR_ASSERT(io->socket.handle.utp == args->socket);
switch (args->callback_type)
{
case UTP_ON_READ:
utp_on_read(io, args->buf, args->len);
break;
case UTP_GET_READ_BUFFER_SIZE:
return utp_get_rb_size(io);
case UTP_ON_STATE_CHANGE:
utp_on_state_change(io, args->u1.state);
break;
case UTP_ON_ERROR:
utp_on_error(io, args->u1.error_code);
break;
case UTP_ON_OVERHEAD_STATISTICS:
utp_on_overhead(io, args->u1.send != 0, args->len, args->u2.type);
break;
}
static size_t dummy_get_rb_size(void* /*closure*/)
{
return 0;
}
static void dummy_on_state_change(void* /*closure*/, int /*state*/)
{
}
static void dummy_on_error(void* /*closure*/, int /*errcode*/)
{
}
static void dummy_on_overhead(void* /*closure*/, bool /*send*/, size_t /*count*/, int /*type*/)
{
}
static auto dummy_utp_function_table = UTPFunctionTable{
dummy_read, dummy_write, dummy_get_rb_size, dummy_on_state_change, dummy_on_error, dummy_on_overhead,
};
#endif /* #ifdef WITH_UTP */
static tr_peerIo* tr_peerIoNew(
@@ -631,16 +601,7 @@ static tr_peerIo* tr_peerIoNew(
case TR_PEER_SOCKET_TYPE_UTP:
tr_logAddTraceIo(io, fmt::format("socket (utp) is {}", fmt::ptr(socket.handle.utp)));
UTP_SetSockopt(socket.handle.utp, SO_RCVBUF, UtpReadBufferSize);
tr_logAddTraceIo(io, "calling UTP_SetCallbacks &utp_function_table");
UTP_SetCallbacks(socket.handle.utp, &utp_function_table, io);
if (!is_incoming)
{
tr_logAddTraceIo(io, "calling UTP_Connect");
UTP_Connect(socket.handle.utp);
}
utp_set_userdata(socket.handle.utp, io);
break;
#endif
@@ -652,6 +613,21 @@ static tr_peerIo* tr_peerIoNew(
return io;
}
void tr_peerIoUtpInit([[maybe_unused]] struct_utp_context* ctx)
{
#ifdef WITH_UTP
utp_set_callback(ctx, UTP_ON_READ, &utp_callback);
utp_set_callback(ctx, UTP_GET_READ_BUFFER_SIZE, &utp_callback);
utp_set_callback(ctx, UTP_ON_STATE_CHANGE, &utp_callback);
utp_set_callback(ctx, UTP_ON_ERROR, &utp_callback);
utp_set_callback(ctx, UTP_ON_OVERHEAD_STATISTICS, &utp_callback);
utp_context_set_option(ctx, UTP_RCVBUF, UtpReadBufferSize);
#endif
}
tr_peerIo* tr_peerIoNewIncoming(
tr_session* session,
tr_bandwidth* parent,
@@ -821,8 +797,8 @@ static void io_close_socket(tr_peerIo* io)
#ifdef WITH_UTP
case TR_PEER_SOCKET_TYPE_UTP:
UTP_SetCallbacks(io->socket.handle.utp, &dummy_utp_function_table, nullptr);
UTP_Close(io->socket.handle.utp);
utp_set_userdata(io->socket.handle.utp, nullptr);
utp_close(io->socket.handle.utp);
break;
#endif
@@ -1190,7 +1166,7 @@ static int tr_peerIoTryRead(tr_peerIo* io, size_t howmuch)
* if one was not going to be sent. */
if (evbuffer_get_length(io->inbuf.get()) == 0)
{
UTP_RBDrained(io->socket.handle.utp);
utp_read_drained(io->socket.handle.utp);
}
break;
@@ -1250,8 +1226,14 @@ static int tr_peerIoTryWrite(tr_peerIo* io, size_t howmuch)
switch (io->socket.type)
{
case TR_PEER_SOCKET_TYPE_UTP:
UTP_Write(io->socket.handle.utp, howmuch);
n = old_len - evbuffer_get_length(io->outbuf.get());
n = utp_write(io->socket.handle.utp, evbuffer_pullup(io->outbuf.get(), howmuch), howmuch);
if (n > 0)
{
evbuffer_drain(io->outbuf.get(), n);
didWriteWrapper(io, n);
}
break;
case TR_PEER_SOCKET_TYPE_TCP:

View File

@@ -32,6 +32,8 @@
#include "tr-assert.h"
class tr_peerIo;
struct tr_bandwidth;
struct struct_utp_context;
struct tr_datatype;
/**
@@ -236,6 +238,8 @@ private:
***
**/
void tr_peerIoUtpInit(struct_utp_context* ctx);
// TODO: 8 constructor args is too many; maybe a builder object?
tr_peerIo* tr_peerIoNewOutgoing(
tr_session* session,

View File

@@ -759,6 +759,8 @@ static void tr_sessionInitImpl(init_data* data)
tr_lpdInit(session, &session->bind_ipv4->addr);
}
tr_utpInit(session);
/* cleanup */
tr_variantFree(&settings);
data->done_cv.notify_one();
@@ -1830,7 +1832,6 @@ static void sessionCloseImplStart(tr_session* session)
tr_lpdUninit(session);
}
tr_utpClose(session);
tr_dhtUninit(session);
event_free(session->saveTimer);
@@ -1915,6 +1916,8 @@ static void sessionCloseImplFinish(tr_session* session)
tr_statsClose(session);
tr_peerMgrFree(session->peerMgr);
tr_utpClose(session);
closeBlocklists(session);
session->openFiles().closeAll();

View File

@@ -49,12 +49,13 @@ struct evdns_base;
class tr_bitfield;
class tr_rpc_server;
class tr_web;
struct tr_bandwidth;
struct BlocklistFile;
struct struct_utp_context;
struct tr_address;
struct tr_announcer;
struct tr_announcer_udp;
struct tr_bandwidth;
struct tr_bindsockets;
struct BlocklistFile;
struct tr_fdInfo;
struct tr_bindinfo
@@ -349,6 +350,7 @@ public:
struct event* udp_event = nullptr;
struct event* udp6_event = nullptr;
struct struct_utp_context* utp_context = nullptr;
struct event* utp_timer = nullptr;
/* The open port on the local machine for incoming peer requests */

View File

@@ -16,6 +16,7 @@
#include "crypto-utils.h" /* tr_rand_int_weak() */
#include "log.h"
#include "net.h"
#include "peer-io.h"
#include "peer-mgr.h"
#include "peer-socket.h"
#include "session.h"
@@ -24,20 +25,24 @@
#ifndef WITH_UTP
void UTP_Close(struct UTPSocket* socket)
void utp_close(UTPSocket* socket)
{
tr_logAddTrace(fmt::format("UTP_Close({}) was called.", fmt::ptr(socket)));
tr_logAddTrace(fmt::format("utp_close({}) was called.", fmt::ptr(socket)));
}
void UTP_RBDrained(struct UTPSocket* socket)
void utp_read_drained(UTPSocket* socket)
{
tr_logAddTrace(fmt::format("UTP_RBDrained({}) was called.", fmt::ptr(socket)));
tr_logAddTrace(fmt::format("utp_read_drained({}) was called.", fmt::ptr(socket)));
}
bool UTP_Write(struct UTPSocket* socket, size_t count)
ssize_t utp_write(UTPSocket* socket, void* buf, size_t count)
{
tr_logAddTrace(fmt::format("utp_write({}, {}, {}) was called.", fmt::ptr(socket), fmt::ptr(socket), count));
return -1;
}
void tr_utpInit(tr_session* /*session*/)
{
tr_logAddTrace(fmt::format("UTP_Write({}, {}) was called.", fmt::ptr(socket), count));
return false;
}
bool tr_utpPacket(
@@ -50,37 +55,27 @@ bool tr_utpPacket(
return false;
}
struct UTPSocket* UTP_Create(
SendToProc* /*send_to_proc*/,
void* /*send_to_userdata*/,
sockaddr const* /*addr*/,
socklen_t /*addrlen*/)
struct UTPSocket* utp_create_socket(struct_utp_context* /*ctx*/)
{
errno = ENOSYS;
return nullptr;
}
void tr_utpClose(tr_session* /*ss*/)
int utp_connect(UTPSocket* /*socket*/, sockaddr const* /*to*/, socklen_t /*tolen*/)
{
return -1;
}
void tr_utpSendTo(
void* /*closure*/,
unsigned char const* /*buf*/,
size_t /*buflen*/,
struct sockaddr const* /*to*/,
socklen_t /*tolen*/)
void tr_utpClose(tr_session* /*session*/)
{
}
#else
/* Greg says 50ms works for them. */
static auto constexpr UtpIntervalUs = int{ 50000 };
static auto constexpr UtpIntervalUs = int{ 500000 };
static void incoming(void* vsession, struct UTPSocket* s)
static void utp_on_accept(tr_session* const session, UTPSocket* const s)
{
auto* session = static_cast<tr_session*>(vsession);
struct sockaddr_storage from_storage;
auto* const from = (struct sockaddr*)&from_storage;
socklen_t fromlen = sizeof(from_storage);
@@ -89,26 +84,29 @@ static void incoming(void* vsession, struct UTPSocket* s)
if (!tr_sessionIsUTPEnabled(session))
{
UTP_Close(s);
utp_close(s);
return;
}
UTP_GetPeerName(s, from, &fromlen);
utp_getpeername(s, from, &fromlen);
if (!tr_address_from_sockaddr_storage(&addr, &port, &from_storage))
{
tr_logAddWarn(_("Unknown socket family"));
UTP_Close(s);
utp_close(s);
return;
}
tr_peerMgrAddIncoming(session->peerMgr, &addr, port, tr_peer_socket_utp_create(s));
}
void tr_utpSendTo(void* closure, unsigned char const* buf, size_t buflen, struct sockaddr const* to, socklen_t tolen)
static void utp_send_to(
tr_session* const ss,
uint8_t const* const buf,
size_t const buflen,
struct sockaddr const* const to,
socklen_t const tolen)
{
auto const* const ss = static_cast<tr_session const*>(closure);
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);
@@ -119,6 +117,44 @@ void tr_utpSendTo(void* closure, unsigned char const* buf, size_t buflen, struct
}
}
#ifdef TR_UTP_TRACE
static void utp_log(tr_session* const /*session*/, char const* const msg)
{
fmt::print(stderr, FMT_STRING("[utp] {}\n"), msg);
}
#endif
static uint64 utp_callback(utp_callback_arguments* args)
{
auto* const session = static_cast<tr_session*>(utp_context_get_userdata(args->context));
TR_ASSERT(tr_isSession(session));
TR_ASSERT(session->utp_context == args->context);
switch (args->callback_type)
{
#ifdef TR_UTP_TRACE
case UTP_LOG:
utp_log(session, args->buf);
break;
#endif
case UTP_ON_ACCEPT:
utp_on_accept(session, args->socket);
break;
case UTP_SENDTO:
utp_send_to(session, args->buf, args->len, args->u1.address, args->u2.address_len);
break;
}
return 0;
}
static void reset_timer(tr_session* ss)
{
int sec = 0;
@@ -132,7 +168,7 @@ static void reset_timer(tr_session* ss)
else
{
/* If somebody has disabled uTP, then we still want to run
UTP_CheckTimeouts, in order to let closed sockets finish
utp_check_timeouts, in order to let closed sockets finish
gracefully and so on. However, since we're not particularly
interested in that happening in a timely manner, we might as
well use a large timeout. */
@@ -146,10 +182,48 @@ static void reset_timer(tr_session* ss)
static void timer_callback(evutil_socket_t /*s*/, short /*type*/, void* vsession)
{
auto* session = static_cast<tr_session*>(vsession);
UTP_CheckTimeouts();
/* utp_internal.cpp says "Should be called each time the UDP socket is drained" but it's tricky with libevent */
utp_issue_deferred_acks(session->utp_context);
utp_check_timeouts(session->utp_context);
reset_timer(session);
}
void tr_utpInit(tr_session* session)
{
if (session->utp_context != nullptr)
{
return;
}
auto* const ctx = utp_init(2);
if (ctx == nullptr)
{
return;
}
utp_context_set_userdata(ctx, session);
utp_set_callback(ctx, UTP_ON_ACCEPT, &utp_callback);
utp_set_callback(ctx, UTP_SENDTO, &utp_callback);
tr_peerIoUtpInit(ctx);
#ifdef TR_UTP_TRACE
utp_set_callback(ctx, UTP_LOG, &utp_callback);
utp_context_set_option(ctx, UTP_LOG_NORMAL, 1);
utp_context_set_option(ctx, UTP_LOG_MTU, 1);
utp_context_set_option(ctx, UTP_LOG_DEBUG, 1);
#endif
session->utp_context = ctx;
}
bool tr_utpPacket(unsigned char const* buf, size_t buflen, struct sockaddr const* from, socklen_t fromlen, tr_session* ss)
{
if (!ss->isClosed && ss->utp_timer == nullptr)
@@ -164,7 +238,12 @@ bool tr_utpPacket(unsigned char const* buf, size_t buflen, struct sockaddr const
reset_timer(ss);
}
return UTP_IsIncomingUTP(incoming, tr_utpSendTo, ss, buf, buflen, from, fromlen);
auto const ret = utp_process_udp(ss->utp_context, buf, buflen, from, fromlen);
/* utp_internal.cpp says "Should be called each time the UDP socket is drained" but it's tricky with libevent */
utp_issue_deferred_acks(ss->utp_context);
return ret != 0;
}
void tr_utpClose(tr_session* session)
@@ -174,6 +253,13 @@ void tr_utpClose(tr_session* session)
evtimer_del(session->utp_timer);
session->utp_timer = nullptr;
}
if (session->utp_context != nullptr)
{
utp_context_set_userdata(session->utp_context, nullptr);
utp_destroy(session->utp_context);
session->utp_context = nullptr;
}
}
#endif /* #ifndef WITH_UTP ... else */

View File

@@ -12,8 +12,8 @@
struct tr_session;
void tr_utpInit(tr_session* session);
bool tr_utpPacket(unsigned char const* buf, size_t buflen, struct sockaddr const* from, socklen_t fromlen, tr_session* ss);
void tr_utpClose(tr_session*);
void tr_utpSendTo(void* closure, unsigned char const* buf, size_t buflen, struct sockaddr const* to, socklen_t tolen);