chiark / gitweb /
sd-bus: add new sd_bus_set_connected_signal() API
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Dec 2017 14:50:05 +0000 (15:50 +0100)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:49:59 +0000 (07:49 +0200)
With this new API sd-bus can synthesize a local "Connected" signal when
the connection is fully established. It mirrors the local "Disconnected"
signal that is already generated when the connection is terminated. This
is useful to be notified when connection setup is done, in order to
start method calls then, in particular when using "slow" connection
methods (for example slow TCP, or most importantly the "watch_bind"
inotify logic).

Note that one could also use hook into the initial NameAcquired signal
received from the bus broker, but that scheme works only if we actually
connect to a bus. The benefit of "Connected" OTOH is that it works with
any kind of connection.

Ideally, we'd just generate this message unconditionally, but in order
not to break clients that do not expect this message it is opt-in.

src/libelogind/libelogind.sym
src/libelogind/sd-bus/bus-internal.h
src/libelogind/sd-bus/sd-bus.c

index a601e42fd7474b2331f8e53af114fb8f9e273a1e..44720bcbf3d58224fceb7542784d02c653b5f8d9 100644 (file)
@@ -547,4 +547,6 @@ global:
         sd_bus_match_signal;
         sd_bus_match_signal_async;
         sd_bus_is_ready;
+        sd_bus_set_connected_signal;
+        sd_bus_get_connected_signal;
 } LIBSYSTEMD_236;
index 443fc6e7412868ca1284ddbe5b4cdec577441477..7124b8edc106f4599653b01b1ac10358995ca741 100644 (file)
@@ -219,6 +219,7 @@ struct sd_bus {
         bool is_monitor:1;
         bool accept_fd:1;
         bool attach_timestamp:1;
+        bool connected_signal:1;
 
         int use_memfd;
 
index 14d90903d11e2ce93844531be3e3cf4aa252a83f..ca4075af61911cf3b1916beb98fd92dfc82de565 100644 (file)
@@ -397,6 +397,66 @@ _public_ int sd_bus_get_watch_bind(sd_bus *bus) {
         return bus->watch_bind;
 }
 
+_public_ int sd_bus_set_connected_signal(sd_bus *bus, int b) {
+        assert_return(bus, -EINVAL);
+        assert_return(bus->state == BUS_UNSET, -EPERM);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+
+        bus->connected_signal = b;
+        return 0;
+}
+
+_public_ int sd_bus_get_connected_signal(sd_bus *bus) {
+        assert_return(bus, -EINVAL);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+
+        return bus->connected_signal;
+}
+
+static int synthesize_connected_signal(sd_bus *bus) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        int r;
+
+        assert(bus);
+
+        /* If enabled, synthesizes a local "Connected" signal mirroring the local "Disconnected" signal. This is called
+         * whenever we fully established a connection, i.e. after the authorization phase, and after receiving the
+         * Hello() reply. Or in other words, whenver we enter BUS_RUNNING state.
+         *
+         * This is useful so that clients can start doing stuff whenver the connection is fully established in a way
+         * that works independently from whether we connected to a full bus or just a direct connection. */
+
+        if (!bus->connected_signal)
+                return 0;
+
+        r = sd_bus_message_new_signal(
+                        bus,
+                        &m,
+                        "/org/freedesktop/DBus/Local",
+                        "org.freedesktop.DBus.Local",
+                        "Connected");
+        if (r < 0)
+                return r;
+
+        bus_message_set_sender_local(bus, m);
+
+        r = bus_seal_synthetic_message(bus, m);
+        if (r < 0)
+                return r;
+
+        r = bus_rqueue_make_room(bus);
+        if (r < 0)
+                return r;
+
+        /* Insert at the very front */
+        memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
+        bus->rqueue[0] = m;
+        m = NULL;
+        bus->rqueue_size++;
+
+        return 0;
+}
+
 static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
         const char *s;
         sd_bus *bus;
@@ -422,9 +482,14 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e
         if (!bus->unique_name)
                 return -ENOMEM;
 
-        if (bus->state == BUS_HELLO)
+        if (bus->state == BUS_HELLO) {
                 bus->state = BUS_RUNNING;
 
+                r = synthesize_connected_signal(bus);
+                if (r < 0)
+                        return r;
+        }
+
         return 1;
 }
 
@@ -454,6 +519,7 @@ int bus_start_running(sd_bus *bus) {
         struct reply_callback *c;
         Iterator i;
         usec_t n;
+        int r;
 
         assert(bus);
         assert(bus->state < BUS_HELLO);
@@ -476,6 +542,11 @@ int bus_start_running(sd_bus *bus) {
         }
 
         bus->state = BUS_RUNNING;
+
+        r = synthesize_connected_signal(bus);
+        if (r < 0)
+                return r;
+
         return 1;
 }