From: Willy Tarreau Date: Sun, 10 Aug 2008 14:21:32 +0000 (+0200) Subject: [MEDIUM] process_cli: don't rely at all on server state X-Git-Tag: v1.3.16-rc1~214 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=718f0ef129ec31c8a38632ca475463a03f1c1c00;p=thirdparty%2Fhaproxy.git [MEDIUM] process_cli: don't rely at all on server state 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. --- diff --git a/include/types/buffers.h b/include/types/buffers.h index 8cc8d29a4a..417fe44627 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -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 { diff --git a/src/proto_http.c b/src/proto_http.c index 5d45f02042..ea7c764a95 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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);