From: Lennart Poettering Date: Fri, 28 Nov 2014 16:44:05 +0000 (+0100) Subject: sd-bus: add arrays of strings in the bloom filter X-Git-Tag: v218~235 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=1abe54d9a9292d746e5990843bbbc509984b7f2c;hp=a6a6ac16030ea8683dfb1916d13a0b577bf3b512;ds=sidebyside 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. --- diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 58f011ff8..aaf44e3e7 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 5ee6eea0e..071b7e0cf 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; }