chiark / gitweb /
sd-bus: add arrays of strings in the bloom filter
authorLennart Poettering <lennart@poettering.net>
Fri, 28 Nov 2014 16:44:05 +0000 (17:44 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 28 Nov 2014 19:29:44 +0000 (20:29 +0100)
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
src/libsystemd/sd-bus/test-bus-kernel-bloom.c

index 58f011f..aaf44e3 100644 (file)
@@ -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;
index 5ee6eea..071b7e0 100644 (file)
@@ -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;
 }