mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-28 14:21:00 +01:00
MINOR: protocol: add a ->drain() function at the connection control layer
This is what we need to drain pending incoming data from an connection. The code was taken from conn_sock_drain() without the connection-specific stuff. It still takes a connection for now for API simplicity.
This commit is contained in:
parent
586f71b43f
commit
427c846cc9
@ -99,6 +99,7 @@ struct protocol {
|
|||||||
void (*ctrl_init)(struct connection *); /* completes initialization of the connection */
|
void (*ctrl_init)(struct connection *); /* completes initialization of the connection */
|
||||||
void (*ctrl_close)(struct connection *); /* completes release of the connection */
|
void (*ctrl_close)(struct connection *); /* completes release of the connection */
|
||||||
int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */
|
int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */
|
||||||
|
int (*drain)(struct connection *); /* drain pending data; 0=failed, >0=success */
|
||||||
|
|
||||||
/* functions acting on the receiver */
|
/* functions acting on the receiver */
|
||||||
int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */
|
int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */
|
||||||
|
|||||||
@ -47,6 +47,7 @@ void sock_conn_ctrl_init(struct connection *conn);
|
|||||||
void sock_conn_ctrl_close(struct connection *conn);
|
void sock_conn_ctrl_close(struct connection *conn);
|
||||||
void sock_conn_iocb(int fd);
|
void sock_conn_iocb(int fd);
|
||||||
int sock_conn_check(struct connection *conn);
|
int sock_conn_check(struct connection *conn);
|
||||||
|
int sock_drain(struct connection *conn);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_SOCK_H */
|
#endif /* _HAPROXY_SOCK_H */
|
||||||
|
|||||||
@ -77,6 +77,7 @@ struct protocol proto_sockpair = {
|
|||||||
.ctrl_init = sock_conn_ctrl_init,
|
.ctrl_init = sock_conn_ctrl_init,
|
||||||
.ctrl_close = sock_conn_ctrl_close,
|
.ctrl_close = sock_conn_ctrl_close,
|
||||||
.connect = sockpair_connect_server,
|
.connect = sockpair_connect_server,
|
||||||
|
.drain = sock_drain,
|
||||||
|
|
||||||
/* binding layer */
|
/* binding layer */
|
||||||
/* Note: suspend/resume not supported */
|
/* Note: suspend/resume not supported */
|
||||||
|
|||||||
@ -67,6 +67,7 @@ struct protocol proto_tcpv4 = {
|
|||||||
.ctrl_init = sock_conn_ctrl_init,
|
.ctrl_init = sock_conn_ctrl_init,
|
||||||
.ctrl_close = sock_conn_ctrl_close,
|
.ctrl_close = sock_conn_ctrl_close,
|
||||||
.connect = tcp_connect_server,
|
.connect = tcp_connect_server,
|
||||||
|
.drain = sock_drain,
|
||||||
|
|
||||||
/* binding layer */
|
/* binding layer */
|
||||||
.rx_suspend = tcp_suspend_receiver,
|
.rx_suspend = tcp_suspend_receiver,
|
||||||
@ -106,6 +107,7 @@ struct protocol proto_tcpv6 = {
|
|||||||
.ctrl_init = sock_conn_ctrl_init,
|
.ctrl_init = sock_conn_ctrl_init,
|
||||||
.ctrl_close = sock_conn_ctrl_close,
|
.ctrl_close = sock_conn_ctrl_close,
|
||||||
.connect = tcp_connect_server,
|
.connect = tcp_connect_server,
|
||||||
|
.drain = sock_drain,
|
||||||
|
|
||||||
/* binding layer */
|
/* binding layer */
|
||||||
.rx_suspend = tcp_suspend_receiver,
|
.rx_suspend = tcp_suspend_receiver,
|
||||||
|
|||||||
@ -63,6 +63,7 @@ struct protocol proto_uxst = {
|
|||||||
.ctrl_init = sock_conn_ctrl_init,
|
.ctrl_init = sock_conn_ctrl_init,
|
||||||
.ctrl_close = sock_conn_ctrl_close,
|
.ctrl_close = sock_conn_ctrl_close,
|
||||||
.connect = uxst_connect_server,
|
.connect = uxst_connect_server,
|
||||||
|
.drain = sock_drain,
|
||||||
|
|
||||||
/* binding layer */
|
/* binding layer */
|
||||||
.rx_suspend = uxst_suspend_receiver,
|
.rx_suspend = uxst_suspend_receiver,
|
||||||
|
|||||||
53
src/sock.c
53
src/sock.c
@ -819,6 +819,59 @@ void sock_conn_iocb(int fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Drains possibly pending incoming data on the file descriptor attached to the
|
||||||
|
* connection. This is used to know whether we need to disable lingering on
|
||||||
|
* close. Returns non-zero if it is safe to close without disabling lingering,
|
||||||
|
* otherwise zero.
|
||||||
|
*/
|
||||||
|
int sock_drain(struct connection *conn)
|
||||||
|
{
|
||||||
|
int turns = 2;
|
||||||
|
int fd = conn->handle.fd;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (fdtab[fd].ev & (FD_POLL_ERR|FD_POLL_HUP))
|
||||||
|
goto shut;
|
||||||
|
|
||||||
|
if (!fd_recv_ready(fd))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* no drain function defined, use the generic one */
|
||||||
|
|
||||||
|
while (turns) {
|
||||||
|
#ifdef MSG_TRUNC_CLEARS_INPUT
|
||||||
|
len = recv(fd, NULL, INT_MAX, MSG_DONTWAIT | MSG_NOSIGNAL | MSG_TRUNC);
|
||||||
|
if (len == -1 && errno == EFAULT)
|
||||||
|
#endif
|
||||||
|
len = recv(fd, trash.area, trash.size, MSG_DONTWAIT | MSG_NOSIGNAL);
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
goto shut;
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
/* connection not closed yet */
|
||||||
|
fd_cant_recv(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (errno == EINTR) /* oops, try again */
|
||||||
|
continue;
|
||||||
|
/* other errors indicate a dead connection, fine. */
|
||||||
|
goto shut;
|
||||||
|
}
|
||||||
|
/* OK we read some data, let's try again once */
|
||||||
|
turns--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* some data are still present, give up */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
shut:
|
||||||
|
/* we're certain the connection was shut down */
|
||||||
|
fdtab[fd].linger_risk = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
* c-indent-level: 8
|
* c-indent-level: 8
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user