summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/bus-control.h1
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h64
-rw-r--r--src/libsystemd/sd-bus/bus-match.c110
-rw-r--r--src/libsystemd/sd-bus/bus-match.h11
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c392
-rw-r--r--src/libsystemd/sd-bus/bus-objects.h1
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c244
-rw-r--r--src/libsystemd/sd-bus/bus-slot.h29
-rw-r--r--src/libsystemd/sd-bus/bus-track.c59
-rw-r--r--src/libsystemd/sd-bus/bus-util.c22
-rw-r--r--src/libsystemd/sd-bus/bus-util.h4
-rw-r--r--src/libsystemd/sd-bus/busctl.c6
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c330
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c8
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel-bloom.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-match.c59
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c12
18 files changed, 779 insertions, 577 deletions
diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h
index 420e091b2e..aa290edac7 100644
--- a/src/libsystemd/sd-bus/bus-control.h
+++ b/src/libsystemd/sd-bus/bus-control.h
@@ -22,6 +22,7 @@
***/
#include "sd-bus.h"
+#include "bus-match.h"
int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie);
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 3dceb8a5da..042d352261 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -40,7 +40,6 @@
struct reply_callback {
sd_bus_message_handler_t callback;
- void *userdata;
usec_t timeout;
uint64_t cookie;
unsigned prioq_idx;
@@ -48,13 +47,23 @@ struct reply_callback {
struct filter_callback {
sd_bus_message_handler_t callback;
- void *userdata;
unsigned last_iteration;
LIST_FIELDS(struct filter_callback, callbacks);
};
+struct match_callback {
+ sd_bus_message_handler_t callback;
+
+ uint64_t cookie;
+ unsigned last_iteration;
+
+ char *match_string;
+
+ struct bus_match_node *match_node;
+};
+
struct node {
char *path;
struct node *parent;
@@ -64,8 +73,7 @@ struct node {
LIST_HEAD(struct node_callback, callbacks);
LIST_HEAD(struct node_vtable, vtables);
LIST_HEAD(struct node_enumerator, enumerators);
-
- bool object_manager;
+ LIST_HEAD(struct node_object_manager, object_managers);
};
struct node_callback {
@@ -73,7 +81,6 @@ struct node_callback {
bool is_fallback;
sd_bus_message_handler_t callback;
- void *userdata;
unsigned last_iteration;
@@ -84,20 +91,24 @@ struct node_enumerator {
struct node *node;
sd_bus_node_enumerator_t callback;
- void *userdata;
unsigned last_iteration;
LIST_FIELDS(struct node_enumerator, enumerators);
};
+struct node_object_manager {
+ struct node *node;
+
+ LIST_FIELDS(struct node_object_manager, object_managers);
+};
+
struct node_vtable {
struct node *node;
char *interface;
bool is_fallback;
const sd_bus_vtable *vtable;
- void *userdata;
sd_bus_object_find_t find;
unsigned last_iteration;
@@ -114,6 +125,37 @@ struct vtable_member {
const sd_bus_vtable *vtable;
};
+typedef enum BusSlotType {
+ _BUS_SLOT_DISCONNECTED,
+ BUS_REPLY_CALLBACK,
+ BUS_FILTER_CALLBACK,
+ BUS_MATCH_CALLBACK,
+ BUS_NODE_CALLBACK,
+ BUS_NODE_ENUMERATOR,
+ BUS_NODE_VTABLE,
+ BUS_NODE_OBJECT_MANAGER,
+} BusSlotType;
+
+struct sd_bus_slot {
+ unsigned n_ref;
+ sd_bus *bus;
+ void *userdata;
+ BusSlotType type;
+ bool floating;
+
+ LIST_FIELDS(sd_bus_slot, slots);
+
+ union {
+ struct reply_callback reply_callback;
+ struct filter_callback filter_callback;
+ struct match_callback match_callback;
+ struct node_callback node_callback;
+ struct node_enumerator node_enumerator;
+ struct node_object_manager node_object_manager;
+ struct node_vtable node_vtable;
+ };
+};
+
enum bus_state {
BUS_UNSET,
BUS_OPENING,
@@ -231,7 +273,6 @@ struct sd_bus {
char *exec_path;
char **exec_argv;
- uint64_t hello_cookie;
unsigned iteration_counter;
void *kdbus_buffer;
@@ -260,7 +301,8 @@ struct sd_bus {
sd_event *event;
int event_priority;
- sd_bus_message *current;
+ sd_bus_message *current_message;
+ sd_bus_slot *current_slot;
sd_bus **default_bus_ptr;
pid_t tid;
@@ -276,6 +318,8 @@ struct sd_bus {
unsigned bloom_n_hash;
sd_bus_track *track_queue;
+
+ LIST_HEAD(sd_bus_slot, slots);
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
@@ -340,3 +384,5 @@ int bus_set_address_system(sd_bus *bus);
int bus_set_address_user(sd_bus *bus);
int bus_set_address_system_remote(sd_bus *b, const char *host);
int bus_set_address_system_container(sd_bus *b, const char *machine);
+
+int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
index c54ca8d71d..b868159b5c 100644
--- a/src/libsystemd/sd-bus/bus-match.c
+++ b/src/libsystemd/sd-bus/bus-match.c
@@ -116,6 +116,9 @@ static void bus_match_node_free(struct bus_match_node *node) {
static bool bus_match_node_maybe_free(struct bus_match_node *node) {
assert(node);
+ if (node->type == BUS_MATCH_ROOT)
+ return false;
+
if (node->child)
return false;
@@ -275,10 +278,10 @@ int bus_match_run(
case BUS_MATCH_LEAF:
if (bus) {
- if (node->leaf.last_iteration == bus->iteration_counter)
+ if (node->leaf.callback->last_iteration == bus->iteration_counter)
return 0;
- node->leaf.last_iteration = bus->iteration_counter;
+ node->leaf.callback->last_iteration = bus->iteration_counter;
}
r = sd_bus_message_rewind(m, true);
@@ -287,9 +290,17 @@ int bus_match_run(
/* Run the callback. And then invoke siblings. */
if (node->leaf.callback) {
+ sd_bus_slot *slot;
+
_cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- r = node->leaf.callback(bus, m, node->leaf.userdata, &error_buffer);
+ slot = container_of(node->leaf.callback, sd_bus_slot, match_callback);
+ if (bus)
+ bus->current_slot = slot;
+ r = node->leaf.callback->callback(bus, m, slot->userdata, &error_buffer);
+ if (bus)
+ bus->current_slot = NULL;
+
r = bus_maybe_reply_error(m, r, &error_buffer);
if (r != 0)
return r;
@@ -535,16 +546,13 @@ static int bus_match_find_compare_value(
static int bus_match_add_leaf(
struct bus_match_node *where,
- sd_bus_message_handler_t callback,
- void *userdata,
- uint64_t cookie,
- struct bus_match_node **ret) {
+ struct match_callback *callback) {
struct bus_match_node *n;
assert(where);
assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
- assert(ret);
+ assert(callback);
n = new0(struct bus_match_node, 1);
if (!n)
@@ -555,13 +563,12 @@ static int bus_match_add_leaf(
n->next = where->child;
if (n->next)
n->next->prev = n;
+
n->leaf.callback = callback;
- n->leaf.userdata = userdata;
- n->leaf.cookie = cookie;
+ callback->match_node = n;
where->child = n;
- *ret = n;
return 1;
}
@@ -578,9 +585,13 @@ static int bus_match_find_leaf(
assert(ret);
for (c = where->child; c; c = c->next) {
+ sd_bus_slot *s;
+
+ s = container_of(c->leaf.callback, sd_bus_slot, match_callback);
+
if (c->type == BUS_MATCH_LEAF &&
- c->leaf.callback == callback &&
- c->leaf.userdata == userdata) {
+ c->leaf.callback->callback == callback &&
+ s->userdata == userdata) {
*ret = c;
return 1;
}
@@ -892,16 +903,14 @@ int bus_match_add(
struct bus_match_node *root,
struct bus_match_component *components,
unsigned n_components,
- sd_bus_message_handler_t callback,
- void *userdata,
- uint64_t cookie,
- struct bus_match_node **ret) {
+ struct match_callback *callback) {
unsigned i;
struct bus_match_node *n;
int r;
assert(root);
+ assert(callback);
n = root;
for (i = 0; i < n_components; i++) {
@@ -912,29 +921,56 @@ int bus_match_add(
return r;
}
- r = bus_match_add_leaf(n, callback, userdata, cookie, &n);
- if (r < 0)
- return r;
+ return bus_match_add_leaf(n, callback);
+}
- if (ret)
- *ret = n;
+int bus_match_remove(
+ struct bus_match_node *root,
+ struct match_callback *callback) {
- return 0;
+ struct bus_match_node *node, *pp;
+
+ assert(root);
+ assert(callback);
+
+ node = callback->match_node;
+ if (!node)
+ return 0;
+
+ assert(node->type == BUS_MATCH_LEAF);
+
+ callback->match_node = NULL;
+
+ /* Free the leaf */
+ pp = node->parent;
+ bus_match_node_free(node);
+
+ /* Prune the tree above */
+ while (pp) {
+ node = pp;
+ pp = node->parent;
+
+ if (!bus_match_node_maybe_free(node))
+ break;
+ }
+
+ return 1;
}
-int bus_match_remove(
+int bus_match_find(
struct bus_match_node *root,
struct bus_match_component *components,
unsigned n_components,
sd_bus_message_handler_t callback,
void *userdata,
- uint64_t *cookie) {
+ struct match_callback **ret) {
- unsigned i;
struct bus_match_node *n, **gc;
+ unsigned i;
int r;
assert(root);
+ assert(ret);
gc = newa(struct bus_match_node*, n_components);
@@ -954,24 +990,8 @@ int bus_match_remove(
if (r <= 0)
return r;
- if (cookie)
- *cookie = n->leaf.cookie;
-
- /* Free the leaf */
- bus_match_node_free(n);
-
- /* Prune the tree above */
- for (i = n_components; i > 0; i --) {
- struct bus_match_node *p = gc[i-1]->parent;
-
- if (!bus_match_node_maybe_free(gc[i-1]))
- break;
-
- if (!bus_match_node_maybe_free(p))
- break;
- }
-
- return r;
+ *ret = n->leaf.callback;
+ return 1;
}
void bus_match_free(struct bus_match_node *node) {
@@ -1065,7 +1085,7 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) {
} else if (node->type == BUS_MATCH_ROOT)
puts(" root");
else if (node->type == BUS_MATCH_LEAF)
- printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata);
+ printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata);
else
putchar('\n');
diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h
index 056082b908..af5f65d073 100644
--- a/src/libsystemd/sd-bus/bus-match.h
+++ b/src/libsystemd/sd-bus/bus-match.h
@@ -58,10 +58,7 @@ struct bus_match_node {
uint8_t u8;
} value;
struct {
- sd_bus_message_handler_t callback;
- void *userdata;
- unsigned last_iteration;
- uint64_t cookie;
+ struct match_callback *callback;
} leaf;
struct {
/* If this is set, then the child is NULL */
@@ -78,8 +75,10 @@ struct bus_match_component {
int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
-int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t cookie, struct bus_match_node **ret);
-int bus_match_remove(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t *cookie);
+int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback);
+int bus_match_remove(struct bus_match_node *root, struct match_callback *callback);
+
+int bus_match_find(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, struct match_callback **ret);
void bus_match_free(struct bus_match_node *node);
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 8b12e89164..f160e2343d 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -28,8 +28,9 @@
#include "bus-type.h"
#include "bus-signature.h"
#include "bus-introspect.h"
-#include "bus-objects.h"
#include "bus-util.h"
+#include "bus-slot.h"
+#include "bus-objects.h"
static int node_vtable_get_userdata(
sd_bus *bus,
@@ -38,6 +39,7 @@ static int node_vtable_get_userdata(
void **userdata,
sd_bus_error *error) {
+ sd_bus_slot *s;
void *u;
int r;
@@ -45,9 +47,13 @@ static int node_vtable_get_userdata(
assert(path);
assert(c);
- u = c->userdata;
+ s = container_of(c, sd_bus_slot, node_vtable);
+ u = s->userdata;
if (c->find) {
+ bus->current_slot = s;
r = c->find(bus, path, c->interface, u, &u, error);
+ bus->current_slot = NULL;
+
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
@@ -113,7 +119,10 @@ static int add_enumerated_to_set(
if (bus->nodes_modified)
return 0;
- r = c->callback(bus, prefix, c->userdata, &children, error);
+ bus->current_slot = container_of(c, sd_bus_slot, node_enumerator);
+ r = c->callback(bus, prefix, bus->current_slot->userdata, &children, error);
+ bus->current_slot = NULL;
+
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
@@ -257,7 +266,10 @@ static int node_callbacks_run(
if (r < 0)
return r;
- r = c->callback(bus, m, c->userdata, &error_buffer);
+ bus->current_slot = container_of(c, sd_bus_slot, node_callback);
+ r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
+ bus->current_slot = NULL;
+
r = bus_maybe_reply_error(m, r, &error_buffer);
if (r != 0)
return r;
@@ -382,7 +394,11 @@ static int method_callbacks_run(
m->enforced_reply_signature = strempty(c->vtable->x.method.result);
if (c->vtable->x.method.handler) {
+
+ bus->current_slot = container_of(c->parent, sd_bus_slot, node_vtable);
r = c->vtable->x.method.handler(bus, m, u, &error);
+ bus->current_slot = NULL;
+
return bus_maybe_reply_error(m, r, &error);
}
@@ -396,6 +412,7 @@ static int method_callbacks_run(
static int invoke_property_get(
sd_bus *bus,
+ sd_bus_slot *slot,
const sd_bus_vtable *v,
const char *path,
const char *interface,
@@ -408,6 +425,7 @@ static int invoke_property_get(
int r;
assert(bus);
+ assert(slot);
assert(v);
assert(path);
assert(interface);
@@ -415,7 +433,11 @@ static int invoke_property_get(
assert(reply);
if (v->x.property.get) {
+
+ bus->current_slot = slot;
r = v->x.property.get(bus, path, interface, property, reply, userdata, error);
+ bus->current_slot = NULL;
+
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
@@ -453,6 +475,7 @@ static int invoke_property_get(
static int invoke_property_set(
sd_bus *bus,
+ sd_bus_slot *slot,
const sd_bus_vtable *v,
const char *path,
const char *interface,
@@ -464,6 +487,7 @@ static int invoke_property_set(
int r;
assert(bus);
+ assert(slot);
assert(v);
assert(path);
assert(interface);
@@ -471,7 +495,11 @@ static int invoke_property_set(
assert(value);
if (v->x.property.set) {
+
+ bus->current_slot = slot;
r = v->x.property.set(bus, path, interface, property, value, userdata, error);
+ bus->current_slot = NULL;
+
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
@@ -527,6 +555,7 @@ static int property_get_set_callbacks_run(
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ sd_bus_slot *slot;
void *u = NULL;
int r;
@@ -544,6 +573,8 @@ static int property_get_set_callbacks_run(
if (bus->nodes_modified)
return 0;
+ slot = container_of(c->parent, sd_bus_slot, node_vtable);
+
*found_object = true;
r = sd_bus_message_new_method_return(m, &reply);
@@ -567,7 +598,7 @@ static int property_get_set_callbacks_run(
* PropertiesChanged signals broadcast contents
* anyway. */
- r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, u, &error);
+ r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error);
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
@@ -598,7 +629,7 @@ static int property_get_set_callbacks_run(
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
- r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, u, &error);
+ r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error);
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
@@ -626,6 +657,7 @@ static int vtable_append_one_property(
void *userdata,
sd_bus_error *error) {
+ sd_bus_slot *slot;
int r;
assert(bus);
@@ -646,7 +678,9 @@ static int vtable_append_one_property(
if (r < 0)
return r;
- r = invoke_property_get(bus, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
+ slot = container_of(c, sd_bus_slot, node_vtable);
+
+ r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
if (r < 0)
return r;
if (bus->nodes_modified)
@@ -783,7 +817,7 @@ static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
assert(bus);
assert(n);
- if (n->object_manager)
+ if (n->object_managers)
return true;
if (n->parent)
@@ -827,7 +861,7 @@ static bool bus_node_exists(
return false;
}
- return !require_fallback && (n->enumerators || n->object_manager);
+ return !require_fallback && (n->enumerators || n->object_managers);
}
static int process_introspect(
@@ -1421,7 +1455,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
return n;
}
-static void bus_node_gc(sd_bus *b, struct node *n) {
+void bus_node_gc(sd_bus *b, struct node *n) {
assert(b);
if (!n)
@@ -1431,7 +1465,7 @@ static void bus_node_gc(sd_bus *b, struct node *n) {
n->callbacks ||
n->vtables ||
n->enumerators ||
- n->object_manager)
+ n->object_managers)
return;
assert(hashmap_remove(b->nodes, n->path) == n);
@@ -1446,12 +1480,13 @@ static void bus_node_gc(sd_bus *b, struct node *n) {
static int bus_add_object(
sd_bus *bus,
+ sd_bus_slot **slot,
bool fallback,
const char *path,
sd_bus_message_handler_t callback,
void *userdata) {
- struct node_callback *c;
+ sd_bus_slot *s;
struct node *n;
int r;
@@ -1464,136 +1499,49 @@ static int bus_add_object(
if (!n)
return -ENOMEM;
- c = new0(struct node_callback, 1);
- if (!c) {
+ s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata);
+ if (!s) {
r = -ENOMEM;
goto fail;
}
- c->node = n;
- c->callback = callback;
- c->userdata = userdata;
- c->is_fallback = fallback;
+ s->node_callback.callback = callback;
+ s->node_callback.is_fallback = fallback;
- LIST_PREPEND(callbacks, n->callbacks, c);
+ s->node_callback.node = n;
+ LIST_PREPEND(callbacks, n->callbacks, &s->node_callback);
bus->nodes_modified = true;
+ if (slot)
+ *slot = s;
+
return 0;
fail:
- free(c);
+ sd_bus_slot_unref(s);
bus_node_gc(bus, n);
+
return r;
}
-static int bus_remove_object(
+_public_ int sd_bus_add_object(
sd_bus *bus,
- bool fallback,
+ sd_bus_slot **slot,
const char *path,
sd_bus_message_handler_t callback,
void *userdata) {
- struct node_callback *c;
- struct node *n;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(callback, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- n = hashmap_get(bus->nodes, path);
- if (!n)
- return 0;
-
- LIST_FOREACH(callbacks, c, n->callbacks)
- if (c->callback == callback && c->userdata == userdata && c->is_fallback == fallback)
- break;
- if (!c)
- return 0;
-
- LIST_REMOVE(callbacks, n->callbacks, c);
- free(c);
-
- bus_node_gc(bus, n);
- bus->nodes_modified = true;
-
- return 1;
-}
-
-_public_ int sd_bus_add_object(sd_bus *bus,
- const char *path,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- return bus_add_object(bus, false, path, callback, userdata);
-}
-
-_public_ int sd_bus_remove_object(sd_bus *bus,
- const char *path,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- return bus_remove_object(bus, false, path, callback, userdata);
-}
-
-_public_ int sd_bus_add_fallback(sd_bus *bus,
- const char *prefix,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- return bus_add_object(bus, true, prefix, callback, userdata);
-}
-
-_public_ int sd_bus_remove_fallback(sd_bus *bus,
- const char *prefix,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- return bus_remove_object(bus, true, prefix, callback, userdata);
+ return bus_add_object(bus, slot, false, path, callback, userdata);
}
-static void free_node_vtable(sd_bus *bus, struct node_vtable *w) {
- assert(bus);
-
- if (!w)
- return;
-
- if (w->interface && w->node && w->vtable) {
- const sd_bus_vtable *v;
-
- for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) {
- struct vtable_member *x = NULL;
-
- switch (v->type) {
-
- case _SD_BUS_VTABLE_METHOD: {
- struct vtable_member key;
-
- key.path = w->node->path;
- key.interface = w->interface;
- key.member = v->x.method.member;
-
- x = hashmap_remove(bus->vtable_methods, &key);
- break;
- }
-
- case _SD_BUS_VTABLE_PROPERTY:
- case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
- struct vtable_member key;
-
- key.path = w->node->path;
- key.interface = w->interface;
- key.member = v->x.property.member;
- x = hashmap_remove(bus->vtable_properties, &key);
- break;
- }}
-
- free(x);
- }
- }
+_public_ int sd_bus_add_fallback(
+ sd_bus *bus,
+ sd_bus_slot **slot,
+ const char *prefix,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
- free(w->interface);
- free(w);
+ return bus_add_object(bus, slot, true, prefix, callback, userdata);
}
static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
@@ -1637,6 +1585,7 @@ static int vtable_member_compare_func(const void *a, const void *b) {
static int add_object_vtable_internal(
sd_bus *bus,
+ sd_bus_slot **slot,
const char *path,
const char *interface,
const sd_bus_vtable *vtable,
@@ -1644,7 +1593,8 @@ static int add_object_vtable_internal(
sd_bus_object_find_t find,
void *userdata) {
- struct node_vtable *c = NULL, *i, *existing = NULL;
+ sd_bus_slot *s;
+ struct node_vtable *i, *existing = NULL;
const sd_bus_vtable *v;
struct node *n;
int r;
@@ -1690,25 +1640,23 @@ static int add_object_vtable_internal(
}
}
- c = new0(struct node_vtable, 1);
- if (!c) {
+ s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata);
+ if (!s) {
r = -ENOMEM;
goto fail;
}
- c->node = n;
- c->is_fallback = fallback;
- c->vtable = vtable;
- c->userdata = userdata;
- c->find = find;
+ s->node_vtable.is_fallback = fallback;
+ s->node_vtable.vtable = vtable;
+ s->node_vtable.find = find;
- c->interface = strdup(interface);
- if (!c->interface) {
+ s->node_vtable.interface = strdup(interface);
+ if (!s->node_vtable.interface) {
r = -ENOMEM;
goto fail;
}
- for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
+ for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
switch (v->type) {
@@ -1730,9 +1678,9 @@ static int add_object_vtable_internal(
goto fail;
}
- m->parent = c;
+ m->parent = &s->node_vtable;
m->path = n->path;
- m->interface = c->interface;
+ m->interface = s->node_vtable.interface;
m->member = v->x.method.member;
m->vtable = v;
@@ -1773,9 +1721,9 @@ static int add_object_vtable_internal(
goto fail;
}
- m->parent = c;
+ m->parent = &s->node_vtable;
m->path = n->path;
- m->interface = c->interface;
+ m->interface = s->node_vtable.interface;
m->member = v->x.property.member;
m->vtable = v;
@@ -1805,110 +1753,53 @@ static int add_object_vtable_internal(
}
}
- LIST_INSERT_AFTER(vtables, n->vtables, existing, c);
+ s->node_vtable.node = n;
+ LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable);
bus->nodes_modified = true;
+ if (slot)
+ *slot = s;
+
return 0;
fail:
- if (c)
- free_node_vtable(bus, c);
-
- bus_node_gc(bus, n);
- return r;
-}
-
-static int remove_object_vtable_internal(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const sd_bus_vtable *vtable,
- bool fallback,
- sd_bus_object_find_t find,
- void *userdata) {
-
- struct node_vtable *c;
- struct node *n;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(interface_name_is_valid(interface), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- n = hashmap_get(bus->nodes, path);
- if (!n)
- return 0;
-
- LIST_FOREACH(vtables, c, n->vtables)
- if (streq(c->interface, interface) &&
- c->is_fallback == fallback &&
- c->vtable == vtable &&
- c->find == find &&
- c->userdata == userdata)
- break;
-
- if (!c)
- return 0;
-
- LIST_REMOVE(vtables, n->vtables, c);
-
- free_node_vtable(bus, c);
+ sd_bus_slot_unref(s);
bus_node_gc(bus, n);
- bus->nodes_modified = true;
-
- return 1;
+ return r;
}
_public_ int sd_bus_add_object_vtable(
sd_bus *bus,
+ sd_bus_slot **slot,
const char *path,
const char *interface,
const sd_bus_vtable *vtable,
void *userdata) {
- return add_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
-}
-
-_public_ int sd_bus_remove_object_vtable(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const sd_bus_vtable *vtable,
- void *userdata) {
-
- return remove_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
+ return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata);
}
_public_ int sd_bus_add_fallback_vtable(
sd_bus *bus,
- const char *path,
- const char *interface,
- const sd_bus_vtable *vtable,
- sd_bus_object_find_t find,
- void *userdata) {
-
- return add_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
-}
-
-_public_ int sd_bus_remove_fallback_vtable(
- sd_bus *bus,
- const char *path,
+ sd_bus_slot **slot,
+ const char *prefix,
const char *interface,
const sd_bus_vtable *vtable,
sd_bus_object_find_t find,
void *userdata) {
- return remove_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
+ return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata);
}
_public_ int sd_bus_add_node_enumerator(
sd_bus *bus,
+ sd_bus_slot **slot,
const char *path,
sd_bus_node_enumerator_t callback,
void *userdata) {
- struct node_enumerator *c;
+ sd_bus_slot *s;
struct node *n;
int r;
@@ -1921,61 +1812,28 @@ _public_ int sd_bus_add_node_enumerator(
if (!n)
return -ENOMEM;
- c = new0(struct node_enumerator, 1);
- if (!c) {
+ s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata);
+ if (!s) {
r = -ENOMEM;
goto fail;
}
- c->node = n;
- c->callback = callback;
- c->userdata = userdata;
-
- LIST_PREPEND(enumerators, n->enumerators, c);
+ s->node_enumerator.callback = callback;
+ s->node_enumerator.node = n;
+ LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator);
bus->nodes_modified = true;
+ if (slot)
+ *slot = s;
+
return 0;
fail:
- free(c);
- bus_node_gc(bus, n);
- return r;
-}
-
-_public_ int sd_bus_remove_node_enumerator(
- sd_bus *bus,
- const char *path,
- sd_bus_node_enumerator_t callback,
- void *userdata) {
-
- struct node_enumerator *c;
- struct node *n;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(callback, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- n = hashmap_get(bus->nodes, path);
- if (!n)
- return 0;
-
- LIST_FOREACH(enumerators, c, n->enumerators)
- if (c->callback == callback && c->userdata == userdata)
- break;
-
- if (!c)
- return 0;
-
- LIST_REMOVE(enumerators, n->enumerators, c);
- free(c);
-
+ sd_bus_slot_unref(s);
bus_node_gc(bus, n);
- bus->nodes_modified = true;
-
- return 1;
+ return r;
}
static int emit_properties_changed_on_interface(
@@ -2481,8 +2339,10 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const
return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
}
-_public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
+_public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
+ sd_bus_slot *s;
struct node *n;
+ int r;
assert_return(bus, -EINVAL);
assert_return(object_path_is_valid(path), -EINVAL);
@@ -2492,28 +2352,24 @@ _public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
if (!n)
return -ENOMEM;
- n->object_manager = true;
- bus->nodes_modified = true;
- return 0;
-}
-
-_public_ int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
- struct node *n;
+ s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL);
+ if (!s) {
+ r = -ENOMEM;
+ goto fail;
+ }
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ s->node_object_manager.node = n;
+ LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager);
+ bus->nodes_modified = true;
- n = hashmap_get(bus->nodes, path);
- if (!n)
- return 0;
+ if (slot)
+ *slot = s;
- if (!n->object_manager)
- return 0;
+ return 0;
- n->object_manager = false;
- bus->nodes_modified = true;
+fail:
+ sd_bus_slot_unref(s);
bus_node_gc(bus, n);
- return 1;
+ return r;
}
diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h
index 420edd9478..4373fae89c 100644
--- a/src/libsystemd/sd-bus/bus-objects.h
+++ b/src/libsystemd/sd-bus/bus-objects.h
@@ -24,3 +24,4 @@
#include "bus-internal.h"
int bus_process_object(sd_bus *bus, sd_bus_message *m);
+void bus_node_gc(sd_bus *b, struct node *n);
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
new file mode 100644
index 0000000000..8e38992ec4
--- /dev/null
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -0,0 +1,244 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2013 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+#include "bus-control.h"
+#include "bus-objects.h"
+#include "bus-slot.h"
+
+sd_bus_slot *bus_slot_allocate(
+ sd_bus *bus,
+ bool floating,
+ BusSlotType type,
+ size_t extra,
+ void *userdata) {
+
+ sd_bus_slot *slot;
+
+ assert(bus);
+
+ slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
+ if (!slot)
+ return NULL;
+
+ slot->n_ref = 1;
+ slot->type = type;
+ slot->bus = bus;
+ slot->floating = floating;
+ slot->userdata = userdata;
+
+ if (!floating)
+ sd_bus_ref(bus);
+
+ LIST_PREPEND(slots, bus->slots, slot);
+
+ return slot;
+}
+
+_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
+ assert_return(slot, NULL);
+
+ assert(slot->n_ref > 0);
+
+ slot->n_ref++;
+ return slot;
+}
+
+void bus_slot_disconnect(sd_bus_slot *slot) {
+ sd_bus *bus;
+
+ assert(slot);
+
+ switch (slot->type) {
+
+ case _BUS_SLOT_DISCONNECTED:
+ /* Already disconnected... */
+ return;
+
+ case BUS_REPLY_CALLBACK:
+
+ if (slot->reply_callback.cookie != 0)
+ hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
+
+ if (slot->reply_callback.timeout != 0)
+ prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
+
+ break;
+
+ case BUS_FILTER_CALLBACK:
+ slot->bus->filter_callbacks_modified = true;
+ LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
+ break;
+
+ case BUS_MATCH_CALLBACK:
+
+ if (slot->bus->bus_client)
+ bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
+
+ slot->bus->match_callbacks_modified = true;
+ bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
+
+ free(slot->match_callback.match_string);
+
+ break;
+
+ case BUS_NODE_CALLBACK:
+
+ if (slot->node_callback.node) {
+ LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
+ slot->bus->nodes_modified = true;
+
+ bus_node_gc(slot->bus, slot->node_callback.node);
+ }
+
+ break;
+
+ case BUS_NODE_ENUMERATOR:
+
+ if (slot->node_enumerator.node) {
+ LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
+ slot->bus->nodes_modified = true;
+
+ bus_node_gc(slot->bus, slot->node_enumerator.node);
+ }
+
+ break;
+
+ case BUS_NODE_OBJECT_MANAGER:
+
+ if (slot->node_object_manager.node) {
+ LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
+ slot->bus->nodes_modified = true;
+
+ bus_node_gc(slot->bus, slot->node_object_manager.node);
+ }
+
+ break;
+
+ case BUS_NODE_VTABLE:
+
+ if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
+ const sd_bus_vtable *v;
+
+ for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) {
+ struct vtable_member *x = NULL;
+
+ switch (v->type) {
+
+ case _SD_BUS_VTABLE_METHOD: {
+ struct vtable_member key;
+
+ key.path = slot->node_vtable.node->path;
+ key.interface = slot->node_vtable.interface;
+ key.member = v->x.method.member;
+
+ x = hashmap_remove(slot->bus->vtable_methods, &key);
+ break;
+ }
+
+ case _SD_BUS_VTABLE_PROPERTY:
+ case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
+ struct vtable_member key;
+
+ key.path = slot->node_vtable.node->path;
+ key.interface = slot->node_vtable.interface;
+ key.member = v->x.method.member;
+
+
+ x = hashmap_remove(slot->bus->vtable_properties, &key);
+ break;
+ }}
+
+ free(x);
+ }
+ }
+
+ free(slot->node_vtable.interface);
+
+ if (slot->node_vtable.node) {
+ LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
+ slot->bus->nodes_modified = true;
+
+ bus_node_gc(slot->bus, slot->node_vtable.node);
+ }
+
+ break;
+ }
+ bus = slot->bus;
+
+ slot->type = _BUS_SLOT_DISCONNECTED;
+ slot->bus = NULL;
+ LIST_REMOVE(slots, bus->slots, slot);
+
+ if (!slot->floating)
+ sd_bus_unref(bus);
+}
+
+_public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
+
+ if (!slot)
+ return NULL;
+
+ assert(slot->n_ref > 0);
+
+ if (slot->n_ref > 1) {
+ slot->n_ref --;
+ return NULL;
+ }
+
+ bus_slot_disconnect(slot);
+ free(slot);
+
+ return NULL;
+}
+
+_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
+ assert_return(slot, NULL);
+
+ return slot->bus;
+}
+
+_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
+ assert_return(slot, NULL);
+
+ return slot->userdata;
+}
+
+_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
+ void *ret;
+
+ assert_return(slot, NULL);
+
+ ret = slot->userdata;
+ slot->userdata = userdata;
+
+ return ret;
+}
+
+_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
+ assert_return(slot, NULL);
+ assert_return(slot->type != _BUS_SLOT_DISCONNECTED, NULL);
+
+ if (slot->bus->current_slot != slot)
+ return NULL;
+
+ return slot->bus->current_message;
+}
diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h
new file mode 100644
index 0000000000..23a15e4d02
--- /dev/null
+++ b/src/libsystemd/sd-bus/bus-slot.h
@@ -0,0 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+#include "bus-internal.h"
+
+sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata);
+
+void bus_slot_disconnect(sd_bus_slot *slot);
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 0f6a2eafbd..ffa2cf3d75 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -21,6 +21,7 @@
#include "sd-bus.h"
#include "set.h"
+#include "bus-util.h"
#include "bus-internal.h"
#include "bus-track.h"
@@ -29,7 +30,7 @@ struct sd_bus_track {
sd_bus *bus;
sd_bus_track_handler_t handler;
void *userdata;
- Set *names;
+ Hashmap *names;
LIST_FIELDS(sd_bus_track, queue);
Iterator iterator;
bool in_queue;
@@ -128,11 +129,11 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
return NULL;
}
- while ((n = set_first(track->names)))
+ while ((n = hashmap_first_key(track->names)))
sd_bus_track_remove_name(track, n);
bus_track_remove_from_queue(track);
- set_free(track->names);
+ hashmap_free(track->names);
sd_bus_unref(track->bus);
free(track);
@@ -157,6 +158,7 @@ static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *use
}
_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
+ _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
_cleanup_free_ char *n = NULL;
const char *match;
int r;
@@ -164,7 +166,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
assert_return(track, -EINVAL);
assert_return(service_name_is_valid(name), -EINVAL);
- r = set_ensure_allocated(&track->names, string_hash_func, string_compare_func);
+ r = hashmap_ensure_allocated(&track->names, string_hash_func, string_compare_func);
if (r < 0)
return r;
@@ -172,30 +174,28 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
if (!n)
return -ENOMEM;
- r = set_put(track->names, n);
+ /* First, subscribe to this name */
+ match = MATCH_FOR_NAME(n);
+ r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(track->names, n, slot);
if (r == -EEXIST)
return 0;
if (r < 0)
return r;
- /* First, subscribe to this name */
- match = MATCH_FOR_NAME(name);
- r = sd_bus_add_match(track->bus, match, on_name_owner_changed, track);
- if (r < 0) {
- set_remove(track->names, n);
- return r;
- }
-
/* Second, check if it is currently existing, or maybe
* doesn't, or maybe disappeared already. */
- r = sd_bus_get_owner(track->bus, name, 0, NULL);
+ r = sd_bus_get_owner(track->bus, n, 0, NULL);
if (r < 0) {
- set_remove(track->names, n);
- sd_bus_remove_match(track->bus, match, on_name_owner_changed, track);
+ hashmap_remove(track->names, n);
return r;
}
n = NULL;
+ slot = NULL;
bus_track_remove_from_queue(track);
track->modified = true;
@@ -204,22 +204,19 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
}
_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
- const char *match;
- _cleanup_free_ char *n = NULL;;
+ _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
+ _cleanup_free_ char *n = NULL;
assert_return(name, -EINVAL);
if (!track)
return 0;
- n = set_remove(track->names, (char*) name);
- if (!n)
+ slot = hashmap_remove2(track->names, (char*) name, (void**) &n);
+ if (!slot)
return 0;
- match = MATCH_FOR_NAME(n);
- sd_bus_remove_match(track->bus, match, on_name_owner_changed, track);
-
- if (set_isempty(track->names))
+ if (hashmap_isempty(track->names))
bus_track_add_to_queue(track);
track->modified = true;
@@ -231,34 +228,40 @@ _public_ unsigned sd_bus_track_count(sd_bus_track *track) {
if (!track)
return 0;
- return set_size(track->names);
+ return hashmap_size(track->names);
}
_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) {
assert_return(track, NULL);
assert_return(name, NULL);
- return set_get(track->names, (void*) name);
+ return hashmap_get(track->names, (void*) name) ? name : NULL;
}
_public_ const char* sd_bus_track_first(sd_bus_track *track) {
+ const char *n = NULL;
+
if (!track)
return NULL;
track->modified = false;
track->iterator = NULL;
- return set_iterate(track->names, &track->iterator);
+ hashmap_iterate(track->names, &track->iterator, (const void**) &n);
+ return n;
}
_public_ const char* sd_bus_track_next(sd_bus_track *track) {
+ const char *n = NULL;
+
if (!track)
return NULL;
if (track->modified)
return NULL;
- return set_iterate(track->names, &track->iterator);
+ hashmap_iterate(track->names, &track->iterator, (const void**) &n);
+ return n;
}
_public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index 84b3fc5af5..b5b3c857b8 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -77,7 +77,7 @@ int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
if (r < 0)
return -ENOMEM;
- r = sd_bus_add_match(bus, match, name_owner_change_callback, e);
+ r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
if (r < 0)
return r;
@@ -251,17 +251,16 @@ typedef struct AsyncPolkitQuery {
sd_bus_message *request, *reply;
sd_bus_message_handler_t callback;
void *userdata;
- uint64_t serial;
+ sd_bus_slot *slot;
Hashmap *registry;
} AsyncPolkitQuery;
-static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
+static void async_polkit_query_free(AsyncPolkitQuery *q) {
if (!q)
return;
- if (q->serial > 0 && b)
- sd_bus_call_async_cancel(b, q->serial);
+ sd_bus_slot_unref(q->slot);
if (q->registry && q->request)
hashmap_remove(q->registry, q->request);
@@ -281,8 +280,8 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd
assert(reply);
assert(q);
+ q->slot = sd_bus_slot_unref(q->slot);
q->reply = sd_bus_message_ref(reply);
- q->serial = 0;
r = sd_bus_message_rewind(q->request, true);
if (r < 0) {
@@ -294,7 +293,8 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd
r = bus_maybe_reply_error(q->request, r, &error_buffer);
finish:
- async_polkit_query_free(bus, q);
+ async_polkit_query_free(q);
+
return r;
}
@@ -413,15 +413,15 @@ int bus_verify_polkit_async(
r = hashmap_put(*registry, m, q);
if (r < 0) {
- async_polkit_query_free(bus, q);
+ async_polkit_query_free(q);
return r;
}
q->registry = *registry;
- r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
+ r = sd_bus_call_async(bus, &q->slot, pk, async_polkit_callback, q, 0);
if (r < 0) {
- async_polkit_query_free(bus, q);
+ async_polkit_query_free(q);
return r;
}
@@ -436,7 +436,7 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
AsyncPolkitQuery *q;
while ((q = hashmap_steal_first(registry)))
- async_polkit_query_free(bus, q);
+ async_polkit_query_free(q);
hashmap_free(registry);
#endif
diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h
index 8103555fe8..1514fad81f 100644
--- a/src/libsystemd/sd-bus/bus-util.h
+++ b/src/libsystemd/sd-bus/bus-util.h
@@ -139,12 +139,16 @@ typedef struct UnitInfo {
int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref);
#define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
+#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp)
#define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
#define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp)
+#define _cleanup_bus_track_unref_ _cleanup_(sd_bus_slot_unrefp)
#define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index 4e396f20c1..4545047011 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -240,7 +240,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
if (!m)
return log_oom();
- r = sd_bus_add_match(bus, m, NULL, NULL);
+ r = sd_bus_add_match(bus, NULL, m, NULL, NULL);
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
return r;
@@ -250,7 +250,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
}
STRV_FOREACH(i, arg_matches) {
- r = sd_bus_add_match(bus, *i, NULL, NULL);
+ r = sd_bus_add_match(bus, NULL, *i, NULL, NULL);
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
return r;
@@ -260,7 +260,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
}
if (!added_something) {
- r = sd_bus_add_match(bus, "", NULL, NULL);
+ r = sd_bus_add_match(bus, NULL, "", NULL, NULL);
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
return r;
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index dc54e211a4..ea80e9d19b 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -52,6 +52,7 @@
#include "bus-container.h"
#include "bus-protocol.h"
#include "bus-track.h"
+#include "bus-slot.h"
static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
static int attach_io_events(sd_bus *b);
@@ -71,43 +72,6 @@ static void bus_close_fds(sd_bus *b) {
b->input_fd = b->output_fd = -1;
}
-static void bus_node_destroy(sd_bus *b, struct node *n) {
- struct node_callback *c;
- struct node_vtable *v;
- struct node_enumerator *e;
-
- assert(b);
-
- if (!n)
- return;
-
- while (n->child)
- bus_node_destroy(b, n->child);
-
- while ((c = n->callbacks)) {
- LIST_REMOVE(callbacks, n->callbacks, c);
- free(c);
- }
-
- while ((v = n->vtables)) {
- LIST_REMOVE(vtables, n->vtables, v);
- free(v->interface);
- free(v);
- }
-
- while ((e = n->enumerators)) {
- LIST_REMOVE(enumerators, n->enumerators, e);
- free(e);
- }
-
- if (n->parent)
- LIST_REMOVE(siblings, n->parent->child, n);
-
- assert_se(hashmap_remove(b->nodes, n->path) == n);
- free(n->path);
- free(n);
-}
-
static void bus_reset_queues(sd_bus *b) {
assert(b);
@@ -133,15 +97,28 @@ static void bus_reset_queues(sd_bus *b) {
}
static void bus_free(sd_bus *b) {
- struct filter_callback *f;
- struct node *n;
+ sd_bus_slot *s;
assert(b);
-
assert(!b->track_queue);
+ b->state = BUS_CLOSED;
+
sd_bus_detach_event(b);
+ while ((s = b->slots)) {
+ /* At this point only floating slots can still be
+ * around, because the non-floating ones keep a
+ * reference to the bus, and we thus couldn't be
+ * destructing right now... We forcibly disconnect the
+ * slots here, so that they still can be referenced by
+ * apps, but are dead. */
+
+ assert(s->floating);
+ bus_slot_disconnect(s);
+ sd_bus_slot_unref(s);
+ }
+
if (b->default_bus_ptr)
*b->default_bus_ptr = NULL;
@@ -171,19 +148,12 @@ static void bus_free(sd_bus *b) {
hashmap_free_free(b->reply_callbacks);
prioq_free(b->reply_callbacks_prioq);
- while ((f = b->filter_callbacks)) {
- LIST_REMOVE(callbacks, b->filter_callbacks, f);
- free(f);
- }
-
bus_match_free(&b->match_callbacks);
hashmap_free_free(b->vtable_methods);
hashmap_free_free(b->vtable_properties);
- while ((n = hashmap_first(b->nodes)))
- bus_node_destroy(b, n);
-
+ assert(hashmap_isempty(b->nodes));
hashmap_free(b->nodes);
bus_kernel_flush_memfd(b);
@@ -426,7 +396,7 @@ static int bus_send_hello(sd_bus *bus) {
if (r < 0)
return r;
- return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_cookie);
+ return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0);
}
int bus_start_running(sd_bus *bus) {
@@ -1793,14 +1763,14 @@ static int timeout_compare(const void *a, const void *b) {
_public_ int sd_bus_call_async(
sd_bus *bus,
+ sd_bus_slot **slot,
sd_bus_message *_m,
sd_bus_message_handler_t callback,
void *userdata,
- uint64_t usec,
- uint64_t *cookie) {
+ uint64_t usec) {
_cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
- struct reply_callback *c;
+ _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL;
int r;
assert_return(bus, -EINVAL);
@@ -1830,55 +1800,37 @@ _public_ int sd_bus_call_async(
if (r < 0)
return r;
- c = new0(struct reply_callback, 1);
- if (!c)
+ s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata);
+ if (!s)
return -ENOMEM;
- c->callback = callback;
- c->userdata = userdata;
- c->cookie = BUS_MESSAGE_COOKIE(m);
- c->timeout = calc_elapse(m->timeout);
+ s->reply_callback.callback = callback;
- r = hashmap_put(bus->reply_callbacks, &c->cookie, c);
+ s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m);
+ r = hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback);
if (r < 0) {
- free(c);
+ s->reply_callback.cookie = 0;
return r;
}
- if (c->timeout != 0) {
- r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ s->reply_callback.timeout = calc_elapse(m->timeout);
+ if (s->reply_callback.timeout != 0) {
+ r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
if (r < 0) {
- c->timeout = 0;
- sd_bus_call_async_cancel(bus, c->cookie);
+ s->reply_callback.timeout = 0;
return r;
}
}
- r = sd_bus_send(bus, m, cookie);
- if (r < 0) {
- sd_bus_call_async_cancel(bus, c->cookie);
+ r = sd_bus_send(bus, m, &s->reply_callback.cookie);
+ if (r < 0)
return r;
- }
-
- return r;
-}
-
-_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie) {
- struct reply_callback *c;
- assert_return(bus, -EINVAL);
- assert_return(cookie != 0, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- c = hashmap_remove(bus->reply_callbacks, &cookie);
- if (!c)
- return 0;
-
- if (c->timeout != 0)
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ if (slot)
+ *slot = s;
+ s = NULL;
- free(c);
- return 1;
+ return r;
}
int bus_ensure_running(sd_bus *bus) {
@@ -2125,6 +2077,11 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
return 0;
}
+ if (c->timeout == 0) {
+ *timeout_usec = (uint64_t) -1;
+ return 0;
+ }
+
*timeout_usec = c->timeout;
return 1;
}
@@ -2161,16 +2118,21 @@ static int process_timeout(sd_bus *bus) {
return r;
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
+ c->timeout = 0;
+
hashmap_remove(bus->reply_callbacks, &c->cookie);
+ c->cookie = 0;
+
+ bus->current_message = m;
+ bus->current_slot = container_of(c, sd_bus_slot, reply_callback);
- bus->current = m;
bus->iteration_counter ++;
- r = c->callback(bus, m, c->userdata, &error_buffer);
+ r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
r = bus_maybe_reply_error(m, r, &error_buffer);
- free(c);
- bus->current = NULL;
+ bus->current_message = NULL;
+ bus->current_slot = NULL;
return r;
}
@@ -2191,7 +2153,7 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
return -EIO;
- if (m->reply_cookie != bus->hello_cookie)
+ if (m->reply_cookie != 1)
return -EIO;
return 0;
@@ -2200,7 +2162,8 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
static int process_reply(sd_bus *bus, sd_bus_message *m) {
_cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- _cleanup_free_ struct reply_callback *c = NULL;
+ sd_bus_slot *slot;
+ struct reply_callback *c;
int r;
assert(bus);
@@ -2220,8 +2183,13 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
if (!c)
return 0;
- if (c->timeout != 0)
+ c->cookie = 0;
+ slot = container_of(c, sd_bus_slot, reply_callback);
+
+ if (c->timeout != 0) {
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ c->timeout = 0;
+ }
if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
@@ -2234,22 +2202,31 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
&SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"),
&synthetic_reply);
if (r < 0)
- return r;
+ goto finish;
r = bus_seal_synthetic_message(bus, synthetic_reply);
if (r < 0)
- return r;
+ goto finish;
m = synthetic_reply;
} else {
r = sd_bus_message_rewind(m, true);
if (r < 0)
- return r;
+ goto finish;
}
- r = c->callback(bus, m, c->userdata, &error_buffer);
+ bus->current_slot = slot;
+ r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
+ bus->current_slot = NULL;
+
r = bus_maybe_reply_error(m, r, &error_buffer);
+finish:
+ if (slot->floating) {
+ bus_slot_disconnect(slot);
+ sd_bus_slot_unref(slot);
+ }
+
return r;
}
@@ -2279,7 +2256,10 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) {
if (r < 0)
return r;
- r = l->callback(bus, m, l->userdata, &error_buffer);
+ bus->current_slot = container_of(l, sd_bus_slot, filter_callback);
+ r = l->callback(bus, m, bus->current_slot->userdata, &error_buffer);
+ bus->current_slot = NULL;
+
r = bus_maybe_reply_error(m, r, &error_buffer);
if (r != 0)
return r;
@@ -2395,7 +2375,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
assert(bus);
assert(m);
- bus->current = m;
+ bus->current_message = m;
bus->iteration_counter++;
log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s",
@@ -2436,7 +2416,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
r = bus_process_object(bus, m);
finish:
- bus->current = NULL;
+ bus->current_message = NULL;
return r;
}
@@ -2539,17 +2519,23 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
if (r < 0)
return r;
- if (c->timeout != 0)
+ if (c->timeout != 0) {
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ c->timeout = 0;
+ }
hashmap_remove(bus->reply_callbacks, &c->cookie);
+ c->cookie = 0;
+
+ bus->current_message = m;
+ bus->current_slot = container_of(c, sd_bus_slot, reply_callback);
- bus->current = m;
bus->iteration_counter++;
- r = c->callback(bus, m, c->userdata, &error_buffer);
+ r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
r = bus_maybe_reply_error(m, r, &error_buffer);
- free(c);
+
+ bus->current_slot = NULL;
goto finish;
}
@@ -2572,7 +2558,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
sd_bus_close(bus);
- bus->current = m;
+ bus->current_message = m;
bus->iteration_counter++;
r = process_filter(bus, m);
@@ -2591,7 +2577,8 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
r = 1;
finish:
- bus->current = NULL;
+ bus->current_message = NULL;
+
return r;
}
@@ -2608,7 +2595,8 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
assert_return(!bus_pid_changed(bus), -ECHILD);
/* We don't allow recursively invoking sd_bus_process(). */
- assert_return(!bus->current, -EBUSY);
+ assert_return(!bus->current_message, -EBUSY);
+ assert(!bus->current_slot);
switch (bus->state) {
@@ -2785,57 +2773,43 @@ _public_ int sd_bus_flush(sd_bus *bus) {
}
}
-_public_ int sd_bus_add_filter(sd_bus *bus,
- sd_bus_message_handler_t callback,
- void *userdata) {
+_public_ int sd_bus_add_filter(
+ sd_bus *bus,
+ sd_bus_slot **slot,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
- struct filter_callback *f;
+ sd_bus_slot *s;
assert_return(bus, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- f = new0(struct filter_callback, 1);
- if (!f)
+ s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata);
+ if (!s)
return -ENOMEM;
- f->callback = callback;
- f->userdata = userdata;
- bus->filter_callbacks_modified = true;
- LIST_PREPEND(callbacks, bus->filter_callbacks, f);
- return 0;
-}
+ s->filter_callback.callback = callback;
-_public_ int sd_bus_remove_filter(sd_bus *bus,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- struct filter_callback *f;
-
- assert_return(bus, -EINVAL);
- assert_return(callback, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
+ bus->filter_callbacks_modified = true;
+ LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback);
- LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
- if (f->callback == callback && f->userdata == userdata) {
- bus->filter_callbacks_modified = true;
- LIST_REMOVE(callbacks, bus->filter_callbacks, f);
- free(f);
- return 1;
- }
- }
+ if (slot)
+ *slot = s;
return 0;
}
-_public_ int sd_bus_add_match(sd_bus *bus,
- const char *match,
- sd_bus_message_handler_t callback,
- void *userdata) {
+_public_ int sd_bus_add_match(
+ sd_bus *bus,
+ sd_bus_slot **slot,
+ const char *match,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
struct bus_match_component *components = NULL;
unsigned n_components = 0;
- uint64_t cookie = 0;
+ sd_bus_slot *s;
int r = 0;
assert_return(bus, -EINVAL);
@@ -2846,35 +2820,60 @@ _public_ int sd_bus_add_match(sd_bus *bus,
if (r < 0)
goto finish;
+ s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata);
+ if (!s) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ s->match_callback.callback = callback;
+ s->match_callback.cookie = ++bus->match_cookie;
+
if (bus->bus_client) {
- cookie = ++bus->match_cookie;
- r = bus_add_match_internal(bus, match, components, n_components, cookie);
+ if (!bus->is_kernel) {
+ /* When this is not a kernel transport, we
+ * store the original match string, so that we
+ * can use it to remove the match again */
+
+ s->match_callback.match_string = strdup(match);
+ if (!s->match_callback.match_string) {
+ r = -ENOMEM;
+ goto finish;
+ }
+ }
+
+ r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
if (r < 0)
goto finish;
}
bus->match_callbacks_modified = true;
- r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
- if (r < 0) {
- if (bus->bus_client)
- bus_remove_match_internal(bus, match, cookie);
- }
+ r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback);
+ if (r < 0)
+ goto finish;
+
+ if (slot)
+ *slot = s;
+ s = NULL;
finish:
bus_match_parse_free(components, n_components);
+ sd_bus_slot_unref(s);
+
return r;
}
-_public_ int sd_bus_remove_match(sd_bus *bus,
- const char *match,
- sd_bus_message_handler_t callback,
- void *userdata) {
+int bus_remove_match_by_string(
+ sd_bus *bus,
+ const char *match,
+ sd_bus_message_handler_t callback,
+ void *userdata) {
struct bus_match_component *components = NULL;
unsigned n_components = 0;
- int r = 0, q = 0;
- uint64_t cookie = 0;
+ struct match_callback *c;
+ int r = 0;
assert_return(bus, -EINVAL);
assert_return(match, -EINVAL);
@@ -2882,17 +2881,18 @@ _public_ int sd_bus_remove_match(sd_bus *bus,
r = bus_match_parse(match, &components, &n_components);
if (r < 0)
- return r;
+ goto finish;
- bus->match_callbacks_modified = true;
- r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
+ r = bus_match_find(&bus->match_callbacks, components, n_components, NULL, NULL, &c);
+ if (r <= 0)
+ goto finish;
- if (bus->bus_client)
- q = bus_remove_match_internal(bus, match, cookie);
+ sd_bus_slot_unref(container_of(c, sd_bus_slot, match_callback));
+finish:
bus_match_parse_free(components, n_components);
- return r < 0 ? r : q;
+ return r;
}
bool bus_pid_changed(sd_bus *bus) {
@@ -3116,10 +3116,16 @@ _public_ sd_event* sd_bus_get_event(sd_bus *bus) {
return bus->event;
}
-_public_ sd_bus_message* sd_bus_get_current(sd_bus *bus) {
+_public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) {
+ assert_return(bus, NULL);
+
+ return bus->current_message;
+}
+
+_public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) {
assert_return(bus, NULL);
- return bus->current;
+ return bus->current_slot;
}
static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) {
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index c0abc7a697..c9eb69843d 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -100,19 +100,19 @@ static int server_init(sd_bus **_bus) {
goto fail;
}
- r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
+ r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
if (r < 0) {
log_error("Failed to add object: %s", strerror(-r));
goto fail;
}
- r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
+ r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
goto fail;
}
- r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
+ r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
goto fail;
@@ -490,7 +490,7 @@ static void* client2(void*p) {
goto finish;
}
- r = sd_bus_call_async(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
+ r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
if (r < 0) {
log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
goto finish;
diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
index 0ecad18f45..5ee6eea0e8 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
@@ -72,7 +72,7 @@ static void test_one(
assert_se(r >= 0);
log_debug("match");
- r = sd_bus_add_match(b, match, NULL, NULL);
+ r = sd_bus_add_match(b, NULL, match, NULL, NULL);
assert_se(r >= 0);
log_debug("signal");
diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c
index 34d000f1c6..7bb8b0a540 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel.c
@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN));
assert_se(r == -EHOSTUNREACH);
- r = sd_bus_add_match(b, "interface='waldo.com',member='Piep'", NULL, NULL);
+ r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL);
assert_se(r >= 0);
r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name");
diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c
index c561be2a65..a62de502f9 100644
--- a/src/libsystemd/sd-bus/test-bus-match.c
+++ b/src/libsystemd/sd-bus/test-bus-match.c
@@ -28,6 +28,7 @@
#include "bus-match.h"
#include "bus-message.h"
#include "bus-util.h"
+#include "bus-slot.h"
static bool mask[32];
@@ -56,31 +57,23 @@ static bool mask_contains(unsigned a[], unsigned n) {
return true;
}
-static int match_add(struct bus_match_node *root, const char *match, int value) {
+static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) {
struct bus_match_component *components = NULL;
unsigned n_components = 0;
+ sd_bus_slot *s;
int r;
- r = bus_match_parse(match, &components, &n_components);
- if (r < 0)
- return r;
-
- r = bus_match_add(root, components, n_components, filter, INT_TO_PTR(value), 0, NULL);
- bus_match_parse_free(components, n_components);
-
- return r;
-}
-
-static int match_remove(struct bus_match_node *root, const char *match, int value) {
- struct bus_match_component *components = NULL;
- unsigned n_components = 0;
- int r;
+ s = slots + value;
+ zero(*s);
r = bus_match_parse(match, &components, &n_components);
if (r < 0)
return r;
- r = bus_match_remove(root, components, n_components, filter, INT_TO_PTR(value), 0);
+ s->userdata = INT_TO_PTR(value);
+ s->match_callback.callback = filter;
+
+ r = bus_match_add(root, components, n_components, &s->match_callback);
bus_match_parse_free(components, n_components);
return r;
@@ -90,24 +83,25 @@ int main(int argc, char *argv[]) {
struct bus_match_node root;
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
enum bus_match_node_type i;
+ sd_bus_slot slots[15];
zero(root);
root.type = BUS_MATCH_ROOT;
- assert_se(match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0);
- assert_se(match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0);
- assert_se(match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0);
- assert_se(match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0);
- assert_se(match_add(&root, "", 5) >= 0);
- assert_se(match_add(&root, "interface='quux.x'", 6) >= 0);
- assert_se(match_add(&root, "interface='bar.x'", 7) >= 0);
- assert_se(match_add(&root, "member='waldo',path='/foo/bar'", 8) >= 0);
- assert_se(match_add(&root, "path='/foo/bar'", 9) >= 0);
- assert_se(match_add(&root, "path_namespace='/foo'", 10) >= 0);
- assert_se(match_add(&root, "path_namespace='/foo/quux'", 11) >= 0);
- assert_se(match_add(&root, "arg1='two'", 12) >= 0);
- assert_se(match_add(&root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
- assert_se(match_add(&root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
+ assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0);
+ assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0);
+ assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0);
+ assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0);
+ assert_se(match_add(slots, &root, "", 5) >= 0);
+ assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0);
+ assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0);
+ assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0);
+ assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0);
+ assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0);
+ assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0);
+ assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0);
+ assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
+ assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
bus_match_dump(&root, 0);
@@ -119,9 +113,8 @@ int main(int argc, char *argv[]) {
assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8));
- assert_se(match_remove(&root, "member='waldo',path='/foo/bar'", 8) > 0);
- assert_se(match_remove(&root, "arg2path='/prefix/',member='waldo'", 13) > 0);
- assert_se(match_remove(&root, "interface='bar.xx'", 7) == 0);
+ assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0);
+ assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0);
bus_match_dump(&root, 0);
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
index e2423c7f67..e7a445f3cb 100644
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ b/src/libsystemd/sd-bus/test-bus-objects.c
@@ -200,7 +200,7 @@ static const sd_bus_vtable vtable2[] = {
SD_BUS_VTABLE_END
};
-static int enumerator_callback(sd_bus *b, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
if (object_path_startswith("/value", path))
assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
@@ -222,11 +222,11 @@ static void *server(void *p) {
assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
assert_se(sd_bus_set_server(bus, 1, id) >= 0);
- assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
- assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
- assert_se(sd_bus_add_fallback_vtable(bus, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
- assert_se(sd_bus_add_node_enumerator(bus, "/value", enumerator_callback, NULL) >= 0);
- assert_se(sd_bus_add_object_manager(bus, "/value") >= 0);
+ assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
+ assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
+ assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
+ assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
+ assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
assert_se(sd_bus_start(bus) >= 0);