summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-11-23 18:17:44 +0100
committerLennart Poettering <lennart@poettering.net>2024-01-02 17:57:35 +0100
commit35793c71e4276eceeac690680732f38e1a50475e (patch)
treef1ab54fb33e08d8bd6a0fb8009a7a92af0861274 /src
parentvarlink: add new helper varlink_get_peer_pidref() for getting PidRef of peer (diff)
downloadsystemd-35793c71e4276eceeac690680732f38e1a50475e.tar.xz
systemd-35793c71e4276eceeac690680732f38e1a50475e.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/shared/varlink.c42
-rw-r--r--src/shared/varlink.h6
2 files changed, 48 insertions, 0 deletions
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
index 4664d6b2a6..b6dc0d8590 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 ad8e9cc46d..bca4fab05d 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);