diff options
Diffstat (limited to 'src/libsystemd-bus')
-rw-r--r-- | src/libsystemd-bus/bus-bloom.c | 93 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-bloom.h | 30 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-internal.c | 13 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-internal.h | 3 | ||||
-rw-r--r-- | src/libsystemd-bus/bus-kernel.c | 93 | ||||
-rw-r--r-- | src/libsystemd-bus/test-bus-kernel.c | 2 |
6 files changed, 222 insertions, 12 deletions
diff --git a/src/libsystemd-bus/bus-bloom.c b/src/libsystemd-bus/bus-bloom.c new file mode 100644 index 0000000000..cb65e47b4c --- /dev/null +++ b/src/libsystemd-bus/bus-bloom.c @@ -0,0 +1,93 @@ +/*-*- 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 "util.h" +#include "MurmurHash3.h" + +#include "bus-bloom.h" + +static inline void set_bit(uint64_t filter[], unsigned b) { + filter[b >> 6] |= 1ULL << (b & 63); +} + +void bloom_add_data(uint64_t filter[BLOOM_SIZE/8], const void *data, size_t n) { + uint16_t hash[8]; + unsigned k = 0; + + /* + * Our bloom filter has the following parameters: + * + * m=512 (bits in the filter) + * k=8 (hash functions) + * + * We calculate a single 128bit MurmurHash value of which we + * use 8 parts of 9 bits as individual hash functions. + * + */ + + MurmurHash3_x64_128(data, n, 0, hash); + + assert_cc(BLOOM_SIZE*8 == 512); + + for (k = 0; k < ELEMENTSOF(hash); k++) + set_bit(filter, hash[k] & 511); +} + +void bloom_add_pair(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b) { + size_t n; + char *c; + + assert(filter); + assert(a); + assert(b); + + n = strlen(a) + 1 + strlen(b); + c = alloca(n + 1); + strcpy(stpcpy(stpcpy(c, a), ":"), b); + + bloom_add_data(filter, c, n); +} + +void bloom_add_prefixes(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b, char sep) { + size_t n; + char *c, *p; + + assert(filter); + assert(a); + assert(b); + + n = strlen(a) + 1 + strlen(b); + c = alloca(n + 1); + + p = stpcpy(stpcpy(c, a), ":"); + strcpy(p, b); + + for (;;) { + char *e; + + e = strrchr(p, sep); + if (!e || e == p) + break; + + *e = 0; + bloom_add_data(filter, c, e - c); + } +} diff --git a/src/libsystemd-bus/bus-bloom.h b/src/libsystemd-bus/bus-bloom.h new file mode 100644 index 0000000000..1bf14a3331 --- /dev/null +++ b/src/libsystemd-bus/bus-bloom.h @@ -0,0 +1,30 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + 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 <sys/types.h> + +#define BLOOM_SIZE 64 + +void bloom_add_data(uint64_t filter[BLOOM_SIZE/8], const void *data, size_t n); +void bloom_add_pair(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b); +void bloom_add_prefixes(uint64_t filter[BLOOM_SIZE/8], const char *a, const char *b, char sep); diff --git a/src/libsystemd-bus/bus-internal.c b/src/libsystemd-bus/bus-internal.c index 3271354600..0e66f3d355 100644 --- a/src/libsystemd-bus/bus-internal.c +++ b/src/libsystemd-bus/bus-internal.c @@ -241,3 +241,16 @@ int bus_message_type_from_string(const char *s, uint8_t *u) { return 0; } + +const char *bus_message_type_to_string(uint8_t u) { + if (u == SD_BUS_MESSAGE_TYPE_SIGNAL) + return "signal"; + else if (u == SD_BUS_MESSAGE_TYPE_METHOD_CALL) + return "method_call"; + else if (u == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) + return "error"; + else if (u == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) + return "method_return"; + else + return NULL; +} diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 9a118f8a21..4babfac86d 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -150,8 +150,6 @@ struct sd_bus { uint64_t hello_serial; unsigned iteration_counter; - - uint64_t bloom_size; }; static inline void bus_unrefp(sd_bus **b) { @@ -191,6 +189,7 @@ bool namespace_simple_pattern(const char *pattern, const char *value); bool path_simple_pattern(const char *pattern, const char *value); int bus_message_type_from_string(const char *s, uint8_t *u); +const char *bus_message_type_to_string(uint8_t u); #define error_name_is_valid interface_name_is_valid diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index 264c6994d9..f36f60e496 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -30,6 +30,7 @@ #include "bus-internal.h" #include "bus-message.h" #include "bus-kernel.h" +#include "bus-bloom.h" #define KDBUS_MSG_FOREACH_DATA(d, k) \ for ((d) = (k)->data; \ @@ -80,17 +81,83 @@ static void append_destination(struct kdbus_msg_data **d, const char *s, size_t *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); } -static void append_bloom(struct kdbus_msg_data **d, const void *p, size_t length) { +static void* append_bloom(struct kdbus_msg_data **d, size_t length) { + void *r; + assert(d); - assert(p); *d = ALIGN8_PTR(*d); (*d)->size = offsetof(struct kdbus_msg_data, data) + length; (*d)->type = KDBUS_MSG_BLOOM; - memcpy((*d)->data, p, length); + r = (*d)->data; *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); + + return r; +} + +static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) { + unsigned i; + int r; + + assert(m); + assert(bloom); + + memset(bloom, 0, BLOOM_SIZE); + + bloom_add_pair(bloom, "message-type", bus_message_type_to_string(m->header->type)); + + if (m->interface) + bloom_add_pair(bloom, "interface", m->interface); + if (m->member) + bloom_add_pair(bloom, "member", m->member); + if (m->path) { + bloom_add_pair(bloom, "path", m->path); + bloom_add_prefixes(bloom, "path-slash-prefix", m->path, '/'); + } + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + for (i = 0; i < 64; i++) { + char type; + const char *t; + char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")]; + char *e; + + r = sd_bus_message_peek_type(m, &type, NULL); + if (r < 0) + return r; + + if (type != SD_BUS_TYPE_STRING && + type != SD_BUS_TYPE_OBJECT_PATH && + type != SD_BUS_TYPE_SIGNATURE) + break; + + r = sd_bus_message_read_basic(m, type, &t); + if (r < 0) + return r; + + e = stpcpy(buf, "arg"); + if (i < 10) + *(e++) = '0' + i; + else { + *(e++) = '0' + (i / 10); + *(e++) = '0' + (i % 10); + } + + *e = 0; + bloom_add_pair(bloom, buf, t); + + strcpy(e, "-dot-prefix"); + bloom_add_prefixes(bloom, buf, t, '.'); + strcpy(e, "-slash-prefix"); + bloom_add_prefixes(bloom, buf, t, '/'); + } + + return 0; } static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { @@ -122,7 +189,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { sz += 3 * ALIGN8(offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec)); /* Add space for bloom filter */ - sz += ALIGN8(offsetof(struct kdbus_msg_data, data) + b->bloom_size); + sz += ALIGN8(offsetof(struct kdbus_msg_data, data) + BLOOM_SIZE); /* Add in well-known destination header */ if (well_known) { @@ -164,9 +231,13 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { void *p; /* For now, let's add a mask all bloom filter */ - p = alloca(b->bloom_size); - memset(p, 0xFF, b->bloom_size); - append_bloom(&d, p, b->bloom_size); + p = append_bloom(&d, BLOOM_SIZE); + r = bus_message_setup_bloom(m, p); + if (r < 0) { + free(m->kdbus); + m->kdbus = NULL; + return -r; + } } m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus; @@ -207,10 +278,12 @@ int bus_kernel_take_fd(sd_bus *b) { hello.conn_flags > 0xFFFFFFFFULL) return -ENOTSUP; + if (hello.bloom_size != BLOOM_SIZE) + return -ENOTSUP; + if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0) return -ENOMEM; - b->bloom_size = hello.bloom_size; b->is_kernel = true; b->bus_client = true; @@ -479,7 +552,9 @@ int bus_kernel_create(const char *name, char **s) { make->size = offsetof(struct kdbus_cmd_bus_make, name) + strlen(make->name) + 1; make->flags = KDBUS_ACCESS_WORLD | KDBUS_POLICY_OPEN; make->bus_flags = 0; - make->bloom_size = 16; + make->bloom_size = BLOOM_SIZE; + + assert_cc(BLOOM_SIZE % 8 == 0); p = strjoin("/dev/kdbus/", make->name, "/bus", NULL); if (!p) diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c index 2164daf690..5a5d9fc252 100644 --- a/src/libsystemd-bus/test-bus-kernel.c +++ b/src/libsystemd-bus/test-bus-kernel.c @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { printf("unique b: %s\n", ub); - r = sd_bus_emit_signal(a, "/foo", "waldo.com", "Piep", "s", "I am a string"); + 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"); assert_se(r >= 0); r = sd_bus_process(b, &m); |