[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
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 */; };
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 */; };
A2DF37050C220D03006523C1 /* CreatorWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CreatorWindowController.m; path = macosx/CreatorWindowController.m; sourceTree = "<group>"; };
A2E23AC30CB5E1930002BB25 /* InfoTabButtonCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InfoTabButtonCell.h; path = macosx/InfoTabButtonCell.h; sourceTree = "<group>"; };
A2E23AC40CB5E1930002BB25 /* InfoTabButtonCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = InfoTabButtonCell.m; path = macosx/InfoTabButtonCell.m; sourceTree = "<group>"; };
- A2E384D2130DFB3A001F501B /* templates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = templates.h; path = "third-party/libutp/templates.h"; sourceTree = "<group>"; };
- 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 = "<group>"; };
- A2E384D4130DFB3A001F501B /* utp_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp_config.h; path = "third-party/libutp/utp_config.h"; sourceTree = "<group>"; };
A2E384D5130DFB3A001F501B /* utp_utils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = utp_utils.cpp; path = "third-party/libutp/utp_utils.cpp"; sourceTree = "<group>"; };
A2E384D6130DFB3A001F501B /* utp_utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp_utils.h; path = "third-party/libutp/utp_utils.h"; sourceTree = "<group>"; };
- A2E384D7130DFB3A001F501B /* utp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = utp.cpp; path = "third-party/libutp/utp.cpp"; sourceTree = "<group>"; };
A2E384D8130DFB3A001F501B /* utp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utp.h; path = "third-party/libutp/utp.h"; sourceTree = "<group>"; };
- A2E384D9130DFB3A001F501B /* utypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = utypes.h; path = "third-party/libutp/utypes.h"; sourceTree = "<group>"; };
- A2E3850B130DFCCB001F501B /* StdAfx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StdAfx.h; path = "third-party/libutp/StdAfx.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; name = StatusBarController.h; path = macosx/StatusBarController.h; sourceTree = "<group>"; };
A2E57ABA1310822C00A7DAB1 /* StatusBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = StatusBarController.m; path = macosx/StatusBarController.m; sourceTree = "<group>"; };
C1425B331EE9C5EA001DB85F /* tr-assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tr-assert.h"; path = "libtransmission/tr-assert.h"; sourceTree = "<group>"; };
C1425B341EE9C5EA001DB85F /* tr-macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tr-macros.h"; path = "libtransmission/tr-macros.h"; sourceTree = "<group>"; };
C1425B351EE9C5EA001DB85F /* peer-socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "peer-socket.h"; path = "libtransmission/peer-socket.h"; sourceTree = "<group>"; };
+ C16089E41F092A1E00CEFC36 /* utp_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_api.cpp; path = "third-party/libutp/utp_api.cpp"; sourceTree = "<group>"; };
+ C16089E51F092A1E00CEFC36 /* utp_callbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_callbacks.cpp; path = "third-party/libutp/utp_callbacks.cpp"; sourceTree = "<group>"; };
+ C16089E61F092A1E00CEFC36 /* utp_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_callbacks.h; path = "third-party/libutp/utp_callbacks.h"; sourceTree = "<group>"; };
+ C16089E71F092A1E00CEFC36 /* utp_hash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_hash.cpp; path = "third-party/libutp/utp_hash.cpp"; sourceTree = "<group>"; };
+ C16089E81F092A1E00CEFC36 /* utp_hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_hash.h; path = "third-party/libutp/utp_hash.h"; sourceTree = "<group>"; };
+ C16089E91F092A1E00CEFC36 /* utp_internal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_internal.cpp; path = "third-party/libutp/utp_internal.cpp"; sourceTree = "<group>"; };
+ C16089EA1F092A1E00CEFC36 /* utp_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_internal.h; path = "third-party/libutp/utp_internal.h"; sourceTree = "<group>"; };
+ C16089EB1F092A1E00CEFC36 /* utp_packedsockaddr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = utp_packedsockaddr.cpp; path = "third-party/libutp/utp_packedsockaddr.cpp"; sourceTree = "<group>"; };
+ C16089EC1F092A1E00CEFC36 /* utp_packedsockaddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_packedsockaddr.h; path = "third-party/libutp/utp_packedsockaddr.h"; sourceTree = "<group>"; };
+ C16089ED1F092A1E00CEFC36 /* utp_templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_templates.h; path = "third-party/libutp/utp_templates.h"; sourceTree = "<group>"; };
+ C16089EE1F092A1E00CEFC36 /* utp_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = utp_types.h; path = "third-party/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 = "third-party/libb64/src/cdecode.c"; sourceTree = "<group>"; };
C1639A771A55F56600E42033 /* cencode.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = cencode.c; path = "third-party/libb64/src/cencode.c"; sourceTree = "<group>"; };
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 = "<group>";
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;
};
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;
};
"$(inherited)",
"\"$(SRCROOT)/third-party/curl/lib\"",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = Transmission;
WRAPPER_EXTENSION = app;
};
"third-party/curl/include",
.,
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = transmissioncli;
};
name = Debug;
"$(inherited)",
"-DHAVE_DAEMON",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = "transmission-daemon";
};
name = Debug;
.,
"third-party/libevent/include",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = "transmission-remote";
};
name = Debug;
"third-party/curl/include",
.,
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = transmissioncli;
};
name = Release;
"$(inherited)",
"\"$(SRCROOT)/third-party/curl/lib\"",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = Transmission;
WRAPPER_EXTENSION = app;
};
"$(inherited)",
"\"$(SRCROOT)/third-party/curl/lib\"",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = Transmission;
WRAPPER_EXTENSION = app;
};
"third-party/curl/include",
.,
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = transmissioncli;
};
name = "Release - Debug";
"$(inherited)",
"-DHAVE_DAEMON",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = "transmission-daemon";
};
name = "Release - Debug";
.,
"third-party/libevent/include",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = "transmission-remote";
};
name = "Release - Debug";
INFOPLIST_FILE = "$(SRCROOT)/macosx/QuickLookPlugin/QuickLookPlugin-Info.plist";
INSTALL_PATH = /Library/QuickLook;
OTHER_LDFLAGS = (
+ "-lc++",
"-read_only_relocs",
suppress,
);
INFOPLIST_FILE = "$(SRCROOT)/macosx/QuickLookPlugin/QuickLookPlugin-Info.plist";
INSTALL_PATH = /Library/QuickLook;
OTHER_LDFLAGS = (
+ "-lc++",
"-read_only_relocs",
suppress,
);
INFOPLIST_FILE = "$(SRCROOT)/macosx/QuickLookPlugin/QuickLookPlugin-Info.plist";
INSTALL_PATH = /Library/QuickLook;
OTHER_LDFLAGS = (
+ "-lc++",
"-read_only_relocs",
suppress,
);
"$(inherited)",
"-DHAVE_DAEMON",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = "transmission-daemon";
};
name = Release;
.,
"third-party/libevent/include",
);
+ OTHER_LDFLAGS = "-lc++";
PRODUCT_NAME = "transmission-remote";
};
name = Release;
{
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);
+ }
}
}
#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);
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);
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");
else if (state == UTP_STATE_DESTROYING)
{
tr_logAddNamedError("UTP", "Impossible state UTP_STATE_DESTROYING");
- return;
}
else
{
}
}
-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)
}
}
-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 */
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
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)
{
#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
* 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;
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:
#include "utils.h" /* tr_time() */
struct evbuffer;
+
+struct struct_utp_context;
+
struct tr_bandwidth;
struct tr_datatype;
struct 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);
#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
tr_lpdInit(session, &session->public_ipv4->addr);
}
+ tr_utpInit(session);
+
/* cleanup */
tr_variantFree(&settings);
data->done = true;
tr_lpdUninit(session);
}
- tr_utpClose(session);
tr_dhtUninit(session);
event_free(session->saveTimer);
tr_statsClose(session);
tr_peerMgrFree(session->peerMgr);
+ tr_utpClose(session);
+
closeBlocklists(session);
tr_fdClose(session);
struct event_base;
struct evdns_base;
+struct struct_utp_context;
+
struct tr_address;
struct tr_announcer;
struct tr_announcer_udp;
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 */
#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"
#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,
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);
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);
}
}
+#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;
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. */
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)
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)
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 */
#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);
-Subproject commit fda9f4b3db97ccb243fcbed2ce280eb4135d705b
+Subproject commit f22f814b5d46ecabb0081a8a0b190f6e93ed1a4d