1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gcall.c convenience routines for calling methods, etc.
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "dbus-glib.h"
26 * @addtogroup DBusGLibInternals
32 * DBusGProxyManager's primary task is to route signals to the proxies
33 * those signals are emitted on. In order to do this it also has to
34 * track the owners of the services proxies are bound to.
38 GStaticMutex lock; /**< Thread lock */
39 int refcount; /**< Reference count */
40 DBusConnection *connection; /**< Connection we're associated with. */
45 /** Lock the DBusGProxyManager */
46 #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock))
47 /** Unlock the DBusGProxyManager */
48 #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock))
50 static int gproxy_manager_slot = -1;
52 /* Lock controlling get/set manager as data on each connection */
53 static GStaticMutex connection_gproxy_lock = G_STATIC_MUTEX_INIT;
55 static void dbus_gproxy_manager_ref (DBusGProxyManager *manager);
57 static DBusGProxyManager*
58 dbus_gproxy_manager_get (DBusConnection *connection)
60 DBusGProxyManager *manager;
62 dbus_connection_allocate_data_slot (&gproxy_manager_slot);
63 if (gproxy_manager_slot < 0)
64 g_error ("out of memory");
66 g_static_mutex_lock (&connection_gproxy_lock);
68 manager = dbus_connection_get_data (connection, gproxy_manager_slot);
71 dbus_connection_free_data_slot (&gproxy_manager_slot);
72 dbus_gproxy_manager_ref (manager);
73 g_static_mutex_unlock (&connection_gproxy_lock);
77 manager = g_new0 (DBusGProxyManager, 1);
79 manager->refcount = 1;
80 manager->connection = connection;
82 g_static_mutex_init (&manager->lock);
84 /* Proxy managers keep the connection alive, which means that
85 * DBusGProxy indirectly does. To free a connection you have to free
86 * all the proxies referring to it.
88 dbus_connection_ref (manager->connection);
90 dbus_connection_set_data (connection, gproxy_manager_slot,
93 g_static_mutex_unlock (&connection_gproxy_lock);
99 dbus_gproxy_manager_ref (DBusGProxyManager *manager)
101 g_assert (manager != NULL);
102 g_assert (manager->refcount > 0);
104 LOCK_MANAGER (manager);
106 manager->refcount += 1;
108 UNLOCK_MANAGER (manager);
112 dbus_gproxy_manager_unref (DBusGProxyManager *manager)
114 g_assert (manager != NULL);
115 g_assert (manager->refcount > 0);
117 LOCK_MANAGER (manager);
118 manager->refcount -= 1;
119 if (manager->refcount == 0)
121 UNLOCK_MANAGER (manager);
123 g_static_mutex_free (&manager->lock);
125 g_static_mutex_lock (&connection_gproxy_lock);
127 dbus_connection_set_data (manager->connection,
131 g_static_mutex_unlock (&connection_gproxy_lock);
133 dbus_connection_unref (manager->connection);
136 dbus_connection_free_data_slot (&gproxy_manager_slot);
140 UNLOCK_MANAGER (manager);
145 * Internals of DBusGProxy
149 GStaticMutex lock; /**< Thread lock */
150 int refcount; /**< Reference count */
151 DBusGProxyManager *manager; /**< Proxy manager */
152 char *service; /**< Service messages go to or NULL */
153 char *path; /**< Path messages go to or NULL */
154 char *interface; /**< Interface messages go to or NULL */
157 /** Lock the DBusGProxy */
158 #define LOCK_PROXY(proxy) (g_static_mutex_lock (&(proxy)->lock))
159 /** Unlock the DBusGProxy */
160 #define UNLOCK_PROXY(proxy) (g_static_mutex_unlock (&(proxy)->lock))
163 _dbus_gproxy_new (DBusConnection *connection)
167 proxy = g_new0 (DBusGProxy, 1);
170 proxy->manager = dbus_gproxy_manager_get (connection);
172 g_static_mutex_init (&proxy->lock);
177 /** @} End of DBusGLibInternals */
179 /** @addtogroup DBusGLib
184 * Creates a new proxy for a remote interface. Method calls and signal
185 * connections over this proxy will go to the service owner; the
186 * service owner is expected to support the given interface name. THE
187 * SERVICE OWNER MAY CHANGE OVER TIME, for example between two
188 * different method calls. If you need a fixed owner, you need to
189 * request the current owner and bind a proxy to that rather than to
190 * the generic service name; see dbus_gproxy_new_for_service_owner().
192 * A service-associated proxy only makes sense with a message bus,
193 * not for app-to-app direct dbus connections.
195 * @param connection the connection to the remote bus or app
196 * @param service_name name of the service on the message bus
197 * @param path_name name of the object inside the service to call methods on
198 * @param interface_name name of the interface to call methods on
199 * @returns new proxy object
202 dbus_gproxy_new_for_service (DBusConnection *connection,
203 const char *service_name,
204 const char *path_name,
205 const char *interface_name)
209 g_return_val_if_fail (connection != NULL, NULL);
210 g_return_val_if_fail (service_name != NULL, NULL);
211 g_return_val_if_fail (path_name != NULL, NULL);
212 g_return_val_if_fail (interface_name != NULL, NULL);
214 proxy = _dbus_gproxy_new (connection);
216 proxy->service = g_strdup (service_name);
217 proxy->path = g_strdup (path_name);
218 proxy->interface = g_strdup (interface_name);
224 * Increment reference count on proxy object.
226 * @todo use GAtomic to avoid locking
228 * @param proxy the proxy
231 dbus_gproxy_ref (DBusGProxy *proxy)
233 g_return_if_fail (proxy != NULL);
237 proxy->refcount += 1;
239 UNLOCK_PROXY (proxy);
243 * Decrement reference count on proxy object.
245 * @todo use GAtomic to avoid locking
247 * @param proxy the proxy
250 dbus_gproxy_unref (DBusGProxy *proxy)
252 g_return_if_fail (proxy != NULL);
256 proxy->refcount -= 1;
258 if (proxy->refcount == 0)
260 UNLOCK_PROXY (proxy);
262 dbus_gproxy_manager_unref (proxy->manager);
263 g_free (proxy->service);
264 g_free (proxy->path);
265 g_free (proxy->interface);
266 g_static_mutex_free (&proxy->lock);
271 UNLOCK_PROXY (proxy);
276 * Invokes a method on a remote interface. This function does not
277 * block; instead it returns an opaque #DBusPendingCall object that
278 * tracks the pending call. The method call will not be sent over the
279 * wire until the application returns to the main loop, or blocks in
280 * dbus_connection_flush() to write out pending data. The call will
281 * be completed after a timeout, or when a reply is received.
282 * To collect the results of the call (which may be an error,
283 * or a reply), use dbus_gproxy_end_call().
285 * @todo this particular function shouldn't die on out of memory,
286 * since you should be able to do a call with large arguments.
288 * @param proxy a proxy for a remote interface
289 * @param method the name of the method to invoke
290 * @param first_arg_type type of the first argument
292 * @returns opaque pending call object
295 dbus_gproxy_begin_call (DBusGProxy *proxy,
300 DBusPendingCall *pending;
301 DBusMessage *message;
304 g_return_val_if_fail (proxy != NULL, NULL);
307 message = dbus_message_new_method_call (proxy->service,
314 va_start (args, first_arg_type);
315 if (!dbus_message_append_args_valist (message, first_arg_type,
320 if (!dbus_connection_send_with_reply (proxy->manager->connection,
326 UNLOCK_PROXY (proxy);
331 /* FIXME we should create a pending call that's
332 * immediately completed with an error status without
333 * ever going on the wire.
336 g_error ("Out of memory");
341 * Collects the results of a method call. The method call was normally
342 * initiated with dbus_gproxy_end_call(). This function will block if
343 * the results haven't yet been received; use
344 * dbus_pending_call_set_notify() to be notified asynchronously that a
345 * pending call has been completed. Use
346 * dbus_pending_call_get_completed() to check whether a call has been
347 * completed. If it's completed, it will not block.
349 * If the call results in an error, the error is set as normal for
350 * GError and the function returns #FALSE.
352 * Otherwise, the "out" parameters and return value of the
353 * method are stored in the provided varargs list.
354 * The list should be terminated with DBUS_TYPE_INVALID.
356 * This function doesn't affect the reference count of the
357 * #DBusPendingCall, the caller of dbus_gproxy_begin_call() still owns
360 * @param proxy a proxy for a remote interface
361 * @param pending the pending call from dbus_gproxy_begin_call()
362 * @param error return location for an error
363 * @param first_arg_type type of first "out" argument
364 * @returns #FALSE if an error is set */
366 dbus_gproxy_end_call (DBusGProxy *proxy,
367 DBusPendingCall *pending,
372 DBusMessage *message;
376 g_return_val_if_fail (proxy != NULL, FALSE);
377 g_return_val_if_fail (pending != NULL, FALSE);
381 dbus_pending_call_block (pending);
382 message = dbus_pending_call_get_reply (pending);
384 g_assert (message != NULL);
386 dbus_error_init (&derror);
387 va_start (args, first_arg_type);
388 if (!dbus_message_get_args_valist (message, &derror, first_arg_type, args))
395 UNLOCK_PROXY (proxy);
400 dbus_set_g_error (error, &derror);
401 dbus_error_free (&derror);
406 * Sends a message to the interface we're proxying for. Does not
407 * block or wait for a reply. The message is only actually written out
408 * when you return to the main loop or block in
409 * dbus_connection_flush().
411 * The message is modified to be addressed to the target interface.
412 * That is, a destination service field or whatever is needed will be
413 * added to the message. The basic point of this function is to add
414 * the necessary header fields, otherwise it's equivalent to
415 * dbus_connection_send().
417 * This function adds a reference to the message, so the caller
418 * still owns its original reference.
420 * @param proxy a proxy for a remote interface
421 * @param message the message to address and send
422 * @param client_serial return location for message's serial, or #NULL */
424 dbus_gproxy_send (DBusGProxy *proxy,
425 DBusMessage *message,
426 dbus_uint32_t *client_serial)
428 g_return_if_fail (proxy != NULL);
433 if (!dbus_message_set_destination (message, proxy->service))
434 g_error ("Out of memory");
438 if (!dbus_message_set_path (message, proxy->path))
439 g_error ("Out of memory");
441 if (proxy->interface)
443 if (!dbus_message_set_interface (message, proxy->interface))
444 g_error ("Out of memory");
447 if (!dbus_connection_send (proxy->manager->connection, message, client_serial))
448 g_error ("Out of memory\n");
450 UNLOCK_PROXY (proxy);
453 /** @} End of DBusGLib public */
455 #ifdef DBUS_BUILD_TESTS
458 * @ingroup DBusGLibInternals
459 * Unit test for GLib proxy functions
460 * @returns #TRUE on success.
463 _dbus_gproxy_test (void)
469 #endif /* DBUS_BUILD_TESTS */