]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MAJOR] buffers: split BF_WRITE_ENA into BF_AUTO_CONNECT and BF_AUTO_CLOSE
authorWilly Tarreau <w@1wt.eu>
Sat, 19 Sep 2009 19:04:57 +0000 (21:04 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 19 Sep 2009 19:14:54 +0000 (21:14 +0200)
The BF_WRITE_ENA buffer flag became very complex to deal with, because
it was used to :
  - enable automatic connection
  - enable close forwarding
  - enable data forwarding

The last point was not very true anymore since we introduced ->send_max,
but still the test remained everywhere. This was causing issues such as
impossibility to connect without forwarding data, impossibility to prevent
closing when data was forwarded, etc...

This patch clarifies the situation by getting rid of this multi-purpose
flag and replacing it with :
  - data forwarding based only on ->send_max || ->pipe ;
  - a new BF_AUTO_CONNECT flag to allow automatic connection and only
    that ;
  - ability to perform an automatic connection when ->send_max or ->pipe
    indicate that data is waiting to leave the buffer ;
  - a new BF_AUTO_CLOSE flag to let the producer automatically set the
    BF_SHUTW_NOW flag when it gets a BF_SHUTR.

During this cleanup, it was discovered that some tests were performed
twice, or that the BF_HIJACK flag was still tested, which is not needed
anymore since ->send_max replcaed it. These places have been fixed too.

These cleanups have also revealed a few areas where the other flags
such as BF_EMPTY are not cleanly used. This will be an opportunity for
a second patch.

include/proto/buffers.h
include/types/buffers.h
src/client.c
src/dumpstats.c
src/proto_http.c
src/proto_tcp.c
src/session.c
src/stream_interface.c
src/stream_sock.c

index 66bee89057de74c5fd6a1e918e9d4f6bda3c42cd..8df6231a1e0b42fb7512389c123cf8acc1e6dd5d 100644 (file)
@@ -211,54 +211,30 @@ static inline void buffer_stop_hijack(struct buffer *buf)
        buf->flags &= ~BF_HIJACK;
 }
 
-/* allows the consumer to send the buffer contents */
-static inline void buffer_write_ena(struct buffer *buf)
+/* allow the consumer to try to establish a new connection. */
+static inline void buffer_auto_connect(struct buffer *buf)
 {
-       buf->flags |= BF_WRITE_ENA;
+       buf->flags |= BF_AUTO_CONNECT;
 }
 
-/* prevents the consumer from sending the buffer contents */
-static inline void buffer_write_dis(struct buffer *buf)
+/* prevent the consumer from trying to establish a new connection, and also
+ * disable auto shutdown forwarding.
+ */
+static inline void buffer_dont_connect(struct buffer *buf)
 {
-       buf->flags &= ~BF_WRITE_ENA;
+       buf->flags &= ~(BF_AUTO_CONNECT|BF_AUTO_CLOSE);
 }
 
-/* check if the buffer needs to be shut down for read, and perform the shutdown
- * at the stream_interface level if needed. This must not be used with a buffer
- * for which a connection is currently in queue or turn-around.
- */
-static inline void buffer_check_shutr(struct buffer *b)
+/* allow the producer to forward shutdown requests */
+static inline void buffer_auto_close(struct buffer *buf)
 {
-       if (b->flags & BF_SHUTR)
-               return;
-
-       if (!(b->flags & (BF_SHUTR_NOW|BF_SHUTW)))
-               return;
-
-       /* Last read, forced read-shutdown, or other end closed. We have to
-        * close our read side and inform the stream_interface.
-        */
-       b->prod->shutr(b->prod);
+       buf->flags |= BF_AUTO_CLOSE;
 }
 
