aboutsummaryrefslogtreecommitdiff
path: root/sshnodelay.c
diff options
context:
space:
mode:
authorJulio Merino <jmmv@meroh.net>2016-02-08 21:40:30 -0500
committerJulio Merino <jmmv@meroh.net>2016-02-08 21:40:30 -0500
commit80db43d7dce4f3979fe5e92b2d616d635f21029d (patch)
treeff8fd1c17b9be6d1aba7ff365614b10e41a1223b /sshnodelay.c
parent27e7029148aa24803af8f40ea916213a381c1967 (diff)
downloadsshfs-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.
Diffstat (limited to 'sshnodelay.c')
-rw-r--r--sshnodelay.c41
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__ */