src/libsystemd/sd-bus/bus-track.h \
src/libsystemd/sd-bus/bus-util.c \
src/libsystemd/sd-bus/bus-util.h \
+ src/libsystemd/sd-bus/bus-slot.c \
+ src/libsystemd/sd-bus/bus-slot.h \
src/libsystemd/sd-bus/bus-protocol.h \
src/libsystemd/sd-bus/kdbus.h \
src/libsystemd/sd-bus/sd-memfd.c \
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
+#include "bus-internal.h"
#include "build.h"
#include "strv.h"
#include "def.h"
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
- r = sd_bus_add_match(a, match, NULL, NULL);
+ r = sd_bus_add_match(a, NULL, match, NULL, NULL);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
- r = sd_bus_remove_match(a, match, NULL, NULL);
+ r = bus_remove_match_by_string(a, match, NULL, NULL);
+ if (r == 0)
+ return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
if (r < 0)
return synthetic_reply_method_errno(m, r, NULL);
r = sd_bus_release_name(a, name);
if (r < 0) {
if (r == -ESRCH)
- synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
+ return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
if (r == -EADDRINUSE)
- synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
+ return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
+
return synthetic_reply_method_errno(m, r, NULL);
}
goto finish;
}
- r = sd_bus_add_match(a, match, NULL, NULL);
+ r = sd_bus_add_match(a, NULL, match, NULL, NULL);
if (r < 0) {
log_error("Failed to add match for NameLost: %s", strerror(-r));
goto finish;
goto finish;
}
- r = sd_bus_add_match(a, match, NULL, NULL);
+ r = sd_bus_add_match(a, NULL, match, NULL, NULL);
if (r < 0) {
log_error("Failed to add match for NameAcquired: %s", strerror(-r));
goto finish;
sd_bus_message *message;
pid_t pid;
- message = sd_bus_get_current(bus);
+ message = sd_bus_get_current_message(bus);
if (!message)
return 0;
assert(bus);
#ifdef HAVE_SELINUX
- r = sd_bus_add_filter(bus, selinux_filter, m);
+ r = sd_bus_add_filter(bus, NULL, selinux_filter, m);
if (r < 0) {
log_error("Failed to add SELinux access filter: %s", strerror(-r));
return r;
}
#endif
- r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
+ r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
if (r < 0) {
log_error("Failed to register Manager vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
if (r < 0) {
log_error("Failed to register Job vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
+ r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
if (r < 0) {
log_error("Failed to add job enumerator: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
if (r < 0) {
log_error("Failed to register Unit vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
+ r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
if (r < 0) {
log_error("Failed to add job enumerator: %s", strerror(-r));
return r;
}
for (t = 0; t < _UNIT_TYPE_MAX; t++) {
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
if (r < 0) {
log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
if (unit_vtable[t]->cgroup_context_offset > 0) {
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
if (r < 0) {
log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
if (r < 0) {
log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
if (unit_vtable[t]->exec_context_offset > 0) {
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
if (r < 0) {
log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
}
if (unit_vtable[t]->kill_context_offset > 0) {
- r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
+ r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
if (r < 0) {
log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
return r;
r = sd_bus_add_match(
bus,
+ NULL,
"sender='org.freedesktop.DBus.Local',"
"type='signal',"
"path='/org/freedesktop/DBus/Local',"
r = sd_bus_add_match(
bus,
+ NULL,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
r = sd_bus_add_match(
bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
r = sd_bus_add_match(
bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
* the system bus */
r = sd_bus_add_match(
bus,
+ NULL,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
return r;
}
- r = sd_bus_add_object_vtable(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c);
+ r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c);
if (r < 0) {
log_error("Failed to register object: %s", strerror(-r));
return r;
sd_bus_send_to;
sd_bus_call;
sd_bus_call_async;
- sd_bus_call_async_cancel;
sd_bus_get_fd;
sd_bus_get_events;
sd_bus_get_timeout;
sd_bus_process_priority;
sd_bus_wait;
sd_bus_flush;
- sd_bus_get_current;
+ sd_bus_get_current_message;
+ sd_bus_get_current_slot;
sd_bus_get_tid;
sd_bus_attach_event;
sd_bus_detach_event;
sd_bus_get_event;
sd_bus_add_filter;
- sd_bus_remove_filter;
sd_bus_add_match;
- sd_bus_remove_match;
sd_bus_add_object;
- sd_bus_remove_object;
sd_bus_add_fallback;
- sd_bus_remove_fallback;
sd_bus_add_object_vtable;
- sd_bus_remove_object_vtable;
sd_bus_add_fallback_vtable;
- sd_bus_remove_fallback_vtable;
sd_bus_add_node_enumerator;
- sd_bus_remove_node_enumerator;
sd_bus_add_object_manager;
- sd_bus_remove_object_manager;
+ sd_bus_slot_ref;
+ sd_bus_slot_unref;
+ sd_bus_slot_get_bus;
+ sd_bus_slot_get_userdata;
+ sd_bus_slot_set_userdata;
+ sd_bus_slot_get_current_message;
sd_bus_message_new_signal;
sd_bus_message_new_method_call;
sd_bus_message_new_method_return;
***/
#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);
struct reply_callback {
sd_bus_message_handler_t callback;
- void *userdata;
usec_t timeout;
uint64_t cookie;
unsigned prioq_idx;
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;
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 {
bool is_fallback;
sd_bus_message_handler_t callback;
- void *userdata;
unsigned last_iteration;
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;
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,
char *exec_path;
char **exec_argv;
- uint64_t hello_cookie;
unsigned iteration_counter;
void *kdbus_buffer;
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;
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))
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);
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;
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);
/* 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;
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)
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;
}
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;
}
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++) {
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);
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) {
} 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');
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 */
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);
#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,
void **userdata,
sd_bus_error *error) {
+ sd_bus_slot *s;
void *u;
int r;
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))
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))
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;
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);
}
static int invoke_property_get(
sd_bus *bus,
+ sd_bus_slot *slot,
const sd_bus_vtable *v,
const char *path,
const char *interface,
int r;
assert(bus);
+ assert(slot);
assert(v);
assert(path);
assert(interface);
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))
static int invoke_property_set(
sd_bus *bus,
+ sd_bus_slot *slot,
const sd_bus_vtable *v,
const char *path,
const char *interface,
int r;
assert(bus);
+ assert(slot);
assert(v);
assert(path);
assert(interface);
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))
_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;
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);
* 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);
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);
void *userdata,
sd_bus_error *error) {
+ sd_bus_slot *slot;
int r;
assert(bus);
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)
assert(bus);
assert(n);
- if (n->object_manager)
+ if (n->object_managers)
return true;
if (n->parent)
return false;
}
- return !require_fallback && (n->enumerators || n->object_manager);
+ return !require_fallback && (n->enumerators || n->object_managers);
}
static int process_introspect(
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)
n->callbacks ||
n->vtables ||
n->enumerators ||
- n->object_manager)
+ n->object_managers)
return;
assert(hashmap_remove(b->nodes, n->path) == 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;
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]) {
static int add_object_vtable_internal(
sd_bus *bus,
+ sd_bus_slot **slot,
const char *path,
const char *interface,
const sd_bus_vtable *vtable,
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;
}
}
- 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) {
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;
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;
}
}
- 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;
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(
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);
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;
}
#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);
--- /dev/null
+/*-*- 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;
+}
--- /dev/null
+/*-*- 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);
#include "sd-bus.h"
#include "set.h"
+#include "bus-util.h"
#include "bus-internal.h"
#include "bus-track.h"
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;
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);
}
_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;
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;
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;
}
_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;
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) {
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;
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);
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) {
r = bus_maybe_reply_error(q->request, r, &error_buffer);
finish:
- async_polkit_query_free(bus, q);
+ async_polkit_query_free(q);
+
return r;
}
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;
}
AsyncPolkitQuery *q;
while ((q = hashmap_steal_first(registry)))
- async_polkit_query_free(bus, q);
+ async_polkit_query_free(q);
hashmap_free(registry);
#endif
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) \
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;
}
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;
}
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;
#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);
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);
}
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;
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);
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) {
_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);
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) {
return 0;
}
+ if (c->timeout == 0) {
+ *timeout_usec = (uint64_t) -1;
+ return 0;
+ }
+
*timeout_usec = c->timeout;
return 1;
}
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;
}
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;
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);
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)) {
&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;
}
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;
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",
r = bus_process_object(bus, m);
finish:
- bus->current = NULL;
+ bus->current_message = NULL;
return r;
}
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;
}
sd_bus_close(bus);
- bus->current = m;
+ bus->current_message = m;
bus->iteration_counter++;
r = process_filter(bus, m);
r = 1;
finish:
- bus->current = NULL;
+ bus->current_message = NULL;
+
return r;
}
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) {
}
}
-_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);
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);
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) {
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) {
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;
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;
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");
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");
#include "bus-match.h"
#include "bus-message.h"
#include "bus-util.h"
+#include "bus-slot.h"
static bool mask[32];
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;
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);
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);
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));
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);
return r;
}
- r = sd_bus_add_object_vtable(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
+ r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
if (r < 0) {
log_error("Failed to register object: %s", strerror(-r));
return r;
Session *session;
pid_t pid;
- message = sd_bus_get_current(bus);
+ message = sd_bus_get_current_message(bus);
if (!message)
return 0;
sd_bus_message *message;
pid_t pid;
- message = sd_bus_get_current(bus);
+ message = sd_bus_get_current_message(bus);
if (!message)
return 0;
sd_bus_message *message;
pid_t pid;
- message = sd_bus_get_current(bus);
+ message = sd_bus_get_current_message(bus);
if (!message)
return 0;
return r;
}
- r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
+ r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
if (r < 0) {
log_error("Failed to add manager object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
if (r < 0) {
log_error("Failed to add seat object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
if (r < 0) {
log_error("Failed to add seat enumerator: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
if (r < 0) {
log_error("Failed to add session object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/session", session_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
if (r < 0) {
log_error("Failed to add session enumerator: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
if (r < 0) {
log_error("Failed to add user object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/user", user_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
if (r < 0) {
log_error("Failed to add user enumerator: %s", strerror(-r));
return r;
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"interface='org.freedesktop.DBus',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.DBus.Properties',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
sd_bus_message *message;
pid_t pid;
- message = sd_bus_get_current(bus);
+ message = sd_bus_get_current_message(bus);
if (!message)
return 0;
return r;
}
- r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
+ r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
if (r < 0) {
log_error("Failed to add manager object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
+ r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
if (r < 0) {
log_error("Failed to add machine object vtable: %s", strerror(-r));
return r;
}
- r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
+ r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
if (r < 0) {
log_error("Failed to add machine enumerator: %s", strerror(-r));
return r;
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.DBus.Properties',"
}
r = sd_bus_add_match(m->bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
if (r < 0)
return r;
- r = sd_bus_call_async(link->manager->bus, m, set_hostname_handler, link, 0, NULL);
+ r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0);
if (r < 0)
log_error_link(link, "Could not set transient hostname: %s", strerror(-r));
r = sd_bus_add_match(
bus,
+ NULL,
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
}
static int wait_for_jobs(sd_bus *bus, Set *s) {
+ _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
WaitData d = { .set = s };
int r = 0, q;
assert(bus);
assert(s);
- q = sd_bus_add_filter(bus, wait_filter, &d);
+ q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
if (q < 0)
return log_oom();
d.result = NULL;
}
- q = sd_bus_remove_filter(bus, wait_filter, &d);
- if (q < 0 && r == 0)
- r = q;
-
return r;
}
typedef struct sd_bus sd_bus;
typedef struct sd_bus_message sd_bus_message;
+typedef struct sd_bus_slot sd_bus_slot;
typedef struct sd_bus_creds sd_bus_creds;
typedef struct sd_bus_track sd_bus_track;
int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie);
int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie);
int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply);
-int sd_bus_call_async(sd_bus *bus, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec, uint64_t *cookie);
-int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie);
+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);
int sd_bus_get_fd(sd_bus *bus);
int sd_bus_get_events(sd_bus *bus);
int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
int sd_bus_flush(sd_bus *bus);
-sd_bus_message* sd_bus_get_current(sd_bus *bus);
+sd_bus_message* sd_bus_get_current_message(sd_bus *bus);
+sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority);
int sd_bus_detach_event(sd_bus *bus);
sd_event *sd_bus_get_event(sd_bus *bus);
-int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
+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);
+int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot, const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
+int sd_bus_add_node_enumerator(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
+int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path);
-int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
+/* Slot object */
-int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata);
+sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot);
+sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot);
-int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
+sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot);
-int sd_bus_add_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
-int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
+void *sd_bus_slot_get_userdata(sd_bus_slot *slot);
+void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
-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);
-int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
-
-int sd_bus_add_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
-int sd_bus_remove_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
-
-int sd_bus_add_object_manager(sd_bus *bus, const char *path);
-int sd_bus_remove_object_manager(sd_bus *bus, const char *path);
+sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot);
/* Message object */
return r;
}
- r = sd_bus_add_object_vtable(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c);
+ r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c);
if (r < 0) {
log_error("Failed to register object: %s", strerror(-r));
return r;