All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] D-Bus client and proxy API
@ 2017-12-01 15:06 Szymon Janc
  2017-12-01 15:06 ` [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist Szymon Janc
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1644 bytes --]

Hi,

This set adds initial version of D-Bus client and proxy APIs.
With this is it possible to connect to specified service, monitor
proxies being added/removed, set/get properties and call methods
on specific proxy.

First 2 patches are some extensions to message API that were needed for
client code.

This is tested against BlueZ D-Bus API and seems to work fine within
my (simple) application.

Changes since RFC:
 - addressed comments from Denis
 - proxy is now obtained only from added callback - this may be
   extended in future if needed
 - no more proxy ref counting as it is valid from add to remove callback
 - pending set properties and method calls are cancelled on proxy removal
 - added simple API usage example to examples/dbus-client.c

Comments are welcome.

Szymon Janc (6):
  dbus: Add l_dbus_message_builder_append_from_valist
  dbus: Use l_dbus_message_builder_append_from_valist in
    append_arguments
  dbus: Add support for proxy interface
  dbus: Add support for setting properties on D-Bus proxy interface
  dbus: Add convenient API for calling method on proxy interface
  examples: Extend dbus-client example

 Makefile.am            |   2 +
 ell/dbus-client.c      | 714 +++++++++++++++++++++++++++++++++++++++++++++++++
 ell/dbus-client.h      |  98 +++++++
 ell/dbus-message.c     | 461 +++++++++++++++----------------
 ell/dbus.h             |   4 +
 ell/ell.h              |   1 +
 examples/dbus-client.c |  93 ++++++-
 7 files changed, 1138 insertions(+), 235 deletions(-)
 create mode 100644 ell/dbus-client.c
 create mode 100644 ell/dbus-client.h

-- 
2.14.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist
  2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
@ 2017-12-01 15:06 ` Szymon Janc
  2017-12-04 18:25   ` Denis Kenzior
  2017-12-01 15:06 ` [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments Szymon Janc
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 6541 bytes --]

This allows to build messages from va_list.
---
 ell/dbus-message.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/dbus.h         |   4 +
 2 files changed, 226 insertions(+)

diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 0314a07..6e64a13 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1930,6 +1930,228 @@ LIB_EXPORT bool l_dbus_message_builder_append_from_iter(
 	return true;
 }
 
