sd-bus: introduce sd_bus_slot objects encapsulating callbacks or vtables attached to a bus connection

This makes callback behaviour more like sd-event or sd-resolve, and
creates proper object for unregistering callbacks.

Taking the refernce to the slot is optional. If not taken life time of
the slot will be bound to the underlying bus object (or in the case of
an async call until the reply has been recieved).
This commit is contained in:
Lennart Poettering
2014-05-15 01:15:30 +02:00
parent 9a78148e40
commit 19befb2d5f
34 changed files with 869 additions and 653 deletions

View File

@@ -2119,6 +2119,8 @@ libsystemd_internal_la_SOURCES = \
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 \

View File

@@ -40,6 +40,7 @@
#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"
@@ -551,7 +552,7 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
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);
@@ -564,7 +565,9 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
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);
@@ -739,9 +742,10 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
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);
}
@@ -1177,7 +1181,7 @@ int main(int argc, char *argv[]) {
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;
@@ -1198,7 +1202,7 @@ int main(int argc, char *argv[]) {
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;

View File

@@ -310,7 +310,7 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_
sd_bus_message *message;
pid_t pid;
message = sd_bus_get_current(bus);
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
@@ -536,58 +536,58 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
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;
@@ -595,7 +595,7 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
}
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;
@@ -603,7 +603,7 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
}
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;
@@ -622,6 +622,7 @@ static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
r = sd_bus_add_match(
bus,
NULL,
"sender='org.freedesktop.DBus.Local',"
"type='signal',"
"path='/org/freedesktop/DBus/Local',"
@@ -710,6 +711,7 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"
@@ -780,6 +782,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
@@ -791,6 +794,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
@@ -874,6 +878,7 @@ static int bus_setup_system(Manager *m, sd_bus *bus) {
* the system bus */
r = sd_bus_add_match(
bus,
NULL,
"type='signal',"
"interface='org.freedesktop.systemd1.Agent',"
"member='Released',"

View File

@@ -591,7 +591,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
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;

View File

@@ -173,7 +173,6 @@ m4_ifdef(`ENABLE_KDBUS',
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;
@@ -181,27 +180,26 @@ m4_ifdef(`ENABLE_KDBUS',
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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
if (ret)
*ret = n;
return 0;
return bus_match_add_leaf(n, callback);
}
int bus_match_remove(
struct bus_match_node *root,
struct match_callback *callback) {
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_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');

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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

View File

@@ -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) \

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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");

Some files were not shown because too many files have changed in this diff Show More