summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-12-19 15:50:05 +0100
committerLennart Poettering <lennart@poettering.net>2018-01-05 13:58:32 +0100
commitb38cc8d5631253738d5474f39b2026eb5524f772 (patch)
tree69cc94e213d72ea2235c87e94bafb1dee4dbd9bd
parentbdbc866914e54189d6f9924349005fa8fa6bf71b (diff)
downloadsystemd-b38cc8d5631253738d5474f39b2026eb5524f772.tar.gz
sd-bus: add new sd_bus_set_connected_signal() API
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.
-rw-r--r--src/libsystemd/libsystemd.sym2
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h1
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c73
3 files changed, 75 insertions, 1 deletions
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index af4226c73a..27f3219ee2 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -541,4 +541,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;
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 29366c4c56..abda27fd56 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -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;
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 7967aac7c6..74d54f785f 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -392,6 +392,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;
@@ -417,9 +477,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;
}
@@ -449,6 +514,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);
@@ -471,6 +537,11 @@ int bus_start_running(sd_bus *bus) {
}
bus->state = BUS_RUNNING;
+
+ r = synthesize_connected_signal(bus);
+ if (r < 0)
+ return r;
+
return 1;
}