diff options
author | David Zeuthen <davidz@redhat.com> | 2011-03-08 10:32:34 -0500 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2011-04-07 14:06:05 +0100 |
commit | 0980e63aacf52201bdf913e706d8ea0accc22610 (patch) | |
tree | fb6315851d768da2851c473495c34d02f86bb8a5 /bus | |
parent | 36cc4c547cb21d8f754ba4b4ee4c1c4204fd84ce (diff) |
Add path_prefix match rule
Add a new path_prefix match rule that can be used for efficient
implementations of the org.freedesktop.DBus.ObjectManager interface
(see bug 34869).
https://bugs.freedesktop.org/show_bug.cgi?id=34870
Signed-off-by: David Zeuthen <davidz@redhat.com>
Diffstat (limited to 'bus')
-rw-r--r-- | bus/signals.c | 168 | ||||
-rw-r--r-- | bus/signals.h | 5 |
2 files changed, 172 insertions, 1 deletions
diff --git a/bus/signals.c b/bus/signals.c index 56a7d6c1..0d18dc6f 100644 --- a/bus/signals.c +++ b/bus/signals.c @@ -41,6 +41,7 @@ struct BusMatchRule char *sender; char *destination; char *path; + char *path_prefix; unsigned int *arg_lens; char **args; @@ -94,6 +95,7 @@ bus_match_rule_unref (BusMatchRule *rule) dbus_free (rule->sender); dbus_free (rule->destination); dbus_free (rule->path); + dbus_free (rule->path_prefix); dbus_free (rule->arg_lens); /* can't use dbus_free_string_array() since there @@ -206,6 +208,18 @@ match_rule_to_string (BusMatchRule *rule) goto nomem; } + if (rule->flags & BUS_MATCH_PATH_PREFIX) + { + if (_dbus_string_get_length (&str) > 0) + { + if (!_dbus_string_append (&str, ",")) + goto nomem; + } + + if (!_dbus_string_append_printf (&str, "path_prefix='%s'", rule->path_prefix)) + goto nomem; + } + if (rule->flags & BUS_MATCH_SENDER) { if (_dbus_string_get_length (&str) > 0) @@ -389,6 +403,25 @@ bus_match_rule_set_path (BusMatchRule *rule, } dbus_bool_t +bus_match_rule_set_path_prefix (BusMatchRule *rule, + const char *path_prefix) +{ + char *new; + + _dbus_assert (path_prefix != NULL); + + new = _dbus_strdup (path_prefix); + if (new == NULL) + return FALSE; + + rule->flags |= BUS_MATCH_PATH_PREFIX; + dbus_free (rule->path_prefix); + rule->path_prefix = new; + + return TRUE; +} + +dbus_bool_t bus_match_rule_set_arg (BusMatchRule *rule, int arg, const DBusString *value, @@ -1018,6 +1051,34 @@ bus_match_rule_parse (DBusConnection *matches_go_to, goto failed; } } + else if (strcmp (key, "path_prefix") == 0) + { + int path_prefix_len; + + if (rule->flags & BUS_MATCH_PATH_PREFIX) + { + dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, + "Key %s specified twice in match rule\n", key); + goto failed; + } + + path_prefix_len = len; + if (_dbus_string_ends_with_c_str (&tmp_str, "/")) + path_prefix_len--; + + if (!_dbus_validate_path (&tmp_str, 0, path_prefix_len)) + { + dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID, + "Path prefix '%s' is invalid\n", value); + goto failed; + } + + if (!bus_match_rule_set_path_prefix (rule, value)) + { + BUS_SET_OOM (error); + goto failed; + } + } else if (strcmp (key, "destination") == 0) { if (rule->flags & BUS_MATCH_DESTINATION) @@ -1349,6 +1410,10 @@ match_rule_equal (BusMatchRule *a, if ((a->flags & BUS_MATCH_PATH) && strcmp (a->path, b->path) != 0) return FALSE; + + if ((a->flags & BUS_MATCH_PATH_PREFIX) && + strcmp (a->path_prefix, b->path_prefix) != 0) + return FALSE; if ((a->flags & BUS_MATCH_INTERFACE) && strcmp (a->interface, b->interface) != 0) @@ -1612,6 +1677,17 @@ connection_is_primary_owner (DBusConnection *connection, } static dbus_bool_t +str_has_prefix (const char *str, const char *prefix) +{ + size_t prefix_len; + prefix_len = strlen (prefix); + if (strncmp (str, prefix, prefix_len) == 0) + return TRUE; + else + return FALSE; +} + +static dbus_bool_t match_rule_matches (BusMatchRule *rule, DBusConnection *sender, DBusConnection *addressed_recipient, @@ -1722,6 +1798,20 @@ match_rule_matches (BusMatchRule *rule, return FALSE; } + if (flags & BUS_MATCH_PATH_PREFIX) + { + const char *path; + + _dbus_assert (rule->path_prefix != NULL); + + path = dbus_message_get_path (message); + if (path == NULL) + return FALSE; + + if (!str_has_prefix (path, rule->path_prefix)) + return FALSE; + } + if (flags & BUS_MATCH_ARGS) { int i; @@ -2616,6 +2706,83 @@ test_path_matching (void) bus_match_rule_unref (rule); } +static const char* +path_prefix_should_match_message_1[] = { + "type='signal',path_prefix='/foo'", + "type='signal',path_prefix='/foo/'", + "type='signal',path_prefix='/foo/TheObjectManager'", + NULL +}; + +static const char* +path_prefix_should_not_match_message_1[] = { + "type='signal',path_prefix='/bar'", + "type='signal',path_prefix='/bar/'", + "type='signal',path_prefix='/bar/TheObjectManager'", + NULL +}; + +static const char* +path_prefix_should_match_message_2[] = { + "type='signal',path_prefix='/foo/TheObjectManager'", + "type='signal',path_prefix='/foo/TheObjectManager/'", + NULL +}; + +static const char* +path_prefix_should_not_match_message_2[] = { + NULL +}; + +static const char* +path_prefix_should_match_message_3[] = { + "type='signal',path_prefix='/foo/TheObjectManager'", + NULL +}; + +static const char* +path_prefix_should_not_match_message_3[] = { + "type='signal',path_prefix='/foo/TheObjectManager/'", + NULL +}; + +static void +test_matching_path_prefix (void) +{ + DBusMessage *message1; + DBusMessage *message2; + DBusMessage *message3; + + message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); + _dbus_assert (message1 != NULL); + if (!dbus_message_set_path (message1, "/foo/TheObjectManager")) + _dbus_assert_not_reached ("oom"); + + message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); + _dbus_assert (message2 != NULL); + if (!dbus_message_set_path (message2, "/foo/TheObjectManager/child_object")) + _dbus_assert_not_reached ("oom"); + + message3 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL); + _dbus_assert (message3 != NULL); + if (!dbus_message_set_path (message3, "/foo/TheObjectManagerOther")) + _dbus_assert_not_reached ("oom"); + + check_matching (message1, 1, + path_prefix_should_match_message_1, + path_prefix_should_not_match_message_1); + check_matching (message2, 2, + path_prefix_should_match_message_2, + path_prefix_should_not_match_message_2); + check_matching (message3, 3, + path_prefix_should_match_message_3, + path_prefix_should_not_match_message_3); + + dbus_message_unref (message3); + dbus_message_unref (message2); + dbus_message_unref (message1); +} + dbus_bool_t bus_signals_test (const DBusString *test_data_dir) { @@ -2632,6 +2799,7 @@ bus_signals_test (const DBusString *test_data_dir) test_equality (); test_matching (); test_path_matching (); + test_matching_path_prefix (); return TRUE; } diff --git a/bus/signals.h b/bus/signals.h index 4702b9e2..0053bd5d 100644 --- a/bus/signals.h +++ b/bus/signals.h @@ -37,7 +37,8 @@ typedef enum BUS_MATCH_SENDER = 1 << 3, BUS_MATCH_DESTINATION = 1 << 4, BUS_MATCH_PATH = 1 << 5, - BUS_MATCH_ARGS = 1 << 6 + BUS_MATCH_ARGS = 1 << 6, + BUS_MATCH_PATH_PREFIX = 1 << 7 } BusMatchFlags; BusMatchRule* bus_match_rule_new (DBusConnection *matches_go_to); @@ -56,6 +57,8 @@ dbus_bool_t bus_match_rule_set_destination (BusMatchRule *rule, const char *destination); dbus_bool_t bus_match_rule_set_path (BusMatchRule *rule, const char *path); +dbus_bool_t bus_match_rule_set_path_prefix (BusMatchRule *rule, + const char *path_prefix); dbus_bool_t bus_match_rule_set_arg (BusMatchRule *rule, int arg, const DBusString *value, |