mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-31 18:41:39 +00:00
MEDIUM: h2: start to implement the frames processing loop
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.
This commit is contained in:
parent
5160683fc7
commit
bc933930a7
77
src/mux_h2.c
77
src/mux_h2.c
@ -576,6 +576,19 @@ static struct h2s *h2c_stream_new(struct h2c *h2c, int id)
|
|||||||
return h2s;
|
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 */
|
/* 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)
|
if (buf->i == buf->size)
|
||||||
h2c->flags |= H2_CF_DEM_DFULL;
|
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 */
|
/* after streams have been processed, we should have made some room */
|
||||||
if (buf->i != buf->size)
|
if (buf->i != buf->size)
|
||||||
@ -631,8 +644,7 @@ static void h2_recv(struct connection *conn)
|
|||||||
static void h2_send(struct connection *conn)
|
static void h2_send(struct connection *conn)
|
||||||
{
|
{
|
||||||
struct h2c *h2c = conn->mux_ctx;
|
struct h2c *h2c = conn->mux_ctx;
|
||||||
|
int done;
|
||||||
/* FIXME: should we try to process pending streams here instead of doing it in ->wake ? */
|
|
||||||
|
|
||||||
if (conn->flags & CO_FL_ERROR)
|
if (conn->flags & CO_FL_ERROR)
|
||||||
return;
|
return;
|
||||||
@ -642,29 +654,50 @@ static void h2_send(struct connection *conn)
|
|||||||
return;
|
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) {
|
if (conn->flags & CO_FL_SOCK_WR_SH) {
|
||||||
/* output closed, nothing to send, clear the buffer to release it */
|
/* output closed, nothing to send, clear the buffer to release it */
|
||||||
h2c->mbuf->o = 0;
|
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 */
|
/* call the wake up function of all streams attached to the connection */
|
||||||
|
Loading…
Reference in New Issue
Block a user