From: Willy Tarreau Date: Fri, 11 Dec 2020 15:20:34 +0000 (+0100) Subject: MINOR: connection: make conn_sock_drain() use the control layer's ->drain() X-Git-Tag: v2.4-dev3~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ded48dd27c2c57128921ae94d0b2a68162719e8;p=thirdparty%2Fhaproxy.git MINOR: connection: make conn_sock_drain() use the control layer's ->drain() Now we don't touch the fd anymore there, instead we rely on the ->drain() provided by the control layer. As such the function was renamed to conn_ctrl_drain(). --- diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index 40b15a31d9..f0ad25c146 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -62,7 +62,7 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag); int conn_ctrl_send(struct connection *conn, const void *buf, int len, int flags); /* drains any pending bytes from the socket */ -int conn_sock_drain(struct connection *conn); +int conn_ctrl_drain(struct connection *conn); /* scoks4 proxy handshake */ int conn_send_socks4_proxy_request(struct connection *conn); diff --git a/src/connection.c b/src/connection.c index d44402e86a..7c70e66a88 100644 --- a/src/connection.c +++ b/src/connection.c @@ -194,66 +194,24 @@ int conn_subscribe(struct connection *conn, void *xprt_ctx, int event_type, stru return 0; } -/* Drains possibly pending incoming data on the file descriptor attached to the - * connection and update the connection's flags accordingly. 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. The SOCK_RD_SH - * flag may also be updated if the incoming shutdown was reported by the drain() - * function. +/* Drains possibly pending incoming data on the connection and update the flags + * accordingly. 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. The CO_FL_SOCK_RD_SH flag may also be updated if the incoming + * shutdown was reported by the ->drain() function. */ -int conn_sock_drain(struct connection *conn) +int conn_ctrl_drain(struct connection *conn) { - int turns = 2; - int len; - - if (!conn_ctrl_ready(conn)) - return 1; - - if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) - return 1; - - if (fdtab[conn->handle.fd].ev & (FD_POLL_ERR|FD_POLL_HUP)) - goto shut; - - if (!fd_recv_ready(conn->handle.fd)) - return 0; - - /* no drain function defined, use the generic one */ - - while (turns) { -#ifdef MSG_TRUNC_CLEARS_INPUT - len = recv(conn->handle.fd, NULL, INT_MAX, MSG_DONTWAIT | MSG_NOSIGNAL | MSG_TRUNC); - if (len == -1 && errno == EFAULT) -#endif - len = recv(conn->handle.fd, trash.area, trash.size, - MSG_DONTWAIT | MSG_NOSIGNAL); - - if (len == 0) - goto shut; + int ret = 0; - if (len < 0) { - if (errno == EAGAIN) { - /* connection not closed yet */ - fd_cant_recv(conn->handle.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--; + if (!conn_ctrl_ready(conn) || conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) + ret = 1; + else if (conn->ctrl->drain) { + ret = conn->ctrl->drain(conn); + if (ret) + conn->flags |= CO_FL_SOCK_RD_SH; } - - /* some data are still present, give up */ - return 0; - - shut: - /* we're certain the connection was shut down */ - fdtab[conn->handle.fd].linger_risk = 0; - conn->flags |= CO_FL_SOCK_RD_SH; - return 1; + return ret; } /* diff --git a/src/mux_pt.c b/src/mux_pt.c index 3e2d066fd5..15309965ce 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -75,7 +75,7 @@ static struct task *mux_pt_io_cb(struct task *t, void *tctx, unsigned short stat ctx->cs->data_cb->wake(ctx->cs); return NULL; } - conn_sock_drain(ctx->conn); + conn_ctrl_drain(ctx->conn); if (ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH)) mux_pt_destroy(ctx); else @@ -148,7 +148,7 @@ static int mux_pt_wake(struct connection *conn) if (ret < 0) return ret; } else { - conn_sock_drain(conn); + conn_ctrl_drain(conn); if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) { mux_pt_destroy(ctx); return -1; @@ -248,7 +248,7 @@ static void mux_pt_shutr(struct conn_stream *cs, enum cs_shr_mode mode) cs->conn->xprt->shutr(cs->conn, cs->conn->xprt_ctx, (mode == CS_SHR_DRAIN)); else if (mode == CS_SHR_DRAIN) - conn_sock_drain(cs->conn); + conn_ctrl_drain(cs->conn); if (cs->flags & CS_FL_SHW) conn_full_close(cs->conn); } diff --git a/src/ssl_sock.c b/src/ssl_sock.c index e1de595fd2..732f586053 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -5276,7 +5276,7 @@ static int ssl_sock_handshake(struct connection *conn, unsigned int flag) * TCP sockets. We first try to drain possibly pending * data to avoid this as much as possible. */ - conn_sock_drain(conn); + conn_ctrl_drain(conn); if (!conn->err_code) conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ? CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE; @@ -5360,7 +5360,7 @@ check_error: * TCP sockets. We first try to drain possibly pending * data to avoid this as much as possible. */ - conn_sock_drain(conn); + conn_ctrl_drain(conn); if (!conn->err_code) conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ? CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE; diff --git a/src/tcp_act.c b/src/tcp_act.c index 182234f489..9179a80d05 100644 --- a/src/tcp_act.c +++ b/src/tcp_act.c @@ -176,7 +176,7 @@ static enum act_return tcp_exec_action_silent_drop(struct act_rule *rule, struct #ifdef TCP_QUICKACK /* drain is needed only to send the quick ACK */ - conn_sock_drain(conn); + conn_ctrl_drain(conn); /* re-enable quickack if it was disabled to ack all data and avoid * retransmits from the client that might trigger a real reset.