mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-25 15:51:24 +02:00
MINOR: h2: implement PING frames
Now we can detect and properly parse PING frames as well as emit a response containing the same payload.
This commit is contained in:
parent
7e98c057ff
commit
cf68c787ae
73
src/mux_h2.c
73
src/mux_h2.c
@ -753,6 +753,71 @@ static int h2c_send_goaway_error(struct h2c *h2c, struct h2s *h2s)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* processes a PING frame and schedules an ACK if needed. The caller must pass
|
||||||
|
* the pointer to the payload in <payload>. Returns > 0 on success or zero on
|
||||||
|
* missing data. It may return an error in h2c.
|
||||||
|
*/
|
||||||
|
static int h2c_handle_ping(struct h2c *h2c)
|
||||||
|
{
|
||||||
|
/* frame length must be exactly 8 */
|
||||||
|
if (h2c->dfl != 8) {
|
||||||
|
h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* schedule a response */
|
||||||
|
if (!(h2c->dft & H2_F_PING_ACK))
|
||||||
|
h2c->st0 = H2_CS_FRAME_A;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to send an ACK for a ping frame on the connection. Returns > 0 on
|
||||||
|
* success, 0 on missing data or one of the h2_status values.
|
||||||
|
*/
|
||||||
|
static int h2c_ack_ping(struct h2c *h2c)
|
||||||
|
{
|
||||||
|
struct buffer *res;
|
||||||
|
char str[17];
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (h2c->dbuf->i < 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (h2c_mux_busy(h2c, NULL)) {
|
||||||
|
h2c->flags |= H2_CF_DEM_MBUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = h2_get_mbuf(h2c);
|
||||||
|
if (!res) {
|
||||||
|
h2c->flags |= H2_CF_MUX_MALLOC;
|
||||||
|
h2c->flags |= H2_CF_DEM_MROOM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(str,
|
||||||
|
"\x00\x00\x08" /* length : 8 (same payload) */
|
||||||
|
"\x06" "\x01" /* type : 6, flags : ACK */
|
||||||
|
"\x00\x00\x00\x00" /* stream ID */, 9);
|
||||||
|
|
||||||
|
/* copy the original payload */
|
||||||
|
h2_get_buf_bytes(str + 9, 8, h2c->dbuf, 0);
|
||||||
|
|
||||||
|
ret = bo_istput(res, ist2(str, 17));
|
||||||
|
if (unlikely(ret <= 0)) {
|
||||||
|
if (!ret) {
|
||||||
|
h2c->flags |= H2_CF_MUX_MFULL;
|
||||||
|
h2c->flags |= H2_CF_DEM_MROOM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
h2c_error(h2c, H2_ERR_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* process Rx frames to be demultiplexed */
|
/* process Rx frames to be demultiplexed */
|
||||||
static void h2_process_demux(struct h2c *h2c)
|
static void h2_process_demux(struct h2c *h2c)
|
||||||
{
|
{
|
||||||
@ -838,6 +903,14 @@ static void h2_process_demux(struct h2c *h2c)
|
|||||||
/* Only H2_CS_FRAME_P and H2_CS_FRAME_A here */
|
/* Only H2_CS_FRAME_P and H2_CS_FRAME_A here */
|
||||||
|
|
||||||
switch (h2c->dft) {
|
switch (h2c->dft) {
|
||||||
|
case H2_FT_PING:
|
||||||
|
if (h2c->st0 == H2_CS_FRAME_P)
|
||||||
|
ret = h2c_handle_ping(h2c);
|
||||||
|
|
||||||
|
if (h2c->st0 == H2_CS_FRAME_A)
|
||||||
|
ret = h2c_ack_ping(h2c);
|
||||||
|
break;
|
||||||
|
|
||||||
/* FIXME: implement all supported frame types here */
|
/* FIXME: implement all supported frame types here */
|
||||||
default:
|
default:
|
||||||
/* drop frames that we ignore. They may be larger than
|
/* drop frames that we ignore. They may be larger than
|
||||||
|
Loading…
x
Reference in New Issue
Block a user