]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: mux-quic: implement release mux operation
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 6 Dec 2021 15:03:47 +0000 (16:03 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 7 Dec 2021 14:44:45 +0000 (15:44 +0100)
Implement qc_release. This function is called by the upper layer on
connection close. For the moment, this only happens on client timeout.

This functions is used the free a qcs instance. If all bidirectional
streams are freed, the qcc instance and the connection are purged.

src/mux_quic.c

index 774612b8af3d7190cf784d184f31c76eb7a8edf3..bdf57e5690aecdc3afcd49a41577d0c097478320 100644 (file)
@@ -215,9 +215,75 @@ static int qc_init(struct connection *conn, struct proxy *prx,
        return -1;
 }
 
+/* detachs the QUIC stream from its QCC and releases it to the QCS pool. */
+static void qcs_destroy(struct qcs *qcs)
+{
+       fprintf(stderr, "%s: release stream %llu\n", __func__, qcs->by_id.key);
+
+       eb64_delete(&qcs->by_id);
+
+       b_free(&qcs->rx.buf);
+       b_free(&qcs->tx.buf);
+       b_free(&qcs->tx.xprt_buf);
+
+       --qcs->qcc->strms[qcs_id_type(qcs->by_id.key)].nb_streams;
+
+       pool_free(pool_head_qcs, qcs);
+}
+
+static inline int qcc_is_dead(const struct qcc *qcc)
+{
+       fprintf(stderr, "%s: %lu\n", __func__, qcc->strms[QCS_CLT_BIDI].nb_streams);
+
+       if (!qcc->strms[QCS_CLT_BIDI].nb_streams)
+               return 1;
+
+       return 0;
+}
+
+/* release function. This one should be called to free all resources allocated
+ * to the mux.
+ */
+static void qc_release(struct qcc *qcc)
+{
+       struct connection *conn = NULL;
+
+       if (qcc) {
+               /* The connection must be aattached to this mux to be released */
+               if (qcc->conn && qcc->conn->ctx == qcc)
+                       conn = qcc->conn;
+
+               if (qcc->wait_event.tasklet)
+                       tasklet_free(qcc->wait_event.tasklet);
+
+               pool_free(pool_head_qcc, qcc);
+       }
+
+       if (conn) {
+               conn->mux = NULL;
+               conn->ctx = NULL;
+
+               conn_stop_tracking(conn);
+               conn_full_close(conn);
+               if (conn->destroy_cb)
+                       conn->destroy_cb(conn);
+               conn_free(conn);
+       }
+}
+
 static void qc_detach(struct conn_stream *cs)
 {
-       /* XXX TO DO XXX */
+       struct qcs *qcs = cs->ctx;
+       struct qcc *qcc = qcs->qcc;
+
+       fprintf(stderr, "%s: leaving with tx.buf.data=%lu, tx.xprt_buf.data=%lu\n",
+               __func__, b_data(&qcs->tx.buf), b_data(&qcs->tx.xprt_buf));
+
+       qcs_destroy(qcs);
+       if (qcc_is_dead(qcc)) {
+               qc_release(qcc);
+               return;
+       }
 }
 
 /* Called from the upper layer, to receive data */