From: Lennart Poettering Date: Thu, 23 Nov 2023 17:17:44 +0000 (+0100) Subject: varlink: add two helpers for delayed processing of method calls X-Git-Tag: v256-rc1~1307^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=35793c71e4276eceeac690680732f38e1a50475e;p=thirdparty%2Fsystemd.git varlink: add two helpers for delayed processing of method calls When we want to do Polkit authentication we want to temporarily pause handling of a method call until we have the Polkit reply, and then start again. Let's add some glue to make that easy. This adds two helpers: varlink_dispatch_again() allows to ask for redispatching of the currently queued incoming message. Usecase is this: if we don't process a methd right away, we can come back later, and ask it to be processed again with this function, in which case our handlers will be called a 2nd time, exactly like on the first time. varlink_get_current_message() provides access to the currently processed method call. With this the polkit logic can look into the current message, do its thing, and then restart the method handling. --- diff --git a/src/shared/varlink.c b/src/shared/varlink.c index 4664d6b2a67..b6dc0d85902 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -1482,6 +1482,48 @@ finish: return r; } +int varlink_dispatch_again(Varlink *v) { + int r; + + assert_return(v, -EINVAL); + + /* If a method call handler could not process the method call just yet (for example because it needed + * some Polkit authentication first), then it can leave the call unanswered, do its thing, and then + * ask to be dispatched a second time, via this call. It will then be called again, for the same + * message */ + + if (v->state == VARLINK_DISCONNECTED) + return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected."); + if (v->state != VARLINK_PENDING_METHOD) + return varlink_log_errno(v, SYNTHETIC_ERRNO(EBUSY), "Connection has no pending method."); + + varlink_set_state(v, VARLINK_IDLE_SERVER); + + r = sd_event_source_set_enabled(v->defer_event_source, SD_EVENT_ON); + if (r < 0) + return varlink_log_errno(v, r, "Failed to enable deferred event source: %m"); + + return 0; +} + +int varlink_get_current_parameters(Varlink *v, JsonVariant **ret) { + JsonVariant *p; + + assert_return(v, -EINVAL); + + if (!v->current) + return -ENODATA; + + p = json_variant_by_key(v->current, "parameters"); + if (!p) + return -ENODATA; + + if (ret) + *ret = json_variant_ref(p); + + return 0; +} + static void handle_revents(Varlink *v, int revents) { assert(v); diff --git a/src/shared/varlink.h b/src/shared/varlink.h index ad8e9cc46d0..bca4fab05d8 100644 --- a/src/shared/varlink.h +++ b/src/shared/varlink.h @@ -117,6 +117,12 @@ int varlink_error_errno(Varlink *v, int error); int varlink_notify(Varlink *v, JsonVariant *parameters); int varlink_notifyb(Varlink *v, ...); +/* Ask for the current message to be dispatched again */ +int varlink_dispatch_again(Varlink *v); + +/* Get the currently processed incoming message */ +int varlink_get_current_parameters(Varlink *v, JsonVariant **ret); + /* Parsing incoming data via json_dispatch() and generate a nice error on parse errors */ int varlink_dispatch(Varlink *v, JsonVariant *parameters, const JsonDispatch table[], void *userdata);