Improve the sshnodelay hack after osxfuse's merge
Document the strage-looking symbol interposition that is necessary for the OS X case. While doing this, homogenize the code to do the real connect call for both the Linux and OS X cases into a helper function. This logic is generic and should not be replicated into various OS-specific cases.
This commit is contained in:
parent
27e7029148
commit
80db43d7dc
41
sshnodelay.c
41
sshnodelay.c
|
|
@ -5,8 +5,32 @@
|
|||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
/* Wrapper around connect(2) to explicitly set TCP_NODELAY. */
|
||||
static int nodelay_connect(
|
||||
int (*real_connect)(int, const struct sockaddr *, socklen_t),
|
||||
int sock, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int res = real_connect(sock, addr, addrlen);
|
||||
if (!res && addr->sa_family == AF_INET) {
|
||||
int opt = 1;
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
|
||||
/* OS X does not have LD_PRELOAD but has DYLD_INSERT_LIBRARIES. The right
|
||||
* environment variable is set by sshfs.c when attempting to load the
|
||||
* sshnodelay workaround.
|
||||
*
|
||||
* However, things are not that simple: DYLD_INSERT_LIBRARIES does not
|
||||
* behave exactly like LD_PRELOAD. Instead, the dyld dynamic linker will
|
||||
* look for __DATA __interpose sections on the libraries given via the
|
||||
* DYLD_INSERT_LIBRARIES variable. The contents of this section are pairs
|
||||
* of replacement functions and functions to be replaced, respectively.
|
||||
* Prepare such section here. */
|
||||
|
||||
int custom_connect(int sock, const struct sockaddr *addr, socklen_t addrlen);
|
||||
|
||||
typedef struct interpose_s {
|
||||
|
|
@ -21,26 +45,15 @@ static const interpose_t interposers[] \
|
|||
|
||||
int custom_connect(int sock, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int res = connect(sock, addr, addrlen);
|
||||
if (!res && addr->sa_family == AF_INET) {
|
||||
int opt = 1;
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
}
|
||||
return res;
|
||||
return nodelay_connect(connect, sock, addr, addrlen);
|
||||
}
|
||||
|
||||
#else /* !__APPLE__ */
|
||||
|
||||
int connect(int sock, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int (*next_connect)(int, const struct sockaddr *, socklen_t) =
|
||||
dlsym(RTLD_NEXT, "connect");
|
||||
int res = next_connect(sock, addr, addrlen);
|
||||
if (!res && addr->sa_family == AF_INET) {
|
||||
int opt = 1;
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
}
|
||||
return res;
|
||||
return nodelay_connect(dlsym(RTLD_NEXT, "connect"),
|
||||
sock, addr, addrlen);
|
||||
}
|
||||
|
||||
#endif /* !__APPLE__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue