From 1abe54d9a9292d746e5990843bbbc509984b7f2c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Nov 2014 17:44:05 +0100 Subject: sd-bus: add arrays of strings in the bloom filter Let's do this right from the beginning, to prepare ground for udev messages that most likely want to store list of strings (for device tags) in messages, and filter on them. --- src/libsystemd/sd-bus/bus-kernel.c | 77 ++++++++++++++++++--------- src/libsystemd/sd-bus/test-bus-kernel-bloom.c | 51 ++++++++++-------- 2 files changed, 82 insertions(+), 46 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 58f011ff86..aaf44e3e75 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -135,6 +135,32 @@ static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) { *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } +static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) { + char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")]; + char *e; + + assert(data); + assert(size > 0); + assert(i < 64); + assert(t); + + e = stpcpy(buf, "arg"); + if (i < 10) + *(e++) = '0' + (char) i; + else { + *(e++) = '0' + (char) (i / 10); + *(e++) = '0' + (char) (i % 10); + } + + *e = 0; + bloom_add_pair(data, size, n_hash, buf, t); + + strcpy(e, "-dot-prefix"); + bloom_add_prefixes(data, size, n_hash, buf, t, '.'); + strcpy(e, "-slash-prefix"); + bloom_add_prefixes(data, size, n_hash, buf, t, '/'); +} + static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) { void *data; unsigned i; @@ -164,39 +190,42 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter return r; for (i = 0; i < 64; i++) { + const char *t, *contents; 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); + r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) return r; - if (type != SD_BUS_TYPE_STRING && - type != SD_BUS_TYPE_OBJECT_PATH && - type != SD_BUS_TYPE_SIGNATURE) - break; + if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { - r = sd_bus_message_read_basic(m, type, &t); - if (r < 0) - return r; + /* The bloom filter includes simple strings of any kind */ + r = sd_bus_message_read_basic(m, type, &t); + if (r < 0) + return r; - e = stpcpy(buf, "arg"); - if (i < 10) - *(e++) = '0' + (char) i; - else { - *(e++) = '0' + (char) (i / 10); - *(e++) = '0' + (char) (i % 10); - } + add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); + } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) { - *e = 0; - bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t); + /* As well as array of simple strings of any kinds */ + r = sd_bus_message_enter_container(m, type, contents); + if (r < 0) + return r; + + while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0) + add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t); + if (r < 0) + return r; - strcpy(e, "-dot-prefix"); - bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '.'); - strcpy(e, "-slash-prefix"); - bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, buf, t, '/'); + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + } else + /* Stop adding to bloom filter as soon as we + * run into the first argument we cannot add + * to it. */ + break; } return 0; diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c index 5ee6eea0e8..071b7e0cf9 100644 --- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c +++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c @@ -32,6 +32,7 @@ static void test_one( const char *path, const char *interface, const char *member, + bool as_list, const char *arg0, const char *match, bool good) { @@ -76,7 +77,11 @@ static void test_one( assert_se(r >= 0); log_debug("signal"); - r = sd_bus_emit_signal(a, path, interface, member, "s", arg0); + + if (as_list) + r = sd_bus_emit_signal(a, path, interface, member, "as", 1, arg0); + else + r = sd_bus_emit_signal(a, path, interface, member, "s", arg0); assert_se(r >= 0); r = sd_bus_process(b, &m); @@ -89,27 +94,29 @@ static void test_one( int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo/tuut'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "interface='waldo.com'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "member='Piep'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "member='Pi_ep'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "arg0='foobar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "arg0='foo_bar'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false); - - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path='/foo/bar/waldo/quux'", false); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/foo/bar/waldo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/foo/bar'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/foo'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/'", true); - test_one("/foo/bar/waldo", "waldo.com", "Piep", "foobar", "path_namespace='/quux'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/tuut'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "interface='waldo.com'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Piep'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Pi_ep'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foobar'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foo_bar'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foo_bar'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false); + + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/quux'", false); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true); + test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false); return 0; } -- cgit v1.2.3-54-g00ecf