From b61b94a14488f22ab7f136dc0a9f6c7787d3f510 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Wed, 9 Mar 2005 23:12:24 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'dbus-0.23.3'. --- glib/dbus-gproxy.c | 842 ++++++++++++----------------------------------------- 1 file changed, 180 insertions(+), 662 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gproxy.c b/glib/dbus-gproxy.c index b5e977a4..744efdef 100644 --- a/glib/dbus-gproxy.c +++ b/glib/dbus-gproxy.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-gproxy.c Proxy for remote objects +/* dbus-gcall.c convenience routines for calling methods, etc. * - * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. + * Copyright (C) 2003, 2004 Red Hat, Inc. * * Licensed under the Academic Free License version 2.1 * @@ -22,14 +22,8 @@ */ #include #include -#include #include "dbus-gutils.h" -#include "dbus-gmarshal.h" -#include "dbus-gvalue.h" -#include "dbus-gobject.h" #include -#include -#include /** * @addtogroup DBusGLibInternals @@ -51,11 +45,9 @@ struct DBusGProxy GObject parent; /**< Parent instance */ DBusGProxyManager *manager; /**< Proxy manager */ - char *name; /**< Name messages go to or NULL */ + char *service; /**< Service messages go to or NULL */ char *path; /**< Path messages go to or NULL */ char *interface; /**< Interface messages go to or NULL */ - - GData *signal_signatures; /**< D-BUS signatures for each signal */ }; /** @@ -66,23 +58,24 @@ struct DBusGProxyClass GObjectClass parent_class; /**< Parent class */ }; -static void dbus_g_proxy_init (DBusGProxy *proxy); -static void dbus_g_proxy_class_init (DBusGProxyClass *klass); -static void dbus_g_proxy_finalize (GObject *object); -static void dbus_g_proxy_dispose (GObject *object); -static void dbus_g_proxy_destroy (DBusGProxy *proxy); -static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, - DBusMessage *message); +static void dbus_g_proxy_init (DBusGProxy *proxy); +static void dbus_g_proxy_class_init (DBusGProxyClass *klass); +static void dbus_g_proxy_finalize (GObject *object); +static void dbus_g_proxy_dispose (GObject *object); +static void dbus_g_proxy_destroy (DBusGProxy *proxy); +static void dbus_g_proxy_emit_received (DBusGProxy *proxy, + DBusMessage *message); + /** - * A list of proxies with a given name+path+interface, used to + * A list of proxies with a given service+path+interface, used to * route incoming signals. */ typedef struct { GSList *proxies; /**< The list of proxies */ - char name[4]; /**< name (empty string for none), nul byte, + char name[4]; /**< service (empty string for none), nul byte, * path, nul byte, * interface, nul byte */ @@ -92,7 +85,7 @@ typedef struct /** * DBusGProxyManager's primary task is to route signals to the proxies * those signals are emitted on. In order to do this it also has to - * track the owners of the names proxies are bound to. + * track the owners of the services proxies are bound to. */ struct DBusGProxyManager { @@ -107,10 +100,9 @@ struct DBusGProxyManager }; static DBusGProxyManager *dbus_g_proxy_manager_ref (DBusGProxyManager *manager); -static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data); - +static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection, + DBusMessage *message, + void *user_data); /** Lock the DBusGProxyManager */ #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock)) @@ -301,48 +293,48 @@ tristring_equal (gconstpointer a, static char* tristring_alloc_from_strings (size_t padding_before, - const char *name, + const char *service, const char *path, const char *interface) { - size_t name_len, iface_len, path_len, len; + size_t service_len, iface_len, path_len, len; char *tri; - if (name) - name_len = strlen (name); + if (service) + service_len = strlen (service); else - name_len = 0; + service_len = 0; path_len = strlen (path); iface_len = strlen (interface); - tri = g_malloc (padding_before + name_len + path_len + iface_len + 3); + tri = g_malloc (padding_before + service_len + path_len + iface_len + 3); len = padding_before; - if (name) - memcpy (&tri[len], name, name_len); + if (service) + memcpy (&tri[len], service, service_len); - len += name_len; + len += service_len; tri[len] = '\0'; len += 1; - g_assert (len == (padding_before + name_len + 1)); + g_assert (len == (padding_before + service_len + 1)); memcpy (&tri[len], path, path_len); len += path_len; tri[len] = '\0'; len += 1; - g_assert (len == (padding_before + name_len + path_len + 2)); + g_assert (len == (padding_before + service_len + path_len + 2)); memcpy (&tri[len], interface, iface_len); len += iface_len; tri[len] = '\0'; len += 1; - g_assert (len == (padding_before + name_len + path_len + iface_len + 3)); + g_assert (len == (padding_before + service_len + path_len + iface_len + 3)); return tri; } @@ -351,7 +343,7 @@ static char* tristring_from_proxy (DBusGProxy *proxy) { return tristring_alloc_from_strings (0, - proxy->name, + proxy->service, proxy->path, proxy->interface); } @@ -359,18 +351,10 @@ tristring_from_proxy (DBusGProxy *proxy) static char* tristring_from_message (DBusMessage *message) { - const char *path; - const char *interface; - - path = dbus_message_get_path (message); - interface = dbus_message_get_interface (message); - - g_assert (path); - g_assert (interface); - return tristring_alloc_from_strings (0, dbus_message_get_sender (message), - path, interface); + dbus_message_get_path (message), + dbus_message_get_interface (message)); } static DBusGProxyList* @@ -379,7 +363,7 @@ g_proxy_list_new (DBusGProxy *first_proxy) DBusGProxyList *list; list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name), - first_proxy->name, + first_proxy->service, first_proxy->path, first_proxy->interface); list->proxies = NULL; @@ -403,9 +387,9 @@ g_proxy_get_match_rule (DBusGProxy *proxy) { /* FIXME Escaping is required here */ - if (proxy->name) + if (proxy->service) return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'", - proxy->name, proxy->path, proxy->interface); + proxy->service, proxy->path, proxy->interface); else return g_strdup_printf ("type='signal',path='%s',interface='%s'", proxy->path, proxy->interface); @@ -413,7 +397,7 @@ g_proxy_get_match_rule (DBusGProxy *proxy) static void dbus_g_proxy_manager_register (DBusGProxyManager *manager, - DBusGProxy *proxy) + DBusGProxy *proxy) { DBusGProxyList *list; @@ -568,8 +552,8 @@ dbus_g_proxy_manager_list_all (DBusGProxyManager *manager) static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection, - DBusMessage *message, - void *user_data) + DBusMessage *message, + void *user_data) { DBusGProxyManager *manager; @@ -583,7 +567,7 @@ dbus_g_proxy_manager_filter (DBusConnection *connection, LOCK_MANAGER (manager); if (dbus_message_is_signal (message, - DBUS_INTERFACE_LOCAL, + DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, "Disconnected")) { /* Destroy all the proxies, quite possibly resulting in unreferencing @@ -620,11 +604,6 @@ dbus_g_proxy_manager_filter (DBusConnection *connection, { char *tri; DBusGProxyList *list; - - /* dbus spec requires these, libdbus validates */ - g_assert (dbus_message_get_path (message) != NULL); - g_assert (dbus_message_get_interface (message) != NULL); - g_assert (dbus_message_get_member (message) != NULL); tri = tristring_from_message (message); @@ -661,7 +640,7 @@ dbus_g_proxy_manager_filter (DBusConnection *connection, proxy = DBUS_G_PROXY (tmp->data); UNLOCK_MANAGER (manager); - dbus_g_proxy_emit_remote_signal (proxy, message); + dbus_g_proxy_emit_received (proxy, message); g_object_unref (G_OBJECT (proxy)); LOCK_MANAGER (manager); @@ -685,15 +664,7 @@ dbus_g_proxy_manager_filter (DBusConnection *connection, /* ---------- DBusGProxy -------------- */ -#define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY (proxy)->manager == NULL) -static void -marshal_dbus_message_to_g_marshaller (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); enum { @@ -708,7 +679,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; static void dbus_g_proxy_init (DBusGProxy *proxy) { - g_datalist_init (&proxy->signal_signatures); + /* Nothing */ } static void @@ -729,17 +700,19 @@ dbus_g_proxy_class_init (DBusGProxyClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - + signals[RECEIVED] = g_signal_new ("received", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, - NULL, NULL, - marshal_dbus_message_to_g_marshaller, - G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_STRING); + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + DBUS_TYPE_MESSAGE); } + static void dbus_g_proxy_dispose (GObject *object) { @@ -747,15 +720,6 @@ dbus_g_proxy_dispose (GObject *object) proxy = DBUS_G_PROXY (object); - if (proxy->manager) - { - dbus_g_proxy_manager_unregister (proxy->manager, proxy); - dbus_g_proxy_manager_unref (proxy->manager); - proxy->manager = NULL; - } - - g_datalist_clear (&proxy->signal_signatures); - g_signal_emit (object, signals[DESTROY], 0); G_OBJECT_CLASS (parent_class)->dispose (object); @@ -765,12 +729,16 @@ static void dbus_g_proxy_finalize (GObject *object) { DBusGProxy *proxy; - + proxy = DBUS_G_PROXY (object); - g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy)); + if (proxy->manager) + { + dbus_g_proxy_manager_unregister (proxy->manager, proxy); + dbus_g_proxy_manager_unref (proxy->manager); + } - g_free (proxy->name); + g_free (proxy->service); g_free (proxy->path); g_free (proxy->interface); @@ -786,169 +754,29 @@ dbus_g_proxy_destroy (DBusGProxy *proxy) g_object_run_dispose (G_OBJECT (proxy)); } -/* this is to avoid people using g_signal_connect() directly, - * to avoid confusion with local signal names, and because - * of the horribly broken current setup (signals are added - * globally to all proxies) - */ static char* -create_signal_name (const char *interface, - const char *signal) +create_signal_detail (const char *interface, + const char *signal) { GString *str; - char *p; str = g_string_new (interface); - g_string_append (str, "-"); - + g_string_append (str, "."); + g_string_append (str, signal); - /* GLib will silently barf on '.' in signal names */ - p = str->str; - while (*p) - { - if (*p == '.') - *p = '-'; - ++p; - } - return g_string_free (str, FALSE); } -static GSignalCMarshaller -lookup_g_marshaller (DBusGProxy *proxy, - const char *signature) -{ - /* The "proxy" arg would eventually be used if you could provide - * a marshaller when adding a signal to the proxy - */ - -#define MATCH1(sig, t0) ((sig)[0] == (DBUS_TYPE_##t0) && (sig)[1] == '\0') -#define MATCH2(sig, t0, t1) ((sig)[0] == (DBUS_TYPE_##t0) && (sig)[1] == (DBUS_TYPE_##t1) && (sig)[2] == '\0') -#define MATCH3(sig, t0, t1, t2) ((sig)[0] == (DBUS_TYPE_##t0) && (sig)[1] == (DBUS_TYPE_##t1) && (sig)[2] == (DBUS_TYPE_##t2) && (sig)[3] == '\0') - - switch (*signature) - { - case '\0': - return g_cclosure_marshal_VOID__VOID; - - case DBUS_TYPE_BOOLEAN: - if (MATCH1 (signature, BOOLEAN)) - return g_cclosure_marshal_VOID__BOOLEAN; - break; - - case DBUS_TYPE_BYTE: - if (MATCH1 (signature, BYTE)) - return g_cclosure_marshal_VOID__UCHAR; - break; - - case DBUS_TYPE_INT16: - if (MATCH1 (signature, INT16)) - return g_cclosure_marshal_VOID__INT; - break; - - case DBUS_TYPE_UINT16: - if (MATCH1 (signature, UINT16)) - return g_cclosure_marshal_VOID__UINT; - break; - - case DBUS_TYPE_INT32: - if (MATCH1 (signature, INT32)) - return g_cclosure_marshal_VOID__INT; - break; - - case DBUS_TYPE_UINT32: - if (MATCH1 (signature, UINT32)) - return g_cclosure_marshal_VOID__UINT; - break; - - case DBUS_TYPE_DOUBLE: - if (MATCH1 (signature, DOUBLE)) - return g_cclosure_marshal_VOID__DOUBLE; - break; - - case DBUS_TYPE_OBJECT_PATH: - if (MATCH1 (signature, OBJECT_PATH)) - return g_cclosure_marshal_VOID__STRING; - break; - - case DBUS_TYPE_SIGNATURE: - if (MATCH1 (signature, SIGNATURE)) - return g_cclosure_marshal_VOID__STRING; - break; - - case DBUS_TYPE_STRING: - if (MATCH1 (signature, STRING)) - return g_cclosure_marshal_VOID__STRING; - /* This is for NameOwnerChanged */ - else if (MATCH3 (signature, STRING, STRING, STRING)) - return _dbus_g_marshal_NONE__STRING_STRING_STRING; - break; - } - - return NULL; -} - -static void -marshal_dbus_message_to_g_marshaller (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - /* Incoming here we have three params, the instance (Proxy), the - * DBusMessage, the signature. We want to convert that to an - * expanded GValue array, then call an appropriate normal GLib - * marshaller. - */ -#define MAX_SIGNATURE_ARGS 20 - GValueArray *value_array; - GValue value = {0, }; - GSignalCMarshaller c_marshaller; - DBusGProxy *proxy; - DBusMessage *message; - const char *signature; - - g_assert (n_param_values == 3); - - proxy = g_value_get_object (¶m_values[0]); - message = g_value_get_boxed (¶m_values[1]); - signature = g_value_get_string (¶m_values[2]); - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (message != NULL); - g_return_if_fail (signature != NULL); - - c_marshaller = lookup_g_marshaller (proxy, signature); - - g_return_if_fail (c_marshaller != NULL); - - value_array = _dbus_glib_marshal_dbus_message_to_gvalue_array (message); - - g_return_if_fail (value_array != NULL); - - g_value_init (&value, G_TYPE_FROM_INSTANCE (proxy)); - g_value_set_instance (&value, proxy); - g_value_array_prepend (value_array, &value); - - (* c_marshaller) (closure, return_value, value_array->n_values, - value_array->values, invocation_hint, marshal_data); - - g_value_array_free (value_array); -} - static void -dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, - DBusMessage *message) +dbus_g_proxy_emit_received (DBusGProxy *proxy, + DBusMessage *message) { const char *interface; const char *signal; - char *name; + char *detail; GQuark q; - - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); interface = dbus_message_get_interface (message); signal = dbus_message_get_member (message); @@ -956,47 +784,21 @@ dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, g_assert (interface != NULL); g_assert (signal != NULL); - name = create_signal_name (interface, signal); + detail = create_signal_detail (interface, signal); /* If the quark isn't preexisting, there's no way there * are any handlers connected. We don't want to create * extra quarks for every possible signal. */ - q = g_quark_try_string (name); + q = g_quark_try_string (detail); if (q != 0) - { - const char *signature; + g_signal_emit (G_OBJECT (proxy), + signals[RECEIVED], + q, + message); - signature = g_datalist_id_get_data (&proxy->signal_signatures, q); - if (signature == NULL) - { -#if 0 - /* this should not trigger a warning, as you shouldn't have to - * add signals you don't care about - */ - g_warning ("Signal '%s' has not been added to this proxy object\n", - name); -#endif - } - else if (!dbus_message_has_signature (message, signature)) - { - g_warning ("Signature '%s' expected for signal '%s', actual signature '%s'\n", - signature, - name, - dbus_message_get_signature (message)); - } - else - { - g_signal_emit (proxy, - signals[RECEIVED], - q, - message, - signature); - } - } - - g_free (name); + g_free (detail); } /** @} End of DBusGLibInternals */ @@ -1040,9 +842,9 @@ dbus_g_proxy_get_type (void) static DBusGProxy* dbus_g_proxy_new (DBusGConnection *connection, - const char *name, - const char *path_name, - const char *interface_name) + const char *service_name, + const char *path_name, + const char *interface_name) { DBusGProxy *proxy; @@ -1056,7 +858,7 @@ dbus_g_proxy_new (DBusGConnection *connection, proxy->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection)); - proxy->name = g_strdup (name); + proxy->service = g_strdup (service_name); proxy->path = g_strdup (path_name); proxy->interface = g_strdup (interface_name); @@ -1066,105 +868,101 @@ dbus_g_proxy_new (DBusGConnection *connection, } /** - * Creates a new proxy for a remote interface exported by a connection - * on a message bus. Method calls and signal connections over this - * proxy will go to the name owner; the name's owner is expected to - * support the given interface name. THE NAME OWNER MAY CHANGE OVER - * TIME, for example between two different method calls, unless the - * name is a unique name. If you need a fixed owner, you need to - * request the current owner and bind a proxy to its unique name - * rather than to the generic name; see - * dbus_g_proxy_new_for_name_owner(). + * Creates a new proxy for a remote interface exported by a service on + * a message bus. Method calls and signal connections over this proxy + * will go to the service owner; the service owner is expected to + * support the given interface name. THE SERVICE OWNER MAY CHANGE OVER + * TIME, for example between two different method calls. If you need a + * fixed owner, you need to request the current owner and bind a proxy + * to that rather than to the generic service name; see + * dbus_g_proxy_new_for_service_owner(). * - * A name-associated proxy only makes sense with a message bus, not - * for app-to-app direct dbus connections. + * A service-associated proxy only makes sense with a message bus, + * not for app-to-app direct dbus connections. * - * This proxy will only emit the "destroy" signal if the - * #DBusConnection is disconnected, the proxy has no remaining - * references, or the name is a unique name and its owner - * disappears. If a well-known name changes owner, the proxy will - * still be alive. + * This proxy will only emit the "destroy" signal if the #DBusConnection + * is disconnected or the proxy is has no remaining references. * * @param connection the connection to the remote bus - * @param name any name on the message bus - * @param path_name name of the object instance to call methods on + * @param service_name name of the service on the message bus + * @param path_name name of the object inside the service to call methods on * @param interface_name name of the interface to call methods on * @returns new proxy object */ DBusGProxy* -dbus_g_proxy_new_for_name (DBusGConnection *connection, - const char *name, - const char *path_name, - const char *interface_name) +dbus_g_proxy_new_for_service (DBusGConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name) { DBusGProxy *proxy; g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (service_name != NULL, NULL); g_return_val_if_fail (path_name != NULL, NULL); g_return_val_if_fail (interface_name != NULL, NULL); - proxy = dbus_g_proxy_new (connection, name, + proxy = dbus_g_proxy_new (connection, service_name, path_name, interface_name); return proxy; } /** - * Similar to dbus_g_proxy_new_for_name(), but makes a round-trip - * request to the message bus to get the current name owner, then - * binds the proxy to the unique name of the current owner, rather - * than to the well-known name. As a result, the name owner will - * not change over time, and the proxy will emit the "destroy" signal - * when the owner disappears from the message bus. + * Similar to dbus_g_proxy_new_for_service(), but makes a round-trip + * request to the message bus to get the current service owner, then + * binds the proxy specifically to the current owner. As a result, the + * service owner will not change over time, and the proxy will emit + * the "destroy" signal when the owner disappears from the message + * bus. * - * An example of the difference between dbus_g_proxy_new_for_name() - * and dbus_g_proxy_new_for_name_owner(): if you provide the well-known name - * "org.freedesktop.Database" dbus_g_proxy_new_for_name() remains bound - * to that name as it changes owner. dbus_g_proxy_new_for_name_owner() - * will fail if the name has no owner. If the name has an owner, - * dbus_g_proxy_new_for_name_owner() will bind to the unique name - * of that owner rather than the generic name. + * An example of the difference between dbus_g_proxy_new_for_service() + * and dbus_g_proxy_new_for_service_owner(): if you pass the service name + * "org.freedesktop.Database" dbus_g_proxy_new_for_service() remains bound + * to that name as it changes owner. dbus_g_proxy_new_for_service_owner() + * will fail if the service has no owner. If the service has an owner, + * dbus_g_proxy_new_for_service_owner() will bind to the unique name + * of that owner rather than the generic service name. * * @param connection the connection to the remote bus - * @param name any name on the message bus + * @param service_name name of the service on the message bus * @param path_name name of the object inside the service to call methods on * @param interface_name name of the interface to call methods on * @param error return location for an error * @returns new proxy object, or #NULL on error */ DBusGProxy* -dbus_g_proxy_new_for_name_owner (DBusGConnection *connection, - const char *name, - const char *path_name, - const char *interface_name, - GError **error) +dbus_g_proxy_new_for_service_owner (DBusGConnection *connection, + const char *service_name, + const char *path_name, + const char *interface_name, + GError **error) { DBusGProxy *proxy; DBusMessage *request, *reply; DBusError derror; - const char *unique_name; - + char *base_service_name; + g_return_val_if_fail (connection != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (service_name != NULL, NULL); g_return_val_if_fail (path_name != NULL, NULL); g_return_val_if_fail (interface_name != NULL, NULL); dbus_error_init (&derror); proxy = NULL; - unique_name = NULL; + base_service_name = NULL; reply = NULL; - request = dbus_message_new_method_call (DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "GetNameOwner"); + request = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "GetServiceOwner"); if (request == NULL) g_error ("Out of memory"); if (! dbus_message_append_args (request, - DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, service_name, DBUS_TYPE_INVALID)) g_error ("Out of memory"); @@ -1179,13 +977,13 @@ dbus_g_proxy_new_for_name_owner (DBusGConnection *connection, goto error; if (! dbus_message_get_args (reply, &derror, - DBUS_TYPE_STRING, &unique_name, + DBUS_TYPE_STRING, &base_service_name, DBUS_TYPE_INVALID)) goto error; - proxy = dbus_g_proxy_new (connection, unique_name, - path_name, interface_name); + proxy = dbus_g_proxy_new (connection, base_service_name, + path_name, interface_name); goto out; @@ -1199,6 +997,7 @@ dbus_g_proxy_new_for_name_owner (DBusGConnection *connection, dbus_message_unref (request); if (reply) dbus_message_unref (reply); + dbus_free (base_service_name); return proxy; } @@ -1219,8 +1018,8 @@ dbus_g_proxy_new_for_name_owner (DBusGConnection *connection, */ DBusGProxy* dbus_g_proxy_new_for_peer (DBusGConnection *connection, - const char *path_name, - const char *interface_name) + const char *path_name, + const char *interface_name) { DBusGProxy *proxy; @@ -1229,31 +1028,11 @@ dbus_g_proxy_new_for_peer (DBusGConnection *connection, g_return_val_if_fail (interface_name != NULL, NULL); proxy = dbus_g_proxy_new (connection, NULL, - path_name, interface_name); + path_name, interface_name); return proxy; } -/** - * Gets the bus name a proxy is bound to (may be #NULL in some cases). - * If you created the proxy with dbus_g_proxy_new_for_name(), then - * the name you passed to that will be returned. - * If you created it with dbus_g_proxy_new_for_name_owner(), then the - * unique connection name will be returned. If you created it - * with dbus_g_proxy_new_for_peer() then #NULL will be returned. - * - * @param proxy the proxy - * @returns the bus name the proxy sends messages to - */ -const char* -dbus_g_proxy_get_bus_name (DBusGProxy *proxy) -{ - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); - - return proxy->name; -} - /** * Invokes a method on a remote interface. This function does not * block; instead it returns an opaque #DBusPendingCall object that @@ -1284,9 +1063,8 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy, va_list args; g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); - message = dbus_message_new_method_call (proxy->name, + message = dbus_message_new_method_call (proxy->service, proxy->path, proxy->interface, method); @@ -1321,43 +1099,39 @@ dbus_g_proxy_begin_call (DBusGProxy *proxy, * Collects the results of a method call. The method call was normally * initiated with dbus_g_proxy_end_call(). This function will block if * the results haven't yet been received; use - * dbus_g_pending_call_set_notify() to be notified asynchronously that a - * pending call has been completed. If it's completed, it will not block. + * dbus_pending_call_set_notify() to be notified asynchronously that a + * pending call has been completed. Use + * dbus_pending_call_get_completed() to check whether a call has been + * completed. If it's completed, it will not block. * * If the call results in an error, the error is set as normal for * GError and the function returns #FALSE. * * Otherwise, the "out" parameters and return value of the * method are stored in the provided varargs list. - * The list should be terminated with #DBUS_TYPE_INVALID. + * The list should be terminated with DBUS_TYPE_INVALID. * * This function doesn't affect the reference count of the - * #DBusGPendingCall, the caller of dbus_g_proxy_begin_call() still owns + * #DBusPendingCall, the caller of dbus_g_proxy_begin_call() still owns * a reference. * - * @todo this should be changed to make a g_malloc() copy of the - * data returned probably; right now the data vanishes - * when you free the PendingCall which is sort of strange. - * * @param proxy a proxy for a remote interface * @param pending the pending call from dbus_g_proxy_begin_call() * @param error return location for an error * @param first_arg_type type of first "out" argument - * @returns #FALSE if an error is set - */ + * @returns #FALSE if an error is set */ gboolean dbus_g_proxy_end_call (DBusGProxy *proxy, - DBusGPendingCall *pending, - GError **error, - int first_arg_type, - ...) + DBusGPendingCall *pending, + GError **error, + int first_arg_type, + ...) { DBusMessage *message; va_list args; DBusError derror; g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); g_return_val_if_fail (pending != NULL, FALSE); dbus_pending_call_block (DBUS_PENDING_CALL_FROM_G_PENDING_CALL (pending)); @@ -1393,214 +1167,11 @@ dbus_g_proxy_end_call (DBusGProxy *proxy, error: dbus_message_unref (message); - dbus_set_g_error (error, &derror); dbus_error_free (&derror); return FALSE; } -/** - * Function for invoking a method and receiving reply values. - * Normally this is not used directly - calls to it are generated - * from client-side wrappers (see dbus-binding-tool). - * - * This function takes two type signatures, one for method arguments, - * and one for return values. The remaining arguments after the - * error parameter should be values of the input arguments, - * followed by pointer values to storage for return values. - * - * @param proxy a proxy for a remote interface - * @param method method to invoke - * @param insig signature of input values - * @param outsig signature of output values - * @param error return location for an error - * @returns #FALSE if an error is set, TRUE otherwise - */ -gboolean -dbus_g_proxy_invoke (DBusGProxy *proxy, - const char *method, - const char *insig, - const char *outsig, - GError **error, - ...) -{ - DBusPendingCall *pending; - DBusMessage *message; - DBusMessage *reply; - va_list args; - va_list args_unwind; - int n_retvals_processed; - DBusMessageIter msgiter; - DBusSignatureIter sigiter; - int expected_type; - gboolean ret; - DBusError derror; - - g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); - g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); - - va_start (args, error); - /* Keep around a copy of output arguments so we - * can free on error. */ - G_VA_COPY (args_unwind, args); - - ret = FALSE; - pending = NULL; - reply = NULL; - n_retvals_processed = 0; - message = dbus_message_new_method_call (proxy->name, - proxy->path, - proxy->interface, - method); - if (message == NULL) - goto oom; - - dbus_signature_iter_init (&sigiter, insig); - dbus_message_iter_init_append (message, &msgiter); - while ((expected_type = dbus_signature_iter_get_current_type (&sigiter)) != DBUS_TYPE_INVALID) - { - GValue gvalue = {0, }; - char *collect_err; - - if (!dbus_gvalue_init (expected_type, &gvalue)) - { - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Unsupported type '%c'"), expected_type); - goto out; - } - - G_VALUE_COLLECT (&gvalue, args, G_VALUE_NOCOPY_CONTENTS, &collect_err); - - if (collect_err) - { - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - collect_err); - goto out; - } - - /* Anything we can init must be marshallable */ - if (!dbus_gvalue_marshal (&msgiter, &gvalue)) - g_assert_not_reached (); - g_value_unset (&gvalue); - - dbus_signature_iter_next (&sigiter); - } - - if (!dbus_connection_send_with_reply (proxy->manager->connection, - message, - &pending, - -1)) - goto oom; - - dbus_pending_call_block (pending); - reply = dbus_pending_call_steal_reply (pending); - - g_assert (reply != NULL); - - dbus_error_init (&derror); - - switch (dbus_message_get_type (reply)) - { - case DBUS_MESSAGE_TYPE_METHOD_RETURN: - - dbus_signature_iter_init (&sigiter, outsig); - dbus_message_iter_init (reply, &msgiter); - while ((expected_type = dbus_signature_iter_get_current_type (&sigiter)) != DBUS_TYPE_INVALID) - { - int arg_type; - gpointer *value_ret; - GValue gvalue = { 0, }; - - value_ret = va_arg (args, gpointer *); - - arg_type = dbus_message_iter_get_arg_type (&msgiter); - if (expected_type != arg_type) - { - if (arg_type == DBUS_TYPE_INVALID) - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Too few arguments in reply")); - else - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Reply argument was \"%c\", expected \"%c\""), - arg_type, expected_type); - goto out; - } - - if (!dbus_gvalue_demarshal (&msgiter, &gvalue)) - { - g_set_error (error, - DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Couldn't convert argument type \"%c\""), expected_type); - goto out; - } - /* Anything that can be demarshaled must be storable */ - if (!dbus_gvalue_store (&gvalue, value_ret)) - g_assert_not_reached (); - g_value_unset (&gvalue); - - n_retvals_processed++; - dbus_signature_iter_next (&sigiter); - dbus_message_iter_next (&msgiter); - } - if (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID) - { - g_set_error (error, DBUS_GERROR, - DBUS_GERROR_INVALID_ARGS, - _("Too many arguments")); - goto out; - } - break; - case DBUS_MESSAGE_TYPE_ERROR: - dbus_set_error_from_message (&derror, reply); - dbus_set_g_error (error, &derror); - dbus_error_free (&derror); - goto out; - break; - default: - dbus_set_error (&derror, DBUS_ERROR_FAILED, - "Reply was neither a method return nor an exception"); - dbus_set_g_error (error, &derror); - dbus_error_free (&derror); - goto out; - break; - } - - ret = TRUE; - out: - va_end (args); - - if (ret == FALSE) - { - int i; - for (i = 0; i < n_retvals_processed; i++) - { - gpointer retval; - - retval = va_arg (args_unwind, gpointer); - - g_free (retval); - } - } - va_end (args_unwind); - - if (pending) - dbus_pending_call_unref (pending); - if (message) - dbus_message_unref (message); - if (reply) - dbus_message_unref (reply); - return ret; - oom: - g_error ("Out of memory"); - ret = FALSE; - goto out; -} - /** * Sends a method call message as with dbus_g_proxy_begin_call(), but * does not ask for a reply or allow you to receive one. @@ -1622,9 +1193,8 @@ dbus_g_proxy_call_no_reply (DBusGProxy *proxy, va_list args; g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - message = dbus_message_new_method_call (proxy->name, + message = dbus_message_new_method_call (proxy->service, proxy->path, proxy->interface, method); @@ -1657,7 +1227,7 @@ dbus_g_proxy_call_no_reply (DBusGProxy *proxy, * dbus_connection_flush(). * * The message is modified to be addressed to the target interface. - * That is, a destination name field or whatever is needed will be + * That is, a destination service field or whatever is needed will be * added to the message. The basic point of this function is to add * the necessary header fields, otherwise it's equivalent to * dbus_connection_send(). @@ -1670,15 +1240,14 @@ dbus_g_proxy_call_no_reply (DBusGProxy *proxy, * @param client_serial return location for message's serial, or #NULL */ void dbus_g_proxy_send (DBusGProxy *proxy, - DBusMessage *message, - dbus_uint32_t *client_serial) + DBusMessage *message, + dbus_uint32_t *client_serial) { g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - if (proxy->name) + if (proxy->service) { - if (!dbus_message_set_destination (message, proxy->name)) + if (!dbus_message_set_destination (message, proxy->service)) g_error ("Out of memory"); } if (proxy->path) @@ -1696,50 +1265,15 @@ dbus_g_proxy_send (DBusGProxy *proxy, g_error ("Out of memory\n"); } -/** - * Specifies the signature of a signal, such that it's possible to - * connect to the signal on this proxy. - * - * @param proxy the proxy for a remote interface - * @param signal_name the name of the signal - * @param signature D-BUS signature of the signal - */ -void -dbus_g_proxy_add_signal (DBusGProxy *proxy, - const char *signal_name, - const char *signature) -{ - GQuark q; - char *name; - - g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); - g_return_if_fail (signal_name != NULL); - g_return_if_fail (signature != NULL); -#ifndef G_DISABLE_CHECKS - if (lookup_g_marshaller (proxy, signature) == NULL) - g_warning ("No marshaller for signature '%s', we need to add API for providing your own", - signature); -#endif - - name = create_signal_name (proxy->interface, signal_name); - - q = g_quark_from_string (name); - - g_return_if_fail (g_datalist_id_get_data (&proxy->signal_signatures, q) == NULL); - - g_datalist_id_set_data_full (&proxy->signal_signatures, - q, g_strdup (signature), - g_free); - - g_free (name); -} - /** * Connect a signal handler to a proxy for a remote interface. When * the remote interface emits the specified signal, the proxy will * emit a corresponding GLib signal. * + * @todo Right now there's no way to specify the signature to use + * for invoking the GCallback. Need to either rely on introspection, + * or require signature here. + * * @param proxy a proxy for a remote interface * @param signal_name the DBus signal name to listen for * @param handler the handler to connect @@ -1748,41 +1282,27 @@ dbus_g_proxy_add_signal (DBusGProxy *proxy, */ void dbus_g_proxy_connect_signal (DBusGProxy *proxy, - const char *signal_name, - GCallback handler, - void *data, - GClosureNotify free_data_func) + const char *signal_name, + GCallback handler, + void *data, + GClosureNotify free_data_func) { - char *name; GClosure *closure; - GQuark q; + char *detail; g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); g_return_if_fail (signal_name != NULL); g_return_if_fail (handler != NULL); - name = create_signal_name (proxy->interface, signal_name); - - q = g_quark_try_string (name); - -#ifndef G_DISABLE_CHECKS - if (q == 0 || g_datalist_id_get_data (&proxy->signal_signatures, q) == NULL) - { - g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name); - g_free (name); - return; - } -#endif + detail = create_signal_detail (proxy->interface, signal_name); closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func); - g_signal_connect_closure_by_id (G_OBJECT (proxy), signals[RECEIVED], - q, + g_quark_from_string (detail), closure, FALSE); - - g_free (name); + + g_free (detail); } /** @@ -1796,40 +1316,38 @@ dbus_g_proxy_connect_signal (DBusGProxy *proxy, */ void dbus_g_proxy_disconnect_signal (DBusGProxy *proxy, - const char *signal_name, - GCallback handler, - void *data) + const char *signal_name, + GCallback handler, + void *data) { - char *name; + char *detail; GQuark q; g_return_if_fail (DBUS_IS_G_PROXY (proxy)); - g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); g_return_if_fail (signal_name != NULL); g_return_if_fail (handler != NULL); - name = create_signal_name (proxy->interface, signal_name); + detail = create_signal_detail (proxy->interface, signal_name); + q = g_quark_try_string (detail); + g_free (detail); - q = g_quark_try_string (name); - - if (q != 0) - { - g_signal_handlers_disconnect_matched (G_OBJECT (proxy), - G_SIGNAL_MATCH_DETAIL | - G_SIGNAL_MATCH_FUNC | - G_SIGNAL_MATCH_DATA, - signals[RECEIVED], - q, - NULL, - G_CALLBACK (handler), data); - } - else +#ifndef G_DISABLE_CHECKS + if (q == 0) { - g_warning ("Attempt to disconnect from signal '%s' which is not registered\n", - name); + g_warning ("%s: No signal handlers for %s found on this DBusGProxy", + G_GNUC_FUNCTION, signal_name); + return; } +#endif - g_free (name); + g_signal_handlers_disconnect_matched (G_OBJECT (proxy), + G_SIGNAL_MATCH_DETAIL | + G_SIGNAL_MATCH_FUNC | + G_SIGNAL_MATCH_DATA, + signals[RECEIVED], + q, + NULL, + G_CALLBACK (handler), data); } /** @} End of DBusGLib public */ -- cgit