From 8bef871cffd92cde21f9c727329740ee1e3b6d3d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 27 Dec 2012 21:19:31 -0800 Subject: [PATCH] gdbus: Add support for creating D-Bus proxies without object manager --- gdbus/client.c | 203 ++++++++++++++++++++++++++++++++++++++++----------------- gdbus/gdbus.h | 6 +- 2 files changed, 147 insertions(+), 62 deletions(-) diff --git a/gdbus/client.c b/gdbus/client.c index 3b00080..8b55e5b 100644 --- a/gdbus/client.c +++ b/gdbus/client.c @@ -198,6 +198,128 @@ static void prop_entry_free(gpointer data) g_free(prop); } +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 = g_hash_table_lookup(proxy->prop_list, name); + if (prop != NULL) { + GDBusClient *client = proxy->client; + + prop_entry_update(prop, &value); + + if (client == NULL) + return; + + if (client->property_changed) + client->property_changed(proxy, name, &value, + client->user_data); + return; + } + + prop = prop_entry_new(name, &value); + if (prop == NULL) + return; + + g_hash_table_replace(proxy->prop_list, prop->name, prop); +} + +static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter) +{ + DBusMessageIter dict; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + 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); + } +} + +static void get_all_properties_reply(DBusPendingCall *call, void *user_data) +{ + GDBusProxy *proxy = user_data; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + DBusMessageIter iter; + DBusError error; + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, reply) == TRUE) { + dbus_error_free(&error); + goto done; + } + + dbus_message_iter_init(reply, &iter); + + update_properties(proxy, &iter); + +done: + if (proxy->client != NULL) { + GDBusClient *client = proxy->client; + + if (client->proxy_added) + client->proxy_added(proxy, client->user_data); + + client->proxy_list = g_list_append(client->proxy_list, proxy); + } else + g_dbus_proxy_unref(proxy); + + dbus_message_unref(reply); +} + +static void get_all_properties(GDBusProxy *proxy) +{ + GDBusClient *client = proxy->client; + const char *service_name = client->service_name; + DBusMessage *msg; + DBusPendingCall *call; + + msg = dbus_message_new_method_call(service_name, proxy->obj_path, + DBUS_INTERFACE_PROPERTIES, "GetAll"); + if (msg == NULL) + return; + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &proxy->interface, + DBUS_TYPE_INVALID); + + if (dbus_connection_send_with_reply(client->dbus_conn, msg, + &call, -1) == FALSE) { + dbus_message_unref(msg); + return; + } + + g_dbus_proxy_ref(proxy); + + dbus_pending_call_set_notify(call, get_all_properties_reply, + proxy, NULL); + dbus_pending_call_unref(call); + + dbus_message_unref(msg); +} + static GDBusProxy *proxy_lookup(GDBusClient *client, const char *path, const char *interface) { @@ -285,6 +407,27 @@ static void proxy_remove(GDBusClient *client, const char *path, } } +GDBusProxy *g_dbus_proxy_new(GDBusClient *client, const char *path, + const char *interface) +{ + GDBusProxy *proxy; + + if (client == NULL) + return NULL; + + proxy = proxy_lookup(client, path, interface); + if (proxy) + return g_dbus_proxy_ref(proxy); + + proxy = proxy_new(client, path, interface); + if (proxy == NULL) + return NULL; + + get_all_properties(proxy); + + return proxy; +} + GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy) { if (proxy == NULL) @@ -514,66 +657,6 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method, 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 = g_hash_table_lookup(proxy->prop_list, name); - if (prop != NULL) { - GDBusClient *client = proxy->client; - - prop_entry_update(prop, &value); - - if (client == NULL) - return; - - if (client->property_changed) - client->property_changed(proxy, name, &value, - client->user_data); - return; - } - - prop = prop_entry_new(name, &value); - if (prop == NULL) - return; - - g_hash_table_replace(proxy->prop_list, prop->name, prop); -} - -static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter) -{ - DBusMessageIter dict; - - if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) - return; - - 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); - } -} - static void properties_changed(GDBusClient *client, const char *path, DBusMessage *msg) { diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h index 0e5c012..4caa31d 100644 --- a/gdbus/gdbus.h +++ b/gdbus/gdbus.h @@ -274,8 +274,12 @@ gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, gboolean g_dbus_attach_object_manager(DBusConnection *connection); gboolean g_dbus_detach_object_manager(DBusConnection *connection); +typedef struct GDBusClient GDBusClient; typedef struct GDBusProxy GDBusProxy; +GDBusProxy *g_dbus_proxy_new(GDBusClient *client, const char *path, + const char *interface); + GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy); void g_dbus_proxy_unref(GDBusProxy *proxy); @@ -300,8 +304,6 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method, GDBusReturnFunction function, void *user_data, GDBusDestroyFunction destroy); -typedef struct GDBusClient GDBusClient; - GDBusClient *g_dbus_client_new(DBusConnection *connection, const char *service, const char *path); -- 2.7.4