uhttpd: protect tcp receive operations with select, make tcp keep-alive optional (#8272)
SVN-Revision: 24952
This commit is contained in:
parent
8067116c10
commit
f38a320e69
6 changed files with 56 additions and 24 deletions
|
@ -8,7 +8,7 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=uhttpd
|
||||
PKG_RELEASE:=20
|
||||
PKG_RELEASE:=21
|
||||
|
||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||
PKG_BUILD_DEPENDS := libcyassl liblua
|
||||
|
|
|
@ -51,6 +51,13 @@ config uhttpd main
|
|||
# request process.
|
||||
option network_timeout 30
|
||||
|
||||
# TCP Keep-Alive, send periodic keep-alive probes
|
||||
# over established connections to detect dead peers.
|
||||
# The value is given in seconds to specify the
|
||||
# interval between subsequent probes.
|
||||
# Setting this to 0 will disable TCP keep-alive.
|
||||
option tcp_keepalive 1
|
||||
|
||||
# Basic auth realm, defaults to local hostname
|
||||
# option realm OpenWrt
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ start_instance()
|
|||
append_arg "$cfg" lua_handler "-L"
|
||||
append_arg "$cfg" script_timeout "-t"
|
||||
append_arg "$cfg" network_timeout "-T"
|
||||
append_arg "$cfg" tcp_keepalive "-A"
|
||||
append_arg "$cfg" error_page "-E"
|
||||
append_arg "$cfg" index_page "-I"
|
||||
|
||||
|
|
|
@ -167,6 +167,9 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
|
|||
int sz = 0;
|
||||
int rsz = 0;
|
||||
|
||||
fd_set reader;
|
||||
struct timeval timeout;
|
||||
|
||||
/* first serve data from peek buffer */
|
||||
if( cl->peeklen > 0 )
|
||||
{
|
||||
|
@ -180,15 +183,28 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
|
|||
/* caller wants more */
|
||||
if( len > 0 )
|
||||
{
|
||||
#ifdef HAVE_TLS
|
||||
if( cl->tls )
|
||||
rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
|
||||
else
|
||||
#endif
|
||||
rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
|
||||
FD_ZERO(&reader);
|
||||
FD_SET(cl->socket, &reader);
|
||||
|
||||
if( (sz == 0) || (rsz > 0) )
|
||||
sz += rsz;
|
||||
timeout.tv_sec = cl->server->conf->network_timeout;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
|
||||
{
|
||||
#ifdef HAVE_TLS
|
||||
if( cl->tls )
|
||||
rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
|
||||
else
|
||||
#endif
|
||||
rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
|
||||
|
||||
if( (sz == 0) || (rsz > 0) )
|
||||
sz += rsz;
|
||||
}
|
||||
else if( sz == 0 )
|
||||
{
|
||||
sz = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return sz;
|
||||
|
@ -233,7 +249,7 @@ int uh_http_sendc(struct client *cl, const char *data, int len)
|
|||
|
||||
if( len > 0 )
|
||||
{
|
||||
clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
|
||||
clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
|
||||
ensure_ret(uh_tcp_send(cl, chunk, clen));
|
||||
ensure_ret(uh_tcp_send(cl, data, len));
|
||||
ensure_ret(uh_tcp_send(cl, "\r\n", 2));
|
||||
|
|
|
@ -127,9 +127,7 @@ static int uh_socket_bind(
|
|||
int status;
|
||||
int bound = 0;
|
||||
|
||||
int tcp_ka_idl = 1;
|
||||
int tcp_ka_int = 1;
|
||||
int tcp_ka_cnt = 3;
|
||||
int tcp_ka_idl, tcp_ka_int, tcp_ka_cnt;
|
||||
|
||||
struct listener *l = NULL;
|
||||
struct addrinfo *addrs = NULL, *p = NULL;
|
||||
|
@ -157,13 +155,20 @@ static int uh_socket_bind(
|
|||
}
|
||||
|
||||
/* TCP keep-alive */
|
||||
if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) ||
|
||||
setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) ||
|
||||
setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) ||
|
||||
setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) )
|
||||
if( conf->tcp_keepalive > 0 )
|
||||
{
|
||||
fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
|
||||
strerror(errno));
|
||||
tcp_ka_idl = 1;
|
||||
tcp_ka_cnt = 3;
|
||||
tcp_ka_int = conf->tcp_keepalive;
|
||||
|
||||
if( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) ||
|
||||
setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &tcp_ka_idl, sizeof(tcp_ka_idl)) ||
|
||||
setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &tcp_ka_int, sizeof(tcp_ka_int)) ||
|
||||
setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &tcp_ka_cnt, sizeof(tcp_ka_cnt)) )
|
||||
{
|
||||
fprintf(stderr, "Notice: Unable to enable TCP keep-alive: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* required to get parallel v4 + v6 working */
|
||||
|
@ -619,7 +624,7 @@ static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd)
|
|||
int main (int argc, char **argv)
|
||||
{
|
||||
/* master file descriptor list */
|
||||
fd_set used_fds, serv_fds, read_fds;
|
||||
fd_set serv_fds;
|
||||
|
||||
/* working structs */
|
||||
struct addrinfo hints;
|
||||
|
@ -650,10 +655,7 @@ int main (int argc, char **argv)
|
|||
void *lib;
|
||||
#endif
|
||||
|
||||
/* clear the master and temp sets */
|
||||
FD_ZERO(&used_fds);
|
||||
FD_ZERO(&serv_fds);
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* handle SIGPIPE, SIGINT, SIGTERM, SIGCHLD */
|
||||
sa.sa_flags = 0;
|
||||
|
@ -722,7 +724,7 @@ int main (int argc, char **argv)
|
|||
#endif
|
||||
|
||||
while( (opt = getopt(argc, argv,
|
||||
"fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:")) > 0
|
||||
"fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:i:t:T:A:")) > 0
|
||||
) {
|
||||
switch(opt)
|
||||
{
|
||||
|
@ -896,6 +898,11 @@ int main (int argc, char **argv)
|
|||
conf.network_timeout = atoi(optarg);
|
||||
break;
|
||||
|
||||
/* tcp keep-alive */
|
||||
case 'A':
|
||||
conf.tcp_keepalive = atoi(optarg);
|
||||
break;
|
||||
|
||||
/* no fork */
|
||||
case 'f':
|
||||
nofork = 1;
|
||||
|
|
|
@ -75,6 +75,7 @@ struct config {
|
|||
int no_dirlists;
|
||||
int network_timeout;
|
||||
int rfc1918_filter;
|
||||
int tcp_keepalive;
|
||||
#ifdef HAVE_CGI
|
||||
char *cgi_prefix;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue