If is illegal to send data if the stream is already closed. The case is
properly handled when data are sent via snd_buf(), by draining the data. But
it was still possible to process these data via nego_ff().
So, in this patch, both for the H2 and QUIC multiplexers, the fast-forward
is disabled if the stream is closed and nothing is performed. Doing so, we
will automatically fall back on the regular sending path and be able to
drain data in snd_buf().
Thanks to Mike Walker for his investigation on the subject.
This patch should be backported as far as 3.0.
TRACE_ENTER(H2_EV_H2S_SEND|H2_EV_STRM_SEND, h2s->h2c->conn, h2s);
+ if (h2s->st >= H2_SS_HLOC) {
+ /* Cannot emit any new data if stream already closed. Data
+ * draining will be performed via snd_buf.
+ */
+ TRACE_DEVEL("stream already closed, disable FF", H2_EV_H2S_SEND, h2s->h2c->conn, h2s);
+ h2s->sd->iobuf.flags |= IOBUF_FL_NO_FF;
+ goto end;
+ }
+
/* If we were not just woken because we wanted to send but couldn't,
* and there's somebody else that is waiting to send, do nothing,
* we will subscribe later and be put at the end of the list
goto end;
}
+ if (qcs_is_close_local(qcs) || (qcs->flags & QC_SF_TO_RESET)) {
+ /* Cannot emit any new data if stream already closed. Data
+ * draining will be performed via snd_buf.
+ */
+ TRACE_DEVEL("stream already closed", QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
+ qcs->sd->iobuf.flags |= IOBUF_FL_NO_FF;
+ goto end;
+ }
+
if (LIST_INLIST(&qcs->el_buf)) {
TRACE_DEVEL("leaving on no buf avail", QMUX_EV_STRM_SEND, qcs->qcc->conn, qcs);
qcs->sd->iobuf.flags |= IOBUF_FL_FF_BLOCKED;