]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/session2: add special event for OS buffer depletion
authorOto Šťáva <oto.stava@nic.cz>
Tue, 11 Jun 2024 14:45:24 +0000 (16:45 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 22 Jul 2024 15:57:47 +0000 (17:57 +0200)
For the future, when we need to account for this for e.g. QUIC, which
will need to handle this in the UDP case.

daemon/io.c
daemon/session2.c
daemon/session2.h

index 6a72d0494d4753472e42a7747e5f14a84ed90b5f..86bd314e88ae358a6d8109b9b5c4098e3da34f09 100644 (file)
@@ -165,15 +165,20 @@ static enum protolayer_event_cb_result pl_tcp_event_wrap(
                enum protolayer_event_type event, void **baton,
                struct session2 *session, void *sess_data)
 {
-       if (event == PROTOLAYER_EVENT_STATS_SEND_ERR) {
+       switch (event) {
+       case PROTOLAYER_EVENT_STATS_SEND_ERR:
                the_worker->stats.err_tcp += 1;
                return PROTOLAYER_EVENT_CONSUME;
-       } else if (event == PROTOLAYER_EVENT_STATS_QRY_OUT) {
+       case PROTOLAYER_EVENT_STATS_QRY_OUT:
                the_worker->stats.tcp += 1;
                return PROTOLAYER_EVENT_CONSUME;
+       case PROTOLAYER_EVENT_OS_BUFFER_FULL:
+               session2_force_close(session);
+               return PROTOLAYER_EVENT_CONSUME;
+       default:
+               return PROTOLAYER_EVENT_PROPAGATE;
        }
 
-       return PROTOLAYER_EVENT_PROPAGATE;
 }
 
 __attribute__((constructor))
index da54beeeab4003b64197e9f85c2736f4dda8ac25..53f90bcdd14dd8b63055923cba21cc5bee819288 100644 (file)
@@ -1235,7 +1235,7 @@ static void session2_event_wrap(struct session2 *s, enum protolayer_event_type e
        session2_transport_event(s, event, baton);
 }
 
-void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum protolayer_event_type event, void *baton)
+static void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum protolayer_event_type event, void *baton)
 {
        bool cont;
        const struct protolayer_grp *grp = &protolayer_grps[s->proto];
@@ -1256,8 +1256,9 @@ void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum protolayer
         *
         * TODO: This might be undesirable for cases with sub-sessions - the
         * current idea is for the layers managing sub-sessions to just return
-        * `false` on `event_unwrap`, but a more "automatic" mechanism may be
-        * added when this is relevant, to make it less error-prone. */
+        * `PROTOLAYER_EVENT_CONSUME` on `event_unwrap`, but a more "automatic"
+        * mechanism may be added when this is relevant, to make it less
+        * error-prone. */
        session2_event_wrap(s, event, baton);
 }
 
@@ -1442,8 +1443,10 @@ static int session2_transport_pushv(struct session2 *s,
                        } else {
                                int ret = uv_udp_try_send((uv_udp_t*)handle,
                                                (uv_buf_t *)iov, iovcnt, comm->comm_addr);
-                               if (ret == UV_EAGAIN)
+                               if (ret == UV_EAGAIN) {
                                        ret = kr_error(ENOBUFS);
+                                       session2_event(s, PROTOLAYER_EVENT_OS_BUFFER_FULL, NULL);
+                               }
 
                                if (false && ret == UV_EAGAIN) { // XXX: see uv_try_write() below
                                        uv_udp_send_t *req = malloc(sizeof(*req));
@@ -1469,7 +1472,7 @@ static int session2_transport_pushv(struct session2 *s,
                        //      We were missing any handling of partial write success, too.
                        if (ret == UV_EAGAIN || (ret >= 0 && ret != iovec_sum(iov, iovcnt))) {
                                ret = kr_error(ENOBUFS);
-                               session2_force_close(s);
+                               session2_event(s, PROTOLAYER_EVENT_OS_BUFFER_FULL, NULL);
                        }
 
                        if (false && ret == UV_EAGAIN) {
index dc602cca0411a49499d3bb47de2f116b3f55b438..604c43a1d2944067163b75f414380a975319352c 100644 (file)
@@ -312,23 +312,31 @@ typedef void (*protolayer_finished_cb)(int status, struct session2 *session,
  * Event types are used to distinguish different events that can be passed to
  * sessions using `session2_event()`. */
 #define PROTOLAYER_EVENT_MAP(XX) \
-       XX(CLOSE) /**< Sending this event closes the session gracefully -
-                  * i.e. layers add their standard disconnection
-                  * ceremony (e.g. `gnutls_bye()`). */\
-       XX(FORCE_CLOSE) /**< Sending this event closes the session forcefully -
-                        * i.e. layers SHOULD NOT add any disconnection
-                        * ceremony, if avoidable. */\
-       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. */\
-       XX(DISCONNECT) /**< Signal that a connection has ended. */\
-       XX(STATS_SEND_ERR) /**< Failed task send - update stats. */\
-       XX(STATS_QRY_OUT) /**< Outgoing query submission - update stats. */
+       /** Closes the session gracefully - i.e. layers add their standard
+        * disconnection ceremony (e.g. `gnutls_bye()`). */\
+       XX(CLOSE) \
+       /** Closes the session forcefully - i.e. layers SHOULD NOT add any
+        * disconnection ceremony, if avoidable. */\
+       XX(FORCE_CLOSE) \
+       /** Signal that a connection could not be established due to a timeout. */\
+       XX(CONNECT_TIMEOUT) \
+       /** Signal that a general application-defined timeout has occurred. */\
+       XX(GENERAL_TIMEOUT) \
+       /** Signal that a connection has been established. */\
+       XX(CONNECT) \
+       /** Signal that a connection could not have been established. */\
+       XX(CONNECT_FAIL) \
+       /** Signal that a malformed request has been received. */\
+       XX(MALFORMED) \
+       /** Signal that a connection has ended. */\
+       XX(DISCONNECT) \
+       /** Failed task send - update stats. */\
+       XX(STATS_SEND_ERR) \
+       /** Outgoing query submission - update stats. */\
+       XX(STATS_QRY_OUT) \
+       /** OS buffers are full, so not sending any more data. */\
+       XX(OS_BUFFER_FULL) \
+       //
 
 /** Event type, to be interpreted by a layer. */
 enum protolayer_event_type {