1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ofdbus/dbus-glib/dbus/dbus-gproxy.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3039 @@
1.4 +/* -*- mode: C; c-file-style: "gnu" -*- */
1.5 +/* dbus-gproxy.c Proxy for remote objects
1.6 + *
1.7 + * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
1.8 + * Copyright (C) 2005 Nokia
1.9 + * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
1.10 + * Licensed under the Academic Free License version 2.1
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify
1.13 + * it under the terms of the GNU General Public License as published by
1.14 + * the Free Software Foundation; either version 2 of the License, or
1.15 + * (at your option) any later version.
1.16 + *
1.17 + * This program is distributed in the hope that it will be useful,
1.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.20 + * GNU General Public License for more details.
1.21 + *
1.22 + * You should have received a copy of the GNU General Public License
1.23 + * along with this program; if not, write to the Free Software
1.24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.25 + *
1.26 + */
1.27 +#include <dbus/dbus-glib.h>
1.28 +#include <dbus/dbus-glib-lowlevel.h>
1.29 +#include <dbus/dbus-signature.h>
1.30 +#include "dbus-gutils.h"
1.31 +#include "dbus-gsignature.h"
1.32 +#include "dbus-gvalue.h"
1.33 +#include "dbus-gvalue-utils.h"
1.34 +#include "dbus-gobject.h"
1.35 +#include <string.h>
1.36 +
1.37 +
1.38 +#ifdef __SYMBIAN32__
1.39 +#include<glib_global.h>
1.40 +#include<glib-object.h>
1.41 +#endif
1.42 +
1.43 +#ifndef __SYMBIAN32__
1.44 +#include <glib/gi18n.h>
1.45 +#include <libintl.h>
1.46 +#define _(x) dgettext (GETTEXT_PACKAGE, x)
1.47 +#define N_(x) x
1.48 +#else
1.49 +
1.50 +#define _(x) x
1.51 +#define N_(x) x
1.52 +#endif
1.53 +
1.54 +#include <gobject/gvaluecollector.h>
1.55 +
1.56 +#ifdef __SYMBIAN32__
1.57 +#include "libdbus_glib_wsd_solution.h"
1.58 +#endif
1.59 +
1.60 +#define DBUS_G_PROXY_CALL_TO_ID(x) (GPOINTER_TO_UINT(x))
1.61 +#define DBUS_G_PROXY_ID_TO_CALL(x) (GUINT_TO_POINTER(x))
1.62 +#define DBUS_G_PROXY_GET_PRIVATE(o) \
1.63 + (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TYPE_G_PROXY, DBusGProxyPrivate))
1.64 +
1.65 +
1.66 +/**
1.67 + * @addtogroup DBusGLibInternals
1.68 + *
1.69 + * @{
1.70 + */
1.71 +
1.72 +/**
1.73 + * DBusGProxyManager typedef
1.74 + */
1.75 +
1.76 +typedef struct _DBusGProxyManager DBusGProxyManager;
1.77 +
1.78 +typedef struct _DBusGProxyPrivate DBusGProxyPrivate;
1.79 +
1.80 +/**
1.81 + * Internals of DBusGProxy
1.82 + */
1.83 +struct _DBusGProxyPrivate
1.84 +{
1.85 + DBusGProxyManager *manager; /**< Proxy manager */
1.86 + char *name; /**< Name messages go to or NULL */
1.87 + char *path; /**< Path messages go to or NULL */
1.88 + char *interface; /**< Interface messages go to or NULL */
1.89 +
1.90 + DBusGProxyCall *name_call; /**< Pending call id to retrieve name owner */
1.91 + guint for_owner : 1; /**< Whether or not this proxy is for a name owner */
1.92 + guint associated : 1; /**< Whether or not this proxy is associated (for name proxies) */
1.93 +
1.94 + /* FIXME: make threadsafe? */
1.95 + guint call_id_counter; /**< Integer counter for pending calls */
1.96 +
1.97 + GData *signal_signatures; /**< D-BUS signatures for each signal */
1.98 +
1.99 + GHashTable *pending_calls; /**< Calls made on this proxy which have not yet returned */
1.100 +};
1.101 +
1.102 +static void dbus_g_proxy_init (DBusGProxy *proxy);
1.103 +static void dbus_g_proxy_class_init (DBusGProxyClass *klass);
1.104 +static GObject *dbus_g_proxy_constructor (GType type,
1.105 + guint n_construct_properties,
1.106 + GObjectConstructParam *construct_properties);
1.107 +static void dbus_g_proxy_set_property (GObject *object,
1.108 + guint prop_id,
1.109 + const GValue *value,
1.110 + GParamSpec *pspec);
1.111 +static void dbus_g_proxy_get_property (GObject *object,
1.112 + guint prop_id,
1.113 + GValue *value,
1.114 + GParamSpec *pspec);
1.115 +
1.116 +static void dbus_g_proxy_finalize (GObject *object);
1.117 +static void dbus_g_proxy_dispose (GObject *object);
1.118 +static void dbus_g_proxy_destroy (DBusGProxy *proxy);
1.119 +static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
1.120 + DBusMessage *message);
1.121 +
1.122 +static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager *manager,
1.123 + const char *method,
1.124 + DBusGProxyCallNotify notify,
1.125 + gpointer data,
1.126 + GDestroyNotify destroy,
1.127 + GType first_arg_type,
1.128 + ...);
1.129 +static guint dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
1.130 + const char *method,
1.131 + DBusGProxyCallNotify notify,
1.132 + gpointer data,
1.133 + GDestroyNotify destroy,
1.134 + GValueArray *args,
1.135 + int timeout );
1.136 +static gboolean dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
1.137 + guint call_id,
1.138 + GError **error,
1.139 + GType first_arg_type,
1.140 + va_list args);
1.141 +
1.142 +/**
1.143 + * A list of proxies with a given name+path+interface, used to
1.144 + * route incoming signals.
1.145 + */
1.146 +typedef struct
1.147 +{
1.148 + GSList *proxies; /**< The list of proxies */
1.149 +
1.150 + char name[4]; /**< name (empty string for none), nul byte,
1.151 + * path, nul byte,
1.152 + * interface, nul byte
1.153 + */
1.154 +
1.155 +} DBusGProxyList;
1.156 +
1.157 +/**
1.158 + * DBusGProxyManager's primary task is to route signals to the proxies
1.159 + * those signals are emitted on. In order to do this it also has to
1.160 + * track the owners of the names proxies are bound to.
1.161 + */
1.162 +struct _DBusGProxyManager
1.163 +{
1.164 + GStaticMutex lock; /**< Thread lock */
1.165 + int refcount; /**< Reference count */
1.166 + DBusConnection *connection; /**< Connection we're associated with. */
1.167 +
1.168 + DBusGProxy *bus_proxy; /**< Special internal proxy used to talk to the bus */
1.169 +
1.170 + GHashTable *proxy_lists; /**< Hash used to route incoming signals
1.171 + * and iterate over proxies
1.172 + */
1.173 + GHashTable *owner_names; /**< Hash to keep track of mapping from
1.174 + * base name -> [name,name,...] for proxies which
1.175 + * are for names.
1.176 + */
1.177 + GSList *unassociated_proxies; /**< List of name proxies for which
1.178 + * there was no result for
1.179 + * GetNameOwner
1.180 + */
1.181 +};
1.182 +
1.183 +static DBusGProxyManager *dbus_g_proxy_manager_ref (DBusGProxyManager *manager);
1.184 +static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection,
1.185 + DBusMessage *message,
1.186 + void *user_data);
1.187 +
1.188 +
1.189 +/** Lock the DBusGProxyManager */
1.190 +#define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock))
1.191 +/** Unlock the DBusGProxyManager */
1.192 +#define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock))
1.193 +
1.194 +
1.195 +#if EMULATOR
1.196 +GET_STATIC_VAR_FROM_TLS(g_proxy_manager_slot,dbus_gproxy,int )
1.197 +#define g_proxy_manager_slot (*GET_DBUS_WSD_VAR_NAME(g_proxy_manager_slot,dbus_gproxy,s)())
1.198 +GET_STATIC_VAR_FROM_TLS(connection_g_proxy_lock,dbus_gproxy,GStaticMutex )
1.199 +#define connection_g_proxy_lock (*GET_DBUS_WSD_VAR_NAME(connection_g_proxy_lock,dbus_gproxy,s)())
1.200 +
1.201 +#else
1.202 +static int g_proxy_manager_slot = -1;
1.203 +/* Lock controlling get/set manager as data on each connection */
1.204 +static GStaticMutex connection_g_proxy_lock = G_STATIC_MUTEX_INIT;
1.205 +
1.206 +#endif
1.207 +
1.208 +
1.209 +
1.210 +
1.211 +static DBusGProxyManager*
1.212 +dbus_g_proxy_manager_get (DBusConnection *connection)
1.213 +{
1.214 + DBusGProxyManager *manager;
1.215 +
1.216 + dbus_connection_allocate_data_slot (&g_proxy_manager_slot);
1.217 + if (g_proxy_manager_slot < 0)
1.218 + g_error ("out of memory");
1.219 +
1.220 + g_static_mutex_lock (&connection_g_proxy_lock);
1.221 +
1.222 + manager = dbus_connection_get_data (connection, g_proxy_manager_slot);
1.223 + if (manager != NULL)
1.224 + {
1.225 + dbus_connection_free_data_slot (&g_proxy_manager_slot);
1.226 + dbus_g_proxy_manager_ref (manager);
1.227 + g_static_mutex_unlock (&connection_g_proxy_lock);
1.228 + return manager;
1.229 + }
1.230 +
1.231 + manager = g_new0 (DBusGProxyManager, 1);
1.232 +
1.233 + manager->refcount = 1;
1.234 + manager->connection = connection;
1.235 +
1.236 + g_static_mutex_init (&manager->lock);
1.237 +
1.238 + /* Proxy managers keep the connection alive, which means that
1.239 + * DBusGProxy indirectly does. To free a connection you have to free
1.240 + * all the proxies referring to it.
1.241 + */
1.242 + dbus_connection_ref (manager->connection);
1.243 +
1.244 + dbus_connection_set_data (connection, g_proxy_manager_slot,
1.245 + manager, NULL);
1.246 +
1.247 + dbus_connection_add_filter (connection, dbus_g_proxy_manager_filter,
1.248 + manager, NULL);
1.249 +
1.250 + g_static_mutex_unlock (&connection_g_proxy_lock);
1.251 +
1.252 + return manager;
1.253 +}
1.254 +
1.255 +static DBusGProxyManager *
1.256 +dbus_g_proxy_manager_ref (DBusGProxyManager *manager)
1.257 +{
1.258 + g_assert (manager != NULL);
1.259 + g_assert (manager->refcount > 0);
1.260 +
1.261 + LOCK_MANAGER (manager);
1.262 +
1.263 + manager->refcount += 1;
1.264 +
1.265 + UNLOCK_MANAGER (manager);
1.266 +
1.267 + return manager;
1.268 +}
1.269 +
1.270 +static void
1.271 +dbus_g_proxy_manager_unref (DBusGProxyManager *manager)
1.272 +{
1.273 + g_assert (manager != NULL);
1.274 + g_assert (manager->refcount > 0);
1.275 +
1.276 + LOCK_MANAGER (manager);
1.277 + manager->refcount -= 1;
1.278 + if (manager->refcount == 0)
1.279 + {
1.280 + UNLOCK_MANAGER (manager);
1.281 +
1.282 + if (manager->bus_proxy)
1.283 + g_object_unref (manager->bus_proxy);
1.284 +
1.285 + if (manager->proxy_lists)
1.286 + {
1.287 + /* can't have any proxies left since they hold
1.288 + * a reference to the proxy manager.
1.289 + */
1.290 + g_assert (g_hash_table_size (manager->proxy_lists) == 0);
1.291 +
1.292 + g_hash_table_destroy (manager->proxy_lists);
1.293 + manager->proxy_lists = NULL;
1.294 +
1.295 + }
1.296 +
1.297 + if (manager->owner_names)
1.298 + {
1.299 + /* Since we destroyed all proxies, none can be tracking
1.300 + * name owners
1.301 + */
1.302 + g_assert (g_hash_table_size (manager->owner_names) == 0);
1.303 +
1.304 + g_hash_table_destroy (manager->owner_names);
1.305 + manager->owner_names = NULL;
1.306 + }
1.307 +
1.308 + g_assert (manager->unassociated_proxies == NULL);
1.309 +
1.310 + g_static_mutex_free (&manager->lock);
1.311 +
1.312 + g_static_mutex_lock (&connection_g_proxy_lock);
1.313 +
1.314 + dbus_connection_remove_filter (manager->connection, dbus_g_proxy_manager_filter,
1.315 + manager);
1.316 +
1.317 + dbus_connection_set_data (manager->connection,
1.318 + g_proxy_manager_slot,
1.319 + NULL, NULL);
1.320 +
1.321 + g_static_mutex_unlock (&connection_g_proxy_lock);
1.322 +
1.323 + dbus_connection_unref (manager->connection);
1.324 + g_free (manager);
1.325 +
1.326 + dbus_connection_free_data_slot (&g_proxy_manager_slot);
1.327 + }
1.328 + else
1.329 + {
1.330 + UNLOCK_MANAGER (manager);
1.331 + }
1.332 +}
1.333 +
1.334 +static guint
1.335 +tristring_hash (gconstpointer key)
1.336 +{
1.337 + const char *p = key;
1.338 + guint h = *p;
1.339 +
1.340 + if (h)
1.341 + {
1.342 + for (p += 1; *p != '\0'; p++)
1.343 + h = (h << 5) - h + *p;
1.344 + }
1.345 +
1.346 + /* skip nul and do the next substring */
1.347 + for (p += 1; *p != '\0'; p++)
1.348 + h = (h << 5) - h + *p;
1.349 +
1.350 + /* skip nul again and another substring */
1.351 + for (p += 1; *p != '\0'; p++)
1.352 + h = (h << 5) - h + *p;
1.353 +
1.354 + return h;
1.355 +}
1.356 +
1.357 +static gboolean
1.358 +strequal_len (const char *a,
1.359 + const char *b,
1.360 + size_t *lenp)
1.361 +{
1.362 + size_t a_len;
1.363 + size_t b_len;
1.364 +
1.365 + a_len = strlen (a);
1.366 + b_len = strlen (b);
1.367 +
1.368 + if (a_len != b_len)
1.369 + return FALSE;
1.370 +
1.371 + if (memcmp (a, b, a_len) != 0)
1.372 + return FALSE;
1.373 +
1.374 + *lenp = a_len;
1.375 +
1.376 + return TRUE;
1.377 +}
1.378 +
1.379 +static gboolean
1.380 +tristring_equal (gconstpointer a,
1.381 + gconstpointer b)
1.382 +{
1.383 + const char *ap = a;
1.384 + const char *bp = b;
1.385 + size_t len;
1.386 +
1.387 + if (!strequal_len (ap, bp, &len))
1.388 + return FALSE;
1.389 +
1.390 + ap += len + 1;
1.391 + bp += len + 1;
1.392 +
1.393 + if (!strequal_len (ap, bp, &len))
1.394 + return FALSE;
1.395 +
1.396 + ap += len + 1;
1.397 + bp += len + 1;
1.398 +
1.399 + if (strcmp (ap, bp) != 0)
1.400 + return FALSE;
1.401 +
1.402 + return TRUE;
1.403 +}
1.404 +
1.405 +static char*
1.406 +tristring_alloc_from_strings (size_t padding_before,
1.407 + const char *name,
1.408 + const char *path,
1.409 + const char *interface)
1.410 +{
1.411 + size_t name_len, iface_len, path_len, len;
1.412 + char *tri;
1.413 +
1.414 + if (name)
1.415 + name_len = strlen (name);
1.416 + else
1.417 + name_len = 0;
1.418 +
1.419 + path_len = strlen (path);
1.420 +
1.421 + iface_len = strlen (interface);
1.422 +
1.423 + tri = g_malloc (padding_before + name_len + path_len + iface_len + 3);
1.424 +
1.425 + len = padding_before;
1.426 +
1.427 + if (name)
1.428 + memcpy (&tri[len], name, name_len);
1.429 +
1.430 + len += name_len;
1.431 + tri[len] = '\0';
1.432 + len += 1;
1.433 +
1.434 + g_assert (len == (padding_before + name_len + 1));
1.435 +
1.436 + memcpy (&tri[len], path, path_len);
1.437 + len += path_len;
1.438 + tri[len] = '\0';
1.439 + len += 1;
1.440 +
1.441 + g_assert (len == (padding_before + name_len + path_len + 2));
1.442 +
1.443 + memcpy (&tri[len], interface, iface_len);
1.444 + len += iface_len;
1.445 + tri[len] = '\0';
1.446 + len += 1;
1.447 +
1.448 + g_assert (len == (padding_before + name_len + path_len + iface_len + 3));
1.449 +
1.450 + return tri;
1.451 +}
1.452 +
1.453 +static char*
1.454 +tristring_from_proxy (DBusGProxy *proxy)
1.455 +{
1.456 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.457 +
1.458 + return tristring_alloc_from_strings (0,
1.459 + priv->name,
1.460 + priv->path,
1.461 + priv->interface);
1.462 +}
1.463 +
1.464 +static char*
1.465 +tristring_from_message (DBusMessage *message)
1.466 +{
1.467 + const char *path;
1.468 + const char *interface;
1.469 +
1.470 + path = dbus_message_get_path (message);
1.471 + interface = dbus_message_get_interface (message);
1.472 +
1.473 + g_assert (path);
1.474 + g_assert (interface);
1.475 +
1.476 + return tristring_alloc_from_strings (0,
1.477 + dbus_message_get_sender (message),
1.478 + path, interface);
1.479 +}
1.480 +
1.481 +static DBusGProxyList*
1.482 +g_proxy_list_new (DBusGProxy *first_proxy)
1.483 +{
1.484 + DBusGProxyList *list;
1.485 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(first_proxy);
1.486 +
1.487 + list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name),
1.488 + priv->name,
1.489 + priv->path,
1.490 + priv->interface);
1.491 + list->proxies = NULL;
1.492 +
1.493 + return list;
1.494 +}
1.495 +
1.496 +static void
1.497 +g_proxy_list_free (DBusGProxyList *list)
1.498 +{
1.499 + /* we don't hold a reference to the proxies in the list,
1.500 + * as they ref the GProxyManager
1.501 + */
1.502 + g_slist_free (list->proxies);
1.503 +
1.504 + g_free (list);
1.505 +}
1.506 +
1.507 +static char*
1.508 +g_proxy_get_match_rule (DBusGProxy *proxy)
1.509 +{
1.510 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.511 + /* FIXME Escaping is required here */
1.512 +
1.513 + if (priv->name)
1.514 + return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'",
1.515 + priv->name, priv->path, priv->interface);
1.516 + else
1.517 + return g_strdup_printf ("type='signal',path='%s',interface='%s'",
1.518 + priv->path, priv->interface);
1.519 +}
1.520 +
1.521 +typedef struct
1.522 +{
1.523 + char *name;
1.524 + guint refcount;
1.525 +} DBusGProxyNameOwnerInfo;
1.526 +
1.527 +static gint
1.528 +find_name_in_info (gconstpointer a, gconstpointer b)
1.529 +{
1.530 + const DBusGProxyNameOwnerInfo *info = a;
1.531 + const char *name = b;
1.532 +
1.533 + return strcmp (info->name, name);
1.534 +}
1.535 +
1.536 +typedef struct
1.537 +{
1.538 + const char *name;
1.539 + const char *owner;
1.540 + DBusGProxyNameOwnerInfo *info;
1.541 +} DBusGProxyNameOwnerForeachData;
1.542 +
1.543 +static void
1.544 +name_owner_foreach (gpointer key, gpointer val, gpointer data)
1.545 +{
1.546 + const char *owner;
1.547 + DBusGProxyNameOwnerForeachData *foreach_data;
1.548 + GSList *names;
1.549 + GSList *link;
1.550 +
1.551 + owner = key;
1.552 + names = val;
1.553 + foreach_data = data;
1.554 +
1.555 + if (foreach_data->owner != NULL)
1.556 + return;
1.557 +
1.558 + g_assert (foreach_data->info == NULL);
1.559 +
1.560 + link = g_slist_find_custom (names, foreach_data->name, find_name_in_info);
1.561 + if (link)
1.562 + {
1.563 + foreach_data->owner = owner;
1.564 + foreach_data->info = link->data;
1.565 + }
1.566 +}
1.567 +
1.568 +static gboolean
1.569 +dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager *manager,
1.570 + const char *name,
1.571 + DBusGProxyNameOwnerInfo **info,
1.572 + const char **owner)
1.573 +{
1.574 + DBusGProxyNameOwnerForeachData foreach_data;
1.575 +
1.576 + foreach_data.name = name;
1.577 + foreach_data.owner = NULL;
1.578 + foreach_data.info = NULL;
1.579 +
1.580 + g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data);
1.581 +
1.582 + *info = foreach_data.info;
1.583 + *owner = foreach_data.owner;
1.584 + return *info != NULL;
1.585 +}
1.586 +
1.587 +static void
1.588 +insert_nameinfo (DBusGProxyManager *manager,
1.589 + const char *owner,
1.590 + DBusGProxyNameOwnerInfo *info)
1.591 +{
1.592 + GSList *names;
1.593 + gboolean insert;
1.594 +
1.595 + names = g_hash_table_lookup (manager->owner_names, owner);
1.596 +
1.597 + /* Only need to g_hash_table_insert the first time */
1.598 + insert = (names == NULL);
1.599 +
1.600 + names = g_slist_append (names, info);
1.601 +
1.602 + if (insert)
1.603 + g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
1.604 +}
1.605 +
1.606 +static void
1.607 +dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager *manager,
1.608 + const char *owner,
1.609 + const char *name)
1.610 +{
1.611 + GSList *names;
1.612 + GSList *link;
1.613 + DBusGProxyNameOwnerInfo *nameinfo;
1.614 +
1.615 + names = g_hash_table_lookup (manager->owner_names, owner);
1.616 + link = g_slist_find_custom (names, name, find_name_in_info);
1.617 +
1.618 + if (!link)
1.619 + {
1.620 + nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1);
1.621 + nameinfo->name = g_strdup (name);
1.622 + nameinfo->refcount = 1;
1.623 +
1.624 + insert_nameinfo (manager, owner, nameinfo);
1.625 + }
1.626 + else
1.627 + {
1.628 + nameinfo = link->data;
1.629 + nameinfo->refcount++;
1.630 + }
1.631 +}
1.632 +
1.633 +static void
1.634 +dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager *manager,
1.635 + const char *name)
1.636 +{
1.637 + DBusGProxyNameOwnerInfo *info;
1.638 + const char *owner;
1.639 + gboolean ret;
1.640 +
1.641 + ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner);
1.642 + g_assert (ret);
1.643 + g_assert (info != NULL);
1.644 + g_assert (owner != NULL);
1.645 +
1.646 + info->refcount--;
1.647 + if (info->refcount == 0)
1.648 + {
1.649 + GSList *names;
1.650 + GSList *link;
1.651 +
1.652 + names = g_hash_table_lookup (manager->owner_names, owner);
1.653 + link = g_slist_find_custom (names, name, find_name_in_info);
1.654 + names = g_slist_delete_link (names, link);
1.655 + if (names != NULL)
1.656 + g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
1.657 + else
1.658 + g_hash_table_remove (manager->owner_names, owner);
1.659 +
1.660 + g_free (info->name);
1.661 + g_free (info);
1.662 + }
1.663 +}
1.664 +
1.665 +typedef struct
1.666 +{
1.667 + const char *name;
1.668 + GSList *destroyed;
1.669 +} DBusGProxyUnassociateData;
1.670 +
1.671 +static void
1.672 +unassociate_proxies (gpointer key, gpointer val, gpointer user_data)
1.673 +{
1.674 + DBusGProxyList *list;
1.675 + const char *name;
1.676 + GSList *tmp;
1.677 + DBusGProxyUnassociateData *data;
1.678 +
1.679 + list = val;
1.680 + data = user_data;
1.681 + name = data->name;
1.682 +
1.683 + for (tmp = list->proxies; tmp; tmp = tmp->next)
1.684 + {
1.685 + DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
1.686 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.687 + DBusGProxyManager *manager;
1.688 +
1.689 + manager = priv->manager;
1.690 +
1.691 + if (!strcmp (priv->name, name))
1.692 + {
1.693 + if (!priv->for_owner)
1.694 + {
1.695 + g_assert (priv->associated);
1.696 + g_assert (priv->name_call == NULL);
1.697 +
1.698 + priv->associated = FALSE;
1.699 + manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy);
1.700 + }
1.701 + else
1.702 + {
1.703 + data->destroyed = g_slist_prepend (data->destroyed, proxy);
1.704 + /* make contents of list into weak pointers in case the objects
1.705 + * unref each other when disposing */
1.706 + g_object_add_weak_pointer (G_OBJECT (proxy),
1.707 + &(data->destroyed->data));
1.708 + }
1.709 + }
1.710 + }
1.711 +}
1.712 +
1.713 +static void
1.714 +dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager *manager,
1.715 + const char *name,
1.716 + const char *prev_owner,
1.717 + const char *new_owner)
1.718 +{
1.719 + GSList *names;
1.720 +
1.721 + if (prev_owner[0] == '\0')
1.722 + {
1.723 + GSList *tmp;
1.724 + GSList *removed;
1.725 +
1.726 + /* We have a new service, look at unassociated proxies */
1.727 +
1.728 + removed = NULL;
1.729 +
1.730 + for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next)
1.731 + {
1.732 + DBusGProxy *proxy = tmp->data;
1.733 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.734 +
1.735 + if (!strcmp (priv->name, name))
1.736 + {
1.737 + removed = g_slist_prepend (removed, tmp);
1.738 +
1.739 + dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name);
1.740 + priv->associated = TRUE;
1.741 + }
1.742 + }
1.743 +
1.744 + for (tmp = removed; tmp; tmp = tmp->next)
1.745 + manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data);
1.746 + g_slist_free (removed);
1.747 + }
1.748 + else
1.749 + {
1.750 + DBusGProxyNameOwnerInfo *info;
1.751 + GSList *link;
1.752 +
1.753 + /* Name owner changed or deleted */
1.754 +
1.755 + names = g_hash_table_lookup (manager->owner_names, prev_owner);
1.756 +
1.757 + info = NULL;
1.758 + if (names != NULL)
1.759 + {
1.760 + link = g_slist_find_custom (names, name, find_name_in_info);
1.761 +
1.762 + if (link != NULL)
1.763 + {
1.764 + info = link->data;
1.765 +
1.766 + names = g_slist_delete_link (names, link);
1.767 +
1.768 + if (names == NULL)
1.769 + g_hash_table_remove (manager->owner_names, prev_owner);
1.770 + }
1.771 + }
1.772 +
1.773 + if (new_owner[0] == '\0')
1.774 + {
1.775 + DBusGProxyUnassociateData data;
1.776 + GSList *tmp;
1.777 +
1.778 + data.name = name;
1.779 + data.destroyed = NULL;
1.780 +
1.781 + /* A service went away, we need to unassociate proxies */
1.782 + g_hash_table_foreach (manager->proxy_lists,
1.783 + unassociate_proxies, &data);
1.784 +
1.785 + UNLOCK_MANAGER (manager);
1.786 +
1.787 + /* the destroyed list's data pointers are weak pointers, so that we
1.788 + * don't end up calling destroy on proxies which have already been
1.789 + * freed up as a result of other ones being destroyed */
1.790 + for (tmp = data.destroyed; tmp; tmp = tmp->next)
1.791 + if (tmp->data != NULL)
1.792 + {
1.793 + g_object_remove_weak_pointer (G_OBJECT (tmp->data),
1.794 + &(tmp->data));
1.795 + dbus_g_proxy_destroy (tmp->data);
1.796 + }
1.797 + g_slist_free (data.destroyed);
1.798 +
1.799 + LOCK_MANAGER (manager);
1.800 +
1.801 + if (info)
1.802 + {
1.803 + g_free (info->name);
1.804 + g_free (info);
1.805 + }
1.806 + }
1.807 + else if (info)
1.808 + {
1.809 + insert_nameinfo (manager, new_owner, info);
1.810 + }
1.811 + }
1.812 +}
1.813 +
1.814 +static void
1.815 +got_name_owner_cb (DBusGProxy *bus_proxy,
1.816 + DBusGProxyCall *call,
1.817 + void *user_data)
1.818 +{
1.819 + DBusGProxy *proxy = user_data;
1.820 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.821 + GError *error;
1.822 + char *owner;
1.823 +
1.824 + error = NULL;
1.825 + owner = NULL;
1.826 +
1.827 + LOCK_MANAGER (priv->manager);
1.828 +
1.829 + if (!dbus_g_proxy_end_call (bus_proxy, call, &error,
1.830 + G_TYPE_STRING, &owner,
1.831 + G_TYPE_INVALID))
1.832 + {
1.833 + if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
1.834 + {
1.835 + priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy);
1.836 + }
1.837 + else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
1.838 + g_warning ("Couldn't get name owner (%s): %s",
1.839 + dbus_g_error_get_name (error),
1.840 + error->message);
1.841 + else
1.842 + g_warning ("Couldn't get name owner (code %d): %s",
1.843 + error->code, error->message);
1.844 + g_clear_error (&error);
1.845 + goto out;
1.846 + }
1.847 + else
1.848 + {
1.849 + dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name);
1.850 + priv->associated = TRUE;
1.851 + }
1.852 +
1.853 + out:
1.854 + priv->name_call = NULL;
1.855 + UNLOCK_MANAGER (priv->manager);
1.856 + g_free (owner);
1.857 +}
1.858 +
1.859 +static char *
1.860 +get_name_owner (DBusConnection *connection,
1.861 + const char *name,
1.862 + GError **error)
1.863 +{
1.864 + DBusError derror;
1.865 + DBusMessage *request, *reply;
1.866 + char *base_name;
1.867 +
1.868 + dbus_error_init (&derror);
1.869 +
1.870 + base_name = NULL;
1.871 + reply = NULL;
1.872 +
1.873 + request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1.874 + DBUS_PATH_DBUS,
1.875 + DBUS_INTERFACE_DBUS,
1.876 + "GetNameOwner");
1.877 + if (request == NULL)
1.878 + g_error ("Out of memory");
1.879 +
1.880 + if (!dbus_message_append_args (request,
1.881 + DBUS_TYPE_STRING, &name,
1.882 + DBUS_TYPE_INVALID))
1.883 + g_error ("Out of memory");
1.884 +
1.885 + reply =
1.886 + dbus_connection_send_with_reply_and_block (connection,
1.887 + request,
1.888 + 2000, &derror);
1.889 + if (reply == NULL)
1.890 + goto error;
1.891 +
1.892 + if (dbus_set_error_from_message (&derror, reply))
1.893 + goto error;
1.894 +
1.895 + if (!dbus_message_get_args (reply, &derror,
1.896 + DBUS_TYPE_STRING, &base_name,
1.897 + DBUS_TYPE_INVALID))
1.898 + goto error;
1.899 +
1.900 + base_name = g_strdup (base_name);
1.901 + goto out;
1.902 +
1.903 + error:
1.904 + g_assert (dbus_error_is_set (&derror));
1.905 + dbus_set_g_error (error, &derror);
1.906 + dbus_error_free (&derror);
1.907 +
1.908 + out:
1.909 + if (request)
1.910 + dbus_message_unref (request);
1.911 + if (reply)
1.912 + dbus_message_unref (reply);
1.913 +
1.914 + return base_name;
1.915 +}
1.916 +
1.917 +
1.918 +static void
1.919 +dbus_g_proxy_manager_register (DBusGProxyManager *manager,
1.920 + DBusGProxy *proxy)
1.921 +{
1.922 + DBusGProxyList *list;
1.923 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.924 +
1.925 + LOCK_MANAGER (manager);
1.926 +
1.927 + if (manager->proxy_lists == NULL)
1.928 + {
1.929 + g_assert (manager->owner_names == NULL);
1.930 +
1.931 + list = NULL;
1.932 + manager->proxy_lists = g_hash_table_new_full (tristring_hash,
1.933 + tristring_equal,
1.934 + NULL,
1.935 + (GFreeFunc) g_proxy_list_free);
1.936 + manager->owner_names = g_hash_table_new_full (g_str_hash,
1.937 + g_str_equal,
1.938 + g_free,
1.939 + NULL);
1.940 + /* FIXME - for now we listen for all NameOwnerChanged; once
1.941 + * Anders' detail patch lands we should add individual rules
1.942 + */
1.943 + dbus_bus_add_match (manager->connection,
1.944 + "type='signal',sender='" DBUS_SERVICE_DBUS
1.945 + "',path='" DBUS_PATH_DBUS
1.946 + "',interface='" DBUS_INTERFACE_DBUS
1.947 + "',member='NameOwnerChanged'",
1.948 + NULL);
1.949 + }
1.950 + else
1.951 + {
1.952 + char *tri;
1.953 +
1.954 + tri = tristring_from_proxy (proxy);
1.955 +
1.956 + list = g_hash_table_lookup (manager->proxy_lists, tri);
1.957 +
1.958 + g_free (tri);
1.959 + }
1.960 +
1.961 + if (list == NULL)
1.962 + {
1.963 + list = g_proxy_list_new (proxy);
1.964 +
1.965 + g_hash_table_replace (manager->proxy_lists,
1.966 + list->name, list);
1.967 + }
1.968 +
1.969 + if (list->proxies == NULL && priv->name)
1.970 + {
1.971 + /* We have to add the match rule to the server,
1.972 + * but only if the server is a message bus,
1.973 + * not if it's a peer.
1.974 + */
1.975 + char *rule;
1.976 +
1.977 + rule = g_proxy_get_match_rule (proxy);
1.978 +
1.979 + /* We don't check for errors; it's not like anyone would handle them, and
1.980 + * we don't want a round trip here.
1.981 + */
1.982 + dbus_bus_add_match (manager->connection,
1.983 + rule, NULL);
1.984 +
1.985 + g_free (rule);
1.986 + }
1.987 +
1.988 + g_assert (g_slist_find (list->proxies, proxy) == NULL);
1.989 +
1.990 + list->proxies = g_slist_prepend (list->proxies, proxy);
1.991 +
1.992 + if (!priv->for_owner)
1.993 + {
1.994 + const char *owner;
1.995 + DBusGProxyNameOwnerInfo *info;
1.996 +
1.997 + if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner))
1.998 + {
1.999 + priv->name_call = manager_begin_bus_call (manager, "GetNameOwner",
1.1000 + got_name_owner_cb,
1.1001 + proxy, NULL,
1.1002 + G_TYPE_STRING,
1.1003 + priv->name,
1.1004 + G_TYPE_INVALID);
1.1005 +
1.1006 + priv->associated = FALSE;
1.1007 + }
1.1008 + else
1.1009 + {
1.1010 + info->refcount++;
1.1011 + priv->associated = TRUE;
1.1012 + }
1.1013 + }
1.1014 +
1.1015 + UNLOCK_MANAGER (manager);
1.1016 +}
1.1017 +
1.1018 +static void
1.1019 +dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
1.1020 + DBusGProxy *proxy)
1.1021 +{
1.1022 + DBusGProxyList *list;
1.1023 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1024 + char *tri;
1.1025 +
1.1026 + LOCK_MANAGER (manager);
1.1027 +
1.1028 +#ifndef G_DISABLE_CHECKS
1.1029 + if (manager->proxy_lists == NULL)
1.1030 + {
1.1031 + g_warning ("Trying to unregister a proxy but there aren't any registered");
1.1032 + return;
1.1033 + }
1.1034 +#endif
1.1035 +
1.1036 + tri = tristring_from_proxy (proxy);
1.1037 +
1.1038 + list = g_hash_table_lookup (manager->proxy_lists, tri);
1.1039 +
1.1040 +#ifndef G_DISABLE_CHECKS
1.1041 + if (list == NULL)
1.1042 + {
1.1043 + g_warning ("Trying to unregister a proxy but it isn't registered");
1.1044 + return;
1.1045 + }
1.1046 +#endif
1.1047 +
1.1048 + g_assert (g_slist_find (list->proxies, proxy) != NULL);
1.1049 +
1.1050 + list->proxies = g_slist_remove (list->proxies, proxy);
1.1051 +
1.1052 + g_assert (g_slist_find (list->proxies, proxy) == NULL);
1.1053 +
1.1054 + if (!priv->for_owner)
1.1055 + {
1.1056 + if (!priv->associated)
1.1057 + {
1.1058 + GSList *link;
1.1059 +
1.1060 + if (priv->name_call != 0)
1.1061 + {
1.1062 + dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
1.1063 + priv->name_call = 0;
1.1064 + }
1.1065 + else
1.1066 + {
1.1067 + link = g_slist_find (manager->unassociated_proxies, proxy);
1.1068 + g_assert (link != NULL);
1.1069 +
1.1070 + manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link);
1.1071 + }
1.1072 + }
1.1073 + else
1.1074 + {
1.1075 + g_assert (priv->name_call == 0);
1.1076 +
1.1077 + dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name);
1.1078 + }
1.1079 + }
1.1080 +
1.1081 + if (list->proxies == NULL)
1.1082 + {
1.1083 + char *rule;
1.1084 + g_hash_table_remove (manager->proxy_lists,
1.1085 + tri);
1.1086 + list = NULL;
1.1087 +
1.1088 + rule = g_proxy_get_match_rule (proxy);
1.1089 + dbus_bus_remove_match (manager->connection,
1.1090 + rule, NULL);
1.1091 + g_free (rule);
1.1092 + }
1.1093 +
1.1094 + if (g_hash_table_size (manager->proxy_lists) == 0)
1.1095 + {
1.1096 + g_hash_table_destroy (manager->proxy_lists);
1.1097 + manager->proxy_lists = NULL;
1.1098 + }
1.1099 +
1.1100 + g_free (tri);
1.1101 +
1.1102 + UNLOCK_MANAGER (manager);
1.1103 +}
1.1104 +
1.1105 +static void
1.1106 +list_proxies_foreach (gpointer key,
1.1107 + gpointer value,
1.1108 + gpointer user_data)
1.1109 +{
1.1110 + DBusGProxyList *list;
1.1111 + GSList **ret;
1.1112 + GSList *tmp;
1.1113 +
1.1114 + list = value;
1.1115 + ret = user_data;
1.1116 +
1.1117 + tmp = list->proxies;
1.1118 + while (tmp != NULL)
1.1119 + {
1.1120 + DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
1.1121 +
1.1122 + g_object_ref (proxy);
1.1123 + *ret = g_slist_prepend (*ret, proxy);
1.1124 +
1.1125 + tmp = tmp->next;
1.1126 + }
1.1127 +}
1.1128 +
1.1129 +static GSList*
1.1130 +dbus_g_proxy_manager_list_all (DBusGProxyManager *manager)
1.1131 +{
1.1132 + GSList *ret;
1.1133 +
1.1134 + ret = NULL;
1.1135 +
1.1136 + if (manager->proxy_lists)
1.1137 + {
1.1138 + g_hash_table_foreach (manager->proxy_lists,
1.1139 + list_proxies_foreach,
1.1140 + &ret);
1.1141 + }
1.1142 +
1.1143 + return ret;
1.1144 +}
1.1145 +
1.1146 +static DBusHandlerResult
1.1147 +dbus_g_proxy_manager_filter (DBusConnection *connection,
1.1148 + DBusMessage *message,
1.1149 + void *user_data)
1.1150 +{
1.1151 + DBusGProxyManager *manager;
1.1152 +
1.1153 + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
1.1154 + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1.1155 +
1.1156 + manager = user_data;
1.1157 +
1.1158 + dbus_g_proxy_manager_ref (manager);
1.1159 +
1.1160 + LOCK_MANAGER (manager);
1.1161 +
1.1162 + if (dbus_message_is_signal (message,
1.1163 + DBUS_INTERFACE_LOCAL,
1.1164 + "Disconnected"))
1.1165 + {
1.1166 + /* Destroy all the proxies, quite possibly resulting in unreferencing
1.1167 + * the proxy manager and the connection as well.
1.1168 + */
1.1169 + GSList *all;
1.1170 + GSList *tmp;
1.1171 +
1.1172 + all = dbus_g_proxy_manager_list_all (manager);
1.1173 +
1.1174 + tmp = all;
1.1175 + while (tmp != NULL)
1.1176 + {
1.1177 + DBusGProxy *proxy;
1.1178 +
1.1179 + proxy = DBUS_G_PROXY (tmp->data);
1.1180 +
1.1181 + UNLOCK_MANAGER (manager);
1.1182 + dbus_g_proxy_destroy (proxy);
1.1183 + g_object_unref (G_OBJECT (proxy));
1.1184 + LOCK_MANAGER (manager);
1.1185 +
1.1186 + tmp = tmp->next;
1.1187 + }
1.1188 +
1.1189 + g_slist_free (all);
1.1190 +
1.1191 +#ifndef G_DISABLE_CHECKS
1.1192 + if (manager->proxy_lists != NULL)
1.1193 + 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.");
1.1194 +#endif
1.1195 + }
1.1196 + else
1.1197 + {
1.1198 + char *tri;
1.1199 + GSList *full_list;
1.1200 + GSList *owned_names;
1.1201 + GSList *tmp;
1.1202 + const char *sender;
1.1203 +
1.1204 + /* First we handle NameOwnerChanged internally */
1.1205 + if (dbus_message_is_signal (message,
1.1206 + DBUS_INTERFACE_DBUS,
1.1207 + "NameOwnerChanged"))
1.1208 + {
1.1209 + const char *name;
1.1210 + const char *prev_owner;
1.1211 + const char *new_owner;
1.1212 + DBusError derr;
1.1213 +
1.1214 + dbus_error_init (&derr);
1.1215 + if (!dbus_message_get_args (message,
1.1216 + &derr,
1.1217 + DBUS_TYPE_STRING,
1.1218 + &name,
1.1219 + DBUS_TYPE_STRING,
1.1220 + &prev_owner,
1.1221 + DBUS_TYPE_STRING,
1.1222 + &new_owner,
1.1223 + DBUS_TYPE_INVALID))
1.1224 + {
1.1225 + /* Ignore this error */
1.1226 + dbus_error_free (&derr);
1.1227 + }
1.1228 + else if (manager->owner_names != NULL)
1.1229 + {
1.1230 + dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner);
1.1231 + }
1.1232 + }
1.1233 +
1.1234 + sender = dbus_message_get_sender (message);
1.1235 +
1.1236 + /* dbus spec requires these, libdbus validates */
1.1237 + g_assert (dbus_message_get_path (message) != NULL);
1.1238 + g_assert (dbus_message_get_interface (message) != NULL);
1.1239 + g_assert (dbus_message_get_member (message) != NULL);
1.1240 +
1.1241 + tri = tristring_from_message (message);
1.1242 +
1.1243 + if (manager->proxy_lists)
1.1244 + {
1.1245 + DBusGProxyList *owner_list;
1.1246 + owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
1.1247 + if (owner_list)
1.1248 + full_list = g_slist_copy (owner_list->proxies);
1.1249 + else
1.1250 + full_list = NULL;
1.1251 + }
1.1252 + else
1.1253 + full_list = NULL;
1.1254 +
1.1255 + g_free (tri);
1.1256 +
1.1257 + if (manager->owner_names && sender)
1.1258 + {
1.1259 + owned_names = g_hash_table_lookup (manager->owner_names, sender);
1.1260 + for (tmp = owned_names; tmp; tmp = tmp->next)
1.1261 + {
1.1262 + DBusGProxyList *owner_list;
1.1263 + DBusGProxyNameOwnerInfo *nameinfo;
1.1264 +
1.1265 + nameinfo = tmp->data;
1.1266 + g_assert (nameinfo->refcount > 0);
1.1267 + tri = tristring_alloc_from_strings (0, nameinfo->name,
1.1268 + dbus_message_get_path (message),
1.1269 + dbus_message_get_interface (message));
1.1270 +
1.1271 + owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
1.1272 + if (owner_list != NULL)
1.1273 + full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies));
1.1274 + g_free (tri);
1.1275 + }
1.1276 + }
1.1277 +
1.1278 +#if 0
1.1279 + g_print ("proxy got %s,%s,%s = list %p\n",
1.1280 + tri,
1.1281 + tri + strlen (tri) + 1,
1.1282 + tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
1.1283 + list);
1.1284 +#endif
1.1285 +
1.1286 + /* Emit the signal */
1.1287 +
1.1288 + g_slist_foreach (full_list, (GFunc) g_object_ref, NULL);
1.1289 +
1.1290 + for (tmp = full_list; tmp; tmp = tmp->next)
1.1291 + {
1.1292 + DBusGProxy *proxy;
1.1293 +
1.1294 + proxy = DBUS_G_PROXY (tmp->data);
1.1295 +
1.1296 + UNLOCK_MANAGER (manager);
1.1297 + dbus_g_proxy_emit_remote_signal (proxy, message);
1.1298 + g_object_unref (G_OBJECT (proxy));
1.1299 + LOCK_MANAGER (manager);
1.1300 + }
1.1301 + g_slist_free (full_list);
1.1302 + }
1.1303 +
1.1304 + UNLOCK_MANAGER (manager);
1.1305 + dbus_g_proxy_manager_unref (manager);
1.1306 +
1.1307 + /* "Handling" signals doesn't make sense, they are for everyone
1.1308 + * who cares
1.1309 + */
1.1310 + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1.1311 +}
1.1312 +
1.1313 +
1.1314 +
1.1315 +/* ---------- DBusGProxy -------------- */
1.1316 +#define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL)
1.1317 +
1.1318 +static void
1.1319 +marshal_dbus_message_to_g_marshaller (GClosure *closure,
1.1320 + GValue *return_value,
1.1321 + guint n_param_values,
1.1322 + const GValue *param_values,
1.1323 + gpointer invocation_hint,
1.1324 + gpointer marshal_data);
1.1325 +enum
1.1326 +{
1.1327 + PROP_0,
1.1328 + PROP_NAME,
1.1329 + PROP_PATH,
1.1330 + PROP_INTERFACE,
1.1331 + PROP_CONNECTION
1.1332 +};
1.1333 +
1.1334 +enum
1.1335 +{
1.1336 + DESTROY,
1.1337 + RECEIVED,
1.1338 + LAST_SIGNAL
1.1339 +};
1.1340 +
1.1341 +#if EMULATOR
1.1342 +GET_STATIC_VAR_FROM_TLS(parent_class,dbus_gproxy,void* )
1.1343 +#define parent_class (*GET_DBUS_WSD_VAR_NAME(parent_class,dbus_gproxy,s)())
1.1344 +
1.1345 +GET_STATIC_ARRAY_FROM_TLS(signals,dbus_gproxy,guint )
1.1346 +#define signals (GET_DBUS_WSD_VAR_NAME(signals,dbus_gproxy,s)())
1.1347 +
1.1348 +#else
1.1349 +static void *parent_class;
1.1350 +static guint signals[LAST_SIGNAL] = { 0 };
1.1351 +
1.1352 +#endif
1.1353 +
1.1354 +
1.1355 +static void
1.1356 +dbus_g_proxy_init (DBusGProxy *proxy)
1.1357 +{
1.1358 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1359 +
1.1360 + g_datalist_init (&priv->signal_signatures);
1.1361 + priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
1.1362 + (GDestroyNotify) dbus_pending_call_unref);
1.1363 + priv->name_call = 0;
1.1364 + priv->associated = FALSE;
1.1365 +}
1.1366 +
1.1367 +static GObject *
1.1368 +dbus_g_proxy_constructor (GType type,
1.1369 + guint n_construct_properties,
1.1370 + GObjectConstructParam *construct_properties)
1.1371 +{
1.1372 + DBusGProxy *proxy;
1.1373 + DBusGProxyClass *klass;
1.1374 + GObjectClass *parent_class;
1.1375 + DBusGProxyPrivate *priv;
1.1376 +
1.1377 + klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
1.1378 +
1.1379 + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
1.1380 +
1.1381 + proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
1.1382 + construct_properties));
1.1383 +
1.1384 + priv = DBUS_G_PROXY_GET_PRIVATE (proxy);
1.1385 +
1.1386 + /* if these assertions fail, a deriving class has not set our required
1.1387 + * parameters - our own public constructors do return_if_fail checks
1.1388 + * on these parameters being provided. unfortunately we can't assert
1.1389 + * for manager because it's allowed to be NULL when tha mangager is
1.1390 + * setting up a bus proxy for its own calls */
1.1391 + g_assert (priv->path != NULL);
1.1392 + g_assert (priv->interface != NULL);
1.1393 +
1.1394 + if (priv->manager != NULL)
1.1395 + {
1.1396 + dbus_g_proxy_manager_register (priv->manager, proxy);
1.1397 + }
1.1398 +
1.1399 + return G_OBJECT (proxy);
1.1400 +}
1.1401 +
1.1402 +static void
1.1403 +dbus_g_proxy_class_init (DBusGProxyClass *klass)
1.1404 +{
1.1405 + GObjectClass *object_class = G_OBJECT_CLASS (klass);
1.1406 +
1.1407 + parent_class = g_type_class_peek_parent (klass);
1.1408 +
1.1409 + g_type_class_add_private (klass, sizeof (DBusGProxyPrivate));
1.1410 +
1.1411 + object_class->set_property = dbus_g_proxy_set_property;
1.1412 + object_class->get_property = dbus_g_proxy_get_property;
1.1413 +
1.1414 + g_object_class_install_property (object_class,
1.1415 + PROP_NAME,
1.1416 + g_param_spec_string ("name",
1.1417 + "name",
1.1418 + "name",
1.1419 + NULL,
1.1420 + // #ifdef WINSCW
1.1421 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1.1422 + // #else
1.1423 + // (GParamFlags)11)); // ARM complaining about enums mixing
1.1424 + // #endif
1.1425 +
1.1426 + g_object_class_install_property (object_class,
1.1427 + PROP_PATH,
1.1428 + g_param_spec_string ("path",
1.1429 + "path",
1.1430 + "path",
1.1431 + NULL,
1.1432 + // #ifdef WINSCW
1.1433 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1.1434 + // #else
1.1435 + // (GParamFlags)11)); // ARM complaining about enums mixing
1.1436 + // #endif
1.1437 +
1.1438 + g_object_class_install_property (object_class,
1.1439 + PROP_INTERFACE,
1.1440 + g_param_spec_string ("interface",
1.1441 + "interface",
1.1442 + "interface",
1.1443 + NULL,
1.1444 + // #ifdef WINSCW
1.1445 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1.1446 + // #else
1.1447 + // (GParamFlags)11)); // ARM complaining about enums mixing
1.1448 + // #endif
1.1449 +
1.1450 + g_object_class_install_property (object_class,
1.1451 + PROP_CONNECTION,
1.1452 + g_param_spec_boxed ("connection",
1.1453 + "connection",
1.1454 + "connection",
1.1455 + DBUS_TYPE_G_CONNECTION,
1.1456 + // #ifdef WINSCW
1.1457 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1.1458 + // #else
1.1459 + // (GParamFlags)11)); // ARM complaining about enums mixing
1.1460 + // #endif
1.1461 +
1.1462 + object_class->finalize = dbus_g_proxy_finalize;
1.1463 + object_class->dispose = dbus_g_proxy_dispose;
1.1464 + object_class->constructor = dbus_g_proxy_constructor;
1.1465 +
1.1466 + signals[DESTROY] =
1.1467 + g_signal_new ("destroy",
1.1468 + G_OBJECT_CLASS_TYPE (object_class),
1.1469 + G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
1.1470 + 0,
1.1471 + NULL, NULL,
1.1472 + g_cclosure_marshal_VOID__VOID,
1.1473 + G_TYPE_NONE, 0);
1.1474 +
1.1475 + signals[RECEIVED] =
1.1476 + g_signal_new ("received",
1.1477 + G_OBJECT_CLASS_TYPE (object_class),
1.1478 + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
1.1479 + 0,
1.1480 + NULL, NULL,
1.1481 + marshal_dbus_message_to_g_marshaller,
1.1482 + G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER);
1.1483 +}
1.1484 +
1.1485 +static void
1.1486 +cancel_pending_call (gpointer key, gpointer val, gpointer data)
1.1487 +{
1.1488 + DBusGProxyCall *call = key;
1.1489 + DBusGProxy *proxy = data;
1.1490 +
1.1491 + dbus_g_proxy_cancel_call (proxy, call);
1.1492 +}
1.1493 +
1.1494 +static void
1.1495 +dbus_g_proxy_dispose (GObject *object)
1.1496 +{
1.1497 + DBusGProxy *proxy = DBUS_G_PROXY (object);
1.1498 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1499 +
1.1500 + if (priv->pending_calls == NULL)
1.1501 + {
1.1502 + return;
1.1503 + }
1.1504 +
1.1505 + /* Cancel outgoing pending calls */
1.1506 + g_hash_table_foreach (priv->pending_calls, cancel_pending_call, proxy);
1.1507 + g_hash_table_destroy (priv->pending_calls);
1.1508 + priv->pending_calls = NULL;
1.1509 +
1.1510 + if (priv->manager && proxy != priv->manager->bus_proxy)
1.1511 + {
1.1512 + dbus_g_proxy_manager_unregister (priv->manager, proxy);
1.1513 + dbus_g_proxy_manager_unref (priv->manager);
1.1514 + }
1.1515 + priv->manager = NULL;
1.1516 +
1.1517 + g_datalist_clear (&priv->signal_signatures);
1.1518 +
1.1519 + g_signal_emit (object, signals[DESTROY], 0);
1.1520 +
1.1521 + G_OBJECT_CLASS (parent_class)->dispose (object);
1.1522 +}
1.1523 +
1.1524 +static void
1.1525 +dbus_g_proxy_finalize (GObject *object)
1.1526 +{
1.1527 + DBusGProxy *proxy = DBUS_G_PROXY (object);
1.1528 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1529 +
1.1530 + g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy));
1.1531 +
1.1532 + g_free (priv->name);
1.1533 + g_free (priv->path);
1.1534 + g_free (priv->interface);
1.1535 +
1.1536 + G_OBJECT_CLASS (parent_class)->finalize (object);
1.1537 +}
1.1538 +
1.1539 +static void
1.1540 +dbus_g_proxy_destroy (DBusGProxy *proxy)
1.1541 +{
1.1542 + /* FIXME do we need the GTK_IN_DESTRUCTION style flag
1.1543 + * from GtkObject?
1.1544 + */
1.1545 + g_object_run_dispose (G_OBJECT (proxy));
1.1546 +}
1.1547 +
1.1548 +static void
1.1549 +dbus_g_proxy_set_property (GObject *object,
1.1550 + guint prop_id,
1.1551 + const GValue *value,
1.1552 + GParamSpec *pspec)
1.1553 +{
1.1554 + DBusGProxy *proxy = DBUS_G_PROXY (object);
1.1555 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1556 + DBusGConnection *connection;
1.1557 +
1.1558 + switch (prop_id)
1.1559 + {
1.1560 + case PROP_NAME:
1.1561 + priv->name = g_strdup (g_value_get_string (value));
1.1562 + if (priv->name)
1.1563 + priv->for_owner = (priv->name[0] == ':');
1.1564 + else
1.1565 + priv->for_owner = TRUE;
1.1566 + break;
1.1567 + case PROP_PATH:
1.1568 + priv->path = g_strdup (g_value_get_string (value));
1.1569 + break;
1.1570 + case PROP_INTERFACE:
1.1571 + priv->interface = g_strdup (g_value_get_string (value));
1.1572 + break;
1.1573 + case PROP_CONNECTION:
1.1574 + connection = g_value_get_boxed (value);
1.1575 + if (connection != NULL)
1.1576 + {
1.1577 + priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
1.1578 + }
1.1579 + break;
1.1580 + default:
1.1581 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.1582 + break;
1.1583 + }
1.1584 +}
1.1585 +
1.1586 +static void
1.1587 +dbus_g_proxy_get_property (GObject *object,
1.1588 + guint prop_id,
1.1589 + GValue *value,
1.1590 + GParamSpec *pspec)
1.1591 +{
1.1592 + DBusGProxy *proxy = DBUS_G_PROXY (object);
1.1593 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1594 +
1.1595 + switch (prop_id)
1.1596 + {
1.1597 + case PROP_NAME:
1.1598 + g_value_set_string (value, priv->name);
1.1599 + break;
1.1600 + case PROP_PATH:
1.1601 + g_value_set_string (value, priv->path);
1.1602 + break;
1.1603 + case PROP_INTERFACE:
1.1604 + g_value_set_string (value, priv->interface);
1.1605 + break;
1.1606 + case PROP_CONNECTION:
1.1607 + g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection));
1.1608 + break;
1.1609 + default:
1.1610 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.1611 + break;
1.1612 + }
1.1613 +}
1.1614 +
1.1615 +/* this is to avoid people using g_signal_connect() directly,
1.1616 + * to avoid confusion with local signal names, and because
1.1617 + * of the horribly broken current setup (signals are added
1.1618 + * globally to all proxies)
1.1619 + */
1.1620 +static char*
1.1621 +create_signal_name (const char *interface,
1.1622 + const char *signal)
1.1623 +{
1.1624 + GString *str;
1.1625 + char *p;
1.1626 +
1.1627 + str = g_string_new (interface);
1.1628 +
1.1629 + g_string_append (str, "-");
1.1630 +
1.1631 + g_string_append (str, signal);
1.1632 +
1.1633 + /* GLib will silently barf on '.' in signal names */
1.1634 + p = str->str;
1.1635 + while (*p)
1.1636 + {
1.1637 + if (*p == '.')
1.1638 + *p = '-';
1.1639 + ++p;
1.1640 + }
1.1641 +
1.1642 + return g_string_free (str, FALSE);
1.1643 +}
1.1644 +
1.1645 +static void
1.1646 +marshal_dbus_message_to_g_marshaller (GClosure *closure,
1.1647 + GValue *return_value,
1.1648 + guint n_param_values,
1.1649 + const GValue *param_values,
1.1650 + gpointer invocation_hint,
1.1651 + gpointer marshal_data)
1.1652 +{
1.1653 + /* Incoming here we have three params, the instance (Proxy), the
1.1654 + * DBusMessage, the signature. We want to convert that to an
1.1655 + * expanded GValue array, then call an appropriate normal GLib
1.1656 + * marshaller.
1.1657 + */
1.1658 +#define MAX_SIGNATURE_ARGS 20
1.1659 + GValueArray *value_array;
1.1660 + GSignalCMarshaller c_marshaller;
1.1661 + DBusGProxy *proxy;
1.1662 + DBusMessage *message;
1.1663 + GArray *gsignature;
1.1664 + const GType *types;
1.1665 + DBusGProxyPrivate *priv;
1.1666 +
1.1667 + g_assert (n_param_values == 3);
1.1668 +
1.1669 + proxy = g_value_get_object (¶m_values[0]);
1.1670 + message = g_value_get_boxed (¶m_values[1]);
1.1671 + gsignature = g_value_get_pointer (¶m_values[2]);
1.1672 +
1.1673 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.1674 + g_return_if_fail (message != NULL);
1.1675 + g_return_if_fail (gsignature != NULL);
1.1676 +
1.1677 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1678 +
1.1679 + c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len,
1.1680 + (GType*) gsignature->data);
1.1681 +
1.1682 + g_return_if_fail (c_marshaller != NULL);
1.1683 +
1.1684 + {
1.1685 + DBusGValueMarshalCtx context;
1.1686 + context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
1.1687 + context.proxy = proxy;
1.1688 +
1.1689 + types = (const GType*) gsignature->data;
1.1690 + value_array = _dbus_gvalue_demarshal_message (&context, message,
1.1691 + gsignature->len, types, NULL);
1.1692 + }
1.1693 +
1.1694 + if (value_array == NULL)
1.1695 + return;
1.1696 +
1.1697 + g_value_array_prepend (value_array, NULL);
1.1698 + g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy));
1.1699 + g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy);
1.1700 +
1.1701 + (* c_marshaller) (closure, return_value, value_array->n_values,
1.1702 + value_array->values, invocation_hint, marshal_data);
1.1703 +
1.1704 + g_value_array_free (value_array);
1.1705 +}
1.1706 +
1.1707 +static void
1.1708 +dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
1.1709 + DBusMessage *message)
1.1710 +{
1.1711 + const char *interface;
1.1712 + const char *signal;
1.1713 + char *name;
1.1714 + GQuark q;
1.1715 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.1716 + GArray *msg_gsignature = NULL;
1.1717 +
1.1718 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.1719 +
1.1720 + interface = dbus_message_get_interface (message);
1.1721 + signal = dbus_message_get_member (message);
1.1722 +
1.1723 + g_assert (interface != NULL);
1.1724 + g_assert (signal != NULL);
1.1725 +
1.1726 + name = create_signal_name (interface, signal);
1.1727 +
1.1728 + /* If the quark isn't preexisting, there's no way there
1.1729 + * are any handlers connected. We don't want to create
1.1730 + * extra quarks for every possible signal.
1.1731 + */
1.1732 + q = g_quark_try_string (name);
1.1733 +
1.1734 + if (q != 0)
1.1735 + {
1.1736 + GArray *gsignature;
1.1737 + guint i;
1.1738 +
1.1739 + gsignature = g_datalist_id_get_data (&priv->signal_signatures, q);
1.1740 + if (gsignature == NULL)
1.1741 + goto out;
1.1742 +
1.1743 + msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message),
1.1744 + TRUE);
1.1745 + for (i = 0; i < gsignature->len; i++)
1.1746 + {
1.1747 + if (msg_gsignature->len == i
1.1748 + || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i))
1.1749 + goto mismatch;
1.1750 + }
1.1751 + if (msg_gsignature->len != i)
1.1752 + goto mismatch;
1.1753 +
1.1754 + g_signal_emit (proxy,
1.1755 + signals[RECEIVED],
1.1756 + q,
1.1757 + message,
1.1758 + msg_gsignature);
1.1759 + }
1.1760 +
1.1761 + out:
1.1762 + g_free (name);
1.1763 + if (msg_gsignature)
1.1764 + g_array_free (msg_gsignature, TRUE);
1.1765 + return;
1.1766 + mismatch:
1.1767 +#if 0
1.1768 + /* Don't spew on remote errors */
1.1769 + g_warning ("Unexpected message signature '%s' for signal '%s'\n",
1.1770 + dbus_message_get_signature (message),
1.1771 + name);
1.1772 +#endif
1.1773 + goto out;
1.1774 +}
1.1775 +
1.1776 +typedef struct
1.1777 +{
1.1778 + DBusGProxy *proxy;
1.1779 + guint call_id;
1.1780 + DBusGProxyCallNotify func;
1.1781 + void *data;
1.1782 + GDestroyNotify free_data_func;
1.1783 +} GPendingNotifyClosure;
1.1784 +
1.1785 +static void
1.1786 +d_pending_call_notify (DBusPendingCall *dcall,
1.1787 + void *data)
1.1788 +{
1.1789 + GPendingNotifyClosure *closure = data;
1.1790 +
1.1791 + (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
1.1792 +}
1.1793 +
1.1794 +static void
1.1795 +d_pending_call_free (void *data)
1.1796 +{
1.1797 + GPendingNotifyClosure *closure = data;
1.1798 +
1.1799 + if (closure->free_data_func)
1.1800 + (* closure->free_data_func) (closure->data);
1.1801 +
1.1802 + g_free (closure);
1.1803 +}
1.1804 +
1.1805 +#define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
1.1806 +do { \
1.1807 + GType valtype; \
1.1808 + int i = 0; \
1.1809 + VALARRAY = g_value_array_new (6); \
1.1810 + valtype = FIRST_ARG_TYPE; \
1.1811 + while (valtype != G_TYPE_INVALID) \
1.1812 + { \
1.1813 + const char *collect_err; \
1.1814 + GValue *val; \
1.1815 + g_value_array_append (VALARRAY, NULL); \
1.1816 + val = g_value_array_get_nth (VALARRAY, i); \
1.1817 + g_value_init (val, valtype); \
1.1818 + collect_err = NULL; \
1.1819 + G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
1.1820 + valtype = va_arg (ARGS, GType); \
1.1821 + i++; \
1.1822 + } \
1.1823 +} while (0)
1.1824 +
1.1825 +DBusGProxyCall *
1.1826 +manager_begin_bus_call (DBusGProxyManager *manager,
1.1827 + const char *method,
1.1828 + DBusGProxyCallNotify notify,
1.1829 + gpointer user_data,
1.1830 + GDestroyNotify destroy,
1.1831 + GType first_arg_type,
1.1832 + ...)
1.1833 +{
1.1834 + DBusGProxyCall *call;
1.1835 + DBusGProxyPrivate *priv;
1.1836 + va_list args;
1.1837 + GValueArray *arg_values;
1.1838 +
1.1839 + va_start (args, first_arg_type);
1.1840 +
1.1841 + if (!manager->bus_proxy)
1.1842 + {
1.1843 + manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
1.1844 + "name", DBUS_SERVICE_DBUS,
1.1845 + "path", DBUS_PATH_DBUS,
1.1846 + "interface", DBUS_INTERFACE_DBUS,
1.1847 + NULL);
1.1848 + priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy);
1.1849 + priv->manager = manager;
1.1850 + }
1.1851 +
1.1852 + DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
1.1853 +
1.1854 + call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values,-1));
1.1855 +
1.1856 + g_value_array_free (arg_values);
1.1857 +
1.1858 + va_end (args);
1.1859 +
1.1860 + return call;
1.1861 +}
1.1862 +
1.1863 +/** @} End of DBusGLibInternals */
1.1864 +
1.1865 +/** @addtogroup DBusGLib
1.1866 + * @{
1.1867 + */
1.1868 +
1.1869 +/**
1.1870 + * SECTION:dbus-gproxy
1.1871 + * @short_description: DBus Proxy
1.1872 + * @see_also: #DBusProxy
1.1873 + * @stability: Stable
1.1874 + *
1.1875 + * A #DBusGProxy is a boxed type abstracting a #DBusProxy.
1.1876 + */
1.1877 +
1.1878 +/**
1.1879 + * dbus_g_proxy_get_type:
1.1880 + * Standard GObject get_type() function for DBusGProxy.
1.1881 + *
1.1882 + * Returns: type ID for DBusGProxy class
1.1883 + */
1.1884 + #if EMULATOR
1.1885 +GET_STATIC_VAR_FROM_TLS(object_type,dbus_gproxy,GType)
1.1886 +#define object_type (*GET_DBUS_WSD_VAR_NAME(object_type,dbus_gproxy,s)())
1.1887 +#endif
1.1888 + #ifdef __SYMBIAN32__
1.1889 + EXPORT_C
1.1890 + #endif
1.1891 +GType
1.1892 +dbus_g_proxy_get_type (void)
1.1893 +{
1.1894 + #ifndef EMULATOR
1.1895 + static GType object_type = 0;
1.1896 +#endif
1.1897 +
1.1898 +
1.1899 + if (!object_type)
1.1900 + {
1.1901 + static const GTypeInfo object_info =
1.1902 + {
1.1903 + sizeof (DBusGProxyClass),
1.1904 + (GBaseInitFunc) NULL,
1.1905 + (GBaseFinalizeFunc) NULL,
1.1906 + (GClassInitFunc) dbus_g_proxy_class_init,
1.1907 + NULL, /* class_finalize */
1.1908 + NULL, /* class_data */
1.1909 + sizeof (DBusGProxy),
1.1910 + 0, /* n_preallocs */
1.1911 + (GInstanceInitFunc) dbus_g_proxy_init,
1.1912 + };
1.1913 +
1.1914 + object_type = g_type_register_static (G_TYPE_OBJECT,
1.1915 + "DBusGProxy",
1.1916 + &object_info, 0);
1.1917 + }
1.1918 +
1.1919 + return object_type;
1.1920 +}
1.1921 +
1.1922 +static DBusGProxy*
1.1923 +dbus_g_proxy_new (DBusGConnection *connection,
1.1924 + const char *name,
1.1925 + const char *path_name,
1.1926 + const char *interface_name)
1.1927 +{
1.1928 + DBusGProxy *proxy;
1.1929 +
1.1930 + g_assert (connection != NULL);
1.1931 +
1.1932 + proxy = g_object_new (DBUS_TYPE_G_PROXY,
1.1933 + "name", name,
1.1934 + "path", path_name,
1.1935 + "interface", interface_name,
1.1936 + "connection", connection, NULL);
1.1937 +
1.1938 + return proxy;
1.1939 +}
1.1940 +
1.1941 +/**
1.1942 + * dbus_g_proxy_new_for_name:
1.1943 + * @connection: the connection to the remote bus
1.1944 + * @name: any name on the message bus
1.1945 + * @path_name: name of the object instance to call methods on
1.1946 + * @interface_name: name of the interface to call methods on
1.1947 + *
1.1948 + * Creates a new proxy for a remote interface exported by a connection
1.1949 + * on a message bus. Method calls and signal connections over this
1.1950 + * proxy will go to the name owner; the name's owner is expected to
1.1951 + * support the given interface name. THE NAME OWNER MAY CHANGE OVER
1.1952 + * TIME, for example between two different method calls, unless the
1.1953 + * name is a unique name. If you need a fixed owner, you need to
1.1954 + * request the current owner and bind a proxy to its unique name
1.1955 + * rather than to the generic name; see
1.1956 + * dbus_g_proxy_new_for_name_owner().
1.1957 + *
1.1958 + * A name-associated proxy only makes sense with a message bus, not
1.1959 + * for app-to-app direct dbus connections.
1.1960 + *
1.1961 + * This proxy will only emit the "destroy" signal if the
1.1962 + * #DBusConnection is disconnected, the proxy has no remaining
1.1963 + * references, or the name is a unique name and its owner
1.1964 + * disappears. If a well-known name changes owner, the proxy will
1.1965 + * still be alive.
1.1966 + *
1.1967 + * Returns: new proxy object
1.1968 + */
1.1969 + #ifdef __SYMBIAN32__
1.1970 + EXPORT_C
1.1971 + #endif
1.1972 +DBusGProxy*
1.1973 +dbus_g_proxy_new_for_name (DBusGConnection *connection,
1.1974 + const char *name,
1.1975 + const char *path_name,
1.1976 + const char *interface_name)
1.1977 +{
1.1978 + g_return_val_if_fail (connection != NULL, NULL);
1.1979 + g_return_val_if_fail (name != NULL, NULL);
1.1980 + g_return_val_if_fail (path_name != NULL, NULL);
1.1981 + g_return_val_if_fail (interface_name != NULL, NULL);
1.1982 +
1.1983 + return dbus_g_proxy_new (connection, name,
1.1984 + path_name, interface_name);
1.1985 +}
1.1986 +
1.1987 +/**
1.1988 + * dbus_g_proxy_new_for_name_owner:
1.1989 + * @connection: the connection to the remote bus
1.1990 + * @name: any name on the message bus
1.1991 + * @path_name: name of the object inside the service to call methods on
1.1992 + * @interface_name: name of the interface to call methods on
1.1993 + * @error: return location for an error
1.1994 + *
1.1995 + * Similar to dbus_g_proxy_new_for_name(), but makes a round-trip
1.1996 + * request to the message bus to get the current name owner, then
1.1997 + * binds the proxy to the unique name of the current owner, rather
1.1998 + * than to the well-known name. As a result, the name owner will
1.1999 + * not change over time, and the proxy will emit the "destroy" signal
1.2000 + * when the owner disappears from the message bus.
1.2001 + *
1.2002 + * An example of the difference between dbus_g_proxy_new_for_name()
1.2003 + * and dbus_g_proxy_new_for_name_owner(): if you provide the well-known name
1.2004 + * "org.freedesktop.Database" dbus_g_proxy_new_for_name() remains bound
1.2005 + * to that name as it changes owner. dbus_g_proxy_new_for_name_owner()
1.2006 + * will fail if the name has no owner. If the name has an owner,
1.2007 + * dbus_g_proxy_new_for_name_owner() will bind to the unique name
1.2008 + * of that owner rather than the generic name.
1.2009 + *
1.2010 + * Returns: new proxy object, or #NULL on error
1.2011 + */
1.2012 + #ifdef __SYMBIAN32__
1.2013 + EXPORT_C
1.2014 + #endif
1.2015 +DBusGProxy*
1.2016 +dbus_g_proxy_new_for_name_owner (DBusGConnection *connection,
1.2017 + const char *name,
1.2018 + const char *path_name,
1.2019 + const char *interface_name,
1.2020 + GError **error)
1.2021 +{
1.2022 + DBusGProxy *proxy;
1.2023 + char *unique_name;
1.2024 +
1.2025 + g_return_val_if_fail (connection != NULL, NULL);
1.2026 + g_return_val_if_fail (name != NULL, NULL);
1.2027 + g_return_val_if_fail (path_name != NULL, NULL);
1.2028 + g_return_val_if_fail (interface_name != NULL, NULL);
1.2029 +
1.2030 + if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error)))
1.2031 + return NULL;
1.2032 +
1.2033 + proxy = dbus_g_proxy_new (connection, unique_name,
1.2034 + path_name, interface_name);
1.2035 + g_free (unique_name);
1.2036 + return proxy;
1.2037 +}
1.2038 +
1.2039 +/**
1.2040 + * dbus_g_proxy_new_from_proxy:
1.2041 + * @proxy: the proxy to use as a template
1.2042 + * @path: of the object inside the peer to call methods on
1.2043 + * @interface: name of the interface to call methods on
1.2044 + *
1.2045 + * Creates a proxy using an existing proxy as a template, substituting
1.2046 + * the specified interface and path. Either or both may be NULL.
1.2047 + *
1.2048 + * Returns: new proxy object
1.2049 + */
1.2050 + #ifdef __SYMBIAN32__
1.2051 + EXPORT_C
1.2052 + #endif
1.2053 +DBusGProxy*
1.2054 +dbus_g_proxy_new_from_proxy (DBusGProxy *proxy,
1.2055 + const char *interface,
1.2056 + const char *path)
1.2057 +{
1.2058 + DBusGProxyPrivate *priv;
1.2059 +
1.2060 + g_return_val_if_fail (proxy != NULL, NULL);
1.2061 +
1.2062 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2063 +
1.2064 + if (interface == NULL)
1.2065 + interface = priv->interface;
1.2066 + if (path == NULL)
1.2067 + path = priv->path;
1.2068 +
1.2069 + return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection),
1.2070 + priv->name,
1.2071 + path, interface);
1.2072 +}
1.2073 +
1.2074 +/**
1.2075 + * dbus_g_proxy_new_for_peer:
1.2076 + * @connection: the connection to the peer
1.2077 + * @path_name: name of the object inside the peer to call methods on
1.2078 + * @interface_name: name of the interface to call methods on
1.2079 + *
1.2080 + * Creates a proxy for an object in peer application (one
1.2081 + * we're directly connected to). That is, this function is
1.2082 + * intended for use when there's no message bus involved,
1.2083 + * we're doing a simple 1-to-1 communication between two
1.2084 + * applications.
1.2085 + *
1.2086 + * Returns: new proxy object
1.2087 + */
1.2088 + #ifdef __SYMBIAN32__
1.2089 + EXPORT_C
1.2090 + #endif
1.2091 +DBusGProxy*
1.2092 +dbus_g_proxy_new_for_peer (DBusGConnection *connection,
1.2093 + const char *path_name,
1.2094 + const char *interface_name)
1.2095 +{
1.2096 + DBusGProxy *proxy;
1.2097 +
1.2098 + g_return_val_if_fail (connection != NULL, NULL);
1.2099 + g_return_val_if_fail (path_name != NULL, NULL);
1.2100 + g_return_val_if_fail (interface_name != NULL, NULL);
1.2101 +
1.2102 + proxy = dbus_g_proxy_new (connection, NULL,
1.2103 + path_name, interface_name);
1.2104 +
1.2105 + return proxy;
1.2106 +}
1.2107 +
1.2108 +/**
1.2109 + * dbus_g_proxy_get_bus_name:
1.2110 + * @proxy: the proxy
1.2111 + *
1.2112 + * Gets the bus name a proxy is bound to (may be #NULL in some cases).
1.2113 + * If you created the proxy with dbus_g_proxy_new_for_name(), then
1.2114 + * the name you passed to that will be returned.
1.2115 + * If you created it with dbus_g_proxy_new_for_name_owner(), then the
1.2116 + * unique connection name will be returned. If you created it
1.2117 + * with dbus_g_proxy_new_for_peer() then #NULL will be returned.
1.2118 + *
1.2119 + * Returns: the bus name the proxy sends messages to
1.2120 + */
1.2121 + #ifdef __SYMBIAN32__
1.2122 + EXPORT_C
1.2123 + #endif
1.2124 +const char*
1.2125 +dbus_g_proxy_get_bus_name (DBusGProxy *proxy)
1.2126 +{
1.2127 + DBusGProxyPrivate *priv;
1.2128 +
1.2129 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
1.2130 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
1.2131 +
1.2132 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2133 +
1.2134 + return priv->name;
1.2135 +}
1.2136 +
1.2137 +/**
1.2138 + * dbus_g_proxy_get_interface:
1.2139 + * @proxy: the proxy
1.2140 + *
1.2141 + * Gets the object interface proxy is bound to (may be #NULL in some cases).
1.2142 + *
1.2143 + * Returns: an object interface
1.2144 + */
1.2145 + #ifdef __SYMBIAN32__
1.2146 + EXPORT_C
1.2147 + #endif
1.2148 +const char*
1.2149 +dbus_g_proxy_get_interface (DBusGProxy *proxy)
1.2150 +{
1.2151 + DBusGProxyPrivate *priv;
1.2152 +
1.2153 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
1.2154 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
1.2155 +
1.2156 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2157 +
1.2158 + return priv->interface;
1.2159 +}
1.2160 +
1.2161 +/**
1.2162 + * dbus_g_proxy_set_interface:
1.2163 + * @proxy: the proxy
1.2164 + * @interface_name: an object interface
1.2165 + *
1.2166 + * Sets the object interface proxy is bound to
1.2167 + */
1.2168 + #ifdef __SYMBIAN32__
1.2169 + EXPORT_C
1.2170 + #endif
1.2171 +void
1.2172 +dbus_g_proxy_set_interface (DBusGProxy *proxy,
1.2173 + const char *interface_name)
1.2174 +{
1.2175 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2176 + /* FIXME - need to unregister when we switch interface for now
1.2177 + * later should support idea of unset interface
1.2178 + */
1.2179 + dbus_g_proxy_manager_unregister (priv->manager, proxy);
1.2180 + g_free (priv->interface);
1.2181 + priv->interface = g_strdup (interface_name);
1.2182 + dbus_g_proxy_manager_register (priv->manager, proxy);
1.2183 +}
1.2184 +
1.2185 +/**
1.2186 + * dbus_g_proxy_get_path:
1.2187 + * Gets the path this proxy is bound to
1.2188 + * @proxy: the proxy
1.2189 + *
1.2190 + * Returns: an object path
1.2191 + */
1.2192 + #ifdef __SYMBIAN32__
1.2193 + EXPORT_C
1.2194 + #endif
1.2195 +const char*
1.2196 +dbus_g_proxy_get_path (DBusGProxy *proxy)
1.2197 +{
1.2198 + DBusGProxyPrivate *priv;
1.2199 +
1.2200 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
1.2201 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
1.2202 +
1.2203 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2204 +
1.2205 + return priv->path;
1.2206 +}
1.2207 +
1.2208 +static DBusMessage *
1.2209 +dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy,
1.2210 + const char *method,
1.2211 + GValueArray *args)
1.2212 +{
1.2213 + DBusMessage *message;
1.2214 + DBusMessageIter msgiter;
1.2215 + guint i;
1.2216 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2217 +
1.2218 + message = dbus_message_new_method_call (priv->name,
1.2219 + priv->path,
1.2220 + priv->interface,
1.2221 + method);
1.2222 + if (message == NULL)
1.2223 + goto oom;
1.2224 +
1.2225 + dbus_message_iter_init_append (message, &msgiter);
1.2226 + for (i = 0; i < args->n_values; i++)
1.2227 + {
1.2228 + GValue *gvalue;
1.2229 +
1.2230 + gvalue = g_value_array_get_nth (args, i);
1.2231 +
1.2232 + if (!_dbus_gvalue_marshal (&msgiter, gvalue))
1.2233 + g_assert_not_reached ();
1.2234 + }
1.2235 + return message;
1.2236 + oom:
1.2237 + return NULL;
1.2238 +}
1.2239 +
1.2240 +static guint
1.2241 +dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
1.2242 + const char *method,
1.2243 + DBusGProxyCallNotify notify,
1.2244 + gpointer user_data,
1.2245 + GDestroyNotify destroy,
1.2246 + GValueArray *args,
1.2247 + int timeout)
1.2248 +{
1.2249 + DBusMessage *message;
1.2250 + DBusPendingCall *pending;
1.2251 + GPendingNotifyClosure *closure;
1.2252 + guint call_id;
1.2253 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2254 +
1.2255 + pending = NULL;
1.2256 +
1.2257 + message = dbus_g_proxy_marshal_args_to_message (proxy, method, args);
1.2258 + if (!message)
1.2259 + goto oom;
1.2260 +
1.2261 + if (!dbus_connection_send_with_reply (priv->manager->connection,
1.2262 + message,
1.2263 + &pending,
1.2264 + timeout))
1.2265 + goto oom;
1.2266 + dbus_message_unref (message);
1.2267 + g_assert (pending != NULL);
1.2268 +
1.2269 + call_id = ++priv->call_id_counter;
1.2270 +
1.2271 + if (notify != NULL)
1.2272 + {
1.2273 + closure = g_new (GPendingNotifyClosure, 1);
1.2274 + closure->proxy = proxy; /* No need to ref as the lifecycle is tied to proxy */
1.2275 + closure->call_id = call_id;
1.2276 + closure->func = notify;
1.2277 + closure->data = user_data;
1.2278 + closure->free_data_func = destroy;
1.2279 + dbus_pending_call_set_notify (pending, d_pending_call_notify,
1.2280 + closure,
1.2281 + d_pending_call_free);
1.2282 + }
1.2283 +
1.2284 + g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending);
1.2285 +
1.2286 + return call_id;
1.2287 + oom:
1.2288 + g_error ("Out of memory");
1.2289 + return 0;
1.2290 +}
1.2291 +
1.2292 +static gboolean
1.2293 +dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
1.2294 + guint call_id,
1.2295 + GError **error,
1.2296 + GType first_arg_type,
1.2297 + va_list args)
1.2298 +{
1.2299 + DBusMessage *reply;
1.2300 + DBusMessageIter msgiter;
1.2301 + DBusError derror;
1.2302 + va_list args_unwind;
1.2303 + guint over;
1.2304 + int n_retvals_processed;
1.2305 + gboolean ret;
1.2306 + GType valtype;
1.2307 + DBusPendingCall *pending;
1.2308 + DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2309 +
1.2310 + reply = NULL;
1.2311 + ret = FALSE;
1.2312 + n_retvals_processed = 0;
1.2313 + over = 0;
1.2314 +
1.2315 + pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
1.2316 +
1.2317 + dbus_pending_call_block (pending);
1.2318 + reply = dbus_pending_call_steal_reply (pending);
1.2319 +
1.2320 + g_assert (reply != NULL);
1.2321 +
1.2322 + dbus_error_init (&derror);
1.2323 +
1.2324 + switch (dbus_message_get_type (reply))
1.2325 + {
1.2326 + case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1.2327 + dbus_message_iter_init (reply, &msgiter);
1.2328 + valtype = first_arg_type;
1.2329 + while (valtype != G_TYPE_INVALID)
1.2330 + {
1.2331 + int arg_type;
1.2332 + gpointer return_storage;
1.2333 + GValue gvalue = { 0, };
1.2334 + DBusGValueMarshalCtx context;
1.2335 +
1.2336 + context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
1.2337 + context.proxy = proxy;
1.2338 +
1.2339 + arg_type = dbus_message_iter_get_arg_type (&msgiter);
1.2340 + if (arg_type == DBUS_TYPE_INVALID)
1.2341 + {
1.2342 + g_set_error (error, DBUS_GERROR,
1.2343 + DBUS_GERROR_INVALID_ARGS,
1.2344 + _("Too few arguments in reply"));
1.2345 + goto out;
1.2346 + }
1.2347 +
1.2348 + return_storage = va_arg (args, gpointer);
1.2349 + if (return_storage == NULL)
1.2350 + goto next;
1.2351 +
1.2352 + /* We handle variants specially; the caller is expected
1.2353 + * to have already allocated storage for them.
1.2354 + */
1.2355 + if (arg_type == DBUS_TYPE_VARIANT
1.2356 + && g_type_is_a (valtype, G_TYPE_VALUE))
1.2357 + {
1.2358 + if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL))
1.2359 + {
1.2360 + g_set_error (error,
1.2361 + DBUS_GERROR,
1.2362 + DBUS_GERROR_INVALID_ARGS,
1.2363 + _("Couldn't convert argument, expected \"%s\""),
1.2364 + g_type_name (valtype));
1.2365 + goto out;
1.2366 + }
1.2367 + }
1.2368 + else
1.2369 + {
1.2370 + g_value_init (&gvalue, valtype);
1.2371 +
1.2372 + if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error))
1.2373 + goto out;
1.2374 +
1.2375 + /* Anything that can be demarshaled must be storable */
1.2376 + if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage))
1.2377 + g_assert_not_reached ();
1.2378 + /* Ownership of the value passes to the client, don't unset */
1.2379 + }
1.2380 +
1.2381 + next:
1.2382 + n_retvals_processed++;
1.2383 + dbus_message_iter_next (&msgiter);
1.2384 + valtype = va_arg (args, GType);
1.2385 + }
1.2386 +
1.2387 + while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID)
1.2388 + {
1.2389 + over++;
1.2390 + dbus_message_iter_next (&msgiter);
1.2391 + }
1.2392 +
1.2393 + if (over > 0)
1.2394 + {
1.2395 + g_set_error (error, DBUS_GERROR,
1.2396 + DBUS_GERROR_INVALID_ARGS,
1.2397 + _("Too many arguments in reply; expected %d, got %d"),
1.2398 + n_retvals_processed, over);
1.2399 + goto out;
1.2400 + }
1.2401 + break;
1.2402 + case DBUS_MESSAGE_TYPE_ERROR:
1.2403 + dbus_set_error_from_message (&derror, reply);
1.2404 + dbus_set_g_error (error, &derror);
1.2405 + dbus_error_free (&derror);
1.2406 + goto out;
1.2407 + break;
1.2408 + default:
1.2409 + dbus_set_error (&derror, DBUS_ERROR_FAILED,
1.2410 + "Reply was neither a method return nor an exception");
1.2411 + dbus_set_g_error (error, &derror);
1.2412 + dbus_error_free (&derror);
1.2413 + goto out;
1.2414 + break;
1.2415 + }
1.2416 +
1.2417 + ret = TRUE;
1.2418 + out:
1.2419 + va_end (args);
1.2420 +
1.2421 + if (ret == FALSE)
1.2422 + {
1.2423 + int i;
1.2424 + for (i = 0; i < n_retvals_processed; i++)
1.2425 + {
1.2426 + gpointer retval;
1.2427 +
1.2428 + retval = va_arg (args_unwind, gpointer);
1.2429 +
1.2430 + g_free (retval);
1.2431 + }
1.2432 + }
1.2433 + va_end (args_unwind);
1.2434 +
1.2435 + g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
1.2436 +
1.2437 + if (reply)
1.2438 + dbus_message_unref (reply);
1.2439 + return ret;
1.2440 +}
1.2441 +
1.2442 +/**
1.2443 + * dbus_g_proxy_begin_call:
1.2444 + * @proxy: a proxy for a remote interface
1.2445 + * @method: the name of the method to invoke
1.2446 + * @notify: callback to be invoked when method returns
1.2447 + * @user_data: user data passed to callback
1.2448 + * @destroy: function called to destroy user_data
1.2449 + * @first_arg_type: type of the first argument
1.2450 + *
1.2451 + * Asynchronously invokes a method on a remote interface. The method
1.2452 + * call will not be sent over the wire until the application returns
1.2453 + * to the main loop, or blocks in dbus_connection_flush() to write out
1.2454 + * pending data. The call will be completed after a timeout, or when
1.2455 + * a reply is received. When the call returns, the callback specified
1.2456 + * will be invoked; you can then collect the results of the call
1.2457 + * (which may be an error, or a reply), use dbus_g_proxy_end_call().
1.2458 + *
1.2459 + * TODO this particular function shouldn't die on out of memory,
1.2460 + * since you should be able to do a call with large arguments.
1.2461 + *
1.2462 + * Returns: call identifier.
1.2463 + */
1.2464 + #ifdef __SYMBIAN32__
1.2465 + EXPORT_C
1.2466 + #endif
1.2467 +DBusGProxyCall *
1.2468 +dbus_g_proxy_begin_call (DBusGProxy *proxy,
1.2469 + const char *method,
1.2470 + DBusGProxyCallNotify notify,
1.2471 + gpointer user_data,
1.2472 + GDestroyNotify destroy,
1.2473 + GType first_arg_type,
1.2474 + ...)
1.2475 +{
1.2476 + guint call_id;
1.2477 + va_list args;
1.2478 + GValueArray *arg_values;
1.2479 +
1.2480 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
1.2481 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
1.2482 +
1.2483 + va_start (args, first_arg_type);
1.2484 +
1.2485 + DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
1.2486 +
1.2487 + call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,-1);
1.2488 +
1.2489 + g_value_array_free (arg_values);
1.2490 +
1.2491 + va_end (args);
1.2492 +
1.2493 + return DBUS_G_PROXY_ID_TO_CALL (call_id);
1.2494 +}
1.2495 +
1.2496 +/**
1.2497 + * dbus_g_proxy_begin_call_with_timeout:
1.2498 + * @proxy: a proxy for a remote interface
1.2499 + * @method: the name of the method to invoke
1.2500 + * @notify: callback to be invoked when method returns
1.2501 + * @user_data: user data passed to callback
1.2502 + * @destroy: function called to destroy user_data
1.2503 + * @timeout: specify the timeout in milliseconds
1.2504 + * @first_arg_type: type of the first argument
1.2505 + *
1.2506 + * Asynchronously invokes a method on a remote interface. The method
1.2507 + * call will not be sent over the wire until the application returns
1.2508 + * to the main loop, or blocks in dbus_connection_flush() to write out
1.2509 + * pending data. The call will be completed after a timeout, or when
1.2510 + * a reply is received. When the call returns, the callback specified
1.2511 + * will be invoked; you can then collect the results of the call
1.2512 + * (which may be an error, or a reply), use dbus_g_proxy_end_call().
1.2513 + *
1.2514 + * TODO this particular function shouldn't die on out of memory,
1.2515 + * since you should be able to do a call with large arguments.
1.2516 + *
1.2517 + * Returns: call identifier.
1.2518 + */
1.2519 + #ifdef __SYMBIAN32__
1.2520 + EXPORT_C
1.2521 + #endif
1.2522 +DBusGProxyCall *
1.2523 +dbus_g_proxy_begin_call_with_timeout (DBusGProxy *proxy,
1.2524 + const char *method,
1.2525 + DBusGProxyCallNotify notify,
1.2526 + gpointer user_data,
1.2527 + GDestroyNotify destroy,
1.2528 + int timeout,
1.2529 + GType first_arg_type,
1.2530 + ...)
1.2531 +{
1.2532 + guint call_id;
1.2533 + va_list args;
1.2534 + GValueArray *arg_values;
1.2535 +
1.2536 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
1.2537 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
1.2538 +
1.2539 + va_start (args, first_arg_type);
1.2540 +
1.2541 + DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
1.2542 +
1.2543 + call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,timeout);
1.2544 +
1.2545 + g_value_array_free (arg_values);
1.2546 +
1.2547 + va_end (args);
1.2548 +
1.2549 + return DBUS_G_PROXY_ID_TO_CALL (call_id);
1.2550 +}
1.2551 +
1.2552 +/**
1.2553 + * dbus_g_proxy_end_call:
1.2554 + * @proxy: a proxy for a remote interface
1.2555 + * @call: the pending call ID from dbus_g_proxy_begin_call()
1.2556 + * @error: return location for an error
1.2557 + * @first_arg_type: type of first "out" argument
1.2558 + *
1.2559 + * Collects the results of a method call. The method call was normally
1.2560 + * initiated with dbus_g_proxy_end_call(). You may use this function
1.2561 + * outside of the callback given to dbus_g_proxy_begin_call; in that
1.2562 + * case this function will block if the results haven't yet been
1.2563 + * received.
1.2564 + *
1.2565 + * If the call results in an error, the error is set as normal for
1.2566 + * GError and the function returns #FALSE.
1.2567 + *
1.2568 + * Otherwise, the "out" parameters and return value of the
1.2569 + * method are stored in the provided varargs list.
1.2570 + * The list should be terminated with G_TYPE_INVALID.
1.2571 + *
1.2572 + * Returns: #FALSE if an error is set.
1.2573 + */
1.2574 + #ifdef __SYMBIAN32__
1.2575 + EXPORT_C
1.2576 + #endif
1.2577 +gboolean
1.2578 +dbus_g_proxy_end_call (DBusGProxy *proxy,
1.2579 + DBusGProxyCall *call,
1.2580 + GError **error,
1.2581 + GType first_arg_type,
1.2582 + ...)
1.2583 +{
1.2584 + gboolean ret;
1.2585 + va_list args;
1.2586 +
1.2587 + va_start (args, first_arg_type);
1.2588 +
1.2589 + ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
1.2590 +
1.2591 + va_end (args);
1.2592 +
1.2593 + return ret;
1.2594 +}
1.2595 +
1.2596 +/**
1.2597 + * dbus_g_proxy_call:
1.2598 + * @proxy: a proxy for a remote interface
1.2599 + * @method: method to invoke
1.2600 + * @error: return location for an error
1.2601 + * @first_arg_type: type of first "in" argument
1.2602 + *
1.2603 + * Function for synchronously invoking a method and receiving reply
1.2604 + * values. This function is equivalent to dbus_g_proxy_begin_call
1.2605 + * followed by dbus_g_proxy_end_call. All of the input arguments are
1.2606 + * specified first, followed by G_TYPE_INVALID, followed by all of the
1.2607 + * output values, followed by a second G_TYPE_INVALID. Note that
1.2608 + * this means you must always specify G_TYPE_INVALID twice.
1.2609 + *
1.2610 + * Returns: #FALSE if an error is set, #TRUE otherwise.
1.2611 + */
1.2612 + #ifdef __SYMBIAN32__
1.2613 + EXPORT_C
1.2614 + #endif
1.2615 +gboolean
1.2616 +dbus_g_proxy_call (DBusGProxy *proxy,
1.2617 + const char *method,
1.2618 + GError **error,
1.2619 + GType first_arg_type,
1.2620 + ...)
1.2621 +{
1.2622 + gboolean ret;
1.2623 + guint call_id;
1.2624 + va_list args;
1.2625 + GValueArray *in_args;
1.2626 +
1.2627 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
1.2628 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
1.2629 +
1.2630 + va_start (args, first_arg_type);
1.2631 +
1.2632 + DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
1.2633 +
1.2634 + call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,-1);
1.2635 +
1.2636 + g_value_array_free (in_args);
1.2637 +
1.2638 + first_arg_type = va_arg (args, GType);
1.2639 + ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
1.2640 +
1.2641 + va_end (args);
1.2642 +
1.2643 + return ret;
1.2644 +}
1.2645 +
1.2646 +/**
1.2647 + * dbus_g_proxy_call_with_timeout:
1.2648 + * @proxy: a proxy for a remote interface
1.2649 + * @method: method to invoke
1.2650 + * @timeout: specify the timeout in milliseconds
1.2651 + * @error: return location for an error
1.2652 + * @first_arg_type: type of first "in" argument
1.2653 + *
1.2654 + * Function for synchronously invoking a method and receiving reply
1.2655 + * values. This function is equivalent to dbus_g_proxy_begin_call
1.2656 + * followed by dbus_g_proxy_end_call. All of the input arguments are
1.2657 + * specified first, followed by G_TYPE_INVALID, followed by all of the
1.2658 + * output values, followed by a second G_TYPE_INVALID. Note that
1.2659 + * this means you must always specify G_TYPE_INVALID twice.
1.2660 + *
1.2661 + * Returns: #FALSE if an error is set, #TRUE otherwise.
1.2662 + */
1.2663 + #ifdef __SYMBIAN32__
1.2664 + EXPORT_C
1.2665 + #endif
1.2666 +gboolean
1.2667 +dbus_g_proxy_call_with_timeout (DBusGProxy *proxy,
1.2668 + const char *method,
1.2669 + int timeout,
1.2670 + GError **error,
1.2671 + GType first_arg_type,
1.2672 + ...)
1.2673 +{
1.2674 + gboolean ret;
1.2675 + guint call_id;
1.2676 + va_list args;
1.2677 + GValueArray *in_args;
1.2678 +
1.2679 + g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
1.2680 + g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
1.2681 +
1.2682 + va_start (args, first_arg_type);
1.2683 +
1.2684 + DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
1.2685 +
1.2686 + call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,timeout);
1.2687 +
1.2688 + g_value_array_free (in_args);
1.2689 +
1.2690 + first_arg_type = va_arg (args, GType);
1.2691 + ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
1.2692 +
1.2693 + va_end (args);
1.2694 +
1.2695 + return ret;
1.2696 +}
1.2697 +
1.2698 +/**
1.2699 + * dbus_g_proxy_call_no_reply:
1.2700 + * @proxy: a proxy for a remote interface
1.2701 + * @method: the name of the method to invoke
1.2702 + * @first_arg_type: type of the first argument
1.2703 + *
1.2704 + * Sends a method call message as with dbus_g_proxy_begin_call(), but
1.2705 + * does not ask for a reply or allow you to receive one.
1.2706 + *
1.2707 + * TODO: this particular function shouldn't die on out of memory,
1.2708 + * since you should be able to do a call with large arguments.
1.2709 + */
1.2710 + #ifdef __SYMBIAN32__
1.2711 + EXPORT_C
1.2712 + #endif
1.2713 +void
1.2714 +dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
1.2715 + const char *method,
1.2716 + GType first_arg_type,
1.2717 + ...)
1.2718 +{
1.2719 + DBusMessage *message;
1.2720 + va_list args;
1.2721 + GValueArray *in_args;
1.2722 + DBusGProxyPrivate *priv;
1.2723 +
1.2724 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.2725 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.2726 +
1.2727 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2728 +
1.2729 + va_start (args, first_arg_type);
1.2730 + DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
1.2731 +
1.2732 + message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args);
1.2733 +
1.2734 + g_value_array_free (in_args);
1.2735 + va_end (args);
1.2736 +
1.2737 + if (!message)
1.2738 + goto oom;
1.2739 +
1.2740 + dbus_message_set_no_reply (message, TRUE);
1.2741 +
1.2742 + if (!dbus_connection_send (priv->manager->connection,
1.2743 + message,
1.2744 + NULL))
1.2745 + goto oom;
1.2746 + dbus_message_unref (message);
1.2747 + return;
1.2748 +
1.2749 + oom:
1.2750 + g_error ("Out of memory");
1.2751 +}
1.2752 +
1.2753 +/**
1.2754 + * dbus_g_proxy_cancel_call
1.2755 + * @proxy: a proxy for a remote interface
1.2756 + * @call: the pending call ID from dbus_g_proxy_begin_call()
1.2757 + *
1.2758 + * Cancels a pending method call. The method call was normally
1.2759 + * initiated with dbus_g_proxy_begin_call(). This function
1.2760 + * may not be used on pending calls that have already been
1.2761 + * ended with dbus_g_proxy_end_call.
1.2762 + */
1.2763 + #ifdef __SYMBIAN32__
1.2764 + EXPORT_C
1.2765 + #endif
1.2766 +void
1.2767 +dbus_g_proxy_cancel_call (DBusGProxy *proxy,
1.2768 + DBusGProxyCall *call)
1.2769 +{
1.2770 + guint call_id;
1.2771 + DBusPendingCall *pending;
1.2772 + DBusGProxyPrivate *priv;
1.2773 +
1.2774 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.2775 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.2776 +
1.2777 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2778 +
1.2779 + call_id = DBUS_G_PROXY_CALL_TO_ID (call);
1.2780 +
1.2781 + pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
1.2782 + g_return_if_fail (pending != NULL);
1.2783 +
1.2784 + dbus_pending_call_cancel (pending);
1.2785 +
1.2786 + g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
1.2787 +}
1.2788 +
1.2789 +/**
1.2790 + * dbus_g_proxy_send:
1.2791 + * @proxy: a proxy for a remote interface
1.2792 + * @message: the message to address and send
1.2793 + * @client_serial: return location for message's serial, or #NULL
1.2794 + *
1.2795 + * Sends a message to the interface we're proxying for. Does not
1.2796 + * block or wait for a reply. The message is only actually written out
1.2797 + * when you return to the main loop or block in
1.2798 + * dbus_connection_flush().
1.2799 + *
1.2800 + * The message is modified to be addressed to the target interface.
1.2801 + * That is, a destination name field or whatever is needed will be
1.2802 + * added to the message. The basic point of this function is to add
1.2803 + * the necessary header fields, otherwise it's equivalent to
1.2804 + * dbus_connection_send().
1.2805 + *
1.2806 + * This function adds a reference to the message, so the caller
1.2807 + * still owns its original reference.
1.2808 + */
1.2809 + #ifdef __SYMBIAN32__
1.2810 + EXPORT_C
1.2811 + #endif
1.2812 +void
1.2813 +dbus_g_proxy_send (DBusGProxy *proxy,
1.2814 + DBusMessage *message,
1.2815 + dbus_uint32_t *client_serial)
1.2816 +{
1.2817 + DBusGProxyPrivate *priv;
1.2818 +
1.2819 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.2820 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.2821 +
1.2822 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2823 +
1.2824 + if (priv->name)
1.2825 + {
1.2826 + if (!dbus_message_set_destination (message, priv->name))
1.2827 + g_error ("Out of memory");
1.2828 + }
1.2829 + if (priv->path)
1.2830 + {
1.2831 + if (!dbus_message_set_path (message, priv->path))
1.2832 + g_error ("Out of memory");
1.2833 + }
1.2834 + if (priv->interface)
1.2835 + {
1.2836 + if (!dbus_message_set_interface (message, priv->interface))
1.2837 + g_error ("Out of memory");
1.2838 + }
1.2839 +
1.2840 + if (!dbus_connection_send (priv->manager->connection, message, client_serial))
1.2841 + g_error ("Out of memory\n");
1.2842 +}
1.2843 +
1.2844 +static void
1.2845 +array_free_all (gpointer array)
1.2846 +{
1.2847 + g_array_free (array, TRUE);
1.2848 +}
1.2849 +
1.2850 +/**
1.2851 + * dbus_g_proxy_add_signal:
1.2852 + * @proxy: the proxy for a remote interface
1.2853 + * @signal_name: the name of the signal
1.2854 + * @first_type: the first argument type, or G_TYPE_INVALID if none
1.2855 + *
1.2856 + * Specifies the argument signature of a signal;.only necessary
1.2857 + * if the remote object does not support introspection. The arguments
1.2858 + * specified are the GLib types expected.
1.2859 + */
1.2860 + #ifdef __SYMBIAN32__
1.2861 + EXPORT_C
1.2862 + #endif
1.2863 +void
1.2864 +dbus_g_proxy_add_signal (DBusGProxy *proxy,
1.2865 + const char *signal_name,
1.2866 + GType first_type,
1.2867 + ...)
1.2868 +{
1.2869 + GQuark q;
1.2870 + char *name;
1.2871 + GArray *gtypesig;
1.2872 + GType gtype;
1.2873 + va_list args;
1.2874 + DBusGProxyPrivate *priv;
1.2875 +
1.2876 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.2877 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.2878 + g_return_if_fail (signal_name != NULL);
1.2879 +
1.2880 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2881 +
1.2882 + name = create_signal_name (priv->interface, signal_name);
1.2883 +
1.2884 + q = g_quark_from_string (name);
1.2885 +
1.2886 + g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL);
1.2887 +
1.2888 + gtypesig = g_array_new (FALSE, TRUE, sizeof (GType));
1.2889 +
1.2890 + va_start (args, first_type);
1.2891 + gtype = first_type;
1.2892 + while (gtype != G_TYPE_INVALID)
1.2893 + {
1.2894 + g_array_append_val (gtypesig, gtype);
1.2895 + gtype = va_arg (args, GType);
1.2896 + }
1.2897 + va_end (args);
1.2898 +
1.2899 +#ifndef G_DISABLE_CHECKS
1.2900 + if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL)
1.2901 + g_warning ("No marshaller for signature of signal '%s'", signal_name);
1.2902 +#endif
1.2903 +
1.2904 +
1.2905 + g_datalist_id_set_data_full (&priv->signal_signatures,
1.2906 + q, gtypesig,
1.2907 + array_free_all);
1.2908 +
1.2909 + g_free (name);
1.2910 +}
1.2911 +
1.2912 +/**
1.2913 + * dbus_g_proxy_connect_signal:
1.2914 + * @proxy: a proxy for a remote interface
1.2915 + * @signal_name: the DBus signal name to listen for
1.2916 + * @handler: the handler to connect
1.2917 + * @data: data to pass to handler
1.2918 + * @free_data_func: callback function to destroy data
1.2919 + *
1.2920 + * Connect a signal handler to a proxy for a remote interface. When
1.2921 + * the remote interface emits the specified signal, the proxy will
1.2922 + * emit a corresponding GLib signal.
1.2923 + */
1.2924 + #ifdef __SYMBIAN32__
1.2925 + EXPORT_C
1.2926 + #endif
1.2927 +void
1.2928 +dbus_g_proxy_connect_signal (DBusGProxy *proxy,
1.2929 + const char *signal_name,
1.2930 + GCallback handler,
1.2931 + void *data,
1.2932 + GClosureNotify free_data_func)
1.2933 +{
1.2934 + char *name;
1.2935 + GClosure *closure;
1.2936 + GQuark q;
1.2937 + DBusGProxyPrivate *priv;
1.2938 +
1.2939 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.2940 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.2941 + g_return_if_fail (signal_name != NULL);
1.2942 + g_return_if_fail (handler != NULL);
1.2943 +
1.2944 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2945 + name = create_signal_name (priv->interface, signal_name);
1.2946 +
1.2947 + q = g_quark_try_string (name);
1.2948 +
1.2949 +#ifndef G_DISABLE_CHECKS
1.2950 + if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL)
1.2951 + {
1.2952 + g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name);
1.2953 + g_free (name);
1.2954 + return;
1.2955 + }
1.2956 +#endif
1.2957 +
1.2958 + closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
1.2959 +
1.2960 + g_signal_connect_closure_by_id (G_OBJECT (proxy),
1.2961 + signals[RECEIVED],
1.2962 + q,
1.2963 + closure, FALSE);
1.2964 +
1.2965 + g_free (name);
1.2966 +}
1.2967 +
1.2968 +/**
1.2969 + * dbus_g_proxy_disconnect_signal:
1.2970 + * @proxy: a proxy for a remote interface
1.2971 + * @signal_name: the DBus signal name to disconnect
1.2972 + * @handler: the handler to disconnect
1.2973 + * @data: the data that was registered with handler
1.2974 + *
1.2975 + * Disconnect all signal handlers from a proxy that match the given
1.2976 + * criteria.
1.2977 + */
1.2978 + #ifdef __SYMBIAN32__
1.2979 + EXPORT_C
1.2980 + #endif
1.2981 +void
1.2982 +dbus_g_proxy_disconnect_signal (DBusGProxy *proxy,
1.2983 + const char *signal_name,
1.2984 + GCallback handler,
1.2985 + void *data)
1.2986 +{
1.2987 + char *name;
1.2988 + GQuark q;
1.2989 + DBusGProxyPrivate *priv;
1.2990 +
1.2991 + g_return_if_fail (DBUS_IS_G_PROXY (proxy));
1.2992 + g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
1.2993 + g_return_if_fail (signal_name != NULL);
1.2994 + g_return_if_fail (handler != NULL);
1.2995 +
1.2996 + priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
1.2997 + name = create_signal_name (priv->interface, signal_name);
1.2998 +
1.2999 + q = g_quark_try_string (name);
1.3000 +
1.3001 + if (q != 0)
1.3002 + {
1.3003 + g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
1.3004 + G_SIGNAL_MATCH_DETAIL |
1.3005 + G_SIGNAL_MATCH_FUNC |
1.3006 + G_SIGNAL_MATCH_DATA,
1.3007 + signals[RECEIVED],
1.3008 + q,
1.3009 + NULL,
1.3010 + #ifdef WINSCW
1.3011 + G_CALLBACK (handler), data);
1.3012 + #else
1.3013 + (gpointer)(handler), data);
1.3014 + #endif
1.3015 + }
1.3016 + else
1.3017 + {
1.3018 + g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
1.3019 + name);
1.3020 + }
1.3021 +
1.3022 + g_free (name);
1.3023 +}
1.3024 +
1.3025 +/** @} End of DBusGLib public */
1.3026 +
1.3027 +#ifdef DBUS_BUILD_TESTS
1.3028 +
1.3029 +/**
1.3030 + * @ingroup DBusGLibInternals
1.3031 + * Unit test for GLib proxy functions
1.3032 + * Returns: #TRUE on success.
1.3033 + */
1.3034 +gboolean
1.3035 +_dbus_g_proxy_test (void)
1.3036 +{
1.3037 +
1.3038 +
1.3039 + return TRUE;
1.3040 +}
1.3041 +
1.3042 +#endif /* DBUS_BUILD_TESTS */