-/* check if the buffer needs to be shut down for write, and perform the shutdown
- * at the stream_interface level if needed. This must not be used with a buffer
- * for which a connection is currently in queue or turn-around.
- */
-static inline void buffer_check_shutw(struct buffer *b)
+/* prevent the producer from forwarding shutdown requests */
+static inline void buffer_dont_close(struct buffer *buf)
 {
-       if (b->flags & BF_SHUTW)
-               return;
-
-       if ((b->flags & BF_SHUTW_NOW) ||
-           (b->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
-           (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)) {
-               /* Application requested write-shutdown, or other end closed
-                * with empty buffer. We have to close our write side and
-                * inform the stream_interface.
-                */
-               b->cons->shutw(b->cons);
-       }
+       buf->flags &= ~BF_AUTO_CLOSE;
 }
 
 /* returns the maximum number of bytes writable at once in this buffer */
index 1d15c708779afdb9952e93afe887746efaa474ce..b758596069caf7a65c3f9dd0046f41d8b7337158 100644 (file)
@@ -71,7 +71,7 @@
 #define BF_EMPTY          0x001000  /* buffer is empty */
 #define BF_SHUTW          0x002000  /* consumer has already shut down */
 #define BF_SHUTW_NOW      0x004000  /* the consumer must shut down for writes ASAP */
-#define BF_WRITE_ENA      0x008000  /* consumer is allowed to forward all buffer contents */
+#define BF_AUTO_CLOSE     0x008000  /* producer can forward shutdown to other side */
 
 /* When either BF_SHUTR_NOW or BF_HIJACK is set, it is strictly forbidden for
  * the producer to alter the buffer contents. When BF_SHUTW_NOW is set, the
@@ -92,7 +92,7 @@
  *    1       0      closed: the consumer has closed its output channel.
  *    1       1      impossible
  *
- * The SHUTW_NOW flag should be set by the session processor when SHUTR and WRITE_ENA
+ * The SHUTW_NOW flag should be set by the session processor when SHUTR and AUTO_CLOSE
  * are both set. It may also be set by a hijacker at the end of data. And it may also
  * be set by the producer when it detects SHUTR while directly forwarding data to the
  * consumer.
 #define BF_READ_ATTACHED  0x100000  /* the read side is attached for the first time */
 #define BF_KERN_SPLICING  0x200000  /* kernel splicing desired for this buffer */
 #define BF_READ_DONTWAIT  0x400000  /* wake the task up after every read (eg: HTTP request) */
+#define BF_AUTO_CONNECT   0x800000  /* consumer may attempt to establish a new connection */
 
 /* Use these masks to clear the flags before going back to lower layers */
 #define BF_CLEAR_READ     (~(BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_ATTACHED))
 #define BF_MASK_ANALYSER        (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY)
 
 /* Mask for static flags which are not events, but might change during processing */
-#define BF_MASK_STATIC          (BF_EMPTY|BF_FULL|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW)
+#define BF_MASK_STATIC          (BF_EMPTY|BF_FULL|BF_HIJACK|BF_AUTO_CLOSE|BF_AUTO_CONNECT|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW)
 
 
 /* Analysers (buffer->analysers).
index 312d896823e1d417fb60b7b26896716e54ed32e0..76c91c919299cd8ce3ebbd89dd766bfd244db7f3 100644 (file)
@@ -403,8 +403,10 @@ int event_accept(int fd) {
                s->req->analysers = l->analysers;
 
                /* note: this should not happen anymore since there's always at least the switching rules */
-               if (!s->req->analysers)
-                       buffer_write_ena(s->req);  /* don't wait to establish connection */
+               if (!s->req->analysers) {
+                       buffer_auto_connect(s->req);  /* don't wait to establish connection */
+                       buffer_auto_close(s->req);    /* let the producer forward close requests */
+               }
 
                s->req->rto = s->fe->timeout.client;
                s->req->wto = s->be->timeout.server;
index 24aab05946e9425dc20975dd022c20e414795849..86e73a95fad393ede0ba5c4ffa2b4bbfb0657ecc 100644 (file)
@@ -316,7 +316,7 @@ int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit)
                memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
                s->data_source = DATA_SRC_STATS;
                s->ana_state = STATS_ST_REQ;
-               buffer_write_dis(s->req);
+               buffer_dont_connect(s->req);
                /* fall through */
 
        case STATS_ST_REQ:
