mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-01-27 20:40:29 +01:00
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>
This commit is contained in:
parent
36cc4c547c
commit
0980e63aac
3 changed files with 192 additions and 1 deletions
168
bus/signals.c
168
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)
|
||||
|
|
@ -388,6 +402,25 @@ bus_match_rule_set_path (BusMatchRule *rule,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -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)
|
||||
|
|
@ -1611,6 +1676,17 @@ connection_is_primary_owner (DBusConnection *connection,
|
|||
return bus_service_get_primary_owners_connection (service) == 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,
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -3721,6 +3721,26 @@
|
|||
<entry>Matches messages which are sent from or to the given object. An example of a
|
||||
path match is path='/org/freedesktop/Hal/Manager'</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>path_prefix</literal></entry>
|
||||
<entry>An object path optionally ending in a slash</entry>
|
||||
<entry>
|
||||
<para>
|
||||
Matches messages which are sent from or to an
|
||||
object for which the object path is a prefix of
|
||||
the given value. Examples of matches are
|
||||
path_prefix='/org/Application/ObjectManager' or
|
||||
path_prefix='/org/Application/ContactObjects/'.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>
|
||||
This match key was added in version 0.15 of the
|
||||
D-Bus specification and implemented by the bus
|
||||
daemon in dbus 1.4.7 and later.
|
||||
</emphasis>
|
||||
</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>destination</literal></entry>
|
||||
<entry>A unique name (see <xref linkend="term-unique-name"/>)</entry>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue