diff options
Diffstat (limited to 'glib/dbus-gproxy.c')
-rw-r--r-- | glib/dbus-gproxy.c | 2748 |
1 files changed, 0 insertions, 2748 deletions
diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c deleted file mode 100644 index e4243114..00000000 --- a/glib/dbus-gproxy.c +++ /dev/null @@ -1,2748 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-gproxy.c Proxy for remote objects - * - * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. - * Copyright (C) 2005 Nokia - * - * Licensed under the Academic Free License version 2.1 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> -#include <dbus/dbus-signature.h> -#include "dbus-gutils.h" -#include "dbus-gsignature.h" -#include "dbus-gvalue.h" -#include "dbus-gvalue-utils.h" -#include "dbus-gobject.h" -#include <string.h> -#include <glib/gi18n.h> -#include <gobject/gvaluecollector.h> - -#define DBUS_G_PROXY_CALL_TO_ID(x) (GPOINTER_TO_UINT(x)) -#define DBUS_G_PROXY_ID_TO_CALL(x) (GUINT_TO_POINTER(x)) -#define DBUS_G_PROXY_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TYPE_G_PROXY, DBusGProxyPrivate)) - - -/** - * @addtogroup DBusGLibInternals - * - * @{ - */ - -/** - * DBusGProxyManager typedef - */ - -typedef struct _DBusGProxyManager DBusGProxyManager; - -typedef struct _DBusGProxyPrivate DBusGProxyPrivate; - -/** - * Internals of DBusGProxy - */ -struct _DBusGProxyPrivate -{ - DBusGProxyManager *manager; /**< Proxy manager */ - char *name; /**< Name messages go to or NULL */ - char *path; /**< Path messages go to or NULL */ - char *interface; /**< Interface messages go to or NULL */ - - DBusGProxyCall *name_call; /**< Pending call id to retrieve name owner */ - guint for_owner : 1; /**< Whether or not this proxy is for a name owner */ - guint associated : 1; /**< Whether or not this proxy is associated (for name proxies) */ - - /* FIXME: make threadsafe? */ - guint call_id_counter; /**< Integer counter for pending calls */ - - GData *signal_signatures; /**< D-BUS signatures for each signal */ - - GHashTable *pending_calls; /**< Calls made on this proxy which have not yet returned */ -}; - -static void dbus_g_proxy_init (DBusGProxy *proxy); -static void dbus_g_proxy_class_init (DBusGProxyClass *klass); -static GObject *dbus_g_proxy_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties); -static void dbus_g_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void dbus_g_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void dbus_g_proxy_finalize (GObject *object); -static void dbus_g_proxy_dispose (GObject *object); -static void dbus_g_proxy_destroy (DBusGProxy *proxy); -static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, - DBusMessage *message); - -static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager *manager, - const char *method, - DBusGProxyCallNotify notify, - gpointer data, - GDestroyNotify destroy, - GType first_arg_type, - ...); -static guint dbus_g_proxy_begin_call_internal (DBusGProxy *proxy, - const char *method, - DBusGProxyCallNotify notify, - gpointer data, - GDestroyNotify destroy, - GValueArray *args); -static gboolean dbus_g_proxy_end_call_internal (DBusGProxy *proxy, - guint call_id, - GError **error, - GType first_arg_type, - va_list args); - -/** - * A list of proxies with a given name+path+interface, used to - * route incoming signals. - */ -typedef struct -{ - GSList *proxies; /**< The list of proxies */ - - char name[4]; /**< name (empty string for none), nul byte, - * path, nul byte, - * interface, nul byte - */ - -} DBusGProxyList; - -/** - * DBusGProxyManager's primary task is to route signals to the proxies - * those signals are emitted on. In order to do this it also has to - * track the owners of the names proxies are bound to. - */ -struct _DBusGProxyManager -{ - GStaticMutex lock; /**< Thread lock */ - int refcount; /**< Reference count */ - DBusConnection *connection; /**< Connection we're associated with. */ - - DBusGProxy *bus_proxy; /**< Special internal proxy used to talk to the bus */ - - GHashTable *proxy_lists; /**< Hash used to route incoming signals - * and iterate over proxies - */ - GHashTable *owner_names; /**< Hash to keep track of mapping from - * base name -> [name,name,...] for proxies which - * are for names. - */ - GSList *unassociated_proxies; /**< List of name proxies for which - * there was no result for - * GetNameOwner - */ -}; - -static DBusGProxyManager *dbus_g_proxy_manager_ref (DBusGProxyManager *manager); -static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data); - - -/** Lock the DBusGProxyManager */ -#define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock)) -/** Unlock the DBusGProxyManager */ -#define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock)) - -static int g_proxy_manager_slot = -1; - -/* Lock controlling get/set manager as data on each connection */ -static GStaticMutex connection_g_proxy_lock = G_STATIC_MUTEX_INIT; - -static DBusGProxyManager* -dbus_g_proxy_manager_get (DBusConnection *connection) -{ - DBusGProxyManager *manager; - - dbus_connection_allocate_data_slot (&g_proxy_manager_slot); - if (g_proxy_manager_slot < 0) - g_error ("out of memory"); - - g_static_mutex_lock (&connection_g_proxy_lock); - - manager = dbus_connection_get_data (connection, g_proxy_manager_slot); - if (manager != NULL) - { - dbus_connection_free_data_slot (&g_proxy_manager_slot); - dbus_g_proxy_manager_ref (manager); - g_static_mutex_unlock (&connection_g_proxy_lock); - return manager; - } - - manager = g_new0 (DBusGProxyManager, 1); - - manager->refcount = 1; - manager->connection = connection; - - g_static_mutex_init (&manager->lock); - - /* Proxy managers keep the connection alive, which means that - * DBusGProxy indirectly does. To free a connection you have to free - * all the proxies referring to it. - */ - dbus_connection_ref (manager->connection); - - dbus_connection_set_data (connection, g_proxy_manager_slot, - manager, NULL); - - dbus_connection_add_filter (connection, dbus_g_proxy_manager_filter, - manager, NULL); - - g_static_mutex_unlock (&connection_g_proxy_lock); - - return manager; -} - -static DBusGProxyManager * -dbus_g_proxy_manager_ref (DBusGProxyManager *manager) -{ - g_assert (manager != NULL); - g_assert (manager->refcount > 0); - - LOCK_MANAGER (manager); - - manager->refcount += 1; - - UNLOCK_MANAGER (manager); - - return manager; -} - -static void -dbus_g_proxy_manager_unref (DBusGProxyManager *manager) -{ - g_assert (manager != NULL); - g_assert (manager->refcount > 0); - - LOCK_MANAGER (manager); - manager->refcount -= 1; - if (manager->refcount == 0) - { - UNLOCK_MANAGER (manager); - - if (manager->bus_proxy) - g_object_unref (manager->bus_proxy); - - if (manager->proxy_lists) - { - /* can't have any proxies left since they hold - * a reference to the proxy manager. - */ - g_assert (g_hash_table_size (manager->proxy_lists) == 0); - - g_hash_table_destroy (manager->proxy_lists); - manager->proxy_lists = NULL; - - } - - if (manager->owner_names) - { - /* Since we destroyed all proxies, none can be tracking - * name owners - */ - g_assert (g_hash_table_size (manager->owner_names) == 0); - - g_hash_table_destroy (manager->owner_names); - manager->owner_names = NULL; - } - - g_assert (manager->unassociated_proxies == NULL); - - g_static_mutex_free (&manager->lock); - - g_static_mutex_lock (&connection_g_proxy_lock); - - dbus_connection_remove_filter (manager->connection, dbus_g_proxy_manager_filter, - manager); - - dbus_connection_set_data (manager->connection, - g_proxy_manager_slot, - NULL, NULL); - - g_static_mutex_unlock (&connection_g_proxy_lock); - - dbus_connection_unref (manager->connection); - g_free (manager); - - dbus_connection_free_data_slot (&g_proxy_manager_slot); - } - else - { - UNLOCK_MANAGER (manager); - } -} - -static guint -tristring_hash (gconstpointer key) -{ - const char *p = key; - guint h = *p; - - if (h) - { - for (p += 1; *p != '\0'; p++) - h = (h << 5) - h + *p; - } - - /* skip nul and do the next substring */ - for (p += 1; *p != '\0'; p++) - h = (h << 5) - h + *p; - - /* skip nul again and another substring */ - for (p += 1; *p != '\0'; p++) - h = (h << 5) - h + *p; - - return h; -} - -static gboolean -strequal_len (const char *a, - const char *b, - size_t *lenp) -{ - size_t a_len; - size_t b_len; - - a_len = strlen (a); - b_len = strlen (b); - - if (a_len != b_len) - return FALSE; - - if (memcmp (a, b, a_len) != 0) - return FALSE; - - *lenp = a_len; - - return TRUE; -} - -static gboolean -tristring_equal (gconstpointer a, - gconstpointer b) -{ - const char *ap = a; - const char *bp = b; - size_t len; - - if (!strequal_len (ap, bp, &len)) - return FALSE; - - ap += len + 1; - bp += len + 1; - - if (!strequal_len (ap, bp, &len)) - return FALSE; - - ap += len + 1; - bp += len + 1; - - if (strcmp (ap, bp) != 0) - return FALSE; - - return TRUE; -} - -static char* -tristring_alloc_from_strings (size_t padding_before, - const char *name, - const char *path, - const char *interface) -{ - size_t name_len, iface_len, path_len, len; - char *tri; - - if (name) - name_len = strlen (name); - else - name_len = 0; - - path_len = strlen (path); - - iface_len = strlen (interface); - - tri = g_malloc (padding_before + name_len + path_len + iface_len + 3); - - len = padding_before; - - if (name) - memcpy (&tri[len], name, name_len); - - len += name_len; - tri[len] = '\0'; - len += 1; - - g_assert (len == (padding_before + name_len + 1)); - - memcpy (&tri[len], path, path_len); - len += path_len; - tri[len] = '\0'; - len += 1; - - g_assert (len == (padding_before + name_len + path_len + 2)); - - memcpy (&tri[len], interface, iface_len); - len += iface_len; - tri[len] = '\0'; - len += 1; - - g_assert (len == (padding_before + name_len + path_len + iface_len + 3)); - - return tri; -} - -static char* -tristring_from_proxy (DBusGProxy *proxy) -{ - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - return tristring_alloc_from_strings (0, - priv->name, - priv->path, - priv->interface); -} - -static char* -tristring_from_message (DBusMessage *message) -{ - const char *path; - const char *interface; - - path = dbus_message_get_path (message); - interface = dbus_message_get_interface (message); - - g_assert (path); - g_assert (interface); - - return tristring_alloc_from_strings (0, - dbus_message_get_sender (message), - path, interface); -} - -static DBusGProxyList* -g_proxy_list_new (DBusGProxy *first_proxy) -{ - DBusGProxyList *list; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(first_proxy); - - list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name), - priv->name, - priv->path, - priv->interface); - list->proxies = NULL; - - return list; -} - -static void -g_proxy_list_free (DBusGProxyList *list) -{ - /* we don't hold a reference to the proxies in the list, - * as they ref the GProxyManager - */ - g_slist_free (list->proxies); - - g_free (list); -} - -static char* -g_proxy_get_match_rule (DBusGProxy *proxy) -{ - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - /* FIXME Escaping is required here */ - - if (priv->name) - return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'", - priv->name, priv->path, priv->interface); - else - return g_strdup_printf ("type='signal',path='%s',interface='%s'", - priv->path, priv->interface); -} - -typedef struct -{ - char *name; - guint refcount; -} DBusGProxyNameOwnerInfo; - -static gint -find_name_in_info (gconstpointer a, gconstpointer b) -{ - const DBusGProxyNameOwnerInfo *info = a; - const char *name = b; - - return strcmp (info->name, name); -} - -typedef struct -{ - const char *name; - const char *owner; - DBusGProxyNameOwnerInfo *info; -} DBusGProxyNameOwnerForeachData; - -static void -name_owner_foreach (gpointer key, gpointer val, gpointer data) -{ - const char *owner; - DBusGProxyNameOwnerForeachData *foreach_data; - GSList *names; - GSList *link; - - owner = key; - names = val; - foreach_data = data; - - if (foreach_data->owner != NULL) - return; - - g_assert (foreach_data->info == NULL); - - link = g_slist_find_custom (names, foreach_data->name, find_name_in_info); - if (link) - { - foreach_data->owner = owner; - foreach_data->info = link->data; - } -} - -static gboolean -dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager *manager, - const char *name, - DBusGProxyNameOwnerInfo **info, - const char **owner) -{ - DBusGProxyNameOwnerForeachData foreach_data; - - foreach_data.name = name; - foreach_data.owner = NULL; - foreach_data.info = NULL; - - g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data); - - *info = foreach_data.info; - *owner = foreach_data.owner; - return *info != NULL; -} - -static void -insert_nameinfo (DBusGProxyManager *manager, - const char *owner, - DBusGProxyNameOwnerInfo *info) -{ - GSList *names; - gboolean insert; - - names = g_hash_table_lookup (manager->owner_names, owner); - - /* Only need to g_hash_table_insert the first time */ - insert = (names == NULL); - - names = g_slist_append (names, info); - - if (insert) - g_hash_table_insert (manager->owner_names, g_strdup (owner), names); -} - -static void -dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager *manager, - const char *owner, - const char *name) -{ - GSList *names; - GSList *link; - DBusGProxyNameOwnerInfo *nameinfo; - - names = g_hash_table_lookup (manager->owner_names, owner); - link = g_slist_find_custom (names, name, find_name_in_info); - - if (!link) - { - nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1); - nameinfo->name = g_strdup (name); - nameinfo->refcount = 1; - - insert_nameinfo (manager, owner, nameinfo); - } - else - { - nameinfo = link->data; - nameinfo->refcount++; - } -} - -static void -dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager *manager, - const char *name) -{ - DBusGProxyNameOwnerInfo *info; - const char *owner; - gboolean ret; - - ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner); - g_assert (ret); - g_assert (info != NULL); - g_assert (owner != NULL); - - info->refcount--; - if (info->refcount == 0) - { - GSList *names; - GSList *link; - - names = g_hash_table_lookup (manager->owner_names, owner); - link = g_slist_find_custom (names, name, find_name_in_info); - names = g_slist_delete_link (names, link); - if (names != NULL) - g_hash_table_insert (manager->owner_names, g_strdup (owner), names); - else - g_hash_table_remove (manager->owner_names, owner); - - g_free (info->name); - g_free (info); - } -} - -typedef struct -{ - const char *name; - GSList *destroyed; -} DBusGProxyUnassociateData; - -static void -unassociate_proxies (gpointer key, gpointer val, gpointer user_data) -{ - DBusGProxyList *list; - const char *name; - GSList *tmp; - DBusGProxyUnassociateData *data; - - list = val; - data = user_data; - name = data->name; - - for (tmp = list->proxies; tmp; tmp = tmp->next) - { - DBusGProxy *proxy = DBUS_G_PROXY (tmp->data); - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - DBusGProxyManager *manager; - - manager = priv->manager; - - if (!strcmp (priv->name, name)) - { - if (!priv->for_owner) - { - g_assert (priv->associated); - g_assert (priv->name_call == NULL); - - priv->associated = FALSE; - manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy); - } - else - { - data->destroyed = g_slist_prepend (data->destroyed, proxy); - } - } - } -} - -static void -dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager *manager, - const char *name, - const char *prev_owner, - const char *new_owner) -{ - GSList *names; - - if (prev_owner[0] == '\0') - { - GSList *tmp; - GSList *removed; - - /* We have a new service, look at unassociated proxies */ - - removed = NULL; - - for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next) - { - DBusGProxy *proxy = tmp->data; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - if (!strcmp (priv->name, name)) - { - removed = g_slist_prepend (removed, tmp); - - dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name); - priv->associated = TRUE; - } - } - - for (tmp = removed; tmp; tmp = tmp->next) - manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data); - g_slist_free (removed); - } - else - { - DBusGProxyNameOwnerInfo *info; - GSList *link; - - /* Name owner changed or deleted */ - - names = g_hash_table_lookup (manager->owner_names, prev_owner); - - link = g_slist_find_custom (names, name, find_name_in_info); - - info = NULL; - if (link != NULL) - { - info = link->data; - - names = g_slist_delete_link (names, link); - - if (names == NULL) - g_hash_table_remove (manager->owner_names, prev_owner); - } - - if (new_owner[0] == '\0') - { - DBusGProxyUnassociateData data; - GSList *tmp; - - data.name = name; - data.destroyed = NULL; - - /* A service went away, we need to unassociate proxies */ - g_hash_table_foreach (manager->proxy_lists, - unassociate_proxies, &data); - - UNLOCK_MANAGER (manager); - - for (tmp = data.destroyed; tmp; tmp = tmp->next) - dbus_g_proxy_destroy (tmp->data); - g_slist_free (data.destroyed); - - LOCK_MANAGER (manager); - } - else - { - insert_nameinfo (manager, new_owner, info); - } - } -} - -static void -got_name_owner_cb (DBusGProxy *bus_proxy, - DBusGProxyCall *call, - void *user_data) -{ - DBusGProxy *proxy = user_data; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - GError *error; - char *owner; - - error = NULL; - owner = NULL; - - LOCK_MANAGER (priv->manager); - - if (!dbus_g_proxy_end_call (bus_proxy, call, &error, - G_TYPE_STRING, &owner, - G_TYPE_INVALID)) - { - if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER) - { - priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy); - } - else - g_warning ("Couldn't get name owner (%s): %s", - dbus_g_error_get_name (error), - error->message); - - g_clear_error (&error); - goto out; - } - else - { - dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name); - priv->associated = TRUE; - } - - out: - priv->name_call = NULL; - UNLOCK_MANAGER (priv->manager); - g_free (owner); -} - -static char * -get_name_owner (DBusConnection *connection, - const char *name, - GError **error) -{ - DBusError derror; - DBusMessage *request, *reply; - char *base_name; - - dbus_error_init (&derror); - - base_name = NULL; - reply = NULL; - - request = dbus_message_new_method_call (DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "GetNameOwner"); - if (request == NULL) - g_error ("Out of memory"); - - if (!dbus_message_append_args (request, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) - g_error ("Out of memory"); - - reply = - dbus_connection_send_with_reply_and_block (connection, - request, - 2000, &derror); - if (reply == NULL) - goto error; - - if (dbus_set_error_from_message (&derror, reply)) - goto error; - - if (!dbus_message_get_args (reply, &derror, - DBUS_TYPE_STRING, &base_name, - DBUS_TYPE_INVALID)) - goto error; - - base_name = g_strdup (base_name); - goto out; - - error: - g_assert (dbus_error_is_set (&derror)); - dbus_set_g_error (error, &derror); - dbus_error_free (&derror); - - out: - if (request) - dbus_message_unref (request); - if (reply) - dbus_message_unref (reply); - - return base_name; -} - - -static void -dbus_g_proxy_manager_register (DBusGProxyManager *manager, - DBusGProxy *proxy) -{ - DBusGProxyList *list; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - LOCK_MANAGER (manager); - - if (manager->proxy_lists == NULL) - { - g_assert (manager->owner_names == NULL); - - list = NULL; - manager->proxy_lists = g_hash_table_new_full (tristring_hash, - tristring_equal, - NULL, - (GFreeFunc) g_proxy_list_free); - manager->owner_names = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - /* FIXME - for now we listen for all NameOwnerChanged; once - * Anders' detail patch lands we should add individual rules - */ - dbus_bus_add_match (manager->connection, - "type='signal',sender='" DBUS_SERVICE_DBUS - "',path='" DBUS_PATH_DBUS - "',interface='" DBUS_INTERFACE_DBUS - "',member='NameOwnerChanged'", - NULL); - } - else - { - char *tri; - - tri = tristring_from_proxy (proxy); - - list = g_hash_table_lookup (manager->proxy_lists, tri); - - g_free (tri); - } - - if (list == NULL) - { - list = g_proxy_list_new (proxy); - - g_hash_table_replace (manager->proxy_lists, - list->name, list); - } - - if (list->proxies == NULL) - { - /* We have to add the match rule to the server, - * but FIXME only if the server is a message bus, - * not if it's a peer. - */ - char *rule; - - rule = g_proxy_get_match_rule (proxy); - - /* We don't check for errors; it's not like anyone would handle them, - * and we don't want a round trip here. - */ - dbus_bus_add_match (manager->connection, - rule, NULL); - - g_free (rule); - } - - g_assert (g_slist_find (list->proxies, proxy) == NULL); - - list->proxies = g_slist_prepend (list->proxies, proxy); - - if (!priv->for_owner) - { - const char *owner; - DBusGProxyNameOwnerInfo *info; - - if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner)) - { - priv->name_call = manager_begin_bus_call (manager, "GetNameOwner", - got_name_owner_cb, - proxy, NULL, - G_TYPE_STRING, - priv->name, - G_TYPE_INVALID); - - priv->associated = FALSE; - } - else - { - info->refcount++; - priv->associated = TRUE; - } - } - - UNLOCK_MANAGER (manager); -} - -static void -dbus_g_proxy_manager_unregister (DBusGProxyManager *manager, - DBusGProxy *proxy) -{ - DBusGProxyList *list; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - char *tri; - - LOCK_MANAGER (manager); - -#ifndef G_DISABLE_CHECKS - if (manager->proxy_lists == NULL) - { - g_warning ("Trying to unregister a proxy but there aren't any registered"); - return; - } -#endif - - tri = tristring_from_proxy (proxy); - - list = g_hash_table_lookup (manager->proxy_lists, tri); - -#ifndef G_DISABLE_CHECKS - if (list == NULL) - { - g_warning ("Trying to unregister a proxy but it isn't registered"); - return; - } -#endif - - g_assert (g_slist_find (list->proxies, proxy) != NULL); - - list->proxies = g_slist_remove (list->proxies, proxy); - - g_assert (g_slist_find (list->proxies, proxy) == NULL); - - if (!priv->for_owner) - { - if (!priv->associated) - { - GSList *link; - - if (priv->name_call != 0) - { - dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call); - priv->name_call = 0; - } - else - { - link = g_slist_find (manager->unassociated_proxies, proxy); - g_assert (link != NULL); - - manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link); - } - } - else - { - g_assert (priv->name_call == 0); - - dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name); - } - } - - if (list->proxies == NULL) - { - char *rule; - g_hash_table_remove (manager->proxy_lists, - tri); - list = NULL; - - rule = g_proxy_get_match_rule (proxy); - dbus_bus_remove_match (manager->connection, - rule, NULL); - g_free (rule); - } - - if (g_hash_table_size (manager->proxy_lists) == 0) - { - g_hash_table_destroy (manager->proxy_lists); - manager->proxy_lists = NULL; - } - - g_free (tri); - - UNLOCK_MANAGER (manager); -} - -static void -list_proxies_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - DBusGProxyList *list; - GSList **ret; - GSList *tmp; - - list = value; - ret = user_data; - - tmp = list->proxies; - while (tmp != NULL) - { - DBusGProxy *proxy = DBUS_G_PROXY (tmp->data); - - g_object_ref (proxy); - *ret = g_slist_prepend (*ret, proxy); - - tmp = tmp->next; - } -} - -static GSList* -dbus_g_proxy_manager_list_all (DBusGProxyManager *manager) -{ - GSList *ret; - - ret = NULL; - - if (manager->proxy_lists) - { - g_hash_table_foreach (manager->proxy_lists, - list_proxies_foreach, - &ret); - } - - return ret; -} - -static DBusHandlerResult -dbus_g_proxy_manager_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - DBusGProxyManager *manager; - - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - manager = user_data; - - dbus_g_proxy_manager_ref (manager); - - LOCK_MANAGER (manager); - - if (dbus_message_is_signal (message, - DBUS_INTERFACE_LOCAL, - "Disconnected")) - { - /* Destroy all the proxies, quite possibly resulting in unreferencing - * the proxy manager and the connection as well. - */ - GSList *all; - GSList *tmp; - - all = dbus_g_proxy_manager_list_all (manager); - - tmp = all; - while (tmp != NULL) - { - DBusGProxy *proxy; - - proxy = DBUS_G_PROXY (tmp->data); - - UNLOCK_MANAGER (manager); - dbus_g_proxy_destroy (proxy); - g_object_unref (G_OBJECT (proxy)); - LOCK_MANAGER (manager); - - tmp = tmp->next; - } - - g_slist_free (all); - -#ifndef G_DISABLE_CHECKS - if (manager->proxy_lists != NULL) - g_warning ("Disconnection emitted \"destroy\" on all DBusGProxy, but somehow new proxies were created in response to one of those destroy signals. This will cause a memory leak."); -#endif - } - else - { - char *tri; - GSList *full_list; - GSList *owned_names; - GSList *tmp; - const char *sender; - - /* First we handle NameOwnerChanged internally */ - if (dbus_message_is_signal (message, - DBUS_INTERFACE_DBUS, - "NameOwnerChanged")) - { - const char *name; - const char *prev_owner; - const char *new_owner; - DBusError derr; - - dbus_error_init (&derr); - if (!dbus_message_get_args (message, - &derr, - DBUS_TYPE_STRING, - &name, - DBUS_TYPE_STRING, - &prev_owner, - DBUS_TYPE_STRING, - &new_owner, - DBUS_TYPE_INVALID)) - { - /* Ignore this error */ - dbus_error_free (&derr); - } - else if (manager->owner_names != NULL) - { - dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner); - } - } - - sender = dbus_message_get_sender (message); - - /* dbus spec requires these, libdbus validates */ - g_assert (sender != NULL); - g_assert (dbus_message_get_path (message) != NULL); - g_assert (dbus_message_get_interface (message) != NULL); - g_assert (dbus_message_get_member (message) != NULL); - - tri = tristring_from_message (message); - - if (manager->proxy_lists) - { - DBusGProxyList *owner_list; - owner_list = g_hash_table_lookup (manager->proxy_lists, tri); - if (owner_list) - full_list = g_slist_copy (owner_list->proxies); - else - full_list = NULL; - } - else - full_list = NULL; - - g_free (tri); - - if (manager->owner_names) - { - owned_names = g_hash_table_lookup (manager->owner_names, sender); - for (tmp = owned_names; tmp; tmp = tmp->next) - { - DBusGProxyList *owner_list; - DBusGProxyNameOwnerInfo *nameinfo; - - nameinfo = tmp->data; - g_assert (nameinfo->refcount > 0); - tri = tristring_alloc_from_strings (0, nameinfo->name, - dbus_message_get_path (message), - dbus_message_get_interface (message)); - - owner_list = g_hash_table_lookup (manager->proxy_lists, tri); - if (owner_list != NULL) - full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies)); - g_free (tri); - } - } - -#if 0 - g_print ("proxy got %s,%s,%s = list %p\n", - tri, - tri + strlen (tri) + 1, - tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1, - list); -#endif - - /* Emit the signal */ - - g_slist_foreach (full_list, (GFunc) g_object_ref, NULL); - - for (tmp = full_list; tmp; tmp = tmp->next) - { - DBusGProxy *proxy; - - proxy = DBUS_G_PROXY (tmp->data); - - UNLOCK_MANAGER (manager); - dbus_g_proxy_emit_remote_signal (proxy, message); - g_object_unref (G_OBJECT (proxy)); - LOCK_MANAGER (manager); - } - g_slist_free (full_list); - } - - UNLOCK_MANAGER (manager); - dbus_g_proxy_manager_unref (manager); - - /* "Handling" signals doesn't make sense, they are for everyone - * who cares - */ - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - - - -/* ---------- DBusGProxy -------------- */ -#define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL) - -static void -marshal_dbus_message_to_g_marshaller (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -enum -{ - PROP_0, - PROP_NAME, - PROP_PATH, - PROP_INTERFACE, - PROP_CONNECTION -}; - -enum -{ - DESTROY, - RECEIVED, - LAST_SIGNAL -}; - -static void *parent_class; -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -dbus_g_proxy_init (DBusGProxy *proxy) -{ - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - g_datalist_init (&priv->signal_signatures); - priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) dbus_pending_call_unref); - priv->name_call = 0; - priv->associated = FALSE; -} - -static GObject * -dbus_g_proxy_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - DBusGProxy *proxy; - DBusGProxyClass *klass; - GObjectClass *parent_class; - DBusGProxyPrivate *priv; - - klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY)); - - parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); - - proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties, - construct_properties)); - - priv = DBUS_G_PROXY_GET_PRIVATE (proxy); - - /* if these assertions fail, a deriving class has not set our required - * parameters - our own public constructors do return_if_fail checks - * on these parameters being provided. unfortunately we can't assert - * for manager because it's allowed to be NULL when tha mangager is - * setting up a bus proxy for its own calls */ - g_assert (priv->name != NULL); - g_assert (priv->path != NULL); - g_assert (priv->interface != NULL); - - if (priv->manager != NULL) - { - dbus_g_proxy_manager_register (priv->manager, proxy); - } - - return G_OBJECT (proxy); -} - -static void -dbus_g_proxy_class_init (DBusGProxyClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - g_type_class_add_private (klass, sizeof (DBusGProxyPrivate)); - - object_class->set_property = dbus_g_proxy_set_property; - object_class->get_property = dbus_g_proxy_get_property; - - g_object_class_install_property (object_class, - PROP_NAME, - g_param_spec_string ("name", - "name", - "name", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", - "path", - "path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_INTERFACE, - g_param_spec_string ("interface", - "interface", - "interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_CONNECTION, - g_param_spec_boxed ("connection", - "connection", - "connection", - DBUS_TYPE_G_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - object_class->finalize = dbus_g_proxy_finalize; - object_class->dispose = dbus_g_proxy_dispose; - object_class->constructor = dbus_g_proxy_constructor; - - signals[DESTROY] = - g_signal_new ("destroy", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[RECEIVED] = - g_signal_new ("received", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - 0, - NULL, NULL, - marshal_dbus_message_to_g_marshaller, - G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER); -} - -static void -cancel_pending_call (gpointer key, gpointer val, gpointer data) -{ - DBusGProxyCall *call = key; - DBusGProxy *proxy = data; - - dbus_g_proxy_cancel_call (proxy, call); -} - -static void -dbus_g_proxy_dispose (GObject *object) -{ - DBusGProxy *proxy = DBUS_G_PROXY (object); - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - if (priv->pending_calls == NULL) - { - return; - } - - /* Cancel outgoing pending calls */ - g_hash_table_foreach (priv->pending_calls, cancel_pending_call, proxy); - g_hash_table_destroy (priv->pending_calls); - priv->pending_calls = NULL; - - if (priv->manager && proxy != priv->manager->bus_proxy) - { - dbus_g_proxy_manager_unregister (priv->manager, proxy); - dbus_g_proxy_manager_unref (priv->manager); - } - priv->manager = NULL; - - g_datalist_clear (&priv->signal_signatures); - - g_signal_emit (object, signals[DESTROY], 0); - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -dbus_g_proxy_finalize (GObject *object) -{ - DBusGProxy *proxy = DBUS_G_PROXY (object); - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy)); - - g_free (priv->name); - g_free (priv->path); - g_free (priv->interface); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -dbus_g_proxy_destroy (DBusGProxy *proxy) -{ - /* FIXME do we need the GTK_IN_DESTRUCTION style flag - * from GtkObject? - */ - g_object_run_dispose (G_OBJECT (proxy)); -} - -static void -dbus_g_proxy_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - DBusGProxy *proxy = DBUS_G_PROXY (object); - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - DBusGConnection *connection; - - switch (prop_id) - { - case PROP_NAME: - priv->name = g_strdup (g_value_get_string (value)); - priv->for_owner = (priv->name[0] == ':'); - break; - case PROP_PATH: - priv->path = g_strdup (g_value_get_string (value)); - break; - case PROP_INTERFACE: - priv->interface = g_strdup (g_value_get_string (value)); - break; - case PROP_CONNECTION: - connection = g_value_get_boxed (value); - if (connection != NULL) - { - priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection)); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dbus_g_proxy_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - DBusGProxy *proxy = DBUS_G_PROXY (object); - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - switch (prop_id) - { - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_INTERFACE: - g_value_set_string (value, priv->interface); - break; - case PROP_CONNECTION: - g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* this is to avoid people using g_signal_connect() directly, - * to avoid confusion with local signal names, and because - * of the horribly broken current setup (signals are added - * globally to all proxies) - */ -static char* -create_signal_name (const char *interface, - const char *signal) -{ - GString *str; - char *p; - - str = g_string_new (interface); - - g_string_append (str, "-"); - - g_string_append (str, signal); - - /* GLib will silently barf on '.' in signal names */ - p = str->str; - while (*p) - { - if (*p == '.') - *p = '-'; - ++p; - } - - return g_string_free (str, FALSE); -} - -static void -marshal_dbus_message_to_g_marshaller (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - /* Incoming here we have three params, the instance (Proxy), the - * DBusMessage, the signature. We want to convert that to an - * expanded GValue array, then call an appropriate normal GLib - * marshaller. - */ -#define MAX_SIGNATURE_ARGS 20 - GValueArray *value_array; - GSignalCMarshaller c_marshaller; - DBusGProxy *proxy; - DBusMessage *message; - GArray *gsignature; - const GType *types; - DBusGProxyPrivate *priv; - - g_assert (n_param_values == 3); - - proxy = g_value_get_object (¶m_values[0]); - message = g_value_get_boxed (¶m_values[1]); - gsignature = g_value_get_pointer (¶m_values[2]); - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (message != NULL); - g_return_if_fail (gsignature != NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len, - (GType*) gsignature->data); - - g_return_if_fail (c_marshaller != NULL); - - { - DBusGValueMarshalCtx context; - context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection); - context.proxy = proxy; - - types = (const GType*) gsignature->data; - value_array = _dbus_gvalue_demarshal_message (&context, message, - gsignature->len, types, NULL); - } - - if (value_array == NULL) - return; - - g_value_array_prepend (value_array, NULL); - g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy)); - g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy); - - (* c_marshaller) (closure, return_value, value_array->n_values, - value_array->values, invocation_hint, marshal_data); - - g_value_array_free (value_array); -} - -static void -dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, - DBusMessage *message) -{ - const char *interface; - const char *signal; - char *name; - GQuark q; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - GArray *msg_gsignature = NULL; - - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - - interface = dbus_message_get_interface (message); - signal = dbus_message_get_member (message); - - g_assert (interface != NULL); - g_assert (signal != NULL); - - name = create_signal_name (interface, signal); - - /* If the quark isn't preexisting, there's no way there - * are any handlers connected. We don't want to create - * extra quarks for every possible signal. - */ - q = g_quark_try_string (name); - - if (q != 0) - { - GArray *gsignature; - guint i; - - gsignature = g_datalist_id_get_data (&priv->signal_signatures, q); - if (gsignature == NULL) - goto out; - - msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message), - TRUE); - for (i = 0; i < gsignature->len; i++) - { - if (msg_gsignature->len == i - || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i)) - goto mismatch; - } - if (msg_gsignature->len != i) - goto mismatch; - - g_signal_emit (proxy, - signals[RECEIVED], - q, - message, - msg_gsignature); - } - - out: - g_free (name); - if (msg_gsignature) - g_array_free (msg_gsignature, TRUE); - return; - mismatch: -#if 0 - /* Don't spew on remote errors */ - g_warning ("Unexpected message signature '%s' for signal '%s'\n", - dbus_message_get_signature (message), - name); -#endif - goto out; -} - -typedef struct -{ - DBusGProxy *proxy; - guint call_id; - DBusGProxyCallNotify func; - void *data; - GDestroyNotify free_data_func; -} GPendingNotifyClosure; - -static void -d_pending_call_notify (DBusPendingCall *dcall, - void *data) -{ - GPendingNotifyClosure *closure = data; - - (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data); -} - -static void -d_pending_call_free (void *data) -{ - GPendingNotifyClosure *closure = data; - - if (closure->free_data_func) - (* closure->free_data_func) (closure->data); - - g_free (closure); -} - -#define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \ -do { \ - GType valtype; \ - int i = 0; \ - VALARRAY = g_value_array_new (6); \ - valtype = FIRST_ARG_TYPE; \ - while (valtype != G_TYPE_INVALID) \ - { \ - const char *collect_err; \ - GValue *val; \ - g_value_array_append (VALARRAY, NULL); \ - val = g_value_array_get_nth (VALARRAY, i); \ - g_value_init (val, valtype); \ - collect_err = NULL; \ - G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \ - valtype = va_arg (ARGS, GType); \ - i++; \ - } \ -} while (0) - -DBusGProxyCall * -manager_begin_bus_call (DBusGProxyManager *manager, - const char *method, - DBusGProxyCallNotify notify, - gpointer user_data, - GDestroyNotify destroy, - GType first_arg_type, - ...) -{ - DBusGProxyCall *call; - DBusGProxyPrivate *priv; - va_list args; - GValueArray *arg_values; - - va_start (args, first_arg_type); - - if (!manager->bus_proxy) - { - manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY, - "name", DBUS_SERVICE_DBUS, - "path", DBUS_PATH_DBUS, - "interface", DBUS_INTERFACE_DBUS, - NULL); - priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy); - priv->manager = manager; - } - - DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args); - - call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values)); - - g_value_array_free (arg_values); - - va_end (args); - - return call; -} - -/** @} End of DBusGLibInternals */ - -/** @addtogroup DBusGLib - * @{ - */ - -/** - * Standard GObject get_type() function for DBusGProxy. - * - * @returns type ID for DBusGProxy class - */ -GType -dbus_g_proxy_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - static const GTypeInfo object_info = - { - sizeof (DBusGProxyClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) dbus_g_proxy_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (DBusGProxy), - 0, /* n_preallocs */ - (GInstanceInitFunc) dbus_g_proxy_init, - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - "DBusGProxy", - &object_info, 0); - } - - return object_type; -} - -static DBusGProxy* -dbus_g_proxy_new (DBusGConnection *connection, - const char *name, - const char *path_name, - const char *interface_name) -{ - DBusGProxy *proxy; - - g_assert (connection != NULL); - - proxy = g_object_new (DBUS_TYPE_G_PROXY, - "name", name, - "path", path_name, - "interface", interface_name, - "connection", connection, NULL); - - return proxy; -} - -/** - * Creates a new proxy for a remote interface exported by a connection - * on a message bus. Method calls and signal connections over this - * proxy will go to the name owner; the name's owner is expected to - * support the given interface name. THE NAME OWNER MAY CHANGE OVER - * TIME, for example between two different method calls, unless the - * name is a unique name. If you need a fixed owner, you need to - * request the current owner and bind a proxy to its unique name - * rather than to the generic name; see - * dbus_g_proxy_new_for_name_owner(). - * - * A name-associated proxy only makes sense with a message bus, not - * for app-to-app direct dbus connections. - * - * This proxy will only emit the "destroy" signal if the - * #DBusConnection is disconnected, the proxy has no remaining - * references, or the name is a unique name and its owner - * disappears. If a well-known name changes owner, the proxy will - * still be alive. - * - * @param connection the connection to the remote bus - * @param name any name on the message bus - * @param path_name name of the object instance to call methods on - * @param interface_name name of the interface to call methods on - * @returns new proxy object - */ -DBusGProxy* -dbus_g_proxy_new_for_name (DBusGConnection *connection, - const char *name, - const char *path_name, - const char *interface_name) -{ - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (path_name != NULL, NULL); - g_return_val_if_fail (interface_name != NULL, NULL); - - return dbus_g_proxy_new (connection, name, - path_name, interface_name); -} - -/** - * Similar to dbus_g_proxy_new_for_name(), but makes a round-trip - * request to the message bus to get the current name owner, then - * binds the proxy to the unique name of the current owner, rather - * than to the well-known name. As a result, the name owner will - * not change over time, and the proxy will emit the "destroy" signal - * when the owner disappears from the message bus. - * - * An example of the difference between dbus_g_proxy_new_for_name() - * and dbus_g_proxy_new_for_name_owner(): if you provide the well-known name - * "org.freedesktop.Database" dbus_g_proxy_new_for_name() remains bound - * to that name as it changes owner. dbus_g_proxy_new_for_name_owner() - * will fail if the name has no owner. If the name has an owner, - * dbus_g_proxy_new_for_name_owner() will bind to the unique name - * of that owner rather than the generic name. - * - * @param connection the connection to the remote bus - * @param name any name on the message bus - * @param path_name name of the object inside the service to call methods on - * @param interface_name name of the interface to call methods on - * @param error return location for an error - * @returns new proxy object, or #NULL on error - */ -DBusGProxy* -dbus_g_proxy_new_for_name_owner (DBusGConnection *connection, - const char *name, - const char *path_name, - const char *interface_name, - GError **error) -{ - DBusGProxy *proxy; - char *unique_name; - - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (path_name != NULL, NULL); - g_return_val_if_fail (interface_name != NULL, NULL); - - if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error))) - return NULL; - - proxy = dbus_g_proxy_new (connection, unique_name, - path_name, interface_name); - g_free (unique_name); - return proxy; -} - -/** - * Creates a proxy using an existing proxy as a template, substituting - * the specified interface and path. Either or both may be NULL. - * - * @param proxy the proxy to use as a template - * @param path of the object inside the peer to call methods on - * @param interface name of the interface to call methods on - * @returns new proxy object - * - */ -DBusGProxy* -dbus_g_proxy_new_from_proxy (DBusGProxy *proxy, - const char *interface, - const char *path) -{ - DBusGProxyPrivate *priv; - - g_return_val_if_fail (proxy != NULL, NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - if (interface == NULL) - interface = priv->interface; - if (path == NULL) - path = priv->path; - - return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection), - priv->name, - path, interface); -} - -/** - * Creates a proxy for an object in peer application (one - * we're directly connected to). That is, this function is - * intended for use when there's no message bus involved, - * we're doing a simple 1-to-1 communication between two - * applications. - * - * - * @param connection the connection to the peer - * @param path_name name of the object inside the peer to call methods on - * @param interface_name name of the interface to call methods on - * @returns new proxy object - * - */ -DBusGProxy* -dbus_g_proxy_new_for_peer (DBusGConnection *connection, - const char *path_name, - const char *interface_name) -{ - DBusGProxy *proxy; - - g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (path_name != NULL, NULL); - g_return_val_if_fail (interface_name != NULL, NULL); - - proxy = dbus_g_proxy_new (connection, NULL, - path_name, interface_name); - - return proxy; -} - -/** - * Gets the bus name a proxy is bound to (may be #NULL in some cases). - * If you created the proxy with dbus_g_proxy_new_for_name(), then - * the name you passed to that will be returned. - * If you created it with dbus_g_proxy_new_for_name_owner(), then the - * unique connection name will be returned. If you created it - * with dbus_g_proxy_new_for_peer() then #NULL will be returned. - * - * @param proxy the proxy - * @returns the bus name the proxy sends messages to - */ -const char* -dbus_g_proxy_get_bus_name (DBusGProxy *proxy) -{ - DBusGProxyPrivate *priv; - - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - return priv->name; -} - -/** - * Gets the object interface proxy is bound to (may be #NULL in some cases). - * - * @param proxy the proxy - * @returns an object interface - */ -const char* -dbus_g_proxy_get_interface (DBusGProxy *proxy) -{ - DBusGProxyPrivate *priv; - - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - return priv->interface; -} - -/** - * Sets the object interface proxy is bound to - * - * @param proxy the proxy - * @param interface_name an object interface - */ -void -dbus_g_proxy_set_interface (DBusGProxy *proxy, - const char *interface_name) -{ - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - /* FIXME - need to unregister when we switch interface for now - * later should support idea of unset interface - */ - dbus_g_proxy_manager_unregister (priv->manager, proxy); - g_free (priv->interface); - priv->interface = g_strdup (interface_name); - dbus_g_proxy_manager_register (priv->manager, proxy); -} - -/** - * Gets the path this proxy is bound to - * - * @param proxy the proxy - * @returns an object path - */ -const char* -dbus_g_proxy_get_path (DBusGProxy *proxy) -{ - DBusGProxyPrivate *priv; - - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - return priv->path; -} - -static DBusMessage * -dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy, - const char *method, - GValueArray *args) -{ - DBusMessage *message; - DBusMessageIter msgiter; - guint i; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - message = dbus_message_new_method_call (priv->name, - priv->path, - priv->interface, - method); - if (message == NULL) - goto oom; - - dbus_message_iter_init_append (message, &msgiter); - for (i = 0; i < args->n_values; i++) - { - GValue *gvalue; - - gvalue = g_value_array_get_nth (args, i); - - if (!_dbus_gvalue_marshal (&msgiter, gvalue)) - g_assert_not_reached (); - } - return message; - oom: - return NULL; -} - -static guint -dbus_g_proxy_begin_call_internal (DBusGProxy *proxy, - const char *method, - DBusGProxyCallNotify notify, - gpointer user_data, - GDestroyNotify destroy, - GValueArray *args) -{ - DBusMessage *message; - DBusPendingCall *pending; - GPendingNotifyClosure *closure; - guint call_id; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - pending = NULL; - - message = dbus_g_proxy_marshal_args_to_message (proxy, method, args); - if (!message) - goto oom; - - if (!dbus_connection_send_with_reply (priv->manager->connection, - message, - &pending, - -1)) - goto oom; - dbus_message_unref (message); - g_assert (pending != NULL); - - call_id = ++priv->call_id_counter; - - if (notify != NULL) - { - closure = g_new (GPendingNotifyClosure, 1); - closure->proxy = proxy; /* No need to ref as the lifecycle is tied to proxy */ - closure->call_id = call_id; - closure->func = notify; - closure->data = user_data; - closure->free_data_func = destroy; - dbus_pending_call_set_notify (pending, d_pending_call_notify, - closure, - d_pending_call_free); - } - - g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending); - - return call_id; - oom: - g_error ("Out of memory"); - return 0; -} - -static gboolean -dbus_g_proxy_end_call_internal (DBusGProxy *proxy, - guint call_id, - GError **error, - GType first_arg_type, - va_list args) -{ - DBusMessage *reply; - DBusMessageIter msgiter; - DBusError derror; - va_list args_unwind; - guint over; - int n_retvals_processed; - gboolean ret; - GType valtype; - DBusPendingCall *pending; - DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - reply = NULL; - ret = FALSE; - n_retvals_processed = 0; - over = 0; - - pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id)); - - dbus_pending_call_block (pending); - reply = dbus_pending_call_steal_reply (pending); - - g_assert (reply != NULL); - - dbus_error_init (&derror); - - switch (dbus_message_get_type (reply)) - { - case DBUS_MESSAGE_TYPE_METHOD_RETURN: - - dbus_message_iter_init (reply, &msgiter); - valtype = first_arg_type; - while (valtype != G_TYPE_INVALID) - { - int arg_type; - gpointer return_storage; - GValue gvalue = { 0, }; - DBusGValueMarshalCtx context; - - context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection); - context.proxy = proxy; - - arg_type = dbus_message_iter_get_arg_type (&msgiter); - if (arg_type == DBUS_TYPE_INVALID) - { - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Too few arguments in reply")); - goto out; - } - - return_storage = va_arg (args, gpointer); - if (return_storage == NULL) - goto next; - - /* We handle variants specially; the caller is expected - * to have already allocated storage for them. - */ - if (arg_type == DBUS_TYPE_VARIANT - && g_type_is_a (valtype, G_TYPE_VALUE)) - { - if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL)) - { - g_set_error (error, - DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Couldn't convert argument, expected \"%s\""), - g_type_name (valtype)); - goto out; - } - } - else - { - g_value_init (&gvalue, valtype); - - if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error)) - goto out; - - /* Anything that can be demarshaled must be storable */ - if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage)) - g_assert_not_reached (); - /* Ownership of the value passes to the client, don't unset */ - } - - next: - n_retvals_processed++; - dbus_message_iter_next (&msgiter); - valtype = va_arg (args, GType); - } - - while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID) - { - over++; - dbus_message_iter_next (&msgiter); - } - - if (over > 0) - { - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Too many arguments in reply; expected %d, got %d"), - n_retvals_processed, over); - goto out; - } - break; - case DBUS_MESSAGE_TYPE_ERROR: - dbus_set_error_from_message (&derror, reply); - dbus_set_g_error (error, &derror); - dbus_error_free (&derror); - goto out; - break; - default: - dbus_set_error (&derror, DBUS_ERROR_FAILED, - "Reply was neither a method return nor an exception"); - dbus_set_g_error (error, &derror); - dbus_error_free (&derror); - goto out; - break; - } - - ret = TRUE; - out: - va_end (args); - - if (ret == FALSE) - { - int i; - for (i = 0; i < n_retvals_processed; i++) - { - gpointer retval; - - retval = va_arg (args_unwind, gpointer); - - g_free (retval); - } - } - va_end (args_unwind); - - g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id)); - - if (reply) - dbus_message_unref (reply); - return ret; -} - -/** - * Asynchronously invokes a method on a remote interface. The method - * call will not be sent over the wire until the application returns - * to the main loop, or blocks in dbus_connection_flush() to write out - * pending data. The call will be completed after a timeout, or when - * a reply is received. When the call returns, the callback specified - * will be invoked; you can then collect the results of the call - * (which may be an error, or a reply), use dbus_g_proxy_end_call(). - * - * @todo this particular function shouldn't die on out of memory, - * since you should be able to do a call with large arguments. - * - * @param proxy a proxy for a remote interface - * @param method the name of the method to invoke - * @param notify callback to be invoked when method returns - * @param user_data user data passed to callback - * @param destroy function called to destroy user_data - * @param first_arg_type type of the first argument - * - * @returns call identifier - * */ -DBusGProxyCall * -dbus_g_proxy_begin_call (DBusGProxy *proxy, - const char *method, - DBusGProxyCallNotify notify, - gpointer user_data, - GDestroyNotify destroy, - GType first_arg_type, - ...) -{ - guint call_id; - va_list args; - GValueArray *arg_values; - - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); - - va_start (args, first_arg_type); - - DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args); - - call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values); - - g_value_array_free (arg_values); - - va_end (args); - - return DBUS_G_PROXY_ID_TO_CALL (call_id); -} - -/** - * Collects the results of a method call. The method call was normally - * initiated with dbus_g_proxy_end_call(). You may use this function - * outside of the callback given to dbus_g_proxy_begin_call; in that - * case this function will block if the results haven't yet been - * received. - * - * If the call results in an error, the error is set as normal for - * GError and the function returns #FALSE. - * - * Otherwise, the "out" parameters and return value of the - * method are stored in the provided varargs list. - * The list should be terminated with G_TYPE_INVALID. - * - * @param proxy a proxy for a remote interface - * @param call the pending call ID from dbus_g_proxy_begin_call() - * @param error return location for an error - * @param first_arg_type type of first "out" argument - * @returns #FALSE if an error is set - */ -gboolean -dbus_g_proxy_end_call (DBusGProxy *proxy, - DBusGProxyCall *call, - GError **error, - GType first_arg_type, - ...) -{ - gboolean ret; - va_list args; - - va_start (args, first_arg_type); - - ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args); - - va_end (args); - - return ret; -} - -/** - * Function for synchronously invoking a method and receiving reply - * values. This function is equivalent to dbus_g_proxy_begin_call - * followed by dbus_g_proxy_end_call. All of the input arguments are - * specified first, followed by G_TYPE_INVALID, followed by all of the - * output values, followed by a second G_TYPE_INVALID. Note that - * this means you must always specify G_TYPE_INVALID twice. - * - * @param proxy a proxy for a remote interface - * @param method method to invoke - * @param error return location for an error - * @param first_arg_type type of first "in" argument - * @returns #FALSE if an error is set, TRUE otherwise - */ -gboolean -dbus_g_proxy_call (DBusGProxy *proxy, - const char *method, - GError **error, - GType first_arg_type, - ...) -{ - gboolean ret; - guint call_id; - va_list args; - GValueArray *in_args; - - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); - - va_start (args, first_arg_type); - - DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args); - - call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args); - - g_value_array_free (in_args); - - first_arg_type = va_arg (args, GType); - ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args); - - va_end (args); - - return ret; -} - -/** - * Sends a method call message as with dbus_g_proxy_begin_call(), but - * does not ask for a reply or allow you to receive one. - * - * @todo this particular function shouldn't die on out of memory, - * since you should be able to do a call with large arguments. - * - * @param proxy a proxy for a remote interface - * @param method the name of the method to invoke - * @param first_arg_type type of the first argument - */ -void -dbus_g_proxy_call_no_reply (DBusGProxy *proxy, - const char *method, - GType first_arg_type, - ...) -{ - DBusMessage *message; - va_list args; - GValueArray *in_args; - DBusGProxyPrivate *priv; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - va_start (args, first_arg_type); - DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args); - - message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args); - - g_value_array_free (in_args); - va_end (args); - - if (!message) - goto oom; - - dbus_message_set_no_reply (message, TRUE); - - if (!dbus_connection_send (priv->manager->connection, - message, - NULL)) - goto oom; - dbus_message_unref (message); - return; - - oom: - g_error ("Out of memory"); -} - -/** - * Cancels a pending method call. The method call was normally - * initiated with dbus_g_proxy_begin_call(). This function - * may not be used on pending calls that have already been - * ended with dbus_g_proxy_end_call. - * - * @param proxy a proxy for a remote interface - * @param call the pending call ID from dbus_g_proxy_begin_call() - */ -void -dbus_g_proxy_cancel_call (DBusGProxy *proxy, - DBusGProxyCall *call) -{ - guint call_id; - DBusPendingCall *pending; - DBusGProxyPrivate *priv; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - call_id = DBUS_G_PROXY_CALL_TO_ID (call); - - pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id)); - g_return_if_fail (pending != NULL); - - dbus_pending_call_cancel (pending); - - g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id)); -} - -/** - * Sends a message to the interface we're proxying for. Does not - * block or wait for a reply. The message is only actually written out - * when you return to the main loop or block in - * dbus_connection_flush(). - * - * The message is modified to be addressed to the target interface. - * That is, a destination name field or whatever is needed will be - * added to the message. The basic point of this function is to add - * the necessary header fields, otherwise it's equivalent to - * dbus_connection_send(). - * - * This function adds a reference to the message, so the caller - * still owns its original reference. - * - * @param proxy a proxy for a remote interface - * @param message the message to address and send - * @param client_serial return location for message's serial, or #NULL */ -void -dbus_g_proxy_send (DBusGProxy *proxy, - DBusMessage *message, - dbus_uint32_t *client_serial) -{ - DBusGProxyPrivate *priv; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - if (priv->name) - { - if (!dbus_message_set_destination (message, priv->name)) - g_error ("Out of memory"); - } - if (priv->path) - { - if (!dbus_message_set_path (message, priv->path)) - g_error ("Out of memory"); - } - if (priv->interface) - { - if (!dbus_message_set_interface (message, priv->interface)) - g_error ("Out of memory"); - } - - if (!dbus_connection_send (priv->manager->connection, message, client_serial)) - g_error ("Out of memory\n"); -} - -static void -array_free_all (gpointer array) -{ - g_array_free (array, TRUE); -} - -/** - * Specifies the argument signature of a signal;.only necessary - * if the remote object does not support introspection. The arguments - * specified are the GLib types expected. - * - * @param proxy the proxy for a remote interface - * @param signal_name the name of the signal - * @param first_type the first argument type, or G_TYPE_INVALID if none - */ -void -dbus_g_proxy_add_signal (DBusGProxy *proxy, - const char *signal_name, - GType first_type, - ...) -{ - GQuark q; - char *name; - GArray *gtypesig; - GType gtype; - va_list args; - DBusGProxyPrivate *priv; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - g_return_if_fail (signal_name != NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - - name = create_signal_name (priv->interface, signal_name); - - q = g_quark_from_string (name); - - g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL); - - gtypesig = g_array_new (FALSE, TRUE, sizeof (GType)); - - va_start (args, first_type); - gtype = first_type; - while (gtype != G_TYPE_INVALID) - { - g_array_append_val (gtypesig, gtype); - gtype = va_arg (args, GType); - } - va_end (args); - -#ifndef G_DISABLE_CHECKS - if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL) - g_warning ("No marshaller for signature of signal '%s'", signal_name); -#endif - - - g_datalist_id_set_data_full (&priv->signal_signatures, - q, gtypesig, - array_free_all); - - g_free (name); -} - -/** - * Connect a signal handler to a proxy for a remote interface. When - * the remote interface emits the specified signal, the proxy will - * emit a corresponding GLib signal. - * - * @param proxy a proxy for a remote interface - * @param signal_name the DBus signal name to listen for - * @param handler the handler to connect - * @param data data to pass to handler - * @param free_data_func callback function to destroy data - */ -void -dbus_g_proxy_connect_signal (DBusGProxy *proxy, - const char *signal_name, - GCallback handler, - void *data, - GClosureNotify free_data_func) -{ - char *name; - GClosure *closure; - GQuark q; - DBusGProxyPrivate *priv; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - g_return_if_fail (signal_name != NULL); - g_return_if_fail (handler != NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - name = create_signal_name (priv->interface, signal_name); - - q = g_quark_try_string (name); - -#ifndef G_DISABLE_CHECKS - if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL) - { - g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name); - g_free (name); - return; - } -#endif - - closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func); - - g_signal_connect_closure_by_id (G_OBJECT (proxy), - signals[RECEIVED], - q, - closure, FALSE); - - g_free (name); -} - -/** - * Disconnect all signal handlers from a proxy that match the given - * criteria. - * - * @param proxy a proxy for a remote interface - * @param signal_name the DBus signal name to disconnect - * @param handler the handler to disconnect - * @param data the data that was registered with handler - */ -void -dbus_g_proxy_disconnect_signal (DBusGProxy *proxy, - const char *signal_name, - GCallback handler, - void *data) -{ - char *name; - GQuark q; - DBusGProxyPrivate *priv; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - g_return_if_fail (signal_name != NULL); - g_return_if_fail (handler != NULL); - - priv = DBUS_G_PROXY_GET_PRIVATE(proxy); - name = create_signal_name (priv->interface, signal_name); - - q = g_quark_try_string (name); - - if (q != 0) - { - g_signal_handlers_disconnect_matched (G_OBJECT (proxy), - G_SIGNAL_MATCH_DETAIL | - G_SIGNAL_MATCH_FUNC | - G_SIGNAL_MATCH_DATA, - signals[RECEIVED], - q, - NULL, - G_CALLBACK (handler), data); - } - else - { - g_warning ("Attempt to disconnect from signal '%s' which is not registered\n", - name); - } - - g_free (name); -} - -/** @} End of DBusGLib public */ - -#ifdef DBUS_BUILD_TESTS - -/** - * @ingroup DBusGLibInternals - * Unit test for GLib proxy functions - * @returns #TRUE on success. - */ -gboolean -_dbus_g_proxy_test (void) -{ - - - return TRUE; -} - -#endif /* DBUS_BUILD_TESTS */ |