diff options
author | Leonid Evdokimov <leon@darkk.net.ru> | 2011-01-24 23:31:52 +0200 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-01-26 18:15:57 +0000 |
commit | 5668fb5c22e3726e732e4f5160aed93fa2c2b12e (patch) | |
tree | fe94bbff5567c424453980566395aaa6011af9c4 | |
parent | e024be4e45fe08c83b3132bd227f3065695c231d (diff) | |
download | libnodelay-5668fb5c22e3726e732e4f5160aed93fa2c2b12e.tar.gz |
Enforce NODELAY on setsockopt().
-rw-r--r-- | nodelay.c | 34 |
1 files changed, 31 insertions, 3 deletions
@@ -13,6 +13,7 @@ #include <netinet/tcp.h> #include <errno.h> #include <unistd.h> +#include <stdlib.h> #if defined(__GNUC__) && (__GNUC__ >= 3) # define unlikely(x) __builtin_expect (!!(x), 0) @@ -21,13 +22,25 @@ #endif static int (*real_socket)(int, int, int); +static int (*real_setsockopt)(int , int , int , const void *, socklen_t); + +static int nodelay_value; void __attribute__ ((constructor)) nodelay_init(void) { - real_socket = dlsym(RTLD_NEXT, "socket"); + char* nodelay = getenv("NODELAY"); + if (nodelay) + nodelay_value = atoi(nodelay); + else + nodelay_value = 1; + real_socket = dlsym(RTLD_NEXT, "socket"); if (!real_socket || dlerror()) _exit(1); + + real_setsockopt = dlsym(RTLD_NEXT, "setsockopt"); + if (!real_setsockopt || dlerror()) + _exit(1); } int socket(int domain, int type, int protocol) @@ -44,12 +57,27 @@ int socket(int domain, int type, int protocol) type == SOCK_STREAM && domain == PF_INET) { int orig_errno = errno; - int optval = 1; + int optval = nodelay_value; /* don't care too much if it fails */ - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)); + real_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int)); errno = orig_errno; } return fd; } + +int setsockopt(int sockfd, int level, int optname, const void *poptval, socklen_t optlen) +{ + int optval; + + if (unlikely(!real_socket)) + nodelay_init(); + + optval = nodelay_value; + if (level == IPPROTO_TCP && optname == TCP_NODELAY) { + poptval = &optval; + optlen = sizeof(optval); + } + return real_setsockopt(sockfd, level, optname, poptval, optlen); +} |