]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] process_cli: don't rely at all on server state
authorWilly Tarreau <w@1wt.eu>
Sun, 10 Aug 2008 14:21:32 +0000 (16:21 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 10 Aug 2008 14:21:32 +0000 (16:21 +0200)
A new buffer flag BF_MAY_FORWARD has been added so that the client
FSM can check whether it is allowed to forward the response to the
client. The client FSM does not have to monitor the server state
anymore.

include/types/buffers.h
src/proto_http.c

index 8cc8d29a4ab3b54e4753e97f398c1735add2d6d3..417fe44627193ad49600eb4002afc904fa1cf18c 100644 (file)
@@ -54,6 +54,7 @@
 #define BF_STREAMER_FAST     8192
 
 #define BF_MAY_CONNECT      16384  /* consumer side is allowed to forward the connection */
+#define BF_MAY_FORWARD      32768  /* consumer side is allowed to forward the data */
 
 /* describes a chunk of string */
 struct chunk {
index 5d45f02042f3ab093d154f0a6f6683ca76b5d8d1..ea7c764a95455b43483ce4b1e84b153750152ca9 100644 (file)
@@ -547,6 +547,7 @@ void srv_close_with_err(struct session *t, int err, int finst,
        t->srv_state = SV_STCLOSE;
        buffer_shutw_done(t->req);
        buffer_shutr_done(t->rep);
+       t->rep->flags |= BF_MAY_FORWARD;
        if (status > 0 && msg) {
                t->txn.status = status;
                if (t->fe->mode == PR_MODE_HTTP)
@@ -1644,7 +1645,7 @@ int process_cli(struct session *t)
                        t->txn.exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq);
                } else {
                        t->cli_state = CL_STDATA;
-                       req->flags |= BF_MAY_CONNECT;
+                       req->flags |= BF_MAY_CONNECT | BF_MAY_FORWARD;
                }
                t->inspect_exp = TICK_ETERNITY;
                return 1;
@@ -2366,14 +2367,14 @@ int process_cli(struct session *t)
                 ************************************************************/
 
                t->cli_state = CL_STDATA;
-               req->flags |= BF_MAY_CONNECT;
+               req->flags |= BF_MAY_CONNECT | BF_MAY_FORWARD;
 
                req->rlim = req->data + BUFSIZE; /* no more rewrite needed */
 
                t->logs.tv_request = now;
 
                if (!t->fe->timeout.client ||
-                   (t->srv_state < SV_STDATA && t->be->timeout.server)) {
+                   (!(rep->flags & BF_MAY_FORWARD) && t->be->timeout.server)) {
                        /* If the client has no timeout, or if the server is not ready yet,
                         * and we know for sure that it can expire, then it's cleaner to
                         * disable the timeout on the client side so that too low values
@@ -2443,14 +2444,14 @@ int process_cli(struct session *t)
                        return 1;
                }
                /* last read, or end of server write */
-               else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
+               else if (req->flags & (BF_READ_NULL | BF_SHUTW_STATUS)) {
                        EV_FD_CLR(t->cli_fd, DIR_RD);
                        buffer_shutr(req);
                        t->cli_state = CL_STSHUTR;
                        return 1;
                }       
                /* last server read and buffer empty */
-               else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
+               else if (rep->flags & BF_SHUTR_STATUS && rep->l == 0) {
                        EV_FD_CLR(t->cli_fd, DIR_WR);
                        buffer_shutw_done(rep);
                        shutdown(t->cli_fd, SHUT_WR);
@@ -2513,11 +2514,12 @@ int process_cli(struct session *t)
                        /* there's still some space in the buffer */
                        if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
                                if (!t->fe->timeout.client ||
-                                   (t->srv_state < SV_STDATA && t->be->timeout.server))
+                                   (!(rep->flags & BF_MAY_FORWARD) && t->be->timeout.server))
                                        /* If the client has no timeout, or if the server not ready yet, and we
                                         * know for sure that it can expire, then it's cleaner to disable the
                                         * timeout on the client side so that too low values cannot make the
-                                        * sessions abort too early.
+                                        * sessions abort too early. NB: we should only do this in HTTP states
+                                        * before HEADERS.
                                         */
                                        req->rex = TICK_ETERNITY;
                                else
@@ -2525,8 +2527,8 @@ int process_cli(struct session *t)
                        }
                }
 
-               if ((rep->l == 0) ||
-                   ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
+               /* we don't enable client write if the buffer is empty, nor if the server has to analyze it */
+               if ((rep->l == 0) || !(rep->flags & BF_MAY_FORWARD)) {
                        if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
                                /* stop writing */
                                rep->wex = TICK_ETERNITY;
@@ -2562,7 +2564,7 @@ int process_cli(struct session *t)
                        }
                        return 1;
                }
-               else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)
+               else if ((rep->flags & BF_SHUTR_STATUS) && (rep->l == 0)
                         && !(t->flags & SN_SELF_GEN)) {
                        buffer_shutw_done(rep);
                        fd_delete(t->cli_fd);
@@ -2596,8 +2598,7 @@ int process_cli(struct session *t)
                        }
                }
 
-               if ((rep->l == 0)
-                   || ((s == SV_STHEADERS) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
+               if ((rep->l == 0) || !(rep->flags & BF_MAY_FORWARD)) {
                        if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
                                /* stop writing */
                                rep->wex = TICK_ETERNITY;
@@ -2628,7 +2629,7 @@ int process_cli(struct session *t)
                        }
                        return 1;
                }
-               else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
+               else if (req->flags & (BF_READ_NULL | BF_SHUTW_STATUS)) {
                        buffer_shutr_done(req);
                        fd_delete(t->cli_fd);
                        t->cli_state = CL_STCLOSE;
@@ -2950,6 +2951,7 @@ int process_srv(struct session *t)
                                EV_FD_SET(t->srv_fd, DIR_RD);
                                rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
                                t->srv_state = SV_STDATA;
+                               rep->flags |= BF_MAY_FORWARD;
                                rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */
 
                                /* if the user wants to log as soon as possible, without counting
@@ -3468,6 +3470,7 @@ int process_srv(struct session *t)
                 ************************************************************/
 
                t->srv_state = SV_STDATA;
+               rep->flags |= BF_MAY_FORWARD;
                rep->rlim = rep->data + BUFSIZE; /* no more rewrite needed */
                t->logs.t_data = tv_ms_elapsed(&t->logs.tv_accept, &now);