* [PATCH 1/8] dbus: More complete checks when removing nodes.
@ 2016-02-01 14:07 Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 2/8] unit: Update _dbus_object_tree_prune_node call parameters Andrew Zaborowski
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 3841 bytes --]
This addresses two problems with nodes being freed from the object tree
but not from tree->objects.
With the current semantics for _dbus_object_tree_prune_node to not
incorrectly remove parent nodes that are still in tree->objects it
would be sufficient to check if the node has any interface instances
left. But with the ongoing ObjectManager it's better to directly check
the path against tree->objects.
---
ell/dbus-private.h | 4 ++-
ell/dbus-service.c | 72 ++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 56 insertions(+), 20 deletions(-)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index e60d09e..a0ddb35 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -167,7 +167,9 @@ struct object_node *_dbus_object_tree_makepath(struct _dbus_object_tree *tree,
const char *path);
struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
const char *path);
-void _dbus_object_tree_prune_node(struct object_node *node);
+bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
+ struct object_node *node,
+ const char *path);
bool _dbus_object_tree_register(struct _dbus_object_tree *tree,
const char *path, const char *interface,
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
index e082226..9380740 100644
--- a/ell/dbus-service.c
+++ b/ell/dbus-service.c
@@ -636,33 +636,65 @@ struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
return lookup_recurse(tree->root, path);
}
-void _dbus_object_tree_prune_node(struct object_node *node)
+bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
+ struct object_node *node,
+ const char *path)
{
- struct object_node *parent = node->parent;
- struct child_node *p = NULL, *c;
+ struct object_node *parent;
+ struct child_node *p, *c;
+ struct interface_instance *instance;
+ char parentpath[strlen(path) + 1];
+
+ if (!node) {
+ node = l_hashmap_remove(tree->objects, path);
+ if (!node)
+ return false;
+ }
+
+ while ((instance = l_queue_pop_head(node->instances)))
+ interface_instance_free(instance);
+
+ if (node->children || !node->parent)
+ return true;
- while (parent) {
- for (c = parent->children, p = NULL; c; p = c, c = c->next) {
- if (c->node != node)
- continue;
+ /*
+ * Walk up the tree until a node that either has more than one
+ * child, is the root or is in the objects hashmap.
+ */
+ strcpy(parentpath, path);
- if (p)
- p->next = c->next;
- else
- parent->children = c->next;
+ while (true) {
+ parent = node->parent;
- subtree_free(c->node);
- l_free(c);
+ if (parent == tree->root)
+ break;
+ if (parent->children->next)
break;
- }
- if (parent->children != NULL)
- return;
+ /* Parent's path */
+ parentpath[strlen(parentpath) -
+ strlen(parent->children->subpath) - 1] = '\0';
+
+ if (l_hashmap_lookup(tree->objects, parentpath))
+ break;
node = parent;
- parent = node->parent;
}
+
+ for (c = parent->children, p = NULL; c; p = c, c = c->next)
+ if (c->node == node)
+ break;
+
+ if (p)
+ p->next = c->next;
+ else
+ parent->children = c->next;
+
+ l_free(c);
+ subtree_free(node);
+
+ return true;
}
bool _dbus_object_tree_register(struct _dbus_object_tree *tree,
@@ -741,9 +773,11 @@ bool _dbus_object_tree_unregister(struct _dbus_object_tree *tree,
if (instance)
interface_instance_free(instance);
- if (l_queue_isempty(node->instances) && !node->children) {
+ if (l_queue_isempty(node->instances)) {
l_hashmap_remove(tree->objects, path);
- _dbus_object_tree_prune_node(node);
+
+ if (!node->children)
+ _dbus_object_tree_prune_node(tree, node, path);
}
return r;
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/8] unit: Update _dbus_object_tree_prune_node call parameters.
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 3/8] dbus: setters and getters API for properties Andrew Zaborowski
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1058 bytes --]
---
unit/test-dbus-service.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/unit/test-dbus-service.c b/unit/test-dbus-service.c
index 7452269..68c35c1 100644
--- a/unit/test-dbus-service.c
+++ b/unit/test-dbus-service.c
@@ -205,16 +205,16 @@ static void test_dbus_object_tree(const void *test_data)
tmp = _dbus_object_tree_lookup(tree, "/foo/bee");
assert(tmp);
- _dbus_object_tree_prune_node(leaf3);
+ _dbus_object_tree_prune_node(tree, leaf3, "/foo/bee/boo");
tmp = _dbus_object_tree_lookup(tree, "/foo/bee");
assert(!tmp);
tmp = _dbus_object_tree_lookup(tree, "/foo/bar");
assert(tmp);
- _dbus_object_tree_prune_node(leaf2);
+ _dbus_object_tree_prune_node(tree, leaf2, "/foo/bar/ble");
tmp = _dbus_object_tree_lookup(tree, "/foo/bar");
assert(tmp);
- _dbus_object_tree_prune_node(leaf1);
+ _dbus_object_tree_prune_node(tree, leaf1, "/foo/bar/baz");
tmp = _dbus_object_tree_lookup(tree, "/foo/bar");
assert(!tmp);
tmp = _dbus_object_tree_lookup(tree, "/foo");
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/8] dbus: setters and getters API for properties.
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 2/8] unit: Update _dbus_object_tree_prune_node call parameters Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 4/8] dbus: Separate interface registration from instantiation Andrew Zaborowski
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 8853 bytes --]
These setters and getters are not used yet.
(I will split all of the patches by directories when submitting a final
version, this is just for the ease of reviewing)
---
ell/dbus-service.c | 28 ++++++------------
ell/dbus-service.h | 27 ++++++++++++-----
examples/dbus-service.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++--
unit/test-dbus-service.c | 20 ++++++++++++-
4 files changed, 122 insertions(+), 30 deletions(-)
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
index 9380740..70d42f3 100644
--- a/ell/dbus-service.c
+++ b/ell/dbus-service.c
@@ -61,6 +61,8 @@ struct _dbus_signal {
};
struct _dbus_property {
+ l_dbus_property_get_cb_t getter;
+ l_dbus_property_set_cb_t setter;
uint32_t flags;
unsigned char name_len;
char metainfo[];
@@ -191,7 +193,7 @@ void _dbus_property_introspection(struct _dbus_property *info,
l_string_append_printf(buf, "\t\t<property name=\"%s\" type=\"%s\" ",
info->metainfo, signature);
- if (info->flags & L_DBUS_PROPERTY_FLAG_WRITABLE)
+ if (info->setter)
l_string_append(buf, "access=\"readwrite\"");
else
l_string_append(buf, "access=\"read\"");
@@ -375,7 +377,9 @@ LIB_EXPORT bool l_dbus_interface_signal(struct l_dbus_interface *interface,
LIB_EXPORT bool l_dbus_interface_property(struct l_dbus_interface *interface,
const char *name, uint32_t flags,
- const char *signature)
+ const char *signature,
+ l_dbus_property_get_cb_t getter,
+ l_dbus_property_set_cb_t setter)
{
unsigned int metainfo_len;
struct _dbus_property *info;
@@ -384,7 +388,7 @@ LIB_EXPORT bool l_dbus_interface_property(struct l_dbus_interface *interface,
if (!_dbus_valid_method(name))
return false;
- if (unlikely(!signature))
+ if (unlikely(!signature || !getter))
return false;
if (!_dbus_valid_signature(signature))
@@ -397,6 +401,8 @@ LIB_EXPORT bool l_dbus_interface_property(struct l_dbus_interface *interface,
info = l_malloc(sizeof(*info) + metainfo_len);
info->flags = flags;
info->name_len = strlen(name);
+ info->getter = getter;
+ info->setter = setter;
p = stpcpy(info->metainfo, name) + 1;
strcpy(p, signature);
@@ -406,22 +412,6 @@ LIB_EXPORT bool l_dbus_interface_property(struct l_dbus_interface *interface,
return true;
}
-LIB_EXPORT bool l_dbus_interface_ro_property(struct l_dbus_interface *interface,
- const char *name,
- const char *signature)
-{
- return l_dbus_interface_property(interface, name, 0, signature);
-}
-
-LIB_EXPORT bool l_dbus_interface_rw_property(struct l_dbus_interface *interface,
- const char *name,
- const char *signature)
-{
- return l_dbus_interface_property(interface, name,
- L_DBUS_PROPERTY_FLAG_WRITABLE,
- signature);
-}
-
struct l_dbus_interface *_dbus_interface_new(const char *name)
{
struct l_dbus_interface *interface;
diff --git a/ell/dbus-service.h b/ell/dbus-service.h
index ce53082..a1e526e 100644
--- a/ell/dbus-service.h
+++ b/ell/dbus-service.h
@@ -46,13 +46,28 @@ enum l_dbus_signal_flag {
enum l_dbus_property_flag {
L_DBUS_PROPERTY_FLAG_DEPRECATED = 1,
- L_DBUS_PROPERTY_FLAG_WRITABLE = 2,
};
typedef struct l_dbus_message *(*l_dbus_interface_method_cb_t) (struct l_dbus *,
struct l_dbus_message *message,
void *user_data);
+typedef void (*l_dbus_property_complete_cb_t) (struct l_dbus *,
+ struct l_dbus_message *,
+ struct l_dbus_message *error);
+
+typedef void (*l_dbus_property_set_cb_t) (struct l_dbus *,
+ struct l_dbus_message *message,
+ struct l_dbus_message_iter *new_value,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data);
+
+typedef void (*l_dbus_property_get_cb_t) (struct l_dbus *,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data);
+
bool l_dbus_interface_method(struct l_dbus_interface *interface,
const char *name, uint32_t flags,
l_dbus_interface_method_cb_t cb,
@@ -65,13 +80,9 @@ bool l_dbus_interface_signal(struct l_dbus_interface *interface,
bool l_dbus_interface_property(struct l_dbus_interface *interface,
const char *name, uint32_t flags,
- const char *signature);
-bool l_dbus_interface_ro_property(struct l_dbus_interface *interface,
- const char *name,
- const char *signature);
-bool l_dbus_interface_rw_property(struct l_dbus_interface *interface,
- const char *name,
- const char *signature);
+ const char *signature,
+ l_dbus_property_get_cb_t getter,
+ l_dbus_property_set_cb_t setter);
#ifdef __cplusplus
}
diff --git a/examples/dbus-service.c b/examples/dbus-service.c
index 40c1646..e4e5fa7 100644
--- a/examples/dbus-service.c
+++ b/examples/dbus-service.c
@@ -187,6 +187,77 @@ static struct l_dbus_message *test_method_call(struct l_dbus *dbus,
return reply;
}
+static void test_string_getter(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data)
+{
+ struct test_data *test = user_data;
+
+ l_dbus_message_builder_append_basic(builder, 's', test->string);
+
+ complete(dbus, message, NULL);
+}
+
+static void test_string_setter(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_iter *new_value,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data)
+{
+ const char *strvalue;
+ struct test_data *test = user_data;
+
+ if (!l_dbus_message_iter_get_variant(new_value, "s", &strvalue)) {
+ complete(dbus, message, l_dbus_message_new_error(message,
+ "org.test.InvalidArguments",
+ "String value expected"));
+ return;
+ }
+
+ l_info("New String value: %s", strvalue);
+ l_free(test->string);
+ test->string = l_strdup(strvalue);
+
+ complete(dbus, message, NULL);
+}
+
+static void test_int_getter(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data)
+{
+ struct test_data *test = user_data;
+
+ l_dbus_message_builder_append_basic(builder, 'u', &test->integer);
+
+ complete(dbus, message, NULL);
+}
+
+static void test_int_setter(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_iter *new_value,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data)
+{
+ uint32_t u;
+ struct test_data *test = user_data;
+
+ if (!l_dbus_message_iter_get_variant(new_value, "u", &u)) {
+ complete(dbus, message, l_dbus_message_new_error(message,
+ "org.test.InvalidArguments",
+ "Integer value expected"));
+ return;
+ }
+
+ l_info("New Integer value: %u", u);
+ test->integer = u;
+
+ complete(dbus, message, NULL);
+}
+
static void setup_test_interface(struct l_dbus_interface *interface)
{
l_dbus_interface_method(interface, "GetProperties", 0,
@@ -201,8 +272,10 @@ static void setup_test_interface(struct l_dbus_interface *interface)
l_dbus_interface_signal(interface, "PropertyChanged", 0,
"sv", "name", "value");
- l_dbus_interface_rw_property(interface, "String", "s");
- l_dbus_interface_rw_property(interface, "Integer", "u");
+ l_dbus_interface_property(interface, "String", 0, "s",
+ test_string_getter, test_string_setter);
+ l_dbus_interface_property(interface, "Integer", 0, "u",
+ test_int_getter, test_int_setter);
}
int main(int argc, char *argv[])
diff --git a/unit/test-dbus-service.c b/unit/test-dbus-service.c
index 68c35c1..d5ee701 100644
--- a/unit/test-dbus-service.c
+++ b/unit/test-dbus-service.c
@@ -315,6 +315,22 @@ static void test_dbus_object_tree_dispatch(const void *test_data)
_dbus_object_tree_free(tree);
}
+static void test_property_getter(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_builder *builder,
+ l_dbus_property_complete_cb_t complete,
+ void *if_user_data)
+{
+}
+
+static void test_property_setter(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message_iter *new_value,
+ l_dbus_property_complete_cb_t complete,
+ void *user_data)
+{
+}
+
int main(int argc, char *argv[])
{
int ret;
@@ -333,7 +349,9 @@ int main(int argc, char *argv[])
l_dbus_interface_signal(interface, "Changed", 0, "b", "new_value");
- l_dbus_interface_rw_property(interface, "Bar", "y");
+ l_dbus_interface_property(interface, "Bar", 0, "y",
+ test_property_getter,
+ test_property_setter);
l_test_add("Test Frobate Introspection", test_introspect_method,
&frobate_test);
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/8] dbus: Separate interface registration from instantiation
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 2/8] unit: Update _dbus_object_tree_prune_node call parameters Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 3/8] dbus: setters and getters API for properties Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 5/8] dbus: Message builder function to copy from an iter Andrew Zaborowski
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 20372 bytes --]
Currently l_dbus_register_interface performs three related actions:
* if needed, creates a new object node in the dbus object tree
* if needed, sets up internal structs for the new interface
* adds the interface to the object
With this patch these are three spearate calls, although the first
is still performed automatically by l_dbus_add_interface if
l_dbus_register_object wasn't called first. This is in preparation for
ObjectManager support. With this the setup_func parameter and new
interface parameters don't need to be passed every time an interface is
instiated, only when it's being registered/created.
Note that while the client doesn't need to call l_dbus_register_object,
they still need to call l_dbus_unregister_object to free the object
because it's not freed automatically when the last interface gets
removed. But they can skip the l_dbus_remove_interface calls
because the interfaces will be removed either way.
---
ell/dbus-private.h | 20 ++++--
ell/dbus-service.c | 163 ++++++++++++++++++++++++++++++++++-------------
ell/dbus.c | 147 ++++++++++++++++++++++++++++++++++++++++--
ell/dbus.h | 19 ++++--
examples/dbus-service.c | 13 ++--
unit/test-dbus-service.c | 15 +++--
unit/test-kdbus.c | 9 ++-
7 files changed, 315 insertions(+), 71 deletions(-)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index a0ddb35..07b85d0 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -167,15 +167,27 @@ struct object_node *_dbus_object_tree_makepath(struct _dbus_object_tree *tree,
const char *path);
struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
const char *path);
+
+struct object_node *_dbus_object_tree_new_object(struct _dbus_object_tree *tree,
+ const char *path,
+ void *user_data,
+ void (*destroy) (void *));
bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
struct object_node *node,
const char *path);
-bool _dbus_object_tree_register(struct _dbus_object_tree *tree,
- const char *path, const char *interface,
+bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
+ const char *interface,
void (*setup_func)(struct l_dbus_interface *),
- void *user_data, void (*destroy) (void *));
-bool _dbus_object_tree_unregister(struct _dbus_object_tree *tree,
+ void (*destroy) (void *),
+ bool old_style_properties);
+bool _dbus_object_tree_unregister_interface(struct _dbus_object_tree *tree,
+ const char *interface);
+
+bool _dbus_object_tree_add_interface(struct _dbus_object_tree *tree,
+ const char *path, const char *interface,
+ void *user_data);
+bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
const char *path,
const char *interface);
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
index 70d42f3..0eec91c 100644
--- a/ell/dbus-service.c
+++ b/ell/dbus-service.c
@@ -72,6 +72,8 @@ struct l_dbus_interface {
struct l_queue *methods;
struct l_queue *signals;
struct l_queue *properties;
+ bool handle_old_style_properties;
+ void (*instance_destroy)(void *);
char name[];
};
@@ -84,13 +86,14 @@ struct child_node {
struct interface_instance {
struct l_dbus_interface *interface;
void *user_data;
- void (*user_destroy) (void *);
};
struct object_node {
struct object_node *parent;
struct l_queue *instances;
struct child_node *children;
+ void *user_data;
+ void (*destroy) (void *);
};
struct _dbus_object_tree {
@@ -489,8 +492,8 @@ struct _dbus_property *_dbus_interface_find_property(struct l_dbus_interface *i,
static void interface_instance_free(struct interface_instance *instance)
{
- if (instance->user_destroy)
- instance->user_destroy(instance->user_data);
+ if (instance->interface->instance_destroy)
+ instance->interface->instance_destroy(instance->user_data);
l_free(instance);
}
@@ -539,6 +542,9 @@ static void subtree_free(struct object_node *node)
l_queue_destroy(node->instances,
(l_queue_destroy_func_t) interface_instance_free);
+ if (node->destroy)
+ node->destroy(node->user_data);
+
l_free(node);
}
@@ -626,6 +632,28 @@ struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
return lookup_recurse(tree->root, path);
}
+struct object_node *_dbus_object_tree_new_object(struct _dbus_object_tree *tree,
+ const char *path,
+ void *user_data,
+ void (*destroy) (void *))
+{
+ struct object_node *node;
+
+ if (!_dbus_valid_object_path(path))
+ return NULL;
+
+ if (l_hashmap_lookup(tree->objects, path))
+ return NULL;
+
+ node = _dbus_object_tree_makepath(tree, path);
+ node->user_data = user_data;
+ node->destroy = destroy;
+
+ l_hashmap_insert(tree->objects, path, node);
+
+ return node;
+}
+
bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
struct object_node *node,
const char *path)
@@ -644,6 +672,12 @@ bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
while ((instance = l_queue_pop_head(node->instances)))
interface_instance_free(instance);
+ if (node->destroy) {
+ node->destroy(node->user_data);
+
+ node->destroy = NULL;
+ }
+
if (node->children || !node->parent)
return true;
@@ -687,52 +721,104 @@ bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
return true;
}
-bool _dbus_object_tree_register(struct _dbus_object_tree *tree,
- const char *path, const char *interface,
+bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
+ const char *interface,
void (*setup_func)(struct l_dbus_interface *),
- void *user_data, void (*destroy) (void *))
+ void (*destroy) (void *),
+ bool old_style_properties)
{
- struct object_node *object;
struct l_dbus_interface *dbi;
- const struct l_queue_entry *entry;
- struct interface_instance *instance;
if (!_dbus_valid_interface(interface))
return false;
- if (!_dbus_valid_object_path(path))
+ /*
+ * Check to make sure we do not have this interface already
+ * registered
+ */
+ dbi = l_hashmap_lookup(tree->interfaces, interface);
+ if (dbi)
+ return false;
+
+ dbi = _dbus_interface_new(interface);
+ dbi->instance_destroy = destroy;
+ dbi->handle_old_style_properties = old_style_properties;
+
+ setup_func(dbi);
+
+ l_hashmap_insert(tree->interfaces, dbi->name, dbi);
+
+ return true;
+}
+
+struct interface_check {
+ struct _dbus_object_tree *tree;
+ const char *interface;
+};
+
+static void check_interface_used(const void *key, void *value, void *user_data)
+{
+ const char *path = key;
+ struct object_node *node = value;
+ struct interface_check *state = user_data;
+
+ if (!l_queue_find(node->instances, match_interface_instance,
+ (char *) state->interface))
+ return;
+
+ _dbus_object_tree_remove_interface(state->tree, path, state->interface);
+}
+
+bool _dbus_object_tree_unregister_interface(struct _dbus_object_tree *tree,
+ const char *interface_name)
+{
+ struct l_dbus_interface *interface;
+ struct interface_check state = { tree, interface_name };
+
+ interface = l_hashmap_lookup(tree->interfaces, interface_name);
+ if (!interface)
+ return false;
+
+ /* Check that the interface is not in use */
+ l_hashmap_foreach(tree->objects, check_interface_used, &state);
+
+ l_hashmap_remove(tree->interfaces, interface_name);
+
+ _dbus_interface_free(interface);
+
+ return true;
+}
+
+bool _dbus_object_tree_add_interface(struct _dbus_object_tree *tree,
+ const char *path, const char *interface,
+ void *user_data)
+{
+ struct object_node *object;
+ struct l_dbus_interface *dbi;
+ struct interface_instance *instance;
+
+ dbi = l_hashmap_lookup(tree->interfaces, interface);
+ if (!dbi)
return false;
object = l_hashmap_lookup(tree->objects, path);
if (!object) {
- object = _dbus_object_tree_makepath(tree, path);
- l_hashmap_insert(tree->objects, path, object);
+ object = _dbus_object_tree_new_object(tree, path, NULL, NULL);
+
+ if (!object)
+ return false;
}
/*
* Check to make sure we do not have this interface already
* registered for this object
*/
- entry = l_queue_get_entries(object->instances);
- while (entry) {
- instance = entry->data;
-
- if (!strcmp(instance->interface->name, interface))
- return false;
-
- entry = entry->next;
- }
-
- dbi = l_hashmap_lookup(tree->interfaces, interface);
- if (!dbi) {
- dbi = _dbus_interface_new(interface);
- setup_func(dbi);
- l_hashmap_insert(tree->interfaces, dbi->name, dbi);
- }
+ if (l_queue_find(object->instances, match_interface_instance,
+ (char *) interface))
+ return false;
instance = l_new(struct interface_instance, 1);
instance->interface = dbi;
- instance->user_destroy = destroy;
instance->user_data = user_data;
if (!object->instances)
@@ -743,13 +829,12 @@ bool _dbus_object_tree_register(struct _dbus_object_tree *tree,
return true;
}
-bool _dbus_object_tree_unregister(struct _dbus_object_tree *tree,
+bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
const char *path,
const char *interface)
{
struct object_node *node;
struct interface_instance *instance;
- bool r;
node = l_hashmap_lookup(tree->objects, path);
if (!node)
@@ -757,20 +842,12 @@ bool _dbus_object_tree_unregister(struct _dbus_object_tree *tree,
instance = l_queue_remove_if(node->instances,
match_interface_instance, (char *) interface);
+ if (!instance)
+ return false;
- r = instance ? true : false;
-
- if (instance)
- interface_instance_free(instance);
-
- if (l_queue_isempty(node->instances)) {
- l_hashmap_remove(tree->objects, path);
-
- if (!node->children)
- _dbus_object_tree_prune_node(tree, node, path);
- }
+ interface_instance_free(instance);
- return r;
+ return true;
}
static void generate_interface_instance(void *data, void *user)
diff --git a/ell/dbus.c b/ell/dbus.c
index 1d9aed5..ff94774 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -1214,11 +1214,28 @@ int _dbus_get_fd(struct l_dbus *dbus)
return l_io_get_fd(dbus->io);
}
+/**
+ * l_dbus_register_interface:
+ * @dbus: D-Bus connection as returned by @l_dbus_new*
+ * @interface: interface name string
+ * @setup_func: function that sets up the methods, signals and properties by
+ * using the #dbus-service.h API.
+ * @destroy: optional destructor to be called every time an instance of this
+ * interface is being removed from an object on this bus.
+ * @handle_old_style_properties: whether to automatically handle SetProperty and
+ * GetProperties for any properties registered by
+ * @setup_func.
+ *
+ * Registers an interface. If successful the interface can then be added
+ * to any number of objects with @l_dbus_object_add_interface.
+ *
+ * Returns: whether the interface was successfully registered
+ **/
LIB_EXPORT bool l_dbus_register_interface(struct l_dbus *dbus,
- const char *path, const char *interface,
+ const char *interface,
l_dbus_interface_setup_func_t setup_func,
- void *user_data,
- l_dbus_destroy_func_t destroy)
+ l_dbus_destroy_func_t destroy,
+ bool handle_old_style_properties)
{
if (unlikely(!dbus))
return false;
@@ -1226,12 +1243,12 @@ LIB_EXPORT bool l_dbus_register_interface(struct l_dbus *dbus,
if (unlikely(!dbus->tree))
return false;
- return _dbus_object_tree_register(dbus->tree, path, interface,
- setup_func, user_data, destroy);
+ return _dbus_object_tree_register_interface(dbus->tree, interface,
+ setup_func, destroy,
+ handle_old_style_properties);
}
LIB_EXPORT bool l_dbus_unregister_interface(struct l_dbus *dbus,
- const char *path,
const char *interface)
{
if (unlikely(!dbus))
@@ -1240,7 +1257,123 @@ LIB_EXPORT bool l_dbus_unregister_interface(struct l_dbus *dbus,
if (unlikely(!dbus->tree))
return false;
- return _dbus_object_tree_unregister(dbus->tree, path, interface);
+ return _dbus_object_tree_unregister_interface(dbus->tree, interface);
+}
+
+/**
+ * l_dbus_register_object:
+ * @dbus: D-Bus connection
+ * @path: new object path
+ * @user_data: user pointer to be passed to @destroy if any
+ * @destroy: optional destructor to be called when object dropped from the tree
+ * @...: NULL-terminated list of 0 or more interfaces to be present on the
+ * object from the moment of creation. For every interface the interface
+ * name string is expected followed by the @user_data pointer same as
+ * would be passed as @l_dbus_object_add_interface's last two parameters.
+ *
+ * Create a new D-Bus object on the tree visible to D-Bus peers. For example:
+ * success = l_dbus_register_object(bus, "/org/example/ExampleManager",
+ * NULL, NULL,
+ * "org.example.Manager",
+ * manager_data,
+ * NULL);
+ *
+ * Returns: whether the object path was successfully registered
+ **/
+LIB_EXPORT bool l_dbus_register_object(struct l_dbus *dbus, const char *path,
+ void *user_data,
+ l_dbus_destroy_func_t destroy, ...)
+{
+ va_list args;
+ const char *interface;
+ void *if_user_data;
+ bool r = true;;
+
+ if (unlikely(!dbus))
+ return false;
+
+ if (unlikely(!dbus->tree))
+ return false;
+
+ if (!_dbus_object_tree_new_object(dbus->tree, path, user_data, destroy))
+ return false;
+
+ va_start(args, destroy);
+ while ((interface = va_arg(args, const char *))) {
+ if_user_data = va_arg(args, void *);
+
+ if (!_dbus_object_tree_add_interface(dbus->tree, path,
+ interface,
+ if_user_data)) {
+ _dbus_object_tree_prune_node(dbus->tree, NULL, path);
+ r = false;
+
+ break;
+ }
+ }
+ va_end(args);
+
+ return r;
+}
+
+LIB_EXPORT bool l_dbus_unregister_object(struct l_dbus *dbus,
+ const char *object)
+{
+ if (unlikely(!dbus))
+ return false;
+
+ if (unlikely(!dbus->tree))
+ return false;
+
+ return _dbus_object_tree_prune_node(dbus->tree, NULL, object);
+}
+
+/**
+ * l_dbus_object_add_interface:
+ * @dbus: D-Bus connection
+ * @object: object path as passed to @l_dbus_register_object
+ * @interface: interface name as passed to @l_dbus_register_interface
+ * @user_data: user data pointer to be passed to any method and property
+ * callbacks provided by the @setup_func and to the @destroy
+ * callback as passed to @l_dbus_register_interface
+ *
+ * Creates an instance of given interface at the given path in the
+ * connection's object tree. If no object was registered at this path
+ * before @l_dbus_register_object gets called automatically.
+ *
+ * The addition of an interface to the object may trigger a query of
+ * all the properties on this interface and
+ * #org.freedesktop.DBus.ObjectManager.InterfacesAdded signals.
+ *
+ * Returns: whether the interface was successfully added.
+ **/
+LIB_EXPORT bool l_dbus_object_add_interface(struct l_dbus *dbus,
+ const char *object,
+ const char *interface,
+ void *user_data)
+{
+ if (unlikely(!dbus))
+ return false;
+
+ if (unlikely(!dbus->tree))
+ return false;
+
+ return _dbus_object_tree_add_interface(dbus->tree, object, interface,
+ user_data);
+}
+
+LIB_EXPORT bool l_dbus_object_remove_interface(struct l_dbus *dbus,
+ const char *object,
+ const char *interface)
+{
+ if (unlikely(!dbus))
+ return false;
+
+ if (unlikely(!dbus->tree))
+ return false;
+
+ return _dbus_object_tree_remove_interface(dbus->tree, object,
+ interface);
}
void _dbus1_filter_format_match(struct dbus1_filter_data *data, char *rule,
diff --git a/ell/dbus.h b/ell/dbus.h
index 39f926b..011d59a 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -191,13 +191,22 @@ bool l_dbus_message_builder_leave_variant(
struct l_dbus_message *l_dbus_message_builder_finalize(
struct l_dbus_message_builder *builder);
-bool l_dbus_register_interface(struct l_dbus *dbus,
- const char *path, const char *interface,
+bool l_dbus_register_interface(struct l_dbus *dbus, const char *interface,
l_dbus_interface_setup_func_t setup_func,
- void *user_data,
- l_dbus_destroy_func_t destroy);
-bool l_dbus_unregister_interface(struct l_dbus *dbus, const char *path,
+ l_dbus_destroy_func_t destroy,
+ bool handle_old_style_properties);
+bool l_dbus_unregister_interface(struct l_dbus *dbus, const char *interface);
+
+bool l_dbus_register_object(struct l_dbus *dbus, const char *path,
+ void *user_data, l_dbus_destroy_func_t destroy,
+ ...);
+bool l_dbus_unregister_object(struct l_dbus *dbus, const char *object);
+
+bool l_dbus_object_add_interface(struct l_dbus *dbus, const char *object,
+ const char *interface, void *user_data);
+bool l_dbus_object_remove_interface(struct l_dbus *dbus, const char *object,
const char *interface);
+
unsigned int l_dbus_add_disconnect_watch(struct l_dbus *dbus,
const char *name,
l_dbus_watch_func_t disconnect_func,
diff --git a/examples/dbus-service.c b/examples/dbus-service.c
index e4e5fa7..488cc47 100644
--- a/examples/dbus-service.c
+++ b/examples/dbus-service.c
@@ -307,17 +307,22 @@ int main(int argc, char *argv[])
test->string = l_strdup("Default");
test->integer = 42;
- if (!l_dbus_register_interface(dbus, "/test", "org.test",
- setup_test_interface, test,
- test_data_destroy)) {
+ if (!l_dbus_register_interface(dbus, "org.test", setup_test_interface,
+ test_data_destroy, false)) {
l_info("Unable to register interface");
test_data_destroy(test);
goto cleanup;
}
+ if (!l_dbus_object_add_interface(dbus, "/test", "org.test", test)) {
+ l_info("Unable to instantiate interface");
+ test_data_destroy(test);
+ goto cleanup;
+ }
+
l_main_run();
- l_dbus_unregister_interface(dbus, "/test", "org.test");
+ l_dbus_unregister_object(dbus, "/test");
cleanup:
l_dbus_destroy(dbus);
diff --git a/unit/test-dbus-service.c b/unit/test-dbus-service.c
index d5ee701..cbaaa82 100644
--- a/unit/test-dbus-service.c
+++ b/unit/test-dbus-service.c
@@ -276,9 +276,10 @@ static void test_dbus_object_tree_introspection(const void *test_data)
tree = _dbus_object_tree_new();
- _dbus_object_tree_register(tree, "/", "org.ofono.Manager",
- build_manager_interface,
- NULL, NULL);
+ _dbus_object_tree_register_interface(tree, "org.ofono.Manager",
+ build_manager_interface,
+ NULL, false);
+ _dbus_object_tree_add_interface(tree, "/", "org.ofono.Manager", NULL);
_dbus_object_tree_makepath(tree, "/phonesim");
@@ -298,9 +299,11 @@ static void test_dbus_object_tree_dispatch(const void *test_data)
tree = _dbus_object_tree_new();
- _dbus_object_tree_register(tree, "/", "org.ofono.Manager",
- build_manager_interface,
- dummy_data, NULL);
+ _dbus_object_tree_register_interface(tree, "org.ofono.Manager",
+ build_manager_interface,
+ NULL, false);
+ _dbus_object_tree_add_interface(tree, "/", "org.ofono.Manager",
+ dummy_data);
message = _dbus_message_new_method_call(1, "org.ofono", "/",
"org.ofono.Manager",
diff --git a/unit/test-kdbus.c b/unit/test-kdbus.c
index 4bf41bb..3a6af3e 100644
--- a/unit/test-kdbus.c
+++ b/unit/test-kdbus.c
@@ -158,12 +158,17 @@ int main(int argc, char *argv[])
l_dbus_set_ready_handler(service, service_ready_callback,
service, NULL);
- if (!l_dbus_register_interface(service, "/test", "org.test",
- setup_test_interface, NULL, NULL)) {
+ if (!l_dbus_register_interface(service, "org.test",
+ setup_test_interface, NULL, false)) {
l_info("Unable to register interface");
goto error;
}
+ if (!l_dbus_object_add_interface(service, "/test", "org.test", NULL)) {
+ l_info("Unable to instantiate interface");
+ goto error;
+ }
+
client = l_dbus_new(bus_address);
assert(client);
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/8] dbus: Message builder function to copy from an iter.
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
` (2 preceding siblings ...)
2016-02-01 14:07 ` [PATCH 4/8] dbus: Separate interface registration from instantiation Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 6/8] dbus: Private function to retrieve the tree for a connection Andrew Zaborowski
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 4735 bytes --]
---
ell/dbus-message.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/dbus.h | 4 ++
2 files changed, 129 insertions(+)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 159df82..e618cf7 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1584,6 +1584,131 @@ LIB_EXPORT bool l_dbus_message_builder_leave_variant(
return l_dbus_message_builder_leave_container(builder, 'v');
}
+/**
+ * l_dbus_message_builder_append_from_iter:
+ * @builder: message builder to receive a new value
+ * @from: message iterator to have its position moved by one value
+ *
+ * Copy one value from a message iterator onto a message builder. The
+ * value's signature is also copied.
+ *
+ * Returns: whether the value was correctly copied. On failure both
+ * the @from iterator and the @builder may have their positions
+ * moved to somewhere within the new value if it's of a
+ * container type.
+ **/
+LIB_EXPORT bool l_dbus_message_builder_append_from_iter(
+ struct l_dbus_message_builder *builder,
+ struct l_dbus_message_iter *from)
+{
+ static const char *simple_types = "sogybnqiuxtd";
+ char type = from->sig_start[from->sig_pos];
+ char container_type;
+ char signature[256];
+ struct l_dbus_message_iter iter;
+ void *basic_ptr;
+ uint64_t basic;
+ uint32_t uint32_val;
+ int fd;
+ bool (*get_basic)(struct l_dbus_message_iter *, char, void *);
+ bool (*enter_func)(struct l_dbus_message_iter *,
+ struct l_dbus_message_iter *);
+ bool (*enter_struct)(struct l_dbus_message_iter *,
+ struct l_dbus_message_iter *);
+ bool (*enter_array)(struct l_dbus_message_iter *,
+ struct l_dbus_message_iter *);
+ bool (*enter_variant)(struct l_dbus_message_iter *,
+ struct l_dbus_message_iter *);
+
+ if (_dbus_message_is_gvariant(from->message)) {
+ get_basic = _gvariant_iter_next_entry_basic;
+ enter_struct = _gvariant_iter_enter_struct;
+ enter_array = _gvariant_iter_enter_array;
+ enter_variant = _gvariant_iter_enter_variant;
+ } else {
+ get_basic = _dbus1_iter_next_entry_basic;
+ enter_struct = _dbus1_iter_enter_struct;
+ enter_array = _dbus1_iter_enter_array;
+ enter_variant = _dbus1_iter_enter_variant;
+ }
+
+ if (strchr(simple_types, type)) {
+ if (strchr("sog", type)) {
+ if (!get_basic(from, type, &basic_ptr))
+ return false;
+ } else {
+ basic_ptr = &basic;
+
+ if (!get_basic(from, type, basic_ptr))
+ return false;
+ }
+
+ if (!l_dbus_message_builder_append_basic(builder, type,
+ basic_ptr))
+ return false;
+
+ return true;
+ }
+
+ switch (type) {
+ case 'h':
+ if (!get_basic(from, type, &uint32_val))
+ return false;
+
+ if (uint32_val >= from->message->num_fds)
+ return false;
+
+ fd = fcntl(from->message->fds[uint32_val], F_DUPFD_CLOEXEC, 3);
+
+ uint32_val = builder->message->num_fds;
+ builder->message->fds[builder->message->num_fds++] = fd;
+
+ if (!l_dbus_message_builder_append_basic(builder, type,
+ &uint32_val))
+ return false;
+
+ return true;
+ case '(':
+ enter_func = enter_struct;
+ container_type = DBUS_CONTAINER_TYPE_STRUCT;
+ break;
+ case '{':
+ enter_func = enter_struct;
+ container_type = DBUS_CONTAINER_TYPE_DICT_ENTRY;
+ break;
+ case 'a':
+ enter_func = enter_array;
+ container_type = DBUS_CONTAINER_TYPE_ARRAY;
+ break;
+ case 'v':
+ enter_func = enter_variant;
+ container_type = DBUS_CONTAINER_TYPE_VARIANT;
+ break;
+ default:
+ return false;
+ }
+
+ if (!enter_func(from, &iter))
+ return false;
+
+ memcpy(signature, iter.sig_start, iter.sig_len);
+ signature[iter.sig_len] = '\0';
+
+ if (!l_dbus_message_builder_enter_container(builder,
+ container_type, signature))
+ return false;
+
+ while (iter.sig_pos < iter.sig_len)
+ if (!l_dbus_message_builder_append_from_iter(builder, &iter))
+ return false;
+
+ if (!l_dbus_message_builder_leave_container(builder,
+ container_type))
+ return false;
+
+ return true;
+}
+
LIB_EXPORT struct l_dbus_message *l_dbus_message_builder_finalize(
struct l_dbus_message_builder *builder)
{
diff --git a/ell/dbus.h b/ell/dbus.h
index 011d59a..29253b6 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -188,6 +188,10 @@ bool l_dbus_message_builder_enter_variant(
bool l_dbus_message_builder_leave_variant(
struct l_dbus_message_builder *builder);
+bool l_dbus_message_builder_append_from_iter(
+ struct l_dbus_message_builder *builder,
+ struct l_dbus_message_iter *from);
+
struct l_dbus_message *l_dbus_message_builder_finalize(
struct l_dbus_message_builder *builder);
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/8] dbus: Private function to retrieve the tree for a connection.
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
` (3 preceding siblings ...)
2016-02-01 14:07 ` [PATCH 5/8] dbus: Message builder function to copy from an iter Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 7/8] dbus: Handle legacy GetProperties and SetProperty automatically Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 8/8] dbus: Implement org.freedesktop.DBus.Properties Andrew Zaborowski
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 920 bytes --]
---
ell/dbus-private.h | 1 +
ell/dbus.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 07b85d0..558ec50 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -226,6 +226,7 @@ int _dbus_kernel_remove_match(int fd, uint64_t cookie);
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 dbus1_filter_data;
diff --git a/ell/dbus.c b/ell/dbus.c
index ff94774..70c6f32 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -1214,6 +1214,11 @@ int _dbus_get_fd(struct l_dbus *dbus)
return l_io_get_fd(dbus->io);
}
+struct _dbus_object_tree *_dbus_get_tree(struct l_dbus *dbus)
+{
+ return dbus->tree;
+}
+
/**
* l_dbus_register_interface:
* @dbus: D-Bus connection as returned by @l_dbus_new*
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/8] dbus: Handle legacy GetProperties and SetProperty automatically.
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
` (4 preceding siblings ...)
2016-02-01 14:07 ` [PATCH 6/8] dbus: Private function to retrieve the tree for a connection Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 8/8] dbus: Implement org.freedesktop.DBus.Properties Andrew Zaborowski
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 14553 bytes --]
---
ell/dbus-private.h | 6 ++
ell/dbus-service.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++
examples/dbus-service.c | 86 +--------------
3 files changed, 282 insertions(+), 85 deletions(-)
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 558ec50..e8697ce 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -197,6 +197,12 @@ bool _dbus_object_tree_dispatch(struct _dbus_object_tree *tree,
struct l_dbus *dbus,
struct l_dbus_message *message);
+void _dbus_object_tree_property_changed(struct l_dbus *dbus,
+ const char *path,
+ const char *interface_name,
+ const char *property_name,
+ struct l_dbus_message_iter *variant);
+
void _dbus_kernel_bloom_add(uint64_t filter[], size_t size, uint8_t num_hash,
const char *prefix, const char *str);
void _dbus_kernel_bloom_add_parents(uint64_t filter[], size_t size,
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
index 0eec91c..93aeb60 100644
--- a/ell/dbus-service.c
+++ b/ell/dbus-service.c
@@ -99,6 +99,7 @@ struct object_node {
struct _dbus_object_tree {
struct l_hashmap *interfaces;
struct l_hashmap *objects;
+ struct l_hashmap *property_requests;
struct object_node *root;
};
@@ -522,6 +523,8 @@ struct _dbus_object_tree *_dbus_object_tree_new()
tree->objects = l_hashmap_string_new();
+ tree->property_requests = l_hashmap_new();
+
tree->root = l_new(struct object_node, 1);
return tree;
@@ -553,6 +556,7 @@ void _dbus_object_tree_free(struct _dbus_object_tree *tree)
l_hashmap_destroy(tree->interfaces,
(l_hashmap_destroy_func_t) _dbus_interface_free);
l_hashmap_destroy(tree->objects, NULL);
+ l_hashmap_destroy(tree->property_requests, NULL);
subtree_free(tree->root);
@@ -721,6 +725,252 @@ bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
return true;
}
+void _dbus_object_tree_property_changed(struct l_dbus *dbus,
+ const char *path,
+ const char *interface_name,
+ const char *property_name,
+ struct l_dbus_message_iter *variant)
+{
+ struct l_dbus_message *signal;
+ struct l_dbus_message_builder *builder;
+ char signature[256];
+ struct l_dbus_interface *interface;
+ struct l_dbus_message_iter value;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+ memcpy(signature, variant->sig_start, variant->sig_len);
+ signature[variant->sig_len] = '\0';
+
+ interface = l_hashmap_lookup(tree->interfaces, interface_name);
+
+ if (interface->handle_old_style_properties) {
+ memcpy(&value, variant, sizeof(value));
+
+ signal = l_dbus_message_new_signal(dbus, path,
+ interface_name,
+ "PropertyChanged");
+
+ builder = l_dbus_message_builder_new(signal);
+
+ l_dbus_message_builder_append_basic(builder, 's',
+ property_name);
+ l_dbus_message_builder_enter_variant(builder, signature);
+ l_dbus_message_builder_append_from_iter(builder, &value);
+ l_dbus_message_builder_leave_variant(builder);
+
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+ l_dbus_send(dbus, signal);
+ }
+}
+
+static void set_property_complete(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message *error)
+{
+ struct l_dbus_message *reply;
+ const char *property_name;
+ struct l_dbus_message_iter variant;
+
+ if (error) {
+ l_dbus_message_unref(message);
+
+ l_dbus_send(dbus, error);
+
+ return;
+ }
+
+ reply = l_dbus_message_new_method_return(message);
+ l_dbus_message_set_arguments(reply, "");
+ l_dbus_send(dbus, reply);
+
+ l_dbus_message_get_arguments(message, "sv", &property_name, &variant);
+
+ _dbus_object_tree_property_changed(dbus,
+ l_dbus_message_get_path(message),
+ l_dbus_message_get_interface(message),
+ property_name, &variant);
+
+ l_dbus_message_unref(message);
+}
+
+static struct l_dbus_message *old_set_property(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus_interface *interface;
+ const char *property_name;
+ struct _dbus_property *property;
+ struct l_dbus_message_iter variant;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+ interface = l_hashmap_lookup(tree->interfaces,
+ l_dbus_message_get_interface(message));
+ /* If we got here the interface must exist */
+
+ if (!l_dbus_message_get_arguments(message, "sv", &property_name,
+ &variant))
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Invalid arguments");
+
+ property = _dbus_interface_find_property(interface, property_name);
+ if (!property)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Unknown Property %s",
+ property_name);
+
+ if (!property->setter)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Property %s is read-only",
+ property_name);
+
+ property->setter(dbus, l_dbus_message_ref(message), &variant,
+ set_property_complete, user_data);
+
+ return NULL;
+}
+
+struct get_properties_state {
+ struct interface_instance *instance;
+ void (*done)(struct l_dbus *dbus, struct get_properties_state *state,
+ struct l_dbus_message *error);
+ struct l_dbus_message *message, *reply;
+ const struct l_queue_entry *entry;
+ struct l_dbus_message_builder *builder;
+ void *user_data;
+ int count;
+ int busy;
+};
+
+static void get_next_property(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message *error)
+{
+ struct get_properties_state *state;
+ struct _dbus_property *property;
+ const char *signature;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+ state = l_hashmap_lookup(tree->property_requests, message);
+
+ if (error || !state->instance) {
+ state->done(dbus, state, error);
+
+ return;
+ }
+
+ /*
+ * Loop in the caller as long as the getters complete immediately
+ * to avoid growing the stack. The callback will only lower
+ * state->busy so that the caller knows the getter completed.
+ */
+ while (!state->busy) {
+ if (state->count) {
+ l_dbus_message_builder_leave_variant(state->builder);
+ l_dbus_message_builder_leave_dict(state->builder);
+ }
+
+ if (!state->entry) {
+ l_dbus_message_builder_leave_array(state->builder);
+
+ state->done(dbus, state, error);
+
+ return;
+ }
+
+ property = state->entry->data;
+ signature = property->metainfo + strlen(property->metainfo) + 1;
+
+ state->entry = state->entry->next;
+ state->count += 1;
+
+ l_dbus_message_builder_enter_dict(state->builder, "sv");
+ l_dbus_message_builder_append_basic(state->builder, 's',
+ property->metainfo);
+ l_dbus_message_builder_enter_variant(state->builder,
+ signature);
+
+ state->busy++;
+ property->getter(dbus, state->message, state->builder,
+ get_next_property, state->user_data);
+ }
+
+ state->busy--;
+}
+
+static void get_properties_dict(struct l_dbus *dbus,
+ struct get_properties_state *state)
+{
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+ l_hashmap_insert(tree->property_requests, state->message, state);
+
+ l_dbus_message_builder_enter_array(state->builder, "{sv}");
+
+ get_next_property(dbus, state->message, NULL);
+}
+
+static void get_properties_done(struct l_dbus *dbus,
+ struct get_properties_state *state,
+ struct l_dbus_message *error)
+{
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+ if (error) {
+ l_dbus_message_unref(state->reply);
+
+ l_dbus_send(dbus, error);
+ } else {
+ l_dbus_message_builder_finalize(state->builder);
+
+ l_dbus_send(dbus, state->reply);
+ }
+
+ l_hashmap_remove(tree->property_requests, state->message);
+ l_dbus_message_unref(state->message);
+ l_dbus_message_builder_destroy(state->builder);
+ l_free(state);
+}
+
+static struct l_dbus_message *old_get_properties(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus_interface *interface;
+ struct get_properties_state *state;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+ struct object_node *object;
+
+ interface = l_hashmap_lookup(tree->interfaces,
+ l_dbus_message_get_interface(message));
+ /* If we got here the interface must exist */
+
+ object = l_hashmap_lookup(tree->objects,
+ l_dbus_message_get_path(message));
+
+ state = l_new(struct get_properties_state, 1);
+
+ state->instance = l_queue_find(object->instances,
+ match_interface_instance,
+ (char *) l_dbus_message_get_interface(message));
+ state->done = get_properties_done;
+ state->message = l_dbus_message_ref(message);
+ state->reply = l_dbus_message_new_method_return(message);
+ state->entry = l_queue_get_entries(interface->properties);
+ state->builder = l_dbus_message_builder_new(state->reply);
+ state->user_data = user_data;
+
+ get_properties_dict(dbus, state);
+
+ return NULL;
+}
+
bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
const char *interface,
void (*setup_func)(struct l_dbus_interface *),
@@ -744,6 +994,19 @@ bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
dbi->instance_destroy = destroy;
dbi->handle_old_style_properties = old_style_properties;
+ /* Add our methods first so we don't have to check for conflicts. */
+ if (old_style_properties) {
+ l_dbus_interface_method(dbi, "SetProperty", 0,
+ old_set_property, "", "sv",
+ "name", "value");
+ l_dbus_interface_method(dbi, "GetProperties", 0,
+ old_get_properties, "a{sv}", "",
+ "properties");
+
+ l_dbus_interface_signal(dbi, "PropertyChanged", 0, "sv",
+ "name", "value");
+ }
+
setup_func(dbi);
l_hashmap_insert(tree->interfaces, dbi->name, dbi);
@@ -829,6 +1092,15 @@ bool _dbus_object_tree_add_interface(struct _dbus_object_tree *tree,
return true;
}
+static void mark_instance_removed(const void *key, void *value, void *user_data)
+{
+ struct get_properties_state *state = value;
+ struct interface_instance *instance = user_data;
+
+ if (state->instance == instance)
+ state->instance = NULL;
+}
+
bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
const char *path,
const char *interface)
@@ -847,6 +1119,9 @@ bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
interface_instance_free(instance);
+ l_hashmap_foreach(tree->property_requests,
+ mark_instance_removed, instance);
+
return true;
}
diff --git a/examples/dbus-service.c b/examples/dbus-service.c
index 488cc47..2158bec 100644
--- a/examples/dbus-service.c
+++ b/examples/dbus-service.c
@@ -98,81 +98,6 @@ static void test_data_destroy(void *data)
l_free(test);
}
-static struct l_dbus_message *test_set_property(struct l_dbus *dbus,
- struct l_dbus_message *message,
- void *user_data)
-{
- struct test_data *test = user_data;
- struct l_dbus_message *reply;
- struct l_dbus_message *signal;
- struct l_dbus_message_iter variant;
- const char *property;
-
- if (!l_dbus_message_get_arguments(message, "sv", &property, &variant))
- return l_dbus_message_new_error(message,
- "org.test.InvalidArguments",
- "Invalid arguments");
-
- if (!strcmp(property, "String")) {
- const char *strvalue;
-
- if (!l_dbus_message_iter_get_variant(&variant, "s",
- &strvalue))
- return l_dbus_message_new_error(message,
- "org.test.InvalidArguments",
- "String value expected");
-
- l_info("New String value: %s", strvalue);
- l_free(test->string);
- test->string = l_strdup(strvalue);
-
- signal = l_dbus_message_new_signal(dbus, "/test",
- "org.test", "PropertyChanged");
- l_dbus_message_set_arguments(signal, "sv",
- "String", "s", test->string);
- } else if (!strcmp(property, "Integer")) {
- uint32_t u;
-
- if (!l_dbus_message_iter_get_variant(&variant, "u", &u))
- return l_dbus_message_new_error(message,
- "org.test.InvalidArguments",
- "Integer value expected");
-
- l_info("New Integer value: %u", u);
- test->integer = u;
- signal = l_dbus_message_new_signal(dbus, "/test",
- "org.test", "PropertyChanged");
- l_dbus_message_set_arguments(signal, "sv",
- "Integer", "u", test->integer);
- } else
- return l_dbus_message_new_error(message,
- "org.test.InvalidArguments",
- "Unknown Property %s",
- property);
-
- reply = l_dbus_message_new_method_return(message);
- l_dbus_message_set_arguments(reply, "");
- l_dbus_send(dbus, reply);
-
- l_dbus_send(dbus, signal);
- return NULL;
-}
-
-static struct l_dbus_message *test_get_properties(struct l_dbus *dbus,
- struct l_dbus_message *message,
- void *user_data)
-{
- struct test_data *test = user_data;
- struct l_dbus_message *reply;
-
- reply = l_dbus_message_new_method_return(message);
- l_dbus_message_set_arguments(reply, "a{sv}", 2,
- "String", "s", test->string,
- "Integer", "u", test->integer);
-
- return reply;
-}
-
static struct l_dbus_message *test_method_call(struct l_dbus *dbus,
struct l_dbus_message *message,
void *user_data)
@@ -260,18 +185,9 @@ static void test_int_setter(struct l_dbus *dbus,
static void setup_test_interface(struct l_dbus_interface *interface)
{
- l_dbus_interface_method(interface, "GetProperties", 0,
- test_get_properties,
- "a{sv}", "", "properties");
- l_dbus_interface_method(interface, "SetProperty", 0,
- test_set_property,
- "", "sv", "name", "value");
l_dbus_interface_method(interface, "MethodCall", 0,
test_method_call, "", "");
- l_dbus_interface_signal(interface, "PropertyChanged", 0,
- "sv", "name", "value");
-
l_dbus_interface_property(interface, "String", 0, "s",
test_string_getter, test_string_setter);
l_dbus_interface_property(interface, "Integer", 0, "u",
@@ -308,7 +224,7 @@ int main(int argc, char *argv[])
test->integer = 42;
if (!l_dbus_register_interface(dbus, "org.test", setup_test_interface,
- test_data_destroy, false)) {
+ test_data_destroy, true)) {
l_info("Unable to register interface");
test_data_destroy(test);
goto cleanup;
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 8/8] dbus: Implement org.freedesktop.DBus.Properties
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
` (5 preceding siblings ...)
2016-02-01 14:07 ` [PATCH 7/8] dbus: Handle legacy GetProperties and SetProperty automatically Andrew Zaborowski
@ 2016-02-01 14:07 ` Andrew Zaborowski
6 siblings, 0 replies; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-01 14:07 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 11952 bytes --]
---
ell/dbus-service.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++
ell/dbus.c | 1 -
examples/dbus-service.c | 7 ++
3 files changed, 294 insertions(+), 1 deletion(-)
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
index 93aeb60..962bbaf 100644
--- a/ell/dbus-service.c
+++ b/ell/dbus-service.c
@@ -47,6 +47,8 @@ static const char *static_introspectable =
"\t\t\t<arg name=\"xml\" type=\"s\" direction=\"out\"/>\n"
"\t\t</method>\n\t</interface>\n";
+#define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
+
struct _dbus_method {
l_dbus_interface_method_cb_t cb;
uint32_t flags;
@@ -510,6 +512,8 @@ static bool match_interface_instance(const void *a, const void *b)
return false;
}
+static void properties_setup_func(struct l_dbus_interface *);
+
struct _dbus_object_tree *_dbus_object_tree_new()
{
struct _dbus_object_tree *tree;
@@ -527,6 +531,10 @@ struct _dbus_object_tree *_dbus_object_tree_new()
tree->root = l_new(struct object_node, 1);
+ _dbus_object_tree_register_interface(tree, DBUS_INTERFACE_PROPERTIES,
+ properties_setup_func, NULL,
+ false);
+
return tree;
}
@@ -725,6 +733,7 @@ bool _dbus_object_tree_prune_node(struct _dbus_object_tree *tree,
return true;
}
+/* Send the signals associated with a property value change */
void _dbus_object_tree_property_changed(struct l_dbus *dbus,
const char *path,
const char *interface_name,
@@ -735,6 +744,7 @@ void _dbus_object_tree_property_changed(struct l_dbus *dbus,
struct l_dbus_message_builder *builder;
char signature[256];
struct l_dbus_interface *interface;
+ struct object_node *object;
struct l_dbus_message_iter value;
struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
@@ -762,6 +772,37 @@ void _dbus_object_tree_property_changed(struct l_dbus *dbus,
l_dbus_message_builder_destroy(builder);
l_dbus_send(dbus, signal);
}
+
+ object = l_hashmap_lookup(tree->objects, path);
+
+ if (l_queue_find(object->instances, match_interface_instance,
+ DBUS_INTERFACE_PROPERTIES)) {
+ memcpy(&value, variant, sizeof(value));
+
+ signal = l_dbus_message_new_signal(dbus, path,
+ DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged");
+
+ builder = l_dbus_message_builder_new(signal);
+
+ l_dbus_message_builder_append_basic(builder, 's',
+ interface_name);
+ l_dbus_message_builder_enter_array(builder, "{sv}");
+ l_dbus_message_builder_enter_dict(builder, "sv");
+ l_dbus_message_builder_append_basic(builder, 's',
+ property_name);
+ l_dbus_message_builder_enter_variant(builder, signature);
+ l_dbus_message_builder_append_from_iter(builder, &value);
+ l_dbus_message_builder_leave_variant(builder);
+ l_dbus_message_builder_leave_dict(builder);
+ l_dbus_message_builder_leave_array(builder);
+ l_dbus_message_builder_enter_array(builder, "s");
+ l_dbus_message_builder_leave_array(builder);
+
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+ l_dbus_send(dbus, signal);
+ }
}
static void set_property_complete(struct l_dbus *dbus,
@@ -1224,3 +1265,249 @@ bool _dbus_object_tree_dispatch(struct _dbus_object_tree *tree,
return true;
}
+
+static void properties_get_complete(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message *error)
+{
+ struct get_properties_state *state;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+
+ state = l_hashmap_lookup(tree->property_requests, message);
+
+ l_dbus_message_builder_leave_variant(state->builder);
+
+ get_properties_done(dbus, state, error);
+}
+
+static struct l_dbus_message *properties_get(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus_interface *interface;
+ struct interface_instance *instance;
+ const char *interface_name, *property_name, *signature;
+ struct _dbus_property *property;
+ struct get_properties_state *state;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+ struct object_node *object;
+
+ if (!l_dbus_message_get_arguments(message, "ss", &interface_name,
+ &property_name))
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Invalid arguments");
+
+ interface = l_hashmap_lookup(tree->interfaces, interface_name);
+ if (!interface)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Unknown Interface %s",
+ interface_name);
+
+ property = _dbus_interface_find_property(interface, property_name);
+ if (!property)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Unknown Property %s",
+ property_name);
+
+ object = l_hashmap_lookup(tree->objects,
+ l_dbus_message_get_path(message));
+ /* If we got here the object must exist */
+
+ instance = l_queue_find(object->instances,
+ match_interface_instance,
+ (char *) interface_name);
+ if (!instance)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Object has no interface %s",
+ interface_name);
+
+ state = l_new(struct get_properties_state, 1);
+
+ state->message = l_dbus_message_ref(message);
+ state->reply = l_dbus_message_new_method_return(message);
+ state->builder = l_dbus_message_builder_new(state->reply);
+
+ l_hashmap_insert(tree->property_requests, message, state);
+
+ signature = property->metainfo + strlen(property->metainfo) + 1;
+
+ l_dbus_message_builder_enter_variant(state->builder,
+ signature);
+
+ property->getter(dbus, state->message, state->builder,
+ properties_get_complete, instance->user_data);
+
+ return NULL;
+}
+
+static void properties_set_complete(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ struct l_dbus_message *error)
+{
+ struct l_dbus_message *reply;
+ const char *interface_name, *property_name;
+ struct l_dbus_message_iter variant;
+
+ if (error) {
+ l_dbus_message_unref(message);
+
+ l_dbus_send(dbus, error);
+
+ return;
+ }
+
+ reply = l_dbus_message_new_method_return(message);
+ l_dbus_message_set_arguments(reply, "");
+ l_dbus_send(dbus, reply);
+
+ l_dbus_message_get_arguments(message, "ssv", &interface_name,
+ &property_name, &variant);
+
+ _dbus_object_tree_property_changed(dbus,
+ l_dbus_message_get_path(message),
+ interface_name, property_name,
+ &variant);
+
+ l_dbus_message_unref(message);
+}
+
+static struct l_dbus_message *properties_set(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus_interface *interface;
+ struct interface_instance *instance;
+ const char *interface_name, *property_name;
+ struct _dbus_property *property;
+ struct l_dbus_message_iter variant;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+ struct object_node *object;
+
+ if (!l_dbus_message_get_arguments(message, "ssv", &interface_name,
+ &property_name, &variant))
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Invalid arguments");
+
+ interface = l_hashmap_lookup(tree->interfaces, interface_name);
+ if (!interface)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Unknown Interface %s",
+ interface_name);
+
+ property = _dbus_interface_find_property(interface, property_name);
+ if (!property)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Unknown Property %s",
+ property_name);
+
+ if (!property->setter)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Property %s is read-only",
+ property_name);
+
+ object = l_hashmap_lookup(tree->objects,
+ l_dbus_message_get_path(message));
+ /* If we got here the object must exist */
+
+ instance = l_queue_find(object->instances,
+ match_interface_instance,
+ (char *) interface_name);
+ if (!instance)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Object has no interface %s",
+ interface_name);
+
+ property->setter(dbus, l_dbus_message_ref(message), &variant,
+ properties_set_complete, instance->user_data);
+
+ return NULL;
+}
+
+static struct l_dbus_message *properties_get_all(struct l_dbus *dbus,
+ struct l_dbus_message *message,
+ void *user_data)
+{
+ struct l_dbus_interface *interface;
+ struct interface_instance *instance;
+ const char *interface_name;
+ struct get_properties_state *state;
+ struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
+ struct object_node *object;
+
+ if (!l_dbus_message_get_arguments(message, "s", &interface_name))
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Invalid arguments");
+
+ interface = l_hashmap_lookup(tree->interfaces, interface_name);
+ if (!interface)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Unknown Interface %s",
+ interface_name);
+
+ object = l_hashmap_lookup(tree->objects,
+ l_dbus_message_get_path(message));
+ /* If we got here the object must exist */
+
+ instance = l_queue_find(object->instances,
+ match_interface_instance,
+ (char *) interface_name);
+ if (!instance)
+ return l_dbus_message_new_error(message,
+ "org.freedesktop.DBus.Error."
+ "InvalidArgs",
+ "Object has no interface %s",
+ interface_name);
+
+ state = l_new(struct get_properties_state, 1);
+
+ state->instance = instance;
+ state->done = get_properties_done;
+ state->message = l_dbus_message_ref(message);
+ state->reply = l_dbus_message_new_method_return(message);
+ state->entry = l_queue_get_entries(interface->properties);
+ state->builder = l_dbus_message_builder_new(state->reply);
+ state->user_data = instance->user_data;
+
+ get_properties_dict(dbus, state);
+
+ return NULL;
+}
+
+static void properties_setup_func(struct l_dbus_interface *interface)
+{
+ l_dbus_interface_method(interface, "Get", 0,
+ properties_get, "v", "ss",
+ "value", "interface_name", "property_name");
+ l_dbus_interface_method(interface, "Set", 0,
+ properties_set, "", "ssv",
+ "interface_name", "property_name", "value");
+ l_dbus_interface_method(interface, "GetAll", 0,
+ properties_get_all, "a{sv}", "s",
+ "props", "interface_name");
+
+ l_dbus_interface_signal(interface, "PropertiesChanged", 0, "sa{sv}as",
+ "interface_name", "changed_properties",
+ "invalidated_properties");
+}
diff --git a/ell/dbus.c b/ell/dbus.c
index 70c6f32..6a55d42 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -51,7 +51,6 @@
#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
#define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
-#define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
diff --git a/examples/dbus-service.c b/examples/dbus-service.c
index 2158bec..6a838cc 100644
--- a/examples/dbus-service.c
+++ b/examples/dbus-service.c
@@ -236,6 +236,13 @@ int main(int argc, char *argv[])
goto cleanup;
}
+ if (!l_dbus_object_add_interface(dbus, "/test",
+ "org.freedesktop.DBus.Properties", NULL)) {
+ l_info("Unable to instantiate the properties interface");
+ test_data_destroy(test);
+ goto cleanup;
+ }
+
l_main_run();
l_dbus_unregister_object(dbus, "/test");
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/8] dbus: More complete checks when removing nodes.
2016-02-05 2:58 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
@ 2016-02-08 15:42 ` Denis Kenzior
0 siblings, 0 replies; 10+ messages in thread
From: Denis Kenzior @ 2016-02-08 15:42 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 310 bytes --]
Hi Andrew,
On 02/04/2016 08:58 PM, Andrew Zaborowski wrote:
> This addresses two problems with nodes being freed from the object tree
> but not from tree->objects.
> ---
> ell/dbus-service.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] dbus: More complete checks when removing nodes.
@ 2016-02-05 2:58 Andrew Zaborowski
2016-02-08 15:42 ` Denis Kenzior
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Zaborowski @ 2016-02-05 2:58 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 995 bytes --]
This addresses two problems with nodes being freed from the object tree
but not from tree->objects.
---
ell/dbus-service.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/ell/dbus-service.c b/ell/dbus-service.c
index e082226..639872b 100644
--- a/ell/dbus-service.c
+++ b/ell/dbus-service.c
@@ -660,6 +660,9 @@ void _dbus_object_tree_prune_node(struct object_node *node)
if (parent->children != NULL)
return;
+ if (parent->instances)
+ return;
+
node = parent;
parent = node->parent;
}
@@ -741,9 +744,11 @@ bool _dbus_object_tree_unregister(struct _dbus_object_tree *tree,
if (instance)
interface_instance_free(instance);
- if (l_queue_isempty(node->instances) && !node->children) {
+ if (l_queue_isempty(node->instances)) {
l_hashmap_remove(tree->objects, path);
- _dbus_object_tree_prune_node(node);
+
+ if (!node->children)
+ _dbus_object_tree_prune_node(node);
}
return r;
--
2.5.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-02-08 15:42 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-01 14:07 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 2/8] unit: Update _dbus_object_tree_prune_node call parameters Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 3/8] dbus: setters and getters API for properties Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 4/8] dbus: Separate interface registration from instantiation Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 5/8] dbus: Message builder function to copy from an iter Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 6/8] dbus: Private function to retrieve the tree for a connection Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 7/8] dbus: Handle legacy GetProperties and SetProperty automatically Andrew Zaborowski
2016-02-01 14:07 ` [PATCH 8/8] dbus: Implement org.freedesktop.DBus.Properties Andrew Zaborowski
2016-02-05 2:58 [PATCH 1/8] dbus: More complete checks when removing nodes Andrew Zaborowski
2016-02-08 15:42 ` 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.