00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <dbus/dbus-glib.h>
00025 #include <dbus/dbus-glib-lowlevel.h>
00026 #include <dbus/dbus-signature.h>
00027 #include "dbus-gutils.h"
00028 #include "dbus-gsignature.h"
00029 #include "dbus-gvalue.h"
00030 #include "dbus-gvalue-utils.h"
00031 #include "dbus-gobject.h"
00032 #include <string.h>
00033 #include <glib/gi18n.h>
00034 #include <gobject/gvaluecollector.h>
00035
00036 #define DBUS_G_PROXY_CALL_TO_ID(x) (GPOINTER_TO_UINT(x))
00037 #define DBUS_G_PROXY_ID_TO_CALL(x) (GUINT_TO_POINTER(x))
00038 #define DBUS_G_PROXY_GET_PRIVATE(o) \
00039 (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUS_TYPE_G_PROXY, DBusGProxyPrivate))
00040
00041
00052 typedef struct _DBusGProxyManager DBusGProxyManager;
00053
00054 typedef struct _DBusGProxyPrivate DBusGProxyPrivate;
00055
00059 struct _DBusGProxyPrivate
00060 {
00061 DBusGProxyManager *manager;
00062 char *name;
00063 char *path;
00064 char *interface;
00066 DBusGProxyCall *name_call;
00067 guint for_owner : 1;
00068 guint associated : 1;
00070
00071 guint call_id_counter;
00073 GData *signal_signatures;
00075 GHashTable *pending_calls;
00076 };
00077
00078 static void dbus_g_proxy_init (DBusGProxy *proxy);
00079 static void dbus_g_proxy_class_init (DBusGProxyClass *klass);
00080 static GObject *dbus_g_proxy_constructor (GType type,
00081 guint n_construct_properties,
00082 GObjectConstructParam *construct_properties);
00083 static void dbus_g_proxy_set_property (GObject *object,
00084 guint prop_id,
00085 const GValue *value,
00086 GParamSpec *pspec);
00087 static void dbus_g_proxy_get_property (GObject *object,
00088 guint prop_id,
00089 GValue *value,
00090 GParamSpec *pspec);
00091
00092 static void dbus_g_proxy_finalize (GObject *object);
00093 static void dbus_g_proxy_dispose (GObject *object);
00094 static void dbus_g_proxy_destroy (DBusGProxy *proxy);
00095 static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
00096 DBusMessage *message);
00097
00098 static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager *manager,
00099 const char *method,
00100 DBusGProxyCallNotify notify,
00101 gpointer data,
00102 GDestroyNotify destroy,
00103 GType first_arg_type,
00104 ...);
00105 static guint dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
00106 const char *method,
00107 DBusGProxyCallNotify notify,
00108 gpointer data,
00109 GDestroyNotify destroy,
00110 GValueArray *args);
00111 static gboolean dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
00112 guint call_id,
00113 GError **error,
00114 GType first_arg_type,
00115 va_list args);
00116
00121 typedef struct
00122 {
00123 GSList *proxies;
00125 char name[4];
00130 } DBusGProxyList;
00131
00137 struct _DBusGProxyManager
00138 {
00139 GStaticMutex lock;
00140 int refcount;
00141 DBusConnection *connection;
00143 DBusGProxy *bus_proxy;
00145 GHashTable *proxy_lists;
00148 GHashTable *owner_names;
00152 GSList *unassociated_proxies;
00156 };
00157
00158 static DBusGProxyManager *dbus_g_proxy_manager_ref (DBusGProxyManager *manager);
00159 static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection,
00160 DBusMessage *message,
00161 void *user_data);
00162
00163
00165 #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock))
00166
00167 #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock))
00168
00169 static int g_proxy_manager_slot = -1;
00170
00171
00172 static GStaticMutex connection_g_proxy_lock = G_STATIC_MUTEX_INIT;
00173
00174 static DBusGProxyManager*
00175 dbus_g_proxy_manager_get (DBusConnection *connection)
00176 {
00177 DBusGProxyManager *manager;
00178
00179 dbus_connection_allocate_data_slot (&g_proxy_manager_slot);
00180 if (g_proxy_manager_slot < 0)
00181 g_error ("out of memory");
00182
00183 g_static_mutex_lock (&connection_g_proxy_lock);
00184
00185 manager = dbus_connection_get_data (connection, g_proxy_manager_slot);
00186 if (manager != NULL)
00187 {
00188 dbus_connection_free_data_slot (&g_proxy_manager_slot);
00189 dbus_g_proxy_manager_ref (manager);
00190 g_static_mutex_unlock (&connection_g_proxy_lock);
00191 return manager;
00192 }
00193
00194 manager = g_new0 (DBusGProxyManager, 1);
00195
00196 manager->refcount = 1;
00197 manager->connection = connection;
00198
00199 g_static_mutex_init (&manager->lock);
00200
00201
00202
00203
00204
00205 dbus_connection_ref (manager->connection);
00206
00207 dbus_connection_set_data (connection, g_proxy_manager_slot,
00208 manager, NULL);
00209
00210 dbus_connection_add_filter (connection, dbus_g_proxy_manager_filter,
00211 manager, NULL);
00212
00213 g_static_mutex_unlock (&connection_g_proxy_lock);
00214
00215 return manager;
00216 }
00217
00218 static DBusGProxyManager *
00219 dbus_g_proxy_manager_ref (DBusGProxyManager *manager)
00220 {
00221 g_assert (manager != NULL);
00222 g_assert (manager->refcount > 0);
00223
00224 LOCK_MANAGER (manager);
00225
00226 manager->refcount += 1;
00227
00228 UNLOCK_MANAGER (manager);
00229
00230 return manager;
00231 }
00232
00233 static void
00234 dbus_g_proxy_manager_unref (DBusGProxyManager *manager)
00235 {
00236 g_assert (manager != NULL);
00237 g_assert (manager->refcount > 0);
00238
00239 LOCK_MANAGER (manager);
00240 manager->refcount -= 1;
00241 if (manager->refcount == 0)
00242 {
00243 UNLOCK_MANAGER (manager);
00244
00245 if (manager->bus_proxy)
00246 g_object_unref (manager->bus_proxy);
00247
00248 if (manager->proxy_lists)
00249 {
00250
00251
00252
00253 g_assert (g_hash_table_size (manager->proxy_lists) == 0);
00254
00255 g_hash_table_destroy (manager->proxy_lists);
00256 manager->proxy_lists = NULL;
00257
00258 }
00259
00260 if (manager->owner_names)
00261 {
00262
00263
00264
00265 g_assert (g_hash_table_size (manager->owner_names) == 0);
00266
00267 g_hash_table_destroy (manager->owner_names);
00268 manager->owner_names = NULL;
00269 }
00270
00271 g_assert (manager->unassociated_proxies == NULL);
00272
00273 g_static_mutex_free (&manager->lock);
00274
00275 g_static_mutex_lock (&connection_g_proxy_lock);
00276
00277 dbus_connection_remove_filter (manager->connection, dbus_g_proxy_manager_filter,
00278 manager);
00279
00280 dbus_connection_set_data (manager->connection,
00281 g_proxy_manager_slot,
00282 NULL, NULL);
00283
00284 g_static_mutex_unlock (&connection_g_proxy_lock);
00285
00286 dbus_connection_unref (manager->connection);
00287 g_free (manager);
00288
00289 dbus_connection_free_data_slot (&g_proxy_manager_slot);
00290 }
00291 else
00292 {
00293 UNLOCK_MANAGER (manager);
00294 }
00295 }
00296
00297 static guint
00298 tristring_hash (gconstpointer key)
00299 {
00300 const char *p = key;
00301 guint h = *p;
00302
00303 if (h)
00304 {
00305 for (p += 1; *p != '\0'; p++)
00306 h = (h << 5) - h + *p;
00307 }
00308
00309
00310 for (p += 1; *p != '\0'; p++)
00311 h = (h << 5) - h + *p;
00312
00313
00314 for (p += 1; *p != '\0'; p++)
00315 h = (h << 5) - h + *p;
00316
00317 return h;
00318 }
00319
00320 static gboolean
00321 strequal_len (const char *a,
00322 const char *b,
00323 size_t *lenp)
00324 {
00325 size_t a_len;
00326 size_t b_len;
00327
00328 a_len = strlen (a);
00329 b_len = strlen (b);
00330
00331 if (a_len != b_len)
00332 return FALSE;
00333
00334 if (memcmp (a, b, a_len) != 0)
00335 return FALSE;
00336
00337 *lenp = a_len;
00338
00339 return TRUE;
00340 }
00341
00342 static gboolean
00343 tristring_equal (gconstpointer a,
00344 gconstpointer b)
00345 {
00346 const char *ap = a;
00347 const char *bp = b;
00348 size_t len;
00349
00350 if (!strequal_len (ap, bp, &len))
00351 return FALSE;
00352
00353 ap += len + 1;
00354 bp += len + 1;
00355
00356 if (!strequal_len (ap, bp, &len))
00357 return FALSE;
00358
00359 ap += len + 1;
00360 bp += len + 1;
00361
00362 if (strcmp (ap, bp) != 0)
00363 return FALSE;
00364
00365 return TRUE;
00366 }
00367
00368 static char*
00369 tristring_alloc_from_strings (size_t padding_before,
00370 const char *name,
00371 const char *path,
00372 const char *interface)
00373 {
00374 size_t name_len, iface_len, path_len, len;
00375 char *tri;
00376
00377 if (name)
00378 name_len = strlen (name);
00379 else
00380 name_len = 0;
00381
00382 path_len = strlen (path);
00383
00384 iface_len = strlen (interface);
00385
00386 tri = g_malloc (padding_before + name_len + path_len + iface_len + 3);
00387
00388 len = padding_before;
00389
00390 if (name)
00391 memcpy (&tri[len], name, name_len);
00392
00393 len += name_len;
00394 tri[len] = '\0';
00395 len += 1;
00396
00397 g_assert (len == (padding_before + name_len + 1));
00398
00399 memcpy (&tri[len], path, path_len);
00400 len += path_len;
00401 tri[len] = '\0';
00402 len += 1;
00403
00404 g_assert (len == (padding_before + name_len + path_len + 2));
00405
00406 memcpy (&tri[len], interface, iface_len);
00407 len += iface_len;
00408 tri[len] = '\0';
00409 len += 1;
00410
00411 g_assert (len == (padding_before + name_len + path_len + iface_len + 3));
00412
00413 return tri;
00414 }
00415
00416 static char*
00417 tristring_from_proxy (DBusGProxy *proxy)
00418 {
00419 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00420
00421 return tristring_alloc_from_strings (0,
00422 priv->name,
00423 priv->path,
00424 priv->interface);
00425 }
00426
00427 static char*
00428 tristring_from_message (DBusMessage *message)
00429 {
00430 const char *path;
00431 const char *interface;
00432
00433 path = dbus_message_get_path (message);
00434 interface = dbus_message_get_interface (message);
00435
00436 g_assert (path);
00437 g_assert (interface);
00438
00439 return tristring_alloc_from_strings (0,
00440 dbus_message_get_sender (message),
00441 path, interface);
00442 }
00443
00444 static DBusGProxyList*
00445 g_proxy_list_new (DBusGProxy *first_proxy)
00446 {
00447 DBusGProxyList *list;
00448 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(first_proxy);
00449
00450 list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name),
00451 priv->name,
00452 priv->path,
00453 priv->interface);
00454 list->proxies = NULL;
00455
00456 return list;
00457 }
00458
00459 static void
00460 g_proxy_list_free (DBusGProxyList *list)
00461 {
00462
00463
00464
00465 g_slist_free (list->proxies);
00466
00467 g_free (list);
00468 }
00469
00470 static char*
00471 g_proxy_get_match_rule (DBusGProxy *proxy)
00472 {
00473 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00474
00475
00476 if (priv->name)
00477 return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'",
00478 priv->name, priv->path, priv->interface);
00479 else
00480 return g_strdup_printf ("type='signal',path='%s',interface='%s'",
00481 priv->path, priv->interface);
00482 }
00483
00484 typedef struct
00485 {
00486 char *name;
00487 guint refcount;
00488 } DBusGProxyNameOwnerInfo;
00489
00490 static gint
00491 find_name_in_info (gconstpointer a, gconstpointer b)
00492 {
00493 const DBusGProxyNameOwnerInfo *info = a;
00494 const char *name = b;
00495
00496 if (info == NULL || info->name == NULL)
00497 return 1;
00498 return strcmp (info->name, name);
00499 }
00500
00501 typedef struct
00502 {
00503 const char *name;
00504 const char *owner;
00505 DBusGProxyNameOwnerInfo *info;
00506 } DBusGProxyNameOwnerForeachData;
00507
00508 static void
00509 name_owner_foreach (gpointer key, gpointer val, gpointer data)
00510 {
00511 const char *owner;
00512 DBusGProxyNameOwnerForeachData *foreach_data;
00513 GSList *names;
00514 GSList *link;
00515
00516 owner = key;
00517 names = val;
00518 foreach_data = data;
00519
00520 if (foreach_data->owner != NULL)
00521 return;
00522
00523 g_assert (foreach_data->info == NULL);
00524
00525 link = g_slist_find_custom (names, foreach_data->name, find_name_in_info);
00526 if (link)
00527 {
00528 foreach_data->owner = owner;
00529 foreach_data->info = link->data;
00530 }
00531 }
00532
00533 static gboolean
00534 dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager *manager,
00535 const char *name,
00536 DBusGProxyNameOwnerInfo **info,
00537 const char **owner)
00538 {
00539 DBusGProxyNameOwnerForeachData foreach_data;
00540
00541 foreach_data.name = name;
00542 foreach_data.owner = NULL;
00543 foreach_data.info = NULL;
00544
00545 g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data);
00546
00547 *info = foreach_data.info;
00548 *owner = foreach_data.owner;
00549 return *info != NULL;
00550 }
00551
00552 static void
00553 insert_nameinfo (DBusGProxyManager *manager,
00554 const char *owner,
00555 DBusGProxyNameOwnerInfo *info)
00556 {
00557 GSList *names;
00558 gboolean insert;
00559
00560 names = g_hash_table_lookup (manager->owner_names, owner);
00561
00562
00563 insert = (names == NULL);
00564
00565 names = g_slist_append (names, info);
00566
00567 if (insert)
00568 g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
00569 }
00570
00571 static void
00572 dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager *manager,
00573 const char *owner,
00574 const char *name)
00575 {
00576 GSList *names;
00577 GSList *link;
00578 DBusGProxyNameOwnerInfo *nameinfo;
00579
00580 names = g_hash_table_lookup (manager->owner_names, owner);
00581 link = g_slist_find_custom (names, name, find_name_in_info);
00582
00583 if (!link)
00584 {
00585 nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1);
00586 nameinfo->name = g_strdup (name);
00587 nameinfo->refcount = 1;
00588
00589 insert_nameinfo (manager, owner, nameinfo);
00590 }
00591 else
00592 {
00593 nameinfo = link->data;
00594 nameinfo->refcount++;
00595 }
00596 }
00597
00598 static void
00599 dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager *manager,
00600 const char *name)
00601 {
00602 DBusGProxyNameOwnerInfo *info;
00603 const char *owner;
00604 gboolean ret;
00605
00606 ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner);
00607 g_assert (ret);
00608 g_assert (info != NULL);
00609 g_assert (owner != NULL);
00610
00611 info->refcount--;
00612 if (info->refcount == 0)
00613 {
00614 GSList *names;
00615 GSList *link;
00616
00617 names = g_hash_table_lookup (manager->owner_names, owner);
00618 link = g_slist_find_custom (names, name, find_name_in_info);
00619 names = g_slist_delete_link (names, link);
00620 if (names != NULL)
00621 g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
00622 else
00623 g_hash_table_remove (manager->owner_names, owner);
00624
00625 g_free (info->name);
00626 g_free (info);
00627 }
00628 }
00629
00630 typedef struct
00631 {
00632 const char *name;
00633 GSList *destroyed;
00634 } DBusGProxyUnassociateData;
00635
00636 static void
00637 unassociate_proxies (gpointer key, gpointer val, gpointer user_data)
00638 {
00639 DBusGProxyList *list;
00640 const char *name;
00641 GSList *tmp;
00642 DBusGProxyUnassociateData *data;
00643
00644 list = val;
00645 data = user_data;
00646 name = data->name;
00647
00648 for (tmp = list->proxies; tmp; tmp = tmp->next)
00649 {
00650 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
00651 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00652 DBusGProxyManager *manager;
00653
00654 manager = priv->manager;
00655
00656 if (!strcmp (priv->name, name))
00657 {
00658 if (!priv->for_owner)
00659 {
00660 if (priv->name_call != NULL)
00661 {
00662 dbus_g_proxy_cancel_call (manager->bus_proxy,
00663 priv->name_call);
00664 priv->name_call = NULL;
00665 }
00666
00667 priv->associated = FALSE;
00668 manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy);
00669 }
00670 else
00671 {
00672 data->destroyed = g_slist_prepend (data->destroyed, proxy);
00673
00674
00675 g_object_add_weak_pointer (G_OBJECT (proxy),
00676 &(data->destroyed->data));
00677 }
00678 }
00679 }
00680 }
00681
00682 static void
00683 dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager *manager,
00684 const char *name,
00685 const char *prev_owner,
00686 const char *new_owner)
00687 {
00688 GSList *names;
00689
00690 if (prev_owner[0] == '\0')
00691 {
00692 GSList *tmp;
00693 GSList *removed;
00694
00695
00696
00697 removed = NULL;
00698
00699 for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next)
00700 {
00701 DBusGProxy *proxy = tmp->data;
00702 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00703
00704 if (!strcmp (priv->name, name))
00705 {
00706 removed = g_slist_prepend (removed, tmp);
00707
00708 dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name);
00709 priv->associated = TRUE;
00710 }
00711 }
00712
00713 for (tmp = removed; tmp; tmp = tmp->next)
00714 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data);
00715 g_slist_free (removed);
00716 }
00717 else
00718 {
00719 DBusGProxyNameOwnerInfo *info;
00720 GSList *link;
00721
00722
00723
00724 names = g_hash_table_lookup (manager->owner_names, prev_owner);
00725
00726 info = NULL;
00727 if (names != NULL)
00728 {
00729 link = g_slist_find_custom (names, name, find_name_in_info);
00730
00731 if (link != NULL)
00732 {
00733 info = link->data;
00734
00735 names = g_slist_delete_link (names, link);
00736
00737 if (names == NULL)
00738 g_hash_table_remove (manager->owner_names, prev_owner);
00739 }
00740 }
00741
00742 if (new_owner[0] == '\0')
00743 {
00744 DBusGProxyUnassociateData data;
00745 GSList *tmp;
00746
00747 data.name = name;
00748 data.destroyed = NULL;
00749
00750
00751 g_hash_table_foreach (manager->proxy_lists,
00752 unassociate_proxies, &data);
00753
00754 UNLOCK_MANAGER (manager);
00755
00756
00757
00758
00759 for (tmp = data.destroyed; tmp; tmp = tmp->next)
00760 if (tmp->data != NULL)
00761 {
00762 g_object_remove_weak_pointer (G_OBJECT (tmp->data),
00763 &(tmp->data));
00764 dbus_g_proxy_destroy (tmp->data);
00765 }
00766 g_slist_free (data.destroyed);
00767
00768 LOCK_MANAGER (manager);
00769
00770 if (info)
00771 {
00772 g_free (info->name);
00773 g_free (info);
00774 }
00775 }
00776 else if (info)
00777 {
00778 insert_nameinfo (manager, new_owner, info);
00779 }
00780 }
00781 }
00782
00783 static void
00784 got_name_owner_cb (DBusGProxy *bus_proxy,
00785 DBusGProxyCall *call,
00786 void *user_data)
00787 {
00788 DBusGProxy *proxy = user_data;
00789 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00790 GError *error;
00791 char *owner;
00792
00793 error = NULL;
00794 owner = NULL;
00795
00796 LOCK_MANAGER (priv->manager);
00797
00798 if (!dbus_g_proxy_end_call (bus_proxy, call, &error,
00799 G_TYPE_STRING, &owner,
00800 G_TYPE_INVALID))
00801 {
00802 if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
00803 {
00804 priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy);
00805 }
00806 else
00807 g_warning ("Couldn't get name owner (%s): %s",
00808 dbus_g_error_get_name (error),
00809 error->message);
00810
00811 g_clear_error (&error);
00812 goto out;
00813 }
00814 else
00815 {
00816 dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name);
00817 priv->associated = TRUE;
00818 }
00819
00820 out:
00821 priv->name_call = NULL;
00822 UNLOCK_MANAGER (priv->manager);
00823 g_free (owner);
00824 }
00825
00826 static char *
00827 get_name_owner (DBusConnection *connection,
00828 const char *name,
00829 GError **error)
00830 {
00831 DBusError derror;
00832 DBusMessage *request, *reply;
00833 char *base_name;
00834
00835 dbus_error_init (&derror);
00836
00837 base_name = NULL;
00838 reply = NULL;
00839
00840 request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
00841 DBUS_PATH_DBUS,
00842 DBUS_INTERFACE_DBUS,
00843 "GetNameOwner");
00844 if (request == NULL)
00845 g_error ("Out of memory");
00846
00847 if (!dbus_message_append_args (request,
00848 DBUS_TYPE_STRING, &name,
00849 DBUS_TYPE_INVALID))
00850 g_error ("Out of memory");
00851
00852 reply =
00853 dbus_connection_send_with_reply_and_block (connection,
00854 request,
00855 2000, &derror);
00856 if (reply == NULL)
00857 goto error;
00858
00859 if (dbus_set_error_from_message (&derror, reply))
00860 goto error;
00861
00862 if (!dbus_message_get_args (reply, &derror,
00863 DBUS_TYPE_STRING, &base_name,
00864 DBUS_TYPE_INVALID))
00865 goto error;
00866
00867 base_name = g_strdup (base_name);
00868 goto out;
00869
00870 error:
00871 g_assert (dbus_error_is_set (&derror));
00872 dbus_set_g_error (error, &derror);
00873 dbus_error_free (&derror);
00874
00875 out:
00876 if (request)
00877 dbus_message_unref (request);
00878 if (reply)
00879 dbus_message_unref (reply);
00880
00881 return base_name;
00882 }
00883
00884
00885 static void
00886 dbus_g_proxy_manager_register (DBusGProxyManager *manager,
00887 DBusGProxy *proxy)
00888 {
00889 DBusGProxyList *list;
00890 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00891
00892 LOCK_MANAGER (manager);
00893
00894 if (manager->proxy_lists == NULL)
00895 {
00896 g_assert (manager->owner_names == NULL);
00897
00898 list = NULL;
00899 manager->proxy_lists = g_hash_table_new_full (tristring_hash,
00900 tristring_equal,
00901 NULL,
00902 (GFreeFunc) g_proxy_list_free);
00903 manager->owner_names = g_hash_table_new_full (g_str_hash,
00904 g_str_equal,
00905 g_free,
00906 NULL);
00907
00908
00909
00910 dbus_bus_add_match (manager->connection,
00911 "type='signal',sender='" DBUS_SERVICE_DBUS
00912 "',path='" DBUS_PATH_DBUS
00913 "',interface='" DBUS_INTERFACE_DBUS
00914 "',member='NameOwnerChanged'",
00915 NULL);
00916 }
00917 else
00918 {
00919 char *tri;
00920
00921 tri = tristring_from_proxy (proxy);
00922
00923 list = g_hash_table_lookup (manager->proxy_lists, tri);
00924
00925 g_free (tri);
00926 }
00927
00928 if (list == NULL)
00929 {
00930 list = g_proxy_list_new (proxy);
00931
00932 g_hash_table_replace (manager->proxy_lists,
00933 list->name, list);
00934 }
00935
00936 if (list->proxies == NULL)
00937 {
00938
00939
00940
00941
00942 char *rule;
00943
00944 rule = g_proxy_get_match_rule (proxy);
00945
00946
00947
00948
00949 dbus_bus_add_match (manager->connection,
00950 rule, NULL);
00951
00952 g_free (rule);
00953 }
00954
00955 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00956
00957 list->proxies = g_slist_prepend (list->proxies, proxy);
00958
00959 if (!priv->for_owner)
00960 {
00961 const char *owner;
00962 DBusGProxyNameOwnerInfo *info;
00963
00964 if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner))
00965 {
00966 priv->name_call = manager_begin_bus_call (manager, "GetNameOwner",
00967 got_name_owner_cb,
00968 proxy, NULL,
00969 G_TYPE_STRING,
00970 priv->name,
00971 G_TYPE_INVALID);
00972
00973 priv->associated = FALSE;
00974 }
00975 else
00976 {
00977 info->refcount++;
00978 priv->associated = TRUE;
00979 }
00980 }
00981
00982 UNLOCK_MANAGER (manager);
00983 }
00984
00985 static void
00986 dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
00987 DBusGProxy *proxy)
00988 {
00989 DBusGProxyList *list;
00990 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00991 char *tri;
00992
00993 LOCK_MANAGER (manager);
00994
00995 #ifndef G_DISABLE_CHECKS
00996 if (manager->proxy_lists == NULL)
00997 {
00998 g_warning ("Trying to unregister a proxy but there aren't any registered");
00999 return;
01000 }
01001 #endif
01002
01003 tri = tristring_from_proxy (proxy);
01004
01005 list = g_hash_table_lookup (manager->proxy_lists, tri);
01006
01007 #ifndef G_DISABLE_CHECKS
01008 if (list == NULL)
01009 {
01010 g_warning ("Trying to unregister a proxy but it isn't registered");
01011 return;
01012 }
01013 #endif
01014
01015 g_assert (g_slist_find (list->proxies, proxy) != NULL);
01016
01017 list->proxies = g_slist_remove (list->proxies, proxy);
01018
01019 g_assert (g_slist_find (list->proxies, proxy) == NULL);
01020
01021 if (!priv->for_owner)
01022 {
01023 if (!priv->associated)
01024 {
01025 GSList *link;
01026
01027 if (priv->name_call != 0)
01028 {
01029 dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
01030 priv->name_call = 0;
01031 }
01032 else
01033 {
01034 link = g_slist_find (manager->unassociated_proxies, proxy);
01035 g_assert (link != NULL);
01036
01037 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link);
01038 }
01039 }
01040 else
01041 {
01042 g_assert (priv->name_call == 0);
01043
01044 dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name);
01045 }
01046 }
01047
01048 if (list->proxies == NULL)
01049 {
01050 char *rule;
01051 g_hash_table_remove (manager->proxy_lists,
01052 tri);
01053 list = NULL;
01054
01055 rule = g_proxy_get_match_rule (proxy);
01056 dbus_bus_remove_match (manager->connection,
01057 rule, NULL);
01058 g_free (rule);
01059 }
01060
01061 if (g_hash_table_size (manager->proxy_lists) == 0)
01062 {
01063 g_hash_table_destroy (manager->proxy_lists);
01064 manager->proxy_lists = NULL;
01065 }
01066
01067 g_free (tri);
01068
01069 UNLOCK_MANAGER (manager);
01070 }
01071
01072 static void
01073 list_proxies_foreach (gpointer key,
01074 gpointer value,
01075 gpointer user_data)
01076 {
01077 DBusGProxyList *list;
01078 GSList **ret;
01079 GSList *tmp;
01080
01081 list = value;
01082 ret = user_data;
01083
01084 tmp = list->proxies;
01085 while (tmp != NULL)
01086 {
01087 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
01088
01089 g_object_ref (proxy);
01090 *ret = g_slist_prepend (*ret, proxy);
01091
01092 tmp = tmp->next;
01093 }
01094 }
01095
01096 static GSList*
01097 dbus_g_proxy_manager_list_all (DBusGProxyManager *manager)
01098 {
01099 GSList *ret;
01100
01101 ret = NULL;
01102
01103 if (manager->proxy_lists)
01104 {
01105 g_hash_table_foreach (manager->proxy_lists,
01106 list_proxies_foreach,
01107 &ret);
01108 }
01109
01110 return ret;
01111 }
01112
01113 static DBusHandlerResult
01114 dbus_g_proxy_manager_filter (DBusConnection *connection,
01115 DBusMessage *message,
01116 void *user_data)
01117 {
01118 DBusGProxyManager *manager;
01119
01120 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
01121 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01122
01123 manager = user_data;
01124
01125 dbus_g_proxy_manager_ref (manager);
01126
01127 LOCK_MANAGER (manager);
01128
01129 if (dbus_message_is_signal (message,
01130 DBUS_INTERFACE_LOCAL,
01131 "Disconnected"))
01132 {
01133
01134
01135
01136 GSList *all;
01137 GSList *tmp;
01138
01139 all = dbus_g_proxy_manager_list_all (manager);
01140
01141 tmp = all;
01142 while (tmp != NULL)
01143 {
01144 DBusGProxy *proxy;
01145
01146 proxy = DBUS_G_PROXY (tmp->data);
01147
01148 UNLOCK_MANAGER (manager);
01149 dbus_g_proxy_destroy (proxy);
01150 g_object_unref (G_OBJECT (proxy));
01151 LOCK_MANAGER (manager);
01152
01153 tmp = tmp->next;
01154 }
01155
01156 g_slist_free (all);
01157
01158 #ifndef G_DISABLE_CHECKS
01159 if (manager->proxy_lists != NULL)
01160 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.");
01161 #endif
01162 }
01163 else
01164 {
01165 char *tri;
01166 GSList *full_list;
01167 GSList *owned_names;
01168 GSList *tmp;
01169 const char *sender;
01170
01171
01172 if (dbus_message_is_signal (message,
01173 DBUS_INTERFACE_DBUS,
01174 "NameOwnerChanged"))
01175 {
01176 const char *name;
01177 const char *prev_owner;
01178 const char *new_owner;
01179 DBusError derr;
01180
01181 dbus_error_init (&derr);
01182 if (!dbus_message_get_args (message,
01183 &derr,
01184 DBUS_TYPE_STRING,
01185 &name,
01186 DBUS_TYPE_STRING,
01187 &prev_owner,
01188 DBUS_TYPE_STRING,
01189 &new_owner,
01190 DBUS_TYPE_INVALID))
01191 {
01192
01193 dbus_error_free (&derr);
01194 }
01195 else if (manager->owner_names != NULL)
01196 {
01197 dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner);
01198 }
01199 }
01200
01201 sender = dbus_message_get_sender (message);
01202
01203
01204 g_assert (sender != NULL);
01205 g_assert (dbus_message_get_path (message) != NULL);
01206 g_assert (dbus_message_get_interface (message) != NULL);
01207 g_assert (dbus_message_get_member (message) != NULL);
01208
01209 tri = tristring_from_message (message);
01210
01211 if (manager->proxy_lists)
01212 {
01213 DBusGProxyList *owner_list;
01214 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01215 if (owner_list)
01216 full_list = g_slist_copy (owner_list->proxies);
01217 else
01218 full_list = NULL;
01219 }
01220 else
01221 full_list = NULL;
01222
01223 g_free (tri);
01224
01225 if (manager->owner_names)
01226 {
01227 owned_names = g_hash_table_lookup (manager->owner_names, sender);
01228 for (tmp = owned_names; tmp; tmp = tmp->next)
01229 {
01230 DBusGProxyList *owner_list;
01231 DBusGProxyNameOwnerInfo *nameinfo;
01232
01233 nameinfo = tmp->data;
01234 g_assert (nameinfo->refcount > 0);
01235 tri = tristring_alloc_from_strings (0, nameinfo->name,
01236 dbus_message_get_path (message),
01237 dbus_message_get_interface (message));
01238
01239 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01240 if (owner_list != NULL)
01241 full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies));
01242 g_free (tri);
01243 }
01244 }
01245
01246 #if 0
01247 g_print ("proxy got %s,%s,%s = list %p\n",
01248 tri,
01249 tri + strlen (tri) + 1,
01250 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
01251 list);
01252 #endif
01253
01254
01255
01256 g_slist_foreach (full_list, (GFunc) g_object_ref, NULL);
01257
01258 for (tmp = full_list; tmp; tmp = tmp->next)
01259 {
01260 DBusGProxy *proxy;
01261
01262 proxy = DBUS_G_PROXY (tmp->data);
01263
01264 UNLOCK_MANAGER (manager);
01265 dbus_g_proxy_emit_remote_signal (proxy, message);
01266 g_object_unref (G_OBJECT (proxy));
01267 LOCK_MANAGER (manager);
01268 }
01269 g_slist_free (full_list);
01270 }
01271
01272 UNLOCK_MANAGER (manager);
01273 dbus_g_proxy_manager_unref (manager);
01274
01275
01276
01277
01278 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01279 }
01280
01281
01282
01283
01284 #define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL)
01285
01286 static void
01287 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01288 GValue *return_value,
01289 guint n_param_values,
01290 const GValue *param_values,
01291 gpointer invocation_hint,
01292 gpointer marshal_data);
01293 enum
01294 {
01295 PROP_0,
01296 PROP_NAME,
01297 PROP_PATH,
01298 PROP_INTERFACE,
01299 PROP_CONNECTION
01300 };
01301
01302 enum
01303 {
01304 DESTROY,
01305 RECEIVED,
01306 LAST_SIGNAL
01307 };
01308
01309 static void *parent_class;
01310 static guint signals[LAST_SIGNAL] = { 0 };
01311
01312 static void
01313 dbus_g_proxy_init (DBusGProxy *proxy)
01314 {
01315 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01316
01317 g_datalist_init (&priv->signal_signatures);
01318 priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
01319 (GDestroyNotify) dbus_pending_call_unref);
01320 priv->name_call = 0;
01321 priv->associated = FALSE;
01322 }
01323
01324 static GObject *
01325 dbus_g_proxy_constructor (GType type,
01326 guint n_construct_properties,
01327 GObjectConstructParam *construct_properties)
01328 {
01329 DBusGProxy *proxy;
01330 DBusGProxyClass *klass;
01331 GObjectClass *parent_class;
01332 DBusGProxyPrivate *priv;
01333
01334 klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
01335
01336 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
01337
01338 proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
01339 construct_properties));
01340
01341 priv = DBUS_G_PROXY_GET_PRIVATE (proxy);
01342
01343
01344
01345
01346
01347
01348 g_assert (priv->name != NULL);
01349 g_assert (priv->path != NULL);
01350 g_assert (priv->interface != NULL);
01351
01352 if (priv->manager != NULL)
01353 {
01354 dbus_g_proxy_manager_register (priv->manager, proxy);
01355 }
01356
01357 return G_OBJECT (proxy);
01358 }
01359
01360 static void
01361 dbus_g_proxy_class_init (DBusGProxyClass *klass)
01362 {
01363 GObjectClass *object_class = G_OBJECT_CLASS (klass);
01364
01365 parent_class = g_type_class_peek_parent (klass);
01366
01367 g_type_class_add_private (klass, sizeof (DBusGProxyPrivate));
01368
01369 object_class->set_property = dbus_g_proxy_set_property;
01370 object_class->get_property = dbus_g_proxy_get_property;
01371
01372 g_object_class_install_property (object_class,
01373 PROP_NAME,
01374 g_param_spec_string ("name",
01375 "name",
01376 "name",
01377 NULL,
01378 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01379
01380 g_object_class_install_property (object_class,
01381 PROP_PATH,
01382 g_param_spec_string ("path",
01383 "path",
01384 "path",
01385 NULL,
01386 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01387
01388 g_object_class_install_property (object_class,
01389 PROP_INTERFACE,
01390 g_param_spec_string ("interface",
01391 "interface",
01392 "interface",
01393 NULL,
01394 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01395
01396 g_object_class_install_property (object_class,
01397 PROP_CONNECTION,
01398 g_param_spec_boxed ("connection",
01399 "connection",
01400 "connection",
01401 DBUS_TYPE_G_CONNECTION,
01402 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01403
01404 object_class->finalize = dbus_g_proxy_finalize;
01405 object_class->dispose = dbus_g_proxy_dispose;
01406 object_class->constructor = dbus_g_proxy_constructor;
01407
01408 signals[DESTROY] =
01409 g_signal_new ("destroy",
01410 G_OBJECT_CLASS_TYPE (object_class),
01411 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
01412 0,
01413 NULL, NULL,
01414 g_cclosure_marshal_VOID__VOID,
01415 G_TYPE_NONE, 0);
01416
01417 signals[RECEIVED] =
01418 g_signal_new ("received",
01419 G_OBJECT_CLASS_TYPE (object_class),
01420 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
01421 0,
01422 NULL, NULL,
01423 marshal_dbus_message_to_g_marshaller,
01424 G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER);
01425 }
01426
01427 static void
01428 cancel_pending_call (gpointer key, gpointer val, gpointer data)
01429 {
01430 DBusGProxyCall *call = key;
01431 DBusGProxy *proxy = data;
01432
01433 dbus_g_proxy_cancel_call (proxy, call);
01434 }
01435
01436 static void
01437 dbus_g_proxy_dispose (GObject *object)
01438 {
01439 DBusGProxy *proxy = DBUS_G_PROXY (object);
01440 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01441
01442 if (priv->pending_calls == NULL)
01443 {
01444 return;
01445 }
01446
01447
01448 g_hash_table_foreach (priv->pending_calls, cancel_pending_call, proxy);
01449 g_hash_table_destroy (priv->pending_calls);
01450 priv->pending_calls = NULL;
01451
01452 if (priv->manager && proxy != priv->manager->bus_proxy)
01453 {
01454 dbus_g_proxy_manager_unregister (priv->manager, proxy);
01455 dbus_g_proxy_manager_unref (priv->manager);
01456 }
01457 priv->manager = NULL;
01458
01459 g_datalist_clear (&priv->signal_signatures);
01460
01461 g_signal_emit (object, signals[DESTROY], 0);
01462
01463 G_OBJECT_CLASS (parent_class)->dispose (object);
01464 }
01465
01466 static void
01467 dbus_g_proxy_finalize (GObject *object)
01468 {
01469 DBusGProxy *proxy = DBUS_G_PROXY (object);
01470 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01471
01472 g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy));
01473
01474 g_free (priv->name);
01475 g_free (priv->path);
01476 g_free (priv->interface);
01477
01478 G_OBJECT_CLASS (parent_class)->finalize (object);
01479 }
01480
01481 static void
01482 dbus_g_proxy_destroy (DBusGProxy *proxy)
01483 {
01484
01485
01486
01487 g_object_run_dispose (G_OBJECT (proxy));
01488 }
01489
01490 static void
01491 dbus_g_proxy_set_property (GObject *object,
01492 guint prop_id,
01493 const GValue *value,
01494 GParamSpec *pspec)
01495 {
01496 DBusGProxy *proxy = DBUS_G_PROXY (object);
01497 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01498 DBusGConnection *connection;
01499
01500 switch (prop_id)
01501 {
01502 case PROP_NAME:
01503 priv->name = g_strdup (g_value_get_string (value));
01504 priv->for_owner = (priv->name[0] == ':');
01505 break;
01506 case PROP_PATH:
01507 priv->path = g_strdup (g_value_get_string (value));
01508 break;
01509 case PROP_INTERFACE:
01510 priv->interface = g_strdup (g_value_get_string (value));
01511 break;
01512 case PROP_CONNECTION:
01513 connection = g_value_get_boxed (value);
01514 if (connection != NULL)
01515 {
01516 priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
01517 }
01518 break;
01519 default:
01520 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01521 break;
01522 }
01523 }
01524
01525 static void
01526 dbus_g_proxy_get_property (GObject *object,
01527 guint prop_id,
01528 GValue *value,
01529 GParamSpec *pspec)
01530 {
01531 DBusGProxy *proxy = DBUS_G_PROXY (object);
01532 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01533
01534 switch (prop_id)
01535 {
01536 case PROP_NAME:
01537 g_value_set_string (value, priv->name);
01538 break;
01539 case PROP_PATH:
01540 g_value_set_string (value, priv->path);
01541 break;
01542 case PROP_INTERFACE:
01543 g_value_set_string (value, priv->interface);
01544 break;
01545 case PROP_CONNECTION:
01546 g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection));
01547 break;
01548 default:
01549 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01550 break;
01551 }
01552 }
01553
01554
01555
01556
01557
01558
01559 static char*
01560 create_signal_name (const char *interface,
01561 const char *signal)
01562 {
01563 GString *str;
01564 char *p;
01565
01566 str = g_string_new (interface);
01567
01568 g_string_append (str, "-");
01569
01570 g_string_append (str, signal);
01571
01572
01573 p = str->str;
01574 while (*p)
01575 {
01576 if (*p == '.')
01577 *p = '-';
01578 ++p;
01579 }
01580
01581 return g_string_free (str, FALSE);
01582 }
01583
01584 static void
01585 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01586 GValue *return_value,
01587 guint n_param_values,
01588 const GValue *param_values,
01589 gpointer invocation_hint,
01590 gpointer marshal_data)
01591 {
01592
01593
01594
01595
01596
01597 #define MAX_SIGNATURE_ARGS 20
01598 GValueArray *value_array;
01599 GSignalCMarshaller c_marshaller;
01600 DBusGProxy *proxy;
01601 DBusMessage *message;
01602 GArray *gsignature;
01603 const GType *types;
01604 DBusGProxyPrivate *priv;
01605
01606 g_assert (n_param_values == 3);
01607
01608 proxy = g_value_get_object (¶m_values[0]);
01609 message = g_value_get_boxed (¶m_values[1]);
01610 gsignature = g_value_get_pointer (¶m_values[2]);
01611
01612 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
01613 g_return_if_fail (message != NULL);
01614 g_return_if_fail (gsignature != NULL);
01615
01616 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01617
01618 c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len,
01619 (GType*) gsignature->data);
01620
01621 g_return_if_fail (c_marshaller != NULL);
01622
01623 {
01624 DBusGValueMarshalCtx context;
01625 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
01626 context.proxy = proxy;
01627
01628 types = (const GType*) gsignature->data;
01629 value_array = _dbus_gvalue_demarshal_message (&context, message,
01630 gsignature->len, types, NULL);
01631 }
01632
01633 if (value_array == NULL)
01634 return;
01635
01636 g_value_array_prepend (value_array, NULL);
01637 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy));
01638 g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy);
01639
01640 (* c_marshaller) (closure, return_value, value_array->n_values,
01641 value_array->values, invocation_hint, marshal_data);
01642
01643 g_value_array_free (value_array);
01644 }
01645
01646 static void
01647 dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
01648 DBusMessage *message)
01649 {
01650 const char *interface;
01651 const char *signal;
01652 char *name;
01653 GQuark q;
01654 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01655 GArray *msg_gsignature = NULL;
01656
01657 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
01658
01659 interface = dbus_message_get_interface (message);
01660 signal = dbus_message_get_member (message);
01661
01662 g_assert (interface != NULL);
01663 g_assert (signal != NULL);
01664
01665 name = create_signal_name (interface, signal);
01666
01667
01668
01669
01670
01671 q = g_quark_try_string (name);
01672
01673 if (q != 0)
01674 {
01675 GArray *gsignature;
01676 guint i;
01677
01678 gsignature = g_datalist_id_get_data (&priv->signal_signatures, q);
01679 if (gsignature == NULL)
01680 goto out;
01681
01682 msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message),
01683 TRUE);
01684 for (i = 0; i < gsignature->len; i++)
01685 {
01686 if (msg_gsignature->len == i
01687 || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i))
01688 goto mismatch;
01689 }
01690 if (msg_gsignature->len != i)
01691 goto mismatch;
01692
01693 g_signal_emit (proxy,
01694 signals[RECEIVED],
01695 q,
01696 message,
01697 msg_gsignature);
01698 }
01699
01700 out:
01701 g_free (name);
01702 if (msg_gsignature)
01703 g_array_free (msg_gsignature, TRUE);
01704 return;
01705 mismatch:
01706 #if 0
01707
01708 g_warning ("Unexpected message signature '%s' for signal '%s'\n",
01709 dbus_message_get_signature (message),
01710 name);
01711 #endif
01712 goto out;
01713 }
01714
01715 typedef struct
01716 {
01717 DBusGProxy *proxy;
01718 guint call_id;
01719 DBusGProxyCallNotify func;
01720 void *data;
01721 GDestroyNotify free_data_func;
01722 } GPendingNotifyClosure;
01723
01724 static void
01725 d_pending_call_notify (DBusPendingCall *dcall,
01726 void *data)
01727 {
01728 GPendingNotifyClosure *closure = data;
01729
01730 (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
01731 }
01732
01733 static void
01734 d_pending_call_free (void *data)
01735 {
01736 GPendingNotifyClosure *closure = data;
01737
01738 if (closure->free_data_func)
01739 (* closure->free_data_func) (closure->data);
01740
01741 g_free (closure);
01742 }
01743
01744 #define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
01745 do { \
01746 GType valtype; \
01747 int i = 0; \
01748 VALARRAY = g_value_array_new (6); \
01749 valtype = FIRST_ARG_TYPE; \
01750 while (valtype != G_TYPE_INVALID) \
01751 { \
01752 const char *collect_err; \
01753 GValue *val; \
01754 g_value_array_append (VALARRAY, NULL); \
01755 val = g_value_array_get_nth (VALARRAY, i); \
01756 g_value_init (val, valtype); \
01757 collect_err = NULL; \
01758 G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
01759 valtype = va_arg (ARGS, GType); \
01760 i++; \
01761 } \
01762 } while (0)
01763
01764 DBusGProxyCall *
01765 manager_begin_bus_call (DBusGProxyManager *manager,
01766 const char *method,
01767 DBusGProxyCallNotify notify,
01768 gpointer user_data,
01769 GDestroyNotify destroy,
01770 GType first_arg_type,
01771 ...)
01772 {
01773 DBusGProxyCall *call;
01774 DBusGProxyPrivate *priv;
01775 va_list args;
01776 GValueArray *arg_values;
01777
01778 va_start (args, first_arg_type);
01779
01780 if (!manager->bus_proxy)
01781 {
01782 manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
01783 "name", DBUS_SERVICE_DBUS,
01784 "path", DBUS_PATH_DBUS,
01785 "interface", DBUS_INTERFACE_DBUS,
01786 NULL);
01787 priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy);
01788 priv->manager = manager;
01789 }
01790
01791 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
01792
01793 call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values));
01794
01795 g_value_array_free (arg_values);
01796
01797 va_end (args);
01798
01799 return call;
01800 }
01801
01823 GType
01824 dbus_g_proxy_get_type (void)
01825 {
01826 static GType object_type = 0;
01827
01828 if (!object_type)
01829 {
01830 static const GTypeInfo object_info =
01831 {
01832 sizeof (DBusGProxyClass),
01833 (GBaseInitFunc) NULL,
01834 (GBaseFinalizeFunc) NULL,
01835 (GClassInitFunc) dbus_g_proxy_class_init,
01836 NULL,
01837 NULL,
01838 sizeof (DBusGProxy),
01839 0,
01840 (GInstanceInitFunc) dbus_g_proxy_init,
01841 };
01842
01843 object_type = g_type_register_static (G_TYPE_OBJECT,
01844 "DBusGProxy",
01845 &object_info, 0);
01846 }
01847
01848 return object_type;
01849 }
01850
01851 static DBusGProxy*
01852 dbus_g_proxy_new (DBusGConnection *connection,
01853 const char *name,
01854 const char *path_name,
01855 const char *interface_name)
01856 {
01857 DBusGProxy *proxy;
01858
01859 g_assert (connection != NULL);
01860
01861 proxy = g_object_new (DBUS_TYPE_G_PROXY,
01862 "name", name,
01863 "path", path_name,
01864 "interface", interface_name,
01865 "connection", connection, NULL);
01866
01867 return proxy;
01868 }
01869
01898 DBusGProxy*
01899 dbus_g_proxy_new_for_name (DBusGConnection *connection,
01900 const char *name,
01901 const char *path_name,
01902 const char *interface_name)
01903 {
01904 g_return_val_if_fail (connection != NULL, NULL);
01905 g_return_val_if_fail (name != NULL, NULL);
01906 g_return_val_if_fail (path_name != NULL, NULL);
01907 g_return_val_if_fail (interface_name != NULL, NULL);
01908
01909 return dbus_g_proxy_new (connection, name,
01910 path_name, interface_name);
01911 }
01912
01938 DBusGProxy*
01939 dbus_g_proxy_new_for_name_owner (DBusGConnection *connection,
01940 const char *name,
01941 const char *path_name,
01942 const char *interface_name,
01943 GError **error)
01944 {
01945 DBusGProxy *proxy;
01946 char *unique_name;
01947
01948 g_return_val_if_fail (connection != NULL, NULL);
01949 g_return_val_if_fail (name != NULL, NULL);
01950 g_return_val_if_fail (path_name != NULL, NULL);
01951 g_return_val_if_fail (interface_name != NULL, NULL);
01952
01953 if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error)))
01954 return NULL;
01955
01956 proxy = dbus_g_proxy_new (connection, unique_name,
01957 path_name, interface_name);
01958 g_free (unique_name);
01959 return proxy;
01960 }
01961
01973 DBusGProxy*
01974 dbus_g_proxy_new_from_proxy (DBusGProxy *proxy,
01975 const char *interface,
01976 const char *path)
01977 {
01978 DBusGProxyPrivate *priv;
01979
01980 g_return_val_if_fail (proxy != NULL, NULL);
01981
01982 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01983
01984 if (interface == NULL)
01985 interface = priv->interface;
01986 if (path == NULL)
01987 path = priv->path;
01988
01989 return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection),
01990 priv->name,
01991 path, interface);
01992 }
01993
02008 DBusGProxy*
02009 dbus_g_proxy_new_for_peer (DBusGConnection *connection,
02010 const char *path_name,
02011 const char *interface_name)
02012 {
02013 DBusGProxy *proxy;
02014
02015 g_return_val_if_fail (connection != NULL, NULL);
02016 g_return_val_if_fail (path_name != NULL, NULL);
02017 g_return_val_if_fail (interface_name != NULL, NULL);
02018
02019 proxy = dbus_g_proxy_new (connection, NULL,
02020 path_name, interface_name);
02021
02022 return proxy;
02023 }
02024
02038 const char*
02039 dbus_g_proxy_get_bus_name (DBusGProxy *proxy)
02040 {
02041 DBusGProxyPrivate *priv;
02042
02043 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02044 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02045
02046 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02047
02048 return priv->name;
02049 }
02050
02059 const char*
02060 dbus_g_proxy_get_interface (DBusGProxy *proxy)
02061 {
02062 DBusGProxyPrivate *priv;
02063
02064 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02065 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02066
02067 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02068
02069 return priv->interface;
02070 }
02071
02079 void
02080 dbus_g_proxy_set_interface (DBusGProxy *proxy,
02081 const char *interface_name)
02082 {
02083 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02084
02085
02086
02087 dbus_g_proxy_manager_unregister (priv->manager, proxy);
02088 g_free (priv->interface);
02089 priv->interface = g_strdup (interface_name);
02090 dbus_g_proxy_manager_register (priv->manager, proxy);
02091 }
02092
02100 const char*
02101 dbus_g_proxy_get_path (DBusGProxy *proxy)
02102 {
02103 DBusGProxyPrivate *priv;
02104
02105 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02106 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02107
02108 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02109
02110 return priv->path;
02111 }
02112
02113 static DBusMessage *
02114 dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy,
02115 const char *method,
02116 GValueArray *args)
02117 {
02118 DBusMessage *message;
02119 DBusMessageIter msgiter;
02120 guint i;
02121 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02122
02123 message = dbus_message_new_method_call (priv->name,
02124 priv->path,
02125 priv->interface,
02126 method);
02127 if (message == NULL)
02128 goto oom;
02129
02130 dbus_message_iter_init_append (message, &msgiter);
02131 for (i = 0; i < args->n_values; i++)
02132 {
02133 GValue *gvalue;
02134
02135 gvalue = g_value_array_get_nth (args, i);
02136
02137 if (!_dbus_gvalue_marshal (&msgiter, gvalue))
02138 g_assert_not_reached ();
02139 }
02140 return message;
02141 oom:
02142 return NULL;
02143 }
02144
02145 static guint
02146 dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
02147 const char *method,
02148 DBusGProxyCallNotify notify,
02149 gpointer user_data,
02150 GDestroyNotify destroy,
02151 GValueArray *args)
02152 {
02153 DBusMessage *message;
02154 DBusPendingCall *pending;
02155 GPendingNotifyClosure *closure;
02156 guint call_id;
02157 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02158
02159 pending = NULL;
02160
02161 message = dbus_g_proxy_marshal_args_to_message (proxy, method, args);
02162 if (!message)
02163 goto oom;
02164
02165 if (!dbus_connection_send_with_reply (priv->manager->connection,
02166 message,
02167 &pending,
02168 -1))
02169 goto oom;
02170 dbus_message_unref (message);
02171 g_assert (pending != NULL);
02172
02173 call_id = ++priv->call_id_counter;
02174
02175 if (notify != NULL)
02176 {
02177 closure = g_new (GPendingNotifyClosure, 1);
02178 closure->proxy = proxy;
02179 closure->call_id = call_id;
02180 closure->func = notify;
02181 closure->data = user_data;
02182 closure->free_data_func = destroy;
02183 dbus_pending_call_set_notify (pending, d_pending_call_notify,
02184 closure,
02185 d_pending_call_free);
02186 }
02187
02188 g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending);
02189
02190 return call_id;
02191 oom:
02192 g_error ("Out of memory");
02193 return 0;
02194 }
02195
02196 static gboolean
02197 dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
02198 guint call_id,
02199 GError **error,
02200 GType first_arg_type,
02201 va_list args)
02202 {
02203 DBusMessage *reply;
02204 DBusMessageIter msgiter;
02205 DBusError derror;
02206 va_list args_unwind;
02207 guint over;
02208 int n_retvals_processed;
02209 gboolean ret;
02210 GType valtype;
02211 DBusPendingCall *pending;
02212 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02213
02214 reply = NULL;
02215 ret = FALSE;
02216 n_retvals_processed = 0;
02217 over = 0;
02218
02219 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02220
02221 dbus_pending_call_block (pending);
02222 reply = dbus_pending_call_steal_reply (pending);
02223
02224 g_assert (reply != NULL);
02225
02226 dbus_error_init (&derror);
02227
02228 switch (dbus_message_get_type (reply))
02229 {
02230 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
02231
02232 dbus_message_iter_init (reply, &msgiter);
02233 valtype = first_arg_type;
02234 while (valtype != G_TYPE_INVALID)
02235 {
02236 int arg_type;
02237 gpointer return_storage;
02238 GValue gvalue = { 0, };
02239 DBusGValueMarshalCtx context;
02240
02241 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
02242 context.proxy = proxy;
02243
02244 arg_type = dbus_message_iter_get_arg_type (&msgiter);
02245 if (arg_type == DBUS_TYPE_INVALID)
02246 {
02247 g_set_error (error, DBUS_GERROR,
02248 DBUS_GERROR_INVALID_ARGS,
02249 _("Too few arguments in reply"));
02250 goto out;
02251 }
02252
02253 return_storage = va_arg (args, gpointer);
02254 if (return_storage == NULL)
02255 goto next;
02256
02257
02258
02259
02260 if (arg_type == DBUS_TYPE_VARIANT
02261 && g_type_is_a (valtype, G_TYPE_VALUE))
02262 {
02263 if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL))
02264 {
02265 g_set_error (error,
02266 DBUS_GERROR,
02267 DBUS_GERROR_INVALID_ARGS,
02268 _("Couldn't convert argument, expected \"%s\""),
02269 g_type_name (valtype));
02270 goto out;
02271 }
02272 }
02273 else
02274 {
02275 g_value_init (&gvalue, valtype);
02276
02277 if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error))
02278 goto out;
02279
02280
02281 if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage))
02282 g_assert_not_reached ();
02283
02284 }
02285
02286 next:
02287 n_retvals_processed++;
02288 dbus_message_iter_next (&msgiter);
02289 valtype = va_arg (args, GType);
02290 }
02291
02292 while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID)
02293 {
02294 over++;
02295 dbus_message_iter_next (&msgiter);
02296 }
02297
02298 if (over > 0)
02299 {
02300 g_set_error (error, DBUS_GERROR,
02301 DBUS_GERROR_INVALID_ARGS,
02302 _("Too many arguments in reply; expected %d, got %d"),
02303 n_retvals_processed, over);
02304 goto out;
02305 }
02306 break;
02307 case DBUS_MESSAGE_TYPE_ERROR:
02308 dbus_set_error_from_message (&derror, reply);
02309 dbus_set_g_error (error, &derror);
02310 dbus_error_free (&derror);
02311 goto out;
02312 break;
02313 default:
02314 dbus_set_error (&derror, DBUS_ERROR_FAILED,
02315 "Reply was neither a method return nor an exception");
02316 dbus_set_g_error (error, &derror);
02317 dbus_error_free (&derror);
02318 goto out;
02319 break;
02320 }
02321
02322 ret = TRUE;
02323 out:
02324 va_end (args);
02325
02326 if (ret == FALSE)
02327 {
02328 int i;
02329 for (i = 0; i < n_retvals_processed; i++)
02330 {
02331 gpointer retval;
02332
02333 retval = va_arg (args_unwind, gpointer);
02334
02335 g_free (retval);
02336 }
02337 }
02338 va_end (args_unwind);
02339
02340 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02341
02342 if (reply)
02343 dbus_message_unref (reply);
02344 return ret;
02345 }
02346
02369 DBusGProxyCall *
02370 dbus_g_proxy_begin_call (DBusGProxy *proxy,
02371 const char *method,
02372 DBusGProxyCallNotify notify,
02373 gpointer user_data,
02374 GDestroyNotify destroy,
02375 GType first_arg_type,
02376 ...)
02377 {
02378 guint call_id;
02379 va_list args;
02380 GValueArray *arg_values;
02381
02382 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02383 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02384
02385 va_start (args, first_arg_type);
02386
02387 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02388
02389 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values);
02390
02391 g_value_array_free (arg_values);
02392
02393 va_end (args);
02394
02395 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02396 }
02397
02420 gboolean
02421 dbus_g_proxy_end_call (DBusGProxy *proxy,
02422 DBusGProxyCall *call,
02423 GError **error,
02424 GType first_arg_type,
02425 ...)
02426 {
02427 gboolean ret;
02428 va_list args;
02429
02430 va_start (args, first_arg_type);
02431
02432 ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
02433
02434 va_end (args);
02435
02436 return ret;
02437 }
02438
02455 gboolean
02456 dbus_g_proxy_call (DBusGProxy *proxy,
02457 const char *method,
02458 GError **error,
02459 GType first_arg_type,
02460 ...)
02461 {
02462 gboolean ret;
02463 guint call_id;
02464 va_list args;
02465 GValueArray *in_args;
02466
02467 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02468 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02469
02470 va_start (args, first_arg_type);
02471
02472 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02473
02474 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args);
02475
02476 g_value_array_free (in_args);
02477
02478 first_arg_type = va_arg (args, GType);
02479 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02480
02481 va_end (args);
02482
02483 return ret;
02484 }
02485
02498 void
02499 dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
02500 const char *method,
02501 GType first_arg_type,
02502 ...)
02503 {
02504 DBusMessage *message;
02505 va_list args;
02506 GValueArray *in_args;
02507 DBusGProxyPrivate *priv;
02508
02509 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02510 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02511
02512 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02513
02514 va_start (args, first_arg_type);
02515 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02516
02517 message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args);
02518
02519 g_value_array_free (in_args);
02520 va_end (args);
02521
02522 if (!message)
02523 goto oom;
02524
02525 dbus_message_set_no_reply (message, TRUE);
02526
02527 if (!dbus_connection_send (priv->manager->connection,
02528 message,
02529 NULL))
02530 goto oom;
02531 dbus_message_unref (message);
02532 return;
02533
02534 oom:
02535 g_error ("Out of memory");
02536 }
02537
02548 void
02549 dbus_g_proxy_cancel_call (DBusGProxy *proxy,
02550 DBusGProxyCall *call)
02551 {
02552 guint call_id;
02553 DBusPendingCall *pending;
02554 DBusGProxyPrivate *priv;
02555
02556 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02557 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02558
02559 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02560
02561 call_id = DBUS_G_PROXY_CALL_TO_ID (call);
02562
02563 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02564 g_return_if_fail (pending != NULL);
02565
02566 dbus_pending_call_cancel (pending);
02567
02568 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02569 }
02570
02591 void
02592 dbus_g_proxy_send (DBusGProxy *proxy,
02593 DBusMessage *message,
02594 dbus_uint32_t *client_serial)
02595 {
02596 DBusGProxyPrivate *priv;
02597
02598 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02599 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02600
02601 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02602
02603 if (priv->name)
02604 {
02605 if (!dbus_message_set_destination (message, priv->name))
02606 g_error ("Out of memory");
02607 }
02608 if (priv->path)
02609 {
02610 if (!dbus_message_set_path (message, priv->path))
02611 g_error ("Out of memory");
02612 }
02613 if (priv->interface)
02614 {
02615 if (!dbus_message_set_interface (message, priv->interface))
02616 g_error ("Out of memory");
02617 }
02618
02619 if (!dbus_connection_send (priv->manager->connection, message, client_serial))
02620 g_error ("Out of memory\n");
02621 }
02622
02623 static void
02624 array_free_all (gpointer array)
02625 {
02626 g_array_free (array, TRUE);
02627 }
02628
02639 void
02640 dbus_g_proxy_add_signal (DBusGProxy *proxy,
02641 const char *signal_name,
02642 GType first_type,
02643 ...)
02644 {
02645 GQuark q;
02646 char *name;
02647 GArray *gtypesig;
02648 GType gtype;
02649 va_list args;
02650 DBusGProxyPrivate *priv;
02651
02652 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02653 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02654 g_return_if_fail (signal_name != NULL);
02655
02656 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02657
02658 name = create_signal_name (priv->interface, signal_name);
02659
02660 q = g_quark_from_string (name);
02661
02662 g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL);
02663
02664 gtypesig = g_array_new (FALSE, TRUE, sizeof (GType));
02665
02666 va_start (args, first_type);
02667 gtype = first_type;
02668 while (gtype != G_TYPE_INVALID)
02669 {
02670 g_array_append_val (gtypesig, gtype);
02671 gtype = va_arg (args, GType);
02672 }
02673 va_end (args);
02674
02675 #ifndef G_DISABLE_CHECKS
02676 if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL)
02677 g_warning ("No marshaller for signature of signal '%s'", signal_name);
02678 #endif
02679
02680
02681 g_datalist_id_set_data_full (&priv->signal_signatures,
02682 q, gtypesig,
02683 array_free_all);
02684
02685 g_free (name);
02686 }
02687
02700 void
02701 dbus_g_proxy_connect_signal (DBusGProxy *proxy,
02702 const char *signal_name,
02703 GCallback handler,
02704 void *data,
02705 GClosureNotify free_data_func)
02706 {
02707 char *name;
02708 GClosure *closure;
02709 GQuark q;
02710 DBusGProxyPrivate *priv;
02711
02712 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02713 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02714 g_return_if_fail (signal_name != NULL);
02715 g_return_if_fail (handler != NULL);
02716
02717 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02718 name = create_signal_name (priv->interface, signal_name);
02719
02720 q = g_quark_try_string (name);
02721
02722 #ifndef G_DISABLE_CHECKS
02723 if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL)
02724 {
02725 g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name);
02726 g_free (name);
02727 return;
02728 }
02729 #endif
02730
02731 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
02732
02733 g_signal_connect_closure_by_id (G_OBJECT (proxy),
02734 signals[RECEIVED],
02735 q,
02736 closure, FALSE);
02737
02738 g_free (name);
02739 }
02740
02751 void
02752 dbus_g_proxy_disconnect_signal (DBusGProxy *proxy,
02753 const char *signal_name,
02754 GCallback handler,
02755 void *data)
02756 {
02757 char *name;
02758 GQuark q;
02759 DBusGProxyPrivate *priv;
02760
02761 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02762 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02763 g_return_if_fail (signal_name != NULL);
02764 g_return_if_fail (handler != NULL);
02765
02766 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02767 name = create_signal_name (priv->interface, signal_name);
02768
02769 q = g_quark_try_string (name);
02770
02771 if (q != 0)
02772 {
02773 g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
02774 G_SIGNAL_MATCH_DETAIL |
02775 G_SIGNAL_MATCH_FUNC |
02776 G_SIGNAL_MATCH_DATA,
02777 signals[RECEIVED],
02778 q,
02779 NULL,
02780 G_CALLBACK (handler), data);
02781 }
02782 else
02783 {
02784 g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
02785 name);
02786 }
02787
02788 g_free (name);
02789 }
02790
02793 #ifdef DBUS_BUILD_TESTS
02794
02800 gboolean
02801 _dbus_g_proxy_test (void)
02802 {
02803
02804
02805 return TRUE;
02806 }
02807
02808 #endif