[MEDIUM] remove stream_sock_update_data()

Two new functions are used instead : buffer_check_{shutr,shutw}.
It is indeed more adequate to check for new closures only when the
buffer reports them.

Several remaining unclosed connections were detected after a test,
even before this patch, so a bug remains. To reproduce, try the
following during 30 seconds :

  inject30l4 -n 20000 -l -t 1000 -P 10 -o 4 -u 100 -s 100 -G 127.0.0.1:8000/
diff --git a/src/proto_http.c b/src/proto_http.c
index df905e2..f73964a 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1136,7 +1136,12 @@
 		if (s->rep->cons->state != SI_ST_CLO) {
 			if (((rqf_cli ^ s->req->flags) & BF_MASK_INTERFACE_I) ||
 			    ((rpf_cli ^ s->rep->flags) & BF_MASK_INTERFACE_O)) {
-				stream_sock_data_update(s->rep->cons->fd);
+
+				if (!(s->rep->flags & BF_SHUTW))
+					buffer_check_shutw(s->rep);
+				if (!(s->req->flags & BF_SHUTR))
+					buffer_check_shutr(s->req);
+
 				rqf_cli = s->req->flags;
 				rpf_cli = s->rep->flags;
 			}
@@ -1175,7 +1180,10 @@
 						buffer_shutw_now(s->req);
 					}
 
-					stream_sock_data_update(s->req->cons->fd);
+					if (!(s->req->flags & BF_SHUTW))
+						buffer_check_shutw(s->req);
+					if (!(s->rep->flags & BF_SHUTR))
+						buffer_check_shutr(s->rep);
 
 					/* When a server-side connection is released, we have to
 					 * count it and check for pending connections on this server.
diff --git a/src/stream_sock.c b/src/stream_sock.c
index a23d0fd..f7b8d9d 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -471,106 +471,55 @@
 /*
  * This function performs a shutdown-write on a stream interface in a connected or
  * init state (it does nothing for other states). It either shuts the write side
- * closes the file descriptor and marks itself as closed. No buffer flags are
+ * or closes the file descriptor and marks itself as closed. No buffer flags are
  * changed, it's up to the caller to adjust them. The sole purpose of this
  * function is to be called from the other stream interface to notify of a
  * close_read, or by itself upon a full write leading to an empty buffer.
- * It normally returns zero, unless it has completely closed the socket, in
- * which case it returns 1.
  */
-int stream_sock_shutw(struct stream_interface *si)
+void stream_sock_shutw(struct stream_interface *si)
 {
-	if (si->state != SI_ST_EST && si->state != SI_ST_CON)
-		return 0;
+	if (si->state != SI_ST_EST && si->state != SI_ST_CON) {
+		if (likely(si->state == SI_ST_INI))
+			si->state = SI_ST_CLO;
+		return;
+	}
 
 	if (si->ib->flags & BF_SHUTR) {
 		fd_delete(si->fd);
 		si->state = SI_ST_DIS;
-		return 1;
+		return;
 	}
 	EV_FD_CLR(si->fd, DIR_WR);
 	shutdown(si->fd, SHUT_WR);
-	return 0;
+	return;
 }
 
 /*
  * This function performs a shutdown-read on a stream interface in a connected or
- * init state (it does nothing for other states). It either shuts the read side or
- * closes the file descriptor and marks itself as closed. No buffer flags are
+ * init state (it does nothing for other states). It either shuts the read side
+ * or closes the file descriptor and marks itself as closed. No buffer flags are
  * changed, it's up to the caller to adjust them. The sole purpose of this
  * function is to be called from the other stream interface to notify of a
  * close_read, or by itself upon a full write leading to an empty buffer.
- * It normally returns zero, unless it has completely closed the socket, in
- * which case it returns 1.
  */
-int stream_sock_shutr(struct stream_interface *si)
+void stream_sock_shutr(struct stream_interface *si)
 {
-	if (si->state != SI_ST_EST && si->state != SI_ST_CON)
-		return 0;
+	if (si->state != SI_ST_EST && si->state != SI_ST_CON) {
+		if (likely(si->state == SI_ST_INI))
+			si->state = SI_ST_CLO;
+		return;
+	}
 
 	if (si->ob->flags & BF_SHUTW) {
 		fd_delete(si->fd);
 		si->state = SI_ST_DIS;
-		return 1;
+		return;
 	}
 	EV_FD_CLR(si->fd, DIR_RD);
-	return 0;
+	return;
 }
 
 /*
- * Manages a stream_sock connection during its data phase. The buffers are
- * examined for various cases of shutdown, then file descriptor and buffers'
- * flags are updated accordingly.
- */
-int stream_sock_data_update(int fd)
-{
-	struct buffer *ib = fdtab[fd].cb[DIR_RD].b;
-	struct buffer *ob = fdtab[fd].cb[DIR_WR].b;
-
-	DPRINTF(stderr,"[%u] %s: fd=%d owner=%p ib=%p, ob=%p, exp(r,w)=%u,%u ibf=%08x obf=%08x ibl=%d obl=%d si=%d\n",
-		now_ms, __FUNCTION__,
-		fd, fdtab[fd].owner,
-		ib, ob,
-		ib->rex, ob->wex,
-		ib->flags, ob->flags,
-		ib->l, ob->l, ob->cons->state);
-
-	/* Check if we need to close the read side */
-	if (!(ib->flags & BF_SHUTR)) {
-		/* Last read, forced read-shutdown, or other end closed */
-		if (ib->flags & (BF_SHUTR_NOW|BF_SHUTW)) {
-			//trace_term(t, TT_HTTP_SRV_10);
-			buffer_shutr(ib);
-			if (ob->flags & BF_SHUTW) {
-				fd_delete(fd);
-				ob->cons->state = SI_ST_DIS;
-				return 0;
-			}
-			EV_FD_CLR(fd, DIR_RD);
-		}
-	}
-
-	/* Check if we need to close the write side */
-	if (!(ob->flags & BF_SHUTW)) {
-		/* Forced write-shutdown or other end closed with empty buffer. */
-		if ((ob->flags & BF_SHUTW_NOW) ||
-		    (ob->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) == (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)) {
-			//trace_term(t, TT_HTTP_SRV_11);
-			buffer_shutw(ob);
-			if (ib->flags & BF_SHUTR) {
-				fd_delete(fd);
-				ob->cons->state = SI_ST_DIS;
-				return 0;
-			}
-			EV_FD_CLR(fd, DIR_WR);
-			shutdown(fd, SHUT_WR);
-		}
-	}
-	return 0; /* other cases change nothing */
-}
-
-
-/*
  * Updates a connected stream_sock file descriptor status and timeouts
  * according to the buffers' flags. It should only be called once after the
  * buffer flags have settled down, and before they are cleared. It doesn't