+LIB_EXPORT bool l_dbus_message_builder_append_from_valist(
+					struct l_dbus_message_builder *builder,
+					const char *signature, va_list args)
+{
+	struct builder_driver *driver;
+	char subsig[256];
+	const char *sigend;
+	/* Nesting requires an extra stack entry for the base level */
+	struct container stack[DBUS_MAX_NESTING + 1];
+	unsigned int stack_index = 0;
+
+	if (unlikely(!builder))
+		return false;
+
+	driver = builder->driver;
+
+	stack[stack_index].type = DBUS_CONTAINER_TYPE_STRUCT;
+	stack[stack_index].sig_start = signature;
+	stack[stack_index].sig_end = signature + strlen(signature);
+	stack[stack_index].n_items = 0;
+
+	while (stack_index != 0 || stack[0].sig_start != stack[0].sig_end) {
+		const char *s;
+		const char *str;
+
+		if (stack[stack_index].type == DBUS_CONTAINER_TYPE_ARRAY &&
+				stack[stack_index].n_items == 0)
+			stack[stack_index].sig_start =
+				stack[stack_index].sig_end;
+
+		if (stack[stack_index].sig_start ==
+				stack[stack_index].sig_end) {
+			bool ret;
+
+			/*
+			 * Sanity check in case of an invalid signature that
+			 * isn't caught elsewhere.
+			 */
+			if (unlikely(stack_index == 0))
+				return false;
+
+			switch (stack[stack_index].type) {
+			case DBUS_CONTAINER_TYPE_STRUCT:
+				ret = driver->leave_struct(builder->builder);
+				break;
+			case DBUS_CONTAINER_TYPE_DICT_ENTRY:
+				ret = driver->leave_dict(builder->builder);
+				break;
+			case DBUS_CONTAINER_TYPE_VARIANT:
+				ret = driver->leave_variant(builder->builder);
+				break;
+			case DBUS_CONTAINER_TYPE_ARRAY:
+				ret = driver->leave_array(builder->builder);
+				break;
+			default:
+				ret = false;
+			}
+
+			if (!ret)
+				return false;
+
+			stack_index -= 1;
+			continue;
+		}
+
+		s = stack[stack_index].sig_start;
+
+		if (stack[stack_index].type != DBUS_CONTAINER_TYPE_ARRAY)
+			stack[stack_index].sig_start += 1;
+		else
+			stack[stack_index].n_items -= 1;
+
+		switch (*s) {
+		case 'o':
+		case 's':
+		case 'g':
+			str = va_arg(args, const char *);
+
+			if (!driver->append_basic(builder->builder, *s, str))
+				return false;
+			break;
+		case 'b':
+		case 'y':
+		{
+			uint8_t y = (uint8_t) va_arg(args, int);
+
+			if (!driver->append_basic(builder->builder, *s, &y))
+				return false;
+
+			break;
+		}
+		case 'n':
+		case 'q':
+		{
+			uint16_t n = (uint16_t) va_arg(args, int);
+
+			if (!driver->append_basic(builder->builder, *s, &n))
+				return false;
+
+			break;
+		}
+		case 'i':
+		case 'u':
+		{
+			uint32_t u = va_arg(args, uint32_t);
+
+			if (!driver->append_basic(builder->builder, *s, &u))
+				return false;
+
+			break;
+		}
+		case 'h':
+		{
+			int fd = va_arg(args, int);
+			struct l_dbus_message *message = builder->message;
+
+			if (!driver->append_basic(builder->builder, *s,
+							&message->num_fds))
+				return false;
+
+			if (message->num_fds < L_ARRAY_SIZE(message->fds))
+				message->fds[message->num_fds++] =
+					fcntl(fd, F_DUPFD_CLOEXEC, 3);
+
+			break;
+		}
+		case 'x':
+		case 't':
+		{
+			uint64_t x = va_arg(args, uint64_t);
+
+			if (!driver->append_basic(builder->builder, *s, &x))
+				return false;
+			break;
+		}
+		case 'd':
+		{
+			double d = va_arg(args, double);
+
+			if (!driver->append_basic(builder->builder, *s, &d))
+				return false;
+			break;
+		}
+		case '(':
+		case '{':
+			if (stack_index == DBUS_MAX_NESTING)
+				return false;
+
+			sigend = _dbus_signature_end(s);
+			memcpy(subsig, s + 1, sigend - s - 1);
+			subsig[sigend - s - 1] = '\0';
+
+			if (*s == '(' && !driver->enter_struct(builder->builder,
+									subsig))
+				return false;
+
+			if (*s == '{' && !driver->enter_dict(builder->builder,
+									subsig))
+				return false;
+
+			if (stack[stack_index].type !=
+					DBUS_CONTAINER_TYPE_ARRAY)
+				stack[stack_index].sig_start = sigend + 1;
+
+			stack_index += 1;
+			stack[stack_index].sig_start = s + 1;
+			stack[stack_index].sig_end = sigend;
+			stack[stack_index].n_items = 0;
+			stack[stack_index].type = *s == '(' ?
+						DBUS_CONTAINER_TYPE_STRUCT :
+						DBUS_CONTAINER_TYPE_DICT_ENTRY;
+
+			break;
+		case 'v':
+			if (stack_index == DBUS_MAX_NESTING)
+				return false;
+
+			str = va_arg(args, const char *);
+
+			if (!str)
+				return false;
+
+			if (!driver->enter_variant(builder->builder, str))
+				return false;
+
+			stack_index += 1;
+			stack[stack_index].type = DBUS_CONTAINER_TYPE_VARIANT;
+			stack[stack_index].sig_start = str;
+			stack[stack_index].sig_end = str + strlen(str);
+			stack[stack_index].n_items = 0;
+
+			break;
+		case 'a':
+			if (stack_index == DBUS_MAX_NESTING)
+				return false;
+
+			sigend = _dbus_signature_end(s + 1) + 1;
+			memcpy(subsig, s + 1, sigend - s - 1);
+			subsig[sigend - s - 1] = '\0';
+
+			if (!driver->enter_array(builder->builder, subsig))
+				return false;
+
+			if (stack[stack_index].type !=
+					DBUS_CONTAINER_TYPE_ARRAY)
+				stack[stack_index].sig_start = sigend;
+
+			stack_index += 1;
+			stack[stack_index].sig_start = s + 1;
+			stack[stack_index].sig_end = sigend;
+			stack[stack_index].n_items = va_arg(args, unsigned int);
+			stack[stack_index].type = DBUS_CONTAINER_TYPE_ARRAY;
+
+			break;
+		default:
+			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 5c7879f..1b1ec2b 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -214,6 +214,10 @@ bool l_dbus_message_builder_append_from_iter(
 					struct l_dbus_message_builder *builder,
 					struct l_dbus_message_iter *from);
 
+bool l_dbus_message_builder_append_from_valist(
+					struct l_dbus_message_builder *builder,
+					const char *signature, va_list args);
+
 struct l_dbus_message *l_dbus_message_builder_finalize(
 					struct l_dbus_message_builder *builder);
 
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments
  2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
  2017-12-01 15:06 ` [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist Szymon Janc
@ 2017-12-01 15:06 ` Szymon Janc
  2017-12-04 18:25   ` Denis Kenzior
  2017-12-01 15:06 ` [PATCH 3/6] dbus: Add support for proxy interface Szymon Janc
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 6625 bytes --]

Those functions do similar things and code duplication can be avoided.
---
 ell/dbus-message.c | 239 +++--------------------------------------------------
 1 file changed, 13 insertions(+), 226 deletions(-)

diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 6e64a13..f4f6b42 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1089,239 +1089,26 @@ struct container {
 static bool append_arguments(struct l_dbus_message *message,
 					const char *signature, va_list args)
 {
-	struct dbus_builder *builder;
-	struct builder_driver *driver;
-	char *generated_signature;
-	char subsig[256];
-	const char *sigend;
-	/* Nesting requires an extra stack entry for the base level */
-	struct container stack[DBUS_MAX_NESTING + 1];
-	unsigned int stack_index = 0;
-
-	if (_dbus_message_is_gvariant(message))
-		driver = &gvariant_driver;
-	else
-		driver = &dbus1_driver;
-
-	builder = driver->new(NULL, 0);
-
-	stack[stack_index].type = DBUS_CONTAINER_TYPE_STRUCT;
-	stack[stack_index].sig_start = signature;
-	stack[stack_index].sig_end = signature + strlen(signature);
-	stack[stack_index].n_items = 0;
-
-	while (stack_index != 0 || stack[0].sig_start != stack[0].sig_end) {
-		const char *s;
-		const char *str;
-
-		if (stack[stack_index].type == DBUS_CONTAINER_TYPE_ARRAY &&
-				stack[stack_index].n_items == 0)
-			stack[stack_index].sig_start =
-				stack[stack_index].sig_end;
-
-		if (stack[stack_index].sig_start ==
-				stack[stack_index].sig_end) {
-			bool ret;
-
-			/*
-			 * Sanity check in case of an invalid signature that
-			 * isn't caught elsewhere.
-			 */
-			if (unlikely(stack_index == 0))
-				goto error;
-
-			switch (stack[stack_index].type) {
-			case DBUS_CONTAINER_TYPE_STRUCT:
-				ret = driver->leave_struct(builder);
-				break;
-			case DBUS_CONTAINER_TYPE_DICT_ENTRY:
-				ret = driver->leave_dict(builder);
-				break;
-			case DBUS_CONTAINER_TYPE_VARIANT:
-				ret = driver->leave_variant(builder);
-				break;
-			case DBUS_CONTAINER_TYPE_ARRAY:
-				ret = driver->leave_array(builder);
-				break;
-			default:
-				ret = false;
-			}
-
-			if (!ret)
-				goto error;
-
-			stack_index -= 1;
-			continue;
-		}
-
-		s = stack[stack_index].sig_start;
-
-		if (stack[stack_index].type != DBUS_CONTAINER_TYPE_ARRAY)
-			stack[stack_index].sig_start += 1;
-		else
-			stack[stack_index].n_items -= 1;
-
-		switch (*s) {
-		case 'o':
-		case 's':
-		case 'g':
-			str = va_arg(args, const char *);
-
-			if (!driver->append_basic(builder, *s, str))
-				goto error;
-			break;
-		case 'b':
-		case 'y':
-		{
-			uint8_t y = (uint8_t) va_arg(args, int);
-
-			if (!driver->append_basic(builder, *s, &y))
-				goto error;
-
-			break;
-		}
-		case 'n':
-		case 'q':
-		{
-			uint16_t n = (uint16_t) va_arg(args, int);
-
-			if (!driver->append_basic(builder, *s, &n))
-				goto error;
-
-			break;
-		}
-		case 'i':
-		case 'u':
-		{
-			uint32_t u = va_arg(args, uint32_t);
-
-			if (!driver->append_basic(builder, *s, &u))
-				goto error;
-
-			break;
-		}
-		case 'h':
-		{
-			int fd = va_arg(args, int);
-
-			if (!driver->append_basic(builder, *s,
-							&message->num_fds))
-				goto error;
-
-			if (message->num_fds < L_ARRAY_SIZE(message->fds))
-				message->fds[message->num_fds++] =
-					fcntl(fd, F_DUPFD_CLOEXEC, 3);
-
-			break;
-		}
-		case 'x':
-		case 't':
-		{
-			uint64_t x = va_arg(args, uint64_t);
-
-			if (!driver->append_basic(builder, *s, &x))
-				goto error;
-			break;
-		}
-		case 'd':
-		{
-			double d = va_arg(args, double);
-
-			if (!driver->append_basic(builder, *s, &d))
-				goto error;
-			break;
-		}
-		case '(':
-		case '{':
-			if (stack_index == DBUS_MAX_NESTING)
-				goto error;
-
-			sigend = _dbus_signature_end(s);
-			memcpy(subsig, s + 1, sigend - s - 1);
-			subsig[sigend - s - 1] = '\0';
-
-			if (*s == '(' && !driver->enter_struct(builder, subsig))
-				goto error;
-
-			if (*s == '{' && !driver->enter_dict(builder, subsig))
-				goto error;
-
-			if (stack[stack_index].type !=
-					DBUS_CONTAINER_TYPE_ARRAY)
-				stack[stack_index].sig_start = sigend + 1;
-
-			stack_index += 1;
-			stack[stack_index].sig_start = s + 1;
-			stack[stack_index].sig_end = sigend;
-			stack[stack_index].n_items = 0;
-			stack[stack_index].type = *s == '(' ?
-						DBUS_CONTAINER_TYPE_STRUCT :
-						DBUS_CONTAINER_TYPE_DICT_ENTRY;
-
-			break;
-		case 'v':
-			if (stack_index == DBUS_MAX_NESTING)
-				goto error;
-
-			str = va_arg(args, const char *);
-
-			if (!str)
-				goto error;
-
-			if (!driver->enter_variant(builder, str))
-				goto error;
-
-			stack_index += 1;
-			stack[stack_index].type = DBUS_CONTAINER_TYPE_VARIANT;
-			stack[stack_index].sig_start = str;
-			stack[stack_index].sig_end = str + strlen(str);
-			stack[stack_index].n_items = 0;
-
-			break;
-		case 'a':
-			if (stack_index == DBUS_MAX_NESTING)
-				goto error;
-
-			sigend = _dbus_signature_end(s + 1) + 1;
-			memcpy(subsig, s + 1, sigend - s - 1);
-			subsig[sigend - s - 1] = '\0';
+	struct l_dbus_message_builder *builder;
+	bool ret;
 
-			if (!driver->enter_array(builder, subsig))
-				goto error;
-
-			if (stack[stack_index].type !=
-					DBUS_CONTAINER_TYPE_ARRAY)
-				stack[stack_index].sig_start = sigend;
-
-			stack_index += 1;
-			stack[stack_index].sig_start = s + 1;
-			stack[stack_index].sig_end = sigend;
-			stack[stack_index].n_items = va_arg(args, unsigned int);
-			stack[stack_index].type = DBUS_CONTAINER_TYPE_ARRAY;
+	builder = l_dbus_message_builder_new(message);
+	if (!builder)
+		return false;
 
-			break;
-		default:
-			goto error;
-		}
+	if (!l_dbus_message_builder_append_from_valist(builder, signature,
+									args)) {
+		l_dbus_message_builder_destroy(builder);
+		return false;
 	}
 
-	generated_signature = driver->finish(builder, &message->body,
-						&message->body_size);
-	driver->free(builder);
+	l_dbus_message_builder_finalize(builder);
 
-	if (strcmp(signature, generated_signature))
-		return false;
+	ret = strcmp(signature, builder->message->signature) == 0;
 
-	build_header(message, signature);
-	message->sealed = true;
-	message->signature = generated_signature;
-	message->signature_free = true;
+	l_dbus_message_builder_destroy(builder);
 
-	return true;
-
-error:
-	driver->free(builder);
-	return false;
+	return ret;
 }
 
 LIB_EXPORT bool l_dbus_message_get_error(struct l_dbus_message *message,
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/6] dbus: Add support for proxy interface
  2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
  2017-12-01 15:06 ` [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist Szymon Janc
  2017-12-01 15:06 ` [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments Szymon Janc
@ 2017-12-01 15:06 ` Szymon Janc
  2017-12-04 18:40   ` Denis Kenzior
  2017-12-01 15:06 ` [PATCH 4/6] dbus: Add support for setting properties on D-Bus " Szymon Janc
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 19449 bytes --]

---
 Makefile.am       |   2 +
 ell/dbus-client.c | 570 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/dbus-client.h |  82 ++++++++
 ell/ell.h         |   1 +
 4 files changed, 655 insertions(+)
 create mode 100644 ell/dbus-client.c
 create mode 100644 ell/dbus-client.h

diff --git a/Makefile.am b/Makefile.am
index a95bac4..19b957e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,6 +32,7 @@ pkginclude_HEADERS = ell/ell.h \
 			ell/genl.h \
 			ell/dbus.h \
 			ell/dbus-service.h \
+			ell/dbus-client.h \
 			ell/hwdb.h \
 			ell/cipher.h \
 			ell/random.h \
@@ -74,6 +75,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
 			ell/dbus-message.c \
 			ell/dbus-util.c \
 			ell/dbus-service.c \
+			ell/dbus-client.c \
 			ell/dbus-name-cache.c \
 			ell/dbus-filter.c \
 			ell/gvariant-private.h \
diff --git a/ell/dbus-client.c b/ell/dbus-client.c
new file mode 100644
index 0000000..f07a183
--- /dev/null
+++ b/ell/dbus-client.c
@@ -0,0 +1,570 @@
+/*
+ *
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2011-2014  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2017  Codecoup. 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
+
+#include "ell.h"
+#include "private.h"
+
+struct l_dbus_client {
+	struct l_dbus *dbus;
+	unsigned int watch;
+	unsigned int added_watch;
+	unsigned int removed_watch;
+	char *service;
+	char *path;
+	uint32_t objects_call;
+
+	l_dbus_watch_func_t connect_cb;
+	void *connect_cb_data;
+	l_dbus_destroy_func_t connect_cb_data_destroy;
+
+	l_dbus_watch_func_t disconnect_cb;
+	void *disconnect_cb_data;
+	l_dbus_destroy_func_t disconnect_cb_data_destroy;
+
+	l_dbus_client_ready_func_t ready_cb;
+	void *ready_cb_data;
+	l_dbus_destroy_func_t ready_cb_data_destroy;
+
+	l_dbus_client_proxy_func_t proxy_added_cb;
+	l_dbus_client_proxy_func_t proxy_removed_cb;
+	l_dbus_client_property_function_t properties_changed_cb;
+	void *proxy_cb_data;
+	l_dbus_destroy_func_t proxy_cb_data_destroy;
+
+	struct l_queue *proxies;
+};
+
+struct proxy_property {
+	char *name;
+	struct l_dbus_message *msg;
+};
+
+struct l_dbus_proxy {
+	struct l_dbus_client *client;
+	char *interface;
+	char *path;
+	uint32_t properties_watch;
+	bool ready;
+
+	struct l_queue *properties;
+};
+
+LIB_EXPORT const char *l_dbus_proxy_get_path(struct l_dbus_proxy *proxy)
+{
+	if (unlikely(!proxy))
+		return NULL;
+
+	return proxy->path;
+}
+
+LIB_EXPORT const char *l_dbus_proxy_get_interface(struct l_dbus_proxy *proxy)
+{
+	if (unlikely(!proxy))
+		return NULL;
+
+	return proxy->interface;
+}
+
+static bool property_match_by_name(const void *a, const void *b)
+{
+	const struct proxy_property *prop = a;
+	const char *name = b;
+
+	return !strcmp(prop->name, name);
+}
+
+static struct proxy_property *find_property(struct l_dbus_proxy *proxy,
+							const char *name)
+{
+	return l_queue_find(proxy->properties, property_match_by_name, name);
+}
+
+static struct proxy_property *get_property(struct l_dbus_proxy *proxy,
+							const char *name)
+{
+	struct proxy_property *prop;
+
+	prop = find_property(proxy, name);
+	if (prop)
+		return prop;
+
+	prop = l_new(struct proxy_property, 1);
+	prop->name = l_strdup(name);
+
+	l_queue_push_tail(proxy->properties, prop);
+
+	return prop;
+}
+
+LIB_EXPORT bool l_dbus_proxy_get_property(struct l_dbus_proxy *proxy,
+						const char *name,
+						const char *signature, ...)
+{
+	struct proxy_property *prop;
+	va_list args;
+	bool res;
+
+	if (unlikely(!proxy))
+		return false;
+
+	prop = find_property(proxy, name);
+	if (!prop)
+		return false;
+
+	va_start(args, signature);
+	res = l_dbus_message_get_arguments_valist(prop->msg, signature, args);
+	va_end(args);
+
+	return res;
+}
+
+static void property_free(void *data)
+{
+	struct proxy_property *prop = data;
+
+	if (prop->msg)
+		l_dbus_message_unref(prop->msg);
+
+	l_free(prop->name);
+	l_free(prop);
+}
+
+static void l_dbus_proxy_destroy(struct l_dbus_proxy *proxy)
+{
+	if (unlikely(!proxy))
+		return;
+
+	if (proxy->properties_watch)
+		l_dbus_remove_signal_watch(proxy->client->dbus,
+						proxy->properties_watch);
+
+	l_queue_destroy(proxy->properties, property_free);
+	l_free(proxy->interface);
+	l_free(proxy->path);
+	l_free(proxy);
+}
+
+static void proxy_update_property(struct l_dbus_proxy *proxy,
+					const char *name,
+					struct l_dbus_message_iter *property)
+{
+	struct l_dbus_message_builder *builder;
+	struct proxy_property *prop = get_property(proxy, name);
+
+	l_dbus_message_unref(prop->msg);
+
+	if (!property) {
+		prop->msg = NULL;
+		goto done;
+	}
+
+	prop->msg = l_dbus_message_new_signal(proxy->client->dbus, proxy->path,
+							proxy->interface, name);
+	if (!prop->msg)
+		return;
+
+	builder = l_dbus_message_builder_new(prop->msg);
+	l_dbus_message_builder_append_from_iter(builder, property);
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+done:
+	if (proxy->client->properties_changed_cb && proxy->ready)
+		proxy->client->properties_changed_cb(proxy, name, prop->msg,
+					proxy->client->proxy_cb_data_destroy);
+}
+
+static void proxy_invalidate_properties(struct l_dbus_proxy *proxy,
+					struct l_dbus_message_iter* props)
+{
+	const char *name;
+
+	while (l_dbus_message_iter_next_entry(props, &name))
+		proxy_update_property(proxy, name, NULL);
+}
+
+static void proxy_update_properties(struct l_dbus_proxy *proxy,
+					struct l_dbus_message_iter* props)
+{
+	struct l_dbus_message_iter variant;
+	const char *name;
+
+	while (l_dbus_message_iter_next_entry(props, &name, &variant))
+		proxy_update_property(proxy, name, &variant);
+}
+
+static void properties_changed_callback(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_proxy *proxy = user_data;
+	const char *interface;
+	struct l_dbus_message_iter changed;
+	struct l_dbus_message_iter invalidated;
+
+	if (!l_dbus_message_get_arguments(message, "sa{sv}as", &interface,
+							&changed, &invalidated))
+		return;
+
+	proxy_update_properties(proxy, &changed);
+	proxy_invalidate_properties(proxy, &invalidated);
+}
+
+static struct l_dbus_proxy *l_dbus_proxy_new(struct l_dbus_client *client,
+					const char *path, const char *interface)
+{
+	struct l_dbus_proxy *proxy;
+
+	proxy = l_new(struct l_dbus_proxy, 1);
+
+	proxy->properties_watch = l_dbus_add_signal_watch(client->dbus,
+						client->service, path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						"PropertiesChanged",
+						L_DBUS_MATCH_ARGUMENT(0),
+						interface, L_DBUS_MATCH_NONE,
+						properties_changed_callback,
+						proxy);
+	if (!proxy->properties_watch) {
+		l_free(proxy);
+		return NULL;
+	}
+
+	proxy->client = client;
+	proxy->interface = l_strdup(interface);
+	proxy->path = l_strdup(path);
+	proxy->properties = l_queue_new();
+
+	l_queue_push_tail(client->proxies, proxy);
+
+	return proxy;
+}
+
+static bool is_ignorable(const char *interface)
+{
+	static const struct {
+		const char *interface;
+	} interfaces_to_ignore[] = {
+		{ L_DBUS_INTERFACE_OBJECT_MANAGER },
+		{ L_DBUS_INTERFACE_INTROSPECTABLE },
+		{ L_DBUS_INTERFACE_PROPERTIES },
+	};
+	size_t i;
+
+	for (i = 0; i < L_ARRAY_SIZE(interfaces_to_ignore); i++)
+		if (!strcmp(interfaces_to_ignore[i].interface, interface))
+			return true;
+
+	return false;
+}
+
+static struct l_dbus_proxy *find_proxy(struct l_dbus_client *client,
+					const char *path, const char *interface)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(client->proxies); entry;
+							entry = entry->next) {
+		struct l_dbus_proxy *proxy = entry->data;
+
+		if (!strcmp(proxy->interface, interface) &&
+						!strcmp(proxy->path, path))
+			return proxy;
+	}
+
+	return NULL;
+}
+
+static void parse_interface(struct l_dbus_client *client, const char *path,
+					const char *interface,
+					struct l_dbus_message_iter *properties)
+{
+	struct l_dbus_proxy *proxy;
+
+	if (is_ignorable(interface))
+		return;
+
+	proxy = find_proxy(client, path, interface);
+	if (!proxy) {
+		proxy = l_dbus_proxy_new(client, path, interface);
+	}
+
+	if (!proxy)
+		return;
+
+	proxy_update_properties(proxy, properties);
+
+	if (!proxy->ready) {
+		proxy->ready = true;
+
+		if (client->proxy_added_cb)
+			client->proxy_added_cb(proxy, client->proxy_cb_data);
+	}
+}
+
+static void parse_object(struct l_dbus_client *client, const char *path,
+					struct l_dbus_message_iter *object)
+{
+	const char *interface;
+	struct l_dbus_message_iter properties;
+
+	if (!path)
+		return;
+
+	while (l_dbus_message_iter_next_entry(object, &interface, &properties))
+		parse_interface(client, path, interface, &properties);
+}
+
+static void interfaces_added_callback(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+	struct l_dbus_message_iter object;
+	const char *path;
+
+	if (!l_dbus_message_get_arguments(message, "oa{sa{sv}}", &path,
+								&object))
+		return
+
+	parse_object(client, path, &object);
+}
+
+static void interfaces_removed_callback(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+	struct l_dbus_message_iter interfaces;
+	const char *interface;
+	const char *path;
+
+	if (!l_dbus_message_get_arguments(message, "oas", &path, &interfaces))
+		return;
+
+	while (l_dbus_message_iter_next_entry(&interfaces, &interface)) {
+		struct l_dbus_proxy *proxy;
+
+		proxy = find_proxy(client, path, interface);
+		if (!proxy)
+			continue;
+
+		l_queue_remove(proxy->client->proxies, proxy);
+
+		if (client->proxy_removed_cb)
+			client->proxy_removed_cb(proxy, client->proxy_cb_data);
+
+		l_dbus_proxy_destroy(proxy);
+	}
+}
+
+static void get_managed_objects_reply(struct l_dbus_message *message,
+								void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+	struct l_dbus_message_iter objects;
+	struct l_dbus_message_iter object;
+	const char *path;
+
+	client->objects_call = 0;
+
+	if (l_dbus_message_is_error(message))
+		return;
+
+	l_dbus_message_get_arguments(message, "a{oa{sa{sv}}}", &objects);
+
+	while (l_dbus_message_iter_next_entry(&objects, &path, &object))
+		parse_object(client, path, &object);
+
+	client->added_watch = l_dbus_add_signal_watch(client->dbus,
+						client->service, "/",
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"InterfacesAdded",
+						L_DBUS_MATCH_NONE,
+						interfaces_added_callback,
+						client);
+
+	client->removed_watch = l_dbus_add_signal_watch(client->dbus,
+						client->service, "/",
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"InterfacesRemoved",
+						L_DBUS_MATCH_NONE,
+						interfaces_removed_callback,
+						client);
+
+	if (client->ready_cb)
+		client->ready_cb(client, client->ready_cb_data);
+}
+
+static void service_appeared_callback(struct l_dbus *dbus, void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+
+	/* TODO should we allow to set different root? */
+	client->objects_call = l_dbus_method_call(dbus, client->service, "/",
+						L_DBUS_INTERFACE_OBJECT_MANAGER,
+						"GetManagedObjects", NULL,
+						get_managed_objects_reply,
+						client, NULL);
+
+	if (client->connect_cb)
+		client->connect_cb(client->dbus, client->connect_cb_data);
+}
+
+static void service_disappeared_callback(struct l_dbus *dbus, void *user_data)
+{
+	struct l_dbus_client *client = user_data;
+
+	if (client->disconnect_cb)
+		client->disconnect_cb(client->dbus, client->disconnect_cb_data);
+
+	l_queue_clear(client->proxies,
+				(l_queue_destroy_func_t)l_dbus_proxy_destroy);
+}
+
+LIB_EXPORT struct l_dbus_client *l_dbus_client_new(struct l_dbus *dbus,
+					const char *service, const char *path)
+{
+	struct l_dbus_client *client;
+
+	client = l_new(struct l_dbus_client, 1);
+
+	client->dbus = dbus;
+
+	client->watch = l_dbus_add_service_watch(dbus, service,
+						service_appeared_callback,
+						service_disappeared_callback,
+						client, NULL);
+
+	if (!client->watch) {
+		l_free(client);
+		return NULL;
+	}
+
+	client->service = l_strdup(service);
+	client->path = l_strdup(path);
+	client->proxies = l_queue_new();
+
+	return client;
+}
+
+LIB_EXPORT void l_dbus_client_destroy(struct l_dbus_client *client)
+{
+	if (unlikely(!client))
+		return;
+
+	if (client->watch)
+		l_dbus_remove_signal_watch(client->dbus, client->watch);
+
+	if (client->added_watch)
+		l_dbus_remove_signal_watch(client->dbus, client->added_watch);
+
+	if (client->removed_watch)
+		l_dbus_remove_signal_watch(client->dbus, client->removed_watch);
+
+	if (client->connect_cb_data_destroy)
+		client->connect_cb_data_destroy(client->connect_cb_data);
+
+	if (client->disconnect_cb_data_destroy)
+		client->disconnect_cb_data_destroy(client->disconnect_cb_data);
+
+	if (client->ready_cb_data_destroy)
+		client->ready_cb_data_destroy(client->ready_cb_data);
+
+	if (client->proxy_cb_data_destroy)
+		client->proxy_cb_data_destroy(client->proxy_cb_data);
+
+	if (client->objects_call)
+		l_dbus_cancel(client->dbus, client->objects_call)
+;
+	l_queue_destroy(client->proxies,
+				(l_queue_destroy_func_t)l_dbus_proxy_destroy);
+
+	l_free(client->service);
+	l_free(client->path);
+	l_free(client);
+}
+
+LIB_EXPORT bool l_dbus_client_set_connect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	client->connect_cb = function;
+	client->connect_cb_data = user_data;
+	client->connect_cb_data_destroy = destroy;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_client_set_disconnect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	client->disconnect_cb = function;
+	client->disconnect_cb_data = user_data;
+	client->disconnect_cb_data_destroy = destroy;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_client_set_ready_handler(struct l_dbus_client *client,
+					l_dbus_client_ready_func_t function,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	client->ready_cb = function;
+	client->ready_cb_data = user_data;
+	client->ready_cb_data_destroy = destroy;
+
+	return true;
+}
+
+LIB_EXPORT bool l_dbus_client_set_proxy_handlers(struct l_dbus_client *client,
+			l_dbus_client_proxy_func_t proxy_added,
+			l_dbus_client_proxy_func_t proxy_removed,
+			l_dbus_client_property_function_t property_changed,
+			void *user_data, l_dbus_destroy_func_t destroy)
+{
+	if (unlikely(!client))
+		return false;
+
+	client->proxy_added_cb = proxy_added;
+	client->proxy_removed_cb = proxy_removed;
+	client->properties_changed_cb = property_changed;
+	client->proxy_cb_data = user_data;
+	client->proxy_cb_data_destroy = destroy;
+
+	return true;
+}
diff --git a/ell/dbus-client.h b/ell/dbus-client.h
new file mode 100644
index 0000000..460c6c5
--- /dev/null
+++ b/ell/dbus-client.h
@@ -0,0 +1,82 @@
+/*
+ *
+ *  Embedded Linux library
+ *
+ *  Copyright (C) 2011-2014  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2017  Codecoup. 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
+ *
+ */
+
+#ifndef __ELL_DBUS_CLIENT_H
+#define __ELL_DBUS_CLIENT_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct l_dbus;
+struct l_dbus_message;
+struct l_dbus_client;
+struct l_dbus_proxy;
+
+typedef void (*l_dbus_client_ready_func_t)(struct l_dbus_client *client,
+							void *user_data);
+typedef void (*l_dbus_client_proxy_func_t) (struct l_dbus_proxy *proxy,
+							void *user_data);
+typedef void (*l_dbus_client_property_function_t) (struct l_dbus_proxy *proxy,
+						const char *name,
+						struct l_dbus_message *msg,
+						void *user_data);
+
+struct l_dbus_client *l_dbus_client_new(struct l_dbus *dbus,
+					const char *service, const char *path);
+void l_dbus_client_destroy(struct l_dbus_client *client);
+
+bool l_dbus_client_set_connect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy);
+
+bool l_dbus_client_set_disconnect_handler(struct l_dbus_client *client,
+						l_dbus_watch_func_t function,
+						void *user_data,
+						l_dbus_destroy_func_t destroy);
+
+bool l_dbus_client_set_ready_handler(struct l_dbus_client *client,
+					l_dbus_client_ready_func_t function,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+
+bool l_dbus_client_set_proxy_handlers(struct l_dbus_client *client,
+			l_dbus_client_proxy_func_t proxy_added,
+			l_dbus_client_proxy_func_t proxy_removed,
+			l_dbus_client_property_function_t property_changed,
+			void *user_data, l_dbus_destroy_func_t destroy);
+
+const char *l_dbus_proxy_get_path(struct l_dbus_proxy *proxy);
+
+const char *l_dbus_proxy_get_interface(struct l_dbus_proxy *proxy);
+
+bool l_dbus_proxy_get_property(struct l_dbus_proxy *proxy, const char *name,
+						const char *signature, ...);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ELL_DBUS_CLIENT_H */
diff --git a/ell/ell.h b/ell/ell.h
index 2efd1c4..4083ee5 100644
--- a/ell/ell.h
+++ b/ell/ell.h
@@ -51,3 +51,4 @@
 #include <ell/genl.h>
 #include <ell/dbus.h>
 #include <ell/dbus-service.h>
+#include <ell/dbus-client.h>
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/6] dbus: Add support for setting properties on D-Bus proxy interface
  2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
                   ` (2 preceding siblings ...)
  2017-12-01 15:06 ` [PATCH 3/6] dbus: Add support for proxy interface Szymon Janc
@ 2017-12-01 15:06 ` Szymon Janc
  2017-12-01 15:06 ` [PATCH 5/6] dbus: Add convenient API for calling method on " Szymon Janc
  2017-12-01 15:06 ` [PATCH 6/6] examples: Extend dbus-client example Szymon Janc
  5 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 5584 bytes --]

l_dbus_proxy_set_property function allows to set properties via proxy
interface.
---
 ell/dbus-client.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ell/dbus-client.h |   8 ++++
 2 files changed, 121 insertions(+)

diff --git a/ell/dbus-client.c b/ell/dbus-client.c
index f07a183..0d69e4b 100644
--- a/ell/dbus-client.c
+++ b/ell/dbus-client.c
@@ -71,6 +71,7 @@ struct l_dbus_proxy {
 	bool ready;
 
 	struct l_queue *properties;
+	struct l_queue *pending_calls;
 };
 
 LIB_EXPORT const char *l_dbus_proxy_get_path(struct l_dbus_proxy *proxy)
@@ -153,6 +154,18 @@ static void property_free(void *data)
 	l_free(prop);
 }
 
+static void cancel_pending_calls(struct l_dbus_proxy *proxy)
+{
+	const struct l_queue_entry *entry;
+
+	for (entry = l_queue_get_entries(proxy->pending_calls); entry;
+							entry = entry->next) {
+		uint32_t call_id = L_PTR_TO_UINT(entry->data);
+
+		l_dbus_cancel(proxy->client->dbus, call_id);
+	}
+}
+
 static void l_dbus_proxy_destroy(struct l_dbus_proxy *proxy)
 {
 	if (unlikely(!proxy))
@@ -162,12 +175,111 @@ static void l_dbus_proxy_destroy(struct l_dbus_proxy *proxy)
 		l_dbus_remove_signal_watch(proxy->client->dbus,
 						proxy->properties_watch);
 
+	cancel_pending_calls(proxy);
+	l_queue_destroy(proxy->pending_calls, NULL);
 	l_queue_destroy(proxy->properties, property_free);
 	l_free(proxy->interface);
 	l_free(proxy->path);
 	l_free(proxy);
 }
 
+struct method_call_request
+{
+	struct l_dbus_proxy *proxy;
+	uint32_t call_id;
+	l_dbus_client_proxy_result_func_t result;
+	void *user_data;
+	l_dbus_destroy_func_t destroy;
+};
+
+static void method_call_request_free(void *user_data)
+{
+	struct method_call_request *req = user_data;
+
+	l_queue_remove(req->proxy->pending_calls, L_UINT_TO_PTR(req->call_id));
+
+	if (req->destroy)
+		req->destroy(req->user_data);
+
+	l_free(req);
+}
+
+static void method_call_reply(struct l_dbus_message *message, void *user_data)
+{
+	struct method_call_request *req = user_data;
+
+	if (req->result)
+		req->result(req->proxy, message, req->user_data);
+}
+
+LIB_EXPORT bool l_dbus_proxy_set_property(struct l_dbus_proxy *proxy,
+				l_dbus_client_proxy_result_func_t result,
+				void *user_data, l_dbus_destroy_func_t destroy,
+				const char *name, const char *signature, ...)
+{
+	struct l_dbus_client *client = proxy->client;
+	struct l_dbus_message_builder *builder;
+	struct method_call_request *req;
+	struct l_dbus_message *message;
+	struct proxy_property *prop;
+	va_list args;
+
+	if (unlikely(!proxy))
+		return false;
+
+	prop = find_property(proxy, name);
+	if (!prop)
+		return false;
+
+	if (strcmp(l_dbus_message_get_signature(prop->msg), signature))
+		return false;
+
+	message = l_dbus_message_new_method_call(client->dbus, client->service,
+						proxy->path,
+						L_DBUS_INTERFACE_PROPERTIES,
+						"Set");
+	if (!message)
+		return false;
+
+	builder = l_dbus_message_builder_new(message);
+	if (!builder) {
+		l_dbus_message_unref(message);
+		return false;
+	}
+
+	l_dbus_message_builder_append_basic(builder, 's', proxy->interface);
+	l_dbus_message_builder_append_basic(builder, 's', name);
+
+	l_dbus_message_builder_enter_variant(builder, signature);
+
+	va_start(args, signature);
+	l_dbus_message_builder_append_from_valist(builder, signature, args);
+	va_end(args);
+
+	l_dbus_message_builder_leave_variant(builder);
+
+	l_dbus_message_builder_finalize(builder);
+	l_dbus_message_builder_destroy(builder);
+
+	req = l_new(struct method_call_request, 1);
+	req->proxy = proxy;
+	req->result = result;
+	req->user_data = user_data;
+	req->destroy = destroy;
+
+	req->call_id = l_dbus_send_with_reply(client->dbus, message,
+						method_call_reply, req,
+						method_call_request_free);
+	if (!req->call_id) {
+		l_free(req);
+		return false;
+	}
+
+	l_queue_push_tail(proxy->pending_calls, L_UINT_TO_PTR(req->call_id));
+
+	return true;
+}
+
 static void proxy_update_property(struct l_dbus_proxy *proxy,
 					const char *name,
 					struct l_dbus_message_iter *property)
@@ -257,6 +369,7 @@ static struct l_dbus_proxy *l_dbus_proxy_new(struct l_dbus_client *client,
 	proxy->interface = l_strdup(interface);
 	proxy->path = l_strdup(path);
 	proxy->properties = l_queue_new();
+	proxy->pending_calls = l_queue_new();;
 
 	l_queue_push_tail(client->proxies, proxy);
 
diff --git a/ell/dbus-client.h b/ell/dbus-client.h
index 460c6c5..928dcec 100644
--- a/ell/dbus-client.h
+++ b/ell/dbus-client.h
@@ -39,6 +39,9 @@ typedef void (*l_dbus_client_ready_func_t)(struct l_dbus_client *client,
 							void *user_data);
 typedef void (*l_dbus_client_proxy_func_t) (struct l_dbus_proxy *proxy,
 							void *user_data);
+typedef void (*l_dbus_client_proxy_result_func_t) (struct l_dbus_proxy *proxy,
+						struct l_dbus_message *result,
+						void *user_data);
 typedef void (*l_dbus_client_property_function_t) (struct l_dbus_proxy *proxy,
 						const char *name,
 						struct l_dbus_message *msg,
@@ -75,6 +78,11 @@ const char *l_dbus_proxy_get_interface(struct l_dbus_proxy *proxy);
 
 bool l_dbus_proxy_get_property(struct l_dbus_proxy *proxy, const char *name,
 						const char *signature, ...);
+
+bool l_dbus_proxy_set_property(struct l_dbus_proxy *proxy,
+				l_dbus_client_proxy_result_func_t result,
+				void *user_data, l_dbus_destroy_func_t destroy,
+				const char *name, const char *signature, ...);
 #ifdef __cplusplus
 }
 #endif
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/6] dbus: Add convenient API for calling method on proxy interface
  2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
                   ` (3 preceding siblings ...)
  2017-12-01 15:06 ` [PATCH 4/6] dbus: Add support for setting properties on D-Bus " Szymon Janc
@ 2017-12-01 15:06 ` Szymon Janc
  2017-12-01 15:06 ` [PATCH 6/6] examples: Extend dbus-client example Szymon Janc
  5 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2116 bytes --]

This is wrapper around l_dbus_method_call that allows to cancel call
both by removed proxy and caller.
---
 ell/dbus-client.c | 31 +++++++++++++++++++++++++++++++
 ell/dbus-client.h |  8 ++++++++
 2 files changed, 39 insertions(+)

diff --git a/ell/dbus-client.c b/ell/dbus-client.c
index 0d69e4b..5a48e52 100644
--- a/ell/dbus-client.c
+++ b/ell/dbus-client.c
@@ -280,6 +280,37 @@ LIB_EXPORT bool l_dbus_proxy_set_property(struct l_dbus_proxy *proxy,
 	return true;
 }
 
+LIB_EXPORT uint32_t l_dbus_proxy_method_call(struct l_dbus_proxy *proxy,
+					const char *method,
+					l_dbus_message_func_t setup,
+					l_dbus_client_proxy_result_func_t reply,
+					void *user_data,
+					l_dbus_destroy_func_t destroy)
+{
+	struct method_call_request *req;
+
+	req = l_new(struct method_call_request, 1);
+	req->proxy = proxy;
+	req->result = reply;
+	req->user_data = user_data;
+	req->destroy = destroy;
+
+	req->call_id = l_dbus_method_call(proxy->client->dbus,
+						proxy->client->service,
+						proxy->path, proxy->interface,
+						method, setup,
+						method_call_reply, req,
+						method_call_request_free);
+	if (!req->call_id) {
+		l_free(req);
+		return 0;
+	}
+
+	l_queue_push_tail(proxy->pending_calls, L_UINT_TO_PTR(req->call_id));
+
+	return req->call_id;
+}
+
 static void proxy_update_property(struct l_dbus_proxy *proxy,
 					const char *name,
 					struct l_dbus_message_iter *property)
diff --git a/ell/dbus-client.h b/ell/dbus-client.h
index 928dcec..699d824 100644
--- a/ell/dbus-client.h
+++ b/ell/dbus-client.h
@@ -83,6 +83,14 @@ bool l_dbus_proxy_set_property(struct l_dbus_proxy *proxy,
 				l_dbus_client_proxy_result_func_t result,
 				void *user_data, l_dbus_destroy_func_t destroy,
 				const char *name, const char *signature, ...);
+
+uint32_t l_dbus_proxy_method_call(struct l_dbus_proxy *proxy,
+					const char *method,
+					l_dbus_message_func_t setup,
+					l_dbus_client_proxy_result_func_t reply,
+					void *user_data,
+					l_dbus_destroy_func_t destroy);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/6] examples: Extend dbus-client example
  2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
                   ` (4 preceding siblings ...)
  2017-12-01 15:06 ` [PATCH 5/6] dbus: Add convenient API for calling method on " Szymon Janc
@ 2017-12-01 15:06 ` Szymon Janc
  5 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2017-12-01 15:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 3791 bytes --]

This adds sample code for using D-Bus proxy interface.
---
 examples/dbus-client.c | 93 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 84 insertions(+), 9 deletions(-)

diff --git a/examples/dbus-client.c b/examples/dbus-client.c
index 507a4e8..1f60643 100644
--- a/examples/dbus-client.c
+++ b/examples/dbus-client.c
@@ -60,23 +60,81 @@ static void disconnect_callback(void *user_data)
 	l_main_quit();
 }
 
-static void service_appeared(struct l_dbus *dbus, void *user_data)
+static void iwd_service_appeared(struct l_dbus *dbus, void *user_data)
 {
 	l_info("Service appeared");
 }
 
-static void service_disappeared(struct l_dbus *dbus, void *user_data)
+static void iwd_service_disappeared(struct l_dbus *dbus, void *user_data)
 {
-	l_info("Service disappeared, quitting...");
-	l_main_quit();
+	l_info("Service disappeared");
+}
+
+static void bluez_client_connected(struct l_dbus *dbus, void *user_data)
+{
+	l_info("client connected");
+}
+
+static void bluez_client_disconnected(struct l_dbus *dbus, void *user_data)
+{
+	l_info("client disconnected");
+}
+
+static void bluez_client_ready(struct l_dbus_client *client, void *user_data)
+{
+	l_info("client ready");
+}
+
+static void proxy_added(struct l_dbus_proxy *proxy, void *user_data)
+{
+	const char *interface = l_dbus_proxy_get_interface(proxy);
+	const char *path = l_dbus_proxy_get_path(proxy);
+
+	l_info("proxy added: %s %s", path, interface);
+
+	if (!strcmp(interface, "org.bluez.Adapter1") ||
+				!strcmp(interface, "org.bluez.Device1")) {
+		char *str;
+
+		if (!l_dbus_proxy_get_property(proxy, "Address", "s", &str))
+			return;
+
+		l_info("   Address: %s", str);
+	}
+}
+
+static void proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
+{
+	l_info("proxy removed: %s %s", l_dbus_proxy_get_path(proxy),
+					l_dbus_proxy_get_interface(proxy));
+}
+
+static void property_changed(struct l_dbus_proxy *proxy, const char *name,
+				struct l_dbus_message *msg, void *user_data)
+{
+	l_info("property changed: %s (%s %s)", name,
+					l_dbus_proxy_get_path(proxy),
+					l_dbus_proxy_get_interface(proxy));
+
+	if (!strcmp(name, "Address")) {
+		char *str;
+
+		if (!l_dbus_message_get_arguments(msg, "s", &str)) {
+			return;
+		}
+
+		l_info("   Address: %s", str);
+	}
 }
 
 int main(int argc, char *argv[])
 {
+	struct l_dbus_client *client;
 	struct l_dbus *dbus;
 	struct l_signal *signal;
 	sigset_t mask;
-	uint32_t watch_id;
+	uint32_t iwd_watch_id;
+
 
 	if (!l_main_init())
 		return -1;
@@ -93,14 +151,31 @@ 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);
 
-	watch_id = l_dbus_add_service_watch(dbus, "net.connman.iwd",
-						service_appeared,
-						service_disappeared,
+	/* service basic watch */
+	iwd_watch_id = l_dbus_add_service_watch(dbus, "net.connman.iwd",
+						iwd_service_appeared,
+						iwd_service_disappeared,
 						NULL, NULL);
 
+	/* proxy example */
+	client = l_dbus_client_new(dbus, "org.bluez", "/org/bluez");
+
+	l_dbus_client_set_connect_handler(client, bluez_client_connected, NULL,
+									NULL);
+	l_dbus_client_set_disconnect_handler(client, bluez_client_disconnected,
+								NULL, NULL);
+
+	l_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+							property_changed, NULL, NULL);
+
+	l_dbus_client_set_ready_handler(client, bluez_client_ready, NULL, NULL);
+
+
 	l_main_run();
 
-	l_dbus_remove_watch(dbus, watch_id);
+	l_dbus_remove_watch(dbus, iwd_watch_id);
+
+	l_dbus_client_destroy(client);
 
 	l_dbus_destroy(dbus);
 	l_signal_remove(signal);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist
  2017-12-01 15:06 ` [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist Szymon Janc
@ 2017-12-04 18:25   ` Denis Kenzior
  0 siblings, 0 replies; 11+ messages in thread
From: Denis Kenzior @ 2017-12-04 18:25 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 314 bytes --]

Hi Szymon,

On 12/01/2017 09:06 AM, Szymon Janc wrote:
> This allows to build messages from va_list.
> ---
>   ell/dbus-message.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>   ell/dbus.h         |   4 +
>   2 files changed, 226 insertions(+)
> 

Applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments
  2017-12-01 15:06 ` [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments Szymon Janc
@ 2017-12-04 18:25   ` Denis Kenzior
  0 siblings, 0 replies; 11+ messages in thread
From: Denis Kenzior @ 2017-12-04 18:25 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 325 bytes --]

Hi Szymon,

On 12/01/2017 09:06 AM, Szymon Janc wrote:
> Those functions do similar things and code duplication can be avoided.
> ---
>   ell/dbus-message.c | 239 +++--------------------------------------------------
>   1 file changed, 13 insertions(+), 226 deletions(-)
> 

Applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/6] dbus: Add support for proxy interface
  2017-12-01 15:06 ` [PATCH 3/6] dbus: Add support for proxy interface Szymon Janc
@ 2017-12-04 18:40   ` Denis Kenzior
  2017-12-05 17:05     ` Szymon Janc
  0 siblings, 1 reply; 11+ messages in thread
From: Denis Kenzior @ 2017-12-04 18:40 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 7616 bytes --]

Hi Szymon,

<snip>

> +static struct l_dbus_proxy *l_dbus_proxy_new(struct l_dbus_client *client,
> +					const char *path, const char *interface)

I would just call it dbus_proxy_new since it is not exported.  Same with 
l_dbus_proxy_destroy

> +{
> +	struct l_dbus_proxy *proxy;
> +
> +	proxy = l_new(struct l_dbus_proxy, 1);

can condense these to a single line...

> +
> +	proxy->properties_watch = l_dbus_add_signal_watch(client->dbus,
> +						client->service, path,
> +						L_DBUS_INTERFACE_PROPERTIES,
> +						"PropertiesChanged",
> +						L_DBUS_MATCH_ARGUMENT(0),
> +						interface, L_DBUS_MATCH_NONE,
> +						properties_changed_callback,
> +						proxy);
> +	if (!proxy->properties_watch) {
> +		l_free(proxy);
> +		return NULL;
> +	}
> +
> +	proxy->client = client;
> +	proxy->interface = l_strdup(interface);
> +	proxy->path = l_strdup(path);
> +	proxy->properties = l_queue_new();
> +
> +	l_queue_push_tail(client->proxies, proxy);
> +
> +	return proxy;
> +}
> +
> +static bool is_ignorable(const char *interface)
> +{
> +	static const struct {
> +		const char *interface;
> +	} interfaces_to_ignore[] = {
> +		{ L_DBUS_INTERFACE_OBJECT_MANAGER },
> +		{ L_DBUS_INTERFACE_INTROSPECTABLE },
> +		{ L_DBUS_INTERFACE_PROPERTIES },
> +	};
> +	size_t i;
> +
> +	for (i = 0; i < L_ARRAY_SIZE(interfaces_to_ignore); i++)
> +		if (!strcmp(interfaces_to_ignore[i].interface, interface))
> +			return true;
> +
> +	return false;
> +}
> +
> +static struct l_dbus_proxy *find_proxy(struct l_dbus_client *client,
> +					const char *path, const char *interface)
> +{
> +	const struct l_queue_entry *entry;
> +
> +	for (entry = l_queue_get_entries(client->proxies); entry;
> +							entry = entry->next) {
> +		struct l_dbus_proxy *proxy = entry->data;
> +
> +		if (!strcmp(proxy->interface, interface) &&
> +						!strcmp(proxy->path, path))
> +			return proxy;
> +	}
> +
> +	return NULL;
> +}
> +
> +static void parse_interface(struct l_dbus_client *client, const char *path,
> +					const char *interface,
> +					struct l_dbus_message_iter *properties)
> +{
> +	struct l_dbus_proxy *proxy;
> +
> +	if (is_ignorable(interface))
> +		return;
> +
> +	proxy = find_proxy(client, path, interface);
> +	if (!proxy) {
> +		proxy = l_dbus_proxy_new(client, path, interface);
> +	}

No need for {}

> +
> +	if (!proxy)
> +		return;
> +
> +	proxy_update_properties(proxy, properties);
> +
> +	if (!proxy->ready) {
> +		proxy->ready = true;
> +
> +		if (client->proxy_added_cb)
> +			client->proxy_added_cb(proxy, client->proxy_cb_data);
> +	}
> +}
> +

<snip>

> +
> +static void service_appeared_callback(struct l_dbus *dbus, void *user_data)
> +{
> +	struct l_dbus_client *client = user_data;
> +
> +	/* TODO should we allow to set different root? */
> +	client->objects_call = l_dbus_method_call(dbus, client->service, "/",
> +						L_DBUS_INTERFACE_OBJECT_MANAGER,
> +						"GetManagedObjects", NULL,
> +						get_managed_objects_reply,
> +						client, NULL);
> +
> +	if (client->connect_cb)
> +		client->connect_cb(client->dbus, client->connect_cb_data);
> +}
> +
> +static void service_disappeared_callback(struct l_dbus *dbus, void *user_data)
> +{
> +	struct l_dbus_client *client = user_data;
> +
> +	if (client->disconnect_cb)
> +		client->disconnect_cb(client->dbus, client->disconnect_cb_data);
> +
> +	l_queue_clear(client->proxies,
> +				(l_queue_destroy_func_t)l_dbus_proxy_destroy);
> +}
> +
> +LIB_EXPORT struct l_dbus_client *l_dbus_client_new(struct l_dbus *dbus,
> +					const char *service, const char *path)
> +{
> +	struct l_dbus_client *client;
> +
> +	client = l_new(struct l_dbus_client, 1);
> +

Can condense these to a single line

> +	client->dbus = dbus;
> +
> +	client->watch = l_dbus_add_service_watch(dbus, service,
> +						service_appeared_callback,
> +						service_disappeared_callback,
> +						client, NULL);
> +
> +	if (!client->watch) {
> +		l_free(client);
> +		return NULL;
> +	}
> +
> +	client->service = l_strdup(service);
> +	client->path = l_strdup(path);

What is the purpose of this member actually?  We're not using it for the 
ObjectManager root, nor are we using it for anything else.  I also don't 
get its purpose in gdbus either.  Can we simply drop it?

> +	client->proxies = l_queue_new();
> +
> +	return client;
> +}
> +
> +LIB_EXPORT void l_dbus_client_destroy(struct l_dbus_client *client)
> +{
> +	if (unlikely(!client))
> +		return;
> +
> +	if (client->watch)
> +		l_dbus_remove_signal_watch(client->dbus, client->watch);
> +
> +	if (client->added_watch)
> +		l_dbus_remove_signal_watch(client->dbus, client->added_watch);
> +
> +	if (client->removed_watch)
> +		l_dbus_remove_signal_watch(client->dbus, client->removed_watch);
> +
> +	if (client->connect_cb_data_destroy)
> +		client->connect_cb_data_destroy(client->connect_cb_data);
> +
> +	if (client->disconnect_cb_data_destroy)
> +		client->disconnect_cb_data_destroy(client->disconnect_cb_data);
> +
> +	if (client->ready_cb_data_destroy)
> +		client->ready_cb_data_destroy(client->ready_cb_data);
> +
> +	if (client->proxy_cb_data_destroy)
> +		client->proxy_cb_data_destroy(client->proxy_cb_data);
> +
> +	if (client->objects_call)
> +		l_dbus_cancel(client->dbus, client->objects_call)
> +;
> +	l_queue_destroy(client->proxies,
> +				(l_queue_destroy_func_t)l_dbus_proxy_destroy);
> +
> +	l_free(client->service);
> +	l_free(client->path);
> +	l_free(client);
> +}
> +
> +LIB_EXPORT bool l_dbus_client_set_connect_handler(struct l_dbus_client *client,
> +						l_dbus_watch_func_t function,
> +						void *user_data,
> +						l_dbus_destroy_func_t destroy)
> +{
> +	if (unlikely(!client))
> +		return false;
> +
> +	client->connect_cb = function;
> +	client->connect_cb_data = user_data;
> +	client->connect_cb_data_destroy = destroy;

No biggie, but maybe we should call destroy function here in case it is 
already set.

> +
> +	return true;
> +}
> +
> +LIB_EXPORT bool l_dbus_client_set_disconnect_handler(struct l_dbus_client *client,
> +						l_dbus_watch_func_t function,
> +						void *user_data,
> +						l_dbus_destroy_func_t destroy)
> +{
> +	if (unlikely(!client))
> +		return false;
> +
> +	client->disconnect_cb = function;
> +	client->disconnect_cb_data = user_data;
> +	client->disconnect_cb_data_destroy = destroy;

as above

> +
> +	return true;
> +}
> +
> +LIB_EXPORT bool l_dbus_client_set_ready_handler(struct l_dbus_client *client,
> +					l_dbus_client_ready_func_t function,
> +					void *user_data,
> +					l_dbus_destroy_func_t destroy)
> +{
> +	if (unlikely(!client))
> +		return false;
> +
> +	client->ready_cb = function;
> +	client->ready_cb_data = user_data;
> +	client->ready_cb_data_destroy = destroy;

as above

> +
> +	return true;
> +}
> +
> +LIB_EXPORT bool l_dbus_client_set_proxy_handlers(struct l_dbus_client *client,
> +			l_dbus_client_proxy_func_t proxy_added,
> +			l_dbus_client_proxy_func_t proxy_removed,
> +			l_dbus_client_property_function_t property_changed,
> +			void *user_data, l_dbus_destroy_func_t destroy)
> +{
> +	if (unlikely(!client))
> +		return false;
> +
> +	client->proxy_added_cb = proxy_added;
> +	client->proxy_removed_cb = proxy_removed;
> +	client->properties_changed_cb = property_changed;
> +	client->proxy_cb_data = user_data;
> +	client->proxy_cb_data_destroy = destroy;

as above

> +
> +	return true;
> +}

<snip>

Regards,
-Denis

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/6] dbus: Add support for proxy interface
  2017-12-04 18:40   ` Denis Kenzior
@ 2017-12-05 17:05     ` Szymon Janc
  0 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2017-12-05 17:05 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 8479 bytes --]

