]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
varlink: add ability to register callback for disconnections
authorLennart Poettering <lennart@poettering.net>
Wed, 27 Nov 2019 13:43:41 +0000 (14:43 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 31 Jan 2020 14:03:27 +0000 (15:03 +0100)
src/shared/varlink.c
src/shared/varlink.h

index 4295eb7ce2f081da0862babb4d7a82597fc0789b..012ce5308c1c7131637a8becde6ec31283744c48 100644 (file)
@@ -168,6 +168,7 @@ struct VarlinkServer {
 
         Hashmap *methods;
         VarlinkConnect connect_callback;
+        VarlinkDisconnect disconnect_callback;
 
         sd_event *event;
         int64_t event_priority;
@@ -1146,6 +1147,7 @@ int varlink_flush(Varlink *v) {
 }
 
 static void varlink_detach_server(Varlink *v) {
+        VarlinkServer *saved_server;
         assert(v);
 
         if (!v->server)
@@ -1169,8 +1171,15 @@ static void varlink_detach_server(Varlink *v) {
         v->server->n_connections--;
 
         /* If this is a connection associated to a server, then let's disconnect the server and the
-         * connection from each other. This drops the dangling reference that connect_callback() set up. */
-        v->server = varlink_server_unref(v->server);
+         * connection from each other. This drops the dangling reference that connect_callback() set up. But
+         * before we release the references, let's call the disconnection callback if it is defined. */
+
+        saved_server = TAKE_PTR(v->server);
+
+        if (saved_server->disconnect_callback)
+                saved_server->disconnect_callback(saved_server, v, saved_server->userdata);
+
+        varlink_server_unref(saved_server);
         varlink_unref(v);
 }
 
@@ -2413,6 +2422,16 @@ int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect callback) {
         return 0;
 }
 
+int varlink_server_bind_disconnect(VarlinkServer *s, VarlinkDisconnect callback) {
+        assert_return(s, -EINVAL);
+
+        if (callback && s->disconnect_callback && callback != s->disconnect_callback)
+                return -EBUSY;
+
+        s->disconnect_callback = callback;
+        return 0;
+}
+
 unsigned varlink_server_connections_max(VarlinkServer *s) {
         int dts;
 
index 6272b33228023d23a46c57b1f9b487cf21eb8242..7440f2ca44d711588c79138bb27f6a3357db3003 100644 (file)
@@ -51,6 +51,7 @@ typedef enum VarlinkServerFlags {
 typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
 typedef int (*VarlinkReply)(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata);
 typedef int (*VarlinkConnect)(VarlinkServer *server, Varlink *link, void *userdata);
+typedef void (*VarlinkDisconnect)(VarlinkServer *server, Varlink *link, void *userdata);
 
 int varlink_connect_address(Varlink **ret, const char *address);
 int varlink_connect_fd(Varlink **ret, int fd);
@@ -134,6 +135,7 @@ int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMeth
 int varlink_server_bind_method_many_internal(VarlinkServer *s, ...);
 #define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
 int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect);
+int varlink_server_bind_disconnect(VarlinkServer *s, VarlinkDisconnect disconnect);
 
 void* varlink_server_set_userdata(VarlinkServer *s, void *userdata);
 void* varlink_server_get_userdata(VarlinkServer *s);