* [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry.
@ 2016-03-21 22:10 Andrew Zaborowski
2016-03-21 22:10 ` [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry Andrew Zaborowski
` (14 more replies)
0 siblings, 15 replies; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1533 bytes --]
This will be used for the get_nth_string_argument function in
dbus-message.c. There seems to be no other way to skip over an iterator
entry without knowing the data type.
---
ell/dbus-private.h | 1 +
ell/dbus-util.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 8322475..cfed4f7 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -77,6 +77,7 @@ bool _dbus1_iter_enter_variant(struct l_dbus_message_iter *iter,
struct l_dbus_message_iter *variant);
bool _dbus1_iter_enter_array(struct l_dbus_message_iter *iter,
struct l_dbus_message_iter *array);
+bool _dbus1_iter_skip_entry(struct l_dbus_message_iter *iter);
struct dbus_builder *_dbus1_builder_new(void *body, size_t body_size);
void _dbus1_builder_free(struct dbus_builder *builder);
diff --git a/ell/dbus-util.c b/ell/dbus-util.c
index 5ab4298..9d5b5af 100644
--- a/ell/dbus-util.c
+++ b/ell/dbus-util.c
@@ -805,6 +805,22 @@ bool _dbus1_iter_enter_array(struct l_dbus_message_iter *iter,
return true;
}
+bool _dbus1_iter_skip_entry(struct l_dbus_message_iter *iter)
+{
+ size_t len;
+ const char *sig_end;
+
+ sig_end = calc_len_next_item(iter->sig_start + iter->sig_pos,
+ iter->data, iter->pos, iter->len, &len);
+ if (!sig_end)
+ return false;
+
+ iter->pos += len;
+ iter->sig_pos = sig_end - iter->sig_start;
+
+ return true;
+}
+
struct dbus_builder {
struct l_string *signature;
void *body;
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 14:35 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 03/15] dbus: Add _dbus_message_get_nth_string_argument Andrew Zaborowski
` (13 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1376 bytes --]
This will be used for the get_nth_string_argument function in
dbus-message.c. There seems to be no other way to skip over an iterator
entry without knowing the data type.
---
ell/gvariant-private.h | 1 +
ell/gvariant-util.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/ell/gvariant-private.h b/ell/gvariant-private.h
index 1acac74..2a20feb 100644
--- a/ell/gvariant-private.h
+++ b/ell/gvariant-private.h
@@ -35,6 +35,7 @@ bool _gvariant_iter_enter_variant(struct l_dbus_message_iter *iter,
struct l_dbus_message_iter *variant);
bool _gvariant_iter_enter_array(struct l_dbus_message_iter *iter,
struct l_dbus_message_iter *array);
+bool _gvariant_iter_skip_entry(struct l_dbus_message_iter *iter);
bool _gvariant_valid_signature(const char *sig);
int _gvariant_get_alignment(const char *signature);
diff --git a/ell/gvariant-util.c b/ell/gvariant-util.c
index 7534509..1aaddc3 100644
--- a/ell/gvariant-util.c
+++ b/ell/gvariant-util.c
@@ -731,6 +731,16 @@ bool _gvariant_iter_enter_array(struct l_dbus_message_iter *iter,
start, item_size);
}
+bool _gvariant_iter_skip_entry(struct l_dbus_message_iter *iter)
+{
+ size_t size;
+
+ if (!next_item(iter, &size))
+ return false;
+
+ return true;
+}
+
struct dbus_builder {
struct l_string *signature;
void *body;
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 03/15] dbus: Add _dbus_message_get_nth_string_argument
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
2016-03-21 22:10 ` [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 14:35 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 04/15] dbus: Support 2+ arguments in l_dbus_message_get_error Andrew Zaborowski
` (12 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2467 bytes --]
We happen to need to access n-th argument specifically only if it is
of a string type in at least three places, so add this shortcut.
---
ell/dbus-message.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
ell/dbus-private.h | 2 ++
2 files changed, 47 insertions(+)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 5b83be7..d35b5a6 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -392,6 +392,51 @@ LIB_EXPORT void l_dbus_message_unref(struct l_dbus_message *message)
l_free(message);
}
+const char *_dbus_message_get_nth_string_argument(
+ struct l_dbus_message *message, int n)
+{
+ struct l_dbus_message_iter iter;
+ const char *signature, *value;
+ void *body;
+ size_t size;
+ char type;
+ bool (*skip_entry)(struct l_dbus_message_iter *);
+ bool (*get_basic)(struct l_dbus_message_iter *, char, void *);
+
+ signature = l_dbus_message_get_signature(message);
+ body = _dbus_message_get_body(message, &size);
+
+ if (!signature)
+ return NULL;
+
+ if (_dbus_message_is_gvariant(message)) {
+ if (!_gvariant_iter_init(&iter, message, signature, NULL,
+ body, size))
+ return NULL;
+
+ skip_entry = _gvariant_iter_skip_entry;
+ get_basic = _gvariant_iter_next_entry_basic;
+ } else {
+ _dbus1_iter_init(&iter, message, signature, NULL, body, size);
+
+ skip_entry = _dbus1_iter_skip_entry;
+ get_basic = _dbus1_iter_next_entry_basic;
+ }
+
+ while (n--)
+ if (!skip_entry(&iter))
+ return NULL;
+
+ type = l_dbus_message_iter_get_type(&iter);
+ if (!strchr("sog", type))
+ return NULL;
+
+ if (!get_basic(&iter, type, &value))
+ return NULL;
+
+ return value;
+}
+
static bool message_iter_next_entry_valist(struct l_dbus_message_iter *orig,
va_list args)
{
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index cfed4f7..607fdf4 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -115,6 +115,8 @@ enum dbus_message_type _dbus_message_get_type(struct l_dbus_message *message);
const char * _dbus_message_get_type_as_string(struct l_dbus_message *message);
uint8_t _dbus_message_get_version(struct l_dbus_message *message);
uint8_t _dbus_message_get_endian(struct l_dbus_message *message);
+const char *_dbus_message_get_nth_string_argument(
+ struct l_dbus_message *message, int n);
struct l_dbus_message *_dbus_message_new_method_call(uint8_t version,
const char *destination,
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 04/15] dbus: Support 2+ arguments in l_dbus_message_get_error
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
2016-03-21 22:10 ` [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry Andrew Zaborowski
2016-03-21 22:10 ` [PATCH 03/15] dbus: Add _dbus_message_get_nth_string_argument Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 14:36 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 05/15] dbus: Fix _dbus_kernel_calculate_bloom for multiple arguments Andrew Zaborowski
` (11 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1281 bytes --]
Error messages may have any number of arguments, the first one is still
the error string if it's a string.
---
ell/dbus-message.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index d35b5a6..0b412b2 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1101,7 +1101,6 @@ error:
LIB_EXPORT bool l_dbus_message_get_error(struct l_dbus_message *message,
const char **name, const char **text)
{
- struct l_dbus_message_iter iter;
struct dbus_header *hdr;
const char *str;
@@ -1116,17 +1115,11 @@ LIB_EXPORT bool l_dbus_message_get_error(struct l_dbus_message *message,
if (!message->signature)
return false;
- if (strcmp(message->signature, "s"))
+ if (message->signature[0] != 's')
return false;
- if (_dbus_message_is_gvariant(message))
- _gvariant_iter_init(&iter, message, message->signature, NULL,
- message->body, message->body_size);
- else
- _dbus1_iter_init(&iter, message, message->signature, NULL,
- message->body, message->body_size);
-
- if (!message_iter_next_entry(&iter, &str))
+ str = _dbus_message_get_nth_string_argument(message, 0);
+ if (!str)
return false;
if (!message->error_name)
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 05/15] dbus: Fix _dbus_kernel_calculate_bloom for multiple arguments.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (2 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 04/15] dbus: Support 2+ arguments in l_dbus_message_get_error Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 14:39 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 06/15] dbus: Add message filter logic in dbus-filter.c Andrew Zaborowski
` (10 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2503 bytes --]
It seems that l_dbus_message_iter_get_type can't be used to get the
value of a single argument and be called repeatedly, it might crash if
the number and types of call arguments don't match the message arguments.
Add a comment explaining why arguments after first non-string argument
are not considered.
---
ell/dbus-message.c | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 0b412b2..a7c9699 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1419,6 +1419,7 @@ bool _dbus_kernel_calculate_bloom(struct l_dbus_message *message,
struct l_dbus_message_iter iter;
uint8_t argn;
char buf[256];
+ bool (*get_basic)(struct l_dbus_message_iter *, char, void *);
/* The string "interface:" suffixed by the interface name */
attr = l_dbus_message_get_interface(message);
@@ -1462,17 +1463,38 @@ bool _dbus_kernel_calculate_bloom(struct l_dbus_message *message,
body = _dbus_message_get_body(message, &body_size);
- if (_dbus_message_is_gvariant(message))
- _gvariant_iter_init(&iter, message, signature, NULL,
- body, body_size);
- else
+ if (_dbus_message_is_gvariant(message)) {
+ if (!_gvariant_iter_init(&iter, message, signature, NULL,
+ body, body_size))
+ return false;
+
+ get_basic = _gvariant_iter_next_entry_basic;
+ } else {
_dbus1_iter_init(&iter, message, signature, NULL,
- body, body_size);
+ body, body_size);
+
+ get_basic = _dbus1_iter_next_entry_basic;
+ }
argn = 0;
+ /*
+ * Stop iteration on the first non-string argument even though
+ * this may lead to legitimate signals not reaching peers that
+ * have set up seemingly correct kernel-side filters.
+ *
+ * "If the first argument of the message is a string,
+ * "arg0-slash-prefix" suffixed with the first argument, and also
+ * all prefixes of the argument (cut off at "/"), also prefixed
+ * with "arg0-slash-prefix".
+ *
+ * Similar for all further arguments that are strings up to 63,
+ * for the arguments and their "dot" and "slash" prefixes. On the
+ * first argument that is not a string, addition to the bloom
+ * filter should be stopped however."
+ */
while (*signature == 's' || *signature == 'o' || *signature == 'g') {
- if (!message_iter_next_entry(&iter, &attr))
+ if (!get_basic(&iter, *signature, &attr))
return false;
sprintf(buf, "arg%hhu", argn);
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 06/15] dbus: Add message filter logic in dbus-filter.c
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (3 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 05/15] dbus: Fix _dbus_kernel_calculate_bloom for multiple arguments Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 16:36 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 07/15] unit: Add dbus message filter tests Andrew Zaborowski
` (9 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 11606 bytes --]
This will be used for the public API for adding and removing signal
callbacks.
---
Makefile.am | 1 +
ell/dbus-filter.c | 351 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/dbus-private.h | 31 +++++
ell/dbus.h | 12 ++
4 files changed, 395 insertions(+)
create mode 100644 ell/dbus-filter.c
diff --git a/Makefile.am b/Makefile.am
index 256b163..7283a7e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -75,6 +75,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/dbus-message.c \
ell/dbus-util.c \
ell/dbus-service.c \
+ ell/dbus-filter.c \
ell/gvariant-private.h \
ell/gvariant-util.c \
ell/siphash-private.h \
diff --git a/ell/dbus-filter.c b/ell/dbus-filter.c
new file mode 100644
index 0000000..048f59a
--- /dev/null
+++ b/ell/dbus-filter.c
@@ -0,0 +1,351 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "util.h"
+#include "queue.h"
+#include "hashmap.h"
+#include "string.h"
+#include "dbus.h"
+#include "dbus-private.h"
+#include "gvariant-private.h"
+#include "private.h"
+
+#define NODE_TYPE_CALLBACK L_DBUS_MATCH_NONE
+
+struct filter_node {
+ enum l_dbus_match_type type;
+ union {
+ struct {
+ char *value;
+ struct filter_node *children;
+ bool remote_rule;
+ } match;
+ struct {
+ l_dbus_message_func_t func;
+ void *user_data;
+ } callback;
+ };
+ unsigned int id;
+ struct filter_node *next;
+};
+
+struct _dbus_filter {
+ struct l_dbus *dbus;
+ struct filter_node *root;
+ unsigned int signal_id;
+ unsigned int last_id;
+ const struct _dbus_filter_ops *driver;
+};
+
+static void filter_subtree_free(struct filter_node *node)
+{
+ struct filter_node *child, *next;
+
+ if (node->type == NODE_TYPE_CALLBACK) {
+ l_free(node);
+ return;
+ }
+
+ next = node->match.children;
+
+ l_free(node->match.value);
+ l_free(node);
+
+ while (next) {
+ child = next;
+ next = child->next;
+
+ filter_subtree_free(child);
+ }
+}
+
+static void dbus_filter_destroy(void *data)
+{
+ struct _dbus_filter *filter = data;
+
+ if (filter->root)
+ filter_subtree_free(filter->root);
+
+ l_free(filter);
+}
+
+static void filter_dispatch_match_recurse(struct _dbus_filter *filter,
+ struct filter_node *node,
+ struct l_dbus_message *message)
+{
+ const char *value = NULL;
+ struct filter_node *child;
+
+ switch ((int) node->type) {
+ case NODE_TYPE_CALLBACK:
+ node->callback.func(message, node->callback.user_data);
+ return;
+
+ case L_DBUS_MATCH_SENDER:
+ value = l_dbus_message_get_sender(message);
+ break;
+
+ case L_DBUS_MATCH_TYPE:
+ value = _dbus_message_get_type_as_string(message);
+ break;
+
+ case L_DBUS_MATCH_PATH:
+ value = l_dbus_message_get_path(message);
+ break;
+
+ case L_DBUS_MATCH_INTERFACE:
+ value = l_dbus_message_get_interface(message);
+ break;
+
+ case L_DBUS_MATCH_MEMBER:
+ value = l_dbus_message_get_member(message);
+ break;
+
+ case L_DBUS_MATCH_ARG0...(L_DBUS_MATCH_ARG0 + 63):
+ value = _dbus_message_get_nth_string_argument(message,
+ node->type - L_DBUS_MATCH_ARG0);
+ break;
+ }
+
+ if (!value)
+ return;
+
+ if (strcmp(value, node->match.value))
+ return;
+
+ for (child = node->match.children; child; child = child->next)
+ filter_dispatch_match_recurse(filter, child, message);
+}
+
+void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data)
+{
+ struct _dbus_filter *filter = user_data;
+
+ filter_dispatch_match_recurse(filter, filter->root, message);
+}
+
+struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
+ const struct _dbus_filter_ops *driver)
+{
+ struct _dbus_filter *filter;
+
+ filter = l_new(struct _dbus_filter, 1);
+
+ filter->dbus = dbus;
+ filter->driver = driver;
+
+ if (!filter->driver->skip_register)
+ filter->signal_id = l_dbus_register(dbus, _dbus_filter_dispatch,
+ filter,
+ dbus_filter_destroy);
+
+ return filter;
+}
+
+void _dbus_filter_free(struct _dbus_filter *filter)
+{
+ if (!filter)
+ return;
+
+ if (!filter->driver->skip_register)
+ l_dbus_unregister(filter->dbus, filter->signal_id);
+ else
+ dbus_filter_destroy(filter);
+}
+
+static int condition_compare(const void *a, const void *b)
+{
+ const struct _dbus_filter_condition *condition_a = a, *condition_b = b;
+
+ return condition_a->type - condition_b->type;
+}
+
+unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
+ struct _dbus_filter_condition *rule,
+ int rule_len,
+ l_dbus_message_func_t signal_func,
+ void *user_data)
+{
+ struct filter_node **node_ptr = &filter->root;
+ struct filter_node *node;
+ struct filter_node *parent = filter->root;
+ bool remote_rule = false;
+ struct _dbus_filter_condition *condition, *end = rule + rule_len;
+
+ qsort(rule, rule_len, sizeof(*rule), condition_compare);
+
+ for (condition = rule; condition < end; condition++) {
+ /* See if this condition is already a child of the node */
+ while (*node_ptr) {
+ node = *node_ptr;
+
+ if (node->type == condition->type &&
+ !strcmp(node->match.value,
+ condition->value))
+ break;
+
+ node_ptr = &node->next;
+ }
+
+ /* Add one */
+ if (!*node_ptr) {
+ node = l_new(struct filter_node, 1);
+ node->type = condition->type;
+ node->match.value = l_strdup(condition->value);
+
+ *node_ptr = node;
+ }
+
+ node_ptr = &node->match.children;
+
+ parent = node;
+
+ /*
+ * Only have to call AddMatch if none of the parent nodes
+ * have yet created an AddMatch rule on the server.
+ */
+ remote_rule |= node->match.remote_rule;
+ }
+
+ node = l_new(struct filter_node, 1);
+ node->type = NODE_TYPE_CALLBACK;
+ node->callback.func = signal_func;
+ node->callback.user_data = user_data;
+ node->id = ++filter->last_id;
+ node->next = *node_ptr;
+
+ if (!remote_rule) {
+ if (!filter->driver->add_match(filter->dbus, node->id,
+ rule, rule_len)) {
+ l_free(node);
+ return 0;
+ }
+
+ parent->id = node->id;
+ parent->match.remote_rule = true;
+ }
+
+ *node_ptr = node;
+
+ return node->id;
+}
+
+static bool remove_recurse(struct _dbus_filter *filter,
+ struct filter_node **node, unsigned int id)
+{
+ struct filter_node *tmp;
+
+ for (; *node; node = &(*node)->next) {
+ if ((*node)->type == NODE_TYPE_CALLBACK && (*node)->id == id)
+ break;
+
+ if ((*node)->type != NODE_TYPE_CALLBACK &&
+ remove_recurse(filter, &(*node)->match.children,
+ id))
+ break;
+ }
+
+ if (!*node)
+ return false;
+
+ if ((*node)->type == NODE_TYPE_CALLBACK || !(*node)->match.children) {
+ tmp = *node;
+ *node = tmp->next;
+
+ if (tmp->match.remote_rule)
+ filter->driver->remove_match(filter->dbus, tmp->id);
+
+ filter_subtree_free(tmp);
+ }
+
+ return true;
+}
+
+bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id)
+{
+ return remove_recurse(filter, &filter->root, id);
+}
+
+char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
+ int rule_len)
+{
+ struct l_string *str = l_string_new(63);
+ char *key, arg_buf[6];
+ const char *value, *endp;
+
+ for (; rule_len; rule++, rule_len--) {
+ switch ((int) rule->type) {
+ case L_DBUS_MATCH_SENDER:
+ key = "sender";
+ break;
+ case L_DBUS_MATCH_TYPE:
+ key = "type";
+ break;
+ case L_DBUS_MATCH_PATH:
+ key = "path";
+ break;
+ case L_DBUS_MATCH_INTERFACE:
+ key = "interface";
+ break;
+ case L_DBUS_MATCH_MEMBER:
+ key = "member";
+ break;
+ case L_DBUS_MATCH_ARG0...(L_DBUS_MATCH_ARG0 + 63):
+ key = arg_buf;
+ snprintf(arg_buf, sizeof(arg_buf), "arg%i",
+ rule->type - L_DBUS_MATCH_ARG0);
+ break;
+ default:
+ l_string_free(str, true);
+ return NULL;
+ }
+
+ l_string_append(str, key);
+ l_string_append(str, "='");
+
+ /* We only need to escape single-quotes in the values */
+ value = rule->value;
+
+ while ((endp = strchr(value, '\''))) {
+ l_string_append_fixed(str, value, endp - value);
+ l_string_append(str, "'\\''");
+
+ value = endp + 1;
+ }
+
+ l_string_append(str, value);
+ l_string_append_c(str, '\'');
+
+ if (rule_len > 1)
+ l_string_append_c(str, ',');
+ }
+
+ return l_string_free(str, false);
+}
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 607fdf4..d4a4782 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -64,6 +64,9 @@ struct _dbus_property;
struct l_dbus_message_iter;
struct l_dbus_message;
struct l_dbus;
+struct _dbus_filter;
+struct _dbus_filter_condition;
+struct _dbus_filter_ops;
void _dbus1_iter_init(struct l_dbus_message_iter *iter,
struct l_dbus_message *message,
@@ -241,6 +244,34 @@ uint8_t _dbus_get_version(struct l_dbus *dbus);
int _dbus_get_fd(struct l_dbus *dbus);
struct _dbus_object_tree *_dbus_get_tree(struct l_dbus *dbus);
+struct _dbus_filter_condition {
+ enum l_dbus_match_type type;
+ const char *value;
+};
+
+struct _dbus_filter_ops {
+ bool skip_register;
+ bool (*add_match)(struct l_dbus *bus, unsigned int id,
+ const struct _dbus_filter_condition *rule,
+ int rule_len);
+ bool (*remove_match)(struct l_dbus *bus, unsigned int id);
+};
+
+struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
+ const struct _dbus_filter_ops *driver);
+void _dbus_filter_free(struct _dbus_filter *filter);
+
+unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
+ struct _dbus_filter_condition *rule,
+ int rule_len,
+ l_dbus_message_func_t signal_func,
+ void *user_data);
+bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id);
+
+char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
+ int rule_len);
+void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data);
+
struct dbus1_filter_data;
void _dbus1_filter_format_match(struct dbus1_filter_data *data, char *rule,
diff --git a/ell/dbus.h b/ell/dbus.h
index c8fdec1..083f2ff 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -42,6 +42,18 @@ enum l_dbus_bus {
L_DBUS_SESSION_BUS,
};
+enum l_dbus_match_type {
+ L_DBUS_MATCH_NONE = 0,
+ L_DBUS_MATCH_TYPE,
+ L_DBUS_MATCH_SENDER,
+ L_DBUS_MATCH_PATH,
+ L_DBUS_MATCH_INTERFACE,
+ L_DBUS_MATCH_MEMBER,
+ L_DBUS_MATCH_ARG0,
+};
+
+#define L_DBUS_MATCH_ARGUMENT(i) (L_DBUS_MATCH_ARG0 + (i))
+
struct l_dbus;
struct l_dbus_interface;
struct l_dbus_message_builder;
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 07/15] unit: Add dbus message filter tests.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (4 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 06/15] dbus: Add message filter logic in dbus-filter.c Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 16:37 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 08/15] dbus-filter: Name owner change tracking support Andrew Zaborowski
` (8 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 7676 bytes --]
---
unit/test-dbus-watch.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 229 insertions(+)
diff --git a/unit/test-dbus-watch.c b/unit/test-dbus-watch.c
index 104f432..684ac34 100644
--- a/unit/test-dbus-watch.c
+++ b/unit/test-dbus-watch.c
@@ -33,6 +33,7 @@
#include <ell/ell.h>
#include "ell/dbus-private.h"
+#include "ell/private.h"
#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
@@ -245,6 +246,230 @@ static void test_disconnect_watch(const void *test_data)
_dbus1_filter_data_destroy(data);
}
+static void test_rule_to_str(const void *test_data)
+{
+ static const struct _dbus_filter_condition rule1[] = {
+ { L_DBUS_MATCH_TYPE, "signal" },
+ { L_DBUS_MATCH_SENDER, DBUS_SERVICE_DBUS },
+ { L_DBUS_MATCH_PATH, DBUS_PATH_DBUS },
+ { L_DBUS_MATCH_INTERFACE, DBUS_INTERFACE_DBUS },
+ { L_DBUS_MATCH_MEMBER, "NameOwnerChanged" },
+ { L_DBUS_MATCH_ARGUMENT(0), ":1.101" }
+ };
+ static const char *expected1 = "type='signal',"
+ "sender='org.freedesktop.DBus',"
+ "path='/org/freedesktop/DBus',"
+ "interface='org.freedesktop.DBus',"
+ "member='NameOwnerChanged',"
+ "arg0=':1.101'";
+ static const struct _dbus_filter_condition rule2[] = {
+ { L_DBUS_MATCH_ARGUMENT(0), "'" },
+ { L_DBUS_MATCH_ARGUMENT(1), "\\" },
+ { L_DBUS_MATCH_ARGUMENT(2), "," },
+ { L_DBUS_MATCH_ARGUMENT(3), "\\\\" }
+ };
+ static const char *expected2 =
+ "arg0=''\\''',arg1='\\',arg2=',',arg3='\\\\'";
+ char *str;
+
+ str = _dbus_filter_rule_to_str(rule1, L_ARRAY_SIZE(rule1));
+ assert(str && !strcmp(str, expected1));
+ l_free(str);
+
+ str = _dbus_filter_rule_to_str(rule2, L_ARRAY_SIZE(rule2));
+ assert(str && !strcmp(str, expected2));
+ l_free(str);
+}
+
+struct l_dbus {
+};
+
+struct filter_test_state {
+ struct l_dbus dbus;
+ const struct _dbus_filter_condition *expected_rule;
+ int expected_rule_len;
+ unsigned int expected_id, new_id;
+ int calls[4];
+};
+
+static void rule_compare(const struct _dbus_filter_condition *a, int len_a,
+ const struct _dbus_filter_condition *b, int len_b)
+{
+ int i, j;
+ bool matched[len_a];
+
+ assert(len_a == len_b);
+
+ for (i = 0; i < len_a; i++)
+ matched[i] = false;
+
+ for (i = 0; i < len_a; i++) {
+ for (j = 0; j < len_a; j++)
+ if (!matched[j] && a[i].type == b[j].type &&
+ !strcmp(a[i].value, b[j].value))
+ break;
+
+ assert(j < len_a);
+ matched[j] = true;
+ }
+}
+
+static bool test_add_match(struct l_dbus *dbus, unsigned int id,
+ const struct _dbus_filter_condition *rule,
+ int rule_len)
+{
+ struct filter_test_state *test =
+ container_of(dbus, struct filter_test_state, dbus);
+
+ assert(test->expected_rule);
+
+ rule_compare(test->expected_rule, test->expected_rule_len,
+ rule, rule_len);
+
+ test->new_id = id;
+ test->expected_rule = NULL;
+
+ return true;
+}
+
+static bool test_remove_match(struct l_dbus *dbus, unsigned int id)
+{
+ struct filter_test_state *test =
+ container_of(dbus, struct filter_test_state, dbus);
+
+ assert(test->expected_id == id && id);
+
+ test->expected_id = 0;
+
+ return true;
+}
+
+static void test_rule1_cb(struct l_dbus_message *message, void *user_data)
+{
+ struct filter_test_state *test = user_data;
+
+ test->calls[0]++;
+}
+
+static void test_rule2_cb(struct l_dbus_message *message, void *user_data)
+{
+ struct filter_test_state *test = user_data;
+
+ test->calls[1]++;
+}
+
+static void test_rule3_cb(struct l_dbus_message *message, void *user_data)
+{
+ struct filter_test_state *test = user_data;
+
+ test->calls[2]++;
+}
+
+static void test_rule4_cb(struct l_dbus_message *message, void *user_data)
+{
+ struct filter_test_state *test = user_data;
+
+ test->calls[3]++;
+}
+
+static void test_filter_tree(const void *test_data)
+{
+ struct _dbus_filter *filter;
+ struct filter_test_state test = { .calls = { 0, 0, 0, 0 } };
+ static const struct _dbus_filter_ops filter_ops = {
+ .skip_register = true,
+ .add_match = test_add_match,
+ .remove_match = test_remove_match,
+ };
+ static struct _dbus_filter_condition rule123[] = {
+ { L_DBUS_MATCH_TYPE, "signal" },
+ { L_DBUS_MATCH_SENDER, DBUS_SERVICE_DBUS },
+ { L_DBUS_MATCH_PATH, DBUS_PATH_DBUS },
+ { L_DBUS_MATCH_INTERFACE, DBUS_INTERFACE_DBUS },
+ { L_DBUS_MATCH_MEMBER, "NameOwnerChanged" },
+ { L_DBUS_MATCH_ARGUMENT(0), ":1.101" }
+ };
+ static struct _dbus_filter_condition rule4[] = {
+ { L_DBUS_MATCH_TYPE, "signal" },
+ { L_DBUS_MATCH_SENDER, "foo" },
+ };
+ unsigned int id1, id2, id3, id4, internal_id1, internal_id4;
+ struct l_dbus_message *message;
+
+ filter = _dbus_filter_new(&test.dbus, &filter_ops);
+ assert(filter);
+
+ test.expected_rule = rule123;
+ test.expected_rule_len = 2;
+ id1 = _dbus_filter_add_rule(filter, rule123, 2, test_rule1_cb, &test);
+ assert(id1);
+ assert(!test.expected_rule);
+ internal_id1 = test.new_id;
+
+ id2 = _dbus_filter_add_rule(filter, rule123, 4, test_rule2_cb, &test);
+ id3 = _dbus_filter_add_rule(filter, rule123, 6, test_rule3_cb, &test);
+ assert(id2 && id3 && id2 != id1 && id3 != id1 && id3 != id2);
+
+ test.expected_rule = rule4;
+ test.expected_rule_len = 2;
+ id4 = _dbus_filter_add_rule(filter, rule4, 2, test_rule4_cb, &test);
+ assert(id4 && id4 != id1 && id4 != id2 && id4 != id3);
+ assert(!test.expected_rule);
+ internal_id4 = test.new_id;
+
+ assert(test.calls[0] == 0 && test.calls[1] == 0 &&
+ test.calls[2] == 0 && test.calls[3] == 0);
+
+ message = _dbus_message_new_signal(2, DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged");
+ l_dbus_message_set_arguments(message, "sss", ":1.101", "", ":1.101");
+ _dbus_message_set_sender(message, DBUS_SERVICE_DBUS);
+ _dbus_filter_dispatch(message, filter);
+ l_dbus_message_unref(message);
+
+ message = _dbus_message_new_signal(2, DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged");
+ l_dbus_message_set_arguments(message, "");
+ _dbus_message_set_sender(message, DBUS_SERVICE_DBUS);
+ _dbus_filter_dispatch(message, filter);
+ l_dbus_message_unref(message);
+
+ message = _dbus_message_new_signal(2, DBUS_PATH_DBUS, "foo", "Bar");
+ l_dbus_message_set_arguments(message, "");
+ _dbus_message_set_sender(message, DBUS_SERVICE_DBUS);
+ _dbus_filter_dispatch(message, filter);
+
+ _dbus_message_set_sender(message, "foo");
+ _dbus_filter_dispatch(message, filter);
+
+ _dbus_message_set_sender(message, "bar");
+ _dbus_filter_dispatch(message, filter);
+ l_dbus_message_unref(message);
+
+ assert(test.calls[0] == 3 && test.calls[1] == 2 &&
+ test.calls[2] == 1 && test.calls[3] == 1);
+
+ test.expected_id = 0;
+ assert(_dbus_filter_remove_rule(filter, id2));
+
+ assert(_dbus_filter_remove_rule(filter, id1));
+
+ test.expected_id = internal_id4;
+ assert(_dbus_filter_remove_rule(filter, id4));
+ assert(!test.expected_id);
+
+ test.expected_id = internal_id1;
+ assert(_dbus_filter_remove_rule(filter, id3));
+ assert(!test.expected_id);
+
+ _dbus_filter_free(filter);
+
+ assert(test.calls[0] == 3 && test.calls[1] == 2 &&
+ test.calls[2] == 1 && test.calls[3] == 1);
+}
+
int main(int argc, char *argv[])
{
l_test_init(&argc, &argv);
@@ -264,5 +489,9 @@ int main(int argc, char *argv[])
l_test_add("DBus disconnect watch", test_disconnect_watch,
&disconnect_test);
+ l_test_add("_dbus_filter_rule_to_str", test_rule_to_str, NULL);
+
+ l_test_add("DBus filter tree", test_filter_tree, NULL);
+
return l_test_run();
}
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 08/15] dbus-filter: Name owner change tracking support.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (5 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 07/15] unit: Add dbus message filter tests Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 17:28 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 09/15] dbus: Classic dbus filter_ops implementation Andrew Zaborowski
` (7 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 8398 bytes --]
This is needed because incoming message callbacks normally care what
Well-known Bus Name the message comes from but the sender field of the
message normally stores unique bus names in classic dbus. The
Well-known names may be re-assigned to different unique names while the
rule is in place.
---
ell/dbus-filter.c | 183 ++++++++++++++++++++++++++++++++++++++++++-----------
ell/dbus-private.h | 4 ++
2 files changed, 151 insertions(+), 36 deletions(-)
diff --git a/ell/dbus-filter.c b/ell/dbus-filter.c
index 048f59a..59059cb 100644
--- a/ell/dbus-filter.c
+++ b/ell/dbus-filter.c
@@ -62,6 +62,12 @@ struct _dbus_filter {
unsigned int signal_id;
unsigned int last_id;
const struct _dbus_filter_ops *driver;
+ struct l_hashmap *unique_names;
+};
+
+struct unique_name_record {
+ int ref_count;
+ char *unique_name;
};
static void filter_subtree_free(struct filter_node *node)
@@ -86,6 +92,14 @@ static void filter_subtree_free(struct filter_node *node)
}
}
+static void unique_name_record_free(void *data)
+{
+ struct unique_name_record *name_rec = data;
+
+ l_free(name_rec->unique_name);
+ l_free(name_rec);
+}
+
static void dbus_filter_destroy(void *data)
{
struct _dbus_filter *filter = data;
@@ -93,6 +107,10 @@ static void dbus_filter_destroy(void *data)
if (filter->root)
filter_subtree_free(filter->root);
+ if (filter->unique_names)
+ l_hashmap_destroy(filter->unique_names,
+ unique_name_record_free);
+
l_free(filter);
}
@@ -101,6 +119,8 @@ static void filter_dispatch_match_recurse(struct _dbus_filter *filter,
struct l_dbus_message *message)
{
const char *value = NULL;
+ const char *alt_value = NULL;
+ const struct unique_name_record *name_rec;
struct filter_node *child;
switch ((int) node->type) {
@@ -137,7 +157,16 @@ static void filter_dispatch_match_recurse(struct _dbus_filter *filter,
if (!value)
return;
- if (strcmp(value, node->match.value))
+ if (node->type == L_DBUS_MATCH_SENDER && filter->unique_names) {
+ name_rec = l_hashmap_lookup(filter->unique_names,
+ node->match.value);
+
+ if (name_rec)
+ alt_value = name_rec->unique_name;
+ }
+
+ if (strcmp(value, node->match.value) &&
+ (!alt_value || strcmp(value, alt_value)))
return;
for (child = node->match.children; child; child = child->next)
@@ -151,6 +180,26 @@ void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data)
filter_dispatch_match_recurse(filter, filter->root, message);
}
+void _dbus_filter_name_owner_notify(struct _dbus_filter *filter,
+ const char *name, const char *owner)
+{
+ struct unique_name_record *name_rec;
+
+ if (!filter)
+ return;
+
+ if (_dbus_parse_unique_name(name, NULL))
+ return;
+
+ name_rec = l_hashmap_lookup(filter->unique_names, name);
+ if (!name_rec)
+ return;
+
+ l_free(name_rec->unique_name);
+
+ name_rec->unique_name = (owner && *owner) ? l_strdup(owner) : NULL;
+}
+
struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
const struct _dbus_filter_ops *driver)
{
@@ -166,6 +215,9 @@ struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
filter,
dbus_filter_destroy);
+ if (filter->driver->get_name_owner)
+ filter->unique_names = l_hashmap_string_new();
+
return filter;
}
@@ -180,6 +232,54 @@ void _dbus_filter_free(struct _dbus_filter *filter)
dbus_filter_destroy(filter);
}
+static bool filter_add_bus_name(struct _dbus_filter *filter, const char *name)
+{
+ struct unique_name_record *name_rec;
+
+ if (!filter->unique_names)
+ return true;
+
+ if (_dbus_parse_unique_name(name, NULL))
+ return true;
+
+ if (!_dbus_valid_bus_name(name))
+ return false;
+
+ name_rec = l_hashmap_lookup(filter->unique_names, name);
+ if (!name_rec) {
+ name_rec = l_new(struct unique_name_record, 1);
+
+ l_hashmap_insert(filter->unique_names, name, name_rec);
+
+ filter->driver->get_name_owner(filter->dbus, name);
+ }
+
+ name_rec->ref_count++;
+
+ return true;
+}
+
+static void filter_remove_bus_name(struct _dbus_filter *filter,
+ const char *name)
+{
+ struct unique_name_record *name_rec;
+
+ if (!filter->unique_names)
+ return;
+
+ if (_dbus_parse_unique_name(name, NULL))
+ return;
+
+ name_rec = l_hashmap_lookup(filter->unique_names, name);
+
+ if (--name_rec->ref_count)
+ return;
+
+ l_hashmap_remove(filter->unique_names, name);
+
+ unique_name_record_free(name_rec);
+}
+
static int condition_compare(const void *a, const void *b)
{
const struct _dbus_filter_condition *condition_a = a, *condition_b = b;
@@ -187,6 +287,40 @@ static int condition_compare(const void *a, const void *b)
return condition_a->type - condition_b->type;
}
+static bool remove_recurse(struct _dbus_filter *filter,
+ struct filter_node **node, unsigned int id)
+{
+ struct filter_node *tmp;
+
+ for (; *node; node = &(*node)->next) {
+ if ((*node)->type == NODE_TYPE_CALLBACK && (*node)->id == id)
+ break;
+
+ if ((*node)->type != NODE_TYPE_CALLBACK &&
+ remove_recurse(filter, &(*node)->match.children,
+ id))
+ break;
+ }
+
+ if (!*node)
+ return false;
+
+ if ((*node)->type == NODE_TYPE_CALLBACK || !(*node)->match.children) {
+ tmp = *node;
+ *node = tmp->next;
+
+ if (tmp->match.remote_rule)
+ filter->driver->remove_match(filter->dbus, tmp->id);
+
+ if (tmp->type == L_DBUS_MATCH_SENDER)
+ filter_remove_bus_name(filter, tmp->match.value);
+
+ filter_subtree_free(tmp);
+ }
+
+ return true;
+}
+
unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
struct _dbus_filter_condition *rule,
int rule_len,
@@ -221,6 +355,9 @@ unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
node->match.value = l_strdup(condition->value);
*node_ptr = node;
+
+ if (node->type == L_DBUS_MATCH_SENDER)
+ filter_add_bus_name(filter, node->match.value);
}
node_ptr = &node->match.children;
@@ -241,51 +378,25 @@ unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
node->id = ++filter->last_id;
node->next = *node_ptr;
+ *node_ptr = node;
+
if (!remote_rule) {
if (!filter->driver->add_match(filter->dbus, node->id,
- rule, rule_len)) {
- l_free(node);
- return 0;
- }
+ rule, rule_len))
+ goto err;
parent->id = node->id;
parent->match.remote_rule = true;
}
- *node_ptr = node;
-
return node->id;
-}
-
-static bool remove_recurse(struct _dbus_filter *filter,
- struct filter_node **node, unsigned int id)
-{
- struct filter_node *tmp;
- for (; *node; node = &(*node)->next) {
- if ((*node)->type == NODE_TYPE_CALLBACK && (*node)->id == id)
- break;
-
- if ((*node)->type != NODE_TYPE_CALLBACK &&
- remove_recurse(filter, &(*node)->match.children,
- id))
- break;
- }
+err:
+ /* Remove all the nodes we may have added */
+ node->id = (unsigned int) -1;
+ remove_recurse(filter, &filter->root, node->id);
- if (!*node)
- return false;
-
- if ((*node)->type == NODE_TYPE_CALLBACK || !(*node)->match.children) {
- tmp = *node;
- *node = tmp->next;
-
- if (tmp->match.remote_rule)
- filter->driver->remove_match(filter->dbus, tmp->id);
-
- filter_subtree_free(tmp);
- }
-
- return true;
+ return 0;
}
bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index d4a4782..d635cc0 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -255,6 +255,7 @@ struct _dbus_filter_ops {
const struct _dbus_filter_condition *rule,
int rule_len);
bool (*remove_match)(struct l_dbus *bus, unsigned int id);
+ bool (*get_name_owner)(struct l_dbus *bus, const char *name);
};
struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
@@ -270,7 +271,10 @@ bool _dbus_filter_remove_rule(struct _dbus_filter *filter, unsigned int id);
char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
int rule_len);
+
void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data);
+void _dbus_filter_name_owner_notify(struct _dbus_filter *filter,
+ const char *name, const char *owner);
struct dbus1_filter_data;
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 09/15] dbus: Classic dbus filter_ops implementation.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (6 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 08/15] dbus-filter: Name owner change tracking support Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 17:41 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 10/15] dbus: kdbus " Andrew Zaborowski
` (6 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 6028 bytes --]
For the name owner tracking I decided to subscribe to all name
owner changes instead of adding separate rules for every name because
in some scenarios that saves us cycles/memory and we don't have
to hold a list of IDs of every such rule so that we could remove them
when no longer needed.
---
ell/dbus.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 135 insertions(+)
diff --git a/ell/dbus.c b/ell/dbus.c
index 2ac9e58..52a9192 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -63,6 +63,7 @@ struct l_dbus_ops {
struct l_dbus_message *message);
struct l_dbus_message *(*recv_message)(struct l_dbus *bus);
void (*free)(struct l_dbus *bus);
+ struct _dbus_filter_ops filter_ops;
};
struct l_dbus {
@@ -87,6 +88,7 @@ struct l_dbus {
l_dbus_destroy_func_t debug_destroy;
void *debug_data;
struct _dbus_object_tree *tree;
+ struct _dbus_filter *filter;
const struct l_dbus_ops *driver;
};
@@ -103,6 +105,7 @@ struct l_dbus_classic {
struct l_dbus super;
void *auth_command;
enum auth_state auth_state;
+ struct l_hashmap *match_strings;
};
struct message_callback {
@@ -553,6 +556,7 @@ static void classic_free(struct l_dbus *dbus)
container_of(dbus, struct l_dbus_classic, super);
l_free(classic->auth_command);
+ l_hashmap_destroy(classic->match_strings, l_free);
l_free(classic);
}
@@ -664,13 +668,132 @@ cmsg_fail:
return NULL;
}
+static bool classic_add_match(struct l_dbus *dbus, unsigned int id,
+ const struct _dbus_filter_condition *rule,
+ int rule_len)
+{
+ struct l_dbus_classic *classic =
+ container_of(dbus, struct l_dbus_classic, super);
+ char *match_str;
+ struct l_dbus_message *message;
+
+ match_str = _dbus_filter_rule_to_str(rule, rule_len);
+
+ l_hashmap_insert(classic->match_strings, L_UINT_TO_PTR(id), match_str);
+
+ message = l_dbus_message_new_method_call(dbus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ L_DBUS_INTERFACE_DBUS,
+ "AddMatch");
+
+ l_dbus_message_set_arguments(message, "s", match_str);
+
+ send_message(dbus, false, message, NULL, NULL, NULL);
+
+ return true;
+}
+
+static bool classic_remove_match(struct l_dbus *dbus, unsigned int id)
+{
+ struct l_dbus_classic *classic =
+ container_of(dbus, struct l_dbus_classic, super);
+ char *match_str = l_hashmap_remove(classic->match_strings,
+ L_UINT_TO_PTR(id));
+ struct l_dbus_message *message;
+
+ if (!match_str)
+ return false;
+
+ message = l_dbus_message_new_method_call(dbus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ L_DBUS_INTERFACE_DBUS,
+ "RemoveMatch");
+
+ l_dbus_message_set_arguments(message, "s", match_str);
+
+ send_message(dbus, false, message, NULL, NULL, NULL);
+
+ l_free(match_str);
+
+ return true;
+}
+
+struct get_name_owner_request {
+ struct l_dbus_message *message;
+ struct l_dbus *dbus;
+};
+
+static void get_name_owner_reply_cb(struct l_dbus_message *reply,
+ void *user_data)
+{
+ struct get_name_owner_request *req = user_data;
+ const char *name, *owner;
+
+ /* No name owner yet */
+ if (l_dbus_message_is_error(reply))
+ return;
+
+ /* Shouldn't happen */
+ if (!l_dbus_message_get_arguments(reply, "s", &owner))
+ return;
+
+ /* Shouldn't happen */
+ if (!l_dbus_message_get_arguments(req->message, "s", &name))
+ return;
+
+ _dbus_filter_name_owner_notify(req->dbus->filter, name, owner);
+}
+
+static bool classic_get_name_owner(struct l_dbus *bus, const char *name)
+{
+ struct get_name_owner_request *req;
+
+ /* Name resolution is not performed for DBUS_SERVICE_DBUS */
+ if (!strcmp(name, DBUS_SERVICE_DBUS))
+ return false;
+
+ req = l_new(struct get_name_owner_request, 1);
+ req->dbus = bus;
+ req->message = l_dbus_message_new_method_call(bus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ L_DBUS_INTERFACE_DBUS,
+ "GetNameOwner");
+
+ l_dbus_message_set_arguments(req->message, "s", name);
+
+ send_message(bus, false, req->message, get_name_owner_reply_cb,
+ req, l_free);
+
+ return true;
+}
+
static const struct l_dbus_ops classic_ops = {
.version = 1,
.send_message = classic_send_message,
.recv_message = classic_recv_message,
.free = classic_free,
+ .filter_ops = {
+ .add_match = classic_add_match,
+ .remove_match = classic_remove_match,
+ .get_name_owner = classic_get_name_owner,
+ },
};
+static void name_owner_changed_cb(struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus *dbus = user_data;
+ char *name, *old, *new;
+
+ if (!l_dbus_message_get_arguments(message, "sss", &name, &old, &new))
+ return;
+
+ _dbus_filter_name_owner_notify(dbus->filter, name, new);
+}
+
static struct l_dbus *setup_dbus1(int fd, const char *guid)
{
static const unsigned char creds = 0x00;
@@ -680,6 +803,13 @@ static struct l_dbus *setup_dbus1(int fd, const char *guid)
ssize_t written;
unsigned int i;
long flags;
+ static struct _dbus_filter_condition rule[] = {
+ { L_DBUS_MATCH_TYPE, "signal" },
+ { L_DBUS_MATCH_SENDER, DBUS_SERVICE_DBUS },
+ { L_DBUS_MATCH_PATH, DBUS_PATH_DBUS },
+ { L_DBUS_MATCH_INTERFACE, L_DBUS_INTERFACE_DBUS },
+ { L_DBUS_MATCH_MEMBER, "NameOwnerChanged" },
+ };
if (snprintf(uid, sizeof(uid), "%d", geteuid()) < 1) {
close(fd);
@@ -714,6 +844,8 @@ static struct l_dbus *setup_dbus1(int fd, const char *guid)
dbus = &classic->super;
dbus->driver = &classic_ops;
+ classic->match_strings = l_hashmap_new();
+
dbus_init(dbus, fd);
dbus->guid = l_strdup(guid);
@@ -726,6 +858,9 @@ static struct l_dbus *setup_dbus1(int fd, const char *guid)
l_io_set_read_handler(dbus->io, auth_read_handler, dbus, NULL);
l_io_set_write_handler(dbus->io, auth_write_handler, dbus, NULL);
+ _dbus_filter_add_rule(dbus->filter, rule, L_ARRAY_SIZE(rule),
+ name_owner_changed_cb, dbus);
+
return dbus;
}
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 10/15] dbus: kdbus filter_ops implementation.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (7 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 09/15] dbus: Classic dbus filter_ops implementation Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 17:51 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 11/15] linux: Update kdbus.h to current github version Andrew Zaborowski
` (5 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 15432 bytes --]
For the name owner tracking I decided to subscribe to all name
owner changes instead of adding separate rules for every name because
in some scenarios that saves us cycles/memory and we don't have
to hold a list of IDs of every such rule so that we could remove them
when no longer needed.
---
ell/dbus-kernel.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++-----
ell/dbus-private.h | 17 ++++-
ell/dbus.c | 151 +++++++++++++++++++++++++++++----------
3 files changed, 313 insertions(+), 57 deletions(-)
diff --git a/ell/dbus-kernel.c b/ell/dbus-kernel.c
index 8e4e552..eda756a 100644
--- a/ell/dbus-kernel.c
+++ b/ell/dbus-kernel.c
@@ -543,11 +543,16 @@ static int _dbus_kernel_make_message(struct kdbus_msg *kmsg,
}
int _dbus_kernel_recv(int fd, void *kdbus_pool,
- struct l_dbus_message **out_message)
+ l_dbus_message_func_t message_func,
+ _dbus_name_owner_change_func_t name_owner_change_func,
+ void *user_data)
{
struct kdbus_cmd_recv recv_cmd;
struct kdbus_msg *msg;
+ struct l_dbus_message *dbus_msg;
+ struct kdbus_item *item;
int r;
+ size_t min_size;
memset(&recv_cmd, 0, sizeof(recv_cmd));
@@ -559,9 +564,39 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
switch (msg->payload_type) {
case KDBUS_PAYLOAD_DBUS:
- r = _dbus_kernel_make_message(msg, out_message);
+ r = _dbus_kernel_make_message(msg, &dbus_msg);
+ if (!r)
+ message_func(dbus_msg, user_data);
break;
case KDBUS_PAYLOAD_KERNEL:
+ if (msg->size < sizeof(*msg) + KDBUS_ITEM_HEADER_SIZE) {
+ r = -EPROTONOSUPPORT;
+ break;
+ }
+
+ item = msg->items;
+
+ switch (item->type) {
+ case KDBUS_ITEM_NAME_ADD:
+ case KDBUS_ITEM_NAME_CHANGE:
+ case KDBUS_ITEM_NAME_REMOVE:
+ min_size = KDBUS_ITEM_SIZE(sizeof(item->name_change));
+ if (msg->size < sizeof(*msg) + min_size ||
+ item->size < min_size) {
+ r = -EPROTONOSUPPORT;
+ break;
+ }
+
+ name_owner_change_func(item->name_change.name,
+ item->name_change.old.id,
+ item->name_change.new.id,
+ user_data);
+ break;
+
+ default:
+ break;
+ }
+
break;
default:
r = -EPROTONOSUPPORT;
@@ -600,47 +635,104 @@ int _dbus_kernel_name_acquire(int fd, const char *name)
}
int _dbus_kernel_add_match(int fd, uint64_t bloom_size, uint64_t bloom_n_hash,
- uint64_t *out_cookie)
+ const struct _dbus_filter_condition *rule,
+ int rule_len, unsigned int id)
{
- static uint64_t cookie = 1;
- struct kdbus_item *item;
+ struct kdbus_item *bloom, *item;
struct kdbus_cmd_match *cmd;
size_t cmd_size;
- int r;
+ const char *prefix;
+ char argstr[8];
+ int r, i;
+ uint64_t sender_id;
cmd_size = sizeof(struct kdbus_cmd_match);
cmd_size += KDBUS_ITEM_SIZE(bloom_size);
+ for (i = 0; i < rule_len; i++) {
+ switch (rule[i].type) {
+ case L_DBUS_MATCH_SENDER:
+ if (_dbus_parse_unique_name(rule->value, NULL))
+ cmd_size += KDBUS_ITEM_SIZE(sizeof(item->id));
+ else
+ cmd_size += KDBUS_ITEM_SIZE(
+ strlen(rule[i].value) + 1);
+ break;
+ default:
+ break;
+ }
+ }
+
cmd = alloca(cmd_size);
memset(cmd, 0, cmd_size);
cmd->size = cmd_size;
- cmd->cookie = cookie++;
+ cmd->cookie = id;
item = cmd->items;
- item->size = KDBUS_ITEM_HEADER_SIZE + bloom_size;
- item->type = KDBUS_ITEM_BLOOM_MASK;
- _dbus_kernel_bloom_add((uint64_t *) item->data64, bloom_size,
- bloom_n_hash, "message-type", "signal");
+ bloom = item;
+ bloom->size = KDBUS_ITEM_HEADER_SIZE + bloom_size;
+ bloom->type = KDBUS_ITEM_BLOOM_MASK;
+
+ for (; rule_len; rule++, rule_len--) {
+ switch ((int) rule->type) {
+ case L_DBUS_MATCH_SENDER:
+ item = KDBUS_ITEM_NEXT(item);
+
+ if (_dbus_parse_unique_name(rule->value, &sender_id)) {
+ item->size = KDBUS_ITEM_HEADER_SIZE +
+ strlen(rule->value) + 1;
+ item->type = KDBUS_ITEM_ID;
+ item->id = id;
+ } else {
+ item->size = KDBUS_ITEM_HEADER_SIZE +
+ strlen(rule->value) + 1;
+ item->type = KDBUS_ITEM_NAME;
+ strcpy(item->str, rule->value);
+ }
+
+ continue;
+ case L_DBUS_MATCH_TYPE:
+ prefix = "message-type";
+ break;
+ case L_DBUS_MATCH_PATH:
+ prefix = "path";
+ break;
+ case L_DBUS_MATCH_INTERFACE:
+ prefix = "interface";
+ break;
+ case L_DBUS_MATCH_MEMBER:
+ prefix = "member";
+ break;
+ case L_DBUS_MATCH_ARG0...(L_DBUS_MATCH_ARG0 + 63):
+ prefix = argstr;
+ snprintf(argstr, sizeof(argstr), "arg%i",
+ rule->type - L_DBUS_MATCH_ARG0);
+ break;
+ default:
+ return -ENOTSUP;
+ }
+
+ _dbus_kernel_bloom_add((uint64_t *) bloom->data64, bloom_size,
+ bloom_n_hash, prefix, rule->value);
+ }
+
item = KDBUS_ITEM_NEXT(item);
r = ioctl(fd, KDBUS_CMD_MATCH_ADD, cmd);
if (r < 0)
return -errno;
- if (out_cookie)
- *out_cookie = cmd->cookie;
-
return 0;
}
-int _dbus_kernel_remove_match(int fd, uint64_t cookie)
+int _dbus_kernel_remove_match(int fd, unsigned int id)
{
struct kdbus_cmd_match cmd;
int r;
memset(&cmd, 0, sizeof(cmd));
cmd.size = sizeof(cmd);
- cmd.cookie = cookie;
+ cmd.cookie = id;
r = ioctl(fd, KDBUS_CMD_MATCH_REMOVE, &cmd);
if (r < 0)
@@ -648,3 +740,81 @@ int _dbus_kernel_remove_match(int fd, uint64_t cookie)
return 0;
}
+
+int _dbus_kernel_enable_name_owner_notify(int fd)
+{
+ struct {
+ struct kdbus_cmd_match cmd;
+ uint8_t param[KDBUS_ITEM_SIZE(
+ sizeof(struct kdbus_notify_name_change))];
+ } cmd_match;
+ struct kdbus_item *item;
+ int r;
+
+ memset(&cmd_match, 0, sizeof(cmd_match));
+ item = cmd_match.cmd.items;
+ item->type = KDBUS_ITEM_NAME_ADD;
+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->name_change);
+ item->name_change.old.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.new.id = KDBUS_MATCH_ID_ANY;
+ cmd_match.cmd.size = sizeof(cmd_match.cmd) + item->size;
+
+ r = ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match);
+ if (r < 0)
+ return -errno;
+
+ memset(&cmd_match, 0, sizeof(cmd_match));
+ item = cmd_match.cmd.items;
+ item->type = KDBUS_ITEM_NAME_CHANGE;
+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->name_change);
+ item->name_change.old.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.new.id = KDBUS_MATCH_ID_ANY;
+ cmd_match.cmd.size = sizeof(cmd_match.cmd) + item->size;
+
+ r = ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match);
+ if (r < 0)
+ return -errno;
+
+ memset(&cmd_match, 0, sizeof(cmd_match));
+ item = cmd_match.cmd.items;
+ item->type = KDBUS_ITEM_NAME_REMOVE;
+ item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->name_change);
+ item->name_change.old.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.new.id = KDBUS_MATCH_ID_ANY;
+ cmd_match.cmd.size = sizeof(cmd_match.cmd) + item->size;
+
+ r = ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match);
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+uint64_t _dbus_kernel_get_name_owner(int fd, void *kdbus_pool,
+ const char *name)
+{
+ struct kdbus_cmd_name_list cmd;
+ struct kdbus_name_list *list;
+ const struct kdbus_cmd_name *entry, *end;
+ uint64_t owner_id = 0;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.flags = KDBUS_NAME_LIST_NAMES;
+
+ if (ioctl(fd, KDBUS_CMD_NAME_LIST, &cmd) < 0)
+ return 0;
+
+ list = (struct kdbus_name_list *) (kdbus_pool + cmd.offset);
+ end = (void *) list + list->size;
+
+ for (entry = list->names; entry < end;
+ entry = (void *) entry + entry->size)
+ if (!strcmp(entry->name, name)) {
+ owner_id = entry->owner_id;
+ break;
+ }
+
+ ioctl(fd, KDBUS_CMD_FREE, &cmd.offset);
+
+ return owner_id;
+}
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index d635cc0..0ae4c69 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -230,15 +230,26 @@ int _dbus_kernel_hello(int fd, const char *connection_name,
uint64_t *id, void **pool, char **guid);
void _dbus_kernel_unmap_pool(void *pool);
+typedef void (*_dbus_name_owner_change_func_t)(const char *name,
+ uint64_t old_owner,
+ uint64_t new_owner,
+ void *user_data);
+
int _dbus_kernel_send(int fd, size_t bloom_size, uint8_t n_bloom_hash,
struct l_dbus_message *message);
int _dbus_kernel_recv(int fd, void *kdbus_pool,
- struct l_dbus_message **out_message);
+ l_dbus_message_func_t message_func,
+ _dbus_name_owner_change_func_t name_owner_change_func,
+ void *user_data);
int _dbus_kernel_name_acquire(int fd, const char *name);
int _dbus_kernel_add_match(int fd, uint64_t bloom_size, uint64_t bloom_n_hash,
- uint64_t *out_cookie);
-int _dbus_kernel_remove_match(int fd, uint64_t cookie);
+ const struct _dbus_filter_condition *rule,
+ int rule_len, unsigned int id);
+int _dbus_kernel_remove_match(int fd, unsigned int it);
+int _dbus_kernel_enable_name_owner_notify(int fd);
+uint64_t _dbus_kernel_get_name_owner(int fd, void *kdbus_pool,
+ const char *name);
uint8_t _dbus_get_version(struct l_dbus *dbus);
int _dbus_get_fd(struct l_dbus *dbus);
diff --git a/ell/dbus.c b/ell/dbus.c
index 52a9192..a816dd3 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -277,7 +277,7 @@ static bool message_read_handler(struct l_io *io, void *user_data)
message = dbus->driver->recv_message(dbus);
if (!message)
- return false;
+ return true;
header = _dbus_message_get_header(message, &header_size);
body = _dbus_message_get_body(message, &body_size);
@@ -347,6 +347,22 @@ static uint32_t send_message(struct l_dbus *dbus, bool priority,
return callback->serial;
}
+static void bus_ready(struct l_dbus *dbus)
+{
+ dbus->is_ready = true;
+
+ if (dbus->ready_handler)
+ dbus->ready_handler(dbus->ready_data);
+
+ l_io_set_read_handler(dbus->io, message_read_handler, dbus, NULL);
+
+ /* Check for messages added before the connection was ready */
+ if (l_queue_isempty(dbus->message_queue))
+ return;
+
+ l_io_set_write_handler(dbus->io, message_write_handler, dbus, NULL);
+}
+
static void hello_callback(struct l_dbus_message *message, void *user_data)
{
struct l_dbus *dbus = user_data;
@@ -366,16 +382,7 @@ static void hello_callback(struct l_dbus_message *message, void *user_data)
dbus->unique_name = l_strdup(unique_name);
- dbus->is_ready = true;
-
- if (dbus->ready_handler)
- dbus->ready_handler(dbus->ready_data);
-
- /* Check for messages added before the connection was ready */
- if (l_queue_isempty(dbus->message_queue))
- return;
-
- l_io_set_write_handler(dbus->io, message_write_handler, dbus, NULL);
+ bus_ready(dbus);
}
static bool auth_write_handler(struct l_io *io, void *user_data)
@@ -937,29 +944,8 @@ static struct l_dbus *setup_unix(char *params)
static void kdbus_ready(void *user_data)
{
struct l_dbus *dbus = user_data;
- struct l_dbus_kdbus *kdbus =
- container_of(dbus, struct l_dbus_kdbus, super);
- int fd = l_io_get_fd(dbus->io);
- int r;
-
- r = _dbus_kernel_add_match(fd, kdbus->bloom_size, kdbus->bloom_n_hash,
- NULL);
- if (r < 0)
- l_util_debug(dbus->debug_handler,
- dbus->debug_data, strerror(-r));
-
- dbus->is_ready = true;
-
- if (dbus->ready_handler)
- dbus->ready_handler(dbus->ready_data);
- l_io_set_read_handler(dbus->io, message_read_handler, dbus, NULL);
-
- /* Check for messages added before the connection was ready */
- if (l_queue_isempty(dbus->message_queue))
- return;
-
- l_io_set_write_handler(dbus->io, message_write_handler, dbus, NULL);
+ bus_ready(dbus);
}
static void kdbus_free(struct l_dbus *dbus)
@@ -992,25 +978,103 @@ static bool kdbus_send_message(struct l_dbus *dbus,
return true;
}
+struct kdbus_message_recv_data {
+ struct l_dbus_message *message;
+ struct l_dbus *dbus;
+};
+
+static void kdbus_message_func(struct l_dbus_message *message, void *user_data)
+{
+ struct kdbus_message_recv_data *recv_data = user_data;
+
+ recv_data->message = message;
+
+ l_util_debug(recv_data->dbus->debug_handler,
+ recv_data->dbus->debug_data, "Read KDBUS Message");
+}
+
+static void kdbus_name_owner_change_func(const char *name, uint64_t old_owner,
+ uint64_t new_owner,
+ void *user_data)
+{
+ struct kdbus_message_recv_data *recv_data = user_data;
+ char owner[32];
+
+ snprintf(owner, sizeof(owner), ":1.%" PRIu64, new_owner);
+
+ _dbus_filter_name_owner_notify(recv_data->dbus->filter, name, owner);
+}
+
static struct l_dbus_message *kdbus_recv_message(struct l_dbus *dbus)
{
struct l_dbus_kdbus *kdbus =
container_of(dbus, struct l_dbus_kdbus, super);
int fd = l_io_get_fd(dbus->io);
- struct l_dbus_message *message = NULL;
+ struct kdbus_message_recv_data recv_data = { NULL, dbus };
int r;
- r = _dbus_kernel_recv(fd, kdbus->kdbus_pool, &message);
+ r = _dbus_kernel_recv(fd, kdbus->kdbus_pool, kdbus_message_func,
+ kdbus_name_owner_change_func, &recv_data);
if (r < 0) {
l_util_debug(dbus->debug_handler,
dbus->debug_data, strerror(-r));
return NULL;
}
- l_util_debug(dbus->debug_handler, dbus->debug_data,
- "Read KDBUS Message");
+ return recv_data.message;
+}
+
+static bool kdbus_add_match(struct l_dbus *dbus, unsigned int id,
+ const struct _dbus_filter_condition *rule,
+ int rule_len)
+{
+ struct l_dbus_kdbus *kdbus =
+ container_of(dbus, struct l_dbus_kdbus, super);
+ int fd = l_io_get_fd(dbus->io);
+ int r;
+
+ r = _dbus_kernel_add_match(fd, kdbus->bloom_size, kdbus->bloom_n_hash,
+ rule, rule_len, id);
+ if (r < 0)
+ l_util_debug(dbus->debug_handler,
+ dbus->debug_data, strerror(-r));
+
+ return !r;
+}
+
+static bool kdbus_remove_match(struct l_dbus *dbus, unsigned int id)
+{
+ int fd = l_io_get_fd(dbus->io);
+ int r;
+
+ r = _dbus_kernel_remove_match(fd, id);
+ if (r < 0)
+ l_util_debug(dbus->debug_handler,
+ dbus->debug_data, strerror(-r));
+
+ return !r;
+}
+
+static bool kdbus_get_name_owner(struct l_dbus *dbus, const char *name)
+{
+ struct l_dbus_kdbus *kdbus =
+ container_of(dbus, struct l_dbus_kdbus, super);
+ int fd = l_io_get_fd(dbus->io);
+ uint64_t owner_id;
+ char owner[32];
+
+ owner_id = _dbus_kernel_get_name_owner(fd, kdbus->kdbus_pool, name);
+ if (!owner_id) {
+ l_util_debug(dbus->debug_handler,
+ dbus->debug_data, "Error getting name owner");
+ return false;
+ }
+
+ snprintf(owner, sizeof(owner), ":1.%" PRIu64, owner_id);
- return message;
+ _dbus_filter_name_owner_notify(dbus->filter, name, owner);
+
+ return true;
}
static const struct l_dbus_ops kdbus_ops = {
@@ -1018,12 +1082,18 @@ static const struct l_dbus_ops kdbus_ops = {
.free = kdbus_free,
.send_message = kdbus_send_message,
.recv_message = kdbus_recv_message,
+ .filter_ops = {
+ .add_match = kdbus_add_match,
+ .remove_match = kdbus_remove_match,
+ .get_name_owner = kdbus_get_name_owner,
+ },
};
static struct l_dbus *setup_kdbus(int fd)
{
struct l_dbus *dbus;
struct l_dbus_kdbus *kdbus;
+ int r;
kdbus = l_new(struct l_dbus_kdbus, 1);
dbus = &kdbus->super;
@@ -1044,6 +1114,11 @@ static struct l_dbus *setup_kdbus(int fd)
l_idle_oneshot(kdbus_ready, dbus, NULL);
+ r = _dbus_kernel_enable_name_owner_notify(fd);
+ if (r < 0)
+ l_util_debug(dbus->debug_handler,
+ dbus->debug_data, strerror(-r));
+
return dbus;
}
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 11/15] linux: Update kdbus.h to current github version.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (8 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 10/15] dbus: kdbus " Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 17:52 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 12/15] dbus-kernel: Update kdbus API usage to current version Andrew Zaborowski
` (4 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 53426 bytes --]
---
linux/kdbus.h | 1061 +++++++++++++++++++++++++++++----------------------------
1 file changed, 547 insertions(+), 514 deletions(-)
diff --git a/linux/kdbus.h b/linux/kdbus.h
index 8f98396..4fc44cb 100644
--- a/linux/kdbus.h
+++ b/linux/kdbus.h
@@ -1,33 +1,22 @@
/*
- * Copyright (C) 2013 Kay Sievers
- * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013 Linux Foundation
- * Copyright (C) 2013 Lennart Poettering
- * Copyright (C) 2013 Daniel Mack <daniel@zonque.org>
- *
* kdbus is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
- *
- * "Everything should be made as simple as possible, but not simpler."
- * -- Albert Einstein
*/
-#ifndef _KDBUS_H_
-#define _KDBUS_H_
+#ifndef _UAPI_KDBUS_H_
+#define _UAPI_KDBUS_H_
-#ifndef __KERNEL__
-#include <sys/ioctl.h>
-#include <sys/types.h>
+#include <linux/ioctl.h>
#include <linux/types.h>
-#endif
#define KDBUS_IOCTL_MAGIC 0x95
#define KDBUS_SRC_ID_KERNEL (0)
#define KDBUS_DST_ID_NAME (0)
#define KDBUS_MATCH_ID_ANY (~0ULL)
#define KDBUS_DST_ID_BROADCAST (~0ULL)
+#define KDBUS_FLAG_NEGOTIATE (1ULL << 63)
/**
* struct kdbus_notify_id_change - name registry change message
@@ -44,12 +33,12 @@
struct kdbus_notify_id_change {
__u64 id;
__u64 flags;
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_notify_name_change - name registry change message
- * @old: ID and flags of former owner of a name
- * @new: ID and flags of new owner of a name
+ * @old_id: ID and flags of former owner of a name
+ * @new_id: ID and flags of new owner of a name
* @name: Well-known name
*
* Sent from kernel to userspace when the owner or activator of
@@ -61,34 +50,67 @@ struct kdbus_notify_id_change {
* KDBUS_ITEM_NAME_CHANGE
*/
struct kdbus_notify_name_change {
- struct kdbus_notify_id_change old;
- struct kdbus_notify_id_change new;
+ struct kdbus_notify_id_change old_id;
+ struct kdbus_notify_id_change new_id;
char name[0];
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_creds - process credentials
* @uid: User ID
+ * @euid: Effective UID
+ * @suid: Saved UID
+ * @fsuid: Filesystem UID
* @gid: Group ID
- * @pid: Process ID
- * @tid: Thread ID
- * @starttime: Starttime of the process
- *
- * The starttime of the process PID. This is useful to detect PID overruns
- * from the client side. i.e. if you use the PID to look something up in
- * /proc/$PID/ you can afterwards check the starttime field of it, to ensure
- * you didn't run into a PID overrun.
+ * @egid: Effective GID
+ * @sgid: Saved GID
+ * @fsgid: Filesystem GID
*
* Attached to:
* KDBUS_ITEM_CREDS
*/
struct kdbus_creds {
__u64 uid;
+ __u64 euid;
+ __u64 suid;
+ __u64 fsuid;
__u64 gid;
+ __u64 egid;
+ __u64 sgid;
+ __u64 fsgid;
+} __attribute__((__aligned__(8)));
+
+/**
+ * struct kdbus_pids - process identifiers
+ * @pid: Process ID
+ * @tid: Thread ID
+ * @ppid: Parent process ID
+ *
+ * The PID and TID of a process.
+ *
+ * Attached to:
+ * KDBUS_ITEM_PIDS
+ */
+struct kdbus_pids {
__u64 pid;
__u64 tid;
- __u64 starttime;
-};
+ __u64 ppid;
+} __attribute__((__aligned__(8)));
+
+/**
+ * struct kdbus_caps - process capabilities
+ * @last_cap: Highest currently known capability bit
+ * @caps: Variable number of 32-bit capabilities flags
+ *
+ * Contains a variable number of 32-bit capabilities flags.
+ *
+ * Attached to:
+ * KDBUS_ITEM_CAPS
+ */
+struct kdbus_caps {
+ __u32 last_cap;
+ __u32 caps[0];
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_audit - audit information
@@ -99,9 +121,9 @@ struct kdbus_creds {
* KDBUS_ITEM_AUDIT
*/
struct kdbus_audit {
- __u64 sessionid;
- __u64 loginuid;
-};
+ __u32 sessionid;
+ __u32 loginuid;
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_timestamp
@@ -116,17 +138,17 @@ struct kdbus_timestamp {
__u64 seqnum;
__u64 monotonic_ns;
__u64 realtime_ns;
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_vec - I/O vector for kdbus payload items
* @size: The size of the vector
- * @address: Memory address for memory addresses
+ * @address: Memory address of data buffer
* @offset: Offset in the in-message payload memory,
* relative to the message head
*
* Attached to:
- * KDBUS_ITEM_PAYLOAD_VEC
+ * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF
*/
struct kdbus_vec {
__u64 size;
@@ -134,7 +156,7 @@ struct kdbus_vec {
__u64 address;
__u64 offset;
};
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_bloom_parameter - bus-wide bloom parameters
@@ -144,7 +166,7 @@ struct kdbus_vec {
struct kdbus_bloom_parameter {
__u64 size;
__u64 n_hash;
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_bloom_filter - bloom filter containing n elements
@@ -154,22 +176,24 @@ struct kdbus_bloom_parameter {
struct kdbus_bloom_filter {
__u64 generation;
__u64 data[0];
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_memfd - a kdbus memfd
- * @size: The memfd's size
+ * @start: The offset into the memfd where the segment starts
+ * @size: The size of the memfd segment
* @fd: The file descriptor number
- * @__pad: Padding to ensure proper alignement and size
+ * @__pad: Padding to ensure proper alignment and size
*
* Attached to:
* KDBUS_ITEM_PAYLOAD_MEMFD
*/
struct kdbus_memfd {
+ __u64 start;
__u64 size;
int fd;
__u32 __pad;
-};
+} __attribute__((__aligned__(8)));
/**
* struct kdbus_name - a registered well-known name with its flags
@@ -177,11 +201,39 @@ struct kdbus_memfd {
* @name: Well-known name
*
* Attached to:
- * KDBUS_ITEM_NAME
+ * KDBUS_ITEM_OWNED_NAME
*/
struct kdbus_name {
__u64 flags;
char name[0];
+} __attribute__((__aligned__(8)));
+
+/**
+ * enum kdbus_policy_access_type - permissions of a policy record
+ * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid
+ * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid
+ * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid
+ * @KDBUS_POLICY_ACCESS_WORLD: World-accessible
+ */
+enum kdbus_policy_access_type {
+ _KDBUS_POLICY_ACCESS_NULL,
+ KDBUS_POLICY_ACCESS_USER,
+ KDBUS_POLICY_ACCESS_GROUP,
+ KDBUS_POLICY_ACCESS_WORLD,
+};
+
+/**
+ * enum kdbus_policy_access_flags - mode flags
+ * @KDBUS_POLICY_OWN: Allow to own a well-known name
+ * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE
+ * @KDBUS_POLICY_TALK: Allow communication to a well-known name
+ * Implies KDBUS_POLICY_SEE
+ * @KDBUS_POLICY_SEE: Allow to see a well-known name
+ */
+enum kdbus_policy_type {
+ KDBUS_POLICY_SEE = 0,
+ KDBUS_POLICY_TALK,
+ KDBUS_POLICY_OWN,
};
/**
@@ -195,83 +247,151 @@ struct kdbus_policy_access {
__u64 type; /* USER, GROUP, WORLD */
__u64 access; /* OWN, TALK, SEE */
__u64 id; /* uid, gid, 0 */
+} __attribute__((__aligned__(8)));
+
+/**
+ * enum kdbus_attach_flags - flags for metadata attachments
+ * @KDBUS_ATTACH_TIMESTAMP: Timestamp
+ * @KDBUS_ATTACH_CREDS: Credentials
+ * @KDBUS_ATTACH_PIDS: PIDs
+ * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups
+ * @KDBUS_ATTACH_NAMES: Well-known names
+ * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID
+ * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID
+ * @KDBUS_ATTACH_EXE: The path of the executable
+ * @KDBUS_ATTACH_CMDLINE: The process command line
+ * @KDBUS_ATTACH_CGROUP: The croup membership
+ * @KDBUS_ATTACH_CAPS: The process capabilities
+ * @KDBUS_ATTACH_SECLABEL: The security label
+ * @KDBUS_ATTACH_AUDIT: The audit IDs
+ * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name
+ * @_KDBUS_ATTACH_ALL: All of the above
+ * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of
+ * metatdata.
+ */
+enum kdbus_attach_flags {
+ KDBUS_ATTACH_TIMESTAMP = 1ULL << 0,
+ KDBUS_ATTACH_CREDS = 1ULL << 1,
+ KDBUS_ATTACH_PIDS = 1ULL << 2,
+ KDBUS_ATTACH_AUXGROUPS = 1ULL << 3,
+ KDBUS_ATTACH_NAMES = 1ULL << 4,
+ KDBUS_ATTACH_TID_COMM = 1ULL << 5,
+ KDBUS_ATTACH_PID_COMM = 1ULL << 6,
+ KDBUS_ATTACH_EXE = 1ULL << 7,
+ KDBUS_ATTACH_CMDLINE = 1ULL << 8,
+ KDBUS_ATTACH_CGROUP = 1ULL << 9,
+ KDBUS_ATTACH_CAPS = 1ULL << 10,
+ KDBUS_ATTACH_SECLABEL = 1ULL << 11,
+ KDBUS_ATTACH_AUDIT = 1ULL << 12,
+ KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13,
+ _KDBUS_ATTACH_ALL = (1ULL << 14) - 1,
+ _KDBUS_ATTACH_ANY = ~0ULL
};
/**
* enum kdbus_item_type - item types to chain data in a list
- * @_KDBUS_ITEM_NULL: Uninitialized/invalid
- * @_KDBUS_ITEM_USER_BASE: Start of user items
- * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data
- * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head
- * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd
- * @KDBUS_ITEM_FDS: Attached file descriptors
- * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with
- * KDBUS_CMD_BUS_MAKE, carries a
- * struct kdbus_bloom_parameter
- * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message, used to
- * match against a bloom mask of a connection,
- * carries a struct kdbus_bloom_filter
- * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a message's
- * bloom filter
- * @KDBUS_ITEM_DST_NAME: Destination's well-known name
- * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint
- * @KDBUS_ITEM_MEMFD_NAME: The human readable name of a memfd (debugging)
- * @KDBUS_ITEM_ATTACH_FLAGS: Attach-flags, used for updating which metadata
- * a connection subscribes to
- * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items
- * @KDBUS_ITEM_NAME: Well-know name with flags
- * @KDBUS_ITEM_ID: Connection ID
- * @KDBUS_ITEM_TIMESTAMP: Timestamp
- * @KDBUS_ITEM_CREDS: Process credential
- * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier
- * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier
- * @KDBUS_ITEM_EXE: The path of the executable
- * @KDBUS_ITEM_CMDLINE: The process command line
- * @KDBUS_ITEM_CGROUP: The croup membership
- * @KDBUS_ITEM_CAPS: The process capabilities
- * @KDBUS_ITEM_SECLABEL: The security label
- * @KDBUS_ITEM_AUDIT: The audit IDs
- * @KDBUS_ITEM_CONN_NAME: The connection's human-readable name (debugging)
- * @_KDBUS_ITEM_POLICY_BASE: Start of policy items
- * @KDBUS_ITEM_POLICY_ACCESS: Policy access block
- * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items
- * @KDBUS_ITEM_NAME_ADD: Notify in struct kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_REMOVE: Notify in struct kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_CHANGE: Notify in struct kdbus_notify_name_change
- * @KDBUS_ITEM_ID_ADD: Notify in struct kdbus_notify_id_change
- * @KDBUS_ITEM_ID_REMOVE: Notify in struct kdbus_notify_id_change
- * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached
- * @KDBUS_ITEM_REPLY_DEAD: Destination died
+ * @_KDBUS_ITEM_NULL: Uninitialized/invalid
+ * @_KDBUS_ITEM_USER_BASE: Start of user items
+ * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items
+ * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data
+ * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head
+ * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd
+ * @KDBUS_ITEM_FDS: Attached file descriptors
+ * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous
+ * operation by writing to it from
+ * userspace
+ * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with
+ * KDBUS_CMD_BUS_MAKE, carries a
+ * struct kdbus_bloom_parameter
+ * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message,
+ * used to match against a bloom mask of a
+ * connection, carries a struct
+ * kdbus_bloom_filter
+ * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a
+ * message'sbloom filter
+ * @KDBUS_ITEM_DST_NAME: Destination's well-known name
+ * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint
+ * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which
+ * metadata a connection opts in to send
+ * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which
+ * metadata a connection requests to
+ * receive for each reeceived message
+ * @KDBUS_ITEM_ID: Connection ID
+ * @KDBUS_ITEM_NAME: Well-know name with flags
+ * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items
+ * @KDBUS_ITEM_TIMESTAMP: Timestamp
+ * @KDBUS_ITEM_CREDS: Process credentials
+ * @KDBUS_ITEM_PIDS: Process identifiers
+ * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups
+ * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated
+ * connection
+ * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier
+ * (Don't trust this, see below.)
+ * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier
+ * (Don't trust this, see below.)
+ * @KDBUS_ITEM_EXE: The path of the executable
+ * (Don't trust this, see below.)
+ * @KDBUS_ITEM_CMDLINE: The process command line
+ * (Don't trust this, see below.)
+ * @KDBUS_ITEM_CGROUP: The croup membership
+ * @KDBUS_ITEM_CAPS: The process capabilities
+ * @KDBUS_ITEM_SECLABEL: The security label
+ * @KDBUS_ITEM_AUDIT: The audit IDs
+ * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name
+ * (debugging)
+ * @_KDBUS_ITEM_POLICY_BASE: Start of policy items
+ * @KDBUS_ITEM_POLICY_ACCESS: Policy access block
+ * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items
+ * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change
+ * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change
+ * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change
+ * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change
+ * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change
+ * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached
+ * @KDBUS_ITEM_REPLY_DEAD: Destination died
+ *
+ * N.B: The process and thread COMM fields, as well as the CMDLINE and
+ * EXE fields may be altered by unprivileged processes und should
+ * hence *not* used for security decisions. Peers should make use of
+ * these items only for informational purposes, such as generating log
+ * records.
*/
enum kdbus_item_type {
_KDBUS_ITEM_NULL,
_KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_PAYLOAD_VEC = _KDBUS_ITEM_USER_BASE,
+ KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE,
+ KDBUS_ITEM_PAYLOAD_VEC,
KDBUS_ITEM_PAYLOAD_OFF,
KDBUS_ITEM_PAYLOAD_MEMFD,
KDBUS_ITEM_FDS,
+ KDBUS_ITEM_CANCEL_FD,
KDBUS_ITEM_BLOOM_PARAMETER,
KDBUS_ITEM_BLOOM_FILTER,
KDBUS_ITEM_BLOOM_MASK,
KDBUS_ITEM_DST_NAME,
KDBUS_ITEM_MAKE_NAME,
- KDBUS_ITEM_MEMFD_NAME,
- KDBUS_ITEM_ATTACH_FLAGS,
+ KDBUS_ITEM_ATTACH_FLAGS_SEND,
+ KDBUS_ITEM_ATTACH_FLAGS_RECV,
+ KDBUS_ITEM_ID,
+ KDBUS_ITEM_NAME,
+ KDBUS_ITEM_DST_ID,
+ /* keep these item types in sync with KDBUS_ATTACH_* flags */
_KDBUS_ITEM_ATTACH_BASE = 0x1000,
- KDBUS_ITEM_NAME = _KDBUS_ITEM_ATTACH_BASE,
- KDBUS_ITEM_ID,
- KDBUS_ITEM_TIMESTAMP,
+ KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE,
KDBUS_ITEM_CREDS,
- KDBUS_ITEM_PID_COMM,
+ KDBUS_ITEM_PIDS,
+ KDBUS_ITEM_AUXGROUPS,
+ KDBUS_ITEM_OWNED_NAME,
KDBUS_ITEM_TID_COMM,
+ KDBUS_ITEM_PID_COMM,
KDBUS_ITEM_EXE,
KDBUS_ITEM_CMDLINE,
KDBUS_ITEM_CGROUP,
KDBUS_ITEM_CAPS,
KDBUS_ITEM_SECLABEL,
KDBUS_ITEM_AUDIT,
- KDBUS_ITEM_CONN_NAME,
+ KDBUS_ITEM_CONN_DESCRIPTION,
_KDBUS_ITEM_POLICY_BASE = 0x2000,
KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE,
@@ -322,7 +442,9 @@ struct kdbus_item {
__u64 id;
struct kdbus_vec vec;
struct kdbus_creds creds;
+ struct kdbus_pids pids;
struct kdbus_audit audit;
+ struct kdbus_caps caps;
struct kdbus_timestamp timestamp;
struct kdbus_name name;
struct kdbus_bloom_parameter bloom_parameter;
@@ -333,38 +455,34 @@ struct kdbus_item {
struct kdbus_notify_id_change id_change;
struct kdbus_policy_access policy_access;
};
-};
+} __attribute__((__aligned__(8)));
/**
* enum kdbus_msg_flags - type of message
- * @KDBUS_MSG_FLAGS_EXPECT_REPLY: Expect a reply message, used for
- * method calls. The userspace-supplied
- * cookie identifies the message and the
- * respective reply carries the cookie
- * in cookie_reply
- * @KDBUS_MSG_FLAGS_SYNC_REPLY: Wait for destination connection to
- * reply to this message. The
- * KDBUS_CMD_MSG_SEND ioctl() will block
- * until the reply is received, and
- * offset_reply in struct kdbus_msg will
- * yield the offset in the sender's pool
- * where the reply can be found.
- * This flag is only valid if
- * @KDBUS_MSG_FLAGS_EXPECT_REPLY is set as
- * well.
- * @KDBUS_MSG_FLAGS_NO_AUTO_START: Do not start a service, if the addressed
- * name is not currently active
+ * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for
+ * method calls. The userspace-supplied
+ * cookie identifies the message and the
+ * respective reply carries the cookie
+ * in cookie_reply
+ * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed
+ * name is not currently active. This flag is
+ * not looked at by the kernel but only
+ * serves as hint for userspace implementations.
+ * @KDBUS_MSG_SIGNAL: Treat this message as signal
*/
enum kdbus_msg_flags {
- KDBUS_MSG_FLAGS_EXPECT_REPLY = 1 << 0,
- KDBUS_MSG_FLAGS_SYNC_REPLY = 1 << 1,
- KDBUS_MSG_FLAGS_NO_AUTO_START = 1 << 2,
+ KDBUS_MSG_EXPECT_REPLY = 1ULL << 0,
+ KDBUS_MSG_NO_AUTO_START = 1ULL << 1,
+ KDBUS_MSG_SIGNAL = 1ULL << 2,
};
/**
* enum kdbus_payload_type - type of payload carried by message
* @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message
* @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus"
+ *
+ * Any payload-type is accepted. Common types will get added here once
+ * established.
*/
enum kdbus_payload_type {
KDBUS_PAYLOAD_KERNEL,
@@ -374,7 +492,7 @@ enum kdbus_payload_type {
/**
* struct kdbus_msg - the representation of a kdbus message
* @size: Total size of the message
- * @flags: Message flags (KDBUS_MSG_FLAGS_*)
+ * @flags: Message flags (KDBUS_MSG_*), userspace → kernel
* @priority: Message queue priority value
* @dst_id: 64-bit ID of the destination connection
* @src_id: 64-bit ID of the source connection
@@ -382,15 +500,16 @@ enum kdbus_payload_type {
* @cookie: Userspace-supplied cookie, for the connection
* to identify its messages
* @timeout_ns: The time to wait for a message reply from the peer.
- * If there is no reply, a kernel-generated message
+ * If there is no reply, and the send command is
+ * executed asynchronously, a kernel-generated message
* with an attached KDBUS_ITEM_REPLY_TIMEOUT item
- * is sent to @src_id.
+ * is sent to @src_id. For synchronously executed send
+ * command, the value denotes the maximum time the call
+ * blocks to wait for a reply. The timeout is expected in
+ * nanoseconds and as absolute CLOCK_MONOTONIC value.
* @cookie_reply: A reply to the requesting message with the same
* cookie. The requesting connection can match its
* request and the reply with this value
- * @offset_reply: If KDBUS_MSG_FLAGS_EXPECT_REPLY, this field will
- * contain the offset in the sender's pool where the
- * reply is stored.
* @items: A list of kdbus_items containing the message payload
*/
struct kdbus_msg {
@@ -404,10 +523,56 @@ struct kdbus_msg {
union {
__u64 timeout_ns;
__u64 cookie_reply;
- __u64 offset_reply;
};
struct kdbus_item items[0];
-} __attribute__((aligned(8)));
+} __attribute__((__aligned__(8)));
+
+/**
+ * struct kdbus_msg_info - returned message container
+ * @offset: Offset of kdbus_msg slice in pool
+ * @msg_size: Copy of the kdbus_msg.size field
+ * @return_flags: Command return flags, kernel → userspace
+ */
+struct kdbus_msg_info {
+ __u64 offset;
+ __u64 msg_size;
+ __u64 return_flags;
+} __attribute__((__aligned__(8)));
+
+/**
+ * enum kdbus_send_flags - flags for sending messages
+ * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to
+ * reply to this message. The
+ * KDBUS_CMD_SEND ioctl() will block
+ * until the reply is received, and
+ * reply in struct kdbus_cmd_send will
+ * yield the offset in the sender's pool
+ * where the reply can be found.
+ * This flag is only valid if
+ * @KDBUS_MSG_EXPECT_REPLY is set as well.
+ */
+enum kdbus_send_flags {
+ KDBUS_SEND_SYNC_REPLY = 1ULL << 0,
+};
+
+/**
+ * struct kdbus_cmd_send - send message
+ * @size: Overall size of this structure
+ * @flags: Flags to change send behavior (KDBUS_SEND_*)
+ * @return_flags: Command return flags, kernel → userspace
+ * @msg_address: Storage address of the kdbus_msg to send
+ * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY
+ * was given
+ * @items: Additional items for this command
+ */
+struct kdbus_cmd_send {
+ __u64 size;
+ __u64 flags;
+ __u64 return_flags;
+ __u64 msg_address;
+ struct kdbus_msg_info reply;
+ struct kdbus_item items[0];
+} __attribute__((__aligned__(8)));
/**
* enum kdbus_recv_flags - flags for de-queuing messages
@@ -423,59 +588,77 @@ struct kdbus_msg {
* the priority value is ignored.
*/
enum kdbus_recv_flags {
- KDBUS_RECV_PEEK = 1 << 0,
- KDBUS_RECV_DROP = 1 << 1,
- KDBUS_RECV_USE_PRIORITY = 1 << 2,
+ KDBUS_RECV_PEEK = 1ULL << 0,
+ KDBUS_RECV_DROP = 1ULL << 1,
+ KDBUS_RECV_USE_PRIORITY = 1ULL << 2,
+};
+
+/**
+ * enum kdbus_recv_return_flags - return flags for message receive commands
+ * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not
+ * be installed. These descriptors in
+ * KDBUS_ITEM_FDS will carry the value -1.
+ * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since
+ * the last time a message was received.
+ * The 'dropped_msgs' counter contains the
+ * number of messages dropped pool
+ * overflows or other missed broadcasts.
+ */
+enum kdbus_recv_return_flags {
+ KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0,
+ KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1,
};
/**
* struct kdbus_cmd_recv - struct to de-queue a buffered message
- * @flags: KDBUS_RECV_* flags
+ * @size: Overall size of this object
+ * @flags: KDBUS_RECV_* flags, userspace → kernel
+ * @return_flags: Command return flags, kernel → userspace
* @priority: Minimum priority of the messages to de-queue. Lowest
* values have the highest priority.
- * @offset: Returned offset in the pool where the message is
- * stored. The user must use KDBUS_CMD_FREE to free
- * the allocated memory.
+ * @dropped_msgs: In case there were any dropped messages since the last
+ * time a message was received, this will be set to the
+ * number of lost messages and
+ * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in
+ * 'return_flags'. This can only happen if the ioctl
+ * returns 0 or EAGAIN.
+ * @msg: Return storage for received message.
+ * @items: Additional items for this command.
*
- * This struct is used with the KDBUS_CMD_MSG_RECV ioctl.
+ * This struct is used with the KDBUS_CMD_RECV ioctl.
*/
struct kdbus_cmd_recv {
+ __u64 size;
__u64 flags;
+ __u64 return_flags;
__s64 priority;
- __u64 offset;
-} __attribute__((aligned(8)));
-
-/**
- * enum kdbus_policy_access_type - permissions of a policy record
- * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid
- * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid
- * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid
- * @KDBUS_POLICY_ACCESS_WORLD: World-accessible
- */
-enum kdbus_policy_access_type {
- _KDBUS_POLICY_ACCESS_NULL,
- KDBUS_POLICY_ACCESS_USER,
- KDBUS_POLICY_ACCESS_GROUP,
- KDBUS_POLICY_ACCESS_WORLD,
-};
+ __u64 dropped_msgs;
+ struct kdbus_msg_info msg;
+ struct kdbus_item items[0];
+} __attribute__((__aligned__(8)));
/**
- * enum kdbus_policy_access_flags - mode flags
- * @KDBUS_POLICY_OWN: Allow to own a well-known name
- * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE
- * @KDBUS_POLICY_TALK: Allow communication to a well-known name
- * Implies KDBUS_POLICY_SEE
- * @KDBUS_POLICY_SEE: Allow to see a well-known name
+ * struct kdbus_cmd_free - struct to free a slice of memory in the pool
+ * @size: Overall size of this structure
+ * @flags: Flags for the free command, userspace → kernel
+ * @return_flags: Command return flags, kernel → userspace
+ * @offset: The offset of the memory slice, as returned by other
+ * ioctls
+ * @items: Additional items to modify the behavior
+ *
+ * This struct is used with the KDBUS_CMD_FREE ioctl.
*/
-enum kdbus_policy_type {
- KDBUS_POLICY_SEE = 0,
- KDBUS_POLICY_TALK,
- KDBUS_POLICY_OWN,
-};
+struct kdbus_cmd_free {
+ __u64 size;
+ __u64 flags;
+ __u64 return_flags;
+ __u64 offset;
+ struct kdbus_item items[0];
+} __attribute__((__aligned__(8)));
/**
* enum kdbus_hello_flags - flags for struct kdbus_cmd_hello
- * @KDBUS_HELLO_ACCEPT_FD: The connection allows the receiving of
+ * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of
* any passed file descriptors
* @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers
* a well-know name for a process to be started
@@ -484,55 +667,27 @@ enum kdbus_policy_type {
* policy entries for a name. The provided name
* is not activated and not registered with the
* name database, it only allows unprivileged
- * connections to aquire a name, talk or discover
+ * connections to acquire a name, talk or discover
* a service
* @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor
* bus traffic
*/
enum kdbus_hello_flags {
- KDBUS_HELLO_ACCEPT_FD = 1 << 0,
- KDBUS_HELLO_ACTIVATOR = 1 << 1,
- KDBUS_HELLO_POLICY_HOLDER = 1 << 2,
- KDBUS_HELLO_MONITOR = 1 << 3,
-};
-
-/**
- * enum kdbus_attach_flags - flags for metadata attachments
- * @KDBUS_ATTACH_TIMESTAMP: Timestamp
- * @KDBUS_ATTACH_CREDS: Credentials
- * @KDBUS_ATTACH_NAMES: Well-known names
- * @KDBUS_ATTACH_COMM: The "comm" process identifier
- * @KDBUS_ATTACH_EXE: The path of the executable
- * @KDBUS_ATTACH_CMDLINE: The process command line
- * @KDBUS_ATTACH_CGROUP: The croup membership
- * @KDBUS_ATTACH_CAPS: The process capabilities
- * @KDBUS_ATTACH_SECLABEL: The security label
- * @KDBUS_ATTACH_AUDIT: The audit IDs
- * @KDBUS_ATTACH_CONN_NAME: The human-readable connection name
- * @_KDBUS_ATTACH_ALL: All of the above
- */
-enum kdbus_attach_flags {
- KDBUS_ATTACH_TIMESTAMP = 1 << 0,
- KDBUS_ATTACH_CREDS = 1 << 1,
- KDBUS_ATTACH_NAMES = 1 << 2,
- KDBUS_ATTACH_COMM = 1 << 3,
- KDBUS_ATTACH_EXE = 1 << 4,
- KDBUS_ATTACH_CMDLINE = 1 << 5,
- KDBUS_ATTACH_CGROUP = 1 << 6,
- KDBUS_ATTACH_CAPS = 1 << 7,
- KDBUS_ATTACH_SECLABEL = 1 << 8,
- KDBUS_ATTACH_AUDIT = 1 << 9,
- KDBUS_ATTACH_CONN_NAME = 1 << 10,
- _KDBUS_ATTACH_ALL = (1 << 11) - 1,
+ KDBUS_HELLO_ACCEPT_FD = 1ULL << 0,
+ KDBUS_HELLO_ACTIVATOR = 1ULL << 1,
+ KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2,
+ KDBUS_HELLO_MONITOR = 1ULL << 3,
};
/**
* struct kdbus_cmd_hello - struct to say hello to kdbus
* @size: The total size of the structure
- * @conn_flags: Connection flags (KDBUS_HELLO_*). The kernel will
- * return its capabilities in that field.
- * @attach_flags: Mask of metadata to attach to each message sent
- * (KDBUS_ATTACH_*)
+ * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel
+ * @return_flags: Command return flags, kernel → userspace
+ * @attach_flags_send: Mask of metadata to attach to each message sent
+ * off by this connection (KDBUS_ATTACH_*)
+ * @attach_flags_recv: Mask of metadata to attach to each message receieved
+ * by the new connection (KDBUS_ATTACH_*)
* @bus_flags: The flags field copied verbatim from the original
* KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful
* to do negotiation of features of the payload that is
@@ -540,8 +695,10 @@ enum kdbus_attach_flags {
* @id: The ID of this connection (kernel → userspace)
* @pool_size: Size of the connection's buffer where the received
* messages are placed
- * @bloom: The bloom properties of the bus, specified
- * by the bus creator (kernel → userspace)
+ * @offset: Pool offset where items are returned to report
+ * additional information about the bus and the newly
+ * created connection.
+ * @items_size: Size of buffer returned in the pool slice at @offset.
* @id128: Unique 128-bit ID of the bus (kernel → userspace)
* @items: A list of items
*
@@ -549,403 +706,279 @@ enum kdbus_attach_flags {
*/
struct kdbus_cmd_hello {
__u64 size;
- __u64 conn_flags;
- __u64 attach_flags;
+ __u64 flags;
+ __u64 return_flags;
+ __u64 attach_flags_send;
+ __u64 attach_flags_recv;
__u64 bus_flags;
__u64 id;
__u64 pool_size;
- struct kdbus_bloom_parameter bloom;
+ __u64 offset;
+ __u64 items_size;
__u8 id128[16];
struct kdbus_item items[0];
-} __attribute__((aligned(8)));
+} __attribute__((__aligned__(8)));
/**
- * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,EP,NS}_MAKE
- * @KDBUS_MAKE_ACCESS_GROUP: Make the device node group-accessible
- * @KDBUS_MAKE_ACCESS_WORLD: Make the device node world-accessible
- */
-enum kdbus_make_flags {
- KDBUS_MAKE_ACCESS_GROUP = 1 << 0,
- KDBUS_MAKE_ACCESS_WORLD = 1 << 1,
-};
-
-/**
- * struct kdbus_cmd_make - struct to make a bus, an endpoint or a domain
- * @size: The total size of the struct
- * @flags: Properties for the bus/ep/domain to create
- * @items: Items describing details
+ * struct kdbus_info - connection information
+ * @size: total size of the struct
+ * @id: 64bit object ID
+ * @flags: object creation flags
+ * @items: list of items
*
- * This structure is used with the KDBUS_CMD_BUS_MAKE, KDBUS_CMD_EP_MAKE and
- * KDBUS_CMD_DOMAIN_MAKE ioctls.
+ * Note that the user is responsible for freeing the allocated memory with
+ * the KDBUS_CMD_FREE ioctl.
*/
-struct kdbus_cmd_make {
+struct kdbus_info {
__u64 size;
+ __u64 id;
__u64 flags;
struct kdbus_item items[0];
-} __attribute__((aligned(8)));
+} __attribute__((__aligned__(8)));
/**
- * enum kdbus_name_flags - properties of a well-known name
- * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections
- * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name
- * @KDBUS_NAME_QUEUE: Name should be queued if busy
- * @KDBUS_NAME_IN_QUEUE: Name is queued
- * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection
+ * enum kdbus_list_flags - what to include into the returned list
+ * @KDBUS_LIST_UNIQUE: active connections
+ * @KDBUS_LIST_ACTIVATORS: activator connections
+ * @KDBUS_LIST_NAMES: known well-known names
+ * @KDBUS_LIST_QUEUED: queued-up names
*/
-enum kdbus_name_flags {
- KDBUS_NAME_REPLACE_EXISTING = 1 << 0,
- KDBUS_NAME_ALLOW_REPLACEMENT = 1 << 1,
- KDBUS_NAME_QUEUE = 1 << 2,
- KDBUS_NAME_IN_QUEUE = 1 << 3,
- KDBUS_NAME_ACTIVATOR = 1 << 4,
+enum kdbus_list_flags {
+ KDBUS_LIST_UNIQUE = 1ULL << 0,
+ KDBUS_LIST_NAMES = 1ULL << 1,
+ KDBUS_LIST_ACTIVATORS = 1ULL << 2,
+ KDBUS_LIST_QUEUED = 1ULL << 3,
};
/**
- * struct kdbus_cmd_name - struct to describe a well-known name
- * @size: The total size of the struct
- * @flags: Flags for a name entry (KDBUS_NAME_*)
- * @owner_id: The current owner of the name.
- * @conn_flags: The flags of the owning connection (KDBUS_HELLO_*)
- * @name: The well-known name
- *
- * This structure is used with the KDBUS_CMD_NAME_ACQUIRE ioctl.
- */
-struct kdbus_cmd_name {
- __u64 size;
- __u64 flags;
- __u64 owner_id;
- __u64 conn_flags;
- char name[0];
-} __attribute__((aligned(8)));
-
-/**
- * enum kdbus_name_list_flags - what to include into the returned list
- * @KDBUS_NAME_LIST_UNIQUE: All active connections
- * @KDBUS_NAME_LIST_NAMES: All known well-known names
- * @KDBUS_NAME_LIST_ACTIVATORS: All activator connections
- * @KDBUS_NAME_LIST_QUEUED: All queued-up names
- */
-enum kdbus_name_list_flags {
- KDBUS_NAME_LIST_UNIQUE = 1 << 0,
- KDBUS_NAME_LIST_NAMES = 1 << 1,
- KDBUS_NAME_LIST_ACTIVATORS = 1 << 2,
- KDBUS_NAME_LIST_QUEUED = 1 << 3,
-};
-
-/**
- * struct kdbus_cmd_name_list - request a list of name entries
- * @flags: Flags for the query (KDBUS_NAME_LIST_*)
- * @offset: The returned offset in the caller's pool buffer.
+ * struct kdbus_cmd_list - list connections
+ * @size: overall size of this object
+ * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel
+ * @return_flags: command return flags, kernel → userspace
+ * @offset: Offset in the caller's pool buffer where an array of
+ * kdbus_info objects is stored.
* The user must use KDBUS_CMD_FREE to free the
* allocated memory.
+ * @list_size: size of returned list in bytes
+ * @items: Items for the command. Reserved for future use.
*
- * This structure is used with the KDBUS_CMD_NAME_LIST ioctl.
+ * This structure is used with the KDBUS_CMD_LIST ioctl.
*/
-struct kdbus_cmd_name_list {
+struct kdbus_cmd_list {
+ __u64 size;
__u64 flags;
+ __u64 return_flags;
__u64 offset;
-} __attribute__((aligned(8)));
-
-/**
- * struct kdbus_name_list - information returned by KDBUS_CMD_NAME_LIST
- * @size: The total size of the structure
- * @names: A list of names
- *
- * Note that the user is responsible for freeing the allocated memory with
- * the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_name_list {
- __u64 size;
- struct kdbus_cmd_name names[0];
-};
+ __u64 list_size;
+ struct kdbus_item items[0];
+} __attribute__((__aligned__(8)));
/**
- * struct kdbus_cmd_conn_info - struct used for KDBUS_CMD_CONN_INFO ioctl
+ * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl
* @size: The total size of the struct
- * @flags: KDBUS_ATTACH_* flags
+ * @flags: Flags for this ioctl, userspace → kernel
+ * @return_flags: Command return flags, kernel → userspace
* @id: The 64-bit ID of the connection. If set to zero, passing
* @name is required. kdbus will look up the name to
* determine the ID in this case.
+ * @attach_flags: Set of attach flags to specify the set of information
+ * to receive, userspace → kernel
* @offset: Returned offset in the caller's pool buffer where the
- * kdbus_conn_info struct result is stored. The user must
+ * kdbus_info struct result is stored. The user must
* use KDBUS_CMD_FREE to free the allocated memory.
- * @name: The optional well-known name to look up. Only needed in
- * case @id is zero.
+ * @info_size: Output buffer to report size of data at @offset.
+ * @items: The optional item list, containing the
+ * well-known name to look up as a KDBUS_ITEM_NAME.
+ * Only needed in case @id is zero.
*
* On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will
* tell the user the offset in the connection pool buffer at which to find the
- * result in a struct kdbus_conn_info.
+ * result in a struct kdbus_info.
*/
-struct kdbus_cmd_conn_info {
+struct kdbus_cmd_info {
__u64 size;
__u64 flags;
+ __u64 return_flags;
__u64 id;
+ __u64 attach_flags;
__u64 offset;
- char name[0];
-} __attribute__((aligned(8)));
-
-/**
- * struct kdbus_conn_info - information returned by KDBUS_CMD_CONN_INFO
- * @size: The total size of the struct
- * @id: The connection's 64-bit ID
- * @flags: The connection's flags
- * @items: A list of struct kdbus_item
- *
- * Note that the user is responsible for freeing the allocated memory with
- * the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_conn_info {
- __u64 size;
- __u64 id;
- __u64 flags;
+ __u64 info_size;
struct kdbus_item items[0];
-};
+} __attribute__((__aligned__(8)));
/**
- * struct kdbus_cmd_update - update flags of a connection
- * @size: The total size of the struct
- * @items: A list of struct kdbus_item
- *
- * This struct is used with the KDBUS_CMD_CONN_UPDATE ioctl.
+ * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl
+ * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already
+ * exists, remove them before installing the new
+ * matches.
*/
-struct kdbus_cmd_update {
- __u64 size;
- struct kdbus_item items[0];
-} __attribute__((aligned(8)));
+enum kdbus_cmd_match_flags {
+ KDBUS_MATCH_REPLACE = 1ULL << 0,
+};
/**
* struct kdbus_cmd_match - struct to add or remove matches
* @size: The total size of the struct
+ * @flags: Flags for match command (KDBUS_MATCH_*),
+ * userspace → kernel
+ * @return_flags: Command return flags, kernel → userspace
* @cookie: Userspace supplied cookie. When removing, the cookie
* identifies the match to remove
* @items: A list of items for additional information
*
- * This structure is used with the KDBUS_CMD_ADD_MATCH and
- * KDBUS_CMD_REMOVE_MATCH ioctl.
+ * This structure is used with the KDBUS_CMD_MATCH_ADD and
+ * KDBUS_CMD_MATCH_REMOVE ioctl.
*/
struct kdbus_cmd_match {
__u64 size;
+ __u64 flags;
+ __u64 return_flags;
__u64 cookie;
struct kdbus_item items[0];
-} __attribute__((aligned(8)));
+} __attribute__((__aligned__(8)));
/**
- * struct kdbus_cmd_memfd_make - create a kdbus memfd
- * @size: The total size of the struct
- * @file_size: The initial file size
- * @fd: The returned file descriptor number
- * @__pad: Padding to ensure proper alignement
- * @items: A list of items for additional information
+ * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE
+ * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible
+ * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible
+ */
+enum kdbus_make_flags {
+ KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0,
+ KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1,
+};
+
+/**
+ * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE
+ * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections
+ * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name
+ * @KDBUS_NAME_QUEUE: Name should be queued if busy
+ * @KDBUS_NAME_IN_QUEUE: Name is queued
+ * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection
+ * @KDBUS_NAME_PRIMARY: Primary owner of the name
+ * @KDBUS_NAME_ACQUIRED: Name was acquired/queued _now_
+ */
+enum kdbus_name_flags {
+ KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0,
+ KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
+ KDBUS_NAME_QUEUE = 1ULL << 2,
+ KDBUS_NAME_IN_QUEUE = 1ULL << 3,
+ KDBUS_NAME_ACTIVATOR = 1ULL << 4,
+ KDBUS_NAME_PRIMARY = 1ULL << 5,
+ KDBUS_NAME_ACQUIRED = 1ULL << 6,
+};
+
+/**
+ * struct kdbus_cmd - generic ioctl payload
+ * @size: Overall size of this structure
+ * @flags: Flags for this ioctl, userspace → kernel
+ * @return_flags: Ioctl return flags, kernel → userspace
+ * @items: Additional items to modify the behavior
*
- * This structure is used with the KDBUS_CMD_MEMFD_NEW ioctl.
+ * This is a generic ioctl payload object. It's used by all ioctls that only
+ * take flags and items as input.
*/
-struct kdbus_cmd_memfd_make {
+struct kdbus_cmd {
__u64 size;
- __u64 file_size;
- int fd;
- __u32 __pad;
+ __u64 flags;
+ __u64 return_flags;
struct kdbus_item items[0];
-} __attribute__((aligned(8)));
+} __attribute__((__aligned__(8)));
/**
- * enum kdbus_ioctl_type - Ioctl API
- * @KDBUS_CMD_BUS_MAKE: After opening the "control" device node, this
- * command creates a new bus with the specified
+ * Ioctl API
+ *
+ * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command
+ * creates a new bus with the specified
* name. The bus is immediately shut down and
- * cleaned up when the opened "control" device node
- * is closed.
- * @KDBUS_CMD_DOMAIN_MAKE: Similar to KDBUS_CMD_BUS_MAKE, but it creates a
- * new kdbus domain.
- * @KDBUS_CMD_EP_MAKE: Creates a new named special endpoint to talk to
+ * cleaned up when the opened file descriptor is
+ * closed.
+ *
+ * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to
* the bus. Such endpoints usually carry a more
* restrictive policy and grant restricted access
* to specific applications.
- * @KDBUS_CMD_HELLO: By opening the bus device node a connection is
+ * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used
+ * to update the policy.
+ *
+ * KDBUS_CMD_HELLO: By opening the bus node, a connection is
* created. After a HELLO the opened connection
* becomes an active peer on the bus.
- * @KDBUS_CMD_BYEBYE: Disconnect a connection. If the connection's
- * message list is empty, the calls succeeds, and
- * the handle is rendered unusable. Otherwise,
- * -EAGAIN is returned without any further side-
- * effects.
- * @KDBUS_CMD_MSG_SEND: Send a message and pass data from userspace to
+ * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to
+ * update the metadata subscription mask and
+ * policy.
+ * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no
+ * messages queued up in the connection's pool,
+ * the call succeeds, and the handle is rendered
+ * unusable. Otherwise, -EBUSY is returned without
+ * any further side-effects.
+ * KDBUS_CMD_FREE: Release the allocated memory in the receiver's
+ * pool.
+ * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the
+ * initial creator of the connection. The data was
+ * stored at registration time and does not
+ * necessarily represent the connected process or
+ * the actual state of the process.
+ * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus
+ * a connection is attached to.
+ *
+ * KDBUS_CMD_SEND: Send a message and pass data from userspace to
* the kernel.
- * @KDBUS_CMD_MSG_RECV: Receive a message from the kernel which is
+ * KDBUS_CMD_RECV: Receive a message from the kernel which is
* placed in the receiver's pool.
- * @KDBUS_CMD_MSG_CANCEL: Cancel a pending request of a message that
- * blocks while waiting for a reply. The parameter
- * denotes the cookie of the message in flight.
- * @KDBUS_CMD_FREE: Release the allocated memory in the receiver's
- * pool.
- * @KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with
+ *
+ * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with
* the connection. Well-known names are used to
* address a peer on the bus.
- * @KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection
+ * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection
* currently owns.
- * @KDBUS_CMD_NAME_LIST: Retrieve the list of all currently registered
+ * KDBUS_CMD_LIST: Retrieve the list of all currently registered
* well-known and unique names.
- * @KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the
- * initial creator of the connection. The data was
- * stored at registration time and does not
- * necessarily represent the connected process or
- * the actual state of the process.
- * @KDBUS_CMD_CONN_UPDATE: Update the properties of a connection. Used to
- * update the metadata subscription mask and
- * policy.
- * @KDBUS_CMD_EP_UPDATE: Update the properties of a custom enpoint. Used
- * to update the policy.
- * @KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should
+ *
+ * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should
* be delivered to the connection.
- * @KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages.
- * @KDBUS_CMD_MEMFD_NEW: Return a new file descriptor which provides an
- * anonymous shared memory file and which can be
- * used to pass around larger chunks of data.
- * Kdbus memfd files can be sealed, which allows
- * the receiver to trust the data it has received.
- * Kdbus memfd files expose only very limited
- * operations, they can be mmap()ed, seek()ed,
- * (p)read(v)() and (p)write(v)(); most other
- * common file operations are not implemented.
- * Special caution needs to be taken with
- * read(v)()/write(v)() on a shared file; the
- * underlying file position is always shared
- * between all users of the file and race against
- * each other, pread(v)()/pwrite(v)() avoid these
- * issues.
- * @KDBUS_CMD_MEMFD_SIZE_GET: Return the size of the underlying file, which
- * changes with write().
- * @KDBUS_CMD_MEMFD_SIZE_SET: Truncate the underlying file to the specified
- * size.
- * @KDBUS_CMD_MEMFD_SEAL_GET: Return the state of the file sealing.
- * @KDBUS_CMD_MEMFD_SEAL_SET: Seal or break a seal of the file. Only files
- * which are not shared with other processes and
- * which are currently not mapped can be sealed.
- * The current process needs to be the one and
- * single owner of the file, the sealing cannot
- * be changed as long as the file is shared.
+ * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages.
*/
enum kdbus_ioctl_type {
+ /* bus owner (00-0f) */
KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00,
- struct kdbus_cmd_make),
- KDBUS_CMD_DOMAIN_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10,
- struct kdbus_cmd_make),
- KDBUS_CMD_EP_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x20,
- struct kdbus_cmd_make),
+ struct kdbus_cmd),
- KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x30,
+ /* endpoint owner (10-1f) */
+ KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10,
+ struct kdbus_cmd),
+ KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11,
+ struct kdbus_cmd),
+
+ /* connection owner (80-ff) */
+ KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80,
struct kdbus_cmd_hello),
- KDBUS_CMD_BYEBYE = _IO(KDBUS_IOCTL_MAGIC, 0x31),
-
- KDBUS_CMD_MSG_SEND = _IOWR(KDBUS_IOCTL_MAGIC, 0x40,
- struct kdbus_msg),
- KDBUS_CMD_MSG_RECV = _IOWR(KDBUS_IOCTL_MAGIC, 0x41,
- struct kdbus_cmd_recv),
- KDBUS_CMD_MSG_CANCEL = _IOW(KDBUS_IOCTL_MAGIC, 0x42, __u64 *),
- KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x43, __u64 *),
-
- KDBUS_CMD_NAME_ACQUIRE = _IOWR(KDBUS_IOCTL_MAGIC, 0x50,
- struct kdbus_cmd_name),
- KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0x51,
- struct kdbus_cmd_name),
- KDBUS_CMD_NAME_LIST = _IOWR(KDBUS_IOCTL_MAGIC, 0x52,
- struct kdbus_cmd_name_list),
-
- KDBUS_CMD_CONN_INFO = _IOWR(KDBUS_IOCTL_MAGIC, 0x60,
- struct kdbus_cmd_conn_info),
- KDBUS_CMD_CONN_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x61,
- struct kdbus_cmd_update),
-
- KDBUS_CMD_EP_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x71,
- struct kdbus_cmd_update),
-
- KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0x80,
+ KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81,
+ struct kdbus_cmd),
+ KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82,
+ struct kdbus_cmd),
+ KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83,
+ struct kdbus_cmd_free),
+ KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84,
+ struct kdbus_cmd_info),
+ KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85,
+ struct kdbus_cmd_info),
+ KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86,
+ struct kdbus_cmd_list),
+
+ KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90,
+ struct kdbus_cmd_send),
+ KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91,
+ struct kdbus_cmd_recv),
+
+ KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0,
+ struct kdbus_cmd),
+ KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1,
+ struct kdbus_cmd),
+
+ KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0,
struct kdbus_cmd_match),
- KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0x81,
+ KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1,
struct kdbus_cmd_match),
-
- KDBUS_CMD_MEMFD_NEW = _IOWR(KDBUS_IOCTL_MAGIC, 0xc0,
- struct kdbus_cmd_memfd_make),
- KDBUS_CMD_MEMFD_SIZE_GET = _IOR(KDBUS_IOCTL_MAGIC, 0xc1, __u64 *),
- KDBUS_CMD_MEMFD_SIZE_SET = _IOW(KDBUS_IOCTL_MAGIC, 0xc2, __u64 *),
- KDBUS_CMD_MEMFD_SEAL_GET = _IOR(KDBUS_IOCTL_MAGIC, 0xc3, int *),
- KDBUS_CMD_MEMFD_SEAL_SET = _IO(KDBUS_IOCTL_MAGIC, 0xc4),
};
-/*
- * errno - api error codes
- * @E2BIG: A message contains too many records or items.
- * @EADDRINUSE: A well-known bus name is already taken by another
- * connection.
- * @EADDRNOTAVAIL: A message flagged not to activate a service, addressed
- * a service which is not currently running.
- * @EAGAIN: No messages are queued@the moment.
- * @EALREADY: A requested name is already owned by the connection,
- * a connection is already disconnected, memfd is already
- * sealed or has the requested size.
- * @EBADF: File descriptors passed with the message are not valid.
- * @EBADFD: A bus connection is in a corrupted state.
- * @EBADMSG: Passed data contains a combination of conflicting or
- * inconsistent types.
- * @EBUSY: The user tried to say BYEBYE to a connection, but the
- * connection had a non-empty message list.
- * @ECANCELED: A synchronous message sending was cancelled.
- * @ECONNRESET: A connection is shut down, no further operations are
- * possible.
- * @ECOMM: A peer does not accept the file descriptors addressed
- * to it.
- * @EDESTADDRREQ: The well-known bus name is required but missing.
- * @EDOM: The size of data does not match the expectations. Used
- * for bloom bit field sizes.
- * @EEXIST: A requested domain, bus or endpoint with the same
- * name already exists. A specific data type, which is
- * only expected once, is provided multiple times.
- * @EFAULT: The supplied memory could not be accessed, or the data
- * is not properly aligned.
- * @EINVAL: The provided data does not match its type or other
- * expectations, like a string which is not NUL terminated,
- * or a string length that points behind the first
- * \0-byte in the string.
- * @EMEDIUMTYPE: A file descriptor which is not a kdbus memfd was
- * refused to send as KDBUS_MSG_PAYLOAD_MEMFD.
- * @EMFILE: Too many file descriptors have been supplied with a
- * message.
- * Too many connections or buses are created for a given
- * user.
- * @EMLINK: Too many requests from this connection to other peers
- * are queued and waiting for a reply
- * @EMSGSIZE: The supplied data is larger than the allowed maximum
- * size.
- * @ENAMETOOLONG: The requested name is larger than the allowed maximum
- * size.
- * @ENOBUFS: There is no space left for the submitted data to fit
- * into the receiver's pool.
- * @ENOENT: The to be cancelled message was not found.
- * @ENOMEM: Out of memory.
- * @ENOMSG: The queue is not empty, but no message with a matching
- * priority is currently queued.
- * @ENOSYS: The requested functionality is not available.
- * @ENOTTY: An unknown ioctl command was received.
- * @ENOTUNIQ: A specific data type was addressed to a broadcast
- * address, but only direct addresses support this kind of
- * data.
- * @ENXIO: A unique address does not exist, or an offset in the
- * receiver's pool does not represent a queued message.
- * @EOPNOTSUPP: The feature negotiation failed, a not supported feature
- * was requested, or an unknown item type was received.
- * @EPERM: The policy prevented an operation. The requested
- * resource is owned by another entity.
- * @EPIPE: When sending a message, a synchronous reply from the
- * receiving connection was expected but the connection
- * died before answering.
- * @ESHUTDOWN: A domain, bus or endpoint is currently shutting down;
- * no further operations will be possible.
- * @ESRCH: A requested well-known bus name is not found.
- * @ETIMEDOUT: A synchronous wait for a message reply did not arrive
- * within the specified time frame.
- * @ETXTBSY: A kdbus memfd file cannot be sealed or the seal removed,
- * because it is shared with other processes or still
- * mmap()ed.
- * @EXFULL: The size limits in the pool are reached, no data of
- * the size tried to submit can be queued.
- */
-#endif
+#endif /* _UAPI_KDBUS_H_ */
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 12/15] dbus-kernel: Update kdbus API usage to current version.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (9 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 11/15] linux: Update kdbus.h to current github version Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 17:52 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 13/15] dbus: Add message filter public API Andrew Zaborowski
` (3 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 10122 bytes --]
---
ell/dbus-kernel.c | 117 +++++++++++++++++++++++++++++++++++-------------------
ell/dbus.c | 4 ++
2 files changed, 81 insertions(+), 40 deletions(-)
diff --git a/ell/dbus-kernel.c b/ell/dbus-kernel.c
index eda756a..b47f973 100644
--- a/ell/dbus-kernel.c
+++ b/ell/dbus-kernel.c
@@ -33,6 +33,7 @@
#include <alloca.h>
#include <errno.h>
#include <sys/mman.h>
+#include <sys/ioctl.h>
#include "linux/kdbus.h"
@@ -180,7 +181,7 @@ void _dbus_kernel_bloom_add_parents(uint64_t filter[], size_t size,
int _dbus_kernel_create_bus(const char *name)
{
struct {
- struct kdbus_cmd_make head;
+ struct kdbus_cmd head;
/* bloom size item */
uint64_t bloom_size;
uint64_t bloom_type;
@@ -244,13 +245,14 @@ int _dbus_kernel_hello(int fd, const char *connection_name,
memset(hello, 0, size);
hello->size = size;
- hello->conn_flags |= KDBUS_HELLO_ACCEPT_FD;
- hello->attach_flags |= KDBUS_ATTACH_NAMES;
+ hello->flags |= KDBUS_HELLO_ACCEPT_FD;
+ hello->attach_flags_send |= KDBUS_ATTACH_NAMES;
+ hello->attach_flags_recv |= KDBUS_ATTACH_NAMES;
hello->pool_size = KDBUS_POOL_SIZE;
item = hello->items;
item->size = KDBUS_ITEM_HEADER_SIZE + len + 1;
- item->type = KDBUS_ITEM_CONN_NAME;
+ item->type = KDBUS_ITEM_CONN_DESCRIPTION;
strcpy(item->str, connection_name);
ret = ioctl(fd, KDBUS_CMD_HELLO, hello);
@@ -259,7 +261,7 @@ int _dbus_kernel_hello(int fd, const char *connection_name,
/* Check for incompatible flags (upper 32 bits) */
if (hello->bus_flags > 0xFFFFFFFFULL ||
- hello->conn_flags > 0xFFFFFFFFULL)
+ hello->flags > 0xFFFFFFFFULL)
return -ENOTSUP;
*pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
@@ -268,8 +270,9 @@ int _dbus_kernel_hello(int fd, const char *connection_name,
return -errno;
}
- *bloom_size = hello->bloom.size;
- *bloom_n_hash = hello->bloom.n_hash;
+ *bloom_size = DEFAULT_BLOOM_SIZE;
+ *bloom_n_hash = DEFAULT_BLOOM_N_HASH;
+
*id = hello->id;
*guid = l_strdup_printf("%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
"%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
@@ -300,6 +303,7 @@ int _dbus_kernel_send(int fd, size_t bloom_size, uint8_t bloom_n_hash,
void *body;
size_t body_size;
int ret;
+ struct kdbus_cmd_send cmd;
L_AUTO_FREE_VAR(struct kdbus_msg *, kmsg);
dest = l_dbus_message_get_destination(message);
@@ -337,10 +341,10 @@ int _dbus_kernel_send(int fd, size_t bloom_size, uint8_t bloom_n_hash,
kmsg->cookie = _dbus_message_get_serial(message);
if (l_dbus_message_get_no_autostart(message))
- kmsg->flags |= KDBUS_MSG_FLAGS_NO_AUTO_START;
+ kmsg->flags |= KDBUS_MSG_NO_AUTO_START;
if (!l_dbus_message_get_no_reply(message))
- kmsg->flags |= KDBUS_MSG_FLAGS_EXPECT_REPLY;
+ kmsg->flags |= KDBUS_MSG_EXPECT_REPLY;
if (!unique && dest) {
kmsg->dst_id = KDBUS_DST_ID_NAME;
@@ -366,9 +370,12 @@ int _dbus_kernel_send(int fd, size_t bloom_size, uint8_t bloom_n_hash,
break;
}
case DBUS_MESSAGE_TYPE_METHOD_CALL:
- kmsg->timeout_ns = 30000 * 1000ULL;
+ if (!l_dbus_message_get_no_reply(message))
+ kmsg->timeout_ns = 30000 * 1000ULL;
break;
case DBUS_MESSAGE_TYPE_SIGNAL:
+ kmsg->flags |= KDBUS_MSG_SIGNAL;
+
item->size = KDBUS_ITEM_HEADER_SIZE +
sizeof(struct kdbus_bloom_filter) + bloom_size;
item->type = KDBUS_ITEM_BLOOM_FILTER;
@@ -400,7 +407,11 @@ int _dbus_kernel_send(int fd, size_t bloom_size, uint8_t bloom_n_hash,
kmsg->size = (void *)item - (void *)kmsg;
- ret = ioctl(fd, KDBUS_CMD_MSG_SEND, kmsg);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.size = sizeof(cmd);
+ cmd.msg_address = (uint64_t) kmsg;
+
+ ret = ioctl(fd, KDBUS_CMD_SEND, &cmd);
if (ret < 0)
return -errno;
@@ -548,6 +559,7 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
void *user_data)
{
struct kdbus_cmd_recv recv_cmd;
+ struct kdbus_cmd_free cmd_free;
struct kdbus_msg *msg;
struct l_dbus_message *dbus_msg;
struct kdbus_item *item;
@@ -556,11 +568,13 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
memset(&recv_cmd, 0, sizeof(recv_cmd));
- r = ioctl(fd, KDBUS_CMD_MSG_RECV, &recv_cmd);
+ recv_cmd.size = sizeof(recv_cmd);
+
+ r = ioctl(fd, KDBUS_CMD_RECV, &recv_cmd);
if (r < 0)
return -errno;
- msg = (struct kdbus_msg *)(kdbus_pool + recv_cmd.offset);
+ msg = (struct kdbus_msg *)(kdbus_pool + recv_cmd.msg.offset);
switch (msg->payload_type) {
case KDBUS_PAYLOAD_DBUS:
@@ -588,8 +602,8 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
}
name_owner_change_func(item->name_change.name,
- item->name_change.old.id,
- item->name_change.new.id,
+ item->name_change.old_id.id,
+ item->name_change.new_id.id,
user_data);
break;
@@ -603,7 +617,11 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
break;
}
- ioctl(fd, KDBUS_CMD_FREE, &recv_cmd.offset);
+ memset(&cmd_free, 0, sizeof(cmd_free));
+ cmd_free.size = sizeof(cmd_free);
+ cmd_free.offset = recv_cmd.msg.offset;
+
+ ioctl(fd, KDBUS_CMD_FREE, &cmd_free);
return r;
}
@@ -611,22 +629,27 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
int _dbus_kernel_name_acquire(int fd, const char *name)
{
struct {
- struct kdbus_cmd_name head;
+ struct kdbus_cmd head;
char param[64];
} cmd_name;
+ struct kdbus_item *item;
size_t nlen;
if (!name)
return false;
nlen = strlen(name) + 1;
- if (nlen > sizeof(cmd_name.param))
+ if (KDBUS_ITEM_SIZE(nlen) > sizeof(cmd_name.param))
return false;
memset(&cmd_name, 0, sizeof(cmd_name));
- strcpy(cmd_name.param, name);
- cmd_name.head.size = sizeof(cmd_name.head) + nlen;
+ cmd_name.head.size = sizeof(cmd_name.head) + KDBUS_ITEM_SIZE(nlen);
+
+ item = cmd_name.head.items;
+ item->size = KDBUS_ITEM_HEADER_SIZE + nlen;
+ item->type = KDBUS_ITEM_NAME;
+ strcpy(item->str, name);
if (ioctl(fd, KDBUS_CMD_NAME_ACQUIRE, &cmd_name) < 0)
return -errno;
@@ -716,8 +739,6 @@ int _dbus_kernel_add_match(int fd, uint64_t bloom_size, uint64_t bloom_n_hash,
bloom_n_hash, prefix, rule->value);
}
- item = KDBUS_ITEM_NEXT(item);
-
r = ioctl(fd, KDBUS_CMD_MATCH_ADD, cmd);
if (r < 0)
return -errno;
@@ -755,8 +776,8 @@ int _dbus_kernel_enable_name_owner_notify(int fd)
item = cmd_match.cmd.items;
item->type = KDBUS_ITEM_NAME_ADD;
item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->name_change);
- item->name_change.old.id = KDBUS_MATCH_ID_ANY;
- item->name_change.new.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
cmd_match.cmd.size = sizeof(cmd_match.cmd) + item->size;
r = ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match);
@@ -767,8 +788,8 @@ int _dbus_kernel_enable_name_owner_notify(int fd)
item = cmd_match.cmd.items;
item->type = KDBUS_ITEM_NAME_CHANGE;
item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->name_change);
- item->name_change.old.id = KDBUS_MATCH_ID_ANY;
- item->name_change.new.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
cmd_match.cmd.size = sizeof(cmd_match.cmd) + item->size;
r = ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match);
@@ -779,8 +800,8 @@ int _dbus_kernel_enable_name_owner_notify(int fd)
item = cmd_match.cmd.items;
item->type = KDBUS_ITEM_NAME_REMOVE;
item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->name_change);
- item->name_change.old.id = KDBUS_MATCH_ID_ANY;
- item->name_change.new.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
+ item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
cmd_match.cmd.size = sizeof(cmd_match.cmd) + item->size;
r = ioctl(fd, KDBUS_CMD_MATCH_ADD, &cmd_match);
@@ -793,28 +814,44 @@ int _dbus_kernel_enable_name_owner_notify(int fd)
uint64_t _dbus_kernel_get_name_owner(int fd, void *kdbus_pool,
const char *name)
{
- struct kdbus_cmd_name_list cmd;
- struct kdbus_name_list *list;
- const struct kdbus_cmd_name *entry, *end;
+ struct kdbus_cmd_list cmd;
+ struct kdbus_cmd_free cmd_free;
+ struct kdbus_info *entry, *end;
+ struct kdbus_item *item;
+ const char *entry_name;
uint64_t owner_id = 0;
memset(&cmd, 0, sizeof(cmd));
- cmd.flags = KDBUS_NAME_LIST_NAMES;
+ cmd.size = sizeof(cmd);
+ cmd.flags = KDBUS_LIST_NAMES;
- if (ioctl(fd, KDBUS_CMD_NAME_LIST, &cmd) < 0)
+ if (ioctl(fd, KDBUS_CMD_LIST, &cmd) < 0)
return 0;
- list = (struct kdbus_name_list *) (kdbus_pool + cmd.offset);
- end = (void *) list + list->size;
+ entry = kdbus_pool + cmd.offset;
+ end = (void *) entry + cmd.list_size;
+
+ for (; entry < end; entry = (void *) entry + entry->size) {
+ entry_name = NULL;
+
+ KDBUS_ITEM_FOREACH(item, entry, items) {
+ if (item->type == KDBUS_ITEM_OWNED_NAME) {
+ entry_name = item->name.name;
+ break;
+ }
+ }
- for (entry = list->names; entry < end;
- entry = (void *) entry + entry->size)
- if (!strcmp(entry->name, name)) {
- owner_id = entry->owner_id;
+ if (entry_name && !strcmp(entry_name, name)) {
+ owner_id = entry->id;
break;
}
+ }
+
+ memset(&cmd_free, 0, sizeof(cmd_free));
+ cmd_free.size = sizeof(cmd_free);
+ cmd_free.offset = cmd.offset;
- ioctl(fd, KDBUS_CMD_FREE, &cmd.offset);
+ ioctl(fd, KDBUS_CMD_FREE, &cmd_free);
return owner_id;
}
diff --git a/ell/dbus.c b/ell/dbus.c
index a816dd3..0276fe3 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -1000,6 +1000,10 @@ static void kdbus_name_owner_change_func(const char *name, uint64_t old_owner,
struct kdbus_message_recv_data *recv_data = user_data;
char owner[32];
+ l_util_debug(recv_data->dbus->debug_handler,
+ recv_data->dbus->debug_data,
+ "Read KDBUS Name Owner Change notification");
+
snprintf(owner, sizeof(owner), ":1.%" PRIu64, new_owner);
_dbus_filter_name_owner_notify(recv_data->dbus->filter, name, owner);
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 13/15] dbus: Add message filter public API.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (10 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 12/15] dbus-kernel: Update kdbus API usage to current version Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 18:04 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 14/15] unit: Use the message filter API in dbus tests Andrew Zaborowski
` (2 subsequent siblings)
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 5265 bytes --]
A do-it-all single method to add a signal filter, an alternative would
be to add a bunch of functions for specific use cases.
---
ell/dbus.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/dbus.h | 7 ++++
2 files changed, 130 insertions(+)
diff --git a/ell/dbus.c b/ell/dbus.c
index 0276fe3..b9864bd 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -555,6 +555,8 @@ static void dbus_init(struct l_dbus *dbus, int fd)
dbus->signal_list = l_hashmap_new();
dbus->tree = _dbus_object_tree_new();
+
+ dbus->filter = _dbus_filter_new(dbus, &dbus->driver->filter_ops);
}
static void classic_free(struct l_dbus *dbus)
@@ -1228,6 +1230,8 @@ LIB_EXPORT void l_dbus_destroy(struct l_dbus *dbus)
if (dbus->ready_destroy)
dbus->ready_destroy(dbus->ready_data);
+ _dbus_filter_free(dbus->filter);
+
l_hashmap_destroy(dbus->signal_list, signal_list_destroy);
l_hashmap_destroy(dbus->message_list, message_list_destroy);
l_queue_destroy(dbus->message_queue, message_queue_destroy);
@@ -1888,3 +1892,122 @@ LIB_EXPORT bool l_dbus_remove_watch(struct l_dbus *dbus, unsigned int id)
{
return l_dbus_unregister(dbus, id);
}
+
+/**
+ * l_dbus_add_signal_watch:
+ * @dbus: D-Bus connection
+ * @sender: bus name to match the signal sender against or NULL to
+ * match any sender
+ * @path: object path to match the signal path against or NULL to
+ * match any path
+ * @interface: interface name to match the signal interface against
+ * or NULL to match any interface
+ * @member: name to match the signal name against or NULL to match any
+ * signal
+ * @...: a list of further conditions to be met by the signal followed
+ * by three more mandatory parameters:
+ * enum l_dbus_match_type list_end_marker,
+ * l_dbus_message_func callback,
+ * void *user_data,
+ * The value L_DBUS_MATCH_NONE must be passed as the end of list
+ * marker, followed by the signal match callback and user_data.
+ * In the list, every condition is a pair of parameters:
+ * enum l_dbus_match_type match_type, const char *value.
+ *
+ * Subscribe to a group of signals based on a set of conditions that
+ * compare the signal's header fields and string arguments against given
+ * values. For example:
+ * signal_id = l_dbus_add_signal_watch(bus, "org.example", "/"
+ * "org.example.Manager",
+ * "PropertyChanged",
+ * L_DBUS_MATCH_ARGUMENT(0),
+ * "ExampleProperty",
+ * L_DBUS_MATCH_NONE
+ * manager_property_change_cb,
+ * NULL);
+ *
+ * Returns: a non-zero signal filter identifier that can be passed to
+ * l_dbus_remove_signal_watch to remove this filter rule, or
+ * zero on failure.
+ **/
+LIB_EXPORT unsigned int l_dbus_add_signal_watch(struct l_dbus *dbus,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member, ...)
+{
+ struct _dbus_filter_condition *rule;
+ int rule_len;
+ va_list args;
+ const char *value;
+ l_dbus_message_func_t signal_func;
+ enum l_dbus_match_type type;
+ void *user_data;
+ unsigned int id;
+
+ va_start(args, member);
+
+ rule_len = 0;
+ while ((type = va_arg(args, enum l_dbus_match_type)) !=
+ L_DBUS_MATCH_NONE)
+ rule_len++;
+
+ va_end(args);
+
+ rule = l_new(struct _dbus_filter_condition, rule_len + 5);
+
+ rule_len = 0;
+
+ rule[rule_len].type = L_DBUS_MATCH_TYPE;
+ rule[rule_len++].value = "signal";
+
+ if (sender) {
+ rule[rule_len].type = L_DBUS_MATCH_SENDER;
+ rule[rule_len++].value = sender;
+ }
+
+ if (path) {
+ rule[rule_len].type = L_DBUS_MATCH_PATH;
+ rule[rule_len++].value = path;
+ }
+
+ if (interface) {
+ rule[rule_len].type = L_DBUS_MATCH_INTERFACE;
+ rule[rule_len++].value = interface;
+ }
+
+ if (member) {
+ rule[rule_len].type = L_DBUS_MATCH_MEMBER;
+ rule[rule_len++].value = member;
+ }
+
+ va_start(args, member);
+
+ while (true) {
+ type = va_arg(args, enum l_dbus_match_type);
+ if (type == L_DBUS_MATCH_NONE)
+ break;
+
+ value = va_arg(args, const char *);
+
+ rule[rule_len].type = type;
+ rule[rule_len++].value = value;
+ }
+
+ signal_func = va_arg(args, l_dbus_message_func_t);
+ user_data = va_arg(args, void *);
+
+ va_end(args);
+
+ id = _dbus_filter_add_rule(dbus->filter, rule, rule_len,
+ signal_func, user_data);
+
+ l_free(rule);
+
+ return id;
+}
+
+LIB_EXPORT bool l_dbus_remove_signal_watch(struct l_dbus *dbus, unsigned int id)
+{
+ return _dbus_filter_remove_rule(dbus->filter, id);
+}
diff --git a/ell/dbus.h b/ell/dbus.h
index 083f2ff..0f20499 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -245,6 +245,13 @@ unsigned int l_dbus_add_disconnect_watch(struct l_dbus *dbus,
l_dbus_destroy_func_t destroy);
bool l_dbus_remove_watch(struct l_dbus *dbus, unsigned int id);
+unsigned int l_dbus_add_signal_watch(struct l_dbus *dbus,
+ const char *sender,
+ const char *path,
+ const char *interface,
+ const char *member, ...);
+bool l_dbus_remove_signal_watch(struct l_dbus *dbus, unsigned int id);
+
#ifdef __cplusplus
}
#endif
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 14/15] unit: Use the message filter API in dbus tests.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (11 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 13/15] dbus: Add message filter public API Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 18:06 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 15/15] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
2016-03-24 14:35 ` [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Denis Kenzior
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 7478 bytes --]
---
unit/test-dbus-properties.c | 142 +++++++++++++++++++++-----------------------
unit/test-kdbus.c | 3 +-
2 files changed, 69 insertions(+), 76 deletions(-)
diff --git a/unit/test-dbus-properties.c b/unit/test-dbus-properties.c
index f1aa406..be91dd3 100644
--- a/unit/test-dbus-properties.c
+++ b/unit/test-dbus-properties.c
@@ -665,56 +665,10 @@ static void signal_timeout_callback(struct l_timeout *timeout, void *user_data)
static bool old_signal_received, new_signal_received;
static bool signal_success;
-static void test_signal_callback(struct l_dbus_message *message)
+static void test_check_signal_success(void)
{
- const char *interface, *member, *property, *value;
- struct l_dbus_message_iter variant, changed, invalidated;
struct l_dbus_message *call;
- if (!signal_timeout)
- return;
-
- interface = l_dbus_message_get_interface(message);
- member = l_dbus_message_get_member(message);
-
- if (!strcmp(interface, "org.test") &&
- !strcmp(member, "PropertyChanged")) {
- test_assert(l_dbus_message_get_arguments(message, "sv",
- &property,
- &variant));
- test_assert(!strcmp(property, "String"));
- test_assert(l_dbus_message_iter_get_variant(&variant, "s",
- &value));
- test_assert(!strcmp(value, "foo"));
-
- test_assert(!old_signal_received);
- old_signal_received = true;
- }
-
- if (!strcmp(interface, "org.freedesktop.DBus.Properties") &&
- !strcmp(member, "PropertiesChanged")) {
- test_assert(l_dbus_message_get_arguments(message, "sa{sv}as",
- &interface,
- &changed,
- &invalidated));
- test_assert(!strcmp(interface, "org.test"));
-
- test_assert(l_dbus_message_iter_next_entry(&changed, &property,
- &variant));
- test_assert(!strcmp(property, "String"));
- test_assert(l_dbus_message_iter_get_variant(&variant, "s",
- &value));
- test_assert(!strcmp(value, "foo"));
-
- test_assert(!l_dbus_message_iter_next_entry(&changed, &property,
- &variant));
- test_assert(!l_dbus_message_iter_next_entry(&invalidated,
- &property));
-
- test_assert(!new_signal_received);
- new_signal_received = true;
- }
-
if (!old_signal_received || !new_signal_received)
return;
@@ -751,6 +705,57 @@ static void test_signal_callback(struct l_dbus_message *message)
}
}
+static void test_old_signal_callback(struct l_dbus_message *message,
+ void *user_data)
+{
+ const char *property, *value;
+ struct l_dbus_message_iter variant;
+
+ if (!signal_timeout)
+ return;
+
+ test_assert(l_dbus_message_get_arguments(message, "sv",
+ &property, &variant));
+ test_assert(!strcmp(property, "String"));
+ test_assert(l_dbus_message_iter_get_variant(&variant, "s", &value));
+ test_assert(!strcmp(value, "foo"));
+
+ test_assert(!old_signal_received);
+ old_signal_received = true;
+
+ test_check_signal_success();
+}
+
+static void test_new_signal_callback(struct l_dbus_message *message,
+ void *user_data)
+{
+ const char *interface, *property, *value;
+ struct l_dbus_message_iter variant, changed, invalidated;
+
+ if (!signal_timeout)
+ return;
+
+ test_assert(l_dbus_message_get_arguments(message, "sa{sv}as",
+ &interface, &changed,
+ &invalidated));
+
+ test_assert(l_dbus_message_iter_next_entry(&changed, &property,
+ &variant));
+ test_assert(!strcmp(property, "String"));
+ test_assert(l_dbus_message_iter_get_variant(&variant, "s", &value));
+ test_assert(!strcmp(value, "foo"));
+
+ test_assert(!l_dbus_message_iter_next_entry(&changed, &property,
+ &variant));
+ test_assert(!l_dbus_message_iter_next_entry(&invalidated,
+ &property));
+
+ test_assert(!new_signal_received);
+ new_signal_received = true;
+
+ test_check_signal_success();
+}
+
static void test_property_signals(struct l_dbus *dbus, void *test_data)
{
old_signal_received = false;
@@ -837,7 +842,7 @@ static void om_signal_timeout_callback(struct l_timeout *timeout,
static bool expect_interfaces_added;
-static void root_signal_callback(struct l_dbus_message *message)
+static void om_signal_callback(struct l_dbus_message *message, void *user_data)
{
const char *path, *interface, *member;
struct l_dbus_message_iter interfaces, properties;
@@ -845,12 +850,8 @@ static void root_signal_callback(struct l_dbus_message *message)
if (!om_signal_timeout)
return;
- interface = l_dbus_message_get_interface(message);
member = l_dbus_message_get_member(message);
- if (strcmp(interface, "org.freedesktop.DBus.ObjectManager"))
- return;
-
if (!strcmp(member, "InterfacesAdded"))
test_assert(expect_interfaces_added);
else if (!strcmp(member, "InterfacesRemoved"))
@@ -909,25 +910,11 @@ static void test_object_manager_signals(struct l_dbus *dbus, void *test_data)
NULL));
}
-static void signal_message(struct l_dbus_message *message, void *user_data)
-{
- const char *path;
-
- path = l_dbus_message_get_path(message);
-
- if (!strcmp(path, "/test"))
- test_signal_callback(message);
-
- if (!strcmp(path, "/"))
- root_signal_callback(message);
-}
-
int main(int argc, char *argv[])
{
struct l_signal *signal;
sigset_t mask;
int i;
- struct l_dbus_message *call;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
@@ -951,15 +938,6 @@ int main(int argc, char *argv[])
l_dbus_set_ready_handler(dbus, ready_callback, dbus, NULL);
l_dbus_set_disconnect_handler(dbus, disconnect_callback, NULL, NULL);
- l_dbus_register(dbus, signal_message, NULL, NULL);
-
- call = l_dbus_message_new_method_call(dbus, "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "AddMatch");
- l_dbus_message_set_arguments(call, "s", "type=signal,sender=org.test");
- l_dbus_send(dbus, call);
-
l_dbus_method_call(dbus, "org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus", "RequestName",
@@ -983,11 +961,25 @@ int main(int argc, char *argv[])
goto done;
}
+ l_dbus_add_signal_watch(dbus, "org.test", "/test", "org.test",
+ "PropertyChanged", L_DBUS_MATCH_NONE,
+ test_old_signal_callback, NULL);
+ l_dbus_add_signal_watch(dbus, "org.test", "/test",
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged", L_DBUS_MATCH_ARGUMENT(0),
+ "org.test", L_DBUS_MATCH_NONE,
+ test_new_signal_callback, NULL);
+
if (!l_dbus_object_manager_enable(dbus)) {
l_info("Unable to enable Object Manager");
goto done;
}
+ l_dbus_add_signal_watch(dbus, "org.test", "/",
+ "org.freedesktop.DBus.ObjectManager",
+ NULL, L_DBUS_MATCH_NONE,
+ om_signal_callback, NULL);
+
test_add("Legacy properties get", test_old_get, NULL);
test_add("Legacy properties set", test_old_set, NULL);
test_add("Legacy optional property", test_old_optional_get, NULL);
diff --git a/unit/test-kdbus.c b/unit/test-kdbus.c
index 3a6af3e..dde2596 100644
--- a/unit/test-kdbus.c
+++ b/unit/test-kdbus.c
@@ -174,7 +174,8 @@ int main(int argc, char *argv[])
l_dbus_set_debug(client, do_debug, "[CLIENT] ", NULL);
l_dbus_set_ready_handler(client, client_ready_callback, client, NULL);
- l_dbus_register(client, signal_message, NULL, NULL);
+ l_dbus_add_signal_watch(client, "org.test", NULL, NULL, NULL,
+ L_DBUS_MATCH_NONE, signal_message, NULL);
l_main_run();
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 15/15] dbus: Don't send replies to messages with no reply flag.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (12 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 14/15] unit: Use the message filter API in dbus tests Andrew Zaborowski
@ 2016-03-21 22:10 ` Andrew Zaborowski
2016-03-24 18:12 ` Denis Kenzior
2016-03-24 14:35 ` [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Denis Kenzior
14 siblings, 1 reply; 38+ messages in thread
From: Andrew Zaborowski @ 2016-03-21 22:10 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 3675 bytes --]
Kdbus doesn't store the cookies for messages that have the no reply flag
and throws error when a reply is sent with reply_cookie that it doesn't
know. It's not fatal, but we also save some cycles by not sending the
message. A further change could be made to not even let users create a
message as a return from a method call but that may be confusing.
---
ell/dbus-message.c | 32 +++++++++++++++++++++++++++-----
ell/dbus-private.h | 1 +
ell/dbus.c | 5 +++++
3 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index a7c9699..5ecac8d 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -43,6 +43,7 @@
#define DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED 0x01
#define DBUS_MESSAGE_FLAG_NO_AUTO_START 0x02
+#define DBUS_MESSAGE_FLAG_DISCARD 0x04
#define DBUS_MESSAGE_FIELD_PATH 1
#define DBUS_MESSAGE_FIELD_INTERFACE 2
@@ -185,6 +186,22 @@ LIB_EXPORT bool l_dbus_message_get_no_autostart(struct l_dbus_message *msg)
}
+bool _dbus_message_get_discard(struct l_dbus_message *msg)
+{
+ struct dbus_header *hdr;
+
+ if (unlikely(!msg))
+ return false;
+
+ hdr = msg->header;
+
+ if (hdr->flags & DBUS_MESSAGE_FLAG_DISCARD)
+ return true;
+
+ return false;
+
+}
+
static struct l_dbus_message *message_new_common(uint8_t type, uint8_t flags,
uint8_t version)
{
@@ -285,10 +302,13 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
struct l_dbus_message *message;
struct dbus_header *hdr = method_call->header;
const char *sender;
+ uint8_t flags = DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
+
+ if (l_dbus_message_get_no_reply(method_call))
+ flags |= DBUS_MESSAGE_FLAG_DISCARD;
message = message_new_common(DBUS_MESSAGE_TYPE_METHOD_RETURN,
- DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
- hdr->version);
+ flags, hdr->version);
message->reply_serial = hdr->serial;
@@ -308,14 +328,16 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
struct l_dbus_message *reply;
struct dbus_header *hdr = method_call->header;
const char *sender;
+ uint8_t flags = DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
if (!_dbus_valid_interface(name))
return NULL;
+ if (l_dbus_message_get_no_reply(method_call))
+ flags |= DBUS_MESSAGE_FLAG_DISCARD;
+
vsnprintf(str, sizeof(str), format, args);
- reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
- DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
- hdr->version);
+ reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR, flags, hdr->version);
reply->reply_serial = hdr->serial;
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 0ae4c69..3b40fea 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -108,6 +108,7 @@ void *_dbus_message_get_header(struct l_dbus_message *msg, size_t *out_size);
void _dbus_message_set_serial(struct l_dbus_message *msg, uint32_t serial);
uint32_t _dbus_message_get_serial(struct l_dbus_message *msg);
uint32_t _dbus_message_get_reply_serial(struct l_dbus_message *message);
+bool _dbus_message_get_discard(struct l_dbus_message *msg);
void _dbus_message_set_sender(struct l_dbus_message *message,
const char *sender);
diff --git a/ell/dbus.c b/ell/dbus.c
index b9864bd..d976496 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -1323,6 +1323,11 @@ LIB_EXPORT uint32_t l_dbus_send(struct l_dbus *dbus,
if (unlikely(!dbus || !message))
return 0;
+ if (_dbus_message_get_discard(message)) {
+ l_dbus_message_unref(message);
+ return 0;
+ }
+
return send_message(dbus, false, message, NULL, NULL, NULL);
}
--
2.5.0
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry.
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
` (13 preceding siblings ...)
2016-03-21 22:10 ` [PATCH 15/15] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
@ 2016-03-24 14:35 ` Denis Kenzior
14 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 14:35 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 413 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> This will be used for the get_nth_string_argument function in
> dbus-message.c. There seems to be no other way to skip over an iterator
> entry without knowing the data type.
> ---
> ell/dbus-private.h | 1 +
> ell/dbus-util.c | 16 ++++++++++++++++
> 2 files changed, 17 insertions(+)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry.
2016-03-21 22:10 ` [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry Andrew Zaborowski
@ 2016-03-24 14:35 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 14:35 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 415 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> This will be used for the get_nth_string_argument function in
> dbus-message.c. There seems to be no other way to skip over an iterator
> entry without knowing the data type.
> ---
> ell/gvariant-private.h | 1 +
> ell/gvariant-util.c | 10 ++++++++++
> 2 files changed, 11 insertions(+)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 03/15] dbus: Add _dbus_message_get_nth_string_argument
2016-03-21 22:10 ` [PATCH 03/15] dbus: Add _dbus_message_get_nth_string_argument Andrew Zaborowski
@ 2016-03-24 14:35 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 14:35 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 402 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> We happen to need to access n-th argument specifically only if it is
> of a string type in at least three places, so add this shortcut.
> ---
> ell/dbus-message.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> ell/dbus-private.h | 2 ++
> 2 files changed, 47 insertions(+)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 04/15] dbus: Support 2+ arguments in l_dbus_message_get_error
2016-03-21 22:10 ` [PATCH 04/15] dbus: Support 2+ arguments in l_dbus_message_get_error Andrew Zaborowski
@ 2016-03-24 14:36 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 14:36 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 326 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> Error messages may have any number of arguments, the first one is still
> the error string if it's a string.
> ---
> ell/dbus-message.c | 13 +++----------
> 1 file changed, 3 insertions(+), 10 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 05/15] dbus: Fix _dbus_kernel_calculate_bloom for multiple arguments.
2016-03-21 22:10 ` [PATCH 05/15] dbus: Fix _dbus_kernel_calculate_bloom for multiple arguments Andrew Zaborowski
@ 2016-03-24 14:39 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 14:39 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2853 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> It seems that l_dbus_message_iter_get_type can't be used to get the
Its for sure :)
> value of a single argument and be called repeatedly, it might crash if
> the number and types of call arguments don't match the message arguments.
> Add a comment explaining why arguments after first non-string argument
> are not considered.
> ---
> ell/dbus-message.c | 34 ++++++++++++++++++++++++++++------
> 1 file changed, 28 insertions(+), 6 deletions(-)
>
> diff --git a/ell/dbus-message.c b/ell/dbus-message.c
> index 0b412b2..a7c9699 100644
> --- a/ell/dbus-message.c
> +++ b/ell/dbus-message.c
> @@ -1419,6 +1419,7 @@ bool _dbus_kernel_calculate_bloom(struct l_dbus_message *message,
> struct l_dbus_message_iter iter;
> uint8_t argn;
> char buf[256];
> + bool (*get_basic)(struct l_dbus_message_iter *, char, void *);
>
> /* The string "interface:" suffixed by the interface name */
> attr = l_dbus_message_get_interface(message);
> @@ -1462,17 +1463,38 @@ bool _dbus_kernel_calculate_bloom(struct l_dbus_message *message,
>
> body = _dbus_message_get_body(message, &body_size);
>
> - if (_dbus_message_is_gvariant(message))
> - _gvariant_iter_init(&iter, message, signature, NULL,
> - body, body_size);
> - else
> + if (_dbus_message_is_gvariant(message)) {
> + if (!_gvariant_iter_init(&iter, message, signature, NULL,
> + body, body_size))
> + return false;
> +
> + get_basic = _gvariant_iter_next_entry_basic;
> + } else {
> _dbus1_iter_init(&iter, message, signature, NULL,
> - body, body_size);
> + body, body_size);
> +
> + get_basic = _dbus1_iter_next_entry_basic;
> + }
>
> argn = 0;
>
> + /*
> + * Stop iteration on the first non-string argument even though
> + * this may lead to legitimate signals not reaching peers that
> + * have set up seemingly correct kernel-side filters.
What's this 'legitimate' business ;) Can we simply quote DBUS1-PORTING
document or whatever from libsystemd sd-bus?
> + *
> + * "If the first argument of the message is a string,
> + * "arg0-slash-prefix" suffixed with the first argument, and also
> + * all prefixes of the argument (cut off at "/"), also prefixed
> + * with "arg0-slash-prefix".
> + *
> + * Similar for all further arguments that are strings up to 63,
> + * for the arguments and their "dot" and "slash" prefixes. On the
> + * first argument that is not a string, addition to the bloom
> + * filter should be stopped however."
> + */
> while (*signature == 's' || *signature == 'o' || *signature == 'g') {
> - if (!message_iter_next_entry(&iter, &attr))
> + if (!get_basic(&iter, *signature, &attr))
> return false;
>
> sprintf(buf, "arg%hhu", argn);
>
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 06/15] dbus: Add message filter logic in dbus-filter.c
2016-03-21 22:10 ` [PATCH 06/15] dbus: Add message filter logic in dbus-filter.c Andrew Zaborowski
@ 2016-03-24 16:36 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 16:36 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 465 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> This will be used for the public API for adding and removing signal
> callbacks.
> ---
> Makefile.am | 1 +
> ell/dbus-filter.c | 351 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> ell/dbus-private.h | 31 +++++
> ell/dbus.h | 12 ++
> 4 files changed, 395 insertions(+)
> create mode 100644 ell/dbus-filter.c
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 07/15] unit: Add dbus message filter tests.
2016-03-21 22:10 ` [PATCH 07/15] unit: Add dbus message filter tests Andrew Zaborowski
@ 2016-03-24 16:37 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 16:37 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 239 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> ---
> unit/test-dbus-watch.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 229 insertions(+)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 08/15] dbus-filter: Name owner change tracking support.
2016-03-21 22:10 ` [PATCH 08/15] dbus-filter: Name owner change tracking support Andrew Zaborowski
@ 2016-03-24 17:28 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 17:28 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 598 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> This is needed because incoming message callbacks normally care what
> Well-known Bus Name the message comes from but the sender field of the
> message normally stores unique bus names in classic dbus. The
> Well-known names may be re-assigned to different unique names while the
> rule is in place.
> ---
> ell/dbus-filter.c | 183 ++++++++++++++++++++++++++++++++++++++++++-----------
> ell/dbus-private.h | 4 ++
> 2 files changed, 151 insertions(+), 36 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 09/15] dbus: Classic dbus filter_ops implementation.
2016-03-21 22:10 ` [PATCH 09/15] dbus: Classic dbus filter_ops implementation Andrew Zaborowski
@ 2016-03-24 17:41 ` Denis Kenzior
2016-03-25 23:30 ` Andrzej Zaborowski
0 siblings, 1 reply; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 17:41 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1846 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> For the name owner tracking I decided to subscribe to all name
> owner changes instead of adding separate rules for every name because
> in some scenarios that saves us cycles/memory and we don't have
> to hold a list of IDs of every such rule so that we could remove them
> when no longer needed.
> ---
> ell/dbus.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 135 insertions(+)
>
I went ahead and applied this one.
One thought / suggestion below:
> +static bool classic_remove_match(struct l_dbus *dbus, unsigned int id)
> +{
> + struct l_dbus_classic *classic =
> + container_of(dbus, struct l_dbus_classic, super);
> + char *match_str = l_hashmap_remove(classic->match_strings,
> + L_UINT_TO_PTR(id));
DBus-1 doesn't reference the AddMatch/RemoveMatch stuff by id, so we
store the match strings here for future lookup.
In theory, we could get rid of this hashmap by sending in the full rule
set into the remove_match method as well. If I grok things correctly,
the information is present in the filter_node structures, we'd just need
to build the rule set during remove_recurse, which can be done with a
simple stack structure.
This should save us some run-time memory at the expense of a bit more
processing.
> + struct l_dbus_message *message;
> +
> + if (!match_str)
> + return false;
> +
> + message = l_dbus_message_new_method_call(dbus,
> + DBUS_SERVICE_DBUS,
> + DBUS_PATH_DBUS,
> + L_DBUS_INTERFACE_DBUS,
> + "RemoveMatch");
> +
> + l_dbus_message_set_arguments(message, "s", match_str);
> +
> + send_message(dbus, false, message, NULL, NULL, NULL);
> +
> + l_free(match_str);
> +
> + return true;
> +}
> +
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 10/15] dbus: kdbus filter_ops implementation.
2016-03-21 22:10 ` [PATCH 10/15] dbus: kdbus " Andrew Zaborowski
@ 2016-03-24 17:51 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 17:51 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 668 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> For the name owner tracking I decided to subscribe to all name
> owner changes instead of adding separate rules for every name because
> in some scenarios that saves us cycles/memory and we don't have
> to hold a list of IDs of every such rule so that we could remove them
> when no longer needed.
> ---
> ell/dbus-kernel.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++-----
> ell/dbus-private.h | 17 ++++-
> ell/dbus.c | 151 +++++++++++++++++++++++++++++----------
> 3 files changed, 313 insertions(+), 57 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 11/15] linux: Update kdbus.h to current github version.
2016-03-21 22:10 ` [PATCH 11/15] linux: Update kdbus.h to current github version Andrew Zaborowski
@ 2016-03-24 17:52 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 17:52 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 257 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> ---
> linux/kdbus.h | 1061 +++++++++++++++++++++++++++++----------------------------
> 1 file changed, 547 insertions(+), 514 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 12/15] dbus-kernel: Update kdbus API usage to current version.
2016-03-21 22:10 ` [PATCH 12/15] dbus-kernel: Update kdbus API usage to current version Andrew Zaborowski
@ 2016-03-24 17:52 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 17:52 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 288 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> ---
> ell/dbus-kernel.c | 117 +++++++++++++++++++++++++++++++++++-------------------
> ell/dbus.c | 4 ++
> 2 files changed, 81 insertions(+), 40 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 13/15] dbus: Add message filter public API.
2016-03-21 22:10 ` [PATCH 13/15] dbus: Add message filter public API Andrew Zaborowski
@ 2016-03-24 18:04 ` Denis Kenzior
2016-03-25 23:45 ` Andrzej Zaborowski
0 siblings, 1 reply; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 18:04 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2588 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> A do-it-all single method to add a signal filter, an alternative would
> be to add a bunch of functions for specific use cases.
> ---
> ell/dbus.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ell/dbus.h | 7 ++++
> 2 files changed, 130 insertions(+)
>
Applied. One more thought below:
> +LIB_EXPORT unsigned int l_dbus_add_signal_watch(struct l_dbus *dbus,
> + const char *sender,
> + const char *path,
> + const char *interface,
> + const char *member, ...)
> +{
> + struct _dbus_filter_condition *rule;
> + int rule_len;
> + va_list args;
> + const char *value;
> + l_dbus_message_func_t signal_func;
> + enum l_dbus_match_type type;
> + void *user_data;
> + unsigned int id;
> +
> + va_start(args, member);
> +
> + rule_len = 0;
> + while ((type = va_arg(args, enum l_dbus_match_type)) !=
> + L_DBUS_MATCH_NONE)
> + rule_len++;
> +
> + va_end(args);
> +
> + rule = l_new(struct _dbus_filter_condition, rule_len + 5);
> +
> + rule_len = 0;
> +
> + rule[rule_len].type = L_DBUS_MATCH_TYPE;
> + rule[rule_len++].value = "signal";
> +
> + if (sender) {
> + rule[rule_len].type = L_DBUS_MATCH_SENDER;
> + rule[rule_len++].value = sender;
> + }
Does it make sense to make glob-match values part of the tree?
For example, I can install watch 1 with:
type='signal', path='/'
and watch 2 with:
type='signal', sender='org.foo', path='/'
Right now it seems we will generate 2 AddMatch cases for the above, even
though watch 2 is already covered by watch 1.
> +
> + if (path) {
> + rule[rule_len].type = L_DBUS_MATCH_PATH;
> + rule[rule_len++].value = path;
> + }
> +
> + if (interface) {
> + rule[rule_len].type = L_DBUS_MATCH_INTERFACE;
> + rule[rule_len++].value = interface;
> + }
> +
> + if (member) {
> + rule[rule_len].type = L_DBUS_MATCH_MEMBER;
> + rule[rule_len++].value = member;
> + }
> +
> + va_start(args, member);
> +
> + while (true) {
> + type = va_arg(args, enum l_dbus_match_type);
> + if (type == L_DBUS_MATCH_NONE)
> + break;
> +
> + value = va_arg(args, const char *);
> +
> + rule[rule_len].type = type;
> + rule[rule_len++].value = value;
> + }
> +
> + signal_func = va_arg(args, l_dbus_message_func_t);
> + user_data = va_arg(args, void *);
> +
> + va_end(args);
> +
> + id = _dbus_filter_add_rule(dbus->filter, rule, rule_len,
> + signal_func, user_data);
> +
> + l_free(rule);
> +
> + return id;
> +}
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 14/15] unit: Use the message filter API in dbus tests.
2016-03-21 22:10 ` [PATCH 14/15] unit: Use the message filter API in dbus tests Andrew Zaborowski
@ 2016-03-24 18:06 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 18:06 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 295 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> ---
> unit/test-dbus-properties.c | 142 +++++++++++++++++++++-----------------------
> unit/test-kdbus.c | 3 +-
> 2 files changed, 69 insertions(+), 76 deletions(-)
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 15/15] dbus: Don't send replies to messages with no reply flag.
2016-03-21 22:10 ` [PATCH 15/15] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
@ 2016-03-24 18:12 ` Denis Kenzior
2016-03-25 23:52 ` Andrzej Zaborowski
0 siblings, 1 reply; 38+ messages in thread
From: Denis Kenzior @ 2016-03-24 18:12 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 4314 bytes --]
Hi Andrew,
On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
> Kdbus doesn't store the cookies for messages that have the no reply flag
> and throws error when a reply is sent with reply_cookie that it doesn't
> know. It's not fatal, but we also save some cycles by not sending the
> message. A further change could be made to not even let users create a
> message as a return from a method call but that may be confusing.
> ---
> ell/dbus-message.c | 32 +++++++++++++++++++++++++++-----
> ell/dbus-private.h | 1 +
> ell/dbus.c | 5 +++++
> 3 files changed, 33 insertions(+), 5 deletions(-)
>
> diff --git a/ell/dbus-message.c b/ell/dbus-message.c
> index a7c9699..5ecac8d 100644
> --- a/ell/dbus-message.c
> +++ b/ell/dbus-message.c
> @@ -43,6 +43,7 @@
>
> #define DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED 0x01
> #define DBUS_MESSAGE_FLAG_NO_AUTO_START 0x02
> +#define DBUS_MESSAGE_FLAG_DISCARD 0x04
No, you're over-riding the ALLOW_INTERACTIVE_AUTHORIZATION flag.
>
> #define DBUS_MESSAGE_FIELD_PATH 1
> #define DBUS_MESSAGE_FIELD_INTERFACE 2
> @@ -185,6 +186,22 @@ LIB_EXPORT bool l_dbus_message_get_no_autostart(struct l_dbus_message *msg)
>
> }
>
> +bool _dbus_message_get_discard(struct l_dbus_message *msg)
> +{
> + struct dbus_header *hdr;
> +
> + if (unlikely(!msg))
> + return false;
> +
> + hdr = msg->header;
> +
> + if (hdr->flags & DBUS_MESSAGE_FLAG_DISCARD)
> + return true;
No, please don't do it this way. hdr gets sent over the wire. We need
to store this flag locally. Lets just add
bool discard : 1;
to struct l_dbus_message
> +
> + return false;
> +
Spurious whitespace
> +}
> +
> static struct l_dbus_message *message_new_common(uint8_t type, uint8_t flags,
> uint8_t version)
> {
> @@ -285,10 +302,13 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
> struct l_dbus_message *message;
> struct dbus_header *hdr = method_call->header;
> const char *sender;
> + uint8_t flags = DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
> +
> + if (l_dbus_message_get_no_reply(method_call))
> + flags |= DBUS_MESSAGE_FLAG_DISCARD;
>
> message = message_new_common(DBUS_MESSAGE_TYPE_METHOD_RETURN,
> - DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
> - hdr->version);
> + flags, hdr->version);
if (l_dbus_message_get_no_reply(method_call))
message->discard = true;
>
> message->reply_serial = hdr->serial;
>
> @@ -308,14 +328,16 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
> struct l_dbus_message *reply;
> struct dbus_header *hdr = method_call->header;
> const char *sender;
> + uint8_t flags = DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
>
> if (!_dbus_valid_interface(name))
> return NULL;
>
> + if (l_dbus_message_get_no_reply(method_call))
> + flags |= DBUS_MESSAGE_FLAG_DISCARD;
> +
> vsnprintf(str, sizeof(str), format, args);
> - reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
> - DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
> - hdr->version);
> + reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR, flags, hdr->version);
>
> reply->reply_serial = hdr->serial;
>
> diff --git a/ell/dbus-private.h b/ell/dbus-private.h
> index 0ae4c69..3b40fea 100644
> --- a/ell/dbus-private.h
> +++ b/ell/dbus-private.h
> @@ -108,6 +108,7 @@ void *_dbus_message_get_header(struct l_dbus_message *msg, size_t *out_size);
> void _dbus_message_set_serial(struct l_dbus_message *msg, uint32_t serial);
> uint32_t _dbus_message_get_serial(struct l_dbus_message *msg);
> uint32_t _dbus_message_get_reply_serial(struct l_dbus_message *message);
> +bool _dbus_message_get_discard(struct l_dbus_message *msg);
>
> void _dbus_message_set_sender(struct l_dbus_message *message,
> const char *sender);
> diff --git a/ell/dbus.c b/ell/dbus.c
> index b9864bd..d976496 100644
> --- a/ell/dbus.c
> +++ b/ell/dbus.c
> @@ -1323,6 +1323,11 @@ LIB_EXPORT uint32_t l_dbus_send(struct l_dbus *dbus,
> if (unlikely(!dbus || !message))
> return 0;
>
> + if (_dbus_message_get_discard(message)) {
> + l_dbus_message_unref(message);
> + return 0;
> + }
> +
> return send_message(dbus, false, message, NULL, NULL, NULL);
> }
>
>
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 09/15] dbus: Classic dbus filter_ops implementation.
2016-03-24 17:41 ` Denis Kenzior
@ 2016-03-25 23:30 ` Andrzej Zaborowski
2016-03-26 2:37 ` Denis Kenzior
0 siblings, 1 reply; 38+ messages in thread
From: Andrzej Zaborowski @ 2016-03-25 23:30 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1956 bytes --]
Hi Denis,
On 24 March 2016 at 18:41, Denis Kenzior <denkenz@gmail.com> wrote:
> On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
>>
>> For the name owner tracking I decided to subscribe to all name
>> owner changes instead of adding separate rules for every name because
>> in some scenarios that saves us cycles/memory and we don't have
>> to hold a list of IDs of every such rule so that we could remove them
>> when no longer needed.
>> ---
>> ell/dbus.c | 135
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 135 insertions(+)
>>
>
> I went ahead and applied this one.
>
> One thought / suggestion below:
>
>> +static bool classic_remove_match(struct l_dbus *dbus, unsigned int id)
>> +{
>> + struct l_dbus_classic *classic =
>> + container_of(dbus, struct l_dbus_classic, super);
>> + char *match_str = l_hashmap_remove(classic->match_strings,
>> + L_UINT_TO_PTR(id));
>
>
> DBus-1 doesn't reference the AddMatch/RemoveMatch stuff by id, so we store
> the match strings here for future lookup.
>
> In theory, we could get rid of this hashmap by sending in the full rule set
> into the remove_match method as well. If I grok things correctly, the
> information is present in the filter_node structures, we'd just need to
> build the rule set during remove_recurse, which can be done with a simple
> stack structure.
>
> This should save us some run-time memory at the expense of a bit more
> processing.
Yes, this would be possible. This is similar to how the object tree
in dbus-service.c could rebuild the paths from node pointers but
instead some functions receive the path string and the node pointer to
avoid this. Let's keep thinking if we want to do that, but the IDs
work well for kdbus. If we change this, kdbus could pass a hash of
the rule string as the cookie.
Best regards
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 13/15] dbus: Add message filter public API.
2016-03-24 18:04 ` Denis Kenzior
@ 2016-03-25 23:45 ` Andrzej Zaborowski
2016-03-26 2:42 ` Denis Kenzior
0 siblings, 1 reply; 38+ messages in thread
From: Andrzej Zaborowski @ 2016-03-25 23:45 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 783 bytes --]
Hi Denis,
On 24 March 2016 at 19:04, Denis Kenzior <denkenz@gmail.com> wrote:
> Does it make sense to make glob-match values part of the tree?
>
> For example, I can install watch 1 with:
> type='signal', path='/'
>
> and watch 2 with:
> type='signal', sender='org.foo', path='/'
>
> Right now it seems we will generate 2 AddMatch cases for the above, even
> though watch 2 is already covered by watch 1.
Ah, good point. I think we could handle that also with the current
structure if we allow the nodes to be added to the tree in any order
necessary, so that the "sender='org.foo'" could be a child of
"path='/'" in specific cases. This wouldn't add any cost to the
filtering of incoming signals, only to adding new rules, what do you
think?
Best regards
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 15/15] dbus: Don't send replies to messages with no reply flag.
2016-03-24 18:12 ` Denis Kenzior
@ 2016-03-25 23:52 ` Andrzej Zaborowski
0 siblings, 0 replies; 38+ messages in thread
From: Andrzej Zaborowski @ 2016-03-25 23:52 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2376 bytes --]
Hi Denis,
On 24 March 2016 at 19:12, Denis Kenzior <denkenz@gmail.com> wrote:
> On 03/21/2016 05:10 PM, Andrew Zaborowski wrote:
>> diff --git a/ell/dbus-message.c b/ell/dbus-message.c
>> index a7c9699..5ecac8d 100644
>> --- a/ell/dbus-message.c
>> +++ b/ell/dbus-message.c
>> @@ -43,6 +43,7 @@
>>
>> #define DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED 0x01
>> #define DBUS_MESSAGE_FLAG_NO_AUTO_START 0x02
>> +#define DBUS_MESSAGE_FLAG_DISCARD 0x04
>
>
> No, you're over-riding the ALLOW_INTERACTIVE_AUTHORIZATION flag.
Oops.
>>
>>
>> #define DBUS_MESSAGE_FIELD_PATH 1
>> #define DBUS_MESSAGE_FIELD_INTERFACE 2
>> @@ -185,6 +186,22 @@ LIB_EXPORT bool
>> l_dbus_message_get_no_autostart(struct l_dbus_message *msg)
>>
>> }
>>
>> +bool _dbus_message_get_discard(struct l_dbus_message *msg)
>> +{
>> + struct dbus_header *hdr;
>> +
>> + if (unlikely(!msg))
>> + return false;
>> +
>> + hdr = msg->header;
>> +
>> + if (hdr->flags & DBUS_MESSAGE_FLAG_DISCARD)
>> + return true;
>
>
> No, please don't do it this way. hdr gets sent over the wire. We need to
> store this flag locally. Lets just add
>
> bool discard : 1;
>
> to struct l_dbus_message
Ok.
>
>> +
>> + return false;
>> +
>
>
> Spurious whitespace
>
>> +}
>> +
>> static struct l_dbus_message *message_new_common(uint8_t type, uint8_t
>> flags,
>> uint8_t version)
>> {
>> @@ -285,10 +302,13 @@ LIB_EXPORT struct l_dbus_message
>> *l_dbus_message_new_method_return(
>> struct l_dbus_message *message;
>> struct dbus_header *hdr = method_call->header;
>> const char *sender;
>> + uint8_t flags = DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED;
>> +
>> + if (l_dbus_message_get_no_reply(method_call))
>> + flags |= DBUS_MESSAGE_FLAG_DISCARD;
>>
>> message = message_new_common(DBUS_MESSAGE_TYPE_METHOD_RETURN,
>> -
>> DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
>> - hdr->version);
>> + flags, hdr->version);
>
>
> if (l_dbus_message_get_no_reply(method_call))
> message->discard = true;
Ok, I'll fix this and send a new version.
Best regards
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 09/15] dbus: Classic dbus filter_ops implementation.
2016-03-25 23:30 ` Andrzej Zaborowski
@ 2016-03-26 2:37 ` Denis Kenzior
0 siblings, 0 replies; 38+ messages in thread
From: Denis Kenzior @ 2016-03-26 2:37 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 585 bytes --]
Hi Andrew,
>
> Yes, this would be possible. This is similar to how the object tree
> in dbus-service.c could rebuild the paths from node pointers but
> instead some functions receive the path string and the node pointer to
> avoid this. Let's keep thinking if we want to do that, but the IDs
> work well for kdbus. If we change this, kdbus could pass a hash of
> the rule string as the cookie.
Actually we could send both. The rules and the id to both add and
remove match methods. We already have the id, so no need to calculate
any hashes.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 13/15] dbus: Add message filter public API.
2016-03-25 23:45 ` Andrzej Zaborowski
@ 2016-03-26 2:42 ` Denis Kenzior
2016-03-26 15:22 ` Andrzej Zaborowski
0 siblings, 1 reply; 38+ messages in thread
From: Denis Kenzior @ 2016-03-26 2:42 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1146 bytes --]
Hi Andrew,
On 03/25/2016 06:45 PM, Andrzej Zaborowski wrote:
> Hi Denis,
>
> On 24 March 2016 at 19:04, Denis Kenzior <denkenz@gmail.com> wrote:
>> Does it make sense to make glob-match values part of the tree?
>>
>> For example, I can install watch 1 with:
>> type='signal', path='/'
>>
>> and watch 2 with:
>> type='signal', sender='org.foo', path='/'
>>
>> Right now it seems we will generate 2 AddMatch cases for the above, even
>> though watch 2 is already covered by watch 1.
>
> Ah, good point. I think we could handle that also with the current
> structure if we allow the nodes to be added to the tree in any order
> necessary, so that the "sender='org.foo'" could be a child of
> "path='/'" in specific cases. This wouldn't add any cost to the
> filtering of incoming signals, only to adding new rules, what do you
> think?
>
Could work, but my first thought is that it would cause lots of
additional processing, since you'd be trying all possible permutations.
Given that we have 4-5 rules on average that's a lot of possibilities
to try. Or were you thinking something else?
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 13/15] dbus: Add message filter public API.
2016-03-26 2:42 ` Denis Kenzior
@ 2016-03-26 15:22 ` Andrzej Zaborowski
2016-03-26 21:53 ` Denis Kenzior
0 siblings, 1 reply; 38+ messages in thread
From: Andrzej Zaborowski @ 2016-03-26 15:22 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1732 bytes --]
On 26 March 2016 at 03:42, Denis Kenzior <denkenz@gmail.com> wrote:
> Hi Andrew,
>
> On 03/25/2016 06:45 PM, Andrzej Zaborowski wrote:
>>
>> Hi Denis,
>>
>> On 24 March 2016 at 19:04, Denis Kenzior <denkenz@gmail.com> wrote:
>>>
>>> Does it make sense to make glob-match values part of the tree?
>>>
>>> For example, I can install watch 1 with:
>>> type='signal', path='/'
>>>
>>> and watch 2 with:
>>> type='signal', sender='org.foo', path='/'
>>>
>>> Right now it seems we will generate 2 AddMatch cases for the above, even
>>> though watch 2 is already covered by watch 1.
>>
>>
>> Ah, good point. I think we could handle that also with the current
>> structure if we allow the nodes to be added to the tree in any order
>> necessary, so that the "sender='org.foo'" could be a child of
>> "path='/'" in specific cases. This wouldn't add any cost to the
>> filtering of incoming signals, only to adding new rules, what do you
>> think?
>>
>
> Could work, but my first thought is that it would cause lots of additional
> processing, since you'd be trying all possible permutations. Given that we
> have 4-5 rules on average that's a lot of possibilities to try. Or were you
> thinking something else?
There would be some additional processing but I think it may be okay.
Now when adding a new rule and we're at a specific node in the tree
we're checking if there's already a child that matches the next
condition in the rule. Instead we could check if there's a match for
any of the yet unused conditions in the rule, and mark that condition
as used or "visited". In the typical case where most rules begin with
a sender value this wouldn't add any overhead I think.
Best regards
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 13/15] dbus: Add message filter public API.
2016-03-26 15:22 ` Andrzej Zaborowski
@ 2016-03-26 21:53 ` Denis Kenzior
2016-03-27 3:48 ` Andrzej Zaborowski
0 siblings, 1 reply; 38+ messages in thread
From: Denis Kenzior @ 2016-03-26 21:53 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2192 bytes --]
Hi Andrew,
On 03/26/2016 10:22 AM, Andrzej Zaborowski wrote:
> On 26 March 2016 at 03:42, Denis Kenzior <denkenz@gmail.com> wrote:
>> Hi Andrew,
>>
>> On 03/25/2016 06:45 PM, Andrzej Zaborowski wrote:
>>>
>>> Hi Denis,
>>>
>>> On 24 March 2016 at 19:04, Denis Kenzior <denkenz@gmail.com> wrote:
>>>>
>>>> Does it make sense to make glob-match values part of the tree?
>>>>
>>>> For example, I can install watch 1 with:
>>>> type='signal', path='/'
>>>>
>>>> and watch 2 with:
>>>> type='signal', sender='org.foo', path='/'
>>>>
>>>> Right now it seems we will generate 2 AddMatch cases for the above, even
>>>> though watch 2 is already covered by watch 1.
>>>
>>>
>>> Ah, good point. I think we could handle that also with the current
>>> structure if we allow the nodes to be added to the tree in any order
>>> necessary, so that the "sender='org.foo'" could be a child of
>>> "path='/'" in specific cases. This wouldn't add any cost to the
>>> filtering of incoming signals, only to adding new rules, what do you
>>> think?
>>>
>>
>> Could work, but my first thought is that it would cause lots of additional
>> processing, since you'd be trying all possible permutations. Given that we
>> have 4-5 rules on average that's a lot of possibilities to try. Or were you
>> thinking something else?
>
> There would be some additional processing but I think it may be okay.
> Now when adding a new rule and we're at a specific node in the tree
> we're checking if there's already a child that matches the next
> condition in the rule. Instead we could check if there's a match for
> any of the yet unused conditions in the rule, and mark that condition
> as used or "visited". In the typical case where most rules begin with
> a sender value this wouldn't add any overhead I think.
>
Lets give it a shot. I ran some mental exercises and can't seem to find
any negatives to the idea besides increasing the add filter cost by a
factor of n, where n = number of rules being added.
The upside is that we could also get rid of the qsort this way. The
silent side-effecting of the input rules is less than ideal.
Regards,
-Denis
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 13/15] dbus: Add message filter public API.
2016-03-26 21:53 ` Denis Kenzior
@ 2016-03-27 3:48 ` Andrzej Zaborowski
0 siblings, 0 replies; 38+ messages in thread
From: Andrzej Zaborowski @ 2016-03-27 3:48 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2380 bytes --]
On 26 March 2016 at 22:53, Denis Kenzior <denkenz@gmail.com> wrote:
> On 03/26/2016 10:22 AM, Andrzej Zaborowski wrote:
>> On 26 March 2016 at 03:42, Denis Kenzior <denkenz@gmail.com> wrote:
>>> On 03/25/2016 06:45 PM, Andrzej Zaborowski wrote:
>>>> I think we could handle that also with the current
>>>> structure if we allow the nodes to be added to the tree in any order
>>>> necessary, so that the "sender='org.foo'" could be a child of
>>>> "path='/'" in specific cases. This wouldn't add any cost to the
>>>> filtering of incoming signals, only to adding new rules, what do you
>>>> think?
>>>>
>>>
>>> Could work, but my first thought is that it would cause lots of
>>> additional
>>> processing, since you'd be trying all possible permutations. Given that
>>> we
>>> have 4-5 rules on average that's a lot of possibilities to try. Or were
>>> you
>>> thinking something else?
>>
>>
>> There would be some additional processing but I think it may be okay.
>> Now when adding a new rule and we're at a specific node in the tree
>> we're checking if there's already a child that matches the next
>> condition in the rule. Instead we could check if there's a match for
>> any of the yet unused conditions in the rule, and mark that condition
>> as used or "visited". In the typical case where most rules begin with
>> a sender value this wouldn't add any overhead I think.
>>
>
> Lets give it a shot. I ran some mental exercises and can't seem to find any
> negatives to the idea besides increasing the add filter cost by a factor of
> n, where n = number of rules being added.
>
> The upside is that we could also get rid of the qsort this way. The silent
> side-effecting of the input rules is less than ideal.
True, but I was actually thinking that we could use the fact that the
elements were already sorted to add some optimization and also that,
even though the tree's shape would be harder to predict, it wlil
probably still be more memory efficient than without sorting.
One optimization would be that when adding a rule to the tree, for
every child node we only have to walk the list of conditions until the
condition type enum is bigger or equal to the child's type enum. For
the easy scenarios that'd mean we only have to compare every child
against one rule condition like we're doing now.
Best regards
^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2016-03-27 3:48 UTC | newest]
Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-21 22:10 [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Andrew Zaborowski
2016-03-21 22:10 ` [PATCH 02/15] gvariant: Add _gvariant_iter_skip_entry Andrew Zaborowski
2016-03-24 14:35 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 03/15] dbus: Add _dbus_message_get_nth_string_argument Andrew Zaborowski
2016-03-24 14:35 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 04/15] dbus: Support 2+ arguments in l_dbus_message_get_error Andrew Zaborowski
2016-03-24 14:36 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 05/15] dbus: Fix _dbus_kernel_calculate_bloom for multiple arguments Andrew Zaborowski
2016-03-24 14:39 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 06/15] dbus: Add message filter logic in dbus-filter.c Andrew Zaborowski
2016-03-24 16:36 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 07/15] unit: Add dbus message filter tests Andrew Zaborowski
2016-03-24 16:37 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 08/15] dbus-filter: Name owner change tracking support Andrew Zaborowski
2016-03-24 17:28 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 09/15] dbus: Classic dbus filter_ops implementation Andrew Zaborowski
2016-03-24 17:41 ` Denis Kenzior
2016-03-25 23:30 ` Andrzej Zaborowski
2016-03-26 2:37 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 10/15] dbus: kdbus " Andrew Zaborowski
2016-03-24 17:51 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 11/15] linux: Update kdbus.h to current github version Andrew Zaborowski
2016-03-24 17:52 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 12/15] dbus-kernel: Update kdbus API usage to current version Andrew Zaborowski
2016-03-24 17:52 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 13/15] dbus: Add message filter public API Andrew Zaborowski
2016-03-24 18:04 ` Denis Kenzior
2016-03-25 23:45 ` Andrzej Zaborowski
2016-03-26 2:42 ` Denis Kenzior
2016-03-26 15:22 ` Andrzej Zaborowski
2016-03-26 21:53 ` Denis Kenzior
2016-03-27 3:48 ` Andrzej Zaborowski
2016-03-21 22:10 ` [PATCH 14/15] unit: Use the message filter API in dbus tests Andrew Zaborowski
2016-03-24 18:06 ` Denis Kenzior
2016-03-21 22:10 ` [PATCH 15/15] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
2016-03-24 18:12 ` Denis Kenzior
2016-03-25 23:52 ` Andrzej Zaborowski
2016-03-24 14:35 ` [PATCH 01/15] dbus: Add _dbus1_message_iter_skip_entry Denis Kenzior
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.