1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
| | /*
* 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 or later
* and the GNU General Public License, version 2.
* See http://www.gnu.org/licenses/
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <sys/socket.h>
#include <netinet/in.h>
#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)
# else
# define unlikely(x) (x)
#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)
{
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)
{
int fd;
if (unlikely(!real_socket))
nodelay_init();
fd = real_socket(domain, type, protocol);
if (fd >= 0 &&
protocol == IPPROTO_TCP &&
(type & SOCK_STREAM) == SOCK_STREAM &&
domain == PF_INET) {
int orig_errno = errno;
int optval = nodelay_value;
/* don't care too much if it fails */
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();
if (level == IPPROTO_TCP && optname == TCP_NODELAY) {
optval = nodelay_value;
poptval = &optval;
optlen = sizeof(optval);
}
return real_setsockopt(sockfd, level, optname, poptval, optlen);
}
|