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;
00077 int default_timeout;
00078 };
00079
00080 static void dbus_g_proxy_init (DBusGProxy *proxy);
00081 static void dbus_g_proxy_class_init (DBusGProxyClass *klass);
00082 static GObject *dbus_g_proxy_constructor (GType type,
00083 guint n_construct_properties,
00084 GObjectConstructParam *construct_properties);
00085 static void dbus_g_proxy_set_property (GObject *object,
00086 guint prop_id,
00087 const GValue *value,
00088 GParamSpec *pspec);
00089 static void dbus_g_proxy_get_property (GObject *object,
00090 guint prop_id,
00091 GValue *value,
00092 GParamSpec *pspec);
00093
00094 static void dbus_g_proxy_finalize (GObject *object);
00095 static void dbus_g_proxy_dispose (GObject *object);
00096 static void dbus_g_proxy_destroy (DBusGProxy *proxy);
00097 static void dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
00098 DBusMessage *message);
00099
00100 static DBusGProxyCall *manager_begin_bus_call (DBusGProxyManager *manager,
00101 const char *method,
00102 DBusGProxyCallNotify notify,
00103 gpointer data,
00104 GDestroyNotify destroy,
00105 GType first_arg_type,
00106 ...);
00107 static guint dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
00108 const char *method,
00109 DBusGProxyCallNotify notify,
00110 gpointer data,
00111 GDestroyNotify destroy,
00112 GValueArray *args,
00113 int timeout );
00114 static gboolean dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
00115 guint call_id,
00116 GError **error,
00117 GType first_arg_type,
00118 va_list args);
00119
00124 typedef struct
00125 {
00126 GSList *proxies;
00132 GHashTable *signal_subscribed;
00133
00134 char name[4];
00139 } DBusGProxyList;
00140
00146 struct _DBusGProxyManager
00147 {
00148 GStaticMutex lock;
00149 int refcount;
00150 DBusConnection *connection;
00152 DBusGProxy *bus_proxy;
00154 GHashTable *proxy_lists;
00158 GHashTable *owner_match_rule;
00162 GHashTable *owner_names;
00167 GSList *unassociated_proxies;
00171 };
00172
00173 static DBusGProxyManager *dbus_g_proxy_manager_ref (DBusGProxyManager *manager);
00174 static DBusHandlerResult dbus_g_proxy_manager_filter (DBusConnection *connection,
00175 DBusMessage *message,
00176 void *user_data);
00177
00178
00180 #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock))
00181
00182 #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock))
00183
00184 static int g_proxy_manager_slot = -1;
00185
00186
00187 static GStaticMutex connection_g_proxy_lock = G_STATIC_MUTEX_INIT;
00188
00189 static DBusGProxyManager*
00190 dbus_g_proxy_manager_get (DBusConnection *connection)
00191 {
00192 DBusGProxyManager *manager;
00193
00194 dbus_connection_allocate_data_slot (&g_proxy_manager_slot);
00195 if (g_proxy_manager_slot < 0)
00196 g_error ("out of memory");
00197
00198 g_static_mutex_lock (&connection_g_proxy_lock);
00199
00200 manager = dbus_connection_get_data (connection, g_proxy_manager_slot);
00201 if (manager != NULL)
00202 {
00203 dbus_connection_free_data_slot (&g_proxy_manager_slot);
00204 dbus_g_proxy_manager_ref (manager);
00205 g_static_mutex_unlock (&connection_g_proxy_lock);
00206 return manager;
00207 }
00208
00209 manager = g_new0 (DBusGProxyManager, 1);
00210
00211 manager->refcount = 1;
00212 manager->connection = connection;
00213
00214 g_static_mutex_init (&manager->lock);
00215
00216
00217
00218
00219
00220 dbus_connection_ref (manager->connection);
00221
00222 dbus_connection_set_data (connection, g_proxy_manager_slot,
00223 manager, NULL);
00224
00225 dbus_connection_add_filter (connection, dbus_g_proxy_manager_filter,
00226 manager, NULL);
00227
00228 g_static_mutex_unlock (&connection_g_proxy_lock);
00229
00230 return manager;
00231 }
00232
00233 static DBusGProxyManager *
00234 dbus_g_proxy_manager_ref (DBusGProxyManager *manager)
00235 {
00236 g_assert (manager != NULL);
00237 g_assert (manager->refcount > 0);
00238
00239 LOCK_MANAGER (manager);
00240
00241 manager->refcount += 1;
00242
00243 UNLOCK_MANAGER (manager);
00244
00245 return manager;
00246 }
00247
00248 static void
00249 dbus_g_proxy_manager_unref (DBusGProxyManager *manager)
00250 {
00251 g_assert (manager != NULL);
00252 g_assert (manager->refcount > 0);
00253
00254 LOCK_MANAGER (manager);
00255 manager->refcount -= 1;
00256 if (manager->refcount == 0)
00257 {
00258 UNLOCK_MANAGER (manager);
00259
00260 if (manager->bus_proxy)
00261 g_object_unref (manager->bus_proxy);
00262
00263 if (manager->proxy_lists)
00264 {
00265
00266
00267
00268 g_assert (g_hash_table_size (manager->proxy_lists) == 0);
00269
00270 g_hash_table_destroy (manager->proxy_lists);
00271 manager->proxy_lists = NULL;
00272
00273 }
00274
00275 if (manager->owner_match_rule)
00276 {
00277
00278
00279
00280 g_assert (g_hash_table_size (manager->owner_match_rule) == 0);
00281 g_hash_table_destroy (manager->owner_match_rule);
00282 manager->owner_match_rule = NULL;
00283 }
00284
00285 if (manager->owner_names)
00286 {
00287
00288
00289
00290 g_assert (g_hash_table_size (manager->owner_names) == 0);
00291
00292 g_hash_table_destroy (manager->owner_names);
00293 manager->owner_names = NULL;
00294 }
00295
00296 g_assert (manager->unassociated_proxies == NULL);
00297
00298 g_static_mutex_free (&manager->lock);
00299
00300 g_static_mutex_lock (&connection_g_proxy_lock);
00301
00302 dbus_connection_remove_filter (manager->connection, dbus_g_proxy_manager_filter,
00303 manager);
00304
00305 dbus_connection_set_data (manager->connection,
00306 g_proxy_manager_slot,
00307 NULL, NULL);
00308
00309 g_static_mutex_unlock (&connection_g_proxy_lock);
00310
00311 dbus_connection_unref (manager->connection);
00312 g_free (manager);
00313
00314 dbus_connection_free_data_slot (&g_proxy_manager_slot);
00315 }
00316 else
00317 {
00318 UNLOCK_MANAGER (manager);
00319 }
00320 }
00321
00322 static guint
00323 tristring_hash (gconstpointer key)
00324 {
00325 const char *p = key;
00326 guint h = *p;
00327
00328 if (h)
00329 {
00330 for (p += 1; *p != '\0'; p++)
00331 h = (h << 5) - h + *p;
00332 }
00333
00334
00335 for (p += 1; *p != '\0'; p++)
00336 h = (h << 5) - h + *p;
00337
00338
00339 for (p += 1; *p != '\0'; p++)
00340 h = (h << 5) - h + *p;
00341
00342 return h;
00343 }
00344
00345 static gboolean
00346 strequal_len (const char *a,
00347 const char *b,
00348 size_t *lenp)
00349 {
00350 size_t a_len;
00351 size_t b_len;
00352
00353 a_len = strlen (a);
00354 b_len = strlen (b);
00355
00356 if (a_len != b_len)
00357 return FALSE;
00358
00359 if (memcmp (a, b, a_len) != 0)
00360 return FALSE;
00361
00362 *lenp = a_len;
00363
00364 return TRUE;
00365 }
00366
00367 static gboolean
00368 tristring_equal (gconstpointer a,
00369 gconstpointer b)
00370 {
00371 const char *ap = a;
00372 const char *bp = b;
00373 size_t len;
00374
00375 if (!strequal_len (ap, bp, &len))
00376 return FALSE;
00377
00378 ap += len + 1;
00379 bp += len + 1;
00380
00381 if (!strequal_len (ap, bp, &len))
00382 return FALSE;
00383
00384 ap += len + 1;
00385 bp += len + 1;
00386
00387 if (strcmp (ap, bp) != 0)
00388 return FALSE;
00389
00390 return TRUE;
00391 }
00392
00393 static char*
00394 tristring_alloc_from_strings (size_t padding_before,
00395 const char *name,
00396 const char *path,
00397 const char *interface)
00398 {
00399 size_t name_len, iface_len, path_len, len;
00400 char *tri;
00401
00402 if (name)
00403 name_len = strlen (name);
00404 else
00405 name_len = 0;
00406
00407 path_len = strlen (path);
00408
00409 iface_len = strlen (interface);
00410
00411 tri = g_malloc (padding_before + name_len + path_len + iface_len + 3);
00412
00413 len = padding_before;
00414
00415 if (name)
00416 memcpy (&tri[len], name, name_len);
00417
00418 len += name_len;
00419 tri[len] = '\0';
00420 len += 1;
00421
00422 g_assert (len == (padding_before + name_len + 1));
00423
00424 memcpy (&tri[len], path, path_len);
00425 len += path_len;
00426 tri[len] = '\0';
00427 len += 1;
00428
00429 g_assert (len == (padding_before + name_len + path_len + 2));
00430
00431 memcpy (&tri[len], interface, iface_len);
00432 len += iface_len;
00433 tri[len] = '\0';
00434 len += 1;
00435
00436 g_assert (len == (padding_before + name_len + path_len + iface_len + 3));
00437
00438 return tri;
00439 }
00440
00441 static char*
00442 tristring_from_proxy (DBusGProxy *proxy)
00443 {
00444 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00445
00446 return tristring_alloc_from_strings (0,
00447 priv->name,
00448 priv->path,
00449 priv->interface);
00450 }
00451
00452 static char*
00453 tristring_from_message (DBusMessage *message)
00454 {
00455 const char *path;
00456 const char *interface;
00457
00458 path = dbus_message_get_path (message);
00459 interface = dbus_message_get_interface (message);
00460
00461 g_assert (path);
00462 g_assert (interface);
00463
00464 return tristring_alloc_from_strings (0,
00465 dbus_message_get_sender (message),
00466 path, interface);
00467 }
00468
00469 static DBusGProxyList*
00470 g_proxy_list_new (DBusGProxy *first_proxy)
00471 {
00472 DBusGProxyList *list;
00473 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(first_proxy);
00474
00475 list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name),
00476 priv->name,
00477 priv->path,
00478 priv->interface);
00479 list->proxies = NULL;
00480 list->signal_subscribed = NULL;
00481
00482 return list;
00483 }
00484
00485 static void
00486 g_proxy_list_free (DBusGProxyList *list)
00487 {
00488
00489
00490
00491 g_slist_free (list->proxies);
00492 if (list->signal_subscribed != NULL)
00493 {
00494 g_hash_table_destroy (list->signal_subscribed);
00495 }
00496
00497 g_free (list);
00498 }
00499
00500 static char*
00501 g_proxy_get_signal_match_rule (DBusGProxy *proxy, const gchar *signal_name)
00502 {
00503 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00504
00505
00506 if (priv->name)
00507 {
00508 if (signal_name == NULL)
00509 return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'",
00510 priv->name, priv->path, priv->interface);
00511 else
00512 return g_strdup_printf ("type='signal',sender='%s',path='%s',"
00513 "interface='%s',member='%s'",
00514 priv->name, priv->path, priv->interface,
00515 signal_name);
00516 }
00517 else
00518 {
00519 if (signal_name == NULL)
00520 return g_strdup_printf ("type='signal',path='%s',interface='%s'",
00521 priv->path, priv->interface);
00522 else
00523 return g_strdup_printf ("type='signal',path='%s',interface='%s',"
00524 "member='%s'",
00525 priv->path, priv->interface, signal_name);
00526 }
00527 }
00528
00529 static char *
00530 g_proxy_get_owner_match_rule (const gchar *name)
00531 {
00532 return g_strdup_printf ("type='signal',sender='" DBUS_SERVICE_DBUS
00533 "',path='" DBUS_PATH_DBUS
00534 "',interface='" DBUS_INTERFACE_DBUS
00535 "',member='NameOwnerChanged'"
00536 ",arg0='%s'", name);
00537 }
00538
00539 typedef struct
00540 {
00541 char *name;
00542 guint refcount;
00543 } DBusGProxyNameOwnerInfo;
00544
00545 static gint
00546 find_name_in_info (gconstpointer a, gconstpointer b)
00547 {
00548 const DBusGProxyNameOwnerInfo *info = a;
00549 const char *name = b;
00550
00551 if (info == NULL || info->name == NULL)
00552 return 1;
00553 return strcmp (info->name, name);
00554 }
00555
00556 typedef struct
00557 {
00558 const char *name;
00559 const char *owner;
00560 DBusGProxyNameOwnerInfo *info;
00561 } DBusGProxyNameOwnerForeachData;
00562
00563 static void
00564 name_owner_foreach (gpointer key, gpointer val, gpointer data)
00565 {
00566 const char *owner;
00567 DBusGProxyNameOwnerForeachData *foreach_data;
00568 GSList *names;
00569 GSList *link;
00570
00571 owner = key;
00572 names = val;
00573 foreach_data = data;
00574
00575 if (foreach_data->owner != NULL)
00576 return;
00577
00578 g_assert (foreach_data->info == NULL);
00579
00580 link = g_slist_find_custom (names, foreach_data->name, find_name_in_info);
00581 if (link)
00582 {
00583 foreach_data->owner = owner;
00584 foreach_data->info = link->data;
00585 }
00586 }
00587
00588 static gboolean
00589 dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager *manager,
00590 const char *name,
00591 DBusGProxyNameOwnerInfo **info,
00592 const char **owner)
00593 {
00594 DBusGProxyNameOwnerForeachData foreach_data;
00595
00596 foreach_data.name = name;
00597 foreach_data.owner = NULL;
00598 foreach_data.info = NULL;
00599
00600 g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data);
00601
00602 *info = foreach_data.info;
00603 *owner = foreach_data.owner;
00604 return *info != NULL;
00605 }
00606
00607 static void
00608 insert_nameinfo (DBusGProxyManager *manager,
00609 const char *owner,
00610 DBusGProxyNameOwnerInfo *info)
00611 {
00612 GSList *names;
00613 gboolean insert;
00614
00615 names = g_hash_table_lookup (manager->owner_names, owner);
00616
00617
00618 insert = (names == NULL);
00619
00620 names = g_slist_append (names, info);
00621
00622 if (insert)
00623 g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
00624 }
00625
00626 static void
00627 dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager *manager,
00628 const char *owner,
00629 const char *name)
00630 {
00631 GSList *names;
00632 GSList *link;
00633 DBusGProxyNameOwnerInfo *nameinfo;
00634
00635 names = g_hash_table_lookup (manager->owner_names, owner);
00636 link = g_slist_find_custom (names, name, find_name_in_info);
00637
00638 if (!link)
00639 {
00640 nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1);
00641 nameinfo->name = g_strdup (name);
00642 nameinfo->refcount = 1;
00643
00644 insert_nameinfo (manager, owner, nameinfo);
00645 }
00646 else
00647 {
00648 nameinfo = link->data;
00649 nameinfo->refcount++;
00650 }
00651 }
00652
00653 static void
00654 dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager *manager,
00655 const char *name)
00656 {
00657 DBusGProxyNameOwnerInfo *info;
00658 const char *owner;
00659 gboolean ret;
00660
00661 ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner);
00662 g_assert (ret);
00663 g_assert (info != NULL);
00664 g_assert (owner != NULL);
00665
00666 info->refcount--;
00667 if (info->refcount == 0)
00668 {
00669 GSList *names;
00670 GSList *link;
00671
00672 names = g_hash_table_lookup (manager->owner_names, owner);
00673 link = g_slist_find_custom (names, name, find_name_in_info);
00674 names = g_slist_delete_link (names, link);
00675 if (names != NULL)
00676 g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
00677 else
00678 g_hash_table_remove (manager->owner_names, owner);
00679
00680 g_free (info->name);
00681 g_free (info);
00682 }
00683 }
00684
00685 typedef struct
00686 {
00687 const char *name;
00688 GSList *destroyed;
00689 } DBusGProxyUnassociateData;
00690
00691 static void
00692 unassociate_proxies (gpointer key, gpointer val, gpointer user_data)
00693 {
00694 DBusGProxyList *list;
00695 const char *name;
00696 GSList *tmp;
00697 DBusGProxyUnassociateData *data;
00698
00699 list = val;
00700 data = user_data;
00701 name = data->name;
00702
00703 for (tmp = list->proxies; tmp; tmp = tmp->next)
00704 {
00705 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
00706 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00707 DBusGProxyManager *manager;
00708
00709 manager = priv->manager;
00710
00711 if (!strcmp (priv->name, name))
00712 {
00713 if (!priv->for_owner)
00714 {
00715
00716
00717
00718
00719
00720 if (priv->name_call)
00721 dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
00722
00723 priv->name_call = NULL;
00724
00725 priv->associated = FALSE;
00726 manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy);
00727 }
00728 else
00729 {
00730 data->destroyed = g_slist_prepend (data->destroyed, proxy);
00731
00732
00733 g_object_add_weak_pointer (G_OBJECT (proxy),
00734 &(data->destroyed->data));
00735 }
00736 }
00737 }
00738 }
00739
00740 static void
00741 dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager *manager,
00742 const char *name,
00743 const char *prev_owner,
00744 const char *new_owner)
00745 {
00746 GSList *names;
00747
00748 if (prev_owner[0] == '\0')
00749 {
00750 GSList *tmp;
00751 GSList *removed;
00752
00753
00754
00755 removed = NULL;
00756
00757 for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next)
00758 {
00759 DBusGProxy *proxy = tmp->data;
00760 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00761
00762 if (!strcmp (priv->name, name))
00763 {
00764 removed = g_slist_prepend (removed, tmp);
00765
00766 dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name);
00767 priv->associated = TRUE;
00768 }
00769 }
00770
00771 for (tmp = removed; tmp; tmp = tmp->next)
00772 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data);
00773 g_slist_free (removed);
00774 }
00775 else
00776 {
00777 DBusGProxyNameOwnerInfo *info;
00778 GSList *link;
00779
00780
00781
00782 names = g_hash_table_lookup (manager->owner_names, prev_owner);
00783
00784 info = NULL;
00785 if (names != NULL)
00786 {
00787 link = g_slist_find_custom (names, name, find_name_in_info);
00788
00789 if (link != NULL)
00790 {
00791 info = link->data;
00792
00793 names = g_slist_delete_link (names, link);
00794
00795 if (names == NULL)
00796 {
00797 g_hash_table_remove (manager->owner_names, prev_owner);
00798 }
00799 else
00800 {
00801 g_hash_table_insert (manager->owner_names,
00802 g_strdup (prev_owner), names);
00803 }
00804 }
00805 }
00806
00807 if (new_owner[0] == '\0')
00808 {
00809 DBusGProxyUnassociateData data;
00810 GSList *tmp;
00811
00812 data.name = name;
00813 data.destroyed = NULL;
00814
00815
00816 g_hash_table_foreach (manager->proxy_lists,
00817 unassociate_proxies, &data);
00818
00819 UNLOCK_MANAGER (manager);
00820
00821
00822
00823
00824 for (tmp = data.destroyed; tmp; tmp = tmp->next)
00825 if (tmp->data != NULL)
00826 {
00827 g_object_remove_weak_pointer (G_OBJECT (tmp->data),
00828 &(tmp->data));
00829 dbus_g_proxy_destroy (tmp->data);
00830 }
00831 g_slist_free (data.destroyed);
00832
00833 LOCK_MANAGER (manager);
00834
00835 if (info)
00836 {
00837 g_free (info->name);
00838 g_free (info);
00839 }
00840 }
00841 else if (info)
00842 {
00843 insert_nameinfo (manager, new_owner, info);
00844 }
00845 }
00846 }
00847
00848 static void
00849 got_name_owner_cb (DBusGProxy *bus_proxy,
00850 DBusGProxyCall *call,
00851 void *user_data)
00852 {
00853 DBusGProxy *proxy = user_data;
00854 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00855 GError *error;
00856 char *owner;
00857
00858 error = NULL;
00859 owner = NULL;
00860
00861 LOCK_MANAGER (priv->manager);
00862
00863 if (!dbus_g_proxy_end_call (bus_proxy, call, &error,
00864 G_TYPE_STRING, &owner,
00865 G_TYPE_INVALID))
00866 {
00867 if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
00868 {
00869 priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy);
00870 }
00871 else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
00872 g_warning ("Couldn't get name owner (%s): %s",
00873 dbus_g_error_get_name (error),
00874 error->message);
00875 else
00876 g_warning ("Couldn't get name owner (code %d): %s",
00877 error->code, error->message);
00878 g_clear_error (&error);
00879 goto out;
00880 }
00881 else
00882 {
00883 dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name);
00884 priv->associated = TRUE;
00885 }
00886
00887 out:
00888 priv->name_call = NULL;
00889 UNLOCK_MANAGER (priv->manager);
00890 g_free (owner);
00891 }
00892
00893 static char *
00894 get_name_owner (DBusConnection *connection,
00895 const char *name,
00896 GError **error)
00897 {
00898 DBusError derror;
00899 DBusMessage *request, *reply;
00900 char *base_name;
00901
00902 dbus_error_init (&derror);
00903
00904 base_name = NULL;
00905 reply = NULL;
00906
00907 request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
00908 DBUS_PATH_DBUS,
00909 DBUS_INTERFACE_DBUS,
00910 "GetNameOwner");
00911 if (request == NULL)
00912 g_error ("Out of memory");
00913
00914 if (!dbus_message_append_args (request,
00915 DBUS_TYPE_STRING, &name,
00916 DBUS_TYPE_INVALID))
00917 g_error ("Out of memory");
00918
00919 reply =
00920 dbus_connection_send_with_reply_and_block (connection,
00921 request,
00922 2000, &derror);
00923 if (reply == NULL)
00924 goto error;
00925
00926 if (dbus_set_error_from_message (&derror, reply))
00927 goto error;
00928
00929 if (!dbus_message_get_args (reply, &derror,
00930 DBUS_TYPE_STRING, &base_name,
00931 DBUS_TYPE_INVALID))
00932 goto error;
00933
00934 base_name = g_strdup (base_name);
00935 goto out;
00936
00937 error:
00938 g_assert (dbus_error_is_set (&derror));
00939 dbus_set_g_error (error, &derror);
00940 dbus_error_free (&derror);
00941
00942 out:
00943 if (request)
00944 dbus_message_unref (request);
00945 if (reply)
00946 dbus_message_unref (reply);
00947
00948 return base_name;
00949 }
00950
00951
00952 static void
00953 dbus_g_proxy_manager_register (DBusGProxyManager *manager,
00954 DBusGProxy *proxy)
00955 {
00956 DBusGProxyList *list;
00957 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00958
00959 LOCK_MANAGER (manager);
00960
00961 if (manager->proxy_lists == NULL)
00962 {
00963 g_assert (manager->owner_names == NULL);
00964 g_assert (manager->owner_match_rule == NULL);
00965
00966 list = NULL;
00967 manager->proxy_lists = g_hash_table_new_full (tristring_hash,
00968 tristring_equal,
00969 NULL,
00970 (GFreeFunc) g_proxy_list_free);
00971 manager->owner_names = g_hash_table_new_full (g_str_hash,
00972 g_str_equal,
00973 g_free,
00974 NULL);
00975 manager->owner_match_rule = g_hash_table_new_full (g_str_hash,
00976 g_str_equal,
00977 g_free,
00978 NULL);
00979 }
00980 else
00981 {
00982 char *tri;
00983
00984 tri = tristring_from_proxy (proxy);
00985
00986 list = g_hash_table_lookup (manager->proxy_lists, tri);
00987
00988 g_free (tri);
00989 }
00990
00991 if (list == NULL)
00992 {
00993 list = g_proxy_list_new (proxy);
00994
00995 g_hash_table_replace (manager->proxy_lists,
00996 list->name, list);
00997 }
00998
00999 if (list->proxies == NULL && priv->name)
01000 {
01001 gpointer orig_key, value;
01002
01003 g_assert (list->signal_subscribed == NULL);
01004 list->signal_subscribed = g_hash_table_new_full (g_str_hash,
01005 g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy);
01006
01007 if (g_hash_table_lookup_extended (manager->owner_match_rule,
01008 priv->name, &orig_key, &value))
01009 {
01010
01011 gint count = GPOINTER_TO_INT (value) + 1;
01012 g_hash_table_steal (manager->owner_match_rule, orig_key);
01013 g_hash_table_insert (manager->owner_match_rule, orig_key,
01014 GINT_TO_POINTER (count));
01015 }
01016 else
01017 {
01018 char *rule;
01019 rule = g_proxy_get_owner_match_rule (priv->name);
01020 dbus_bus_add_match (manager->connection,
01021 rule, NULL);
01022 g_free (rule);
01023 g_hash_table_insert (manager->owner_match_rule, g_strdup (priv->name),
01024 GINT_TO_POINTER (1));
01025 }
01026
01027 }
01028
01029 g_assert (g_slist_find (list->proxies, proxy) == NULL);
01030
01031 list->proxies = g_slist_prepend (list->proxies, proxy);
01032
01033 if (!priv->for_owner)
01034 {
01035 const char *owner;
01036 DBusGProxyNameOwnerInfo *info;
01037
01038 if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner))
01039 {
01040 priv->name_call = manager_begin_bus_call (manager, "GetNameOwner",
01041 got_name_owner_cb,
01042 proxy, NULL,
01043 G_TYPE_STRING,
01044 priv->name,
01045 G_TYPE_INVALID);
01046
01047 priv->associated = FALSE;
01048 }
01049 else
01050 {
01051 info->refcount++;
01052 priv->associated = TRUE;
01053 }
01054 }
01055
01056 UNLOCK_MANAGER (manager);
01057 }
01058
01059 static void
01060 dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
01061 DBusGProxy *proxy)
01062 {
01063 DBusGProxyList *list;
01064 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01065 char *tri;
01066
01067 LOCK_MANAGER (manager);
01068
01069 #ifndef G_DISABLE_CHECKS
01070 if (manager->proxy_lists == NULL)
01071 {
01072 g_warning ("Trying to unregister a proxy but there aren't any registered");
01073 return;
01074 }
01075 #endif
01076
01077 tri = tristring_from_proxy (proxy);
01078
01079 list = g_hash_table_lookup (manager->proxy_lists, tri);
01080
01081 #ifndef G_DISABLE_CHECKS
01082 if (list == NULL)
01083 {
01084 g_warning ("Trying to unregister a proxy but it isn't registered");
01085 return;
01086 }
01087 #endif
01088
01089 g_assert (g_slist_find (list->proxies, proxy) != NULL);
01090
01091 list->proxies = g_slist_remove (list->proxies, proxy);
01092
01093 g_assert (g_slist_find (list->proxies, proxy) == NULL);
01094
01095 if (!priv->for_owner)
01096 {
01097 if (!priv->associated)
01098 {
01099 GSList *link;
01100
01101 if (priv->name_call != 0)
01102 {
01103 dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
01104 priv->name_call = 0;
01105 }
01106 else
01107 {
01108 link = g_slist_find (manager->unassociated_proxies, proxy);
01109 if (link != NULL)
01110 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link);
01111 else
01112 g_warning ("Proxy not in namecall nor on unassociated list - failed namecall?");
01113 }
01114 }
01115 else
01116 {
01117 g_assert (priv->name_call == 0);
01118
01119 dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name);
01120 }
01121 }
01122
01123 if (list->signal_subscribed != NULL)
01124 {
01125 GHashTableIter iter;
01126 gpointer proxy_set;
01127 gpointer signal_name;
01128
01129 g_hash_table_iter_init (&iter, list->signal_subscribed);
01130 while (g_hash_table_iter_next (&iter, &signal_name, &proxy_set))
01131 {
01132 g_hash_table_remove (proxy_set, proxy);
01133 if (g_hash_table_size (proxy_set) == 0)
01134 {
01135 char *rule;
01136
01137 rule = g_proxy_get_signal_match_rule (proxy, (gchar *) signal_name);
01138 dbus_bus_remove_match (priv->manager->connection,
01139 rule, NULL);
01140 g_free (rule);
01141 }
01142 }
01143 }
01144
01145 if (list->proxies == NULL)
01146 {
01147 gpointer orig_key, value;
01148
01149 g_hash_table_remove (manager->proxy_lists,
01150 tri);
01151 if (priv->name && g_hash_table_lookup_extended (
01152 manager->owner_match_rule, priv->name, &orig_key, &value))
01153 {
01154 gint count = GPOINTER_TO_INT (value) - 1;
01155 if (count == 0)
01156 {
01157 char *rule;
01158 rule = g_proxy_get_owner_match_rule (priv->name);
01159 dbus_bus_remove_match (manager->connection,
01160 rule, NULL);
01161 g_free (rule);
01162 g_hash_table_remove (manager->owner_match_rule, priv->name);
01163 }
01164 else
01165 {
01166 g_hash_table_steal (manager->owner_match_rule, orig_key);
01167 g_hash_table_insert (manager->owner_match_rule, orig_key,
01168 GINT_TO_POINTER (count));
01169 }
01170 }
01171 }
01172
01173 if (g_hash_table_size (manager->proxy_lists) == 0)
01174 {
01175 g_hash_table_destroy (manager->proxy_lists);
01176 manager->proxy_lists = NULL;
01177 }
01178
01179 if (g_hash_table_size (manager->owner_match_rule) == 0)
01180 {
01181 g_hash_table_destroy (manager->owner_match_rule);
01182 manager->owner_match_rule = NULL;
01183 }
01184
01185 g_free (tri);
01186
01187 UNLOCK_MANAGER (manager);
01188 }
01189
01190 static void
01191 list_proxies_foreach (gpointer key,
01192 gpointer value,
01193 gpointer user_data)
01194 {
01195 DBusGProxyList *list;
01196 GSList **ret;
01197 GSList *tmp;
01198
01199 list = value;
01200 ret = user_data;
01201
01202 tmp = list->proxies;
01203 while (tmp != NULL)
01204 {
01205 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
01206
01207 g_object_ref (proxy);
01208 *ret = g_slist_prepend (*ret, proxy);
01209
01210 tmp = tmp->next;
01211 }
01212 }
01213
01214 static GSList*
01215 dbus_g_proxy_manager_list_all (DBusGProxyManager *manager)
01216 {
01217 GSList *ret;
01218
01219 ret = NULL;
01220
01221 if (manager->proxy_lists)
01222 {
01223 g_hash_table_foreach (manager->proxy_lists,
01224 list_proxies_foreach,
01225 &ret);
01226 }
01227
01228 return ret;
01229 }
01230
01231 static DBusHandlerResult
01232 dbus_g_proxy_manager_filter (DBusConnection *connection,
01233 DBusMessage *message,
01234 void *user_data)
01235 {
01236 DBusGProxyManager *manager;
01237
01238 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
01239 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01240
01241 manager = user_data;
01242
01243 dbus_g_proxy_manager_ref (manager);
01244
01245 LOCK_MANAGER (manager);
01246
01247 if (dbus_message_is_signal (message,
01248 DBUS_INTERFACE_LOCAL,
01249 "Disconnected"))
01250 {
01251
01252
01253
01254 GSList *all;
01255 GSList *tmp;
01256
01257 all = dbus_g_proxy_manager_list_all (manager);
01258
01259 tmp = all;
01260 while (tmp != NULL)
01261 {
01262 DBusGProxy *proxy;
01263
01264 proxy = DBUS_G_PROXY (tmp->data);
01265
01266 UNLOCK_MANAGER (manager);
01267 dbus_g_proxy_destroy (proxy);
01268 g_object_unref (G_OBJECT (proxy));
01269 LOCK_MANAGER (manager);
01270
01271 tmp = tmp->next;
01272 }
01273
01274 g_slist_free (all);
01275
01276 #ifndef G_DISABLE_CHECKS
01277 if (manager->proxy_lists != NULL)
01278 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.");
01279 #endif
01280 }
01281 else
01282 {
01283 char *tri;
01284 GSList *full_list;
01285 GSList *owned_names;
01286 GSList *tmp;
01287 const char *sender;
01288
01289
01290 if (dbus_message_is_signal (message,
01291 DBUS_INTERFACE_DBUS,
01292 "NameOwnerChanged"))
01293 {
01294 const char *name;
01295 const char *prev_owner;
01296 const char *new_owner;
01297 DBusError derr;
01298
01299 dbus_error_init (&derr);
01300 if (!dbus_message_get_args (message,
01301 &derr,
01302 DBUS_TYPE_STRING,
01303 &name,
01304 DBUS_TYPE_STRING,
01305 &prev_owner,
01306 DBUS_TYPE_STRING,
01307 &new_owner,
01308 DBUS_TYPE_INVALID))
01309 {
01310
01311 dbus_error_free (&derr);
01312 }
01313 else if (manager->owner_names != NULL)
01314 {
01315 dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner);
01316 }
01317 }
01318
01319 sender = dbus_message_get_sender (message);
01320
01321
01322 g_assert (dbus_message_get_path (message) != NULL);
01323 g_assert (dbus_message_get_interface (message) != NULL);
01324 g_assert (dbus_message_get_member (message) != NULL);
01325
01326 tri = tristring_from_message (message);
01327
01328 if (manager->proxy_lists)
01329 {
01330 DBusGProxyList *owner_list;
01331 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01332 if (owner_list)
01333 full_list = g_slist_copy (owner_list->proxies);
01334 else
01335 full_list = NULL;
01336 }
01337 else
01338 full_list = NULL;
01339
01340 g_free (tri);
01341
01342 if (manager->owner_names && sender)
01343 {
01344 owned_names = g_hash_table_lookup (manager->owner_names, sender);
01345 for (tmp = owned_names; tmp; tmp = tmp->next)
01346 {
01347 DBusGProxyList *owner_list;
01348 DBusGProxyNameOwnerInfo *nameinfo;
01349
01350 nameinfo = tmp->data;
01351 g_assert (nameinfo->refcount > 0);
01352 tri = tristring_alloc_from_strings (0, nameinfo->name,
01353 dbus_message_get_path (message),
01354 dbus_message_get_interface (message));
01355
01356 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01357 if (owner_list != NULL)
01358 {
01359 GSList *elt;
01360
01361
01362 for (elt = owner_list->proxies; elt; elt = g_slist_next (elt))
01363 {
01364 if (!g_slist_find (full_list, elt->data))
01365 full_list = g_slist_append (full_list, elt->data);
01366 }
01367 }
01368 g_free (tri);
01369 }
01370 }
01371
01372 #if 0
01373 g_print ("proxy got %s,%s,%s = list %p\n",
01374 tri,
01375 tri + strlen (tri) + 1,
01376 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
01377 list);
01378 #endif
01379
01380
01381
01382 g_slist_foreach (full_list, (GFunc) g_object_ref, NULL);
01383
01384 for (tmp = full_list; tmp; tmp = tmp->next)
01385 {
01386 DBusGProxy *proxy;
01387
01388 proxy = DBUS_G_PROXY (tmp->data);
01389
01390 UNLOCK_MANAGER (manager);
01391 dbus_g_proxy_emit_remote_signal (proxy, message);
01392 g_object_unref (G_OBJECT (proxy));
01393 LOCK_MANAGER (manager);
01394 }
01395 g_slist_free (full_list);
01396 }
01397
01398 UNLOCK_MANAGER (manager);
01399 dbus_g_proxy_manager_unref (manager);
01400
01401
01402
01403
01404 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01405 }
01406
01407
01408
01409
01410 #define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL)
01411
01412 static void
01413 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01414 GValue *return_value,
01415 guint n_param_values,
01416 const GValue *param_values,
01417 gpointer invocation_hint,
01418 gpointer marshal_data);
01419 enum
01420 {
01421 PROP_0,
01422 PROP_NAME,
01423 PROP_PATH,
01424 PROP_INTERFACE,
01425 PROP_CONNECTION
01426 };
01427
01428 enum
01429 {
01430 DESTROY,
01431 RECEIVED,
01432 LAST_SIGNAL
01433 };
01434
01435 static void *parent_class;
01436 static guint signals[LAST_SIGNAL] = { 0 };
01437
01438 static void
01439 dbus_g_proxy_init (DBusGProxy *proxy)
01440 {
01441 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01442
01443 g_datalist_init (&priv->signal_signatures);
01444 priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
01445 (GDestroyNotify) dbus_pending_call_unref);
01446 priv->name_call = 0;
01447 priv->associated = FALSE;
01448 priv->default_timeout = -1;
01449 }
01450
01451 static GObject *
01452 dbus_g_proxy_constructor (GType type,
01453 guint n_construct_properties,
01454 GObjectConstructParam *construct_properties)
01455 {
01456 DBusGProxy *proxy;
01457 DBusGProxyClass *klass;
01458 GObjectClass *parent_class;
01459 DBusGProxyPrivate *priv;
01460
01461 klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
01462
01463 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
01464
01465 proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
01466 construct_properties));
01467
01468 priv = DBUS_G_PROXY_GET_PRIVATE (proxy);
01469
01470
01471
01472
01473
01474
01475 g_assert (priv->path != NULL);
01476 g_assert (priv->interface != NULL);
01477
01478 if (priv->manager != NULL)
01479 {
01480 dbus_g_proxy_manager_register (priv->manager, proxy);
01481 }
01482
01483 return G_OBJECT (proxy);
01484 }
01485
01486 static void
01487 dbus_g_proxy_class_init (DBusGProxyClass *klass)
01488 {
01489 GObjectClass *object_class = G_OBJECT_CLASS (klass);
01490
01491 parent_class = g_type_class_peek_parent (klass);
01492
01493 g_type_class_add_private (klass, sizeof (DBusGProxyPrivate));
01494
01495 object_class->set_property = dbus_g_proxy_set_property;
01496 object_class->get_property = dbus_g_proxy_get_property;
01497
01498 g_object_class_install_property (object_class,
01499 PROP_NAME,
01500 g_param_spec_string ("name",
01501 "name",
01502 "name",
01503 NULL,
01504 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01505
01506 g_object_class_install_property (object_class,
01507 PROP_PATH,
01508 g_param_spec_string ("path",
01509 "path",
01510 "path",
01511 NULL,
01512 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01513
01514 g_object_class_install_property (object_class,
01515 PROP_INTERFACE,
01516 g_param_spec_string ("interface",
01517 "interface",
01518 "interface",
01519 NULL,
01520 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01521
01522 g_object_class_install_property (object_class,
01523 PROP_CONNECTION,
01524 g_param_spec_boxed ("connection",
01525 "connection",
01526 "connection",
01527 DBUS_TYPE_G_CONNECTION,
01528 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01529
01530 object_class->finalize = dbus_g_proxy_finalize;
01531 object_class->dispose = dbus_g_proxy_dispose;
01532 object_class->constructor = dbus_g_proxy_constructor;
01533
01534 signals[DESTROY] =
01535 g_signal_new ("destroy",
01536 G_OBJECT_CLASS_TYPE (object_class),
01537 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
01538 0,
01539 NULL, NULL,
01540 g_cclosure_marshal_VOID__VOID,
01541 G_TYPE_NONE, 0);
01542
01543 signals[RECEIVED] =
01544 g_signal_new ("received",
01545 G_OBJECT_CLASS_TYPE (object_class),
01546 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
01547 0,
01548 NULL, NULL,
01549 marshal_dbus_message_to_g_marshaller,
01550 G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER);
01551 }
01552
01553 static gboolean
01554 cancel_pending_call (gpointer key, gpointer val, gpointer data)
01555 {
01556 DBusPendingCall *pending = val;
01557
01558 dbus_pending_call_cancel (pending);
01559
01560 return TRUE;
01561 }
01562
01563 static void
01564 dbus_g_proxy_dispose (GObject *object)
01565 {
01566 DBusGProxy *proxy = DBUS_G_PROXY (object);
01567 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01568
01569 if (priv->pending_calls == NULL)
01570 {
01571 return;
01572 }
01573
01574
01575 g_hash_table_foreach_remove (priv->pending_calls, cancel_pending_call, NULL);
01576 g_hash_table_destroy (priv->pending_calls);
01577 priv->pending_calls = NULL;
01578
01579 if (priv->manager && proxy != priv->manager->bus_proxy)
01580 {
01581 dbus_g_proxy_manager_unregister (priv->manager, proxy);
01582 dbus_g_proxy_manager_unref (priv->manager);
01583 }
01584 priv->manager = NULL;
01585
01586 g_datalist_clear (&priv->signal_signatures);
01587
01588 g_signal_emit (object, signals[DESTROY], 0);
01589
01590 G_OBJECT_CLASS (parent_class)->dispose (object);
01591 }
01592
01593 static void
01594 dbus_g_proxy_finalize (GObject *object)
01595 {
01596 DBusGProxy *proxy = DBUS_G_PROXY (object);
01597 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01598
01599 g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy));
01600
01601 g_free (priv->name);
01602 g_free (priv->path);
01603 g_free (priv->interface);
01604
01605 G_OBJECT_CLASS (parent_class)->finalize (object);
01606 }
01607
01608 static void
01609 dbus_g_proxy_destroy (DBusGProxy *proxy)
01610 {
01611
01612
01613
01614 g_object_run_dispose (G_OBJECT (proxy));
01615 }
01616
01617 static void
01618 dbus_g_proxy_set_property (GObject *object,
01619 guint prop_id,
01620 const GValue *value,
01621 GParamSpec *pspec)
01622 {
01623 DBusGProxy *proxy = DBUS_G_PROXY (object);
01624 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01625 DBusGConnection *connection;
01626
01627 switch (prop_id)
01628 {
01629 case PROP_NAME:
01630 priv->name = g_strdup (g_value_get_string (value));
01631 if (priv->name)
01632 priv->for_owner = (priv->name[0] == ':');
01633 else
01634 priv->for_owner = TRUE;
01635 break;
01636 case PROP_PATH:
01637 priv->path = g_strdup (g_value_get_string (value));
01638 break;
01639 case PROP_INTERFACE:
01640 priv->interface = g_strdup (g_value_get_string (value));
01641 break;
01642 case PROP_CONNECTION:
01643 connection = g_value_get_boxed (value);
01644 if (connection != NULL)
01645 {
01646 priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
01647 }
01648 break;
01649 default:
01650 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01651 break;
01652 }
01653 }
01654
01655 static void
01656 dbus_g_proxy_get_property (GObject *object,
01657 guint prop_id,
01658 GValue *value,
01659 GParamSpec *pspec)
01660 {
01661 DBusGProxy *proxy = DBUS_G_PROXY (object);
01662 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01663
01664 switch (prop_id)
01665 {
01666 case PROP_NAME:
01667 g_value_set_string (value, priv->name);
01668 break;
01669 case PROP_PATH:
01670 g_value_set_string (value, priv->path);
01671 break;
01672 case PROP_INTERFACE:
01673 g_value_set_string (value, priv->interface);
01674 break;
01675 case PROP_CONNECTION:
01676 g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection));
01677 break;
01678 default:
01679 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01680 break;
01681 }
01682 }
01683
01684
01685
01686
01687
01688
01689 static char*
01690 create_signal_name (const char *interface,
01691 const char *signal)
01692 {
01693 GString *str;
01694 char *p;
01695
01696 str = g_string_new (interface);
01697
01698 g_string_append (str, "-");
01699
01700 g_string_append (str, signal);
01701
01702
01703 p = str->str;
01704 while (*p)
01705 {
01706 if (*p == '.')
01707 *p = '-';
01708 ++p;
01709 }
01710
01711 return g_string_free (str, FALSE);
01712 }
01713
01714 static void
01715 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01716 GValue *return_value,
01717 guint n_param_values,
01718 const GValue *param_values,
01719 gpointer invocation_hint,
01720 gpointer marshal_data)
01721 {
01722
01723
01724
01725
01726
01727 #define MAX_SIGNATURE_ARGS 20
01728 GValueArray *value_array;
01729 GSignalCMarshaller c_marshaller;
01730 DBusGProxy *proxy;
01731 DBusMessage *message;
01732 GArray *gsignature;
01733 const GType *types;
01734 DBusGProxyPrivate *priv;
01735
01736 g_assert (n_param_values == 3);
01737
01738 proxy = g_value_get_object (¶m_values[0]);
01739 message = g_value_get_boxed (¶m_values[1]);
01740 gsignature = g_value_get_pointer (¶m_values[2]);
01741
01742 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
01743 g_return_if_fail (message != NULL);
01744 g_return_if_fail (gsignature != NULL);
01745
01746 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01747
01748 c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len,
01749 (GType*) gsignature->data);
01750
01751 g_return_if_fail (c_marshaller != NULL);
01752
01753 {
01754 DBusGValueMarshalCtx context;
01755 context.recursion_depth = 0;
01756 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
01757 context.proxy = proxy;
01758
01759 types = (const GType*) gsignature->data;
01760 value_array = _dbus_gvalue_demarshal_message (&context, message,
01761 gsignature->len, types, NULL);
01762 }
01763
01764 if (value_array == NULL)
01765 return;
01766
01767 g_value_array_prepend (value_array, NULL);
01768 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy));
01769 g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy);
01770
01771 (* c_marshaller) (closure, return_value, value_array->n_values,
01772 value_array->values, invocation_hint, marshal_data);
01773
01774 g_value_array_free (value_array);
01775 }
01776
01777 static void
01778 dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
01779 DBusMessage *message)
01780 {
01781 const char *interface;
01782 const char *signal;
01783 char *name;
01784 GQuark q;
01785 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01786 GArray *msg_gsignature = NULL;
01787
01788 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
01789
01790 interface = dbus_message_get_interface (message);
01791 signal = dbus_message_get_member (message);
01792
01793 g_assert (interface != NULL);
01794 g_assert (signal != NULL);
01795
01796 name = create_signal_name (interface, signal);
01797
01798
01799
01800
01801
01802 q = g_quark_try_string (name);
01803
01804 if (q != 0)
01805 {
01806 GArray *gsignature;
01807 guint i;
01808
01809 gsignature = g_datalist_id_get_data (&priv->signal_signatures, q);
01810 if (gsignature == NULL)
01811 goto out;
01812
01813 msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message),
01814 TRUE);
01815 for (i = 0; i < gsignature->len; i++)
01816 {
01817 if (msg_gsignature->len == i
01818 || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i))
01819 goto mismatch;
01820 }
01821 if (msg_gsignature->len != i)
01822 goto mismatch;
01823
01824 g_signal_emit (proxy,
01825 signals[RECEIVED],
01826 q,
01827 message,
01828 msg_gsignature);
01829 }
01830
01831 out:
01832 g_free (name);
01833 if (msg_gsignature)
01834 g_array_free (msg_gsignature, TRUE);
01835 return;
01836 mismatch:
01837 #if 0
01838
01839 g_warning ("Unexpected message signature '%s' for signal '%s'\n",
01840 dbus_message_get_signature (message),
01841 name);
01842 #endif
01843 goto out;
01844 }
01845
01846 typedef struct
01847 {
01848 DBusGProxy *proxy;
01849 guint call_id;
01850 DBusGProxyCallNotify func;
01851 void *data;
01852 GDestroyNotify free_data_func;
01853 } GPendingNotifyClosure;
01854
01855 static void
01856 d_pending_call_notify (DBusPendingCall *dcall,
01857 void *data)
01858 {
01859 GPendingNotifyClosure *closure = data;
01860
01861 (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
01862 }
01863
01864 static void
01865 d_pending_call_free (void *data)
01866 {
01867 GPendingNotifyClosure *closure = data;
01868
01869 if (closure->free_data_func)
01870 (* closure->free_data_func) (closure->data);
01871
01872 g_free (closure);
01873 }
01874
01875 #define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
01876 do { \
01877 GType valtype; \
01878 int i = 0; \
01879 VALARRAY = g_value_array_new (6); \
01880 valtype = FIRST_ARG_TYPE; \
01881 while (valtype != G_TYPE_INVALID) \
01882 { \
01883 const char *collect_err; \
01884 GValue *val; \
01885 g_value_array_append (VALARRAY, NULL); \
01886 val = g_value_array_get_nth (VALARRAY, i); \
01887 g_value_init (val, valtype); \
01888 collect_err = NULL; \
01889 G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
01890 valtype = va_arg (ARGS, GType); \
01891 i++; \
01892 } \
01893 } while (0)
01894
01895 DBusGProxyCall *
01896 manager_begin_bus_call (DBusGProxyManager *manager,
01897 const char *method,
01898 DBusGProxyCallNotify notify,
01899 gpointer user_data,
01900 GDestroyNotify destroy,
01901 GType first_arg_type,
01902 ...)
01903 {
01904 DBusGProxyCall *call;
01905 DBusGProxyPrivate *priv;
01906 va_list args;
01907 GValueArray *arg_values;
01908
01909 va_start (args, first_arg_type);
01910
01911 if (!manager->bus_proxy)
01912 {
01913 manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
01914 "name", DBUS_SERVICE_DBUS,
01915 "path", DBUS_PATH_DBUS,
01916 "interface", DBUS_INTERFACE_DBUS,
01917 NULL);
01918 priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy);
01919 priv->manager = manager;
01920 }
01921
01922 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
01923
01924 call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values,-1));
01925
01926 g_value_array_free (arg_values);
01927
01928 va_end (args);
01929
01930 return call;
01931 }
01932
01954 GType
01955 dbus_g_proxy_get_type (void)
01956 {
01957 static GType object_type = 0;
01958
01959 if (!object_type)
01960 {
01961 static const GTypeInfo object_info =
01962 {
01963 sizeof (DBusGProxyClass),
01964 (GBaseInitFunc) NULL,
01965 (GBaseFinalizeFunc) NULL,
01966 (GClassInitFunc) dbus_g_proxy_class_init,
01967 NULL,
01968 NULL,
01969 sizeof (DBusGProxy),
01970 0,
01971 (GInstanceInitFunc) dbus_g_proxy_init,
01972 };
01973
01974 object_type = g_type_register_static (G_TYPE_OBJECT,
01975 "DBusGProxy",
01976 &object_info, 0);
01977 }
01978
01979 return object_type;
01980 }
01981
01982 static DBusGProxy*
01983 dbus_g_proxy_new (DBusGConnection *connection,
01984 const char *name,
01985 const char *path_name,
01986 const char *interface_name)
01987 {
01988 DBusGProxy *proxy;
01989
01990 g_assert (connection != NULL);
01991
01992 proxy = g_object_new (DBUS_TYPE_G_PROXY,
01993 "name", name,
01994 "path", path_name,
01995 "interface", interface_name,
01996 "connection", connection, NULL);
01997
01998 return proxy;
01999 }
02000
02029 DBusGProxy*
02030 dbus_g_proxy_new_for_name (DBusGConnection *connection,
02031 const char *name,
02032 const char *path_name,
02033 const char *interface_name)
02034 {
02035 g_return_val_if_fail (connection != NULL, NULL);
02036 g_return_val_if_fail (name != NULL, NULL);
02037 g_return_val_if_fail (path_name != NULL, NULL);
02038 g_return_val_if_fail (interface_name != NULL, NULL);
02039
02040 return dbus_g_proxy_new (connection, name,
02041 path_name, interface_name);
02042 }
02043
02069 DBusGProxy*
02070 dbus_g_proxy_new_for_name_owner (DBusGConnection *connection,
02071 const char *name,
02072 const char *path_name,
02073 const char *interface_name,
02074 GError **error)
02075 {
02076 DBusGProxy *proxy;
02077 char *unique_name;
02078
02079 g_return_val_if_fail (connection != NULL, NULL);
02080 g_return_val_if_fail (name != NULL, NULL);
02081 g_return_val_if_fail (path_name != NULL, NULL);
02082 g_return_val_if_fail (interface_name != NULL, NULL);
02083
02084 if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error)))
02085 return NULL;
02086
02087 proxy = dbus_g_proxy_new (connection, unique_name,
02088 path_name, interface_name);
02089 g_free (unique_name);
02090 return proxy;
02091 }
02092
02104 DBusGProxy*
02105 dbus_g_proxy_new_from_proxy (DBusGProxy *proxy,
02106 const char *interface,
02107 const char *path)
02108 {
02109 DBusGProxyPrivate *priv;
02110
02111 g_return_val_if_fail (proxy != NULL, NULL);
02112
02113 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02114
02115 if (interface == NULL)
02116 interface = priv->interface;
02117 if (path == NULL)
02118 path = priv->path;
02119
02120 return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection),
02121 priv->name,
02122 path, interface);
02123 }
02124
02139 DBusGProxy*
02140 dbus_g_proxy_new_for_peer (DBusGConnection *connection,
02141 const char *path_name,
02142 const char *interface_name)
02143 {
02144 DBusGProxy *proxy;
02145
02146 g_return_val_if_fail (connection != NULL, NULL);
02147 g_return_val_if_fail (path_name != NULL, NULL);
02148 g_return_val_if_fail (interface_name != NULL, NULL);
02149
02150 proxy = dbus_g_proxy_new (connection, NULL,
02151 path_name, interface_name);
02152
02153 return proxy;
02154 }
02155
02169 const char*
02170 dbus_g_proxy_get_bus_name (DBusGProxy *proxy)
02171 {
02172 DBusGProxyPrivate *priv;
02173
02174 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02175 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02176
02177 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02178
02179 return priv->name;
02180 }
02181
02190 const char*
02191 dbus_g_proxy_get_interface (DBusGProxy *proxy)
02192 {
02193 DBusGProxyPrivate *priv;
02194
02195 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02196 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02197
02198 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02199
02200 return priv->interface;
02201 }
02202
02210 void
02211 dbus_g_proxy_set_interface (DBusGProxy *proxy,
02212 const char *interface_name)
02213 {
02214 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02215
02216
02217
02218 dbus_g_proxy_manager_unregister (priv->manager, proxy);
02219 g_free (priv->interface);
02220 priv->interface = g_strdup (interface_name);
02221 dbus_g_proxy_manager_register (priv->manager, proxy);
02222 }
02223
02231 const char*
02232 dbus_g_proxy_get_path (DBusGProxy *proxy)
02233 {
02234 DBusGProxyPrivate *priv;
02235
02236 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02237 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02238
02239 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02240
02241 return priv->path;
02242 }
02243
02244 static DBusMessage *
02245 dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy,
02246 const char *method,
02247 GValueArray *args)
02248 {
02249 DBusMessage *message;
02250 DBusMessageIter msgiter;
02251 guint i;
02252 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02253
02254 message = dbus_message_new_method_call (priv->name,
02255 priv->path,
02256 priv->interface,
02257 method);
02258 if (message == NULL)
02259 goto oom;
02260
02261 dbus_message_iter_init_append (message, &msgiter);
02262 for (i = 0; i < args->n_values; i++)
02263 {
02264 GValue *gvalue;
02265
02266 gvalue = g_value_array_get_nth (args, i);
02267
02268 if (!_dbus_gvalue_marshal (&msgiter, gvalue))
02269 g_assert_not_reached ();
02270 }
02271 return message;
02272 oom:
02273 return NULL;
02274 }
02275
02276 static guint
02277 dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
02278 const char *method,
02279 DBusGProxyCallNotify notify,
02280 gpointer user_data,
02281 GDestroyNotify destroy,
02282 GValueArray *args,
02283 int timeout)
02284 {
02285 DBusMessage *message;
02286 DBusPendingCall *pending;
02287 GPendingNotifyClosure *closure;
02288 guint call_id;
02289 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02290
02291 pending = NULL;
02292
02293 message = dbus_g_proxy_marshal_args_to_message (proxy, method, args);
02294 if (!message)
02295 goto oom;
02296
02297 if (!dbus_connection_send_with_reply (priv->manager->connection,
02298 message,
02299 &pending,
02300 timeout))
02301 goto oom;
02302 dbus_message_unref (message);
02303
02304
02305
02306
02307
02308 if (pending == NULL)
02309 return 0;
02310
02311 call_id = ++priv->call_id_counter;
02312
02313 if (notify != NULL)
02314 {
02315 closure = g_new (GPendingNotifyClosure, 1);
02316 closure->proxy = proxy;
02317 closure->call_id = call_id;
02318 closure->func = notify;
02319 closure->data = user_data;
02320 closure->free_data_func = destroy;
02321 dbus_pending_call_set_notify (pending, d_pending_call_notify,
02322 closure,
02323 d_pending_call_free);
02324 }
02325
02326 g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending);
02327
02328 return call_id;
02329 oom:
02330 g_error ("Out of memory");
02331 return 0;
02332 }
02333
02334 static gboolean
02335 dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
02336 guint call_id,
02337 GError **error,
02338 GType first_arg_type,
02339 va_list args)
02340 {
02341 DBusMessage *reply;
02342 DBusMessageIter msgiter;
02343 DBusError derror;
02344 va_list args_unwind;
02345 guint over;
02346 int n_retvals_processed;
02347 gboolean ret;
02348 GType valtype;
02349 DBusPendingCall *pending;
02350 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02351
02352 reply = NULL;
02353 ret = FALSE;
02354 n_retvals_processed = 0;
02355 over = 0;
02356
02357
02358 G_VA_COPY(args_unwind, args);
02359
02360 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02361
02362 dbus_pending_call_block (pending);
02363 reply = dbus_pending_call_steal_reply (pending);
02364
02365 g_assert (reply != NULL);
02366
02367 dbus_error_init (&derror);
02368
02369 switch (dbus_message_get_type (reply))
02370 {
02371 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
02372 dbus_message_iter_init (reply, &msgiter);
02373 valtype = first_arg_type;
02374 while (valtype != G_TYPE_INVALID)
02375 {
02376 int arg_type;
02377 gpointer return_storage;
02378 GValue gvalue = { 0, };
02379 DBusGValueMarshalCtx context;
02380
02381 context.recursion_depth = 0;
02382 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
02383 context.proxy = proxy;
02384
02385 arg_type = dbus_message_iter_get_arg_type (&msgiter);
02386 if (arg_type == DBUS_TYPE_INVALID)
02387 {
02388 g_set_error (error, DBUS_GERROR,
02389 DBUS_GERROR_INVALID_ARGS,
02390 _("Too few arguments in reply"));
02391 goto out;
02392 }
02393
02394 return_storage = va_arg (args, gpointer);
02395 if (return_storage == NULL)
02396 goto next;
02397
02398
02399
02400
02401 if (arg_type == DBUS_TYPE_VARIANT
02402 && g_type_is_a (valtype, G_TYPE_VALUE))
02403 {
02404 if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL))
02405 {
02406 g_set_error (error,
02407 DBUS_GERROR,
02408 DBUS_GERROR_INVALID_ARGS,
02409 _("Couldn't convert argument, expected \"%s\""),
02410 g_type_name (valtype));
02411 goto out;
02412 }
02413 }
02414 else
02415 {
02416 g_value_init (&gvalue, valtype);
02417
02418 if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error))
02419 goto out;
02420
02421
02422 if (!_dbus_gvalue_store (&gvalue, return_storage))
02423 g_assert_not_reached ();
02424
02425 }
02426
02427 next:
02428 n_retvals_processed++;
02429 dbus_message_iter_next (&msgiter);
02430 valtype = va_arg (args, GType);
02431 }
02432
02433 while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID)
02434 {
02435 over++;
02436 dbus_message_iter_next (&msgiter);
02437 }
02438
02439 if (over > 0)
02440 {
02441 g_set_error (error, DBUS_GERROR,
02442 DBUS_GERROR_INVALID_ARGS,
02443 _("Too many arguments in reply; expected %d, got %d"),
02444 n_retvals_processed, over);
02445 goto out;
02446 }
02447 break;
02448 case DBUS_MESSAGE_TYPE_ERROR:
02449 dbus_set_error_from_message (&derror, reply);
02450 dbus_set_g_error (error, &derror);
02451 dbus_error_free (&derror);
02452 goto out;
02453 break;
02454 default:
02455 dbus_set_error (&derror, DBUS_ERROR_FAILED,
02456 "Reply was neither a method return nor an exception");
02457 dbus_set_g_error (error, &derror);
02458 dbus_error_free (&derror);
02459 goto out;
02460 break;
02461 }
02462
02463 ret = TRUE;
02464 out:
02465 if (ret == FALSE)
02466 {
02467 int i;
02468
02469 valtype = first_arg_type;
02470 for (i = 0; i < n_retvals_processed; i++)
02471 {
02472 GValue value = {0,};
02473 gpointer retval;
02474
02475 g_value_init (&value, valtype);
02476
02477 retval = va_arg (args_unwind, gpointer);
02478 if (retval == NULL)
02479 {
02480 i--;
02481 continue;
02482 }
02483
02484 _dbus_gvalue_take (&value, retval);
02485 g_value_unset (&value);
02486
02487 valtype = va_arg (args_unwind, GType);
02488 }
02489 }
02490 va_end (args_unwind);
02491 va_end (args);
02492
02493 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02494
02495 if (reply)
02496 dbus_message_unref (reply);
02497 return ret;
02498 }
02499
02522 DBusGProxyCall *
02523 dbus_g_proxy_begin_call (DBusGProxy *proxy,
02524 const char *method,
02525 DBusGProxyCallNotify notify,
02526 gpointer user_data,
02527 GDestroyNotify destroy,
02528 GType first_arg_type,
02529 ...)
02530 {
02531 guint call_id;
02532 va_list args;
02533 GValueArray *arg_values;
02534 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02535
02536 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02537 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02538
02539 va_start (args, first_arg_type);
02540
02541 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02542
02543 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values, priv->default_timeout);
02544
02545 g_value_array_free (arg_values);
02546
02547 va_end (args);
02548
02549 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02550 }
02551
02575 DBusGProxyCall *
02576 dbus_g_proxy_begin_call_with_timeout (DBusGProxy *proxy,
02577 const char *method,
02578 DBusGProxyCallNotify notify,
02579 gpointer user_data,
02580 GDestroyNotify destroy,
02581 int timeout,
02582 GType first_arg_type,
02583 ...)
02584 {
02585 guint call_id;
02586 va_list args;
02587 GValueArray *arg_values;
02588
02589 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02590 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02591
02592 va_start (args, first_arg_type);
02593
02594 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02595
02596 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,timeout);
02597
02598 g_value_array_free (arg_values);
02599
02600 va_end (args);
02601
02602 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02603 }
02604
02627 gboolean
02628 dbus_g_proxy_end_call (DBusGProxy *proxy,
02629 DBusGProxyCall *call,
02630 GError **error,
02631 GType first_arg_type,
02632 ...)
02633 {
02634 gboolean ret;
02635 va_list args;
02636
02637 va_start (args, first_arg_type);
02638
02639 ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
02640
02641 va_end (args);
02642
02643 return ret;
02644 }
02645
02662 gboolean
02663 dbus_g_proxy_call (DBusGProxy *proxy,
02664 const char *method,
02665 GError **error,
02666 GType first_arg_type,
02667 ...)
02668 {
02669 gboolean ret;
02670 guint call_id;
02671 va_list args;
02672 GValueArray *in_args;
02673 DBusGProxyPrivate *priv;
02674
02675 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02676 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02677
02678 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02679
02680 va_start (args, first_arg_type);
02681
02682 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02683
02684 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args, priv->default_timeout);
02685
02686 g_value_array_free (in_args);
02687
02688 if (call_id > 0)
02689 {
02690 first_arg_type = va_arg (args, GType);
02691 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02692 }
02693 else
02694 {
02695 g_set_error (error, DBUS_GERROR,
02696 DBUS_GERROR_FAILED,
02697 _("Disconnection or out-of-memory"));
02698 ret = FALSE;
02699 }
02700
02701 va_end (args);
02702
02703 return ret;
02704 }
02705
02723 gboolean
02724 dbus_g_proxy_call_with_timeout (DBusGProxy *proxy,
02725 const char *method,
02726 int timeout,
02727 GError **error,
02728 GType first_arg_type,
02729 ...)
02730 {
02731 gboolean ret = TRUE;
02732 guint call_id;
02733 va_list args;
02734 GValueArray *in_args;
02735
02736 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02737 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02738
02739 va_start (args, first_arg_type);
02740
02741 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02742
02743 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,timeout);
02744
02745 g_value_array_free (in_args);
02746
02747 if (call_id > 0) {
02748 first_arg_type = va_arg (args, GType);
02749 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02750 }
02751
02752 va_end (args);
02753
02754 return ret;
02755 }
02756
02769 void
02770 dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
02771 const char *method,
02772 GType first_arg_type,
02773 ...)
02774 {
02775 DBusMessage *message;
02776 va_list args;
02777 GValueArray *in_args;
02778 DBusGProxyPrivate *priv;
02779
02780 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02781 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02782
02783 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02784
02785 va_start (args, first_arg_type);
02786 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02787
02788 message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args);
02789
02790 g_value_array_free (in_args);
02791 va_end (args);
02792
02793 if (!message)
02794 goto oom;
02795
02796 dbus_message_set_no_reply (message, TRUE);
02797
02798 if (!dbus_connection_send (priv->manager->connection,
02799 message,
02800 NULL))
02801 goto oom;
02802 dbus_message_unref (message);
02803 return;
02804
02805 oom:
02806 g_error ("Out of memory");
02807 }
02808
02819 void
02820 dbus_g_proxy_cancel_call (DBusGProxy *proxy,
02821 DBusGProxyCall *call)
02822 {
02823 guint call_id;
02824 DBusPendingCall *pending;
02825 DBusGProxyPrivate *priv;
02826
02827 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02828 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02829
02830 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02831
02832 call_id = DBUS_G_PROXY_CALL_TO_ID (call);
02833
02834 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02835 g_return_if_fail (pending != NULL);
02836
02837 dbus_pending_call_cancel (pending);
02838
02839 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02840 }
02841
02862 void
02863 dbus_g_proxy_send (DBusGProxy *proxy,
02864 DBusMessage *message,
02865 dbus_uint32_t *client_serial)
02866 {
02867 DBusGProxyPrivate *priv;
02868
02869 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02870 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02871
02872 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02873
02874 if (priv->name)
02875 {
02876 if (!dbus_message_set_destination (message, priv->name))
02877 g_error ("Out of memory");
02878 }
02879 if (priv->path)
02880 {
02881 if (!dbus_message_set_path (message, priv->path))
02882 g_error ("Out of memory");
02883 }
02884 if (priv->interface)
02885 {
02886 if (!dbus_message_set_interface (message, priv->interface))
02887 g_error ("Out of memory");
02888 }
02889
02890 if (!dbus_connection_send (priv->manager->connection, message, client_serial))
02891 g_error ("Out of memory\n");
02892 }
02893
02894 static void
02895 array_free_all (gpointer array)
02896 {
02897 g_array_free (array, TRUE);
02898 }
02899
02910 void
02911 dbus_g_proxy_add_signal (DBusGProxy *proxy,
02912 const char *signal_name,
02913 GType first_type,
02914 ...)
02915 {
02916 GQuark q;
02917 char *name;
02918 GArray *gtypesig;
02919 GType gtype;
02920 va_list args;
02921 DBusGProxyPrivate *priv;
02922
02923 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02924 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02925 g_return_if_fail (signal_name != NULL);
02926
02927 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02928
02929 name = create_signal_name (priv->interface, signal_name);
02930
02931 q = g_quark_from_string (name);
02932
02933 g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL);
02934
02935 gtypesig = g_array_new (FALSE, TRUE, sizeof (GType));
02936
02937 va_start (args, first_type);
02938 gtype = first_type;
02939 while (gtype != G_TYPE_INVALID)
02940 {
02941 g_array_append_val (gtypesig, gtype);
02942 gtype = va_arg (args, GType);
02943 }
02944 va_end (args);
02945
02946 #ifndef G_DISABLE_CHECKS
02947 if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL)
02948 g_warning ("No marshaller for signature of signal '%s'", signal_name);
02949 #endif
02950
02951
02952 g_datalist_id_set_data_full (&priv->signal_signatures,
02953 q, gtypesig,
02954 array_free_all);
02955
02956 g_free (name);
02957 }
02958
02971 void
02972 dbus_g_proxy_connect_signal (DBusGProxy *proxy,
02973 const char *signal_name,
02974 GCallback handler,
02975 void *data,
02976 GClosureNotify free_data_func)
02977 {
02978 char *name;
02979 GClosure *closure;
02980 GQuark q;
02981 DBusGProxyPrivate *priv;
02982 char *tri;
02983 DBusGProxyList *list;
02984
02985 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02986 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02987 g_return_if_fail (signal_name != NULL);
02988 g_return_if_fail (handler != NULL);
02989
02990 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02991
02992 tri = tristring_from_proxy (proxy);
02993 list = g_hash_table_lookup (priv->manager->proxy_lists, tri);
02994 g_free (tri);
02995
02996
02997
02998
02999 if (priv->name && list->signal_subscribed != NULL)
03000 {
03001 gchar *orig_key;
03002 GHashTable *proxy_set;
03003 gboolean found = g_hash_table_lookup_extended (list->signal_subscribed,
03004 signal_name, (gpointer *) &orig_key, (gpointer *) &proxy_set);
03005 gint handler_count;
03006 gpointer value;
03007
03008 if (!found || g_hash_table_size (proxy_set) == 0)
03009 {
03010 char *rule;
03011
03012 rule = g_proxy_get_signal_match_rule (proxy, signal_name);
03013
03014
03015
03016 dbus_bus_add_match (priv->manager->connection,
03017 rule, NULL);
03018 g_free (rule);
03019 }
03020
03021 if (!found)
03022 {
03023 proxy_set = g_hash_table_new (NULL, NULL);
03024 orig_key = g_strdup (signal_name);
03025 }
03026
03027 if (g_hash_table_lookup_extended (proxy_set, proxy, NULL,
03028 &value))
03029 {
03030 handler_count = GPOINTER_TO_UINT (value) + 1;
03031 }
03032 else
03033 {
03034 handler_count = 1;
03035 }
03036 g_hash_table_insert (proxy_set, proxy, GINT_TO_POINTER (handler_count));
03037
03038 g_hash_table_steal (list->signal_subscribed, signal_name);
03039 g_hash_table_insert (list->signal_subscribed, orig_key, proxy_set);
03040 }
03041
03042 name = create_signal_name (priv->interface, signal_name);
03043
03044 q = g_quark_try_string (name);
03045
03046 #ifndef G_DISABLE_CHECKS
03047 if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL)
03048 {
03049 g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name);
03050 g_free (name);
03051 return;
03052 }
03053 #endif
03054
03055 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
03056
03057 g_signal_connect_closure_by_id (G_OBJECT (proxy),
03058 signals[RECEIVED],
03059 q,
03060 closure, FALSE);
03061
03062 g_free (name);
03063 }
03064
03075 void
03076 dbus_g_proxy_disconnect_signal (DBusGProxy *proxy,
03077 const char *signal_name,
03078 GCallback handler,
03079 void *data)
03080 {
03081 guint matched_count;
03082 gint handler_count;
03083 char *name;
03084 GQuark q;
03085 DBusGProxyPrivate *priv;
03086 char *tri;
03087 DBusGProxyList *list;
03088 gchar *_signal_name;
03089
03090 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
03091 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
03092 g_return_if_fail (signal_name != NULL);
03093 g_return_if_fail (handler != NULL);
03094
03095 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
03096 name = create_signal_name (priv->interface, signal_name);
03097
03098 q = g_quark_try_string (name);
03099 g_free (name);
03100
03101 if (q == 0)
03102 {
03103 g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
03104 signal_name);
03105 return;
03106 }
03107
03108
03109
03110
03111 _signal_name = g_strdup (signal_name);
03112 matched_count = g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
03113 G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
03114 signals[RECEIVED], q, NULL, G_CALLBACK (handler), data);
03115
03116 tri = tristring_from_proxy (proxy);
03117 list = g_hash_table_lookup (priv->manager->proxy_lists, tri);
03118 g_free (tri);
03119
03120
03121 if (list->signal_subscribed != NULL)
03122 {
03123 GHashTable *proxy_set = g_hash_table_lookup (list->signal_subscribed,
03124 _signal_name);
03125 gpointer value;
03126
03127 if (proxy_set == NULL || !g_hash_table_lookup_extended (proxy_set, proxy,
03128 NULL, &value))
03129 {
03130 g_warning ("Attempt to disconnect from signal '%s' which is not"
03131 " registered\n", _signal_name);
03132 g_free (_signal_name);
03133 return;
03134 }
03135
03136 handler_count = GPOINTER_TO_INT (value);
03137 handler_count -= matched_count;
03138 g_assert (handler_count >= 0);
03139 if (handler_count == 0)
03140 {
03141 g_hash_table_remove (proxy_set, proxy);
03142 }
03143 else
03144 {
03145 g_hash_table_insert (proxy_set, proxy,
03146 GINT_TO_POINTER (handler_count));
03147 }
03148
03149 if (g_hash_table_size (proxy_set) == 0)
03150 {
03151 char *rule;
03152
03153 rule = g_proxy_get_signal_match_rule (proxy, _signal_name);
03154
03155
03156
03157 dbus_bus_remove_match (priv->manager->connection,
03158 rule, NULL);
03159 g_free (rule);
03160
03161 g_hash_table_remove (list->signal_subscribed, _signal_name);
03162 }
03163 }
03164 g_free (_signal_name);
03165 }
03166
03184 void
03185 dbus_g_proxy_set_default_timeout (DBusGProxy *proxy,
03186 int timeout)
03187 {
03188 DBusGProxyPrivate *priv;
03189
03190 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
03191 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
03192
03193 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
03194 priv->default_timeout = timeout;
03195 }
03196
03197
03200 #ifdef DBUS_BUILD_TESTS
03201
03207 gboolean
03208 _dbus_g_proxy_test (void)
03209 {
03210
03211
03212 return TRUE;
03213 }
03214
03215 #endif