diff options
author | Julio Merino <jmmv@meroh.net> | 2016-02-08 21:40:30 -0500 |
---|---|---|
committer | Julio Merino <jmmv@meroh.net> | 2016-02-08 21:40:30 -0500 |
commit | 80db43d7dce4f3979fe5e92b2d616d635f21029d (patch) | |
tree | ff8fd1c17b9be6d1aba7ff365614b10e41a1223b | |
parent | 27e7029148aa24803af8f40ea916213a381c1967 (diff) | |
download | sshfs-80db43d7dce4f3979fe5e92b2d616d635f21029d.tar sshfs-80db43d7dce4f3979fe5e92b2d616d635f21029d.tar.gz sshfs-80db43d7dce4f3979fe5e92b2d616d635f21029d.tar.bz2 sshfs-80db43d7dce4f3979fe5e92b2d616d635f21029d.zip |
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.
-rw-r--r-- | sshnodelay.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/sshnodelay.c b/sshnodelay.c index e1d9220..a9f307c 100644 --- a/sshnodelay.c +++ b/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__ */ |