BUG/MEDIUM: stream-int: Don't rely on CF_WRITE_PARTIAL to unblock opposite si

In the function stream_int_notify(), when the opposite stream-interface is
blocked because there is no more room into the input buffer, if the flag
CF_WRITE_PARTIAL is set on this buffer, it is unblocked. It is a way to unblock
the reads on the other side because some data was sent.

But it is a problem during the fast-forwarding because only the stream is able
to remove the flag CF_WRITE_PARTIAL. So it is possible to have this flag because
of a previous send while the input buffer of the opposite stream-interface is
now full. In such case, the opposite stream-interface will be woken up for
nothing because its input buffer is full. If the same happens on the opposite
side, we will have a loop consumming all the CPU.

To fix the bug, the opposite side is now only notify if there is some available
room in its input buffer in the function si_cs_send(), so only if some data was
sent.

This patch must be backported to 2.0 and 1.9.

(cherry picked from commit 037b3ebd3502e9eb7bbe7e56187ce1f929b4a02e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/include/proto/channel.h b/include/proto/channel.h
index 5e5d822..4872aa3 100644
--- a/include/proto/channel.h
+++ b/include/proto/channel.h
@@ -950,6 +950,7 @@
 
 	/* notify that some data was written to the SI from the buffer */
 	chn->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
+	chn_prod(chn)->flags &= ~SI_FL_RXBLK_ROOM; // si_rx_room_rdy()
 }
 
 /* HTX version of co_skip(). This function skips at most <len> bytes from the
@@ -967,6 +968,7 @@
 
 		/* notify that some data was written to the SI from the buffer */
 		chn->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
+		chn_prod(chn)->flags &= ~SI_FL_RXBLK_ROOM; // si_rx_room_rdy()
 	}
 }
 
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 481938f..9b9a8e9 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -482,10 +482,6 @@
 				ic->rex = tick_add_ifset(now_ms, ic->rto);
 	}
 
-	if ((sio->flags & SI_FL_RXBLK_ROOM) &&
-	    ((oc->flags & CF_WRITE_PARTIAL) || channel_is_empty(oc)))
-		si_rx_room_rdy(sio);
-
 	if (oc->flags & CF_DONT_READ)
 		si_rx_chan_blk(sio);
 	else
@@ -761,6 +757,8 @@
 		oc->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
 		if (si->state == SI_ST_CON)
 			si->state = SI_ST_RDY;
+
+		si_rx_room_rdy(si_opposite(si));
 	}
 
 	if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) {
@@ -920,8 +918,7 @@
 	if (cs->conn->flags & CO_FL_ERROR)
 		return;
 
-	if (si_cs_send(cs))
-		si_rx_room_rdy(si_opposite(si));
+	si_cs_send(cs);
 }
 
 /* Updates at once the channel flags, and timers of both stream interfaces of a