summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-12-11 01:20:43 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2017-12-11 21:35:31 -0500
commit84b5064dc4ca6a9e670f4566923ee8c8b4706c55 (patch)
tree30ffda08fd74b436226e41e3fcd2ae1a06f863b0
parente4ed2ed4aeb3a0afe9f5bc51559c0c0c2ac11a72 (diff)
downloadlighttpd-git-84b5064dc4ca6a9e670f4566923ee8c8b4706c55.tar.gz
[core] discard from socket using recv MSG_TRUNC
discard from socket using recv MSG_TRUNC on Linux TCP SOCK_STREAM socket Currently, lighttpd supports only TCP SOCK_STREAM. If UDP SOCK_DGRAM were to be supported in the future, then socket type will need to be stored so that MSG_TRUNC is used appropriately for the desired effect. To find out socket type on arbitrary socket fd: getsockopt(..., SOL_SOCKET, SO_TYPE, ...) but better to store it with each listening socket.
-rw-r--r--src/connections.c7
-rw-r--r--src/fdevent.c22
-rw-r--r--src/fdevent.h2
-rw-r--r--src/mod_extforward.c17
4 files changed, 43 insertions, 5 deletions
diff --git a/src/connections.c b/src/connections.c
index 80c63f45..03122fd5 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -161,10 +161,11 @@ static void connection_read_for_eos(server *srv, connection *con) {
* it will make the client not see all our output.
*/
ssize_t len;
- char buf[4096];
-
+ const int type = con->dst_addr.plain.sa_family;
+ char buf[16384];
do {
- len = read(con->fd, buf, sizeof(buf));
+ len = fdevent_socket_read_discard(con->fd, buf, sizeof(buf),
+ type, SOCK_STREAM);
} while (len > 0 || (len < 0 && errno == EINTR));
if (len < 0 && errno == EAGAIN) return;
diff --git a/src/fdevent.c b/src/fdevent.c
index 441744a7..e8b94dfa 100644
--- a/src/fdevent.c
+++ b/src/fdevent.c
@@ -889,6 +889,28 @@ int fdevent_cycle_logger(const char *logger, int *curfd) {
}
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0
+#endif
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+
+ssize_t fdevent_socket_read_discard (int fd, char *buf, size_t sz, int family, int so_type) {
+ #if defined(MSG_TRUNC) && defined(__linux__)
+ if ((family == AF_INET || family == AF_INET6) && so_type == SOCK_STREAM) {
+ ssize_t len = recv(fd, buf, sz, MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL);
+ if (len >= 0 || errno != EINVAL) return len;
+ }
+ #else
+ UNUSED(family);
+ UNUSED(so_type);
+ #endif
+ return read(fd, buf, sz);
+}
+
+
#include <sys/ioctl.h>
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h> /* FIONREAD (for illumos (OpenIndiana)) */
diff --git a/src/fdevent.h b/src/fdevent.h
index 4c7f42a9..44dbbb9d 100644
--- a/src/fdevent.h
+++ b/src/fdevent.h
@@ -78,6 +78,8 @@ void fdevent_close_logger_pipes(void);
void fdevent_breakagelog_logger_pipe(int fd);
void fdevent_clr_logger_pipe_pids(void);
+ssize_t fdevent_socket_read_discard (int fd, char *buf, size_t sz, int family, int so_type);
+
int fdevent_ioctl_fionread (int fd, int fdfmt, int *toread);
int fdevent_connect_status(int fd);
diff --git a/src/mod_extforward.c b/src/mod_extforward.c
index 0d1d7d7b..edccbfbf 100644
--- a/src/mod_extforward.c
+++ b/src/mod_extforward.c
@@ -1224,7 +1224,7 @@ indicating which element is present :
#endif
/* returns 0 if needs to poll, <0 upon error or >0 is protocol vers (success) */
-static int hap_PROXY_recv (const int fd, union hap_PROXY_hdr * const hdr)
+static int hap_PROXY_recv (const int fd, union hap_PROXY_hdr * const hdr, const int family, const int so_type)
{
static const char v2sig[12] =
"\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
@@ -1273,10 +1273,22 @@ static int hap_PROXY_recv (const int fd, union hap_PROXY_hdr * const hdr)
/* we need to consume the appropriate amount of data from the socket
* (overwrites existing contents of hdr with same data) */
+ UNUSED(family);
+ UNUSED(so_type);
do {
+ #if defined(MSG_TRUNC) && defined(__linux__)
+ if ((family==AF_INET || family==AF_INET6) && so_type == SOCK_STREAM) {
+ ret = recv(fd, hdr, sz, MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL);
+ if (ret >= 0 || errno != EINVAL) continue;
+ }
+ #endif
ret = recv(fd, hdr, sz, MSG_DONTWAIT|MSG_NOSIGNAL);
} while (-1 == ret && errno == EINTR);
if (ret < 0) return -1;
+ if (ret != (ssize_t)sz) {
+ errno = EIO; /*(partial read; valid but unexpected; not handled)*/
+ return -1;
+ }
if (1 == ver) hdr->v1.line[sz-2] = '\0'; /*terminate str to ease parsing*/
return ver;
}
@@ -1540,7 +1552,8 @@ static int mod_extforward_network_read (server *srv, connection *con,
* In the future, might add config switch to enable doing this extra work */
union hap_PROXY_hdr hdr;
- int rc = hap_PROXY_recv(con->fd, &hdr);
+ int rc = hap_PROXY_recv(con->fd, &hdr,
+ con->dst_addr.plain.sa_family, SOCK_STREAM);
switch (rc) {
case 2: rc = mod_extforward_hap_PROXY_v2(con, &hdr); break;
case 1: rc = mod_extforward_hap_PROXY_v1(con, &hdr); break;