MINOR: quic: Re-arm the PTO timer upon datagram receipt

When block by the anti-amplification limit, this is the responsability of the
client to unblock it sending new datagrams. On the server side, even if not
well parsed, such datagrams must trigger the PTO timer arming.
diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h
index 8005b9b..c6e4354 100644
--- a/include/haproxy/xprt_quic-t.h
+++ b/include/haproxy/xprt_quic-t.h
@@ -615,8 +615,14 @@
 #define QUIC_FL_PKTNS_ACK_REQUIRED  (1UL << QUIC_FL_PKTNS_ACK_REQUIRED_BIT)
 
 /* Flags at connection level */
-#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1U << 0)
-#define QUIC_FL_POST_HANDSHAKE_FRAMES_BUILT     (1U << 1)
+#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT 0
+#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED \
+	(1U << QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT)
+
+#define QUIC_FL_CONN_IO_CB_WAKEUP_BIT               1
+#define QUIC_FL_CONN_IO_CB_WAKEUP (1U << QUIC_FL_CONN_IO_CB_WAKEUP_BIT)
+
+#define QUIC_FL_POST_HANDSHAKE_FRAMES_BUILT     (1U << 2)
 #define QUIC_FL_CONN_IMMEDIATE_CLOSE            (1U << 31)
 struct quic_conn {
 	/* The quic_conn instance is refcounted as it can be used by threads
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index b4dca75..93a24f0 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -3097,6 +3097,15 @@
 	qr = NULL;
 	st = HA_ATOMIC_LOAD(&qc->state);
 	TRACE_ENTER(QUIC_EV_CONN_HDSHK, qc, &st);
+	if (HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_IO_CB_WAKEUP) {
+		HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
+		/* The I/O handler has been woken up by the dgram listener
+		 * after the anti-amplification was reached.
+		 */
+		qc_set_timer(qc);
+		if (tick_isset(qc->timer) && tick_is_lt(qc->timer, now_ms))
+			task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
+	}
 	ssl_err = SSL_ERROR_NONE;
 	zero_rtt = st < QUIC_HS_ST_COMPLETE &&
 		(!MT_LIST_ISEMPTY(&qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA].rx.pqpkts) ||
@@ -4013,7 +4022,7 @@
 	struct quic_conn *qc, *qc_to_purge = NULL;
 	struct listener *l;
 	struct ssl_sock_ctx *conn_ctx;
-	int long_header = 0;
+	int long_header = 0, io_cb_wakeup = 0;
 	size_t b_cspace;
 	struct quic_enc_level *qel;
 
@@ -4218,6 +4227,17 @@
 	 */
 	if (!dgram_ctx->dcid.len) {
 		memcpy(dgram_ctx->dcid.data, pkt->dcid.data, pkt->dcid.len);
+		if (!quic_peer_validated_addr(qc) &&
+		    HA_ATOMIC_LOAD(&qc->flags) & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
+			TRACE_PROTO("PTO timer must be armed after anti-amplication was reached",
+			            QUIC_EV_CONN_LPKT, qc);
+			/* Reset the anti-amplification bit. It will be set again
+			 * when sending the next packet if reached again.
+			 */
+			HA_ATOMIC_BTR(&qc->flags, QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED_BIT);
+			HA_ATOMIC_OR(&qc->flags, QUIC_FL_CONN_IO_CB_WAKEUP_BIT);
+			io_cb_wakeup = 1;
+		}
 	}
 	else if (memcmp(dgram_ctx->dcid.data, pkt->dcid.data, pkt->dcid.len)) {
 		TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc);
@@ -4279,6 +4299,14 @@
 	return pkt->len;
 
  err:
+	/* Wakeup the I/O handler callback if the PTO timer must be armed.
+	 * This cannot be done by this thread.
+	 */
+	if (io_cb_wakeup) {
+		conn_ctx = HA_ATOMIC_LOAD(&qc->xprt_ctx);
+		if (conn_ctx && conn_ctx->wait_event.tasklet)
+			tasklet_wakeup(conn_ctx->wait_event.tasklet);
+	}
 	/* If length not found, consume the entire datagram */
 	if (!pkt->len)
 		pkt->len = end - beg;