From 8ec0dab7fa8e4139ba51d61302e0f21b814df20a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 13 Dec 2012 14:06:25 +0100 Subject: gdbus: Add support for D-Bus client properties --- gdbus/client.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- gdbus/gdbus.h | 3 ++ 2 files changed, 126 insertions(+), 3 deletions(-) (limited to 'gdbus') diff --git a/gdbus/client.c b/gdbus/client.c index 5d19b19c..d0cbfa16 100644 --- a/gdbus/client.c +++ b/gdbus/client.c @@ -55,8 +55,61 @@ struct GDBusProxy { GDBusClient *client; char *obj_path; char *interface; + GHashTable *prop_list; }; +struct prop_entry { + char *name; + int type; + DBusMessage *msg; +}; + +static struct prop_entry *prop_entry_new(const char *name, + DBusMessageIter *iter) +{ + struct prop_entry *prop; + + prop = g_try_new0(struct prop_entry, 1); + if (prop == NULL) + return NULL; + + prop->name = g_strdup(name); + prop->type = dbus_message_iter_get_arg_type(iter); + + if (dbus_type_is_basic(prop->type)) { + DBusMessage *msg; + DBusMessageIter append_iter; + const void *value; + + msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); + if (msg == NULL) + return prop; + + dbus_message_iter_init_append(msg, &append_iter); + dbus_message_iter_get_basic(iter, &value); + dbus_message_iter_append_basic(&append_iter, + prop->type, &value); + + prop->msg = dbus_message_copy(msg); + + dbus_message_unref(msg); + } + + return prop; +} + +static void prop_entry_free(gpointer data) +{ + struct prop_entry *prop = data; + + if (prop->msg != NULL) + dbus_message_unref(prop->msg); + + g_free(prop->name); + + g_free(prop); +} + static GDBusProxy *proxy_new(GDBusClient *client, const char *path, const char *interface) { @@ -70,6 +123,9 @@ static GDBusProxy *proxy_new(GDBusClient *client, const char *path, proxy->obj_path = g_strdup(path); proxy->interface = g_strdup(interface); + proxy->prop_list = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, prop_entry_free); + return g_dbus_proxy_ref(proxy); } @@ -126,6 +182,8 @@ void g_dbus_proxy_unref(GDBusProxy *proxy) if (g_atomic_int_dec_and_test(&proxy->ref_count) == FALSE) return; + g_hash_table_destroy(proxy->prop_list); + g_free(proxy->obj_path); g_free(proxy->interface); @@ -148,9 +206,49 @@ const char *g_dbus_proxy_get_interface(GDBusProxy *proxy) return proxy->interface; } +gboolean g_dbus_proxy_get_property(GDBusProxy *proxy, const char *name, + DBusMessageIter *iter) +{ + struct prop_entry *prop; + + if (proxy == NULL || name == NULL) + return FALSE; + + prop = g_hash_table_lookup(proxy->prop_list, name); + if (prop == NULL) + return FALSE; + + if (prop->msg == NULL) + return FALSE; + + if (dbus_message_iter_init(prop->msg, iter) == FALSE) + return FALSE; + + return TRUE; +} + +static void add_property(GDBusProxy *proxy, const char *name, + DBusMessageIter *iter) +{ + DBusMessageIter value; + struct prop_entry *prop; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) + return; + + dbus_message_iter_recurse(iter, &value); + + prop = prop_entry_new(name, &value); + if (prop == NULL) + return; + + g_hash_table_replace(proxy->prop_list, prop->name, prop); +} + static void parse_properties(GDBusClient *client, const char *path, const char *interface, DBusMessageIter *iter) { + DBusMessageIter dict; GDBusProxy *proxy; if (g_str_equal(interface, DBUS_INTERFACE_INTROSPECTABLE) == TRUE) @@ -161,6 +259,29 @@ static void parse_properties(GDBusClient *client, const char *path, proxy = proxy_new(client, path, interface); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + goto done; + + dbus_message_iter_recurse(iter, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry; + const char *name; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + break; + + dbus_message_iter_get_basic(&entry, &name); + dbus_message_iter_next(&entry); + + add_property(proxy, name, &entry); + + dbus_message_iter_next(&dict); + } + +done: if (client->proxy_added) client->proxy_added(proxy, client->proxy_data); @@ -178,7 +299,7 @@ static void parse_interfaces(GDBusClient *client, const char *path, dbus_message_iter_recurse(iter, &dict); while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry, value; + DBusMessageIter entry; const char *interface; dbus_message_iter_recurse(&dict, &entry); @@ -189,8 +310,7 @@ static void parse_interfaces(GDBusClient *client, const char *path, dbus_message_iter_get_basic(&entry, &interface); dbus_message_iter_next(&entry); - dbus_message_iter_recurse(&entry, &value); - parse_properties(client, path, interface, &value); + parse_properties(client, path, interface, &entry); dbus_message_iter_next(&dict); } diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h index 3eed52b8..a0ca173a 100644 --- a/gdbus/gdbus.h +++ b/gdbus/gdbus.h @@ -276,6 +276,9 @@ void g_dbus_proxy_unref(GDBusProxy *proxy); const char *g_dbus_proxy_get_path(GDBusProxy *proxy); const char *g_dbus_proxy_get_interface(GDBusProxy *proxy); +gboolean g_dbus_proxy_get_property(GDBusProxy *proxy, const char *name, + DBusMessageIter *iter); + typedef struct GDBusClient GDBusClient; GDBusClient *g_dbus_client_new(DBusConnection *connection, -- cgit v1.2.3