[MEDIUM] buffers: ensure buffer_shut* are properly called upon shutdowns

It is important that buffer states reflect the state of both sides so
that we can remove client and server state inter-dependencies.
diff --git a/src/proto_http.c b/src/proto_http.c
index 9ab5a80..89f32ef 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -545,6 +545,8 @@
 			int status, const struct chunk *msg)
 {
 	t->srv_state = SV_STCLOSE;
+	buffer_shutw_done(t->req);
+	buffer_shutr_done(t->rep);
 	if (status > 0 && msg) {
 		t->txn.status = status;
 		if (t->fe->mode == PR_MODE_HTTP)
@@ -1558,7 +1560,8 @@
 		 */
 		if (unlikely(req->flags & (BF_READ_ERROR | BF_READ_NULL))) {
 			t->inspect_exp = TICK_ETERNITY;
-			buffer_shutr(req);
+			buffer_shutr_done(req);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			t->fe->failed_req++;
@@ -1572,7 +1575,8 @@
 		/* Abort if client read timeout has expired */
 		else if (unlikely(tick_is_expired(req->rex, now_ms))) {
 			t->inspect_exp = TICK_ETERNITY;
-			buffer_shutr(req);
+			buffer_shutr_done(req);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			t->fe->failed_req++;
@@ -1615,7 +1619,8 @@
 			if (ret) {
 				/* we have a matching rule. */
 				if (rule->action == TCP_ACT_REJECT) {
-					buffer_shutr(req);
+					buffer_shutr_done(req);
+					buffer_shutw_done(rep);
 					fd_delete(t->cli_fd);
 					t->cli_state = CL_STCLOSE;
 					t->fe->failed_req++;
@@ -1722,7 +1727,8 @@
 			/* 2: have we encountered a read error or a close ? */
 			else if (unlikely(req->flags & (BF_READ_ERROR | BF_READ_NULL))) {
 				/* read error, or last read : give up. */
-				buffer_shutr(req);
+				buffer_shutr_done(req);
+				buffer_shutw_done(rep);
 				fd_delete(t->cli_fd);
 				t->cli_state = CL_STCLOSE;
 				t->fe->failed_req++;
@@ -2418,8 +2424,8 @@
 		 */
 		/* read or write error */
 		if (rep->flags & BF_WRITE_ERROR || req->flags & BF_READ_ERROR) {
-			buffer_shutr(req);
-			buffer_shutw(rep);
+			buffer_shutr_done(req);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2444,7 +2450,7 @@
 		/* last server read and buffer empty */
 		else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			shutdown(t->cli_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -2474,7 +2480,7 @@
 		/* write timeout */
 		else if (tick_is_expired(rep->wex, now_ms)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			shutdown(t->cli_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -2539,7 +2545,7 @@
 	}
 	else if (c == CL_STSHUTR) {
 		if (rep->flags & BF_WRITE_ERROR) {
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2556,13 +2562,13 @@
 		}
 		else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)
 			 && !(t->flags & SN_SELF_GEN)) {
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
 		else if (tick_is_expired(rep->wex, now_ms)) {
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2581,7 +2587,7 @@
 		if (t->flags & SN_SELF_GEN) {
 			produce_content(t);
 			if (rep->l == 0) {
-				buffer_shutw(rep);
+				buffer_shutw_done(rep);
 				fd_delete(t->cli_fd);
 				t->cli_state = CL_STCLOSE;
 				return 1;
@@ -2605,7 +2611,7 @@
 	}
 	else if (c == CL_STSHUTW) {
 		if (req->flags & BF_READ_ERROR) {
-			buffer_shutr(req);
+			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -2621,13 +2627,13 @@
 			return 1;
 		}
 		else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
-			buffer_shutr(req);
+			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
 		else if (tick_is_expired(req->rex, now_ms)) {
-			buffer_shutr(req);
+			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -3074,8 +3080,8 @@
 			if (unlikely((msg->msg_state == HTTP_MSG_ERROR) ||
 			             (req->flags & BF_WRITE_ERROR) ||
 			             (rep->flags & BF_READ_ERROR))) {
-				buffer_shutr(rep);
-				buffer_shutw(req);
+				buffer_shutr_done(rep);
+				buffer_shutw_done(req);
 				fd_delete(t->srv_fd);
 				if (t->srv) {
 					t->srv->cur_sess--;
@@ -3107,7 +3113,7 @@
 			                  c == CL_STSHUTW || c == CL_STCLOSE ||
 			                  rep->l >= rep->rlim - rep->data)) {
 				EV_FD_CLR(t->srv_fd, DIR_RD);
-				buffer_shutr(rep);
+				buffer_shutr_done(rep);
 				t->srv_state = SV_STSHUTR;
 				//fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
 				return 1;
@@ -3116,8 +3122,8 @@
 			/* read timeout : return a 504 to the client. */
 			else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_RD) &&
 			                  tick_is_expired(rep->rex, now_ms))) {
-				buffer_shutr(rep);
-				buffer_shutw(req);
+				buffer_shutr_done(rep);
+				buffer_shutw_done(req);
 				fd_delete(t->srv_fd);
 				if (t->srv) {
 					t->srv->cur_sess--;
@@ -3147,11 +3153,13 @@
 			 * The side-effect is that if the client completely closes its
 			 * connection during SV_STHEADER, the connection to the server
 			 * is kept until a response comes back or the timeout is reached.
+			 * FIXME!!! this code can never be called because the condition is
+			 * caught earlier (CL_STCLOSE).
 			 */
 			else if (unlikely((/*c == CL_STSHUTR ||*/ c == CL_STCLOSE) &&
 			                  (req->l == 0))) {
 				EV_FD_CLR(t->srv_fd, DIR_WR);
-				buffer_shutw(req);
+				buffer_shutw_done(req);
 
 				/* We must ensure that the read part is still
 				 * alive when switching to shutw */
@@ -3171,7 +3179,7 @@
 			else if (unlikely(EV_FD_ISSET(t->srv_fd, DIR_WR) &&
 					  tick_is_expired(req->wex, now_ms))) {
 				EV_FD_CLR(t->srv_fd, DIR_WR);
-				buffer_shutw(req);
+				buffer_shutw_done(req);
 				shutdown(t->srv_fd, SHUT_WR);
 				/* We must ensure that the read part is still alive
 				 * when switching to shutw */
@@ -3294,8 +3302,8 @@
 					}
 					cur_proxy->failed_resp++;
 				return_srv_prx_502:
-					buffer_shutr(rep);
-					buffer_shutw(req);
+					buffer_shutr_done(rep);
+					buffer_shutw_done(req);
 					fd_delete(t->srv_fd);
 					t->srv_state = SV_STCLOSE;
 					txn->status = 502;
@@ -3499,7 +3507,7 @@
 		if ((req->l == 0) &&
 		    (c == CL_STSHUTR || c == CL_STCLOSE || t->be->options & PR_O_FORCE_CLO)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -3539,8 +3547,8 @@
 	else if (s == SV_STDATA) {
 		/* read or write error */
 		if (req->flags & BF_WRITE_ERROR || rep->flags & BF_READ_ERROR) {
-			buffer_shutr(rep);
-			buffer_shutw(req);
+			buffer_shutr_done(rep);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -3572,7 +3580,7 @@
 		/* end of client read and no more data to send */
 		else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			shutdown(t->srv_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -3596,7 +3604,7 @@
 		/* write timeout */
 		else if (tick_is_expired(req->wex, now_ms)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			shutdown(t->srv_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -3646,7 +3654,7 @@
 	else if (s == SV_STSHUTR) {
 		if (req->flags & BF_WRITE_ERROR) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -3670,7 +3678,7 @@
 		}
 		else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -3688,7 +3696,7 @@
 		}
 		else if (tick_is_expired(req->wex, now_ms)) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -3725,7 +3733,7 @@
 	else if (s == SV_STSHUTW) {
 		if (rep->flags & BF_READ_ERROR) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
-			buffer_shutr(rep);
+			buffer_shutr_done(rep);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -3749,7 +3757,7 @@
 		}
 		else if (rep->flags & BF_READ_NULL || c == CL_STSHUTW || c == CL_STCLOSE) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
-			buffer_shutr(rep);
+			buffer_shutr_done(rep);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -3767,7 +3775,7 @@
 		}
 		else if (tick_is_expired(rep->rex, now_ms)) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
-			buffer_shutr(rep);
+			buffer_shutr_done(rep);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index d00b499..8c89241 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -556,8 +556,8 @@
 		 */
 		/* read or write error */
 		if (rep->flags & BF_WRITE_ERROR || req->flags & BF_READ_ERROR) {
-			buffer_shutr(req);
-			buffer_shutw(rep);
+			buffer_shutr_done(req);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -582,7 +582,7 @@
 		/* last server read and buffer empty */
 		else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			shutdown(t->cli_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -612,7 +612,7 @@
 		/* write timeout */
 		else if (tick_is_expired(rep->wex, now_ms)) {
 			EV_FD_CLR(t->cli_fd, DIR_WR);
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			shutdown(t->cli_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -677,7 +677,7 @@
 	}
 	else if (c == CL_STSHUTR) {
 		if (rep->flags & BF_WRITE_ERROR) {
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -693,13 +693,13 @@
 			return 1;
 		}
 		else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) {
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
 		else if (tick_is_expired(rep->wex, now_ms)) {
-			buffer_shutw(rep);
+			buffer_shutw_done(rep);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -731,7 +731,7 @@
 	}
 	else if (c == CL_STSHUTW) {
 		if (req->flags & BF_READ_ERROR) {
-			buffer_shutr(req);
+			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -747,13 +747,13 @@
 			return 1;
 		}
 		else if (req->flags & BF_READ_NULL || s == SV_STSHUTW || s == SV_STCLOSE) {
-			buffer_shutr(req);
+			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			return 1;
 		}
 		else if (tick_is_expired(req->rex, now_ms)) {
-			buffer_shutr(req);
+			buffer_shutr_done(req);
 			fd_delete(t->cli_fd);
 			t->cli_state = CL_STCLOSE;
 			if (!(t->flags & SN_ERR_MASK))
@@ -975,8 +975,8 @@
 	else if (s == SV_STDATA) {
 		/* read or write error */
 		if (req->flags & BF_WRITE_ERROR || rep->flags & BF_READ_ERROR) {
-			buffer_shutr(rep);
-			buffer_shutw(req);
+			buffer_shutr_done(rep);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -1007,7 +1007,7 @@
 		/* end of client read and no more data to send */
 		else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			shutdown(t->srv_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -1031,7 +1031,7 @@
 		/* write timeout */
 		else if (tv_isle(&req->wex, &now)) {
 			EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			shutdown(t->srv_fd, SHUT_WR);
 			/* We must ensure that the read part is still alive when switching
 			 * to shutw */
@@ -1083,7 +1083,7 @@
 	else if (s == SV_STSHUTR) {
 		if (req->flags & BF_WRITE_ERROR) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -1106,7 +1106,7 @@
 		}
 		else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv)
 				t->srv->cur_sess--;
@@ -1122,7 +1122,7 @@
 		}
 		else if (tv_isle(&req->wex, &now)) {
 			//EV_FD_CLR(t->srv_fd, DIR_WR);
-			buffer_shutw(req);
+			buffer_shutw_done(req);
 			fd_delete(t->srv_fd);
 			if (t->srv)
 				t->srv->cur_sess--;
@@ -1158,7 +1158,7 @@
 	else if (s == SV_STSHUTW) {
 		if (rep->flags & BF_READ_ERROR) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
-			buffer_shutr(rep);
+			buffer_shutr_done(rep);
 			fd_delete(t->srv_fd);
 			if (t->srv) {
 				t->srv->cur_sess--;
@@ -1181,7 +1181,7 @@
 		}
 		else if (rep->flags & BF_READ_NULL || c == CL_STSHUTW || c == CL_STCLOSE) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
-			buffer_shutr(rep);
+			buffer_shutr_done(rep);
 			fd_delete(t->srv_fd);
 			if (t->srv)
 				t->srv->cur_sess--;
@@ -1197,7 +1197,7 @@
 		}
 		else if (tv_isle(&rep->rex, &now)) {
 			//EV_FD_CLR(t->srv_fd, DIR_RD);
-			buffer_shutr(rep);
+			buffer_shutr_done(rep);
 			fd_delete(t->srv_fd);
 			if (t->srv)
 				t->srv->cur_sess--;