]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: create a timeout task
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 13 Jan 2022 15:28:06 +0000 (16:28 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 1 Feb 2022 14:19:35 +0000 (15:19 +0100)
This task will be used to schedule a timer when there is no activity on
the mux. The timeout is set via the "timeout client" from the
configuration file.

The timeout task process schedule the timeout only on specific
conditions. Currently, it's done if there is no opened bidirectional
stream.

For now this task is not used. This will be implemented in the following
commit.

include/haproxy/mux_quic-t.h
src/mux_quic.c

index 0a60868a06652d72832e113032fff1c930237001..f2b217fd179e381447b1fcfb6fe59ec31e32f04f 100644 (file)
@@ -54,6 +54,10 @@ struct qcc {
        struct wait_event wait_event;  /* To be used if we're waiting for I/Os */
        struct wait_event *subs;
 
+       /* haproxy timeout management */
+       struct task *task;
+       int timeout;
+
        const struct qcc_app_ops *app_ops;
        void *ctx; /* Application layer context */
 };
index 9efb2f232d114582a0b03de1ce3406ca40405d16..532304f311894eb65105a7ce497273459bb72cbb 100644 (file)
@@ -209,6 +209,19 @@ 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 && !qcc->task)
+               return 1;
+
+       return 0;
+}
+
+/* Return true if the mux timeout should be armed. */
+static inline int qcc_may_expire(struct qcc *qcc)
+{
+
+       /* Consider that the timeout must be set if no bidirectional streams
+        * are opened.
+        */
        if (!qcc->strms[QCS_CLT_BIDI].nb_streams)
                return 1;
 
@@ -387,6 +400,36 @@ static struct task *qc_io_cb(struct task *t, void *ctx, unsigned int status)
        return NULL;
 }
 
+static struct task *qc_timeout_task(struct task *t, void *ctx, unsigned int state)
+{
+       struct qcc *qcc = ctx;
+       int expired = tick_is_expired(t->expire, now_ms);
+
+       fprintf(stderr, "%s\n", __func__);
+
+       if (qcc) {
+               if (!expired) {
+                       fprintf(stderr, "%s: not expired\n", __func__);
+                       return t;
+               }
+
+               if (!qcc_may_expire(qcc)) {
+                       fprintf(stderr, "%s: cannot expire\n", __func__);
+                       t->expire = TICK_ETERNITY;
+                       return t;
+               }
+       }
+
+       fprintf(stderr, "%s: timeout\n", __func__);
+       task_destroy(t);
+       qcc->task = NULL;
+
+       if (qcc_is_dead(qcc))
+               qc_release(qcc);
+
+       return NULL;
+}
+
 static int qc_init(struct connection *conn, struct proxy *prx,
                    struct session *sess, struct buffer *input)
 {
@@ -445,12 +488,23 @@ static int qc_init(struct connection *conn, struct proxy *prx,
        qcc->wait_event.tasklet->process = qc_io_cb;
        qcc->wait_event.tasklet->context = qcc;
 
+       /* haproxy timeouts */
+       qcc->timeout = prx->timeout.client;
+       qcc->task = task_new_here();
+       if (!qcc->task)
+               goto fail_no_timeout_task;
+       qcc->task->process = qc_timeout_task;
+       qcc->task->context = qcc;
+       qcc->task->expire = tick_add(now_ms, qcc->timeout);
+
        HA_ATOMIC_STORE(&conn->qc->qcc, qcc);
        /* init read cycle */
        tasklet_wakeup(qcc->wait_event.tasklet);
 
        return 0;
 
+ fail_no_timeout_task:
+       tasklet_free(qcc->wait_event.tasklet);
  fail_no_tasklet:
        pool_free(pool_head_qcc, qcc);
  fail_no_qcc: