From: Oto Šťáva Date: Tue, 11 Jun 2024 14:45:24 +0000 (+0200) Subject: daemon/session2: add special event for OS buffer depletion X-Git-Tag: v6.0.8^2~1^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=158a492fd06ceed0566e3424aeb268a49149ac60;p=thirdparty%2Fknot-resolver.git daemon/session2: add special event for OS buffer depletion For the future, when we need to account for this for e.g. QUIC, which will need to handle this in the UDP case. --- diff --git a/daemon/io.c b/daemon/io.c index 6a72d0494..86bd314e8 100644 --- a/daemon/io.c +++ b/daemon/io.c @@ -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)) diff --git a/daemon/session2.c b/daemon/session2.c index da54beeea..53f90bcdd 100644 --- a/daemon/session2.c +++ b/daemon/session2.c @@ -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) { diff --git a/daemon/session2.h b/daemon/session2.h index dc602cca0..604c43a1d 100644 --- a/daemon/session2.h +++ b/daemon/session2.h @@ -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 {