index 1ecdc0b9155a3429a1f02b688601200d10d9695d..a159769b6cf04184701ff7aba8fd31487a9d3112 100644 (file)
@@ -526,7 +526,7 @@ static void http_server_error(struct session *t, struct stream_interface *si,
 {
        buffer_erase(si->ob);
        buffer_erase(si->ib);
-       buffer_write_ena(si->ib);
+       buffer_auto_close(si->ib);
        if (status > 0 && msg) {
                t->txn.status = status;
                buffer_write(si->ib, msg->str, msg->len);
@@ -1885,7 +1885,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
                        return 0;
                }
 
-               buffer_write_dis(req);
+               buffer_dont_connect(req);
                req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */
 
                /* just set the request timeout once at the beginning of the request */
@@ -2036,7 +2036,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
 
        if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
                /* we need more data */
-               buffer_write_dis(req);
+               buffer_dont_connect(req);
                return 0;
        }
 
@@ -2094,7 +2094,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
                        /* wipe the request out so that we can drop the connection early
                         * if the client closes first.
                         */
-                       buffer_write_dis(req);
+                       buffer_dont_connect(req);
                        req->analysers = 0; /* remove switching rules etc... */
                        req->analysers |= AN_REQ_HTTP_TARPIT;
                        req->analyse_exp = tick_add_ifset(now_ms,  s->be->timeout.tarpit);
@@ -2321,7 +2321,7 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit)
 
        if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
                /* we need more data */
-               buffer_write_dis(req);
+               buffer_dont_connect(req);
                return 0;
        }
 
@@ -2549,7 +2549,7 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit)
                        ctx.idx = 0;
                        http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx);
                        if (ctx.idx && ctx.vlen >= 7 && strncasecmp(ctx.line+ctx.val, "chunked", 7) == 0) {
-                               buffer_write_dis(req);
+                               buffer_dont_connect(req);
                                req->analysers |= AN_REQ_HTTP_BODY;
                        }
                        else {
@@ -2572,7 +2572,7 @@ int http_process_request(struct session *s, struct buffer *req, int an_bit)
                                        hint = s->be->url_param_post_limit;
                                /* now do we really need to buffer more data? */
                                if (len < hint) {
-                                       buffer_write_dis(req);
+                                       buffer_dont_connect(req);
                                        req->analysers |= AN_REQ_HTTP_BODY;
                                }
                                /* else... There are no body bytes to wait for */
@@ -2626,7 +2626,7 @@ int http_process_tarpit(struct session *s, struct buffer *req, int an_bit)
         * timeout. We just have to check that the client is still
         * there and that the timeout has not expired.
         */
-       buffer_write_dis(req);
+       buffer_dont_connect(req);
        if ((req->flags & (BF_SHUTR|BF_READ_ERROR)) == 0 &&
            !tick_is_expired(req->analyse_exp, now_ms))
                return 0;
@@ -2669,7 +2669,7 @@ int http_process_request_body(struct session *s, struct buffer *req, int an_bit)
 
        if (unlikely(msg->msg_state != HTTP_MSG_BODY)) {
                /* we need more data */
-               buffer_write_dis(req);
+               buffer_dont_connect(req);
                return 0;
        }
 
@@ -2738,7 +2738,7 @@ int http_process_request_body(struct session *s, struct buffer *req, int an_bit)
                 * request timeout once at the beginning of the
                 * request.
                 */
-               buffer_write_dis(req);
+               buffer_dont_connect(req);
                if (!tick_isset(req->analyse_exp))
                        req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.httpreq);
                return 0;
@@ -2921,14 +2921,7 @@ int process_response(struct session *t)
                                return 0;
                        }
 
-                       /* We disable sending only if we have nothing to send.
-                        * Note that we should not need to do this since the
-                        * buffer is protected by the fact that at least one
-                        * analyser remains. But close events could still be
-                        * forwarded if we don't disable the BF_WRITE_ENA flag.
-                        */
-                       if (!rep->send_max)
-                               buffer_write_dis(rep);
+                       buffer_dont_close(rep);
                        return 0;
                }
 
