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