]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/session2: support for various event types in session2_start_timeout
authorOto Šťáva <oto.stava@nic.cz>
Wed, 12 Oct 2022 11:18:49 +0000 (13:18 +0200)
committerOto Šťáva <oto.stava@nic.cz>
Thu, 26 Jan 2023 11:56:08 +0000 (12:56 +0100)
daemon/io.c
daemon/session2.c
daemon/session2.h
daemon/tls.c
daemon/worker.c

index 938da46437810b477708aadb006c5c7ec9c73d2e..2503c81da70e20a299c563c4cf88f90379c483c9 100644 (file)
@@ -568,7 +568,8 @@ static void _tcp_accept(uv_stream_t *master, int status, enum protolayer_grp grp
        uint64_t idle_in_timeout = the_network->tcp.in_idle_timeout;
        uint64_t timeout = KR_CONN_RTT_MAX / 2;
        session2_event(s, PROTOLAYER_EVENT_CONNECT, NULL);
-       session2_timer_start(s, timeout, idle_in_timeout);
+       session2_timer_start(s, PROTOLAYER_EVENT_GENERAL_TIMEOUT,
+                       timeout, idle_in_timeout);
        io_start_read((uv_handle_t *)client);
 }
 
index 55d3cc4dde3bb357016e9345c93cf30f7dd1ac31..ee391464091fb9f25e4e6554dce09ea6b4dccec6 100644 (file)
@@ -786,11 +786,12 @@ uv_handle_t *session2_get_handle(struct session2 *s)
 static void session2_on_timeout(uv_timer_t *timer)
 {
        struct session2 *s = timer->data;
-       session2_event(s, PROTOLAYER_EVENT_TIMEOUT, NULL);
+       session2_event(s, s->timer_event, NULL);
 }
 
-int session2_timer_start(struct session2 *s, uint64_t timeout, uint64_t repeat)
+int session2_timer_start(struct session2 *s, enum protolayer_event_type event, uint64_t timeout, uint64_t repeat)
 {
+       s->timer_event = event;
        return uv_timer_start(&s->timer, session2_on_timeout, timeout, repeat);
 }
 
