|
1 /* -*- mode: C; c-file-style: "gnu" -*- */ |
|
2 /* dbus-gproxy.c Proxy for remote objects |
|
3 * |
|
4 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. |
|
5 * Copyright (C) 2005 Nokia |
|
6 * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
7 * Licensed under the Academic Free License version 2.1 |
|
8 * |
|
9 * This program is free software; you can redistribute it and/or modify |
|
10 * it under the terms of the GNU General Public License as published by |
|
11 * the Free Software Foundation; either version 2 of the License, or |
|
12 * (at your option) any later version. |
|
13 * |
|
14 * This program is distributed in the hope that it will be useful, |
|
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 * GNU General Public License for more details. |
|
18 * |
|
19 * You should have received a copy of the GNU General Public License |
|
20 * along with this program; if not, write to the Free Software |
|
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
22 * |
|
23 */ |
|
24 #include <dbus/dbus-glib.h> |
|
25 #include <dbus/dbus-glib-lowlevel.h> |
|
26 #include <dbus/dbus-signature.h> |
|
27 #include "dbus-gutils.h" |
|
28 #include "dbus-gsignature.h" |
|
29 #include "dbus-gvalue.h" |
|
30 #include "dbus-gvalue-utils.h" |
|
31 #include "dbus-gobject.h" |
|
32 #include <string.h> |
|
33 |
|
34 |
|
35 #ifdef __SYMBIAN32__ |
|
36 #include<glib_global.h> |
|
37 #include<glib-object.h> |
|
38 #endif |
|
39 |
|
40 #ifndef __SYMBIAN32__ |
|
41 #include <glib/gi18n.h> |
|
42 #include <libintl.h> |
|
43 #define _(x) dgettext (GETTEXT_PACKAGE, x) |
|
44 #define N_(x) x |
|
45 #else |
|
46 |
|
47 #define _(x) x |
|
48 #define N_(x) x |
|
49 #endif |
|
50 |
|
51 #include <gobject/gvaluecollector.h> |
|
52 |
|
53 #ifdef __SYMBIAN32__ |
|
54 #include "libdbus_glib_wsd_solution.h" |
|
55 #endif |
|
56 |
|
57 #define DBUS_G_PROXY_CALL_TO_ID(x) (GPOINTER_TO_UINT(x)) |
|
58 #define DBUS_G_PROXY_ID_TO_CALL(x) (GUINT_TO_POINTER(x)) |
|
59 #define DBUS_G_PROXY_GET_PRIVATE(o) \ |
|
60 (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TYPE_G_PROXY, DBusGProxyPrivate)) |
|
61 |
|
62 |
|
63 /** |
|
64 * @addtogroup DBusGLibInternals |
|
65 * |
|
66 * @{ |
|
67 */ |
|
68 |
|
69 /** |
|
70 * DBusGProxyManager typedef |
|
71 */ |
|
72 |
|
73 typedef struct _DBusGProxyManager DBusGProxyManager; |
|
74 |
|
75 typedef struct _DBusGProxyPrivate DBusGProxyPrivate; |
|
76 |
|
77 /** |
|
78 * Internals of DBusGProxy |
|
79 */ |
|
80 struct _DBusGProxyPrivate |
|
81 { |
|
82 DBusGProxyManager *manager; /**< Proxy manager */ |
|
83 char *name; /**< Name messages go to or NULL */ |
|
84 char *path; /**< Path messages go to or NULL */ |
|
85 char *interface; /**< Interface messages go to or NULL */ |
|
86 |
|
87 DBusGProxyCall *name_call; /**< Pending call id to retrieve name owner */ |
|
88 guint for_owner : 1; /**< Whether or not this proxy is for a name owner */ |
|
89 guint associated : 1; /**< Whether or not this proxy is associated (for name proxies) */ |
|
90 |
|
91 /* FIXME: make threadsafe? */ |
|
92 guint call_id_counter; /**< Integer counter for pending calls */ |
|
93 |
|
94 GData *signal_signatures; /**< D-BUS signatures for each signal */ |
|
95 |
|
96 GHashTable *pending_calls; /**< Calls made on this proxy which have not yet returned */ |
|
97 }; |
|
98 |
|
99 static void dbus_g_proxy_init (DBusGProxy *proxy); |
|
100 static void dbus_g_proxy_class_init (DBusGProxyClass *klass); |
|
101 static GObject *dbus_g_proxy_constructor (GType type, |
|
102 guint n_construct_properties, |
|
103 GObjectConstructParam *construct_properties); |
|
104 static void dbus_g_proxy_set_property (GObject *object, |
|
105 guint prop_id, |
|
106 const GValue *value, |
|
107 GParamSpec *pspec); |
|
108 static void dbus_g_proxy_get_property (GObject *object, |
|
109 guint prop_id, |
|
110 GValue *value, |
|
111 GParamSpec *pspec); |
|
112 |
|
113 static void dbus_g_proxy_finalize (GObject *object); |
|
114 static void dbus_g_proxy_dispose (GObject *object); |
|
115 static void dbus_g_proxy_destroy (DBusGProxy *proxy); |
|
116 static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, |
|
117 DBusMessage *message); |
|
118 |
|
119 static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager *manager, |
|
120 const char *method, |
|
121 DBusGProxyCallNotify notify, |
|
122 gpointer data, |
|
123 GDestroyNotify destroy, |
|
124 GType first_arg_type, |
|
125 ...); |
|
126 static guint dbus_g_proxy_begin_call_internal (DBusGProxy *proxy, |
|
127 const char *method, |
|
128 DBusGProxyCallNotify notify, |
|
129 gpointer data, |
|
130 GDestroyNotify destroy, |
|
131 GValueArray *args, |
|
132 int timeout ); |
|
133 static gboolean dbus_g_proxy_end_call_internal (DBusGProxy *proxy, |
|
134 guint call_id, |
|
135 GError **error, |
|
136 GType first_arg_type, |
|
137 va_list args); |
|
138 |
|
139 /** |
|
140 * A list of proxies with a given name+path+interface, used to |
|
141 * route incoming signals. |
|
142 */ |
|
143 typedef struct |
|
144 { |
|
145 GSList *proxies; /**< The list of proxies */ |
|
146 |
|
147 char name[4]; /**< name (empty string for none), nul byte, |
|
148 * path, nul byte, |
|
149 * interface, nul byte |
|
150 */ |
|
151 |
|
152 } DBusGProxyList; |
|
153 |
|
154 /** |
|
155 * DBusGProxyManager's primary task is to route signals to the proxies |
|
156 * those signals are emitted on. In order to do this it also has to |
|
157 * track the owners of the names proxies are bound to. |
|
158 */ |
|
159 struct _DBusGProxyManager |
|
160 { |
|
161 GStaticMutex lock; /**< Thread lock */ |
|
162 int refcount; /**< Reference count */ |
|
163 DBusConnection *connection; /**< Connection we're associated with. */ |
|
164 |
|
165 DBusGProxy *bus_proxy; /**< Special internal proxy used to talk to the bus */ |
|
166 |
|
167 GHashTable *proxy_lists; /**< Hash used to route incoming signals |
|
168 * and iterate over proxies |
|
169 */ |
|
170 GHashTable *owner_names; /**< Hash to keep track of mapping from |
|
171 * base name -> [name,name,...] for proxies which |
|
172 * are for names. |
|
173 */ |
|
174 GSList *unassociated_proxies; /**< List of name proxies for which |
|
175 * there was no result for |
|
176 * GetNameOwner |
|
177 */ |
|
178 }; |
|
179 |
|
180 static DBusGProxyManager *dbus_g_proxy_manager_ref (DBusGProxyManager *manager); |
|
181 static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection, |
|
182 DBusMessage *message, |
|
183 void *user_data); |
|
184 |
|
185 |
|
186 /** Lock the DBusGProxyManager */ |
|
187 #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock)) |
|
188 /** Unlock the DBusGProxyManager */ |
|
189 #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock)) |
|
190 |
|
191 |
|
192 #if EMULATOR |
|
193 GET_STATIC_VAR_FROM_TLS(g_proxy_manager_slot,dbus_gproxy,int ) |
|
194 #define g_proxy_manager_slot (*GET_DBUS_WSD_VAR_NAME(g_proxy_manager_slot,dbus_gproxy,s)()) |
|
195 GET_STATIC_VAR_FROM_TLS(connection_g_proxy_lock,dbus_gproxy,GStaticMutex ) |
|
196 #define connection_g_proxy_lock (*GET_DBUS_WSD_VAR_NAME(connection_g_proxy_lock,dbus_gproxy,s)()) |
|
197 |
|
198 #else |
|
199 static int g_proxy_manager_slot = -1; |
|
200 /* Lock controlling get/set manager as data on each connection */ |
|
201 static GStaticMutex connection_g_proxy_lock = G_STATIC_MUTEX_INIT; |
|
202 |
|
203 #endif |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 static DBusGProxyManager* |
|
209 dbus_g_proxy_manager_get (DBusConnection *connection) |
|
210 { |
|
211 DBusGProxyManager *manager; |
|
212 |
|
213 dbus_connection_allocate_data_slot (&g_proxy_manager_slot); |
|
214 if (g_proxy_manager_slot < 0) |
|
215 g_error ("out of memory"); |
|
216 |
|
217 g_static_mutex_lock (&connection_g_proxy_lock); |
|
218 |
|
219 manager = dbus_connection_get_data (connection, g_proxy_manager_slot); |
|
220 if (manager != NULL) |
|
221 { |
|
222 dbus_connection_free_data_slot (&g_proxy_manager_slot); |
|
223 dbus_g_proxy_manager_ref (manager); |
|
224 g_static_mutex_unlock (&connection_g_proxy_lock); |
|
225 return manager; |
|
226 } |
|
227 |
|
228 manager = g_new0 (DBusGProxyManager, 1); |
|
229 |
|
230 manager->refcount = 1; |
|
231 manager->connection = connection; |
|
232 |
|
233 g_static_mutex_init (&manager->lock); |
|
234 |
|
235 /* Proxy managers keep the connection alive, which means that |
|
236 * DBusGProxy indirectly does. To free a connection you have to free |
|
237 * all the proxies referring to it. |
|
238 */ |
|
239 dbus_connection_ref (manager->connection); |
|
240 |
|
241 dbus_connection_set_data (connection, g_proxy_manager_slot, |
|
242 manager, NULL); |
|
243 |
|
244 dbus_connection_add_filter (connection, dbus_g_proxy_manager_filter, |
|
245 manager, NULL); |
|
246 |
|
247 g_static_mutex_unlock (&connection_g_proxy_lock); |
|
248 |
|
249 return manager; |
|
250 } |
|
251 |
|
252 static DBusGProxyManager * |
|
253 dbus_g_proxy_manager_ref (DBusGProxyManager *manager) |
|
254 { |
|
255 g_assert (manager != NULL); |
|
256 g_assert (manager->refcount > 0); |
|
257 |
|
258 LOCK_MANAGER (manager); |
|
259 |
|
260 manager->refcount += 1; |
|
261 |
|
262 UNLOCK_MANAGER (manager); |
|
263 |
|
264 return manager; |
|
265 } |
|
266 |
|
267 static void |
|
268 dbus_g_proxy_manager_unref (DBusGProxyManager *manager) |
|
269 { |
|
270 g_assert (manager != NULL); |
|
271 g_assert (manager->refcount > 0); |
|
272 |
|
273 LOCK_MANAGER (manager); |
|
274 manager->refcount -= 1; |
|
275 if (manager->refcount == 0) |
|
276 { |
|
277 UNLOCK_MANAGER (manager); |
|
278 |
|
279 if (manager->bus_proxy) |
|
280 g_object_unref (manager->bus_proxy); |
|
281 |
|
282 if (manager->proxy_lists) |
|
283 { |
|
284 /* can't have any proxies left since they hold |
|
285 * a reference to the proxy manager. |
|
286 */ |
|
287 g_assert (g_hash_table_size (manager->proxy_lists) == 0); |
|
288 |
|
289 g_hash_table_destroy (manager->proxy_lists); |
|
290 manager->proxy_lists = NULL; |
|
291 |
|
292 } |
|
293 |
|
294 if (manager->owner_names) |
|
295 { |
|
296 /* Since we destroyed all proxies, none can be tracking |
|
297 * name owners |
|
298 */ |
|
299 g_assert (g_hash_table_size (manager->owner_names) == 0); |
|
300 |
|
301 g_hash_table_destroy (manager->owner_names); |
|
302 manager->owner_names = NULL; |
|
303 } |
|
304 |
|
305 g_assert (manager->unassociated_proxies == NULL); |
|
306 |
|
307 g_static_mutex_free (&manager->lock); |
|
308 |
|
309 g_static_mutex_lock (&connection_g_proxy_lock); |
|
310 |
|
311 dbus_connection_remove_filter (manager->connection, dbus_g_proxy_manager_filter, |
|
312 manager); |
|
313 |
|
314 dbus_connection_set_data (manager->connection, |
|
315 g_proxy_manager_slot, |
|
316 NULL, NULL); |
|
317 |
|
318 g_static_mutex_unlock (&connection_g_proxy_lock); |
|
319 |
|
320 dbus_connection_unref (manager->connection); |
|
321 g_free (manager); |
|
322 |
|
323 dbus_connection_free_data_slot (&g_proxy_manager_slot); |
|
324 } |
|
325 else |
|
326 { |
|
327 UNLOCK_MANAGER (manager); |
|
328 } |
|
329 } |
|
330 |
|
331 static guint |
|
332 tristring_hash (gconstpointer key) |
|
333 { |
|
334 const char *p = key; |
|
335 guint h = *p; |
|
336 |
|
337 if (h) |
|
338 { |
|
339 for (p += 1; *p != '\0'; p++) |
|
340 h = (h << 5) - h + *p; |
|
341 } |
|
342 |
|
343 /* skip nul and do the next substring */ |
|
344 for (p += 1; *p != '\0'; p++) |
|
345 h = (h << 5) - h + *p; |
|
346 |
|
347 /* skip nul again and another substring */ |
|
348 for (p += 1; *p != '\0'; p++) |
|
349 h = (h << 5) - h + *p; |
|
350 |
|
351 return h; |
|
352 } |
|
353 |
|
354 static gboolean |
|
355 strequal_len (const char *a, |
|
356 const char *b, |
|
357 size_t *lenp) |
|
358 { |
|
359 size_t a_len; |
|
360 size_t b_len; |
|
361 |
|
362 a_len = strlen (a); |
|
363 b_len = strlen (b); |
|
364 |
|
365 if (a_len != b_len) |
|
366 return FALSE; |
|
367 |
|
368 if (memcmp (a, b, a_len) != 0) |
|
369 return FALSE; |
|
370 |
|
371 *lenp = a_len; |
|
372 |
|
373 return TRUE; |
|
374 } |
|
375 |
|
376 static gboolean |
|
377 tristring_equal (gconstpointer a, |
|
378 gconstpointer b) |
|
379 { |
|
380 const char *ap = a; |
|
381 const char *bp = b; |
|
382 size_t len; |
|
383 |
|
384 if (!strequal_len (ap, bp, &len)) |
|
385 return FALSE; |
|
386 |
|
387 ap += len + 1; |
|
388 bp += len + 1; |
|
389 |
|
390 if (!strequal_len (ap, bp, &len)) |
|
391 return FALSE; |
|
392 |
|
393 ap += len + 1; |
|
394 bp += len + 1; |
|
395 |
|
396 if (strcmp (ap, bp) != 0) |
|
397 return FALSE; |
|
398 |
|
399 return TRUE; |
|
400 } |
|
401 |
|
402 static char* |
|
403 tristring_alloc_from_strings (size_t padding_before, |
|
404 const char *name, |
|
405 const char *path, |
|
406 const char *interface) |
|
407 { |
|
408 size_t name_len, iface_len, path_len, len; |
|
409 char *tri; |
|
410 |
|
411 if (name) |
|
412 name_len = strlen (name); |
|
413 else |
|
414 name_len = 0; |
|
415 |
|
416 path_len = strlen (path); |
|
417 |
|
418 iface_len = strlen (interface); |
|
419 |
|
420 tri = g_malloc (padding_before + name_len + path_len + iface_len + 3); |
|
421 |
|
422 len = padding_before; |
|
423 |
|
424 if (name) |
|
425 memcpy (&tri[len], name, name_len); |
|
426 |
|
427 len += name_len; |
|
428 tri[len] = '\0'; |
|
429 len += 1; |
|
430 |
|
431 g_assert (len == (padding_before + name_len + 1)); |
|
432 |
|
433 memcpy (&tri[len], path, path_len); |
|
434 len += path_len; |
|
435 tri[len] = '\0'; |
|
436 len += 1; |
|
437 |
|
438 g_assert (len == (padding_before + name_len + path_len + 2)); |
|
439 |
|
440 memcpy (&tri[len], interface, iface_len); |
|
441 len += iface_len; |
|
442 tri[len] = '\0'; |
|
443 len += 1; |
|
444 |
|
445 g_assert (len == (padding_before + name_len + path_len + iface_len + 3)); |
|
446 |
|
447 return tri; |
|
448 } |
|
449 |
|
450 static char* |
|
451 tristring_from_proxy (DBusGProxy *proxy) |
|
452 { |
|
453 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
454 |
|
455 return tristring_alloc_from_strings (0, |
|
456 priv->name, |
|
457 priv->path, |
|
458 priv->interface); |
|
459 } |
|
460 |
|
461 static char* |
|
462 tristring_from_message (DBusMessage *message) |
|
463 { |
|
464 const char *path; |
|
465 const char *interface; |
|
466 |
|
467 path = dbus_message_get_path (message); |
|
468 interface = dbus_message_get_interface (message); |
|
469 |
|
470 g_assert (path); |
|
471 g_assert (interface); |
|
472 |
|
473 return tristring_alloc_from_strings (0, |
|
474 dbus_message_get_sender (message), |
|
475 path, interface); |
|
476 } |
|
477 |
|
478 static DBusGProxyList* |
|
479 g_proxy_list_new (DBusGProxy *first_proxy) |
|
480 { |
|
481 DBusGProxyList *list; |
|
482 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(first_proxy); |
|
483 |
|
484 list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name), |
|
485 priv->name, |
|
486 priv->path, |
|
487 priv->interface); |
|
488 list->proxies = NULL; |
|
489 |
|
490 return list; |
|
491 } |
|
492 |
|
493 static void |
|
494 g_proxy_list_free (DBusGProxyList *list) |
|
495 { |
|
496 /* we don't hold a reference to the proxies in the list, |
|
497 * as they ref the GProxyManager |
|
498 */ |
|
499 g_slist_free (list->proxies); |
|
500 |
|
501 g_free (list); |
|
502 } |
|
503 |
|
504 static char* |
|
505 g_proxy_get_match_rule (DBusGProxy *proxy) |
|
506 { |
|
507 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
508 /* FIXME Escaping is required here */ |
|
509 |
|
510 if (priv->name) |
|
511 return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'", |
|
512 priv->name, priv->path, priv->interface); |
|
513 else |
|
514 return g_strdup_printf ("type='signal',path='%s',interface='%s'", |
|
515 priv->path, priv->interface); |
|
516 } |
|
517 |
|
518 typedef struct |
|
519 { |
|
520 char *name; |
|
521 guint refcount; |
|
522 } DBusGProxyNameOwnerInfo; |
|
523 |
|
524 static gint |
|
525 find_name_in_info (gconstpointer a, gconstpointer b) |
|
526 { |
|
527 const DBusGProxyNameOwnerInfo *info = a; |
|
528 const char *name = b; |
|
529 |
|
530 return strcmp (info->name, name); |
|
531 } |
|
532 |
|
533 typedef struct |
|
534 { |
|
535 const char *name; |
|
536 const char *owner; |
|
537 DBusGProxyNameOwnerInfo *info; |
|
538 } DBusGProxyNameOwnerForeachData; |
|
539 |
|
540 static void |
|
541 name_owner_foreach (gpointer key, gpointer val, gpointer data) |
|
542 { |
|
543 const char *owner; |
|
544 DBusGProxyNameOwnerForeachData *foreach_data; |
|
545 GSList *names; |
|
546 GSList *link; |
|
547 |
|
548 owner = key; |
|
549 names = val; |
|
550 foreach_data = data; |
|
551 |
|
552 if (foreach_data->owner != NULL) |
|
553 return; |
|
554 |
|
555 g_assert (foreach_data->info == NULL); |
|
556 |
|
557 link = g_slist_find_custom (names, foreach_data->name, find_name_in_info); |
|
558 if (link) |
|
559 { |
|
560 foreach_data->owner = owner; |
|
561 foreach_data->info = link->data; |
|
562 } |
|
563 } |
|
564 |
|
565 static gboolean |
|
566 dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager *manager, |
|
567 const char *name, |
|
568 DBusGProxyNameOwnerInfo **info, |
|
569 const char **owner) |
|
570 { |
|
571 DBusGProxyNameOwnerForeachData foreach_data; |
|
572 |
|
573 foreach_data.name = name; |
|
574 foreach_data.owner = NULL; |
|
575 foreach_data.info = NULL; |
|
576 |
|
577 g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data); |
|
578 |
|
579 *info = foreach_data.info; |
|
580 *owner = foreach_data.owner; |
|
581 return *info != NULL; |
|
582 } |
|
583 |
|
584 static void |
|
585 insert_nameinfo (DBusGProxyManager *manager, |
|
586 const char *owner, |
|
587 DBusGProxyNameOwnerInfo *info) |
|
588 { |
|
589 GSList *names; |
|
590 gboolean insert; |
|
591 |
|
592 names = g_hash_table_lookup (manager->owner_names, owner); |
|
593 |
|
594 /* Only need to g_hash_table_insert the first time */ |
|
595 insert = (names == NULL); |
|
596 |
|
597 names = g_slist_append (names, info); |
|
598 |
|
599 if (insert) |
|
600 g_hash_table_insert (manager->owner_names, g_strdup (owner), names); |
|
601 } |
|
602 |
|
603 static void |
|
604 dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager *manager, |
|
605 const char *owner, |
|
606 const char *name) |
|
607 { |
|
608 GSList *names; |
|
609 GSList *link; |
|
610 DBusGProxyNameOwnerInfo *nameinfo; |
|
611 |
|
612 names = g_hash_table_lookup (manager->owner_names, owner); |
|
613 link = g_slist_find_custom (names, name, find_name_in_info); |
|
614 |
|
615 if (!link) |
|
616 { |
|
617 nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1); |
|
618 nameinfo->name = g_strdup (name); |
|
619 nameinfo->refcount = 1; |
|
620 |
|
621 insert_nameinfo (manager, owner, nameinfo); |
|
622 } |
|
623 else |
|
624 { |
|
625 nameinfo = link->data; |
|
626 nameinfo->refcount++; |
|
627 } |
|
628 } |
|
629 |
|
630 static void |
|
631 dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager *manager, |
|
632 const char *name) |
|
633 { |
|
634 DBusGProxyNameOwnerInfo *info; |
|
635 const char *owner; |
|
636 gboolean ret; |
|
637 |
|
638 ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner); |
|
639 g_assert (ret); |
|
640 g_assert (info != NULL); |
|
641 g_assert (owner != NULL); |
|
642 |
|
643 info->refcount--; |
|
644 if (info->refcount == 0) |
|
645 { |
|
646 GSList *names; |
|
647 GSList *link; |
|
648 |
|
649 names = g_hash_table_lookup (manager->owner_names, owner); |
|
650 link = g_slist_find_custom (names, name, find_name_in_info); |
|
651 names = g_slist_delete_link (names, link); |
|
652 if (names != NULL) |
|
653 g_hash_table_insert (manager->owner_names, g_strdup (owner), names); |
|
654 else |
|
655 g_hash_table_remove (manager->owner_names, owner); |
|
656 |
|
657 g_free (info->name); |
|
658 g_free (info); |
|
659 } |
|
660 } |
|
661 |
|
662 typedef struct |
|
663 { |
|
664 const char *name; |
|
665 GSList *destroyed; |
|
666 } DBusGProxyUnassociateData; |
|
667 |
|
668 static void |
|
669 unassociate_proxies (gpointer key, gpointer val, gpointer user_data) |
|
670 { |
|
671 DBusGProxyList *list; |
|
672 const char *name; |
|
673 GSList *tmp; |
|
674 DBusGProxyUnassociateData *data; |
|
675 |
|
676 list = val; |
|
677 data = user_data; |
|
678 name = data->name; |
|
679 |
|
680 for (tmp = list->proxies; tmp; tmp = tmp->next) |
|
681 { |
|
682 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data); |
|
683 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
684 DBusGProxyManager *manager; |
|
685 |
|
686 manager = priv->manager; |
|
687 |
|
688 if (!strcmp (priv->name, name)) |
|
689 { |
|
690 if (!priv->for_owner) |
|
691 { |
|
692 g_assert (priv->associated); |
|
693 g_assert (priv->name_call == NULL); |
|
694 |
|
695 priv->associated = FALSE; |
|
696 manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy); |
|
697 } |
|
698 else |
|
699 { |
|
700 data->destroyed = g_slist_prepend (data->destroyed, proxy); |
|
701 /* make contents of list into weak pointers in case the objects |
|
702 * unref each other when disposing */ |
|
703 g_object_add_weak_pointer (G_OBJECT (proxy), |
|
704 &(data->destroyed->data)); |
|
705 } |
|
706 } |
|
707 } |
|
708 } |
|
709 |
|
710 static void |
|
711 dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager *manager, |
|
712 const char *name, |
|
713 const char *prev_owner, |
|
714 const char *new_owner) |
|
715 { |
|
716 GSList *names; |
|
717 |
|
718 if (prev_owner[0] == '\0') |
|
719 { |
|
720 GSList *tmp; |
|
721 GSList *removed; |
|
722 |
|
723 /* We have a new service, look at unassociated proxies */ |
|
724 |
|
725 removed = NULL; |
|
726 |
|
727 for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next) |
|
728 { |
|
729 DBusGProxy *proxy = tmp->data; |
|
730 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
731 |
|
732 if (!strcmp (priv->name, name)) |
|
733 { |
|
734 removed = g_slist_prepend (removed, tmp); |
|
735 |
|
736 dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name); |
|
737 priv->associated = TRUE; |
|
738 } |
|
739 } |
|
740 |
|
741 for (tmp = removed; tmp; tmp = tmp->next) |
|
742 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data); |
|
743 g_slist_free (removed); |
|
744 } |
|
745 else |
|
746 { |
|
747 DBusGProxyNameOwnerInfo *info; |
|
748 GSList *link; |
|
749 |
|
750 /* Name owner changed or deleted */ |
|
751 |
|
752 names = g_hash_table_lookup (manager->owner_names, prev_owner); |
|
753 |
|
754 info = NULL; |
|
755 if (names != NULL) |
|
756 { |
|
757 link = g_slist_find_custom (names, name, find_name_in_info); |
|
758 |
|
759 if (link != NULL) |
|
760 { |
|
761 info = link->data; |
|
762 |
|
763 names = g_slist_delete_link (names, link); |
|
764 |
|
765 if (names == NULL) |
|
766 g_hash_table_remove (manager->owner_names, prev_owner); |
|
767 } |
|
768 } |
|
769 |
|
770 if (new_owner[0] == '\0') |
|
771 { |
|
772 DBusGProxyUnassociateData data; |
|
773 GSList *tmp; |
|
774 |
|
775 data.name = name; |
|
776 data.destroyed = NULL; |
|
777 |
|
778 /* A service went away, we need to unassociate proxies */ |
|
779 g_hash_table_foreach (manager->proxy_lists, |
|
780 unassociate_proxies, &data); |
|
781 |
|
782 UNLOCK_MANAGER (manager); |
|
783 |
|
784 /* the destroyed list's data pointers are weak pointers, so that we |
|
785 * don't end up calling destroy on proxies which have already been |
|
786 * freed up as a result of other ones being destroyed */ |
|
787 for (tmp = data.destroyed; tmp; tmp = tmp->next) |
|
788 if (tmp->data != NULL) |
|
789 { |
|
790 g_object_remove_weak_pointer (G_OBJECT (tmp->data), |
|
791 &(tmp->data)); |
|
792 dbus_g_proxy_destroy (tmp->data); |
|
793 } |
|
794 g_slist_free (data.destroyed); |
|
795 |
|
796 LOCK_MANAGER (manager); |
|
797 |
|
798 if (info) |
|
799 { |
|
800 g_free (info->name); |
|
801 g_free (info); |
|
802 } |
|
803 } |
|
804 else if (info) |
|
805 { |
|
806 insert_nameinfo (manager, new_owner, info); |
|
807 } |
|
808 } |
|
809 } |
|
810 |
|
811 static void |
|
812 got_name_owner_cb (DBusGProxy *bus_proxy, |
|
813 DBusGProxyCall *call, |
|
814 void *user_data) |
|
815 { |
|
816 DBusGProxy *proxy = user_data; |
|
817 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
818 GError *error; |
|
819 char *owner; |
|
820 |
|
821 error = NULL; |
|
822 owner = NULL; |
|
823 |
|
824 LOCK_MANAGER (priv->manager); |
|
825 |
|
826 if (!dbus_g_proxy_end_call (bus_proxy, call, &error, |
|
827 G_TYPE_STRING, &owner, |
|
828 G_TYPE_INVALID)) |
|
829 { |
|
830 if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER) |
|
831 { |
|
832 priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy); |
|
833 } |
|
834 else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) |
|
835 g_warning ("Couldn't get name owner (%s): %s", |
|
836 dbus_g_error_get_name (error), |
|
837 error->message); |
|
838 else |
|
839 g_warning ("Couldn't get name owner (code %d): %s", |
|
840 error->code, error->message); |
|
841 g_clear_error (&error); |
|
842 goto out; |
|
843 } |
|
844 else |
|
845 { |
|
846 dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name); |
|
847 priv->associated = TRUE; |
|
848 } |
|
849 |
|
850 out: |
|
851 priv->name_call = NULL; |
|
852 UNLOCK_MANAGER (priv->manager); |
|
853 g_free (owner); |
|
854 } |
|
855 |
|
856 static char * |
|
857 get_name_owner (DBusConnection *connection, |
|
858 const char *name, |
|
859 GError **error) |
|
860 { |
|
861 DBusError derror; |
|
862 DBusMessage *request, *reply; |
|
863 char *base_name; |
|
864 |
|
865 dbus_error_init (&derror); |
|
866 |
|
867 base_name = NULL; |
|
868 reply = NULL; |
|
869 |
|
870 request = dbus_message_new_method_call (DBUS_SERVICE_DBUS, |
|
871 DBUS_PATH_DBUS, |
|
872 DBUS_INTERFACE_DBUS, |
|
873 "GetNameOwner"); |
|
874 if (request == NULL) |
|
875 g_error ("Out of memory"); |
|
876 |
|
877 if (!dbus_message_append_args (request, |
|
878 DBUS_TYPE_STRING, &name, |
|
879 DBUS_TYPE_INVALID)) |
|
880 g_error ("Out of memory"); |
|
881 |
|
882 reply = |
|
883 dbus_connection_send_with_reply_and_block (connection, |
|
884 request, |
|
885 2000, &derror); |
|
886 if (reply == NULL) |
|
887 goto error; |
|
888 |
|
889 if (dbus_set_error_from_message (&derror, reply)) |
|
890 goto error; |
|
891 |
|
892 if (!dbus_message_get_args (reply, &derror, |
|
893 DBUS_TYPE_STRING, &base_name, |
|
894 DBUS_TYPE_INVALID)) |
|
895 goto error; |
|
896 |
|
897 base_name = g_strdup (base_name); |
|
898 goto out; |
|
899 |
|
900 error: |
|
901 g_assert (dbus_error_is_set (&derror)); |
|
902 dbus_set_g_error (error, &derror); |
|
903 dbus_error_free (&derror); |
|
904 |
|
905 out: |
|
906 if (request) |
|
907 dbus_message_unref (request); |
|
908 if (reply) |
|
909 dbus_message_unref (reply); |
|
910 |
|
911 return base_name; |
|
912 } |
|
913 |
|
914 |
|
915 static void |
|
916 dbus_g_proxy_manager_register (DBusGProxyManager *manager, |
|
917 DBusGProxy *proxy) |
|
918 { |
|
919 DBusGProxyList *list; |
|
920 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
921 |
|
922 LOCK_MANAGER (manager); |
|
923 |
|
924 if (manager->proxy_lists == NULL) |
|
925 { |
|
926 g_assert (manager->owner_names == NULL); |
|
927 |
|
928 list = NULL; |
|
929 manager->proxy_lists = g_hash_table_new_full (tristring_hash, |
|
930 tristring_equal, |
|
931 NULL, |
|
932 (GFreeFunc) g_proxy_list_free); |
|
933 manager->owner_names = g_hash_table_new_full (g_str_hash, |
|
934 g_str_equal, |
|
935 g_free, |
|
936 NULL); |
|
937 /* FIXME - for now we listen for all NameOwnerChanged; once |
|
938 * Anders' detail patch lands we should add individual rules |
|
939 */ |
|
940 dbus_bus_add_match (manager->connection, |
|
941 "type='signal',sender='" DBUS_SERVICE_DBUS |
|
942 "',path='" DBUS_PATH_DBUS |
|
943 "',interface='" DBUS_INTERFACE_DBUS |
|
944 "',member='NameOwnerChanged'", |
|
945 NULL); |
|
946 } |
|
947 else |
|
948 { |
|
949 char *tri; |
|
950 |
|
951 tri = tristring_from_proxy (proxy); |
|
952 |
|
953 list = g_hash_table_lookup (manager->proxy_lists, tri); |
|
954 |
|
955 g_free (tri); |
|
956 } |
|
957 |
|
958 if (list == NULL) |
|
959 { |
|
960 list = g_proxy_list_new (proxy); |
|
961 |
|
962 g_hash_table_replace (manager->proxy_lists, |
|
963 list->name, list); |
|
964 } |
|
965 |
|
966 if (list->proxies == NULL && priv->name) |
|
967 { |
|
968 /* We have to add the match rule to the server, |
|
969 * but only if the server is a message bus, |
|
970 * not if it's a peer. |
|
971 */ |
|
972 char *rule; |
|
973 |
|
974 rule = g_proxy_get_match_rule (proxy); |
|
975 |
|
976 /* We don't check for errors; it's not like anyone would handle them, and |
|
977 * we don't want a round trip here. |
|
978 */ |
|
979 dbus_bus_add_match (manager->connection, |
|
980 rule, NULL); |
|
981 |
|
982 g_free (rule); |
|
983 } |
|
984 |
|
985 g_assert (g_slist_find (list->proxies, proxy) == NULL); |
|
986 |
|
987 list->proxies = g_slist_prepend (list->proxies, proxy); |
|
988 |
|
989 if (!priv->for_owner) |
|
990 { |
|
991 const char *owner; |
|
992 DBusGProxyNameOwnerInfo *info; |
|
993 |
|
994 if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner)) |
|
995 { |
|
996 priv->name_call = manager_begin_bus_call (manager, "GetNameOwner", |
|
997 got_name_owner_cb, |
|
998 proxy, NULL, |
|
999 G_TYPE_STRING, |
|
1000 priv->name, |
|
1001 G_TYPE_INVALID); |
|
1002 |
|
1003 priv->associated = FALSE; |
|
1004 } |
|
1005 else |
|
1006 { |
|
1007 info->refcount++; |
|
1008 priv->associated = TRUE; |
|
1009 } |
|
1010 } |
|
1011 |
|
1012 UNLOCK_MANAGER (manager); |
|
1013 } |
|
1014 |
|
1015 static void |
|
1016 dbus_g_proxy_manager_unregister (DBusGProxyManager *manager, |
|
1017 DBusGProxy *proxy) |
|
1018 { |
|
1019 DBusGProxyList *list; |
|
1020 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1021 char *tri; |
|
1022 |
|
1023 LOCK_MANAGER (manager); |
|
1024 |
|
1025 #ifndef G_DISABLE_CHECKS |
|
1026 if (manager->proxy_lists == NULL) |
|
1027 { |
|
1028 g_warning ("Trying to unregister a proxy but there aren't any registered"); |
|
1029 return; |
|
1030 } |
|
1031 #endif |
|
1032 |
|
1033 tri = tristring_from_proxy (proxy); |
|
1034 |
|
1035 list = g_hash_table_lookup (manager->proxy_lists, tri); |
|
1036 |
|
1037 #ifndef G_DISABLE_CHECKS |
|
1038 if (list == NULL) |
|
1039 { |
|
1040 g_warning ("Trying to unregister a proxy but it isn't registered"); |
|
1041 return; |
|
1042 } |
|
1043 #endif |
|
1044 |
|
1045 g_assert (g_slist_find (list->proxies, proxy) != NULL); |
|
1046 |
|
1047 list->proxies = g_slist_remove (list->proxies, proxy); |
|
1048 |
|
1049 g_assert (g_slist_find (list->proxies, proxy) == NULL); |
|
1050 |
|
1051 if (!priv->for_owner) |
|
1052 { |
|
1053 if (!priv->associated) |
|
1054 { |
|
1055 GSList *link; |
|
1056 |
|
1057 if (priv->name_call != 0) |
|
1058 { |
|
1059 dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call); |
|
1060 priv->name_call = 0; |
|
1061 } |
|
1062 else |
|
1063 { |
|
1064 link = g_slist_find (manager->unassociated_proxies, proxy); |
|
1065 g_assert (link != NULL); |
|
1066 |
|
1067 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link); |
|
1068 } |
|
1069 } |
|
1070 else |
|
1071 { |
|
1072 g_assert (priv->name_call == 0); |
|
1073 |
|
1074 dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name); |
|
1075 } |
|
1076 } |
|
1077 |
|
1078 if (list->proxies == NULL) |
|
1079 { |
|
1080 char *rule; |
|
1081 g_hash_table_remove (manager->proxy_lists, |
|
1082 tri); |
|
1083 list = NULL; |
|
1084 |
|
1085 rule = g_proxy_get_match_rule (proxy); |
|
1086 dbus_bus_remove_match (manager->connection, |
|
1087 rule, NULL); |
|
1088 g_free (rule); |
|
1089 } |
|
1090 |
|
1091 if (g_hash_table_size (manager->proxy_lists) == 0) |
|
1092 { |
|
1093 g_hash_table_destroy (manager->proxy_lists); |
|
1094 manager->proxy_lists = NULL; |
|
1095 } |
|
1096 |
|
1097 g_free (tri); |
|
1098 |
|
1099 UNLOCK_MANAGER (manager); |
|
1100 } |
|
1101 |
|
1102 static void |
|
1103 list_proxies_foreach (gpointer key, |
|
1104 gpointer value, |
|
1105 gpointer user_data) |
|
1106 { |
|
1107 DBusGProxyList *list; |
|
1108 GSList **ret; |
|
1109 GSList *tmp; |
|
1110 |
|
1111 list = value; |
|
1112 ret = user_data; |
|
1113 |
|
1114 tmp = list->proxies; |
|
1115 while (tmp != NULL) |
|
1116 { |
|
1117 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data); |
|
1118 |
|
1119 g_object_ref (proxy); |
|
1120 *ret = g_slist_prepend (*ret, proxy); |
|
1121 |
|
1122 tmp = tmp->next; |
|
1123 } |
|
1124 } |
|
1125 |
|
1126 static GSList* |
|
1127 dbus_g_proxy_manager_list_all (DBusGProxyManager *manager) |
|
1128 { |
|
1129 GSList *ret; |
|
1130 |
|
1131 ret = NULL; |
|
1132 |
|
1133 if (manager->proxy_lists) |
|
1134 { |
|
1135 g_hash_table_foreach (manager->proxy_lists, |
|
1136 list_proxies_foreach, |
|
1137 &ret); |
|
1138 } |
|
1139 |
|
1140 return ret; |
|
1141 } |
|
1142 |
|
1143 static DBusHandlerResult |
|
1144 dbus_g_proxy_manager_filter (DBusConnection *connection, |
|
1145 DBusMessage *message, |
|
1146 void *user_data) |
|
1147 { |
|
1148 DBusGProxyManager *manager; |
|
1149 |
|
1150 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) |
|
1151 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
|
1152 |
|
1153 manager = user_data; |
|
1154 |
|
1155 dbus_g_proxy_manager_ref (manager); |
|
1156 |
|
1157 LOCK_MANAGER (manager); |
|
1158 |
|
1159 if (dbus_message_is_signal (message, |
|
1160 DBUS_INTERFACE_LOCAL, |
|
1161 "Disconnected")) |
|
1162 { |
|
1163 /* Destroy all the proxies, quite possibly resulting in unreferencing |
|
1164 * the proxy manager and the connection as well. |
|
1165 */ |
|
1166 GSList *all; |
|
1167 GSList *tmp; |
|
1168 |
|
1169 all = dbus_g_proxy_manager_list_all (manager); |
|
1170 |
|
1171 tmp = all; |
|
1172 while (tmp != NULL) |
|
1173 { |
|
1174 DBusGProxy *proxy; |
|
1175 |
|
1176 proxy = DBUS_G_PROXY (tmp->data); |
|
1177 |
|
1178 UNLOCK_MANAGER (manager); |
|
1179 dbus_g_proxy_destroy (proxy); |
|
1180 g_object_unref (G_OBJECT (proxy)); |
|
1181 LOCK_MANAGER (manager); |
|
1182 |
|
1183 tmp = tmp->next; |
|
1184 } |
|
1185 |
|
1186 g_slist_free (all); |
|
1187 |
|
1188 #ifndef G_DISABLE_CHECKS |
|
1189 if (manager->proxy_lists != NULL) |
|
1190 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."); |
|
1191 #endif |
|
1192 } |
|
1193 else |
|
1194 { |
|
1195 char *tri; |
|
1196 GSList *full_list; |
|
1197 GSList *owned_names; |
|
1198 GSList *tmp; |
|
1199 const char *sender; |
|
1200 |
|
1201 /* First we handle NameOwnerChanged internally */ |
|
1202 if (dbus_message_is_signal (message, |
|
1203 DBUS_INTERFACE_DBUS, |
|
1204 "NameOwnerChanged")) |
|
1205 { |
|
1206 const char *name; |
|
1207 const char *prev_owner; |
|
1208 const char *new_owner; |
|
1209 DBusError derr; |
|
1210 |
|
1211 dbus_error_init (&derr); |
|
1212 if (!dbus_message_get_args (message, |
|
1213 &derr, |
|
1214 DBUS_TYPE_STRING, |
|
1215 &name, |
|
1216 DBUS_TYPE_STRING, |
|
1217 &prev_owner, |
|
1218 DBUS_TYPE_STRING, |
|
1219 &new_owner, |
|
1220 DBUS_TYPE_INVALID)) |
|
1221 { |
|
1222 /* Ignore this error */ |
|
1223 dbus_error_free (&derr); |
|
1224 } |
|
1225 else if (manager->owner_names != NULL) |
|
1226 { |
|
1227 dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner); |
|
1228 } |
|
1229 } |
|
1230 |
|
1231 sender = dbus_message_get_sender (message); |
|
1232 |
|
1233 /* dbus spec requires these, libdbus validates */ |
|
1234 g_assert (dbus_message_get_path (message) != NULL); |
|
1235 g_assert (dbus_message_get_interface (message) != NULL); |
|
1236 g_assert (dbus_message_get_member (message) != NULL); |
|
1237 |
|
1238 tri = tristring_from_message (message); |
|
1239 |
|
1240 if (manager->proxy_lists) |
|
1241 { |
|
1242 DBusGProxyList *owner_list; |
|
1243 owner_list = g_hash_table_lookup (manager->proxy_lists, tri); |
|
1244 if (owner_list) |
|
1245 full_list = g_slist_copy (owner_list->proxies); |
|
1246 else |
|
1247 full_list = NULL; |
|
1248 } |
|
1249 else |
|
1250 full_list = NULL; |
|
1251 |
|
1252 g_free (tri); |
|
1253 |
|
1254 if (manager->owner_names && sender) |
|
1255 { |
|
1256 owned_names = g_hash_table_lookup (manager->owner_names, sender); |
|
1257 for (tmp = owned_names; tmp; tmp = tmp->next) |
|
1258 { |
|
1259 DBusGProxyList *owner_list; |
|
1260 DBusGProxyNameOwnerInfo *nameinfo; |
|
1261 |
|
1262 nameinfo = tmp->data; |
|
1263 g_assert (nameinfo->refcount > 0); |
|
1264 tri = tristring_alloc_from_strings (0, nameinfo->name, |
|
1265 dbus_message_get_path (message), |
|
1266 dbus_message_get_interface (message)); |
|
1267 |
|
1268 owner_list = g_hash_table_lookup (manager->proxy_lists, tri); |
|
1269 if (owner_list != NULL) |
|
1270 full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies)); |
|
1271 g_free (tri); |
|
1272 } |
|
1273 } |
|
1274 |
|
1275 #if 0 |
|
1276 g_print ("proxy got %s,%s,%s = list %p\n", |
|
1277 tri, |
|
1278 tri + strlen (tri) + 1, |
|
1279 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1, |
|
1280 list); |
|
1281 #endif |
|
1282 |
|
1283 /* Emit the signal */ |
|
1284 |
|
1285 g_slist_foreach (full_list, (GFunc) g_object_ref, NULL); |
|
1286 |
|
1287 for (tmp = full_list; tmp; tmp = tmp->next) |
|
1288 { |
|
1289 DBusGProxy *proxy; |
|
1290 |
|
1291 proxy = DBUS_G_PROXY (tmp->data); |
|
1292 |
|
1293 UNLOCK_MANAGER (manager); |
|
1294 dbus_g_proxy_emit_remote_signal (proxy, message); |
|
1295 g_object_unref (G_OBJECT (proxy)); |
|
1296 LOCK_MANAGER (manager); |
|
1297 } |
|
1298 g_slist_free (full_list); |
|
1299 } |
|
1300 |
|
1301 UNLOCK_MANAGER (manager); |
|
1302 dbus_g_proxy_manager_unref (manager); |
|
1303 |
|
1304 /* "Handling" signals doesn't make sense, they are for everyone |
|
1305 * who cares |
|
1306 */ |
|
1307 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
|
1308 } |
|
1309 |
|
1310 |
|
1311 |
|
1312 /* ---------- DBusGProxy -------------- */ |
|
1313 #define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL) |
|
1314 |
|
1315 static void |
|
1316 marshal_dbus_message_to_g_marshaller (GClosure *closure, |
|
1317 GValue *return_value, |
|
1318 guint n_param_values, |
|
1319 const GValue *param_values, |
|
1320 gpointer invocation_hint, |
|
1321 gpointer marshal_data); |
|
1322 enum |
|
1323 { |
|
1324 PROP_0, |
|
1325 PROP_NAME, |
|
1326 PROP_PATH, |
|
1327 PROP_INTERFACE, |
|
1328 PROP_CONNECTION |
|
1329 }; |
|
1330 |
|
1331 enum |
|
1332 { |
|
1333 DESTROY, |
|
1334 RECEIVED, |
|
1335 LAST_SIGNAL |
|
1336 }; |
|
1337 |
|
1338 #if EMULATOR |
|
1339 GET_STATIC_VAR_FROM_TLS(parent_class,dbus_gproxy,void* ) |
|
1340 #define parent_class (*GET_DBUS_WSD_VAR_NAME(parent_class,dbus_gproxy,s)()) |
|
1341 |
|
1342 GET_STATIC_ARRAY_FROM_TLS(signals,dbus_gproxy,guint ) |
|
1343 #define signals (GET_DBUS_WSD_VAR_NAME(signals,dbus_gproxy,s)()) |
|
1344 |
|
1345 #else |
|
1346 static void *parent_class; |
|
1347 static guint signals[LAST_SIGNAL] = { 0 }; |
|
1348 |
|
1349 #endif |
|
1350 |
|
1351 |
|
1352 static void |
|
1353 dbus_g_proxy_init (DBusGProxy *proxy) |
|
1354 { |
|
1355 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1356 |
|
1357 g_datalist_init (&priv->signal_signatures); |
|
1358 priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL, |
|
1359 (GDestroyNotify) dbus_pending_call_unref); |
|
1360 priv->name_call = 0; |
|
1361 priv->associated = FALSE; |
|
1362 } |
|
1363 |
|
1364 static GObject * |
|
1365 dbus_g_proxy_constructor (GType type, |
|
1366 guint n_construct_properties, |
|
1367 GObjectConstructParam *construct_properties) |
|
1368 { |
|
1369 DBusGProxy *proxy; |
|
1370 DBusGProxyClass *klass; |
|
1371 GObjectClass *parent_class; |
|
1372 DBusGProxyPrivate *priv; |
|
1373 |
|
1374 klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY)); |
|
1375 |
|
1376 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); |
|
1377 |
|
1378 proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties, |
|
1379 construct_properties)); |
|
1380 |
|
1381 priv = DBUS_G_PROXY_GET_PRIVATE (proxy); |
|
1382 |
|
1383 /* if these assertions fail, a deriving class has not set our required |
|
1384 * parameters - our own public constructors do return_if_fail checks |
|
1385 * on these parameters being provided. unfortunately we can't assert |
|
1386 * for manager because it's allowed to be NULL when tha mangager is |
|
1387 * setting up a bus proxy for its own calls */ |
|
1388 g_assert (priv->path != NULL); |
|
1389 g_assert (priv->interface != NULL); |
|
1390 |
|
1391 if (priv->manager != NULL) |
|
1392 { |
|
1393 dbus_g_proxy_manager_register (priv->manager, proxy); |
|
1394 } |
|
1395 |
|
1396 return G_OBJECT (proxy); |
|
1397 } |
|
1398 |
|
1399 static void |
|
1400 dbus_g_proxy_class_init (DBusGProxyClass *klass) |
|
1401 { |
|
1402 GObjectClass *object_class = G_OBJECT_CLASS (klass); |
|
1403 |
|
1404 parent_class = g_type_class_peek_parent (klass); |
|
1405 |
|
1406 g_type_class_add_private (klass, sizeof (DBusGProxyPrivate)); |
|
1407 |
|
1408 object_class->set_property = dbus_g_proxy_set_property; |
|
1409 object_class->get_property = dbus_g_proxy_get_property; |
|
1410 |
|
1411 g_object_class_install_property (object_class, |
|
1412 PROP_NAME, |
|
1413 g_param_spec_string ("name", |
|
1414 "name", |
|
1415 "name", |
|
1416 NULL, |
|
1417 // #ifdef WINSCW |
|
1418 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); |
|
1419 // #else |
|
1420 // (GParamFlags)11)); // ARM complaining about enums mixing |
|
1421 // #endif |
|
1422 |
|
1423 g_object_class_install_property (object_class, |
|
1424 PROP_PATH, |
|
1425 g_param_spec_string ("path", |
|
1426 "path", |
|
1427 "path", |
|
1428 NULL, |
|
1429 // #ifdef WINSCW |
|
1430 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); |
|
1431 // #else |
|
1432 // (GParamFlags)11)); // ARM complaining about enums mixing |
|
1433 // #endif |
|
1434 |
|
1435 g_object_class_install_property (object_class, |
|
1436 PROP_INTERFACE, |
|
1437 g_param_spec_string ("interface", |
|
1438 "interface", |
|
1439 "interface", |
|
1440 NULL, |
|
1441 // #ifdef WINSCW |
|
1442 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); |
|
1443 // #else |
|
1444 // (GParamFlags)11)); // ARM complaining about enums mixing |
|
1445 // #endif |
|
1446 |
|
1447 g_object_class_install_property (object_class, |
|
1448 PROP_CONNECTION, |
|
1449 g_param_spec_boxed ("connection", |
|
1450 "connection", |
|
1451 "connection", |
|
1452 DBUS_TYPE_G_CONNECTION, |
|
1453 // #ifdef WINSCW |
|
1454 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); |
|
1455 // #else |
|
1456 // (GParamFlags)11)); // ARM complaining about enums mixing |
|
1457 // #endif |
|
1458 |
|
1459 object_class->finalize = dbus_g_proxy_finalize; |
|
1460 object_class->dispose = dbus_g_proxy_dispose; |
|
1461 object_class->constructor = dbus_g_proxy_constructor; |
|
1462 |
|
1463 signals[DESTROY] = |
|
1464 g_signal_new ("destroy", |
|
1465 G_OBJECT_CLASS_TYPE (object_class), |
|
1466 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, |
|
1467 0, |
|
1468 NULL, NULL, |
|
1469 g_cclosure_marshal_VOID__VOID, |
|
1470 G_TYPE_NONE, 0); |
|
1471 |
|
1472 signals[RECEIVED] = |
|
1473 g_signal_new ("received", |
|
1474 G_OBJECT_CLASS_TYPE (object_class), |
|
1475 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
1476 0, |
|
1477 NULL, NULL, |
|
1478 marshal_dbus_message_to_g_marshaller, |
|
1479 G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER); |
|
1480 } |
|
1481 |
|
1482 static void |
|
1483 cancel_pending_call (gpointer key, gpointer val, gpointer data) |
|
1484 { |
|
1485 DBusGProxyCall *call = key; |
|
1486 DBusGProxy *proxy = data; |
|
1487 |
|
1488 dbus_g_proxy_cancel_call (proxy, call); |
|
1489 } |
|
1490 |
|
1491 static void |
|
1492 dbus_g_proxy_dispose (GObject *object) |
|
1493 { |
|
1494 DBusGProxy *proxy = DBUS_G_PROXY (object); |
|
1495 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1496 |
|
1497 if (priv->pending_calls == NULL) |
|
1498 { |
|
1499 return; |
|
1500 } |
|
1501 |
|
1502 /* Cancel outgoing pending calls */ |
|
1503 g_hash_table_foreach (priv->pending_calls, cancel_pending_call, proxy); |
|
1504 g_hash_table_destroy (priv->pending_calls); |
|
1505 priv->pending_calls = NULL; |
|
1506 |
|
1507 if (priv->manager && proxy != priv->manager->bus_proxy) |
|
1508 { |
|
1509 dbus_g_proxy_manager_unregister (priv->manager, proxy); |
|
1510 dbus_g_proxy_manager_unref (priv->manager); |
|
1511 } |
|
1512 priv->manager = NULL; |
|
1513 |
|
1514 g_datalist_clear (&priv->signal_signatures); |
|
1515 |
|
1516 g_signal_emit (object, signals[DESTROY], 0); |
|
1517 |
|
1518 G_OBJECT_CLASS (parent_class)->dispose (object); |
|
1519 } |
|
1520 |
|
1521 static void |
|
1522 dbus_g_proxy_finalize (GObject *object) |
|
1523 { |
|
1524 DBusGProxy *proxy = DBUS_G_PROXY (object); |
|
1525 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1526 |
|
1527 g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy)); |
|
1528 |
|
1529 g_free (priv->name); |
|
1530 g_free (priv->path); |
|
1531 g_free (priv->interface); |
|
1532 |
|
1533 G_OBJECT_CLASS (parent_class)->finalize (object); |
|
1534 } |
|
1535 |
|
1536 static void |
|
1537 dbus_g_proxy_destroy (DBusGProxy *proxy) |
|
1538 { |
|
1539 /* FIXME do we need the GTK_IN_DESTRUCTION style flag |
|
1540 * from GtkObject? |
|
1541 */ |
|
1542 g_object_run_dispose (G_OBJECT (proxy)); |
|
1543 } |
|
1544 |
|
1545 static void |
|
1546 dbus_g_proxy_set_property (GObject *object, |
|
1547 guint prop_id, |
|
1548 const GValue *value, |
|
1549 GParamSpec *pspec) |
|
1550 { |
|
1551 DBusGProxy *proxy = DBUS_G_PROXY (object); |
|
1552 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1553 DBusGConnection *connection; |
|
1554 |
|
1555 switch (prop_id) |
|
1556 { |
|
1557 case PROP_NAME: |
|
1558 priv->name = g_strdup (g_value_get_string (value)); |
|
1559 if (priv->name) |
|
1560 priv->for_owner = (priv->name[0] == ':'); |
|
1561 else |
|
1562 priv->for_owner = TRUE; |
|
1563 break; |
|
1564 case PROP_PATH: |
|
1565 priv->path = g_strdup (g_value_get_string (value)); |
|
1566 break; |
|
1567 case PROP_INTERFACE: |
|
1568 priv->interface = g_strdup (g_value_get_string (value)); |
|
1569 break; |
|
1570 case PROP_CONNECTION: |
|
1571 connection = g_value_get_boxed (value); |
|
1572 if (connection != NULL) |
|
1573 { |
|
1574 priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection)); |
|
1575 } |
|
1576 break; |
|
1577 default: |
|
1578 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
1579 break; |
|
1580 } |
|
1581 } |
|
1582 |
|
1583 static void |
|
1584 dbus_g_proxy_get_property (GObject *object, |
|
1585 guint prop_id, |
|
1586 GValue *value, |
|
1587 GParamSpec *pspec) |
|
1588 { |
|
1589 DBusGProxy *proxy = DBUS_G_PROXY (object); |
|
1590 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1591 |
|
1592 switch (prop_id) |
|
1593 { |
|
1594 case PROP_NAME: |
|
1595 g_value_set_string (value, priv->name); |
|
1596 break; |
|
1597 case PROP_PATH: |
|
1598 g_value_set_string (value, priv->path); |
|
1599 break; |
|
1600 case PROP_INTERFACE: |
|
1601 g_value_set_string (value, priv->interface); |
|
1602 break; |
|
1603 case PROP_CONNECTION: |
|
1604 g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection)); |
|
1605 break; |
|
1606 default: |
|
1607 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
1608 break; |
|
1609 } |
|
1610 } |
|
1611 |
|
1612 /* this is to avoid people using g_signal_connect() directly, |
|
1613 * to avoid confusion with local signal names, and because |
|
1614 * of the horribly broken current setup (signals are added |
|
1615 * globally to all proxies) |
|
1616 */ |
|
1617 static char* |
|
1618 create_signal_name (const char *interface, |
|
1619 const char *signal) |
|
1620 { |
|
1621 GString *str; |
|
1622 char *p; |
|
1623 |
|
1624 str = g_string_new (interface); |
|
1625 |
|
1626 g_string_append (str, "-"); |
|
1627 |
|
1628 g_string_append (str, signal); |
|
1629 |
|
1630 /* GLib will silently barf on '.' in signal names */ |
|
1631 p = str->str; |
|
1632 while (*p) |
|
1633 { |
|
1634 if (*p == '.') |
|
1635 *p = '-'; |
|
1636 ++p; |
|
1637 } |
|
1638 |
|
1639 return g_string_free (str, FALSE); |
|
1640 } |
|
1641 |
|
1642 static void |
|
1643 marshal_dbus_message_to_g_marshaller (GClosure *closure, |
|
1644 GValue *return_value, |
|
1645 guint n_param_values, |
|
1646 const GValue *param_values, |
|
1647 gpointer invocation_hint, |
|
1648 gpointer marshal_data) |
|
1649 { |
|
1650 /* Incoming here we have three params, the instance (Proxy), the |
|
1651 * DBusMessage, the signature. We want to convert that to an |
|
1652 * expanded GValue array, then call an appropriate normal GLib |
|
1653 * marshaller. |
|
1654 */ |
|
1655 #define MAX_SIGNATURE_ARGS 20 |
|
1656 GValueArray *value_array; |
|
1657 GSignalCMarshaller c_marshaller; |
|
1658 DBusGProxy *proxy; |
|
1659 DBusMessage *message; |
|
1660 GArray *gsignature; |
|
1661 const GType *types; |
|
1662 DBusGProxyPrivate *priv; |
|
1663 |
|
1664 g_assert (n_param_values == 3); |
|
1665 |
|
1666 proxy = g_value_get_object (¶m_values[0]); |
|
1667 message = g_value_get_boxed (¶m_values[1]); |
|
1668 gsignature = g_value_get_pointer (¶m_values[2]); |
|
1669 |
|
1670 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
1671 g_return_if_fail (message != NULL); |
|
1672 g_return_if_fail (gsignature != NULL); |
|
1673 |
|
1674 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1675 |
|
1676 c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len, |
|
1677 (GType*) gsignature->data); |
|
1678 |
|
1679 g_return_if_fail (c_marshaller != NULL); |
|
1680 |
|
1681 { |
|
1682 DBusGValueMarshalCtx context; |
|
1683 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection); |
|
1684 context.proxy = proxy; |
|
1685 |
|
1686 types = (const GType*) gsignature->data; |
|
1687 value_array = _dbus_gvalue_demarshal_message (&context, message, |
|
1688 gsignature->len, types, NULL); |
|
1689 } |
|
1690 |
|
1691 if (value_array == NULL) |
|
1692 return; |
|
1693 |
|
1694 g_value_array_prepend (value_array, NULL); |
|
1695 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy)); |
|
1696 g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy); |
|
1697 |
|
1698 (* c_marshaller) (closure, return_value, value_array->n_values, |
|
1699 value_array->values, invocation_hint, marshal_data); |
|
1700 |
|
1701 g_value_array_free (value_array); |
|
1702 } |
|
1703 |
|
1704 static void |
|
1705 dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy, |
|
1706 DBusMessage *message) |
|
1707 { |
|
1708 const char *interface; |
|
1709 const char *signal; |
|
1710 char *name; |
|
1711 GQuark q; |
|
1712 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
1713 GArray *msg_gsignature = NULL; |
|
1714 |
|
1715 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
1716 |
|
1717 interface = dbus_message_get_interface (message); |
|
1718 signal = dbus_message_get_member (message); |
|
1719 |
|
1720 g_assert (interface != NULL); |
|
1721 g_assert (signal != NULL); |
|
1722 |
|
1723 name = create_signal_name (interface, signal); |
|
1724 |
|
1725 /* If the quark isn't preexisting, there's no way there |
|
1726 * are any handlers connected. We don't want to create |
|
1727 * extra quarks for every possible signal. |
|
1728 */ |
|
1729 q = g_quark_try_string (name); |
|
1730 |
|
1731 if (q != 0) |
|
1732 { |
|
1733 GArray *gsignature; |
|
1734 guint i; |
|
1735 |
|
1736 gsignature = g_datalist_id_get_data (&priv->signal_signatures, q); |
|
1737 if (gsignature == NULL) |
|
1738 goto out; |
|
1739 |
|
1740 msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message), |
|
1741 TRUE); |
|
1742 for (i = 0; i < gsignature->len; i++) |
|
1743 { |
|
1744 if (msg_gsignature->len == i |
|
1745 || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i)) |
|
1746 goto mismatch; |
|
1747 } |
|
1748 if (msg_gsignature->len != i) |
|
1749 goto mismatch; |
|
1750 |
|
1751 g_signal_emit (proxy, |
|
1752 signals[RECEIVED], |
|
1753 q, |
|
1754 message, |
|
1755 msg_gsignature); |
|
1756 } |
|
1757 |
|
1758 out: |
|
1759 g_free (name); |
|
1760 if (msg_gsignature) |
|
1761 g_array_free (msg_gsignature, TRUE); |
|
1762 return; |
|
1763 mismatch: |
|
1764 #if 0 |
|
1765 /* Don't spew on remote errors */ |
|
1766 g_warning ("Unexpected message signature '%s' for signal '%s'\n", |
|
1767 dbus_message_get_signature (message), |
|
1768 name); |
|
1769 #endif |
|
1770 goto out; |
|
1771 } |
|
1772 |
|
1773 typedef struct |
|
1774 { |
|
1775 DBusGProxy *proxy; |
|
1776 guint call_id; |
|
1777 DBusGProxyCallNotify func; |
|
1778 void *data; |
|
1779 GDestroyNotify free_data_func; |
|
1780 } GPendingNotifyClosure; |
|
1781 |
|
1782 static void |
|
1783 d_pending_call_notify (DBusPendingCall *dcall, |
|
1784 void *data) |
|
1785 { |
|
1786 GPendingNotifyClosure *closure = data; |
|
1787 |
|
1788 (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data); |
|
1789 } |
|
1790 |
|
1791 static void |
|
1792 d_pending_call_free (void *data) |
|
1793 { |
|
1794 GPendingNotifyClosure *closure = data; |
|
1795 |
|
1796 if (closure->free_data_func) |
|
1797 (* closure->free_data_func) (closure->data); |
|
1798 |
|
1799 g_free (closure); |
|
1800 } |
|
1801 |
|
1802 #define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \ |
|
1803 do { \ |
|
1804 GType valtype; \ |
|
1805 int i = 0; \ |
|
1806 VALARRAY = g_value_array_new (6); \ |
|
1807 valtype = FIRST_ARG_TYPE; \ |
|
1808 while (valtype != G_TYPE_INVALID) \ |
|
1809 { \ |
|
1810 const char *collect_err; \ |
|
1811 GValue *val; \ |
|
1812 g_value_array_append (VALARRAY, NULL); \ |
|
1813 val = g_value_array_get_nth (VALARRAY, i); \ |
|
1814 g_value_init (val, valtype); \ |
|
1815 collect_err = NULL; \ |
|
1816 G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \ |
|
1817 valtype = va_arg (ARGS, GType); \ |
|
1818 i++; \ |
|
1819 } \ |
|
1820 } while (0) |
|
1821 |
|
1822 DBusGProxyCall * |
|
1823 manager_begin_bus_call (DBusGProxyManager *manager, |
|
1824 const char *method, |
|
1825 DBusGProxyCallNotify notify, |
|
1826 gpointer user_data, |
|
1827 GDestroyNotify destroy, |
|
1828 GType first_arg_type, |
|
1829 ...) |
|
1830 { |
|
1831 DBusGProxyCall *call; |
|
1832 DBusGProxyPrivate *priv; |
|
1833 va_list args; |
|
1834 GValueArray *arg_values; |
|
1835 |
|
1836 va_start (args, first_arg_type); |
|
1837 |
|
1838 if (!manager->bus_proxy) |
|
1839 { |
|
1840 manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY, |
|
1841 "name", DBUS_SERVICE_DBUS, |
|
1842 "path", DBUS_PATH_DBUS, |
|
1843 "interface", DBUS_INTERFACE_DBUS, |
|
1844 NULL); |
|
1845 priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy); |
|
1846 priv->manager = manager; |
|
1847 } |
|
1848 |
|
1849 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args); |
|
1850 |
|
1851 call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values,-1)); |
|
1852 |
|
1853 g_value_array_free (arg_values); |
|
1854 |
|
1855 va_end (args); |
|
1856 |
|
1857 return call; |
|
1858 } |
|
1859 |
|
1860 /** @} End of DBusGLibInternals */ |
|
1861 |
|
1862 /** @addtogroup DBusGLib |
|
1863 * @{ |
|
1864 */ |
|
1865 |
|
1866 /** |
|
1867 * SECTION:dbus-gproxy |
|
1868 * @short_description: DBus Proxy |
|
1869 * @see_also: #DBusProxy |
|
1870 * @stability: Stable |
|
1871 * |
|
1872 * A #DBusGProxy is a boxed type abstracting a #DBusProxy. |
|
1873 */ |
|
1874 |
|
1875 /** |
|
1876 * dbus_g_proxy_get_type: |
|
1877 * Standard GObject get_type() function for DBusGProxy. |
|
1878 * |
|
1879 * Returns: type ID for DBusGProxy class |
|
1880 */ |
|
1881 #if EMULATOR |
|
1882 GET_STATIC_VAR_FROM_TLS(object_type,dbus_gproxy,GType) |
|
1883 #define object_type (*GET_DBUS_WSD_VAR_NAME(object_type,dbus_gproxy,s)()) |
|
1884 #endif |
|
1885 #ifdef __SYMBIAN32__ |
|
1886 EXPORT_C |
|
1887 #endif |
|
1888 GType |
|
1889 dbus_g_proxy_get_type (void) |
|
1890 { |
|
1891 #ifndef EMULATOR |
|
1892 static GType object_type = 0; |
|
1893 #endif |
|
1894 |
|
1895 |
|
1896 if (!object_type) |
|
1897 { |
|
1898 static const GTypeInfo object_info = |
|
1899 { |
|
1900 sizeof (DBusGProxyClass), |
|
1901 (GBaseInitFunc) NULL, |
|
1902 (GBaseFinalizeFunc) NULL, |
|
1903 (GClassInitFunc) dbus_g_proxy_class_init, |
|
1904 NULL, /* class_finalize */ |
|
1905 NULL, /* class_data */ |
|
1906 sizeof (DBusGProxy), |
|
1907 0, /* n_preallocs */ |
|
1908 (GInstanceInitFunc) dbus_g_proxy_init, |
|
1909 }; |
|
1910 |
|
1911 object_type = g_type_register_static (G_TYPE_OBJECT, |
|
1912 "DBusGProxy", |
|
1913 &object_info, 0); |
|
1914 } |
|
1915 |
|
1916 return object_type; |
|
1917 } |
|
1918 |
|
1919 static DBusGProxy* |
|
1920 dbus_g_proxy_new (DBusGConnection *connection, |
|
1921 const char *name, |
|
1922 const char *path_name, |
|
1923 const char *interface_name) |
|
1924 { |
|
1925 DBusGProxy *proxy; |
|
1926 |
|
1927 g_assert (connection != NULL); |
|
1928 |
|
1929 proxy = g_object_new (DBUS_TYPE_G_PROXY, |
|
1930 "name", name, |
|
1931 "path", path_name, |
|
1932 "interface", interface_name, |
|
1933 "connection", connection, NULL); |
|
1934 |
|
1935 return proxy; |
|
1936 } |
|
1937 |
|
1938 /** |
|
1939 * dbus_g_proxy_new_for_name: |
|
1940 * @connection: the connection to the remote bus |
|
1941 * @name: any name on the message bus |
|
1942 * @path_name: name of the object instance to call methods on |
|
1943 * @interface_name: name of the interface to call methods on |
|
1944 * |
|
1945 * Creates a new proxy for a remote interface exported by a connection |
|
1946 * on a message bus. Method calls and signal connections over this |
|
1947 * proxy will go to the name owner; the name's owner is expected to |
|
1948 * support the given interface name. THE NAME OWNER MAY CHANGE OVER |
|
1949 * TIME, for example between two different method calls, unless the |
|
1950 * name is a unique name. If you need a fixed owner, you need to |
|
1951 * request the current owner and bind a proxy to its unique name |
|
1952 * rather than to the generic name; see |
|
1953 * dbus_g_proxy_new_for_name_owner(). |
|
1954 * |
|
1955 * A name-associated proxy only makes sense with a message bus, not |
|
1956 * for app-to-app direct dbus connections. |
|
1957 * |
|
1958 * This proxy will only emit the "destroy" signal if the |
|
1959 * #DBusConnection is disconnected, the proxy has no remaining |
|
1960 * references, or the name is a unique name and its owner |
|
1961 * disappears. If a well-known name changes owner, the proxy will |
|
1962 * still be alive. |
|
1963 * |
|
1964 * Returns: new proxy object |
|
1965 */ |
|
1966 #ifdef __SYMBIAN32__ |
|
1967 EXPORT_C |
|
1968 #endif |
|
1969 DBusGProxy* |
|
1970 dbus_g_proxy_new_for_name (DBusGConnection *connection, |
|
1971 const char *name, |
|
1972 const char *path_name, |
|
1973 const char *interface_name) |
|
1974 { |
|
1975 g_return_val_if_fail (connection != NULL, NULL); |
|
1976 g_return_val_if_fail (name != NULL, NULL); |
|
1977 g_return_val_if_fail (path_name != NULL, NULL); |
|
1978 g_return_val_if_fail (interface_name != NULL, NULL); |
|
1979 |
|
1980 return dbus_g_proxy_new (connection, name, |
|
1981 path_name, interface_name); |
|
1982 } |
|
1983 |
|
1984 /** |
|
1985 * dbus_g_proxy_new_for_name_owner: |
|
1986 * @connection: the connection to the remote bus |
|
1987 * @name: any name on the message bus |
|
1988 * @path_name: name of the object inside the service to call methods on |
|
1989 * @interface_name: name of the interface to call methods on |
|
1990 * @error: return location for an error |
|
1991 * |
|
1992 * Similar to dbus_g_proxy_new_for_name(), but makes a round-trip |
|
1993 * request to the message bus to get the current name owner, then |
|
1994 * binds the proxy to the unique name of the current owner, rather |
|
1995 * than to the well-known name. As a result, the name owner will |
|
1996 * not change over time, and the proxy will emit the "destroy" signal |
|
1997 * when the owner disappears from the message bus. |
|
1998 * |
|
1999 * An example of the difference between dbus_g_proxy_new_for_name() |
|
2000 * and dbus_g_proxy_new_for_name_owner(): if you provide the well-known name |
|
2001 * "org.freedesktop.Database" dbus_g_proxy_new_for_name() remains bound |
|
2002 * to that name as it changes owner. dbus_g_proxy_new_for_name_owner() |
|
2003 * will fail if the name has no owner. If the name has an owner, |
|
2004 * dbus_g_proxy_new_for_name_owner() will bind to the unique name |
|
2005 * of that owner rather than the generic name. |
|
2006 * |
|
2007 * Returns: new proxy object, or #NULL on error |
|
2008 */ |
|
2009 #ifdef __SYMBIAN32__ |
|
2010 EXPORT_C |
|
2011 #endif |
|
2012 DBusGProxy* |
|
2013 dbus_g_proxy_new_for_name_owner (DBusGConnection *connection, |
|
2014 const char *name, |
|
2015 const char *path_name, |
|
2016 const char *interface_name, |
|
2017 GError **error) |
|
2018 { |
|
2019 DBusGProxy *proxy; |
|
2020 char *unique_name; |
|
2021 |
|
2022 g_return_val_if_fail (connection != NULL, NULL); |
|
2023 g_return_val_if_fail (name != NULL, NULL); |
|
2024 g_return_val_if_fail (path_name != NULL, NULL); |
|
2025 g_return_val_if_fail (interface_name != NULL, NULL); |
|
2026 |
|
2027 if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error))) |
|
2028 return NULL; |
|
2029 |
|
2030 proxy = dbus_g_proxy_new (connection, unique_name, |
|
2031 path_name, interface_name); |
|
2032 g_free (unique_name); |
|
2033 return proxy; |
|
2034 } |
|
2035 |
|
2036 /** |
|
2037 * dbus_g_proxy_new_from_proxy: |
|
2038 * @proxy: the proxy to use as a template |
|
2039 * @path: of the object inside the peer to call methods on |
|
2040 * @interface: name of the interface to call methods on |
|
2041 * |
|
2042 * Creates a proxy using an existing proxy as a template, substituting |
|
2043 * the specified interface and path. Either or both may be NULL. |
|
2044 * |
|
2045 * Returns: new proxy object |
|
2046 */ |
|
2047 #ifdef __SYMBIAN32__ |
|
2048 EXPORT_C |
|
2049 #endif |
|
2050 DBusGProxy* |
|
2051 dbus_g_proxy_new_from_proxy (DBusGProxy *proxy, |
|
2052 const char *interface, |
|
2053 const char *path) |
|
2054 { |
|
2055 DBusGProxyPrivate *priv; |
|
2056 |
|
2057 g_return_val_if_fail (proxy != NULL, NULL); |
|
2058 |
|
2059 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2060 |
|
2061 if (interface == NULL) |
|
2062 interface = priv->interface; |
|
2063 if (path == NULL) |
|
2064 path = priv->path; |
|
2065 |
|
2066 return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection), |
|
2067 priv->name, |
|
2068 path, interface); |
|
2069 } |
|
2070 |
|
2071 /** |
|
2072 * dbus_g_proxy_new_for_peer: |
|
2073 * @connection: the connection to the peer |
|
2074 * @path_name: name of the object inside the peer to call methods on |
|
2075 * @interface_name: name of the interface to call methods on |
|
2076 * |
|
2077 * Creates a proxy for an object in peer application (one |
|
2078 * we're directly connected to). That is, this function is |
|
2079 * intended for use when there's no message bus involved, |
|
2080 * we're doing a simple 1-to-1 communication between two |
|
2081 * applications. |
|
2082 * |
|
2083 * Returns: new proxy object |
|
2084 */ |
|
2085 #ifdef __SYMBIAN32__ |
|
2086 EXPORT_C |
|
2087 #endif |
|
2088 DBusGProxy* |
|
2089 dbus_g_proxy_new_for_peer (DBusGConnection *connection, |
|
2090 const char *path_name, |
|
2091 const char *interface_name) |
|
2092 { |
|
2093 DBusGProxy *proxy; |
|
2094 |
|
2095 g_return_val_if_fail (connection != NULL, NULL); |
|
2096 g_return_val_if_fail (path_name != NULL, NULL); |
|
2097 g_return_val_if_fail (interface_name != NULL, NULL); |
|
2098 |
|
2099 proxy = dbus_g_proxy_new (connection, NULL, |
|
2100 path_name, interface_name); |
|
2101 |
|
2102 return proxy; |
|
2103 } |
|
2104 |
|
2105 /** |
|
2106 * dbus_g_proxy_get_bus_name: |
|
2107 * @proxy: the proxy |
|
2108 * |
|
2109 * Gets the bus name a proxy is bound to (may be #NULL in some cases). |
|
2110 * If you created the proxy with dbus_g_proxy_new_for_name(), then |
|
2111 * the name you passed to that will be returned. |
|
2112 * If you created it with dbus_g_proxy_new_for_name_owner(), then the |
|
2113 * unique connection name will be returned. If you created it |
|
2114 * with dbus_g_proxy_new_for_peer() then #NULL will be returned. |
|
2115 * |
|
2116 * Returns: the bus name the proxy sends messages to |
|
2117 */ |
|
2118 #ifdef __SYMBIAN32__ |
|
2119 EXPORT_C |
|
2120 #endif |
|
2121 const char* |
|
2122 dbus_g_proxy_get_bus_name (DBusGProxy *proxy) |
|
2123 { |
|
2124 DBusGProxyPrivate *priv; |
|
2125 |
|
2126 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); |
|
2127 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); |
|
2128 |
|
2129 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2130 |
|
2131 return priv->name; |
|
2132 } |
|
2133 |
|
2134 /** |
|
2135 * dbus_g_proxy_get_interface: |
|
2136 * @proxy: the proxy |
|
2137 * |
|
2138 * Gets the object interface proxy is bound to (may be #NULL in some cases). |
|
2139 * |
|
2140 * Returns: an object interface |
|
2141 */ |
|
2142 #ifdef __SYMBIAN32__ |
|
2143 EXPORT_C |
|
2144 #endif |
|
2145 const char* |
|
2146 dbus_g_proxy_get_interface (DBusGProxy *proxy) |
|
2147 { |
|
2148 DBusGProxyPrivate *priv; |
|
2149 |
|
2150 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); |
|
2151 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); |
|
2152 |
|
2153 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2154 |
|
2155 return priv->interface; |
|
2156 } |
|
2157 |
|
2158 /** |
|
2159 * dbus_g_proxy_set_interface: |
|
2160 * @proxy: the proxy |
|
2161 * @interface_name: an object interface |
|
2162 * |
|
2163 * Sets the object interface proxy is bound to |
|
2164 */ |
|
2165 #ifdef __SYMBIAN32__ |
|
2166 EXPORT_C |
|
2167 #endif |
|
2168 void |
|
2169 dbus_g_proxy_set_interface (DBusGProxy *proxy, |
|
2170 const char *interface_name) |
|
2171 { |
|
2172 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2173 /* FIXME - need to unregister when we switch interface for now |
|
2174 * later should support idea of unset interface |
|
2175 */ |
|
2176 dbus_g_proxy_manager_unregister (priv->manager, proxy); |
|
2177 g_free (priv->interface); |
|
2178 priv->interface = g_strdup (interface_name); |
|
2179 dbus_g_proxy_manager_register (priv->manager, proxy); |
|
2180 } |
|
2181 |
|
2182 /** |
|
2183 * dbus_g_proxy_get_path: |
|
2184 * Gets the path this proxy is bound to |
|
2185 * @proxy: the proxy |
|
2186 * |
|
2187 * Returns: an object path |
|
2188 */ |
|
2189 #ifdef __SYMBIAN32__ |
|
2190 EXPORT_C |
|
2191 #endif |
|
2192 const char* |
|
2193 dbus_g_proxy_get_path (DBusGProxy *proxy) |
|
2194 { |
|
2195 DBusGProxyPrivate *priv; |
|
2196 |
|
2197 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); |
|
2198 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); |
|
2199 |
|
2200 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2201 |
|
2202 return priv->path; |
|
2203 } |
|
2204 |
|
2205 static DBusMessage * |
|
2206 dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy, |
|
2207 const char *method, |
|
2208 GValueArray *args) |
|
2209 { |
|
2210 DBusMessage *message; |
|
2211 DBusMessageIter msgiter; |
|
2212 guint i; |
|
2213 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2214 |
|
2215 message = dbus_message_new_method_call (priv->name, |
|
2216 priv->path, |
|
2217 priv->interface, |
|
2218 method); |
|
2219 if (message == NULL) |
|
2220 goto oom; |
|
2221 |
|
2222 dbus_message_iter_init_append (message, &msgiter); |
|
2223 for (i = 0; i < args->n_values; i++) |
|
2224 { |
|
2225 GValue *gvalue; |
|
2226 |
|
2227 gvalue = g_value_array_get_nth (args, i); |
|
2228 |
|
2229 if (!_dbus_gvalue_marshal (&msgiter, gvalue)) |
|
2230 g_assert_not_reached (); |
|
2231 } |
|
2232 return message; |
|
2233 oom: |
|
2234 return NULL; |
|
2235 } |
|
2236 |
|
2237 static guint |
|
2238 dbus_g_proxy_begin_call_internal (DBusGProxy *proxy, |
|
2239 const char *method, |
|
2240 DBusGProxyCallNotify notify, |
|
2241 gpointer user_data, |
|
2242 GDestroyNotify destroy, |
|
2243 GValueArray *args, |
|
2244 int timeout) |
|
2245 { |
|
2246 DBusMessage *message; |
|
2247 DBusPendingCall *pending; |
|
2248 GPendingNotifyClosure *closure; |
|
2249 guint call_id; |
|
2250 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2251 |
|
2252 pending = NULL; |
|
2253 |
|
2254 message = dbus_g_proxy_marshal_args_to_message (proxy, method, args); |
|
2255 if (!message) |
|
2256 goto oom; |
|
2257 |
|
2258 if (!dbus_connection_send_with_reply (priv->manager->connection, |
|
2259 message, |
|
2260 &pending, |
|
2261 timeout)) |
|
2262 goto oom; |
|
2263 dbus_message_unref (message); |
|
2264 g_assert (pending != NULL); |
|
2265 |
|
2266 call_id = ++priv->call_id_counter; |
|
2267 |
|
2268 if (notify != NULL) |
|
2269 { |
|
2270 closure = g_new (GPendingNotifyClosure, 1); |
|
2271 closure->proxy = proxy; /* No need to ref as the lifecycle is tied to proxy */ |
|
2272 closure->call_id = call_id; |
|
2273 closure->func = notify; |
|
2274 closure->data = user_data; |
|
2275 closure->free_data_func = destroy; |
|
2276 dbus_pending_call_set_notify (pending, d_pending_call_notify, |
|
2277 closure, |
|
2278 d_pending_call_free); |
|
2279 } |
|
2280 |
|
2281 g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending); |
|
2282 |
|
2283 return call_id; |
|
2284 oom: |
|
2285 g_error ("Out of memory"); |
|
2286 return 0; |
|
2287 } |
|
2288 |
|
2289 static gboolean |
|
2290 dbus_g_proxy_end_call_internal (DBusGProxy *proxy, |
|
2291 guint call_id, |
|
2292 GError **error, |
|
2293 GType first_arg_type, |
|
2294 va_list args) |
|
2295 { |
|
2296 DBusMessage *reply; |
|
2297 DBusMessageIter msgiter; |
|
2298 DBusError derror; |
|
2299 va_list args_unwind; |
|
2300 guint over; |
|
2301 int n_retvals_processed; |
|
2302 gboolean ret; |
|
2303 GType valtype; |
|
2304 DBusPendingCall *pending; |
|
2305 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2306 |
|
2307 reply = NULL; |
|
2308 ret = FALSE; |
|
2309 n_retvals_processed = 0; |
|
2310 over = 0; |
|
2311 |
|
2312 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id)); |
|
2313 |
|
2314 dbus_pending_call_block (pending); |
|
2315 reply = dbus_pending_call_steal_reply (pending); |
|
2316 |
|
2317 g_assert (reply != NULL); |
|
2318 |
|
2319 dbus_error_init (&derror); |
|
2320 |
|
2321 switch (dbus_message_get_type (reply)) |
|
2322 { |
|
2323 case DBUS_MESSAGE_TYPE_METHOD_RETURN: |
|
2324 dbus_message_iter_init (reply, &msgiter); |
|
2325 valtype = first_arg_type; |
|
2326 while (valtype != G_TYPE_INVALID) |
|
2327 { |
|
2328 int arg_type; |
|
2329 gpointer return_storage; |
|
2330 GValue gvalue = { 0, }; |
|
2331 DBusGValueMarshalCtx context; |
|
2332 |
|
2333 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection); |
|
2334 context.proxy = proxy; |
|
2335 |
|
2336 arg_type = dbus_message_iter_get_arg_type (&msgiter); |
|
2337 if (arg_type == DBUS_TYPE_INVALID) |
|
2338 { |
|
2339 g_set_error (error, DBUS_GERROR, |
|
2340 DBUS_GERROR_INVALID_ARGS, |
|
2341 _("Too few arguments in reply")); |
|
2342 goto out; |
|
2343 } |
|
2344 |
|
2345 return_storage = va_arg (args, gpointer); |
|
2346 if (return_storage == NULL) |
|
2347 goto next; |
|
2348 |
|
2349 /* We handle variants specially; the caller is expected |
|
2350 * to have already allocated storage for them. |
|
2351 */ |
|
2352 if (arg_type == DBUS_TYPE_VARIANT |
|
2353 && g_type_is_a (valtype, G_TYPE_VALUE)) |
|
2354 { |
|
2355 if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL)) |
|
2356 { |
|
2357 g_set_error (error, |
|
2358 DBUS_GERROR, |
|
2359 DBUS_GERROR_INVALID_ARGS, |
|
2360 _("Couldn't convert argument, expected \"%s\""), |
|
2361 g_type_name (valtype)); |
|
2362 goto out; |
|
2363 } |
|
2364 } |
|
2365 else |
|
2366 { |
|
2367 g_value_init (&gvalue, valtype); |
|
2368 |
|
2369 if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error)) |
|
2370 goto out; |
|
2371 |
|
2372 /* Anything that can be demarshaled must be storable */ |
|
2373 if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage)) |
|
2374 g_assert_not_reached (); |
|
2375 /* Ownership of the value passes to the client, don't unset */ |
|
2376 } |
|
2377 |
|
2378 next: |
|
2379 n_retvals_processed++; |
|
2380 dbus_message_iter_next (&msgiter); |
|
2381 valtype = va_arg (args, GType); |
|
2382 } |
|
2383 |
|
2384 while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID) |
|
2385 { |
|
2386 over++; |
|
2387 dbus_message_iter_next (&msgiter); |
|
2388 } |
|
2389 |
|
2390 if (over > 0) |
|
2391 { |
|
2392 g_set_error (error, DBUS_GERROR, |
|
2393 DBUS_GERROR_INVALID_ARGS, |
|
2394 _("Too many arguments in reply; expected %d, got %d"), |
|
2395 n_retvals_processed, over); |
|
2396 goto out; |
|
2397 } |
|
2398 break; |
|
2399 case DBUS_MESSAGE_TYPE_ERROR: |
|
2400 dbus_set_error_from_message (&derror, reply); |
|
2401 dbus_set_g_error (error, &derror); |
|
2402 dbus_error_free (&derror); |
|
2403 goto out; |
|
2404 break; |
|
2405 default: |
|
2406 dbus_set_error (&derror, DBUS_ERROR_FAILED, |
|
2407 "Reply was neither a method return nor an exception"); |
|
2408 dbus_set_g_error (error, &derror); |
|
2409 dbus_error_free (&derror); |
|
2410 goto out; |
|
2411 break; |
|
2412 } |
|
2413 |
|
2414 ret = TRUE; |
|
2415 out: |
|
2416 va_end (args); |
|
2417 |
|
2418 if (ret == FALSE) |
|
2419 { |
|
2420 int i; |
|
2421 for (i = 0; i < n_retvals_processed; i++) |
|
2422 { |
|
2423 gpointer retval; |
|
2424 |
|
2425 retval = va_arg (args_unwind, gpointer); |
|
2426 |
|
2427 g_free (retval); |
|
2428 } |
|
2429 } |
|
2430 va_end (args_unwind); |
|
2431 |
|
2432 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id)); |
|
2433 |
|
2434 if (reply) |
|
2435 dbus_message_unref (reply); |
|
2436 return ret; |
|
2437 } |
|
2438 |
|
2439 /** |
|
2440 * dbus_g_proxy_begin_call: |
|
2441 * @proxy: a proxy for a remote interface |
|
2442 * @method: the name of the method to invoke |
|
2443 * @notify: callback to be invoked when method returns |
|
2444 * @user_data: user data passed to callback |
|
2445 * @destroy: function called to destroy user_data |
|
2446 * @first_arg_type: type of the first argument |
|
2447 * |
|
2448 * Asynchronously invokes a method on a remote interface. The method |
|
2449 * call will not be sent over the wire until the application returns |
|
2450 * to the main loop, or blocks in dbus_connection_flush() to write out |
|
2451 * pending data. The call will be completed after a timeout, or when |
|
2452 * a reply is received. When the call returns, the callback specified |
|
2453 * will be invoked; you can then collect the results of the call |
|
2454 * (which may be an error, or a reply), use dbus_g_proxy_end_call(). |
|
2455 * |
|
2456 * TODO this particular function shouldn't die on out of memory, |
|
2457 * since you should be able to do a call with large arguments. |
|
2458 * |
|
2459 * Returns: call identifier. |
|
2460 */ |
|
2461 #ifdef __SYMBIAN32__ |
|
2462 EXPORT_C |
|
2463 #endif |
|
2464 DBusGProxyCall * |
|
2465 dbus_g_proxy_begin_call (DBusGProxy *proxy, |
|
2466 const char *method, |
|
2467 DBusGProxyCallNotify notify, |
|
2468 gpointer user_data, |
|
2469 GDestroyNotify destroy, |
|
2470 GType first_arg_type, |
|
2471 ...) |
|
2472 { |
|
2473 guint call_id; |
|
2474 va_list args; |
|
2475 GValueArray *arg_values; |
|
2476 |
|
2477 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); |
|
2478 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); |
|
2479 |
|
2480 va_start (args, first_arg_type); |
|
2481 |
|
2482 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args); |
|
2483 |
|
2484 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,-1); |
|
2485 |
|
2486 g_value_array_free (arg_values); |
|
2487 |
|
2488 va_end (args); |
|
2489 |
|
2490 return DBUS_G_PROXY_ID_TO_CALL (call_id); |
|
2491 } |
|
2492 |
|
2493 /** |
|
2494 * dbus_g_proxy_begin_call_with_timeout: |
|
2495 * @proxy: a proxy for a remote interface |
|
2496 * @method: the name of the method to invoke |
|
2497 * @notify: callback to be invoked when method returns |
|
2498 * @user_data: user data passed to callback |
|
2499 * @destroy: function called to destroy user_data |
|
2500 * @timeout: specify the timeout in milliseconds |
|
2501 * @first_arg_type: type of the first argument |
|
2502 * |
|
2503 * Asynchronously invokes a method on a remote interface. The method |
|
2504 * call will not be sent over the wire until the application returns |
|
2505 * to the main loop, or blocks in dbus_connection_flush() to write out |
|
2506 * pending data. The call will be completed after a timeout, or when |
|
2507 * a reply is received. When the call returns, the callback specified |
|
2508 * will be invoked; you can then collect the results of the call |
|
2509 * (which may be an error, or a reply), use dbus_g_proxy_end_call(). |
|
2510 * |
|
2511 * TODO this particular function shouldn't die on out of memory, |
|
2512 * since you should be able to do a call with large arguments. |
|
2513 * |
|
2514 * Returns: call identifier. |
|
2515 */ |
|
2516 #ifdef __SYMBIAN32__ |
|
2517 EXPORT_C |
|
2518 #endif |
|
2519 DBusGProxyCall * |
|
2520 dbus_g_proxy_begin_call_with_timeout (DBusGProxy *proxy, |
|
2521 const char *method, |
|
2522 DBusGProxyCallNotify notify, |
|
2523 gpointer user_data, |
|
2524 GDestroyNotify destroy, |
|
2525 int timeout, |
|
2526 GType first_arg_type, |
|
2527 ...) |
|
2528 { |
|
2529 guint call_id; |
|
2530 va_list args; |
|
2531 GValueArray *arg_values; |
|
2532 |
|
2533 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL); |
|
2534 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL); |
|
2535 |
|
2536 va_start (args, first_arg_type); |
|
2537 |
|
2538 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args); |
|
2539 |
|
2540 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,timeout); |
|
2541 |
|
2542 g_value_array_free (arg_values); |
|
2543 |
|
2544 va_end (args); |
|
2545 |
|
2546 return DBUS_G_PROXY_ID_TO_CALL (call_id); |
|
2547 } |
|
2548 |
|
2549 /** |
|
2550 * dbus_g_proxy_end_call: |
|
2551 * @proxy: a proxy for a remote interface |
|
2552 * @call: the pending call ID from dbus_g_proxy_begin_call() |
|
2553 * @error: return location for an error |
|
2554 * @first_arg_type: type of first "out" argument |
|
2555 * |
|
2556 * Collects the results of a method call. The method call was normally |
|
2557 * initiated with dbus_g_proxy_end_call(). You may use this function |
|
2558 * outside of the callback given to dbus_g_proxy_begin_call; in that |
|
2559 * case this function will block if the results haven't yet been |
|
2560 * received. |
|
2561 * |
|
2562 * If the call results in an error, the error is set as normal for |
|
2563 * GError and the function returns #FALSE. |
|
2564 * |
|
2565 * Otherwise, the "out" parameters and return value of the |
|
2566 * method are stored in the provided varargs list. |
|
2567 * The list should be terminated with G_TYPE_INVALID. |
|
2568 * |
|
2569 * Returns: #FALSE if an error is set. |
|
2570 */ |
|
2571 #ifdef __SYMBIAN32__ |
|
2572 EXPORT_C |
|
2573 #endif |
|
2574 gboolean |
|
2575 dbus_g_proxy_end_call (DBusGProxy *proxy, |
|
2576 DBusGProxyCall *call, |
|
2577 GError **error, |
|
2578 GType first_arg_type, |
|
2579 ...) |
|
2580 { |
|
2581 gboolean ret; |
|
2582 va_list args; |
|
2583 |
|
2584 va_start (args, first_arg_type); |
|
2585 |
|
2586 ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args); |
|
2587 |
|
2588 va_end (args); |
|
2589 |
|
2590 return ret; |
|
2591 } |
|
2592 |
|
2593 /** |
|
2594 * dbus_g_proxy_call: |
|
2595 * @proxy: a proxy for a remote interface |
|
2596 * @method: method to invoke |
|
2597 * @error: return location for an error |
|
2598 * @first_arg_type: type of first "in" argument |
|
2599 * |
|
2600 * Function for synchronously invoking a method and receiving reply |
|
2601 * values. This function is equivalent to dbus_g_proxy_begin_call |
|
2602 * followed by dbus_g_proxy_end_call. All of the input arguments are |
|
2603 * specified first, followed by G_TYPE_INVALID, followed by all of the |
|
2604 * output values, followed by a second G_TYPE_INVALID. Note that |
|
2605 * this means you must always specify G_TYPE_INVALID twice. |
|
2606 * |
|
2607 * Returns: #FALSE if an error is set, #TRUE otherwise. |
|
2608 */ |
|
2609 #ifdef __SYMBIAN32__ |
|
2610 EXPORT_C |
|
2611 #endif |
|
2612 gboolean |
|
2613 dbus_g_proxy_call (DBusGProxy *proxy, |
|
2614 const char *method, |
|
2615 GError **error, |
|
2616 GType first_arg_type, |
|
2617 ...) |
|
2618 { |
|
2619 gboolean ret; |
|
2620 guint call_id; |
|
2621 va_list args; |
|
2622 GValueArray *in_args; |
|
2623 |
|
2624 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); |
|
2625 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); |
|
2626 |
|
2627 va_start (args, first_arg_type); |
|
2628 |
|
2629 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args); |
|
2630 |
|
2631 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,-1); |
|
2632 |
|
2633 g_value_array_free (in_args); |
|
2634 |
|
2635 first_arg_type = va_arg (args, GType); |
|
2636 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args); |
|
2637 |
|
2638 va_end (args); |
|
2639 |
|
2640 return ret; |
|
2641 } |
|
2642 |
|
2643 /** |
|
2644 * dbus_g_proxy_call_with_timeout: |
|
2645 * @proxy: a proxy for a remote interface |
|
2646 * @method: method to invoke |
|
2647 * @timeout: specify the timeout in milliseconds |
|
2648 * @error: return location for an error |
|
2649 * @first_arg_type: type of first "in" argument |
|
2650 * |
|
2651 * Function for synchronously invoking a method and receiving reply |
|
2652 * values. This function is equivalent to dbus_g_proxy_begin_call |
|
2653 * followed by dbus_g_proxy_end_call. All of the input arguments are |
|
2654 * specified first, followed by G_TYPE_INVALID, followed by all of the |
|
2655 * output values, followed by a second G_TYPE_INVALID. Note that |
|
2656 * this means you must always specify G_TYPE_INVALID twice. |
|
2657 * |
|
2658 * Returns: #FALSE if an error is set, #TRUE otherwise. |
|
2659 */ |
|
2660 #ifdef __SYMBIAN32__ |
|
2661 EXPORT_C |
|
2662 #endif |
|
2663 gboolean |
|
2664 dbus_g_proxy_call_with_timeout (DBusGProxy *proxy, |
|
2665 const char *method, |
|
2666 int timeout, |
|
2667 GError **error, |
|
2668 GType first_arg_type, |
|
2669 ...) |
|
2670 { |
|
2671 gboolean ret; |
|
2672 guint call_id; |
|
2673 va_list args; |
|
2674 GValueArray *in_args; |
|
2675 |
|
2676 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE); |
|
2677 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE); |
|
2678 |
|
2679 va_start (args, first_arg_type); |
|
2680 |
|
2681 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args); |
|
2682 |
|
2683 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,timeout); |
|
2684 |
|
2685 g_value_array_free (in_args); |
|
2686 |
|
2687 first_arg_type = va_arg (args, GType); |
|
2688 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args); |
|
2689 |
|
2690 va_end (args); |
|
2691 |
|
2692 return ret; |
|
2693 } |
|
2694 |
|
2695 /** |
|
2696 * dbus_g_proxy_call_no_reply: |
|
2697 * @proxy: a proxy for a remote interface |
|
2698 * @method: the name of the method to invoke |
|
2699 * @first_arg_type: type of the first argument |
|
2700 * |
|
2701 * Sends a method call message as with dbus_g_proxy_begin_call(), but |
|
2702 * does not ask for a reply or allow you to receive one. |
|
2703 * |
|
2704 * TODO: this particular function shouldn't die on out of memory, |
|
2705 * since you should be able to do a call with large arguments. |
|
2706 */ |
|
2707 #ifdef __SYMBIAN32__ |
|
2708 EXPORT_C |
|
2709 #endif |
|
2710 void |
|
2711 dbus_g_proxy_call_no_reply (DBusGProxy *proxy, |
|
2712 const char *method, |
|
2713 GType first_arg_type, |
|
2714 ...) |
|
2715 { |
|
2716 DBusMessage *message; |
|
2717 va_list args; |
|
2718 GValueArray *in_args; |
|
2719 DBusGProxyPrivate *priv; |
|
2720 |
|
2721 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
2722 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
2723 |
|
2724 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2725 |
|
2726 va_start (args, first_arg_type); |
|
2727 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args); |
|
2728 |
|
2729 message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args); |
|
2730 |
|
2731 g_value_array_free (in_args); |
|
2732 va_end (args); |
|
2733 |
|
2734 if (!message) |
|
2735 goto oom; |
|
2736 |
|
2737 dbus_message_set_no_reply (message, TRUE); |
|
2738 |
|
2739 if (!dbus_connection_send (priv->manager->connection, |
|
2740 message, |
|
2741 NULL)) |
|
2742 goto oom; |
|
2743 dbus_message_unref (message); |
|
2744 return; |
|
2745 |
|
2746 oom: |
|
2747 g_error ("Out of memory"); |
|
2748 } |
|
2749 |
|
2750 /** |
|
2751 * dbus_g_proxy_cancel_call |
|
2752 * @proxy: a proxy for a remote interface |
|
2753 * @call: the pending call ID from dbus_g_proxy_begin_call() |
|
2754 * |
|
2755 * Cancels a pending method call. The method call was normally |
|
2756 * initiated with dbus_g_proxy_begin_call(). This function |
|
2757 * may not be used on pending calls that have already been |
|
2758 * ended with dbus_g_proxy_end_call. |
|
2759 */ |
|
2760 #ifdef __SYMBIAN32__ |
|
2761 EXPORT_C |
|
2762 #endif |
|
2763 void |
|
2764 dbus_g_proxy_cancel_call (DBusGProxy *proxy, |
|
2765 DBusGProxyCall *call) |
|
2766 { |
|
2767 guint call_id; |
|
2768 DBusPendingCall *pending; |
|
2769 DBusGProxyPrivate *priv; |
|
2770 |
|
2771 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
2772 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
2773 |
|
2774 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2775 |
|
2776 call_id = DBUS_G_PROXY_CALL_TO_ID (call); |
|
2777 |
|
2778 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id)); |
|
2779 g_return_if_fail (pending != NULL); |
|
2780 |
|
2781 dbus_pending_call_cancel (pending); |
|
2782 |
|
2783 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id)); |
|
2784 } |
|
2785 |
|
2786 /** |
|
2787 * dbus_g_proxy_send: |
|
2788 * @proxy: a proxy for a remote interface |
|
2789 * @message: the message to address and send |
|
2790 * @client_serial: return location for message's serial, or #NULL |
|
2791 * |
|
2792 * Sends a message to the interface we're proxying for. Does not |
|
2793 * block or wait for a reply. The message is only actually written out |
|
2794 * when you return to the main loop or block in |
|
2795 * dbus_connection_flush(). |
|
2796 * |
|
2797 * The message is modified to be addressed to the target interface. |
|
2798 * That is, a destination name field or whatever is needed will be |
|
2799 * added to the message. The basic point of this function is to add |
|
2800 * the necessary header fields, otherwise it's equivalent to |
|
2801 * dbus_connection_send(). |
|
2802 * |
|
2803 * This function adds a reference to the message, so the caller |
|
2804 * still owns its original reference. |
|
2805 */ |
|
2806 #ifdef __SYMBIAN32__ |
|
2807 EXPORT_C |
|
2808 #endif |
|
2809 void |
|
2810 dbus_g_proxy_send (DBusGProxy *proxy, |
|
2811 DBusMessage *message, |
|
2812 dbus_uint32_t *client_serial) |
|
2813 { |
|
2814 DBusGProxyPrivate *priv; |
|
2815 |
|
2816 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
2817 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
2818 |
|
2819 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2820 |
|
2821 if (priv->name) |
|
2822 { |
|
2823 if (!dbus_message_set_destination (message, priv->name)) |
|
2824 g_error ("Out of memory"); |
|
2825 } |
|
2826 if (priv->path) |
|
2827 { |
|
2828 if (!dbus_message_set_path (message, priv->path)) |
|
2829 g_error ("Out of memory"); |
|
2830 } |
|
2831 if (priv->interface) |
|
2832 { |
|
2833 if (!dbus_message_set_interface (message, priv->interface)) |
|
2834 g_error ("Out of memory"); |
|
2835 } |
|
2836 |
|
2837 if (!dbus_connection_send (priv->manager->connection, message, client_serial)) |
|
2838 g_error ("Out of memory\n"); |
|
2839 } |
|
2840 |
|
2841 static void |
|
2842 array_free_all (gpointer array) |
|
2843 { |
|
2844 g_array_free (array, TRUE); |
|
2845 } |
|
2846 |
|
2847 /** |
|
2848 * dbus_g_proxy_add_signal: |
|
2849 * @proxy: the proxy for a remote interface |
|
2850 * @signal_name: the name of the signal |
|
2851 * @first_type: the first argument type, or G_TYPE_INVALID if none |
|
2852 * |
|
2853 * Specifies the argument signature of a signal;.only necessary |
|
2854 * if the remote object does not support introspection. The arguments |
|
2855 * specified are the GLib types expected. |
|
2856 */ |
|
2857 #ifdef __SYMBIAN32__ |
|
2858 EXPORT_C |
|
2859 #endif |
|
2860 void |
|
2861 dbus_g_proxy_add_signal (DBusGProxy *proxy, |
|
2862 const char *signal_name, |
|
2863 GType first_type, |
|
2864 ...) |
|
2865 { |
|
2866 GQuark q; |
|
2867 char *name; |
|
2868 GArray *gtypesig; |
|
2869 GType gtype; |
|
2870 va_list args; |
|
2871 DBusGProxyPrivate *priv; |
|
2872 |
|
2873 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
2874 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
2875 g_return_if_fail (signal_name != NULL); |
|
2876 |
|
2877 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2878 |
|
2879 name = create_signal_name (priv->interface, signal_name); |
|
2880 |
|
2881 q = g_quark_from_string (name); |
|
2882 |
|
2883 g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL); |
|
2884 |
|
2885 gtypesig = g_array_new (FALSE, TRUE, sizeof (GType)); |
|
2886 |
|
2887 va_start (args, first_type); |
|
2888 gtype = first_type; |
|
2889 while (gtype != G_TYPE_INVALID) |
|
2890 { |
|
2891 g_array_append_val (gtypesig, gtype); |
|
2892 gtype = va_arg (args, GType); |
|
2893 } |
|
2894 va_end (args); |
|
2895 |
|
2896 #ifndef G_DISABLE_CHECKS |
|
2897 if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL) |
|
2898 g_warning ("No marshaller for signature of signal '%s'", signal_name); |
|
2899 #endif |
|
2900 |
|
2901 |
|
2902 g_datalist_id_set_data_full (&priv->signal_signatures, |
|
2903 q, gtypesig, |
|
2904 array_free_all); |
|
2905 |
|
2906 g_free (name); |
|
2907 } |
|
2908 |
|
2909 /** |
|
2910 * dbus_g_proxy_connect_signal: |
|
2911 * @proxy: a proxy for a remote interface |
|
2912 * @signal_name: the DBus signal name to listen for |
|
2913 * @handler: the handler to connect |
|
2914 * @data: data to pass to handler |
|
2915 * @free_data_func: callback function to destroy data |
|
2916 * |
|
2917 * Connect a signal handler to a proxy for a remote interface. When |
|
2918 * the remote interface emits the specified signal, the proxy will |
|
2919 * emit a corresponding GLib signal. |
|
2920 */ |
|
2921 #ifdef __SYMBIAN32__ |
|
2922 EXPORT_C |
|
2923 #endif |
|
2924 void |
|
2925 dbus_g_proxy_connect_signal (DBusGProxy *proxy, |
|
2926 const char *signal_name, |
|
2927 GCallback handler, |
|
2928 void *data, |
|
2929 GClosureNotify free_data_func) |
|
2930 { |
|
2931 char *name; |
|
2932 GClosure *closure; |
|
2933 GQuark q; |
|
2934 DBusGProxyPrivate *priv; |
|
2935 |
|
2936 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
2937 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
2938 g_return_if_fail (signal_name != NULL); |
|
2939 g_return_if_fail (handler != NULL); |
|
2940 |
|
2941 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2942 name = create_signal_name (priv->interface, signal_name); |
|
2943 |
|
2944 q = g_quark_try_string (name); |
|
2945 |
|
2946 #ifndef G_DISABLE_CHECKS |
|
2947 if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL) |
|
2948 { |
|
2949 g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name); |
|
2950 g_free (name); |
|
2951 return; |
|
2952 } |
|
2953 #endif |
|
2954 |
|
2955 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func); |
|
2956 |
|
2957 g_signal_connect_closure_by_id (G_OBJECT (proxy), |
|
2958 signals[RECEIVED], |
|
2959 q, |
|
2960 closure, FALSE); |
|
2961 |
|
2962 g_free (name); |
|
2963 } |
|
2964 |
|
2965 /** |
|
2966 * dbus_g_proxy_disconnect_signal: |
|
2967 * @proxy: a proxy for a remote interface |
|
2968 * @signal_name: the DBus signal name to disconnect |
|
2969 * @handler: the handler to disconnect |
|
2970 * @data: the data that was registered with handler |
|
2971 * |
|
2972 * Disconnect all signal handlers from a proxy that match the given |
|
2973 * criteria. |
|
2974 */ |
|
2975 #ifdef __SYMBIAN32__ |
|
2976 EXPORT_C |
|
2977 #endif |
|
2978 void |
|
2979 dbus_g_proxy_disconnect_signal (DBusGProxy *proxy, |
|
2980 const char *signal_name, |
|
2981 GCallback handler, |
|
2982 void *data) |
|
2983 { |
|
2984 char *name; |
|
2985 GQuark q; |
|
2986 DBusGProxyPrivate *priv; |
|
2987 |
|
2988 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); |
|
2989 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy)); |
|
2990 g_return_if_fail (signal_name != NULL); |
|
2991 g_return_if_fail (handler != NULL); |
|
2992 |
|
2993 priv = DBUS_G_PROXY_GET_PRIVATE(proxy); |
|
2994 name = create_signal_name (priv->interface, signal_name); |
|
2995 |
|
2996 q = g_quark_try_string (name); |
|
2997 |
|
2998 if (q != 0) |
|
2999 { |
|
3000 g_signal_handlers_disconnect_matched (G_OBJECT (proxy), |
|
3001 G_SIGNAL_MATCH_DETAIL | |
|
3002 G_SIGNAL_MATCH_FUNC | |
|
3003 G_SIGNAL_MATCH_DATA, |
|
3004 signals[RECEIVED], |
|
3005 q, |
|
3006 NULL, |
|
3007 #ifdef WINSCW |
|
3008 G_CALLBACK (handler), data); |
|
3009 #else |
|
3010 (gpointer)(handler), data); |
|
3011 #endif |
|
3012 } |
|
3013 else |
|
3014 { |
|
3015 g_warning ("Attempt to disconnect from signal '%s' which is not registered\n", |
|
3016 name); |
|
3017 } |
|
3018 |
|
3019 g_free (name); |
|
3020 } |
|
3021 |
|
3022 /** @} End of DBusGLib public */ |
|
3023 |
|
3024 #ifdef DBUS_BUILD_TESTS |
|
3025 |
|
3026 /** |
|
3027 * @ingroup DBusGLibInternals |
|
3028 * Unit test for GLib proxy functions |
|
3029 * Returns: #TRUE on success. |
|
3030 */ |
|
3031 gboolean |
|
3032 _dbus_g_proxy_test (void) |
|
3033 { |
|
3034 |
|
3035 |
|
3036 return TRUE; |
|
3037 } |
|
3038 |
|
3039 #endif /* DBUS_BUILD_TESTS */ |