BUG/MEDIUM: channel: incorrect polling condition may delay event delivery

The condition to poll for receive as implemented in channel_may_recv()
is still incorrect. If buf->o is null and buf->i is slightly larger than
chn->to_forward and at least as large as buf->size - maxrewrite, then
reading will be disabled. It may slightly delay some data delivery by
having first to forward pending bytes, but may also cause some random
issues with analysers that wait for some data before starting to forward
what they correctly parsed. For instance, a body analyser may be prevented
from seeing the data that only fits in the reserve.

This bug may also prevent an applet's chk_rcv() function from being called
when part of a buffer is released. It is possible (though not verified)
that this participated to some peers frozen session issues some people
have been facing.

This fix should be backported to 1.6 and 1.5 to ensure better coherency
with channel_recv_limit().
(cherry picked from commit 93dc478a04485272c723c0e510450d00b3c345c3)
(cherry picked from commit 83732fc353756b8e3eb08dca7e1f377755dc92de)
[wt: in 1.5 channel_full returns the opposite from 1.6's channel_may_recv]
diff --git a/include/proto/channel.h b/include/proto/channel.h
index 3d8a1b7..739d04c 100644
--- a/include/proto/channel.h
+++ b/include/proto/channel.h
@@ -147,21 +147,14 @@
 	if (!rem)
 		return 1; /* buffer already full */
 
-	if (rem <= global.tune.maxrewrite && !channel_may_send(chn))
-		return 1;
+	if (rem > global.tune.maxrewrite)
+		return 0;
 
-	/* now we know there's some room left, verify if we're touching
-	 * the reserve with some permanent input data.
-	 */
-	if (chn->to_forward >= chn->buf->i ||
-	    (CHN_INFINITE_FORWARD < MAX_RANGE(typeof(chn->buf->i)) && // just there to ensure gcc
-	     chn->to_forward == CHN_INFINITE_FORWARD))                // avoids the useless second
-		return 0;                                             // test whenever possible
+	if (!channel_may_send(chn))
+		return 1;
 
-	rem -= global.tune.maxrewrite;
-	rem += chn->buf->o;
-	rem += chn->to_forward;
-	return rem <= 0;
+	rem = chn->buf->i + global.tune.maxrewrite - chn->buf->size;
+	return rem >= 0 && (unsigned int)rem >= chn->to_forward;
 }
 
 /* Returns true if the channel's input is already closed */