From 1d393228e09febd9e039d2fc6b247ba47d182fc6 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 17 Oct 2017 10:26:19 +0200 Subject: [PATCH] MEDIUM: h2: enable connection polling for send when a cs wants to emit A conn_stream indicates its intent to send by setting the WR_ENA flag and calling mux->update_poll(). There's no synchronous write so the only way to emit a response from a stream is to proceed this way. The sender h2s is then queued into the h2c's send_list if it was not yet queued. Once the connection is ready, it will enter its send() callback to visit writers, calling their data->send_cb() callback to complete the operation using mux->snd_buf(). Also we enable polling if the mux contains data and wasn't enabled. This may happen just after a response has been transmitted using chk_snd(). It likely is incomplete for now and should probably be refined. --- src/mux_h2.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/mux_h2.c b/src/mux_h2.c index 08cc574ef..f05c26939 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -938,6 +938,36 @@ static struct conn_stream *h2_attach(struct connection *conn) */ static void h2_update_poll(struct conn_stream *cs) { + struct h2s *h2s = cs->ctx; + + if (!h2s) + return; + + /* Note: the stream and stream-int code doesn't allow us to perform a + * synchronous send() here unfortunately, because this code is called + * as si_update() from the process_stream() context. This means that + * we have to queue the current cs and defer its processing after the + * connection's cs list is processed anyway. + */ + + if (cs->flags & CS_FL_DATA_WR_ENA) { + if (LIST_ISEMPTY(&h2s->list)) { + if (LIST_ISEMPTY(&h2s->h2c->send_list) && + !h2s->h2c->mbuf->o && // not yet subscribed + !(cs->conn->flags & CO_FL_SOCK_WR_SH)) + conn_xprt_want_send(cs->conn); + LIST_ADDQ(&h2s->h2c->send_list, &h2s->list); + } + } + else if (!LIST_ISEMPTY(&h2s->list)) { + LIST_DEL(&h2s->list); + LIST_INIT(&h2s->list); + h2s->flags &= ~(H2_SF_BLK_MBUSY | H2_SF_BLK_MROOM | H2_SF_BLK_MFCTL); + } + + /* this can happen from within si_chk_snd() */ + if (h2s->h2c->mbuf->o && !(cs->conn->flags & CO_FL_XPRT_WR_ENA)) + conn_xprt_want_send(cs->conn); } /*