Hi Denis,

On Monday, 4 December 2017 19:40:29 CET Denis Kenzior wrote:
> Hi Szymon,
> 
> <snip>
> 
> > +static struct l_dbus_proxy *l_dbus_proxy_new(struct l_dbus_client
> > *client,
> > +					const char *path, const char *interface)
> 
> I would just call it dbus_proxy_new since it is not exported.  Same with
> l_dbus_proxy_destroy

Done.

> 
> > +{
> > +	struct l_dbus_proxy *proxy;
> > +
> > +	proxy = l_new(struct l_dbus_proxy, 1);
> 
> can condense these to a single line...

OK.

> 
> > +
> > +	proxy->properties_watch = l_dbus_add_signal_watch(client->dbus,
> > +						client->service, path,
> > +						L_DBUS_INTERFACE_PROPERTIES,
> > +						"PropertiesChanged",
> > +						L_DBUS_MATCH_ARGUMENT(0),
> > +						interface, L_DBUS_MATCH_NONE,
> > +						properties_changed_callback,
> > +						proxy);
> > +	if (!proxy->properties_watch) {
> > +		l_free(proxy);
> > +		return NULL;
> > +	}
> > +
> > +	proxy->client = client;
> > +	proxy->interface = l_strdup(interface);
> > +	proxy->path = l_strdup(path);
> > +	proxy->properties = l_queue_new();
> > +
> > +	l_queue_push_tail(client->proxies, proxy);
> > +
> > +	return proxy;
> > +}
> > +
> > +static bool is_ignorable(const char *interface)
> > +{
> > +	static const struct {
> > +		const char *interface;
> > +	} interfaces_to_ignore[] = {
> > +		{ L_DBUS_INTERFACE_OBJECT_MANAGER },
> > +		{ L_DBUS_INTERFACE_INTROSPECTABLE },
> > +		{ L_DBUS_INTERFACE_PROPERTIES },
> > +	};
> > +	size_t i;
> > +
> > +	for (i = 0; i < L_ARRAY_SIZE(interfaces_to_ignore); i++)
> > +		if (!strcmp(interfaces_to_ignore[i].interface, interface))
> > +			return true;
> > +
> > +	return false;
> > +}
> > +
> > +static struct l_dbus_proxy *find_proxy(struct l_dbus_client *client,
> > +					const char *path, const char *interface)
> > +{
> > +	const struct l_queue_entry *entry;
> > +
> > +	for (entry = l_queue_get_entries(client->proxies); entry;
> > +							entry = entry->next) {
> > +		struct l_dbus_proxy *proxy = entry->data;
> > +
> > +		if (!strcmp(proxy->interface, interface) &&
> > +						!strcmp(proxy->path, path))
> > +			return proxy;
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static void parse_interface(struct l_dbus_client *client, const char
> > *path, +					const char *interface,
> > +					struct l_dbus_message_iter *properties)
> > +{
> > +	struct l_dbus_proxy *proxy;
> > +
> > +	if (is_ignorable(interface))
> > +		return;
> > +
> > +	proxy = find_proxy(client, path, interface);
> > +	if (!proxy) {
> > +		proxy = l_dbus_proxy_new(client, path, interface);
> > +	}
> 
> No need for {}

Fixed.

> 
> > +
> > +	if (!proxy)
> > +		return;
> > +
> > +	proxy_update_properties(proxy, properties);
> > +
> > +	if (!proxy->ready) {
> > +		proxy->ready = true;
> > +
> > +		if (client->proxy_added_cb)
> > +			client->proxy_added_cb(proxy, client->proxy_cb_data);
> > +	}
> > +}
> > +
> 
> <snip>
> 
> > +
> > +static void service_appeared_callback(struct l_dbus *dbus, void
> > *user_data) +{
> > +	struct l_dbus_client *client = user_data;
> > +
> > +	/* TODO should we allow to set different root? */
> > +	client->objects_call = l_dbus_method_call(dbus, client->service, "/",
> > +						L_DBUS_INTERFACE_OBJECT_MANAGER,
> > +						"GetManagedObjects", NULL,
> > +						get_managed_objects_reply,
> > +						client, NULL);
> > +
> > +	if (client->connect_cb)
> > +		client->connect_cb(client->dbus, client->connect_cb_data);
> > +}
> > +
> > +static void service_disappeared_callback(struct l_dbus *dbus, void
> > *user_data) +{
> > +	struct l_dbus_client *client = user_data;
> > +
> > +	if (client->disconnect_cb)
> > +		client->disconnect_cb(client->dbus, client->disconnect_cb_data);
> > +
> > +	l_queue_clear(client->proxies,
> > +				(l_queue_destroy_func_t)l_dbus_proxy_destroy);
> > +}
> > +
> > +LIB_EXPORT struct l_dbus_client *l_dbus_client_new(struct l_dbus *dbus,
> > +					const char *service, const char *path)
> > +{
> > +	struct l_dbus_client *client;
> > +
> > +	client = l_new(struct l_dbus_client, 1);
> > +
> 
> Can condense these to a single line

OK.

> 
> > +	client->dbus = dbus;
> > +
> > +	client->watch = l_dbus_add_service_watch(dbus, service,
> > +						service_appeared_callback,
> > +						service_disappeared_callback,
> > +						client, NULL);
> > +
> > +	if (!client->watch) {
> > +		l_free(client);
> > +		return NULL;
> > +	}
> > +
> > +	client->service = l_strdup(service);
> > +	client->path = l_strdup(path);
> 
> What is the purpose of this member actually?  We're not using it for the
> ObjectManager root, nor are we using it for anything else.  I also don't
> get its purpose in gdbus either.  Can we simply drop it?

Yeap, I think I initially had getter for it that turned out to be useless but 
forgot to remove member from client. Fixed.

> 
> > +	client->proxies = l_queue_new();
> > +
> > +	return client;
> > +}
> > +
> > +LIB_EXPORT void l_dbus_client_destroy(struct l_dbus_client *client)
> > +{
> > +	if (unlikely(!client))
> > +		return;
> > +
> > +	if (client->watch)
> > +		l_dbus_remove_signal_watch(client->dbus, client->watch);
> > +
> > +	if (client->added_watch)
> > +		l_dbus_remove_signal_watch(client->dbus, client->added_watch);
> > +
> > +	if (client->removed_watch)
> > +		l_dbus_remove_signal_watch(client->dbus, client->removed_watch);
> > +
> > +	if (client->connect_cb_data_destroy)
> > +		client->connect_cb_data_destroy(client->connect_cb_data);
> > +
> > +	if (client->disconnect_cb_data_destroy)
> > +		client->disconnect_cb_data_destroy(client->disconnect_cb_data);
> > +
> > +	if (client->ready_cb_data_destroy)
> > +		client->ready_cb_data_destroy(client->ready_cb_data);
> > +
> > +	if (client->proxy_cb_data_destroy)
> > +		client->proxy_cb_data_destroy(client->proxy_cb_data);
> > +
> > +	if (client->objects_call)
> > +		l_dbus_cancel(client->dbus, client->objects_call)
> > +;
> > +	l_queue_destroy(client->proxies,
> > +				(l_queue_destroy_func_t)l_dbus_proxy_destroy);
> > +
> > +	l_free(client->service);
> > +	l_free(client->path);
> > +	l_free(client);
> > +}
> > +
> > +LIB_EXPORT bool l_dbus_client_set_connect_handler(struct l_dbus_client
> > *client, +						l_dbus_watch_func_t function,
> > +						void *user_data,
> > +						l_dbus_destroy_func_t destroy)
> > +{
> > +	if (unlikely(!client))
> > +		return false;
> > +
> > +	client->connect_cb = function;
> > +	client->connect_cb_data = user_data;
> > +	client->connect_cb_data_destroy = destroy;
> 
> No biggie, but maybe we should call destroy function here in case it is
> already set.

OK.

> 
> > +
> > +	return true;
> > +}
> > +
> > +LIB_EXPORT bool l_dbus_client_set_disconnect_handler(struct l_dbus_client
> > *client, +						l_dbus_watch_func_t function,
> > +						void *user_data,
> > +						l_dbus_destroy_func_t destroy)
> > +{
> > +	if (unlikely(!client))
> > +		return false;
> > +
> > +	client->disconnect_cb = function;
> > +	client->disconnect_cb_data = user_data;
> > +	client->disconnect_cb_data_destroy = destroy;
> 
> as above
> 
> > +
> > +	return true;
> > +}
> > +
> > +LIB_EXPORT bool l_dbus_client_set_ready_handler(struct l_dbus_client
> > *client, +					l_dbus_client_ready_func_t function,
> > +					void *user_data,
> > +					l_dbus_destroy_func_t destroy)
> > +{
> > +	if (unlikely(!client))
> > +		return false;
> > +
> > +	client->ready_cb = function;
> > +	client->ready_cb_data = user_data;
> > +	client->ready_cb_data_destroy = destroy;
> 
> as above
> 
> > +
> > +	return true;
> > +}
> > +
> > +LIB_EXPORT bool l_dbus_client_set_proxy_handlers(struct l_dbus_client
> > *client, +			l_dbus_client_proxy_func_t proxy_added,
> > +			l_dbus_client_proxy_func_t proxy_removed,
> > +			l_dbus_client_property_function_t property_changed,
> > +			void *user_data, l_dbus_destroy_func_t destroy)
> > +{
> > +	if (unlikely(!client))
> > +		return false;
> > +
> > +	client->proxy_added_cb = proxy_added;
> > +	client->proxy_removed_cb = proxy_removed;
> > +	client->properties_changed_cb = property_changed;
> > +	client->proxy_cb_data = user_data;
> > +	client->proxy_cb_data_destroy = destroy;
> 
> as above
> 
> > +
> > +	return true;
> > +}
> 
> <snip>
> 
> Regards,
> -Denis


-- 
pozdrawiam
Szymon Janc

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-12-05 17:05 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
2017-12-01 15:06 ` [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist Szymon Janc
2017-12-04 18:25   ` Denis Kenzior
2017-12-01 15:06 ` [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments Szymon Janc
2017-12-04 18:25   ` Denis Kenzior
2017-12-01 15:06 ` [PATCH 3/6] dbus: Add support for proxy interface Szymon Janc
2017-12-04 18:40   ` Denis Kenzior
2017-12-05 17:05     ` Szymon Janc
2017-12-01 15:06 ` [PATCH 4/6] dbus: Add support for setting properties on D-Bus " Szymon Janc
2017-12-01 15:06 ` [PATCH 5/6] dbus: Add convenient API for calling method on " Szymon Janc
2017-12-01 15:06 ` [PATCH 6/6] examples: Extend dbus-client example Szymon Janc

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.