diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2011-01-09 23:35:45 +0000 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2011-01-09 23:35:45 +0000 |
commit | 15fc78d18733eb52a2274073545129fb061ac8e9 (patch) | |
tree | 8768880835efa6372f319d6285706a31955a8469 /package/uhttpd/src | |
parent | 8176a01da4842638acd8f757a666976e6cdd86f3 (diff) | |
download | upstream-15fc78d18733eb52a2274073545129fb061ac8e9.tar.gz upstream-15fc78d18733eb52a2274073545129fb061ac8e9.tar.bz2 upstream-15fc78d18733eb52a2274073545129fb061ac8e9.zip |
[package] uhttpd: protect tcp receive operations with select, make tcp keep-alive optional (#8272)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@24952 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/uhttpd/src')
-rw-r--r-- | package/uhttpd/src/uhttpd-utils.c | 30 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd.c | 35 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd.h | 1 |
3 files changed, 45 insertions, 21 deletions
diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index c7bc867aab..ac00af824e 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -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 ) { + FD_ZERO(&reader); + FD_SET(cl->socket, &reader); + + 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 + 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); + rsz = recv(cl->socket, (void *)&buf[sz], len, 0); - if( (sz == 0) || (rsz > 0) ) - sz += rsz; + 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)); diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index 2c7755f8da..1fd21344fe 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -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; diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h index 6747b905ff..ff058d62bf 100644 --- a/package/uhttpd/src/uhttpd.h +++ b/package/uhttpd/src/uhttpd.h @@ -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 |