[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.personal/stbuehler/fix-fdevent
parent
e4ed2ed4ae
commit
84b5064dc4
|
@ -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;
|
||||
|
|
|
@ -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)) */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue