MINOR: h2: implement PING frames
Now we can detect and properly parse PING frames as well as emit a
response containing the same payload.
diff --git a/src/mux_h2.c b/src/mux_h2.c
index f7319d0..0986baa 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -753,6 +753,71 @@
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 */
static void h2_process_demux(struct h2c *h2c)
{
@@ -838,6 +903,14 @@
/* Only H2_CS_FRAME_P and H2_CS_FRAME_A here */
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 */
default:
/* drop frames that we ignore. They may be larger than