diff options
Diffstat (limited to 'nodelay.c')
-rw-r--r-- | nodelay.c | 55 |
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; +} |