From 4bcd87c6172f7396e5c50363f4d109421775ed88 Mon Sep 17 00:00:00 2001 From: Mike Gelfand Date: Sun, 2 Jul 2017 13:34:41 +0300 Subject: [PATCH] Update libutp to 3.4+ (TRAC-5888) --- .gitmodules | 2 +- Transmission.xcodeproj/project.pbxproj | 81 ++++++++--- libtransmission/net.c | 13 +- libtransmission/peer-io.c | 178 ++++++++++--------------- libtransmission/peer-io.h | 5 + libtransmission/peer-mgr.c | 3 +- libtransmission/session.c | 5 +- libtransmission/session.h | 3 + libtransmission/tr-utp.c | 148 +++++++++++++++----- libtransmission/tr-utp.h | 4 +- third-party/libutp | 2 +- 11 files changed, 279 insertions(+), 165 deletions(-) diff --git a/.gitmodules b/.gitmodules index 041d7a0e8..a8b651a06 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,7 +17,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 diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 9474ce94e..f27eb15a6 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -249,14 +249,9 @@ A2D8CFBB15F82E030056E93D /* NSStringAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CC9C0980656F00BE280E /* NSStringAdditions.m */; }; A2DF37070C220D03006523C1 /* CreatorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A2DF37050C220D03006523C1 /* CreatorWindowController.m */; }; A2E23AC60CB5E1930002BB25 /* InfoTabButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A2E23AC40CB5E1930002BB25 /* InfoTabButtonCell.m */; }; - 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.m in Sources */ = {isa = PBXBuildFile; fileRef = A2E57ABA1310822C00A7DAB1 /* StatusBarController.m */; }; A2E57AC61310831400A7DAB1 /* StatusBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = A2E57AC51310831400A7DAB1 /* StatusBar.xib */; }; A2E57B9C13109DC200A7DAB1 /* FilterBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = A2E57B9B13109DC200A7DAB1 /* FilterBar.xib */; }; @@ -349,6 +344,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 */; }; @@ -880,15 +886,9 @@ A2DF37050C220D03006523C1 /* CreatorWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CreatorWindowController.m; path = macosx/CreatorWindowController.m; sourceTree = ""; }; A2E23AC30CB5E1930002BB25 /* InfoTabButtonCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InfoTabButtonCell.h; path = macosx/InfoTabButtonCell.h; sourceTree = ""; }; A2E23AC40CB5E1930002BB25 /* InfoTabButtonCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = InfoTabButtonCell.m; path = macosx/InfoTabButtonCell.m; sourceTree = ""; }; - A2E384D2130DFB3A001F501B /* templates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = templates.h; path = "third-party/libutp/templates.h"; sourceTree = ""; }; - A2E384D3130DFB3A001F501B /* utp_config_example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp_config_example.h; path = "third-party/libutp/utp_config_example.h"; sourceTree = ""; }; - A2E384D4130DFB3A001F501B /* utp_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp_config.h; path = "third-party/libutp/utp_config.h"; sourceTree = ""; }; A2E384D5130DFB3A001F501B /* utp_utils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = utp_utils.cpp; path = "third-party/libutp/utp_utils.cpp"; sourceTree = ""; }; A2E384D6130DFB3A001F501B /* utp_utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp_utils.h; path = "third-party/libutp/utp_utils.h"; sourceTree = ""; }; - A2E384D7130DFB3A001F501B /* utp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = utp.cpp; path = "third-party/libutp/utp.cpp"; sourceTree = ""; }; A2E384D8130DFB3A001F501B /* utp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp.h; path = "third-party/libutp/utp.h"; sourceTree = ""; }; - A2E384D9130DFB3A001F501B /* utypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utypes.h; path = "third-party/libutp/utypes.h"; sourceTree = ""; }; - A2E3850B130DFCCB001F501B /* StdAfx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StdAfx.h; path = "third-party/libutp/StdAfx.h"; sourceTree = ""; }; 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; name = StatusBarController.h; path = macosx/StatusBarController.h; sourceTree = ""; }; A2E57ABA1310822C00A7DAB1 /* StatusBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = StatusBarController.m; path = macosx/StatusBarController.m; sourceTree = ""; }; @@ -994,6 +994,17 @@ C1425B331EE9C5EA001DB85F /* tr-assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tr-assert.h"; path = "libtransmission/tr-assert.h"; sourceTree = ""; }; C1425B341EE9C5EA001DB85F /* tr-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tr-macros.h"; path = "libtransmission/tr-macros.h"; sourceTree = ""; }; C1425B351EE9C5EA001DB85F /* peer-socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "peer-socket.h"; path = "libtransmission/peer-socket.h"; sourceTree = ""; }; + C16089E41F092A1E00CEFC36 /* utp_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_api.cpp; path = "third-party/libutp/utp_api.cpp"; sourceTree = ""; }; + C16089E51F092A1E00CEFC36 /* utp_callbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_callbacks.cpp; path = "third-party/libutp/utp_callbacks.cpp"; sourceTree = ""; }; + C16089E61F092A1E00CEFC36 /* utp_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_callbacks.h; path = "third-party/libutp/utp_callbacks.h"; sourceTree = ""; }; + C16089E71F092A1E00CEFC36 /* utp_hash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_hash.cpp; path = "third-party/libutp/utp_hash.cpp"; sourceTree = ""; }; + C16089E81F092A1E00CEFC36 /* utp_hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_hash.h; path = "third-party/libutp/utp_hash.h"; sourceTree = ""; }; + C16089E91F092A1E00CEFC36 /* utp_internal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_internal.cpp; path = "third-party/libutp/utp_internal.cpp"; sourceTree = ""; }; + C16089EA1F092A1E00CEFC36 /* utp_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_internal.h; path = "third-party/libutp/utp_internal.h"; sourceTree = ""; }; + C16089EB1F092A1E00CEFC36 /* utp_packedsockaddr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_packedsockaddr.cpp; path = "third-party/libutp/utp_packedsockaddr.cpp"; sourceTree = ""; }; + C16089EC1F092A1E00CEFC36 /* utp_packedsockaddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_packedsockaddr.h; path = "third-party/libutp/utp_packedsockaddr.h"; sourceTree = ""; }; + C16089ED1F092A1E00CEFC36 /* utp_templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_templates.h; path = "third-party/libutp/utp_templates.h"; sourceTree = ""; }; + C16089EE1F092A1E00CEFC36 /* utp_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_types.h; path = "third-party/libutp/utp_types.h"; sourceTree = ""; }; 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 = "third-party/libb64/src/cdecode.c"; sourceTree = ""; }; C1639A771A55F56600E42033 /* cencode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cencode.c; path = "third-party/libb64/src/cencode.c"; sourceTree = ""; }; @@ -1562,15 +1573,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; sourceTree = ""; @@ -1854,12 +1870,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; }; @@ -2498,8 +2516,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; }; @@ -2940,6 +2962,7 @@ "$(inherited)", "\"$(SRCROOT)/third-party/curl/lib\"", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = Transmission; WRAPPER_EXTENSION = app; }; @@ -2952,6 +2975,7 @@ "third-party/curl/include", ., ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = transmissioncli; }; name = Debug; @@ -2968,6 +2992,7 @@ "$(inherited)", "-DHAVE_DAEMON", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = "transmission-daemon"; }; name = Debug; @@ -2980,6 +3005,7 @@ ., "third-party/libevent/include", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = "transmission-remote"; }; name = Debug; @@ -3106,6 +3132,7 @@ "third-party/curl/include", ., ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = transmissioncli; }; name = Release; @@ -3120,6 +3147,7 @@ "$(inherited)", "\"$(SRCROOT)/third-party/curl/lib\"", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = Transmission; WRAPPER_EXTENSION = app; }; @@ -3268,6 +3296,7 @@ "$(inherited)", "\"$(SRCROOT)/third-party/curl/lib\"", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = Transmission; WRAPPER_EXTENSION = app; }; @@ -3280,6 +3309,7 @@ "third-party/curl/include", ., ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = transmissioncli; }; name = "Release - Debug"; @@ -3330,6 +3360,7 @@ "$(inherited)", "-DHAVE_DAEMON", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = "transmission-daemon"; }; name = "Release - Debug"; @@ -3342,6 +3373,7 @@ ., "third-party/libevent/include", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = "transmission-remote"; }; name = "Release - Debug"; @@ -3389,6 +3421,7 @@ INFOPLIST_FILE = "$(SRCROOT)/macosx/QuickLookPlugin/QuickLookPlugin-Info.plist"; INSTALL_PATH = /Library/QuickLook; OTHER_LDFLAGS = ( + "-lc++", "-read_only_relocs", suppress, ); @@ -3404,6 +3437,7 @@ INFOPLIST_FILE = "$(SRCROOT)/macosx/QuickLookPlugin/QuickLookPlugin-Info.plist"; INSTALL_PATH = /Library/QuickLook; OTHER_LDFLAGS = ( + "-lc++", "-read_only_relocs", suppress, ); @@ -3419,6 +3453,7 @@ INFOPLIST_FILE = "$(SRCROOT)/macosx/QuickLookPlugin/QuickLookPlugin-Info.plist"; INSTALL_PATH = /Library/QuickLook; OTHER_LDFLAGS = ( + "-lc++", "-read_only_relocs", suppress, ); @@ -3469,6 +3504,7 @@ "$(inherited)", "-DHAVE_DAEMON", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = "transmission-daemon"; }; name = Release; @@ -3481,6 +3517,7 @@ ., "third-party/libevent/include", ); + OTHER_LDFLAGS = "-lc++"; PRODUCT_NAME = "transmission-remote"; }; name = Release; diff --git a/libtransmission/net.c b/libtransmission/net.c index 588dc2b27..02e5b51dd 100644 --- a/libtransmission/net.c +++ b/libtransmission/net.c @@ -331,15 +331,22 @@ struct tr_peer_socket tr_netOpenPeerUTPSocket(tr_session* session, tr_address co { struct tr_peer_socket ret = TR_PEER_SOCKET_INIT; - if (tr_address_is_valid_for_peers(addr, port)) + if (session->utp_context != NULL && 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); + struct UTPSocket* const socket = utp_create_socket(session->utp_context); if (socket != NULL) { - ret = tr_peer_socket_utp_create(socket); + if (utp_connect(socket, (struct sockaddr*)&ss, sslen) != -1) + { + ret = tr_peer_socket_utp_create(socket); + } + else + { + utp_close(socket); + } } } diff --git a/libtransmission/peer-io.c b/libtransmission/peer-io.c index 9fd955063..fb48788a0 100644 --- a/libtransmission/peer-io.c +++ b/libtransmission/peer-io.c @@ -440,12 +440,8 @@ static void maybeSetCongestionAlgorithm(tr_socket_t socket, char const* algorith #ifdef WITH_UTP /* UTP callbacks */ -static void utp_on_read(void* closure, 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) { - tr_peerIo* io = closure; - - TR_ASSERT(tr_isPeerIo(io)); - int rc = evbuffer_add(io->inbuf, buf, buflen); dbgmsg(io, "utp_on_read got %zu bytes", buflen); @@ -459,30 +455,8 @@ static void utp_on_read(void* closure, unsigned char const* buf, size_t buflen) canReadWrapper(io); } -static void utp_on_write(void* closure, unsigned char* buf, size_t buflen) -{ - tr_peerIo* io = closure; - - TR_ASSERT(tr_isPeerIo(io)); - - int rc = evbuffer_remove(io->outbuf, buf, buflen); - dbgmsg(io, "utp_on_write sending %zu bytes... evbuffer_remove returned %d", buflen, rc); - TR_ASSERT(rc == (int)buflen); /* if this fails, we've corrupted our bookkeeping somewhere */ - - if (rc < (long)buflen) - { - tr_logAddNamedError("UTP", "Short write: %d < %ld", rc, (long)buflen); - } - - didWriteWrapper(io, buflen); -} - -static size_t utp_get_rb_size(void* closure) +static uint64 utp_get_rb_size(tr_peerIo* const io) { - tr_peerIo* io = closure; - - TR_ASSERT(tr_isPeerIo(io)); - size_t bytes = tr_bandwidthClamp(&io->bandwidth, TR_DOWN, UTP_READ_BUFFER_SIZE); dbgmsg(io, "utp_get_rb_size is saying it's ready to read %zu bytes", bytes); @@ -501,12 +475,8 @@ static void utp_on_writable(tr_peerIo* io) tr_peerIoSetEnabled(io, TR_UP, n != 0 && evbuffer_get_length(io->outbuf) != 0); } -static void utp_on_state_change(void* closure, int state) +static void utp_on_state_change(tr_peerIo* const io, int const state) { - tr_peerIo* io = closure; - - TR_ASSERT(tr_isPeerIo(io)); - if (state == UTP_STATE_CONNECT) { dbgmsg(io, "utp_on_state_change -- changed to connected"); @@ -531,7 +501,6 @@ static void utp_on_state_change(void* closure, int state) else if (state == UTP_STATE_DESTROYING) { tr_logAddNamedError("UTP", "Impossible state UTP_STATE_DESTROYING"); - return; } else { @@ -539,12 +508,8 @@ static void utp_on_state_change(void* closure, int state) } } -static void utp_on_error(void* closure, int errcode) +static void utp_on_error(tr_peerIo* const io, int const errcode) { - tr_peerIo* io = closure; - - TR_ASSERT(tr_isPeerIo(io)); - dbgmsg(io, "utp_on_error -- errcode is %d", errcode); if (io->gotError != NULL) @@ -554,71 +519,60 @@ static void utp_on_error(void* closure, int errcode) } } -static void utp_on_overhead(void* closure, uint8_t /* bool */ send, size_t count, int type UNUSED) +static void utp_on_overhead(tr_peerIo* const io, bool const send, size_t const count, int const type UNUSED) { - tr_peerIo* io = closure; - - TR_ASSERT(tr_isPeerIo(io)); - dbgmsg(io, "utp_on_overhead -- count is %zu", count); tr_bandwidthUsed(&io->bandwidth, send ? TR_UP : TR_DOWN, count, false, tr_time_msec()); } -static struct UTPFunctionTable utp_function_table = +static uint64 utp_callback(utp_callback_arguments* args) { - .on_read = utp_on_read, - .on_write = utp_on_write, - .get_rb_size = utp_get_rb_size, - .on_state = utp_on_state_change, - .on_error = utp_on_error, - .on_overhead = utp_on_overhead -}; + tr_peerIo* const io = utp_get_userdata(args->socket); -/* Dummy UTP callbacks. */ -/* We switch a UTP socket to use these after the associated peerIo has been - destroyed -- see io_dtor. */ + if (io == NULL) + { +#ifdef TR_UTP_TRACE -static void dummy_read(void* closure UNUSED, unsigned char const* buf UNUSED, size_t buflen UNUSED) -{ - /* This cannot happen, as far as I'm aware. */ - tr_logAddNamedError("UTP", "On_read called on closed socket"); -} + if (args->callback_type != UTP_ON_STATE_CHANGE || args->u1.state != UTP_STATE_DESTROYING) + { + fprintf(stderr, "[utp] [%p:%p] [%s] io is null! buf=%p, len=%zu, flags=%d, send/error_code/state=%d, type=%d\n", + args->context, args->socket, utp_callback_names[args->callback_type], args->buf, args->len, args->flags, + args->u1.send, args->u2.type); + } -static void dummy_write(void* closure UNUSED, 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_logAddNamedDbg("UTP", "On_write called on closed socket"); - memset(buf, 0, buflen); -} +#endif -static size_t dummy_get_rb_size(void* closure UNUSED) -{ - return 0; -} + return 0; + } -static void dummy_on_state_change(void* closure UNUSED, int state UNUSED) -{ -} + TR_ASSERT(tr_isPeerIo(io)); + TR_ASSERT(io->socket.handle.utp == args->socket); -static void dummy_on_error(void* closure UNUSED, int errcode UNUSED) -{ -} + switch (args->callback_type) + { + case UTP_ON_READ: + utp_on_read(io, args->buf, args->len); + break; -static void dummy_on_overhead(void* closure UNUSED, uint8_t /* bool */ send UNUSED, size_t count UNUSED, int type UNUSED) -{ -} + case UTP_GET_READ_BUFFER_SIZE: + return utp_get_rb_size(io); -static struct UTPFunctionTable dummy_utp_function_table = -{ - .on_read = dummy_read, - .on_write = dummy_write, - .get_rb_size = dummy_get_rb_size, - .on_state = dummy_on_state_change, - .on_error = dummy_on_error, - .on_overhead = dummy_on_overhead -}; + 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; + } + + return 0; +} #endif /* #ifdef WITH_UTP */ @@ -670,16 +624,7 @@ static tr_peerIo* tr_peerIoNew(tr_session* session, tr_bandwidth* parent, tr_add case TR_PEER_SOCKET_TYPE_UTP: dbgmsg(io, "socket (utp) is %p", (void*)socket.handle.utp); - UTP_SetSockopt(socket.handle.utp, SO_RCVBUF, UTP_READ_BUFFER_SIZE); - dbgmsg(io, "%s", "calling UTP_SetCallbacks &utp_function_table"); - UTP_SetCallbacks(socket.handle.utp, &utp_function_table, io); - - if (!isIncoming) - { - dbgmsg(io, "%s", "calling UTP_Connect"); - UTP_Connect(socket.handle.utp); - } - + utp_set_userdata(socket.handle.utp, io); break; #endif @@ -691,6 +636,25 @@ static tr_peerIo* tr_peerIoNew(tr_session* session, tr_bandwidth* parent, tr_add return io; } +void tr_peerIoUtpInit(struct 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, UTP_READ_BUFFER_SIZE); + +#else + + (void)ctx; + +#endif +} + tr_peerIo* tr_peerIoNewIncoming(tr_session* session, tr_bandwidth* parent, tr_address const* addr, tr_port port, struct tr_peer_socket const socket) { @@ -848,8 +812,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, NULL); - UTP_Close(io->socket.handle.utp); + utp_set_userdata(io->socket.handle.utp, NULL); + utp_close(io->socket.handle.utp); break; #endif @@ -1281,7 +1245,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) == 0) { - UTP_RBDrained(io->socket.handle.utp); + utp_read_drained(io->socket.handle.utp); } break; @@ -1344,8 +1308,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); + n = utp_write(io->socket.handle.utp, evbuffer_pullup(io->outbuf, howmuch), howmuch); + + if (n > 0) + { + evbuffer_drain(io->outbuf, n); + didWriteWrapper(io, n); + } + break; case TR_PEER_SOCKET_TYPE_TCP: diff --git a/libtransmission/peer-io.h b/libtransmission/peer-io.h index 471633128..cf47d2bde 100644 --- a/libtransmission/peer-io.h +++ b/libtransmission/peer-io.h @@ -26,6 +26,9 @@ #include "utils.h" /* tr_time() */ struct evbuffer; + +struct struct_utp_context; + struct tr_bandwidth; struct tr_datatype; struct tr_peerIo; @@ -109,6 +112,8 @@ tr_peerIo; *** **/ +void tr_peerIoUtpInit(struct struct_utp_context* ctx); + tr_peerIo* tr_peerIoNewOutgoing(tr_session* session, struct tr_bandwidth* parent, struct tr_address const* addr, tr_port port, uint8_t const* torrentHash, bool isSeed, bool utp); diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c index 08cc18212..d920f1550 100644 --- a/libtransmission/peer-mgr.c +++ b/libtransmission/peer-mgr.c @@ -2137,7 +2137,8 @@ static void close_peer_socket(struct tr_peer_socket const socket, tr_session* se #ifdef WITH_UTP case TR_PEER_SOCKET_TYPE_UTP: - UTP_Close(socket.handle.utp); + utp_set_userdata(socket.handle.utp, NULL); + utp_close(socket.handle.utp); break; #endif diff --git a/libtransmission/session.c b/libtransmission/session.c index 86d054f7f..fa344651a 100644 --- a/libtransmission/session.c +++ b/libtransmission/session.c @@ -777,6 +777,8 @@ static void tr_sessionInitImpl(void* vdata) tr_lpdInit(session, &session->public_ipv4->addr); } + tr_utpInit(session); + /* cleanup */ tr_variantFree(&settings); data->done = true; @@ -1925,7 +1927,6 @@ static void sessionCloseImplStart(tr_session* session) tr_lpdUninit(session); } - tr_utpClose(session); tr_dhtUninit(session); event_free(session->saveTimer); @@ -2003,6 +2004,8 @@ static void sessionCloseImplFinish(tr_session* session) tr_statsClose(session); tr_peerMgrFree(session->peerMgr); + tr_utpClose(session); + closeBlocklists(session); tr_fdClose(session); diff --git a/libtransmission/session.h b/libtransmission/session.h index 9499507f9..4b009fafe 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -46,6 +46,8 @@ void tr_peerIdInit(uint8_t* setme); struct event_base; struct evdns_base; +struct struct_utp_context; + struct tr_address; struct tr_announcer; struct tr_announcer_udp; @@ -155,6 +157,7 @@ struct tr_session struct event* udp_event; struct event* udp6_event; + struct struct_utp_context* utp_context; struct event* utp_timer; /* The open port on the local machine for incoming peer requests */ diff --git a/libtransmission/tr-utp.c b/libtransmission/tr-utp.c index 06db2fd4a..a52887152 100644 --- a/libtransmission/tr-utp.c +++ b/libtransmission/tr-utp.c @@ -30,6 +30,7 @@ THE SOFTWARE. #include "net.h" #include "session.h" #include "crypto-utils.h" /* tr_rand_int_weak() */ +#include "peer-io.h" #include "peer-mgr.h" #include "peer-socket.h" #include "tr-assert.h" @@ -42,26 +43,30 @@ THE SOFTWARE. #ifndef WITH_UTP -void UTP_Close(struct UTPSocket* socket) +void utp_close(struct UTPSocket* socket) { - tr_logAddNamedError(MY_NAME, "UTP_Close(%p) was called.", socket); - dbgmsg("UTP_Close(%p) was called.", socket); + tr_logAddNamedError(MY_NAME, "utp_close(%p) was called.", socket); + dbgmsg("utp_close(%p) was called.", socket); TR_ASSERT(false); /* FIXME: this is too much for the long term, but probably needed in the short term */ } -void UTP_RBDrained(struct UTPSocket* socket) +void utp_read_drained(struct UTPSocket* socket) { - tr_logAddNamedError(MY_NAME, "UTP_RBDrained(%p) was called.", socket); - dbgmsg("UTP_RBDrained(%p) was called.", socket); + tr_logAddNamedError(MY_NAME, "utp_read_drained(%p) was called.", socket); + dbgmsg("utp_read_drained(%p) was called.", socket); TR_ASSERT(false); /* FIXME: this is too much for the long term, but probably needed in the short term */ } -bool UTP_Write(struct UTPSocket* socket, size_t count) +ssize_t utp_write(struct UTPSocket* socket, void* buf, size_t count) { - tr_logAddNamedError(MY_NAME, "UTP_RBDrained(%p, %zu) was called.", socket, count); - dbgmsg("UTP_RBDrained(%p, %zu) was called.", socket, count); + tr_logAddNamedError(MY_NAME, "utp_write(%p, %p, %zu) was called.", socket, buf, count); + dbgmsg("utp_write(%p, %p, %zu) was called.", socket, buf, count); TR_ASSERT(false); /* FIXME: this is too much for the long term, but probably needed in the short term */ - return false; + return -1; +} + +void tr_utpInit(tr_session* session UNUSED) +{ } int tr_utpPacket(unsigned char const* buf UNUSED, size_t buflen UNUSED, struct sockaddr const* from UNUSED, @@ -70,31 +75,27 @@ int tr_utpPacket(unsigned char const* buf UNUSED, size_t buflen UNUSED, struct s return -1; } -struct UTPSocket* UTP_Create(SendToProc* send_to_proc UNUSED, void* send_to_userdata UNUSED, struct sockaddr const* addr UNUSED, - socklen_t addrlen UNUSED) +struct UTPSocket* utp_create_socket(struct struct_utp_context *ctx UNUSED) { - errno = ENOSYS; return NULL; } -void tr_utpClose(tr_session* ss UNUSED) +int utp_connect(struct UTPSocket* s UNUSED, struct sockaddr const* to UNUSED, socklen_t tolen UNUSED) { + return -1; } -void tr_utpSendTo(void* closure UNUSED, unsigned char const* buf UNUSED, size_t buflen UNUSED, struct sockaddr const* to UNUSED, - socklen_t tolen UNUSED) +void tr_utpClose(tr_session* ss UNUSED) { } #else -/* Greg says 50ms works for them. */ +/* utp_internal.cpp says "Should be called every 500ms" for utp_check_timeouts */ +#define UTP_INTERVAL_US 500000 -#define UTP_INTERVAL_US 50000 - -static void incoming(void* closure, struct UTPSocket* s) +static void utp_on_accept(tr_session* const ss, struct UTPSocket* const s) { - tr_session* ss = closure; struct sockaddr_storage from_storage; struct sockaddr* from = (struct sockaddr*)&from_storage; socklen_t fromlen = sizeof(from_storage); @@ -103,26 +104,25 @@ static void incoming(void* closure, struct UTPSocket* s) if (!tr_sessionIsUTPEnabled(ss)) { - 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_logAddNamedError("UTP", "Unknown socket family"); - UTP_Close(s); + utp_close(s); return; } tr_peerMgrAddIncoming(ss->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) { - tr_session* ss = closure; - if (to->sa_family == AF_INET && ss->udp_socket != TR_BAD_SOCKET) { sendto(ss->udp_socket, (void const*)buf, buflen, 0, to, tolen); @@ -133,6 +133,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 ss UNUSED, char const* const msg) +{ + fprintf(stderr, "[utp] %s\n", msg); +} + +#endif + +static uint64 utp_callback(utp_callback_arguments* args) +{ + tr_session* const 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; @@ -146,7 +184,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. */ @@ -160,10 +198,48 @@ static void reset_timer(tr_session* ss) static void timer_callback(evutil_socket_t s UNUSED, short type UNUSED, void* closure) { tr_session* ss = closure; - 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(ss->utp_context); + + utp_check_timeouts(ss->utp_context); reset_timer(ss); } +void tr_utpInit(tr_session* session) +{ + if (session->utp_context != NULL) + { + return; + } + + struct struct_utp_context* ctx = utp_init(2); + + if (ctx == NULL) + { + 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; +} + int 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 == NULL) @@ -178,7 +254,12 @@ int 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); + int 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; } void tr_utpClose(tr_session* session) @@ -188,6 +269,13 @@ void tr_utpClose(tr_session* session) evtimer_del(session->utp_timer); session->utp_timer = NULL; } + + if (session->utp_context != NULL) + { + utp_context_set_userdata(session->utp_context, NULL); + utp_destroy(session->utp_context); + session->utp_context = NULL; + } } #endif /* #ifndef WITH_UTP ... else */ diff --git a/libtransmission/tr-utp.h b/libtransmission/tr-utp.h index 4aae573c5..32a488138 100644 --- a/libtransmission/tr-utp.h +++ b/libtransmission/tr-utp.h @@ -27,8 +27,8 @@ THE SOFTWARE. #pragma once +void tr_utpInit(tr_session* session); + int 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); diff --git a/third-party/libutp b/third-party/libutp index fda9f4b3d..f22f814b5 160000 --- a/third-party/libutp +++ b/third-party/libutp @@ -1 +1 @@ -Subproject commit fda9f4b3db97ccb243fcbed2ce280eb4135d705b +Subproject commit f22f814b5d46ecabb0081a8a0b190f6e93ed1a4d -- 2.40.0