about summary refs log tree commit homepage
path: root/nodelay.c
diff options
context:
space:
mode:
Diffstat (limited to 'nodelay.c')
-rw-r--r--nodelay.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/nodelay.c b/nodelay.c
new file mode 100644
index 0000000..134a95a
--- /dev/null
+++ b/nodelay.c
@@ -0,0 +1,55 @@
+/*
+ * LD_PRELOAD-able library that disables the Nagle algorithm for all
+ * TCP sockets, both server and client.
+ *
+ * Copyright (C) 2009 Eric Wong <normalperson@yhbt.net>
+ *
+ * Licensed under the Lesser GNU General Public License, version 3.
+ */
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <errno.h>
+#include <unistd.h>
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#  define unlikely(x)        __builtin_expect (!!(x), 0)
+# else
+#  define unlikely(x)        (x)
+#endif
+
+static int (*real_socket)(int, int, int);
+
+void __attribute__ ((constructor)) nodelay_init(void)
+{
+        real_socket = dlsym(RTLD_NEXT, "socket");
+
+        if (!real_socket || dlerror())
+                _exit(1);
+}
+
+int socket(int domain, int type, int protocol)
+{
+        int fd;
+
+        if (unlikely(!real_socket))
+                nodelay_init();
+
+        fd = real_socket(domain, type, protocol);
+
+        if (fd >= 0 &&
+            protocol == IPPROTO_TCP &&
+            type == SOCK_STREAM &&
+            domain == PF_INET) {
+                int orig_errno = errno;
+                int optval = 1;
+
+                /* don't care too much if it fails */
+                setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
+                errno = orig_errno;
+        }
+
+        return fd;
+}