@@ -4635,7 +4628,7 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend)
        /* The request is valid, the user is authenticated. Let's start sending
         * data.
         */
-       buffer_write_dis(t->req);
+       buffer_dont_connect(t->req);
        buffer_shutw_now(t->req);
        buffer_shutr_now(t->rep);
        t->logs.tv_request = now;
index 73a2ba6eb379296d6cbf19df9d8f03ee13381315..a03c80948ac461f662c0f9071689ff8cd65b1134 100644 (file)
@@ -668,7 +668,7 @@ int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
                if (rule->cond) {
                        ret = acl_exec_cond(rule->cond, s->fe, s, &s->txn, ACL_DIR_REQ | partial);
                        if (ret == ACL_PAT_MISS) {
-                               buffer_write_dis(req);
+                               buffer_dont_connect(req);
                                /* just set the request timeout once at the beginning of the request */
                                if (!tick_isset(req->analyse_exp) && s->fe->tcp_req.inspect_delay)
                                        req->analyse_exp = tick_add_ifset(now_ms, s->fe->tcp_req.inspect_delay);
index 013be7f029b1a8bb4ad6718d43684f1e28738661..6c9390d118decd25e33352648210132fac706baf 100644 (file)
@@ -769,8 +769,9 @@ resync_stream_interface:
                if (s->req->prod->state >= SI_ST_EST) {
                        unsigned int last_ana = 0;
 
-                       /* it's up to the analysers to reset write_ena */
-                       buffer_write_ena(s->req);
+                       /* it's up to the analysers to stop new connections */
+                       buffer_auto_connect(s->req);
+                       buffer_auto_close(s->req);
 
                        /* We will call all analysers for which a bit is set in
                         * s->req->analysers, following the bit order from LSB
@@ -884,8 +885,8 @@ resync_stream_interface:
                unsigned int flags = s->rep->flags;
 
                if (s->rep->prod->state >= SI_ST_EST) {
-                       /* it's up to the analysers to reset write_ena */
-                       buffer_write_ena(s->rep);
+                       /* it's up to the analysers to reset auto_close */
+                       buffer_auto_close(s->rep);
                        if (s->rep->analysers)
                                process_response(s);
                }
@@ -950,6 +951,8 @@ resync_stream_interface:
                 * attached to it. If any data are left in, we'll permit them to
                 * move.
                 */
+               buffer_auto_connect(s->req);
+               buffer_auto_close(s->req);
                buffer_flush(s->req);
 
                /* If the producer is still connected, we'll schedule large blocks
@@ -980,18 +983,15 @@ resync_stream_interface:
         * Now forward all shutdown requests between both sides of the buffer
         */
 
-       /* first, let's check if the request buffer needs to shutdown(write) */
-       if (unlikely((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
-                    (BF_WRITE_ENA|BF_SHUTR)))
-               buffer_shutw_now(s->req);
-       else if ((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ENA)) == (BF_WRITE_ENA) &&
-                (s->req->cons->state == SI_ST_EST) &&
-                s->be->options & PR_O_FORCE_CLO &&
-                s->rep->flags & BF_READ_ACTIVITY) {
-               /* We want to force the connection to the server to close,
-                * and the server has begun to respond. That's the right
-                * time.
-                */
+       /* first, let's check if the request buffer needs to shutdown(write), which may
+        * happen either because the input is closed or because we want to force a close
+        * once the server has begun to respond.
+        */
+       if ((s->req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_AUTO_CLOSE)) == BF_AUTO_CLOSE) {
+               if (unlikely((s->req->flags & BF_SHUTR) ||
+                            ((s->req->cons->state == SI_ST_EST) &&
+                             (s->be->options & PR_O_FORCE_CLO) &&
+                             (s->rep->flags & BF_READ_ACTIVITY))))
                buffer_shutw_now(s->req);
        }
 
@@ -1008,17 +1008,23 @@ resync_stream_interface:
        if (unlikely((s->req->flags & (BF_SHUTR|BF_SHUTR_NOW)) == BF_SHUTR_NOW))
                s->req->prod->shutr(s->req->prod);
 
-       /* it's possible that an upper layer has requested a connection setup or abort */
-       if (s->req->cons->state == SI_ST_INI &&
-           (s->req->flags & (BF_WRITE_ENA|BF_SHUTW|BF_SHUTW_NOW))) {
-               if ((s->req->flags & (BF_WRITE_ENA|BF_SHUTW|BF_SHUTW_NOW)) == BF_WRITE_ENA) {
-                       /* If we have a ->connect method, we need to perform a connection request,
-                        * otherwise we immediately switch to the connected state.
-                        */
-                       if (s->req->cons->connect)
-                               s->req->cons->state = SI_ST_REQ; /* new connection requested */
-                       else
-                               s->req->cons->state = SI_ST_EST; /* connection established */
+       /* it's possible that an upper layer has requested a connection setup or abort.
+        * There are 2 situations where we decide to establish a new connection :
+        *  - there are data scheduled for emission in the buffer
+        *  - the BF_AUTO_CONNECT flag is set (active connection)
+        */
+       if (s->req->cons->state == SI_ST_INI) {
+               if (!(s->req->flags & (BF_SHUTW|BF_SHUTW_NOW))) {
+                       if ((s->req->flags & BF_AUTO_CONNECT) ||
+                           (s->req->send_max || s->req->pipe)) {
+                               /* If we have a ->connect method, we need to perform a connection request,
+                                * otherwise we immediately switch to the connected state.
+                                */
+                               if (s->req->cons->connect)
+                                       s->req->cons->state = SI_ST_REQ; /* new connection requested */
+                               else
+                                       s->req->cons->state = SI_ST_EST; /* connection established */
+                       }
                }
                else
                        s->req->cons->state = SI_ST_CLO; /* shutw+ini = abort */
@@ -1065,6 +1071,7 @@ resync_stream_interface:
                 * attached to it. If any data are left in, we'll permit them to
                 * move.
                 */
+               buffer_auto_close(s->rep);
                buffer_flush(s->rep);
 
                /* If the producer is still connected, we'll schedule large blocks
@@ -1100,8 +1107,8 @@ resync_stream_interface:
         */
 
        /* first, let's check if the response buffer needs to shutdown(write) */
-       if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
-                    (BF_WRITE_ENA|BF_SHUTR)))
+       if (unlikely((s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_AUTO_CLOSE|BF_SHUTR)) ==
+                    (BF_AUTO_CLOSE|BF_SHUTR)))
                buffer_shutw_now(s->rep);
 
        /* shutdown(write) pending */
@@ -1182,7 +1189,7 @@ resync_stream_interface:
                 * request timeout is set and the server has not yet sent a response.
                 */
 
-               if ((s->rep->flags & (BF_WRITE_ENA|BF_SHUTR)) == 0 &&
+               if ((s->rep->flags & (BF_AUTO_CLOSE|BF_SHUTR)) == 0 &&
                    (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
                        s->req->flags |= BF_READ_NOEXP;
                        s->req->rex = TICK_ETERNITY;
index d8ee9e69efcbf93e55dfebc45a136f0c2d765f89..2b14d2d449303a69136c173b12bae7b64360d635 100644 (file)
@@ -89,7 +89,7 @@ void stream_int_retnclose(struct stream_interface *si, const struct chunk *msg)
                buffer_write(si->ob, msg->str, msg->len);
 
        si->ob->wex = tick_add_ifset(now_ms, si->ob->wto);
-       buffer_write_ena(si->ob);
+       buffer_auto_close(si->ob);
 }
 
 /*
index 715259b2727610f2a3a3b1c1051265e2949a14d3..0ec83cd7f29787df1595309fea882c0edc739d98 100644 (file)
@@ -502,7 +502,7 @@ int stream_sock_read(int fd) {
        /* we received a shutdown */
        fdtab[fd].ev &= ~FD_POLL_HUP;
        b->flags |= BF_READ_NULL;
-       if (b->flags & BF_WRITE_ENA)
+       if (b->flags & BF_AUTO_CLOSE)
                buffer_shutw_now(b);
        stream_sock_shutr(si);
        goto out_wakeup;
@@ -601,7 +601,7 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
                        unsigned int send_flag = MSG_DONTWAIT | MSG_NOSIGNAL;
 
                        if (MSG_MORE &&
-                           (((b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_WRITE_ENA)) == (BF_WRITE_ENA|BF_SHUTW_NOW) &&
+                           (((b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK)) == BF_SHUTW_NOW &&
                              (max == b->l)) ||
                             (max != b->l && max != b->send_max))
                            && (fdtab[si->fd].flags & FD_FL_TCP)) {
@@ -741,8 +741,7 @@ int stream_sock_write(int fd)
                 * send_max limit was reached. Maybe we just wrote the last
                 * chunk and need to close.
                 */
-               if (((b->flags & (BF_SHUTW|BF_HIJACK|BF_WRITE_ENA|BF_SHUTW_NOW)) ==
-                    (BF_WRITE_ENA|BF_SHUTW_NOW)) &&
+               if (((b->flags & (BF_SHUTW|BF_HIJACK|BF_SHUTW_NOW)) == BF_SHUTW_NOW) &&
                    (si->state == SI_ST_EST)) {
                        stream_sock_shutw(si);
                        goto out_wakeup;
@@ -926,11 +925,9 @@ void stream_sock_data_finish(struct stream_interface *si)
        /* Check if we need to close the write side */
        if (!(ob->flags & BF_SHUTW)) {
                /* Write not closed, update FD status and timeout for writes */
-               if ((ob->send_max == 0 && !ob->pipe) ||
-                   (ob->flags & BF_EMPTY) ||
-                   (ob->flags & (BF_HIJACK|BF_WRITE_ENA)) == 0) {
+               if ((ob->send_max == 0 && !ob->pipe) || (ob->flags & BF_EMPTY)) {
                        /* stop writing */
-                       if ((ob->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA)) == (BF_EMPTY|BF_WRITE_ENA))
+                       if ((ob->flags & (BF_EMPTY|BF_HIJACK)) == BF_EMPTY)
                                si->flags |= SI_FL_WAIT_DATA;
                        EV_FD_COND_C(fd, DIR_WR);
                        ob->wex = TICK_ETERNITY;
@@ -1014,8 +1011,7 @@ void stream_sock_chk_snd(struct stream_interface *si)
 
        if (!(si->flags & SI_FL_WAIT_DATA) ||        /* not waiting for data */
            (fdtab[si->fd].ev & FD_POLL_OUT) ||      /* we'll be called anyway */
-           !(ob->send_max || ob->pipe) ||           /* called with nothing to send ! */
-           !(ob->flags & (BF_HIJACK|BF_WRITE_ENA))) /* we may not write */
+           !(ob->send_max || ob->pipe))             /* called with nothing to send ! */
                return;
 
        retval = stream_sock_write_loop(si, ob);
@@ -1045,14 +1041,14 @@ void stream_sock_chk_snd(struct stream_interface *si)
                 * send_max limit was reached. Maybe we just wrote the last
                 * chunk and need to close.
                 */
-               if (((ob->flags & (BF_SHUTW|BF_HIJACK|BF_WRITE_ENA|BF_SHUTW_NOW)) ==
-                    (BF_WRITE_ENA|BF_SHUTW_NOW)) &&
+               if (((ob->flags & (BF_SHUTW|BF_HIJACK|BF_AUTO_CLOSE|BF_SHUTW_NOW)) ==
+                    (BF_AUTO_CLOSE|BF_SHUTW_NOW)) &&
                    (si->state == SI_ST_EST)) {
                        stream_sock_shutw(si);
                        goto out_wakeup;
                }
 
-               if ((ob->flags & (BF_SHUTW|BF_EMPTY|BF_HIJACK|BF_WRITE_ENA)) == (BF_EMPTY|BF_WRITE_ENA))
+               if ((ob->flags & (BF_SHUTW|BF_EMPTY|BF_HIJACK)) == BF_EMPTY)
                        si->flags |= SI_FL_WAIT_DATA;
                ob->wex = TICK_ETERNITY;
        }