[OPTIM] http: set MSG_MORE on response when a pipelined request is pending

Many times we see a lot of short responses in HTTP (typically 304 on a
reload). It is a waste of network bandwidth to send that many small packets
when we know we can merge them. When we know that another HTTP request is
following a response, we set BF_EXPECT_MORE on the response buffer, which
will turn MSG_MORE on exactly once. That way, multiple short responses can
leave pipelined if their corresponding requests were also pipelined.
diff --git a/include/types/buffers.h b/include/types/buffers.h
index fd078fa..34189cd 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -112,6 +112,7 @@
 #define BF_AUTO_CONNECT   0x800000  /* consumer may attempt to establish a new connection */
 
 #define BF_DONT_READ     0x1000000  /* disable reading for now */
+#define BF_EXPECT_MORE   0x2000000  /* more data expected to be sent very soon (one-shoot) */
 
 /* 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))
diff --git a/src/proto_http.c b/src/proto_http.c
index d8dc711..5cc0f23 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3497,6 +3497,13 @@
 				if (s->be->options2 & PR_O2_INDEPSTR)
 					s->req->cons->flags |= SI_FL_INDEP_STR;
 
+				/* if the request buffer is not empty, it means we're
+				 * about to process another request, so send pending
+				 * data with MSG_MORE to merge TCP packets when possible.
+				 */
+				if (s->req->l)
+					s->rep->flags |= BF_EXPECT_MORE;
+
 				/* make ->lr point to the first non-forwarded byte */
 				s->req->lr = s->req->w + s->req->send_max;
 				if (s->req->lr >= s->req->data + s->req->size)
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 7e9dd2c..4a9434c 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -608,16 +608,20 @@
 		 * tests.
 		 */
 
-		if (MSG_NOSIGNAL) {
+		if (MSG_NOSIGNAL && MSG_MORE) {
 			unsigned int send_flag = MSG_DONTWAIT | MSG_NOSIGNAL;
 
-			if (MSG_MORE &&
-			    ((b->to_forward && b->to_forward != BUF_INFINITE_FORWARD) ||
+			if (((b->to_forward && b->to_forward != BUF_INFINITE_FORWARD) ||
 			     ((b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK)) == BF_SHUTW_NOW && (max == b->send_max)) ||
 			     (max != b->l && max != b->send_max))
 			    && (fdtab[si->fd].flags & FD_FL_TCP)) {
 				send_flag |= MSG_MORE;
 			}
+			else if (b->flags & BF_EXPECT_MORE) {
+				/* it was forced on the buffer, this flag is one-shoot */
+				b->flags &= ~BF_EXPECT_MORE;
+				send_flag |= MSG_MORE;
+			}
 
 			ret = send(si->fd, b->w, max, send_flag);
 		} else {