index 604a295035c09559cda9f19bfc2cebd88d214d51..a511de60ffc437ccbb37e9cddc3979e7ec17582b 100644 (file)
@@ -202,7 +202,8 @@ typedef void (*protolayer_finished_cb)(int status, struct session2 *session,
                         * session - i.e. layers SHOULD NOT add
                         * any disconnection ceremony, if
                         * avoidable. */\
-       XX(TIMEOUT) /**< Signal that the session has timed out. */\
+       XX(CONNECT_TIMEOUT) /**< Signal that a connection could not be established due to a timeout. */\
+       XX(GENERAL_TIMEOUT) /**< Signal that a general application-defined timeout has occurred. */\
        XX(CONNECT) /**< Signal that a connection has been established. */\
        XX(CONNECT_FAIL) /**< Signal that a connection could not have been established. */\
        XX(MALFORMED) /**< Signal that a malformed request has been received. */\
@@ -691,6 +692,7 @@ struct session2 {
        struct protolayer_manager *layers; /**< Protocol layers of this session. */
        knot_mm_t pool;
        uv_timer_t timer; /**< For session-wide timeout events. */
+       enum protolayer_event_type timer_event; /**< The event fired on timeout. */
        trie_t *tasks; /**< List of tasks associated with given session. */
        queue_t(struct qr_task *) waiting; /**< List of tasks waiting for
                                            * sending to upstream. */
@@ -812,9 +814,10 @@ struct sockaddr *session2_get_sockname(struct session2 *s);
  * May return `NULL` if no peer is set.  */
 KR_EXPORT uv_handle_t *session2_get_handle(struct session2 *s);
 
-/** Start the session timer. When the timer ends, a `_TIMEOUT` event is sent
- * in the `_UNWRAP` direction. */
-int session2_timer_start(struct session2 *s, uint64_t timeout, uint64_t repeat);
+/** Start the session timer. On timeout, the specified `event` is sent in the
+ * `_UNWRAP` direction. Only a single timeout can be active at a time. */
+int session2_timer_start(struct session2 *s, enum protolayer_event_type event,
+                         uint64_t timeout, uint64_t repeat);
 
 /** Restart the session timer without changing any of its parameters. */
 int session2_timer_restart(struct session2 *s);
index 96d5988747b4c8094c20ed05b36ac63170a852ff..fc43b0e3c64119b854acabf4f10f157e2e10f40d 100644 (file)
@@ -1261,6 +1261,12 @@ static bool pl_tls_client_connect_start(struct pl_tls_sess_data *tls,
        while (tls->handshake_state <= TLS_HS_IN_PROGRESS) {
                int ret = tls_handshake(tls, session);
                if (ret != kr_ok()) {
+                       if (ret == kr_error(EAGAIN)) {
+                               session2_timer_stop(session);
+                               session2_timer_start(session,
+                                               PROTOLAYER_EVENT_GENERAL_TIMEOUT,
+                                               MAX_TCP_INACTIVITY, MAX_TCP_INACTIVITY);
+                       }
                        return false;
                }
        }
index fc62d825f1d1e945f85803180bf1c75e9d2967d1..37d900742dffe99e6320a535a4e5d02804dff5ad 100644 (file)
@@ -578,7 +578,8 @@ int qr_task_on_send(struct qr_task *task, struct session2 *s, int status)
                if (kr_fails_assert(qry && task->transport))
                        return status;
                size_t timeout = task->transport->timeout;
-               int ret = session2_timer_start(s, timeout, 0);
+               int ret = session2_timer_start(s, PROTOLAYER_EVENT_GENERAL_TIMEOUT,
+                               timeout, 0);
                /* Start next step with timeout, fatal if can't start a timer. */
                if (ret != 0) {
                        subreq_finalize(task, &task->transport->address.ip, task->pktbuf);
@@ -819,7 +820,8 @@ static void on_connect(uv_connect_t *req, int status)
        }
 
        session2_timer_stop(session);
-       session2_timer_start(session, MAX_TCP_INACTIVITY, MAX_TCP_INACTIVITY);
+       session2_timer_start(session, PROTOLAYER_EVENT_GENERAL_TIMEOUT,
+                       MAX_TCP_INACTIVITY, MAX_TCP_INACTIVITY);
 }
 
 static int transmit(struct qr_task *task)
@@ -1176,7 +1178,8 @@ static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr
        memcpy(peer, addr, kr_sockaddr_len(addr));
 
        /*  Start watchdog to catch eventual connection timeout. */
-       ret = session2_timer_start(session, KR_CONN_RTT_MAX, 0);
+       ret = session2_timer_start(session, PROTOLAYER_EVENT_CONNECT_TIMEOUT,
+                       KR_CONN_RTT_MAX, 0);
        if (ret != 0) {
                worker_del_tcp_waiting(addr);
                free(conn);
@@ -1733,7 +1736,7 @@ static bool pl_dns_dgram_event_unwrap(enum protolayer_event_type event,
                                       struct protolayer_manager *manager,
                                       void *sess_data)
 {
-       if (event != PROTOLAYER_EVENT_TIMEOUT)
+       if (event != PROTOLAYER_EVENT_GENERAL_TIMEOUT)
                return true;
 
        struct session2 *session = manager->session;
@@ -1868,6 +1871,7 @@ static bool pl_dns_stream_resolution_timeout(struct session2 *s)
        if (!session2_tasklist_is_empty(s)) {
                session2_timer_stop(s);
                session2_timer_start(s,
+                               PROTOLAYER_EVENT_GENERAL_TIMEOUT,
                                KR_RESOLVE_TIME_LIMIT / 2,
                                KR_RESOLVE_TIME_LIMIT / 2);
        } else {
@@ -1886,7 +1890,8 @@ static bool pl_dns_stream_resolution_timeout(struct session2 *s)
                if (idle_time < idle_in_timeout) {
                        idle_in_timeout -= idle_time;
                        session2_timer_stop(s);
-                       session2_timer_start(s, idle_in_timeout, idle_in_timeout);
+                       session2_timer_start(s, PROTOLAYER_EVENT_GENERAL_TIMEOUT,
+                                       idle_in_timeout, idle_in_timeout);
                } else {
                        struct sockaddr *peer = session2_get_peer(s);
                        char *peer_str = kr_straddr(peer);
@@ -2031,12 +2036,11 @@ static bool pl_dns_stream_event_unwrap(enum protolayer_event_type event,
        if (session->closing)
                return true;
 
-       if (event == PROTOLAYER_EVENT_TIMEOUT) {
-               if (session->connected)
-                       return pl_dns_stream_resolution_timeout(manager->session);
-               else
-                       return pl_dns_stream_connection_fail(manager->session,
-                                       KR_SELECTION_TCP_CONNECT_TIMEOUT);
+       if (event == PROTOLAYER_EVENT_GENERAL_TIMEOUT) {
+               return pl_dns_stream_resolution_timeout(manager->session);
+       } else if (event == PROTOLAYER_EVENT_CONNECT_TIMEOUT) {
+               return pl_dns_stream_connection_fail(manager->session,
+                               KR_SELECTION_TCP_CONNECT_TIMEOUT);
        } else if (event == PROTOLAYER_EVENT_CONNECT) {
                return pl_dns_stream_connected(session);
        } else if (event == PROTOLAYER_EVENT_DISCONNECT