]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: make conn_sock_drain() use the control layer's ->drain()
authorWilly Tarreau <w@1wt.eu>
Fri, 11 Dec 2020 15:20:34 +0000 (16:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 11 Dec 2020 15:26:01 +0000 (16:26 +0100)
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().

include/haproxy/connection.h
src/connection.c
src/mux_pt.c
src/ssl_sock.c
src/tcp_act.c

index 40b15a31d91cc0d3353c4ed43c8c4568effc77dc..f0ad25c1468f3364e152d761447ea43f2a40bc67 100644 (file)
@@ -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);
index d44402e86aa823afbbaaa9f7c3023de139440223..7c70e66a8879bc8a9735b158034f6b44baae19d8 100644 (file)
@@ -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;
 }
 
 /*
index 3e2d066fd510625b0db51cf59e64e8f31e899d9a..15309965ce355b6f64ff272a1293d46465338c5d 100644 (file)
@@ -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);
 }
index e1de595fd2902e44d8d68ce0018451d6077f4887..732f58605331e96e587010ef3f3c587d7f1bdc1d 100644 (file)
@@ -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;
index 182234f489c82c4263e7bcb2338f70d5172cc8b8..9179a80d05c72687138a120daa88969e5ad8cbd0 100644 (file)
@@ -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.