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