* [PATCH 1/2] dbus: Add private _dbus_message_new_error
@ 2016-04-18 14:31 Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 2/2] dbus: Handle kdbus KDBUS_ITEM_REPLY_TIMEOUT / _DEAD Andrew Zaborowski
` (9 more replies)
0 siblings, 10 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 3112 bytes --]
---
ell/dbus-message.c | 47 +++++++++++++++++++++++++++++++----------------
ell/dbus-private.h | 5 +++++
2 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index a409e53..86cec96 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -328,33 +328,32 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
return message;
}
-LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
- struct l_dbus_message *method_call,
- const char *name,
- const char *format, va_list args)
+struct l_dbus_message *_dbus_message_new_error(uint8_t version,
+ uint32_t reply_serial,
+ const char *destination,
+ const char *name,
+ const char *error)
{
- char str[1024];
struct l_dbus_message *reply;
- struct dbus_header *hdr = method_call->header;
- const char *sender;
+ bool r;
if (!_dbus_valid_interface(name))
return NULL;
- vsnprintf(str, sizeof(str), format, args);
reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
- hdr->version);
-
- reply->reply_serial = _dbus_message_get_serial(method_call);
-
- sender = l_dbus_message_get_sender(method_call);
- if (sender)
- reply->destination = l_strdup(sender);
+ version);
reply->error_name = l_strdup(name);
+ reply->destination = l_strdup(destination);
+ reply->reply_serial = reply_serial;
- if (!l_dbus_message_set_arguments(reply, "s", str)) {
+ if (error)
+ r = l_dbus_message_set_arguments(reply, "s", error);
+ else
+ r = l_dbus_message_set_arguments(reply, "");
+
+ if (!r) {
l_dbus_message_unref(reply);
return NULL;
}
@@ -362,6 +361,22 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
return reply;
}
+LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
+ struct l_dbus_message *method_call,
+ const char *name,
+ const char *format, va_list args)
+{
+ char str[1024];
+ struct dbus_header *hdr = method_call->header;
+
+ vsnprintf(str, sizeof(str), format, args);
+
+ return _dbus_message_new_error(hdr->version,
+ _dbus_message_get_serial(method_call),
+ l_dbus_message_get_sender(method_call),
+ name, str);
+}
+
LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error(
struct l_dbus_message *method_call,
const char *name,
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 63c239b..030ce0b 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -141,6 +141,11 @@ struct l_dbus_message *_dbus_message_new_signal(uint8_t version,
const char *path,
const char *interface,
const char *name);
+struct l_dbus_message *_dbus_message_new_error(uint8_t version,
+ uint32_t reply_serial,
+ const char *destination,
+ const char *name,
+ const char *error);
struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size);
struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/2] dbus: Handle kdbus KDBUS_ITEM_REPLY_TIMEOUT / _DEAD
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-18 14:31 ` [PATCH] dbus: Check message->sealed before get_header_field() Andrew Zaborowski
` (8 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1112 bytes --]
Generate DBus1-like error messages on kernel error notifications.
---
ell/dbus-kernel.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/ell/dbus-kernel.c b/ell/dbus-kernel.c
index b5a07a5..4fd2f29 100644
--- a/ell/dbus-kernel.c
+++ b/ell/dbus-kernel.c
@@ -559,6 +559,7 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
struct kdbus_item *item;
int r;
size_t min_size;
+ const char *error;
memset(&recv_cmd, 0, sizeof(recv_cmd));
@@ -601,6 +602,23 @@ int _dbus_kernel_recv(int fd, void *kdbus_pool,
user_data);
break;
+ case KDBUS_ITEM_REPLY_TIMEOUT:
+ case KDBUS_ITEM_REPLY_DEAD:
+ if (item->type == KDBUS_ITEM_REPLY_TIMEOUT)
+ error = "Did not receive a reply.";
+ else
+ error = "Message recipient disconnected from "
+ "message bus without replying.";
+
+ dbus_msg = _dbus_message_new_error(
+ 2, msg->cookie_reply, NULL,
+ "org.freedesktop.DBus.Error.NoReply",
+ error);
+ if (dbus_msg)
+ message_func(dbus_msg, user_data);
+
+ break;
+
default:
break;
}
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH] dbus: Check message->sealed before get_header_field()
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 2/2] dbus: Handle kdbus KDBUS_ITEM_REPLY_TIMEOUT / _DEAD Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-19 2:39 ` Denis Kenzior
2016-04-18 14:31 ` [PATCH] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
` (7 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2368 bytes --]
Also make sure _dbus_message_get_reply_serial on kdbus doesn't overwrite
message->reply_serial with uninitialised value.
---
ell/dbus-message.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 86cec96..aecf398 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1336,7 +1336,7 @@ LIB_EXPORT const char *l_dbus_message_get_path(struct l_dbus_message *message)
if (unlikely(!message))
return NULL;
- if (!message->path)
+ if (!message->path && message->sealed)
get_header_field(message, DBUS_MESSAGE_FIELD_PATH, 'o',
&message->path);
@@ -1348,7 +1348,7 @@ LIB_EXPORT const char *l_dbus_message_get_interface(struct l_dbus_message *messa
if (unlikely(!message))
return NULL;
- if (!message->interface)
+ if (!message->interface && message->sealed)
get_header_field(message, DBUS_MESSAGE_FIELD_INTERFACE, 's',
&message->interface);
@@ -1360,7 +1360,7 @@ LIB_EXPORT const char *l_dbus_message_get_member(struct l_dbus_message *message)
if (unlikely(!message))
return NULL;
- if (!message->member)
+ if (!message->member && message->sealed)
get_header_field(message, DBUS_MESSAGE_FIELD_MEMBER, 's',
&message->member);
@@ -1372,7 +1372,7 @@ LIB_EXPORT const char *l_dbus_message_get_destination(struct l_dbus_message *mes
if (unlikely(!message))
return NULL;
- if (!message->destination)
+ if (!message->destination && message->sealed)
get_header_field(message, DBUS_MESSAGE_FIELD_DESTINATION, 's',
&message->destination);
@@ -1384,7 +1384,7 @@ LIB_EXPORT const char *l_dbus_message_get_sender(struct l_dbus_message *message)
if (unlikely(!message))
return NULL;
- if (!message->sender)
+ if (!message->sender && message->sealed)
get_header_field(message, DBUS_MESSAGE_FIELD_SENDER, 's',
&message->sender);
@@ -1405,9 +1405,9 @@ uint32_t _dbus_message_get_reply_serial(struct l_dbus_message *message)
if (unlikely(!message))
return 0;
- if (message->reply_serial == 0) {
+ if (message->reply_serial == 0 && message->sealed) {
if (_dbus_message_is_gvariant(message)) {
- uint64_t reply_serial;
+ uint64_t reply_serial = 0;
get_header_field(message,
DBUS_MESSAGE_FIELD_REPLY_SERIAL, 't',
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH] dbus: Don't send replies to messages with no reply flag
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 2/2] dbus: Handle kdbus KDBUS_ITEM_REPLY_TIMEOUT / _DEAD Andrew Zaborowski
2016-04-18 14:31 ` [PATCH] dbus: Check message->sealed before get_header_field() Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-18 14:31 ` [PATCH] unit: Add test-dbus-properties --kdbus option Andrew Zaborowski
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2313 bytes --]
Kdbus doesn't store the cookies for messages that have the no reply flag
and throws error when a reply is sent with reply_cookie that it doesn't
know. It's not fatal, but we also save some cycles by not sending the
message.
We mark those replies with reply_serial == 0, rather than setting a
"discard" flag on the message, because the method call's serial is
effectively an invalid reply_serial value.
---
ell/dbus-message.c | 10 +++++++---
ell/dbus.c | 10 ++++++++++
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index aecf398..9286f0e 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -319,7 +319,8 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
hdr->version);
- message->reply_serial = _dbus_message_get_serial(method_call);
+ if (!l_dbus_message_get_no_reply(method_call))
+ message->reply_serial = _dbus_message_get_serial(method_call);
sender = l_dbus_message_get_sender(method_call);
if (sender)
@@ -368,11 +369,14 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
{
char str[1024];
struct dbus_header *hdr = method_call->header;
+ uint32_t reply_serial = 0;
vsnprintf(str, sizeof(str), format, args);
- return _dbus_message_new_error(hdr->version,
- _dbus_message_get_serial(method_call),
+ if (!l_dbus_message_get_no_reply(method_call))
+ reply_serial = _dbus_message_get_serial(method_call);
+
+ return _dbus_message_new_error(hdr->version, reply_serial,
l_dbus_message_get_sender(method_call),
name, str);
}
diff --git a/ell/dbus.c b/ell/dbus.c
index 9bb47ae..84b3fa1 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -325,6 +325,16 @@ static uint32_t send_message(struct l_dbus *dbus, bool priority,
void *user_data, l_dbus_destroy_func_t destroy)
{
struct message_callback *callback;
+ enum dbus_message_type type;
+
+ type = _dbus_message_get_type(message);
+
+ if ((type == DBUS_MESSAGE_TYPE_METHOD_RETURN ||
+ type == DBUS_MESSAGE_TYPE_ERROR) &&
+ _dbus_message_get_reply_serial(message) == 0) {
+ l_dbus_message_unref(message);
+ return 0;
+ }
callback = l_new(struct message_callback, 1);
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH] unit: Add test-dbus-properties --kdbus option
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (2 preceding siblings ...)
2016-04-18 14:31 ` [PATCH] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-19 2:41 ` Denis Kenzior
2016-04-18 14:31 ` [PATCH 1/5] dbus: Add a Bus Name cache Andrew Zaborowski
` (5 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2958 bytes --]
---
unit/test-dbus-properties.c | 49 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/unit/test-dbus-properties.c b/unit/test-dbus-properties.c
index c7ed384..3238cf6 100644
--- a/unit/test-dbus-properties.c
+++ b/unit/test-dbus-properties.c
@@ -27,13 +27,19 @@
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
+#include <stdio.h>
#include <ell/ell.h>
+#include <ell/dbus-private.h>
#define TEST_BUS_ADDRESS "unix:path=/tmp/ell-test-bus"
static pid_t dbus_daemon_pid = -1;
+static int kdbus_fd = -1;
+
+static char bus_address[128];
+
static void start_dbus_daemon(void)
{
char *prg_argv[6];
@@ -65,6 +71,24 @@ static void start_dbus_daemon(void)
l_info("dbus-daemon process %d created", pid);
dbus_daemon_pid = pid;
+
+ strcpy(bus_address, TEST_BUS_ADDRESS);
+}
+
+static void create_kdbus(void)
+{
+ char bus_name[64];
+
+ snprintf(bus_name, sizeof(bus_name), "%u-ell-test", getuid());
+
+ kdbus_fd = _dbus_kernel_create_bus(bus_name);
+ if (kdbus_fd < 0) {
+ l_warn("kdbus not available");
+ return;
+ }
+
+ snprintf(bus_address, sizeof(bus_address),
+ "kernel:path=/dev/kdbus/%s/bus", bus_name);
}
static void signal_handler(struct l_signal *signal, uint32_t signo,
@@ -164,6 +188,9 @@ static void request_name_callback(struct l_dbus *dbus, bool success,
static void ready_callback(void *user_data)
{
l_info("ready");
+
+ l_dbus_name_acquire(dbus, "org.test", false, false, false,
+ request_name_callback, NULL);
}
static void disconnect_callback(void *user_data)
@@ -894,6 +921,12 @@ int main(int argc, char *argv[])
struct l_signal *signal;
sigset_t mask;
int i;
+ bool kdbus = false;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "--kdbus"))
+ kdbus = true;
+ }
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
@@ -904,12 +937,18 @@ int main(int argc, char *argv[])
l_log_set_stderr();
- start_dbus_daemon();
+ if (kdbus)
+ create_kdbus();
+ else
+ start_dbus_daemon();
+
+ if (!bus_address[0])
+ return -1;
for (i = 0; i < 10; i++) {
usleep(200 * 1000);
- dbus = l_dbus_new(TEST_BUS_ADDRESS);
+ dbus = l_dbus_new(bus_address);
if (dbus)
break;
}
@@ -917,9 +956,6 @@ int main(int argc, char *argv[])
l_dbus_set_ready_handler(dbus, ready_callback, dbus, NULL);
l_dbus_set_disconnect_handler(dbus, disconnect_callback, NULL, NULL);
- l_dbus_name_acquire(dbus, "org.test", false, false, false,
- request_name_callback, NULL);
-
if (!l_dbus_register_interface(dbus, "org.test", setup_test_interface,
NULL, true)) {
l_info("Unable to register interface");
@@ -977,6 +1013,9 @@ done:
if (dbus_daemon_pid > 0)
kill(dbus_daemon_pid, SIGKILL);
+ if (kdbus_fd >= 0)
+ close(kdbus_fd);
+
l_signal_remove(signal);
if (!success)
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 1/5] dbus: Add a Bus Name cache
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (3 preceding siblings ...)
2016-04-18 14:31 ` [PATCH] unit: Add test-dbus-properties --kdbus option Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-21 3:30 ` Denis Kenzior
2016-04-18 14:31 ` [PATCH 2/5] dbus: Use the name cache API in _dbus_filter Andrew Zaborowski
` (4 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 9250 bytes --]
---
Makefile.am | 1 +
ell/dbus-name-cache.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
ell/dbus-private.h | 18 ++++++
ell/dbus.c | 35 +++++++++---
4 files changed, 196 insertions(+), 7 deletions(-)
create mode 100644 ell/dbus-name-cache.c
diff --git a/Makefile.am b/Makefile.am
index 7283a7e..3e8e3ef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -75,6 +75,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
ell/dbus-message.c \
ell/dbus-util.c \
ell/dbus-service.c \
+ ell/dbus-name-cache.c \
ell/dbus-filter.c \
ell/gvariant-private.h \
ell/gvariant-util.c \
diff --git a/ell/dbus-name-cache.c b/ell/dbus-name-cache.c
new file mode 100644
index 0000000..76b1792
--- /dev/null
+++ b/ell/dbus-name-cache.c
@@ -0,0 +1,149 @@
+/*
+ *
+ * Embedded Linux library
+ *
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "util.h"
+#include "hashmap.h"
+#include "dbus.h"
+#include "dbus-private.h"
+
+struct _dbus_name_cache {
+ struct l_dbus *bus;
+ struct l_hashmap *names;
+ const struct _dbus_name_ops *driver;
+};
+
+struct name_cache_entry {
+ int ref_count;
+ char *unique_name;
+};
+
+struct _dbus_name_cache *_dbus_name_cache_new(struct l_dbus *bus,
+ const struct _dbus_name_ops *driver)
+{
+ struct _dbus_name_cache *cache;
+
+ cache = l_new(struct _dbus_name_cache, 1);
+
+ cache->bus = bus;
+ cache->driver = driver;
+
+ return cache;
+}
+
+static void name_cache_entry_destroy(void *data)
+{
+ struct name_cache_entry *entry = data;
+
+ l_free(entry->unique_name);
+
+ l_free(entry);
+}
+
+void _dbus_name_cache_free(struct _dbus_name_cache *cache)
+{
+ l_hashmap_destroy(cache->names, name_cache_entry_destroy);
+
+ l_free(cache);
+}
+
+bool _dbus_name_cache_add(struct _dbus_name_cache *cache, const char *name)
+{
+ struct name_cache_entry *entry;
+
+ if (!_dbus_valid_bus_name(name))
+ return false;
+
+ if (!cache->names)
+ cache->names = l_hashmap_string_new();
+
+ entry = l_hashmap_lookup(cache->names, name);
+
+ if (!entry) {
+ entry = l_new(struct name_cache_entry, 1);
+
+ l_hashmap_insert(cache->names, name, entry);
+
+ cache->driver->get_name_owner(cache->bus, name);
+ }
+
+ entry->ref_count++;
+
+ return true;
+}
+
+bool _dbus_name_cache_remove(struct _dbus_name_cache *cache, const char *name)
+{
+ struct name_cache_entry *entry;
+
+ entry = l_hashmap_lookup(cache->names, name);
+
+ if (!entry)
+ return false;
+
+ if (--entry->ref_count)
+ return true;
+
+ l_hashmap_remove(cache->names, name);
+
+ name_cache_entry_destroy(entry);
+
+ return true;
+}
+
+const char *_dbus_name_cache_lookup(struct _dbus_name_cache *cache,
+ const char *name)
+{
+ struct name_cache_entry *entry;
+
+ entry = l_hashmap_lookup(cache->names, name);
+
+ if (!entry)
+ return NULL;
+
+ return entry->unique_name;
+}
+
+void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
+ const char *name, const char *owner)
+{
+ struct name_cache_entry *entry;
+
+ if (_dbus_parse_unique_name(name, NULL))
+ return;
+
+ entry = l_hashmap_lookup(cache->names, name);
+
+ if (!entry)
+ return;
+
+ l_free(entry->unique_name);
+
+ entry->unique_name = (owner && *owner != '\0') ? l_strdup(owner) : NULL;
+}
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 030ce0b..327f0e3 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -273,6 +273,24 @@ uint8_t _dbus_get_version(struct l_dbus *dbus);
int _dbus_get_fd(struct l_dbus *dbus);
struct _dbus_object_tree *_dbus_get_tree(struct l_dbus *dbus);
+struct _dbus_name_ops {
+ bool (*get_name_owner)(struct l_dbus *bus, const char *name);
+};
+
+struct _dbus_name_cache;
+
+struct _dbus_name_cache *_dbus_name_cache_new(struct l_dbus *bus,
+ const struct _dbus_name_ops *driver);
+void _dbus_name_cache_free(struct _dbus_name_cache *cache);
+
+bool _dbus_name_cache_add(struct _dbus_name_cache *cache, const char *name);
+bool _dbus_name_cache_remove(struct _dbus_name_cache *cache, const char *name);
+const char *_dbus_name_cache_lookup(struct _dbus_name_cache *cache,
+ const char *name);
+
+void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
+ const char *name, const char *owner);
+
struct _dbus_filter_condition {
enum l_dbus_match_type type;
const char *value;
diff --git a/ell/dbus.c b/ell/dbus.c
index 84b3fa1..529a26a 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -64,6 +64,7 @@ struct l_dbus_ops {
struct l_dbus_message *message);
struct l_dbus_message *(*recv_message)(struct l_dbus *bus);
void (*free)(struct l_dbus *bus);
+ struct _dbus_name_ops name_ops;
struct _dbus_filter_ops filter_ops;
uint32_t (*name_acquire)(struct l_dbus *dbus, const char *name,
bool allow_replacement, bool replace_existing,
@@ -93,6 +94,7 @@ struct l_dbus {
l_dbus_destroy_func_t debug_destroy;
void *debug_data;
struct _dbus_object_tree *tree;
+ struct _dbus_name_cache *name_cache;
struct _dbus_filter *filter;
const struct l_dbus_ops *driver;
@@ -571,6 +573,8 @@ static void dbus_init(struct l_dbus *dbus, int fd)
dbus->tree = _dbus_object_tree_new();
+ dbus->name_cache = _dbus_name_cache_new(dbus, &dbus->driver->name_ops);
+
dbus->filter = _dbus_filter_new(dbus, &dbus->driver->filter_ops);
}
@@ -768,6 +772,8 @@ static void get_name_owner_reply_cb(struct l_dbus_message *reply,
return;
_dbus_filter_name_owner_notify(req->dbus->filter, name, owner);
+
+ _dbus_name_cache_notify(req->dbus->name_cache, name, owner);
}
static bool classic_get_name_owner(struct l_dbus *bus, const char *name)
@@ -879,6 +885,9 @@ static const struct l_dbus_ops classic_ops = {
.send_message = classic_send_message,
.recv_message = classic_recv_message,
.free = classic_free,
+ .name_ops = {
+ .get_name_owner = classic_get_name_owner,
+ },
.filter_ops = {
.add_match = classic_add_match,
.remove_match = classic_remove_match,
@@ -897,6 +906,8 @@ static void name_owner_changed_cb(struct l_dbus_message *message,
return;
_dbus_filter_name_owner_notify(dbus->filter, name, new);
+
+ _dbus_name_cache_notify(dbus->name_cache, name, new);
}
static struct l_dbus *setup_dbus1(int fd, const char *guid)
@@ -1102,9 +1113,14 @@ static void kdbus_name_owner_change_func(const char *name, uint64_t old_owner,
recv_data->dbus->debug_data,
"Read KDBUS Name Owner Change notification");
- snprintf(owner, sizeof(owner), ":1.%" PRIu64, new_owner);
+ if (new_owner)
+ snprintf(owner, sizeof(owner), ":1.%" PRIu64, new_owner);
+ else
+ owner[0] = '\0';
_dbus_filter_name_owner_notify(recv_data->dbus->filter, name, owner);
+
+ _dbus_name_cache_notify(recv_data->dbus->name_cache, name, owner);
}
static struct l_dbus_message *kdbus_recv_message(struct l_dbus *dbus)
@@ -1166,16 +1182,16 @@ static bool kdbus_get_name_owner(struct l_dbus *dbus, const char *name)
char owner[32];
owner_id = _dbus_kernel_get_name_owner(fd, kdbus->kdbus_pool, name);
- if (!owner_id) {
- l_util_debug(dbus->debug_handler,
- dbus->debug_data, "Error getting name owner");
- return false;
- }
- snprintf(owner, sizeof(owner), ":1.%" PRIu64, owner_id);
+ if (owner_id)
+ snprintf(owner, sizeof(owner), ":1.%" PRIu64, owner_id);
+ else
+ owner[0] = '\0';
_dbus_filter_name_owner_notify(dbus->filter, name, owner);
+ _dbus_name_cache_notify(dbus->name_cache, name, owner);
+
return true;
}
@@ -1210,6 +1226,9 @@ static const struct l_dbus_ops kdbus_ops = {
.free = kdbus_free,
.send_message = kdbus_send_message,
.recv_message = kdbus_recv_message,
+ .name_ops = {
+ .get_name_owner = kdbus_get_name_owner,
+ },
.filter_ops = {
.add_match = kdbus_add_match,
.remove_match = kdbus_remove_match,
@@ -1355,6 +1374,8 @@ LIB_EXPORT void l_dbus_destroy(struct l_dbus *dbus)
_dbus_filter_free(dbus->filter);
+ _dbus_name_cache_free(dbus->name_cache);
+
l_hashmap_destroy(dbus->signal_list, signal_list_destroy);
l_hashmap_destroy(dbus->message_list, message_list_destroy);
l_queue_destroy(dbus->message_queue, message_queue_destroy);
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/5] dbus: Use the name cache API in _dbus_filter
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (4 preceding siblings ...)
2016-04-18 14:31 ` [PATCH 1/5] dbus: Add a Bus Name cache Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 3/5] unit: Update _dbus_filter usage in test-dbus-watch Andrew Zaborowski
` (3 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 9024 bytes --]
---
ell/dbus-filter.c | 122 +++++++++--------------------------------------------
ell/dbus-private.h | 6 +--
ell/dbus.c | 13 +-----
3 files changed, 24 insertions(+), 117 deletions(-)
diff --git a/ell/dbus-filter.c b/ell/dbus-filter.c
index 59059cb..42755a9 100644
--- a/ell/dbus-filter.c
+++ b/ell/dbus-filter.c
@@ -62,12 +62,7 @@ struct _dbus_filter {
unsigned int signal_id;
unsigned int last_id;
const struct _dbus_filter_ops *driver;
- struct l_hashmap *unique_names;
-};
-
-struct unique_name_record {
- int ref_count;
- char *unique_name;
+ struct _dbus_name_cache *name_cache;
};
static void filter_subtree_free(struct filter_node *node)
@@ -92,14 +87,6 @@ static void filter_subtree_free(struct filter_node *node)
}
}
-static void unique_name_record_free(void *data)
-{
- struct unique_name_record *name_rec = data;
-
- l_free(name_rec->unique_name);
- l_free(name_rec);
-}
-
static void dbus_filter_destroy(void *data)
{
struct _dbus_filter *filter = data;
@@ -107,10 +94,6 @@ static void dbus_filter_destroy(void *data)
if (filter->root)
filter_subtree_free(filter->root);
- if (filter->unique_names)
- l_hashmap_destroy(filter->unique_names,
- unique_name_record_free);
-
l_free(filter);
}
@@ -120,7 +103,6 @@ static void filter_dispatch_match_recurse(struct _dbus_filter *filter,
{
const char *value = NULL;
const char *alt_value = NULL;
- const struct unique_name_record *name_rec;
struct filter_node *child;
switch ((int) node->type) {
@@ -157,13 +139,9 @@ static void filter_dispatch_match_recurse(struct _dbus_filter *filter,
if (!value)
return;
- if (node->type == L_DBUS_MATCH_SENDER && filter->unique_names) {
- name_rec = l_hashmap_lookup(filter->unique_names,
- node->match.value);
-
- if (name_rec)
- alt_value = name_rec->unique_name;
- }
+ if (node->type == L_DBUS_MATCH_SENDER && filter->name_cache)
+ alt_value = _dbus_name_cache_lookup(filter->name_cache,
+ node->match.value);
if (strcmp(value, node->match.value) &&
(!alt_value || strcmp(value, alt_value)))
@@ -180,28 +158,9 @@ void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data)
filter_dispatch_match_recurse(filter, filter->root, message);
}
-void _dbus_filter_name_owner_notify(struct _dbus_filter *filter,
- const char *name, const char *owner)
-{
- struct unique_name_record *name_rec;
-
- if (!filter)
- return;
-
- if (_dbus_parse_unique_name(name, NULL))
- return;
-
- name_rec = l_hashmap_lookup(filter->unique_names, name);
- if (!name_rec)
- return;
-
- l_free(name_rec->unique_name);
-
- name_rec->unique_name = (owner && *owner) ? l_strdup(owner) : NULL;
-}
-
struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
- const struct _dbus_filter_ops *driver)
+ const struct _dbus_filter_ops *driver,
+ struct _dbus_name_cache *name_cache)
{
struct _dbus_filter *filter;
@@ -209,15 +168,13 @@ struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
filter->dbus = dbus;
filter->driver = driver;
+ filter->name_cache = name_cache;
if (!filter->driver->skip_register)
filter->signal_id = l_dbus_register(dbus, _dbus_filter_dispatch,
filter,
dbus_filter_destroy);
- if (filter->driver->get_name_owner)
- filter->unique_names = l_hashmap_string_new();
-
return filter;
}
@@ -232,54 +189,6 @@ void _dbus_filter_free(struct _dbus_filter *filter)
dbus_filter_destroy(filter);
}
-static bool filter_add_bus_name(struct _dbus_filter *filter, const char *name)
-{
- struct unique_name_record *name_rec;
-
- if (!filter->unique_names)
- return true;
-
- if (_dbus_parse_unique_name(name, NULL))
- return true;
-
- if (!_dbus_valid_bus_name(name))
- return false;
-
- name_rec = l_hashmap_lookup(filter->unique_names, name);
- if (!name_rec) {
- name_rec = l_new(struct unique_name_record, 1);
-
- l_hashmap_insert(filter->unique_names, name, name_rec);
-
- filter->driver->get_name_owner(filter->dbus, name);
- }
-
- name_rec->ref_count++;
-
- return true;
-}
-
-static void filter_remove_bus_name(struct _dbus_filter *filter,
- const char *name)
-{
- struct unique_name_record *name_rec;
-
- if (!filter->unique_names)
- return;
-
- if (_dbus_parse_unique_name(name, NULL))
- return;
-
- name_rec = l_hashmap_lookup(filter->unique_names, name);
-
- if (--name_rec->ref_count)
- return;
-
- l_hashmap_remove(filter->unique_names, name);
-
- unique_name_record_free(name_rec);
-}
-
static int condition_compare(const void *a, const void *b)
{
const struct _dbus_filter_condition *condition_a = a, *condition_b = b;
@@ -312,8 +221,11 @@ static bool remove_recurse(struct _dbus_filter *filter,
if (tmp->match.remote_rule)
filter->driver->remove_match(filter->dbus, tmp->id);
- if (tmp->type == L_DBUS_MATCH_SENDER)
- filter_remove_bus_name(filter, tmp->match.value);
+ if (tmp->type == L_DBUS_MATCH_SENDER && filter->name_cache &&
+ !_dbus_parse_unique_name(tmp->match.value,
+ NULL))
+ _dbus_name_cache_remove(filter->name_cache,
+ tmp->match.value);
filter_subtree_free(tmp);
}
@@ -356,8 +268,14 @@ unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
*node_ptr = node;
- if (node->type == L_DBUS_MATCH_SENDER)
- filter_add_bus_name(filter, node->match.value);
+ if (node->type == L_DBUS_MATCH_SENDER &&
+ filter->name_cache &&
+ !_dbus_parse_unique_name(
+ node->match.value,
+ NULL))
+ _dbus_name_cache_add(filter->name_cache,
+ node->match.value);
+
}
node_ptr = &node->match.children;
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 327f0e3..1ade3e0 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -302,11 +302,11 @@ struct _dbus_filter_ops {
const struct _dbus_filter_condition *rule,
int rule_len);
bool (*remove_match)(struct l_dbus *bus, unsigned int id);
- bool (*get_name_owner)(struct l_dbus *bus, const char *name);
};
struct _dbus_filter *_dbus_filter_new(struct l_dbus *dbus,
- const struct _dbus_filter_ops *driver);
+ const struct _dbus_filter_ops *driver,
+ struct _dbus_name_cache *name_cache);
void _dbus_filter_free(struct _dbus_filter *filter);
unsigned int _dbus_filter_add_rule(struct _dbus_filter *filter,
@@ -320,8 +320,6 @@ char *_dbus_filter_rule_to_str(const struct _dbus_filter_condition *rule,
int rule_len);
void _dbus_filter_dispatch(struct l_dbus_message *message, void *user_data);
-void _dbus_filter_name_owner_notify(struct _dbus_filter *filter,
- const char *name, const char *owner);
struct dbus1_filter_data;
diff --git a/ell/dbus.c b/ell/dbus.c
index 529a26a..bc6aaed 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -575,7 +575,8 @@ static void dbus_init(struct l_dbus *dbus, int fd)
dbus->name_cache = _dbus_name_cache_new(dbus, &dbus->driver->name_ops);
- dbus->filter = _dbus_filter_new(dbus, &dbus->driver->filter_ops);
+ dbus->filter = _dbus_filter_new(dbus, &dbus->driver->filter_ops,
+ dbus->name_cache);
}
static void classic_free(struct l_dbus *dbus)
@@ -771,8 +772,6 @@ static void get_name_owner_reply_cb(struct l_dbus_message *reply,
if (!l_dbus_message_get_arguments(req->message, "s", &name))
return;
- _dbus_filter_name_owner_notify(req->dbus->filter, name, owner);
-
_dbus_name_cache_notify(req->dbus->name_cache, name, owner);
}
@@ -891,7 +890,6 @@ static const struct l_dbus_ops classic_ops = {
.filter_ops = {
.add_match = classic_add_match,
.remove_match = classic_remove_match,
- .get_name_owner = classic_get_name_owner,
},
.name_acquire = classic_name_acquire,
};
@@ -905,8 +903,6 @@ static void name_owner_changed_cb(struct l_dbus_message *message,
if (!l_dbus_message_get_arguments(message, "sss", &name, &old, &new))
return;
- _dbus_filter_name_owner_notify(dbus->filter, name, new);
-
_dbus_name_cache_notify(dbus->name_cache, name, new);
}
@@ -1118,8 +1114,6 @@ static void kdbus_name_owner_change_func(const char *name, uint64_t old_owner,
else
owner[0] = '\0';
- _dbus_filter_name_owner_notify(recv_data->dbus->filter, name, owner);
-
_dbus_name_cache_notify(recv_data->dbus->name_cache, name, owner);
}
@@ -1188,8 +1182,6 @@ static bool kdbus_get_name_owner(struct l_dbus *dbus, const char *name)
else
owner[0] = '\0';
- _dbus_filter_name_owner_notify(dbus->filter, name, owner);
-
_dbus_name_cache_notify(dbus->name_cache, name, owner);
return true;
@@ -1232,7 +1224,6 @@ static const struct l_dbus_ops kdbus_ops = {
.filter_ops = {
.add_match = kdbus_add_match,
.remove_match = kdbus_remove_match,
- .get_name_owner = kdbus_get_name_owner,
},
.name_acquire = kdbus_name_acquire,
};
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/5] unit: Update _dbus_filter usage in test-dbus-watch
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (5 preceding siblings ...)
2016-04-18 14:31 ` [PATCH 2/5] dbus: Use the name cache API in _dbus_filter Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 4/5] dbus: Add service watch API based on the name cache Andrew Zaborowski
` (2 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 1568 bytes --]
Also fix what seems to be incorrect use of l_dbus_message_set_arguments
---
unit/test-dbus-watch.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/unit/test-dbus-watch.c b/unit/test-dbus-watch.c
index 684ac34..1d8f94c 100644
--- a/unit/test-dbus-watch.c
+++ b/unit/test-dbus-watch.c
@@ -387,7 +387,7 @@ static void test_filter_tree(const void *test_data)
{ L_DBUS_MATCH_PATH, DBUS_PATH_DBUS },
{ L_DBUS_MATCH_INTERFACE, DBUS_INTERFACE_DBUS },
{ L_DBUS_MATCH_MEMBER, "NameOwnerChanged" },
- { L_DBUS_MATCH_ARGUMENT(0), ":1.101" }
+ { L_DBUS_MATCH_ARGUMENT(0), "org.test" }
};
static struct _dbus_filter_condition rule4[] = {
{ L_DBUS_MATCH_TYPE, "signal" },
@@ -396,7 +396,7 @@ static void test_filter_tree(const void *test_data)
unsigned int id1, id2, id3, id4, internal_id1, internal_id4;
struct l_dbus_message *message;
- filter = _dbus_filter_new(&test.dbus, &filter_ops);
+ filter = _dbus_filter_new(&test.dbus, &filter_ops, NULL);
assert(filter);
test.expected_rule = rule123;
@@ -423,7 +423,8 @@ static void test_filter_tree(const void *test_data)
message = _dbus_message_new_signal(2, DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"NameOwnerChanged");
- l_dbus_message_set_arguments(message, "sss", ":1.101", "", ":1.101");
+ l_dbus_message_set_arguments(message, "sss", "org.test",
+ ":1.101", "", ":1.101");
_dbus_message_set_sender(message, DBUS_SERVICE_DBUS);
_dbus_filter_dispatch(message, filter);
l_dbus_message_unref(message);
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/5] dbus: Add service watch API based on the name cache
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (6 preceding siblings ...)
2016-04-18 14:31 ` [PATCH 3/5] unit: Update _dbus_filter usage in test-dbus-watch Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 5/5] dbus: Use the name cache for public service watches Andrew Zaborowski
2016-04-19 2:37 ` [PATCH 1/2] dbus: Add private _dbus_message_new_error Denis Kenzior
9 siblings, 0 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 6300 bytes --]
---
ell/dbus-name-cache.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++-
ell/dbus-private.h | 9 +++
2 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/ell/dbus-name-cache.c b/ell/dbus-name-cache.c
index 76b1792..f7d5e50 100644
--- a/ell/dbus-name-cache.c
+++ b/ell/dbus-name-cache.c
@@ -30,6 +30,7 @@
#include "util.h"
#include "hashmap.h"
+#include "idle.h"
#include "dbus.h"
#include "dbus-private.h"
@@ -37,11 +38,24 @@ struct _dbus_name_cache {
struct l_dbus *bus;
struct l_hashmap *names;
const struct _dbus_name_ops *driver;
+ unsigned int last_watch_id;
+ struct l_idle *watch_remove_work;
+};
+
+struct service_watch {
+ l_dbus_watch_func_t connect_func;
+ l_dbus_watch_func_t disconnect_func;
+ l_dbus_destroy_func_t destroy;
+ void *user_data;
+ unsigned int id;
+ bool removed;
+ struct service_watch *next;
};
struct name_cache_entry {
int ref_count;
char *unique_name;
+ struct service_watch *watches;
};
struct _dbus_name_cache *_dbus_name_cache_new(struct l_dbus *bus,
@@ -57,9 +71,27 @@ struct _dbus_name_cache *_dbus_name_cache_new(struct l_dbus *bus,
return cache;
}
+static void service_watch_destroy(void *data)
+{
+ struct service_watch *watch = data;
+
+ if (watch->destroy)
+ watch->destroy(watch->user_data);
+
+ l_free(watch);
+}
+
static void name_cache_entry_destroy(void *data)
{
struct name_cache_entry *entry = data;
+ struct service_watch *watch;
+
+ while (entry->watches) {
+ watch = entry->watches;
+ entry->watches = watch->next;
+
+ service_watch_destroy(watch);
+ }
l_free(entry->unique_name);
@@ -68,6 +100,9 @@ static void name_cache_entry_destroy(void *data)
void _dbus_name_cache_free(struct _dbus_name_cache *cache)
{
+ if (cache->watch_remove_work)
+ l_idle_remove(cache->watch_remove_work);
+
l_hashmap_destroy(cache->names, name_cache_entry_destroy);
l_free(cache);
@@ -134,6 +169,8 @@ void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
const char *name, const char *owner)
{
struct name_cache_entry *entry;
+ struct service_watch *watch;
+ bool prev_connected, connected;
if (_dbus_parse_unique_name(name, NULL))
return;
@@ -143,7 +180,117 @@ void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
if (!entry)
return;
+ prev_connected = !!entry->unique_name;
+ connected = owner && *owner != '\0';
+
l_free(entry->unique_name);
- entry->unique_name = (owner && *owner != '\0') ? l_strdup(owner) : NULL;
+ entry->unique_name = connected ? l_strdup(owner) : NULL;
+
+ /*
+ * This check also means we notify all watchers who have a connected
+ * callback when we first learn that the service is in fact connected.
+ */
+ if (connected == prev_connected)
+ return;
+
+ for (watch = entry->watches; watch; watch = watch->next)
+ if (connected && watch->connect_func)
+ watch->connect_func(cache->bus, watch->user_data);
+ else if (!connected && watch->disconnect_func)
+ watch->disconnect_func(cache->bus, watch->user_data);
+}
+
+unsigned int _dbus_name_cache_add_watch(struct _dbus_name_cache *cache,
+ const char *name,
+ l_dbus_watch_func_t connect_func,
+ l_dbus_watch_func_t disconnect_func,
+ void *user_data,
+ l_dbus_destroy_func_t destroy)
+{
+ struct name_cache_entry *entry;
+ struct service_watch *watch;
+
+ if (!_dbus_name_cache_add(cache, name))
+ return 0;
+
+ watch = l_new(struct service_watch, 1);
+ watch->id = ++cache->last_watch_id;
+ watch->connect_func = connect_func;
+ watch->disconnect_func = disconnect_func;
+ watch->user_data = user_data;
+ watch->destroy = destroy;
+
+ entry = l_hashmap_lookup(cache->names, name);
+
+ watch->next = entry->watches;
+ entry->watches = watch;
+
+ if (entry->unique_name && connect_func)
+ watch->connect_func(cache->bus, watch->user_data);
+
+ return watch->id;
+}
+
+static void service_watch_remove(const void *key, void *value, void *user_data)
+{
+ struct _dbus_name_cache *cache = user_data;
+ struct name_cache_entry *entry = value;
+ struct service_watch **watch, *tmp;
+
+ for (watch = &entry->watches; *watch;) {
+ if (!(*watch)->removed) {
+ watch = &(*watch)->next;
+ continue;
+ }
+
+ tmp = *watch;
+ *watch = tmp->next;
+
+ service_watch_destroy(tmp);
+
+ _dbus_name_cache_remove(cache, key);
+ }
+}
+
+static void service_watch_remove_all(struct l_idle *idle, void *user_data)
+{
+ struct _dbus_name_cache *cache = user_data;
+
+ l_idle_remove(cache->watch_remove_work);
+ cache->watch_remove_work = NULL;
+
+ l_hashmap_foreach(cache->names, service_watch_remove, cache);
+}
+
+static void service_watch_mark(const void *key, void *value, void *user_data)
+{
+ struct name_cache_entry *entry = value;
+ struct service_watch *watch;
+ unsigned int *id = user_data;
+
+ for (watch = entry->watches; watch; watch = watch->next)
+ if (watch->id == *id) {
+ watch->removed = true;
+ watch->connect_func = NULL;
+ watch->disconnect_func = NULL;
+ *id = 0;
+ break;
+ }
+}
+
+bool _dbus_name_cache_remove_watch(struct _dbus_name_cache *cache,
+ unsigned int id)
+{
+ l_hashmap_foreach(cache->names, service_watch_mark, &id);
+
+ if (id)
+ return false;
+
+ if (!cache->watch_remove_work)
+ cache->watch_remove_work = l_idle_create(
+ service_watch_remove_all,
+ cache, NULL);
+
+ return true;
}
diff --git a/ell/dbus-private.h b/ell/dbus-private.h
index 1ade3e0..48541e0 100644
--- a/ell/dbus-private.h
+++ b/ell/dbus-private.h
@@ -291,6 +291,15 @@ const char *_dbus_name_cache_lookup(struct _dbus_name_cache *cache,
void _dbus_name_cache_notify(struct _dbus_name_cache *cache,
const char *name, const char *owner);
+unsigned int _dbus_name_cache_add_watch(struct _dbus_name_cache *cache,
+ const char *name,
+ l_dbus_watch_func_t connect_func,
+ l_dbus_watch_func_t disconnect_func,
+ void *user_data,
+ l_dbus_destroy_func_t destroy);
+bool _dbus_name_cache_remove_watch(struct _dbus_name_cache *cache,
+ unsigned int id);
+
struct _dbus_filter_condition {
enum l_dbus_match_type type;
const char *value;
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 5/5] dbus: Use the name cache for public service watches
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (7 preceding siblings ...)
2016-04-18 14:31 ` [PATCH 4/5] dbus: Add service watch API based on the name cache Andrew Zaborowski
@ 2016-04-18 14:31 ` Andrew Zaborowski
2016-04-19 2:37 ` [PATCH 1/2] dbus: Add private _dbus_message_new_error Denis Kenzior
9 siblings, 0 replies; 15+ messages in thread
From: Andrew Zaborowski @ 2016-04-18 14:31 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 4542 bytes --]
This also removes the now unused dbus.c functions to fix compilation but
doesn't remove the rest of the logic which is now only used by the unit
test I think and can be removed separately.
---
ell/dbus.c | 120 +++----------------------------------------------------------
1 file changed, 5 insertions(+), 115 deletions(-)
diff --git a/ell/dbus.c b/ell/dbus.c
index bc6aaed..af0000d 100644
--- a/ell/dbus.c
+++ b/ell/dbus.c
@@ -1822,57 +1822,6 @@ void _dbus1_filter_data_destroy(void *user_data)
l_free(data);
}
-static void dbus1_send_match(struct l_dbus *dbus, const char *rule,
- const char *method)
-{
- struct l_dbus_message *message;
-
- message = l_dbus_message_new_method_call(dbus,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- L_DBUS_INTERFACE_DBUS,
- method);
-
- l_dbus_message_set_arguments(message, "s", rule);
-
- send_message(dbus, false, message, NULL, NULL, NULL);
-}
-
-static void dbus1_bus_add_match(struct l_dbus *dbus, const char *rule)
-{
- dbus1_send_match(dbus, rule, "AddMatch");
-}
-
-static void dbus1_bus_remove_match(struct l_dbus *dbus, const char *rule)
-{
- dbus1_send_match(dbus, rule, "RemoveMatch");
-}
-
-static void add_match(struct dbus1_filter_data *data)
-{
- char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
-
- _dbus1_filter_format_match(data, rule, sizeof(rule));
-
- dbus1_bus_add_match(data->dbus, rule);
-}
-
-static void remove_match(struct dbus1_filter_data *data)
-{
- char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
-
- _dbus1_filter_format_match(data, rule, sizeof(rule));
-
- dbus1_bus_remove_match(data->dbus, rule);
-}
-
-static void filter_data_destroy(void *user_data)
-{
- remove_match(user_data);
-
- _dbus1_filter_data_destroy(user_data);
-}
-
void _dbus1_signal_dispatcher(struct l_dbus_message *message, void *user_data)
{
struct dbus1_filter_data *data = user_data;
@@ -1939,33 +1888,6 @@ void _dbus1_name_owner_changed_filter(struct l_dbus_message *message,
}
}
-static void _dbus1_get_name_owner_reply(struct l_dbus_message *message,
- void *user_data)
-{
- struct dbus1_filter_data *data = user_data;
- const char *name;
-
- data->get_name_owner_id = 0;
-
- /* No name owner yet */
- if (l_dbus_message_is_error(message))
- return;
-
- /* Shouldn't happen */
- if (!l_dbus_message_get_arguments(message, "s", &name))
- return;
-
- /* If the signal arrived before the reply, don't do anything */
- if (data->owner && !strcmp(data->owner, name))
- return;
-
- l_free(data->owner);
- data->owner = l_strdup(name);
-
- if (data->connect_func)
- data->connect_func(data->dbus, data->user_data);
-}
-
LIB_EXPORT unsigned int l_dbus_add_disconnect_watch(struct l_dbus *dbus,
const char *name,
l_dbus_watch_func_t disconnect_func,
@@ -1976,56 +1898,24 @@ LIB_EXPORT unsigned int l_dbus_add_disconnect_watch(struct l_dbus *dbus,
user_data, destroy);
}
-unsigned int l_dbus_add_service_watch(struct l_dbus *dbus,
+LIB_EXPORT unsigned int l_dbus_add_service_watch(struct l_dbus *dbus,
const char *name,
l_dbus_watch_func_t connect_func,
l_dbus_watch_func_t disconnect_func,
void *user_data,
l_dbus_destroy_func_t destroy)
{
- struct dbus1_filter_data *data;
-
if (!name)
return 0;
- data = _dbus1_filter_data_get(dbus, _dbus1_name_owner_changed_filter,
- DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
- L_DBUS_INTERFACE_DBUS, "NameOwnerChanged",
- name,
- disconnect_func,
- user_data,
- destroy);
- if (!data)
- return 0;
-
- add_match(data);
-
- if (connect_func) {
- struct l_dbus_message *message;
-
- data->connect_func = connect_func;
-
- message = l_dbus_message_new_method_call(dbus,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- L_DBUS_INTERFACE_DBUS,
- "GetNameOwner");
-
- l_dbus_message_set_arguments(message, "s", name);
-
- data->get_name_owner_id =
- l_dbus_send_with_reply(dbus, message,
- _dbus1_get_name_owner_reply,
- data, NULL);
- }
-
- return l_dbus_register(dbus, _dbus1_signal_dispatcher, data,
- filter_data_destroy);
+ return _dbus_name_cache_add_watch(dbus->name_cache, name, connect_func,
+ disconnect_func, user_data,
+ destroy);
}
LIB_EXPORT bool l_dbus_remove_watch(struct l_dbus *dbus, unsigned int id)
{
- return l_dbus_unregister(dbus, id);
+ return _dbus_name_cache_remove_watch(dbus->name_cache, id);
}
/**
--
2.5.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] dbus: Add private _dbus_message_new_error
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
` (8 preceding siblings ...)
2016-04-18 14:31 ` [PATCH 5/5] dbus: Use the name cache for public service watches Andrew Zaborowski
@ 2016-04-19 2:37 ` Denis Kenzior
2016-04-22 0:03 ` Andrzej Zaborowski
9 siblings, 1 reply; 15+ messages in thread
From: Denis Kenzior @ 2016-04-19 2:37 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 3497 bytes --]
Hi Andrew,
On 04/18/2016 09:31 AM, Andrew Zaborowski wrote:
> ---
> ell/dbus-message.c | 47 +++++++++++++++++++++++++++++++----------------
> ell/dbus-private.h | 5 +++++
> 2 files changed, 36 insertions(+), 16 deletions(-)
>
> diff --git a/ell/dbus-message.c b/ell/dbus-message.c
> index a409e53..86cec96 100644
> --- a/ell/dbus-message.c
> +++ b/ell/dbus-message.c
> @@ -328,33 +328,32 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_method_return(
> return message;
> }
>
> -LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
> - struct l_dbus_message *method_call,
> - const char *name,
> - const char *format, va_list args)
> +struct l_dbus_message *_dbus_message_new_error(uint8_t version,
> + uint32_t reply_serial,
> + const char *destination,
> + const char *name,
> + const char *error)
> {
> - char str[1024];
> struct l_dbus_message *reply;
> - struct dbus_header *hdr = method_call->header;
> - const char *sender;
> + bool r;
>
> if (!_dbus_valid_interface(name))
> return NULL;
>
> - vsnprintf(str, sizeof(str), format, args);
> reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
> DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
> - hdr->version);
> -
> - reply->reply_serial = _dbus_message_get_serial(method_call);
> -
> - sender = l_dbus_message_get_sender(method_call);
> - if (sender)
> - reply->destination = l_strdup(sender);
> + version);
>
> reply->error_name = l_strdup(name);
> + reply->destination = l_strdup(destination);
> + reply->reply_serial = reply_serial;
>
> - if (!l_dbus_message_set_arguments(reply, "s", str)) {
> + if (error)
> + r = l_dbus_message_set_arguments(reply, "s", error);
> + else
> + r = l_dbus_message_set_arguments(reply, "");
Under what circumstances would we want to create an error without at
least a single string argument?
> +
> + if (!r) {
> l_dbus_message_unref(reply);
> return NULL;
> }
> @@ -362,6 +361,22 @@ LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
> return reply;
> }
>
> +LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
> + struct l_dbus_message *method_call,
> + const char *name,
> + const char *format, va_list args)
> +{
> + char str[1024];
> + struct dbus_header *hdr = method_call->header;
> +
> + vsnprintf(str, sizeof(str), format, args);
> +
> + return _dbus_message_new_error(hdr->version,
> + _dbus_message_get_serial(method_call),
> + l_dbus_message_get_sender(method_call),
> + name, str);
> +}
> +
> LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error(
> struct l_dbus_message *method_call,
> const char *name,
> diff --git a/ell/dbus-private.h b/ell/dbus-private.h
> index 63c239b..030ce0b 100644
> --- a/ell/dbus-private.h
> +++ b/ell/dbus-private.h
> @@ -141,6 +141,11 @@ struct l_dbus_message *_dbus_message_new_signal(uint8_t version,
> const char *path,
> const char *interface,
> const char *name);
> +struct l_dbus_message *_dbus_message_new_error(uint8_t version,
> + uint32_t reply_serial,
> + const char *destination,
> + const char *name,
> + const char *error);
>
> struct l_dbus_message *dbus_message_from_blob(const void *data, size_t size);
> struct l_dbus_message *dbus_message_build(void *header, size_t header_size,
>
Regards,
-Denis
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dbus: Check message->sealed before get_header_field()
2016-04-18 14:31 ` [PATCH] dbus: Check message->sealed before get_header_field() Andrew Zaborowski
@ 2016-04-19 2:39 ` Denis Kenzior
0 siblings, 0 replies; 15+ messages in thread
From: Denis Kenzior @ 2016-04-19 2:39 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 337 bytes --]
Hi Andrew,
On 04/18/2016 09:31 AM, Andrew Zaborowski wrote:
> Also make sure _dbus_message_get_reply_serial on kdbus doesn't overwrite
> message->reply_serial with uninitialised value.
> ---
> ell/dbus-message.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] unit: Add test-dbus-properties --kdbus option
2016-04-18 14:31 ` [PATCH] unit: Add test-dbus-properties --kdbus option Andrew Zaborowski
@ 2016-04-19 2:41 ` Denis Kenzior
0 siblings, 0 replies; 15+ messages in thread
From: Denis Kenzior @ 2016-04-19 2:41 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 254 bytes --]
Hi Andrew,
On 04/18/2016 09:31 AM, Andrew Zaborowski wrote:
> ---
> unit/test-dbus-properties.c | 49 ++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 44 insertions(+), 5 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] dbus: Add a Bus Name cache
2016-04-18 14:31 ` [PATCH 1/5] dbus: Add a Bus Name cache Andrew Zaborowski
@ 2016-04-21 3:30 ` Denis Kenzior
0 siblings, 0 replies; 15+ messages in thread
From: Denis Kenzior @ 2016-04-21 3:30 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 429 bytes --]
Hi Andrew,
On 04/18/2016 09:31 AM, Andrew Zaborowski wrote:
> ---
> Makefile.am | 1 +
> ell/dbus-name-cache.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
> ell/dbus-private.h | 18 ++++++
> ell/dbus.c | 35 +++++++++---
> 4 files changed, 196 insertions(+), 7 deletions(-)
> create mode 100644 ell/dbus-name-cache.c
>
All 5 applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] dbus: Add private _dbus_message_new_error
2016-04-19 2:37 ` [PATCH 1/2] dbus: Add private _dbus_message_new_error Denis Kenzior
@ 2016-04-22 0:03 ` Andrzej Zaborowski
0 siblings, 0 replies; 15+ messages in thread
From: Andrzej Zaborowski @ 2016-04-22 0:03 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 2686 bytes --]
Hi Denis,
On 19 April 2016 at 04:37, Denis Kenzior <denkenz@gmail.com> wrote:
> On 04/18/2016 09:31 AM, Andrew Zaborowski wrote:
>>
>> ---
>> ell/dbus-message.c | 47 +++++++++++++++++++++++++++++++----------------
>> ell/dbus-private.h | 5 +++++
>> 2 files changed, 36 insertions(+), 16 deletions(-)
>>
>> diff --git a/ell/dbus-message.c b/ell/dbus-message.c
>> index a409e53..86cec96 100644
>> --- a/ell/dbus-message.c
>> +++ b/ell/dbus-message.c
>> @@ -328,33 +328,32 @@ LIB_EXPORT struct l_dbus_message
>> *l_dbus_message_new_method_return(
>> return message;
>> }
>>
>> -LIB_EXPORT struct l_dbus_message *l_dbus_message_new_error_valist(
>> - struct l_dbus_message
>> *method_call,
>> - const char *name,
>> - const char *format, va_list args)
>> +struct l_dbus_message *_dbus_message_new_error(uint8_t version,
>> + uint32_t reply_serial,
>> + const char *destination,
>> + const char *name,
>> + const char *error)
>> {
>> - char str[1024];
>> struct l_dbus_message *reply;
>> - struct dbus_header *hdr = method_call->header;
>> - const char *sender;
>> + bool r;
>>
>> if (!_dbus_valid_interface(name))
>> return NULL;
>>
>> - vsnprintf(str, sizeof(str), format, args);
>> reply = message_new_common(DBUS_MESSAGE_TYPE_ERROR,
>>
>> DBUS_MESSAGE_FLAG_NO_REPLY_EXPECTED,
>> - hdr->version);
>> -
>> - reply->reply_serial = _dbus_message_get_serial(method_call);
>> -
>> - sender = l_dbus_message_get_sender(method_call);
>> - if (sender)
>> - reply->destination = l_strdup(sender);
>> + version);
>>
>> reply->error_name = l_strdup(name);
>> + reply->destination = l_strdup(destination);
>> + reply->reply_serial = reply_serial;
>>
>> - if (!l_dbus_message_set_arguments(reply, "s", str)) {
>> + if (error)
>> + r = l_dbus_message_set_arguments(reply, "s", error);
>> + else
>> + r = l_dbus_message_set_arguments(reply, "");
>
>
> Under what circumstances would we want to create an error without at least a
> single string argument?
I don't know but didn't want to exclude that possibility since it's
legal. Let me remove the check.
Best regards
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2016-04-22 0:03 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-18 14:31 [PATCH 1/2] dbus: Add private _dbus_message_new_error Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 2/2] dbus: Handle kdbus KDBUS_ITEM_REPLY_TIMEOUT / _DEAD Andrew Zaborowski
2016-04-18 14:31 ` [PATCH] dbus: Check message->sealed before get_header_field() Andrew Zaborowski
2016-04-19 2:39 ` Denis Kenzior
2016-04-18 14:31 ` [PATCH] dbus: Don't send replies to messages with no reply flag Andrew Zaborowski
2016-04-18 14:31 ` [PATCH] unit: Add test-dbus-properties --kdbus option Andrew Zaborowski
2016-04-19 2:41 ` Denis Kenzior
2016-04-18 14:31 ` [PATCH 1/5] dbus: Add a Bus Name cache Andrew Zaborowski
2016-04-21 3:30 ` Denis Kenzior
2016-04-18 14:31 ` [PATCH 2/5] dbus: Use the name cache API in _dbus_filter Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 3/5] unit: Update _dbus_filter usage in test-dbus-watch Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 4/5] dbus: Add service watch API based on the name cache Andrew Zaborowski
2016-04-18 14:31 ` [PATCH 5/5] dbus: Use the name cache for public service watches Andrew Zaborowski
2016-04-19 2:37 ` [PATCH 1/2] dbus: Add private _dbus_message_new_error Denis Kenzior
2016-04-22 0:03 ` Andrzej Zaborowski
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.