]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: h2: start to implement the frames processing loop
authorWilly Tarreau <w@1wt.eu>
Mon, 9 Oct 2017 14:21:43 +0000 (16:21 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 17:16:18 +0000 (18:16 +0100)
The rcv_buf() callback now calls h2_process_demux() after an recv() call
leaving some data in the buffer, and the snd_buf() callback calls
h2_process_mux() to try to process pending data from streams.

src/mux_h2.c

index 9776deaa310ff10f55006f051b2e20c45d0925a4..08b6657098dc54209a94625e2b03b7b7a104e73c 100644 (file)
@@ -576,6 +576,19 @@ static struct h2s *h2c_stream_new(struct h2c *h2c, int id)
        return h2s;
 }
 
+/* process Rx frames to be demultiplexed */
+static void h2_process_demux(struct h2c *h2c)
+{
+}
+
+/* process Tx frames from streams to be multiplexed. Returns > 0 if it reached
+ * the end.
+ */
+static int h2_process_mux(struct h2c *h2c)
+{
+       return 1;
+}
+
 
 /*********************************************************/
 /* functions below are I/O callbacks from the connection */
@@ -619,7 +632,7 @@ static void h2_recv(struct connection *conn)
        if (buf->i == buf->size)
                h2c->flags |= H2_CF_DEM_DFULL;
 
-       /* FIXME: should we try to process streams here instead of doing it in ->wake ? */
+       h2_process_demux(h2c);
 
        /* after streams have been processed, we should have made some room */
        if (buf->i != buf->size)
@@ -631,8 +644,7 @@ static void h2_recv(struct connection *conn)
 static void h2_send(struct connection *conn)
 {
        struct h2c *h2c = conn->mux_ctx;
-
-       /* FIXME: should we try to process pending streams here instead of doing it in ->wake ? */
+       int done;
 
        if (conn->flags & CO_FL_ERROR)
                return;
@@ -642,29 +654,50 @@ static void h2_send(struct connection *conn)
                return;
        }
 
+       /* This loop is quite simple : it tries to fill as much as it can from
+        * pending streams into the existing buffer until it's reportedly full
+        * or the end of send requests is reached. Then it tries to send this
+        * buffer's contents out, marks it not full if at least one byte could
+        * be sent, and tries again.
+        *
+        * The snd_buf() function normally takes a "flags" argument which may
+        * be made of a combination of CO_SFL_MSG_MORE to indicate that more
+        * data immediately comes and CO_SFL_STREAMER to indicate that the
+        * connection is streaming lots of data (used to increase TLS record
+        * size at the expense of latency). The former can be sent any time
+        * there's a buffer full flag, as it indicates at least one stream
+        * attempted to send and failed so there are pending data. An
+        * alternative would be to set it as long as there's an active stream
+        * but that would be problematic for ACKs until we have an absolute
+        * guarantee that all waiters have at least one byte to send. The
+        * latter should possibly not be set for now.
+        */
+
+       done = 0;
+       while (!done) {
+               unsigned int flags = 0;
+
+               /* fill as much as we can into the current buffer */
+               while (((h2c->flags & (H2_CF_MUX_MFULL|H2_CF_MUX_MALLOC)) == 0) && !done)
+                       done = h2_process_mux(h2c);
+
+               if (conn->flags & CO_FL_ERROR)
+                       break;
+
+               if (h2c->flags & (H2_CF_MUX_MFULL | H2_CF_DEM_MBUSY | H2_CF_DEM_MROOM))
+                       flags |= CO_SFL_MSG_MORE;
+
+               if (conn->xprt->snd_buf(conn, h2c->mbuf, flags) <= 0)
+                       break;
+
+               /* wrote at least one byte, the buffer is not full anymore */
+               h2c->flags &= ~(H2_CF_MUX_MFULL | H2_CF_DEM_MROOM);
+       }
+
        if (conn->flags & CO_FL_SOCK_WR_SH) {
                /* output closed, nothing to send, clear the buffer to release it */
                h2c->mbuf->o = 0;
        }
-
-       /* pending response data, we need to try to send or subscribe to
-        * writes. The snd_buf() function takes a "flags" argument which
-        * may be made of a combination of CO_SFL_MSG_MORE to indicate
-        * that more data immediately comes and CO_SFL_STREAMER to
-        * indicate that the connection is streaming lots of data (used
-        * to increase TLS record size at the expense of latency). The
-        * former could be sent any time there's a buffer full flag, as
-        * it indicates at least one stream attempted to send and failed
-        * so there are pending data. And alternative would be to set it
-        * as long as there's an active stream but that would be
-        * problematic for ACKs. The latter should possibly not be set
-        * for now.
-        */
-       if (conn->xprt->snd_buf(conn, h2c->mbuf, 0) > 0)
-               h2c->flags &= ~(H2_CF_MUX_MFULL | H2_CF_DEM_MROOM);
-
-       if (conn->flags & CO_FL_ERROR)
-               return;
 }
 
 /* call the wake up function of all streams attached to the connection */