]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
varlink: add two helpers for delayed processing of method calls
authorLennart Poettering <lennart@poettering.net>
Thu, 23 Nov 2023 17:17:44 +0000 (18:17 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 2 Jan 2024 16:57:35 +0000 (17:57 +0100)
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.

src/shared/varlink.c
src/shared/varlink.h

index 4664d6b2a67313d44120caeb5cd785812ae036d7..b6dc0d859026c539ca7cc192b1ba7bd9dbd5d095 100644 (file)
@@ -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);
 
index ad8e9cc46d01564fb49b517efccab6ebc5d9617b..bca4fab05d84401d02d6c56f50c203a330547705 100644 (file)
@@ -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);