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 return strcmp (info->name, name);
00498 }
00499
00500 typedef struct
00501 {
00502 const char *name;
00503 const char *owner;
00504 DBusGProxyNameOwnerInfo *info;
00505 } DBusGProxyNameOwnerForeachData;
00506
00507 static void
00508 name_owner_foreach (gpointer key, gpointer val, gpointer data)
00509 {
00510 const char *owner;
00511 DBusGProxyNameOwnerForeachData *foreach_data;
00512 GSList *names;
00513 GSList *link;
00514
00515 owner = key;
00516 names = val;
00517 foreach_data = data;
00518
00519 if (foreach_data->owner != NULL)
00520 return;
00521
00522 g_assert (foreach_data->info == NULL);
00523
00524 link = g_slist_find_custom (names, foreach_data->name, find_name_in_info);
00525 if (link)
00526 {
00527 foreach_data->owner = owner;
00528 foreach_data->info = link->data;
00529 }
00530 }
00531
00532 static gboolean
00533 dbus_g_proxy_manager_lookup_name_owner (DBusGProxyManager *manager,
00534 const char *name,
00535 DBusGProxyNameOwnerInfo **info,
00536 const char **owner)
00537 {
00538 DBusGProxyNameOwnerForeachData foreach_data;
00539
00540 foreach_data.name = name;
00541 foreach_data.owner = NULL;
00542 foreach_data.info = NULL;
00543
00544 g_hash_table_foreach (manager->owner_names, name_owner_foreach, &foreach_data);
00545
00546 *info = foreach_data.info;
00547 *owner = foreach_data.owner;
00548 return *info != NULL;
00549 }
00550
00551 static void
00552 insert_nameinfo (DBusGProxyManager *manager,
00553 const char *owner,
00554 DBusGProxyNameOwnerInfo *info)
00555 {
00556 GSList *names;
00557 gboolean insert;
00558
00559 names = g_hash_table_lookup (manager->owner_names, owner);
00560
00561
00562 insert = (names == NULL);
00563
00564 names = g_slist_append (names, info);
00565
00566 if (insert)
00567 g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
00568 }
00569
00570 static void
00571 dbus_g_proxy_manager_monitor_name_owner (DBusGProxyManager *manager,
00572 const char *owner,
00573 const char *name)
00574 {
00575 GSList *names;
00576 GSList *link;
00577 DBusGProxyNameOwnerInfo *nameinfo;
00578
00579 names = g_hash_table_lookup (manager->owner_names, owner);
00580 link = g_slist_find_custom (names, name, find_name_in_info);
00581
00582 if (!link)
00583 {
00584 nameinfo = g_new0 (DBusGProxyNameOwnerInfo, 1);
00585 nameinfo->name = g_strdup (name);
00586 nameinfo->refcount = 1;
00587
00588 insert_nameinfo (manager, owner, nameinfo);
00589 }
00590 else
00591 {
00592 nameinfo = link->data;
00593 nameinfo->refcount++;
00594 }
00595 }
00596
00597 static void
00598 dbus_g_proxy_manager_unmonitor_name_owner (DBusGProxyManager *manager,
00599 const char *name)
00600 {
00601 DBusGProxyNameOwnerInfo *info;
00602 const char *owner;
00603 gboolean ret;
00604
00605 ret = dbus_g_proxy_manager_lookup_name_owner (manager, name, &info, &owner);
00606 g_assert (ret);
00607 g_assert (info != NULL);
00608 g_assert (owner != NULL);
00609
00610 info->refcount--;
00611 if (info->refcount == 0)
00612 {
00613 GSList *names;
00614 GSList *link;
00615
00616 names = g_hash_table_lookup (manager->owner_names, owner);
00617 link = g_slist_find_custom (names, name, find_name_in_info);
00618 names = g_slist_delete_link (names, link);
00619 if (names != NULL)
00620 g_hash_table_insert (manager->owner_names, g_strdup (owner), names);
00621 else
00622 g_hash_table_remove (manager->owner_names, owner);
00623
00624 g_free (info->name);
00625 g_free (info);
00626 }
00627 }
00628
00629 typedef struct
00630 {
00631 const char *name;
00632 GSList *destroyed;
00633 } DBusGProxyUnassociateData;
00634
00635 static void
00636 unassociate_proxies (gpointer key, gpointer val, gpointer user_data)
00637 {
00638 DBusGProxyList *list;
00639 const char *name;
00640 GSList *tmp;
00641 DBusGProxyUnassociateData *data;
00642
00643 list = val;
00644 data = user_data;
00645 name = data->name;
00646
00647 for (tmp = list->proxies; tmp; tmp = tmp->next)
00648 {
00649 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
00650 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00651 DBusGProxyManager *manager;
00652
00653 manager = priv->manager;
00654
00655 if (!strcmp (priv->name, name))
00656 {
00657 if (!priv->for_owner)
00658 {
00659 g_assert (priv->associated);
00660 g_assert (priv->name_call == NULL);
00661
00662 priv->associated = FALSE;
00663 manager->unassociated_proxies = g_slist_prepend (manager->unassociated_proxies, proxy);
00664 }
00665 else
00666 {
00667 data->destroyed = g_slist_prepend (data->destroyed, proxy);
00668
00669
00670 g_object_add_weak_pointer (G_OBJECT (proxy),
00671 &(data->destroyed->data));
00672 }
00673 }
00674 }
00675 }
00676
00677 static void
00678 dbus_g_proxy_manager_replace_name_owner (DBusGProxyManager *manager,
00679 const char *name,
00680 const char *prev_owner,
00681 const char *new_owner)
00682 {
00683 GSList *names;
00684
00685 if (prev_owner[0] == '\0')
00686 {
00687 GSList *tmp;
00688 GSList *removed;
00689
00690
00691
00692 removed = NULL;
00693
00694 for (tmp = manager->unassociated_proxies; tmp ; tmp = tmp->next)
00695 {
00696 DBusGProxy *proxy = tmp->data;
00697 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00698
00699 if (!strcmp (priv->name, name))
00700 {
00701 removed = g_slist_prepend (removed, tmp);
00702
00703 dbus_g_proxy_manager_monitor_name_owner (manager, new_owner, name);
00704 priv->associated = TRUE;
00705 }
00706 }
00707
00708 for (tmp = removed; tmp; tmp = tmp->next)
00709 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, tmp->data);
00710 g_slist_free (removed);
00711 }
00712 else
00713 {
00714 DBusGProxyNameOwnerInfo *info;
00715 GSList *link;
00716
00717
00718
00719 names = g_hash_table_lookup (manager->owner_names, prev_owner);
00720
00721 info = NULL;
00722 if (names != NULL)
00723 {
00724 link = g_slist_find_custom (names, name, find_name_in_info);
00725
00726 if (link != NULL)
00727 {
00728 info = link->data;
00729
00730 names = g_slist_delete_link (names, link);
00731
00732 if (names == NULL)
00733 g_hash_table_remove (manager->owner_names, prev_owner);
00734 }
00735 }
00736
00737 if (new_owner[0] == '\0')
00738 {
00739 DBusGProxyUnassociateData data;
00740 GSList *tmp;
00741
00742 data.name = name;
00743 data.destroyed = NULL;
00744
00745
00746 g_hash_table_foreach (manager->proxy_lists,
00747 unassociate_proxies, &data);
00748
00749 UNLOCK_MANAGER (manager);
00750
00751
00752
00753
00754 for (tmp = data.destroyed; tmp; tmp = tmp->next)
00755 if (tmp->data != NULL)
00756 {
00757 g_object_remove_weak_pointer (G_OBJECT (tmp->data),
00758 &(tmp->data));
00759 dbus_g_proxy_destroy (tmp->data);
00760 }
00761 g_slist_free (data.destroyed);
00762
00763 LOCK_MANAGER (manager);
00764
00765 if (info)
00766 {
00767 g_free (info->name);
00768 g_free (info);
00769 }
00770 }
00771 else if (info)
00772 {
00773 insert_nameinfo (manager, new_owner, info);
00774 }
00775 }
00776 }
00777
00778 static void
00779 got_name_owner_cb (DBusGProxy *bus_proxy,
00780 DBusGProxyCall *call,
00781 void *user_data)
00782 {
00783 DBusGProxy *proxy = user_data;
00784 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00785 GError *error;
00786 char *owner;
00787
00788 error = NULL;
00789 owner = NULL;
00790
00791 LOCK_MANAGER (priv->manager);
00792
00793 if (!dbus_g_proxy_end_call (bus_proxy, call, &error,
00794 G_TYPE_STRING, &owner,
00795 G_TYPE_INVALID))
00796 {
00797 if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
00798 {
00799 priv->manager->unassociated_proxies = g_slist_prepend (priv->manager->unassociated_proxies, proxy);
00800 }
00801 else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
00802 g_warning ("Couldn't get name owner (%s): %s",
00803 dbus_g_error_get_name (error),
00804 error->message);
00805 else
00806 g_warning ("Couldn't get name owner (code %d): %s",
00807 error->code, error->message);
00808 g_clear_error (&error);
00809 goto out;
00810 }
00811 else
00812 {
00813 dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name);
00814 priv->associated = TRUE;
00815 }
00816
00817 out:
00818 priv->name_call = NULL;
00819 UNLOCK_MANAGER (priv->manager);
00820 g_free (owner);
00821 }
00822
00823 static char *
00824 get_name_owner (DBusConnection *connection,
00825 const char *name,
00826 GError **error)
00827 {
00828 DBusError derror;
00829 DBusMessage *request, *reply;
00830 char *base_name;
00831
00832 dbus_error_init (&derror);
00833
00834 base_name = NULL;
00835 reply = NULL;
00836
00837 request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
00838 DBUS_PATH_DBUS,
00839 DBUS_INTERFACE_DBUS,
00840 "GetNameOwner");
00841 if (request == NULL)
00842 g_error ("Out of memory");
00843
00844 if (!dbus_message_append_args (request,
00845 DBUS_TYPE_STRING, &name,
00846 DBUS_TYPE_INVALID))
00847 g_error ("Out of memory");
00848
00849 reply =
00850 dbus_connection_send_with_reply_and_block (connection,
00851 request,
00852 2000, &derror);
00853 if (reply == NULL)
00854 goto error;
00855
00856 if (dbus_set_error_from_message (&derror, reply))
00857 goto error;
00858
00859 if (!dbus_message_get_args (reply, &derror,
00860 DBUS_TYPE_STRING, &base_name,
00861 DBUS_TYPE_INVALID))
00862 goto error;
00863
00864 base_name = g_strdup (base_name);
00865 goto out;
00866
00867 error:
00868 g_assert (dbus_error_is_set (&derror));
00869 dbus_set_g_error (error, &derror);
00870 dbus_error_free (&derror);
00871
00872 out:
00873 if (request)
00874 dbus_message_unref (request);
00875 if (reply)
00876 dbus_message_unref (reply);
00877
00878 return base_name;
00879 }
00880
00881
00882 static void
00883 dbus_g_proxy_manager_register (DBusGProxyManager *manager,
00884 DBusGProxy *proxy)
00885 {
00886 DBusGProxyList *list;
00887 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00888
00889 LOCK_MANAGER (manager);
00890
00891 if (manager->proxy_lists == NULL)
00892 {
00893 g_assert (manager->owner_names == NULL);
00894
00895 list = NULL;
00896 manager->proxy_lists = g_hash_table_new_full (tristring_hash,
00897 tristring_equal,
00898 NULL,
00899 (GFreeFunc) g_proxy_list_free);
00900 manager->owner_names = g_hash_table_new_full (g_str_hash,
00901 g_str_equal,
00902 g_free,
00903 NULL);
00904
00905
00906
00907 dbus_bus_add_match (manager->connection,
00908 "type='signal',sender='" DBUS_SERVICE_DBUS
00909 "',path='" DBUS_PATH_DBUS
00910 "',interface='" DBUS_INTERFACE_DBUS
00911 "',member='NameOwnerChanged'",
00912 NULL);
00913 }
00914 else
00915 {
00916 char *tri;
00917
00918 tri = tristring_from_proxy (proxy);
00919
00920 list = g_hash_table_lookup (manager->proxy_lists, tri);
00921
00922 g_free (tri);
00923 }
00924
00925 if (list == NULL)
00926 {
00927 list = g_proxy_list_new (proxy);
00928
00929 g_hash_table_replace (manager->proxy_lists,
00930 list->name, list);
00931 }
00932
00933 if (list->proxies == NULL && priv->name)
00934 {
00935
00936
00937
00938
00939 char *rule;
00940
00941 rule = g_proxy_get_match_rule (proxy);
00942
00943
00944
00945
00946 dbus_bus_add_match (manager->connection,
00947 rule, NULL);
00948
00949 g_free (rule);
00950 }
00951
00952 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00953
00954 list->proxies = g_slist_prepend (list->proxies, proxy);
00955
00956 if (!priv->for_owner)
00957 {
00958 const char *owner;
00959 DBusGProxyNameOwnerInfo *info;
00960
00961 if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner))
00962 {
00963 priv->name_call = manager_begin_bus_call (manager, "GetNameOwner",
00964 got_name_owner_cb,
00965 proxy, NULL,
00966 G_TYPE_STRING,
00967 priv->name,
00968 G_TYPE_INVALID);
00969
00970 priv->associated = FALSE;
00971 }
00972 else
00973 {
00974 info->refcount++;
00975 priv->associated = TRUE;
00976 }
00977 }
00978
00979 UNLOCK_MANAGER (manager);
00980 }
00981
00982 static void
00983 dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
00984 DBusGProxy *proxy)
00985 {
00986 DBusGProxyList *list;
00987 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00988 char *tri;
00989
00990 LOCK_MANAGER (manager);
00991
00992 #ifndef G_DISABLE_CHECKS
00993 if (manager->proxy_lists == NULL)
00994 {
00995 g_warning ("Trying to unregister a proxy but there aren't any registered");
00996 return;
00997 }
00998 #endif
00999
01000 tri = tristring_from_proxy (proxy);
01001
01002 list = g_hash_table_lookup (manager->proxy_lists, tri);
01003
01004 #ifndef G_DISABLE_CHECKS
01005 if (list == NULL)
01006 {
01007 g_warning ("Trying to unregister a proxy but it isn't registered");
01008 return;
01009 }
01010 #endif
01011
01012 g_assert (g_slist_find (list->proxies, proxy) != NULL);
01013
01014 list->proxies = g_slist_remove (list->proxies, proxy);
01015
01016 g_assert (g_slist_find (list->proxies, proxy) == NULL);
01017
01018 if (!priv->for_owner)
01019 {
01020 if (!priv->associated)
01021 {
01022 GSList *link;
01023
01024 if (priv->name_call != 0)
01025 {
01026 dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
01027 priv->name_call = 0;
01028 }
01029 else
01030 {
01031 link = g_slist_find (manager->unassociated_proxies, proxy);
01032 g_assert (link != NULL);
01033
01034 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link);
01035 }
01036 }
01037 else
01038 {
01039 g_assert (priv->name_call == 0);
01040
01041 dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name);
01042 }
01043 }
01044
01045 if (list->proxies == NULL)
01046 {
01047 char *rule;
01048 g_hash_table_remove (manager->proxy_lists,
01049 tri);
01050 list = NULL;
01051
01052 rule = g_proxy_get_match_rule (proxy);
01053 dbus_bus_remove_match (manager->connection,
01054 rule, NULL);
01055 g_free (rule);
01056 }
01057
01058 if (g_hash_table_size (manager->proxy_lists) == 0)
01059 {
01060 g_hash_table_destroy (manager->proxy_lists);
01061 manager->proxy_lists = NULL;
01062 }
01063
01064 g_free (tri);
01065
01066 UNLOCK_MANAGER (manager);
01067 }
01068
01069 static void
01070 list_proxies_foreach (gpointer key,
01071 gpointer value,
01072 gpointer user_data)
01073 {
01074 DBusGProxyList *list;
01075 GSList **ret;
01076 GSList *tmp;
01077
01078 list = value;
01079 ret = user_data;
01080
01081 tmp = list->proxies;
01082 while (tmp != NULL)
01083 {
01084 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
01085
01086 g_object_ref (proxy);
01087 *ret = g_slist_prepend (*ret, proxy);
01088
01089 tmp = tmp->next;
01090 }
01091 }
01092
01093 static GSList*
01094 dbus_g_proxy_manager_list_all (DBusGProxyManager *manager)
01095 {
01096 GSList *ret;
01097
01098 ret = NULL;
01099
01100 if (manager->proxy_lists)
01101 {
01102 g_hash_table_foreach (manager->proxy_lists,
01103 list_proxies_foreach,
01104 &ret);
01105 }
01106
01107 return ret;
01108 }
01109
01110 static DBusHandlerResult
01111 dbus_g_proxy_manager_filter (DBusConnection *connection,
01112 DBusMessage *message,
01113 void *user_data)
01114 {
01115 DBusGProxyManager *manager;
01116
01117 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
01118 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01119
01120 manager = user_data;
01121
01122 dbus_g_proxy_manager_ref (manager);
01123
01124 LOCK_MANAGER (manager);
01125
01126 if (dbus_message_is_signal (message,
01127 DBUS_INTERFACE_LOCAL,
01128 "Disconnected"))
01129 {
01130
01131
01132
01133 GSList *all;
01134 GSList *tmp;
01135
01136 all = dbus_g_proxy_manager_list_all (manager);
01137
01138 tmp = all;
01139 while (tmp != NULL)
01140 {
01141 DBusGProxy *proxy;
01142
01143 proxy = DBUS_G_PROXY (tmp->data);
01144
01145 UNLOCK_MANAGER (manager);
01146 dbus_g_proxy_destroy (proxy);
01147 g_object_unref (G_OBJECT (proxy));
01148 LOCK_MANAGER (manager);
01149
01150 tmp = tmp->next;
01151 }
01152
01153 g_slist_free (all);
01154
01155 #ifndef G_DISABLE_CHECKS
01156 if (manager->proxy_lists != NULL)
01157 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.");
01158 #endif
01159 }
01160 else
01161 {
01162 char *tri;
01163 GSList *full_list;
01164 GSList *owned_names;
01165 GSList *tmp;
01166 const char *sender;
01167
01168
01169 if (dbus_message_is_signal (message,
01170 DBUS_INTERFACE_DBUS,
01171 "NameOwnerChanged"))
01172 {
01173 const char *name;
01174 const char *prev_owner;
01175 const char *new_owner;
01176 DBusError derr;
01177
01178 dbus_error_init (&derr);
01179 if (!dbus_message_get_args (message,
01180 &derr,
01181 DBUS_TYPE_STRING,
01182 &name,
01183 DBUS_TYPE_STRING,
01184 &prev_owner,
01185 DBUS_TYPE_STRING,
01186 &new_owner,
01187 DBUS_TYPE_INVALID))
01188 {
01189
01190 dbus_error_free (&derr);
01191 }
01192 else if (manager->owner_names != NULL)
01193 {
01194 dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner);
01195 }
01196 }
01197
01198 sender = dbus_message_get_sender (message);
01199
01200
01201 g_assert (dbus_message_get_path (message) != NULL);
01202 g_assert (dbus_message_get_interface (message) != NULL);
01203 g_assert (dbus_message_get_member (message) != NULL);
01204
01205 tri = tristring_from_message (message);
01206
01207 if (manager->proxy_lists)
01208 {
01209 DBusGProxyList *owner_list;
01210 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01211 if (owner_list)
01212 full_list = g_slist_copy (owner_list->proxies);
01213 else
01214 full_list = NULL;
01215 }
01216 else
01217 full_list = NULL;
01218
01219 g_free (tri);
01220
01221 if (manager->owner_names && sender)
01222 {
01223 owned_names = g_hash_table_lookup (manager->owner_names, sender);
01224 for (tmp = owned_names; tmp; tmp = tmp->next)
01225 {
01226 DBusGProxyList *owner_list;
01227 DBusGProxyNameOwnerInfo *nameinfo;
01228
01229 nameinfo = tmp->data;
01230 g_assert (nameinfo->refcount > 0);
01231 tri = tristring_alloc_from_strings (0, nameinfo->name,
01232 dbus_message_get_path (message),
01233 dbus_message_get_interface (message));
01234
01235 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01236 if (owner_list != NULL)
01237 full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies));
01238 g_free (tri);
01239 }
01240 }
01241
01242 #if 0
01243 g_print ("proxy got %s,%s,%s = list %p\n",
01244 tri,
01245 tri + strlen (tri) + 1,
01246 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
01247 list);
01248 #endif
01249
01250
01251
01252 g_slist_foreach (full_list, (GFunc) g_object_ref, NULL);
01253
01254 for (tmp = full_list; tmp; tmp = tmp->next)
01255 {
01256 DBusGProxy *proxy;
01257
01258 proxy = DBUS_G_PROXY (tmp->data);
01259
01260 UNLOCK_MANAGER (manager);
01261 dbus_g_proxy_emit_remote_signal (proxy, message);
01262 g_object_unref (G_OBJECT (proxy));
01263 LOCK_MANAGER (manager);
01264 }
01265 g_slist_free (full_list);
01266 }
01267
01268 UNLOCK_MANAGER (manager);
01269 dbus_g_proxy_manager_unref (manager);
01270
01271
01272
01273
01274 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01275 }
01276
01277
01278
01279
01280 #define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL)
01281
01282 static void
01283 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01284 GValue *return_value,
01285 guint n_param_values,
01286 const GValue *param_values,
01287 gpointer invocation_hint,
01288 gpointer marshal_data);
01289 enum
01290 {
01291 PROP_0,
01292 PROP_NAME,
01293 PROP_PATH,
01294 PROP_INTERFACE,
01295 PROP_CONNECTION
01296 };
01297
01298 enum
01299 {
01300 DESTROY,
01301 RECEIVED,
01302 LAST_SIGNAL
01303 };
01304
01305 static void *parent_class;
01306 static guint signals[LAST_SIGNAL] = { 0 };
01307
01308 static void
01309 dbus_g_proxy_init (DBusGProxy *proxy)
01310 {
01311 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01312
01313 g_datalist_init (&priv->signal_signatures);
01314 priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
01315 (GDestroyNotify) dbus_pending_call_unref);
01316 priv->name_call = 0;
01317 priv->associated = FALSE;
01318 }
01319
01320 static GObject *
01321 dbus_g_proxy_constructor (GType type,
01322 guint n_construct_properties,
01323 GObjectConstructParam *construct_properties)
01324 {
01325 DBusGProxy *proxy;
01326 DBusGProxyClass *klass;
01327 GObjectClass *parent_class;
01328 DBusGProxyPrivate *priv;
01329
01330 klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
01331
01332 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
01333
01334 proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
01335 construct_properties));
01336
01337 priv = DBUS_G_PROXY_GET_PRIVATE (proxy);
01338
01339
01340
01341
01342
01343
01344 g_assert (priv->path != NULL);
01345 g_assert (priv->interface != NULL);
01346
01347 if (priv->manager != NULL)
01348 {
01349 dbus_g_proxy_manager_register (priv->manager, proxy);
01350 }
01351
01352 return G_OBJECT (proxy);
01353 }
01354
01355 static void
01356 dbus_g_proxy_class_init (DBusGProxyClass *klass)
01357 {
01358 GObjectClass *object_class = G_OBJECT_CLASS (klass);
01359
01360 parent_class = g_type_class_peek_parent (klass);
01361
01362 g_type_class_add_private (klass, sizeof (DBusGProxyPrivate));
01363
01364 object_class->set_property = dbus_g_proxy_set_property;
01365 object_class->get_property = dbus_g_proxy_get_property;
01366
01367 g_object_class_install_property (object_class,
01368 PROP_NAME,
01369 g_param_spec_string ("name",
01370 "name",
01371 "name",
01372 NULL,
01373 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01374
01375 g_object_class_install_property (object_class,
01376 PROP_PATH,
01377 g_param_spec_string ("path",
01378 "path",
01379 "path",
01380 NULL,
01381 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01382
01383 g_object_class_install_property (object_class,
01384 PROP_INTERFACE,
01385 g_param_spec_string ("interface",
01386 "interface",
01387 "interface",
01388 NULL,
01389 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01390
01391 g_object_class_install_property (object_class,
01392 PROP_CONNECTION,
01393 g_param_spec_boxed ("connection",
01394 "connection",
01395 "connection",
01396 DBUS_TYPE_G_CONNECTION,
01397 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01398
01399 object_class->finalize = dbus_g_proxy_finalize;
01400 object_class->dispose = dbus_g_proxy_dispose;
01401 object_class->constructor = dbus_g_proxy_constructor;
01402
01403 signals[DESTROY] =
01404 g_signal_new ("destroy",
01405 G_OBJECT_CLASS_TYPE (object_class),
01406 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
01407 0,
01408 NULL, NULL,
01409 g_cclosure_marshal_VOID__VOID,
01410 G_TYPE_NONE, 0);
01411
01412 signals[RECEIVED] =
01413 g_signal_new ("received",
01414 G_OBJECT_CLASS_TYPE (object_class),
01415 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
01416 0,
01417 NULL, NULL,
01418 marshal_dbus_message_to_g_marshaller,
01419 G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER);
01420 }
01421
01422 static void
01423 cancel_pending_call (gpointer key, gpointer val, gpointer data)
01424 {
01425 DBusGProxyCall *call = key;
01426 DBusGProxy *proxy = data;
01427
01428 dbus_g_proxy_cancel_call (proxy, call);
01429 }
01430
01431 static void
01432 dbus_g_proxy_dispose (GObject *object)
01433 {
01434 DBusGProxy *proxy = DBUS_G_PROXY (object);
01435 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01436
01437 if (priv->pending_calls == NULL)
01438 {
01439 return;
01440 }
01441
01442
01443 g_hash_table_foreach (priv->pending_calls, cancel_pending_call, proxy);
01444 g_hash_table_destroy (priv->pending_calls);
01445 priv->pending_calls = NULL;
01446
01447 if (priv->manager && proxy != priv->manager->bus_proxy)
01448 {
01449 dbus_g_proxy_manager_unregister (priv->manager, proxy);
01450 dbus_g_proxy_manager_unref (priv->manager);
01451 }
01452 priv->manager = NULL;
01453
01454 g_datalist_clear (&priv->signal_signatures);
01455
01456 g_signal_emit (object, signals[DESTROY], 0);
01457
01458 G_OBJECT_CLASS (parent_class)->dispose (object);
01459 }
01460
01461 static void
01462 dbus_g_proxy_finalize (GObject *object)
01463 {
01464 DBusGProxy *proxy = DBUS_G_PROXY (object);
01465 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01466
01467 g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy));
01468
01469 g_free (priv->name);
01470 g_free (priv->path);
01471 g_free (priv->interface);
01472
01473 G_OBJECT_CLASS (parent_class)->finalize (object);
01474 }
01475
01476 static void
01477 dbus_g_proxy_destroy (DBusGProxy *proxy)
01478 {
01479
01480
01481
01482 g_object_run_dispose (G_OBJECT (proxy));
01483 }
01484
01485 static void
01486 dbus_g_proxy_set_property (GObject *object,
01487 guint prop_id,
01488 const GValue *value,
01489 GParamSpec *pspec)
01490 {
01491 DBusGProxy *proxy = DBUS_G_PROXY (object);
01492 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01493 DBusGConnection *connection;
01494
01495 switch (prop_id)
01496 {
01497 case PROP_NAME:
01498 priv->name = g_strdup (g_value_get_string (value));
01499 if (priv->name)
01500 priv->for_owner = (priv->name[0] == ':');
01501 else
01502 priv->for_owner = TRUE;
01503 break;
01504 case PROP_PATH:
01505 priv->path = g_strdup (g_value_get_string (value));
01506 break;
01507 case PROP_INTERFACE:
01508 priv->interface = g_strdup (g_value_get_string (value));
01509 break;
01510 case PROP_CONNECTION:
01511 connection = g_value_get_boxed (value);
01512 if (connection != NULL)
01513 {
01514 priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
01515 }
01516 break;
01517 default:
01518 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01519 break;
01520 }
01521 }
01522
01523 static void
01524 dbus_g_proxy_get_property (GObject *object,
01525 guint prop_id,
01526 GValue *value,
01527 GParamSpec *pspec)
01528 {
01529 DBusGProxy *proxy = DBUS_G_PROXY (object);
01530 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01531
01532 switch (prop_id)
01533 {
01534 case PROP_NAME:
01535 g_value_set_string (value, priv->name);
01536 break;
01537 case PROP_PATH:
01538 g_value_set_string (value, priv->path);
01539 break;
01540 case PROP_INTERFACE:
01541 g_value_set_string (value, priv->interface);
01542 break;
01543 case PROP_CONNECTION:
01544 g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection));
01545 break;
01546 default:
01547 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01548 break;
01549 }
01550 }
01551
01552
01553
01554
01555
01556
01557 static char*
01558 create_signal_name (const char *interface,
01559 const char *signal)
01560 {
01561 GString *str;
01562 char *p;
01563
01564 str = g_string_new (interface);
01565
01566 g_string_append (str, "-");
01567
01568 g_string_append (str, signal);
01569
01570
01571 p = str->str;
01572 while (*p)
01573 {
01574 if (*p == '.')
01575 *p = '-';
01576 ++p;
01577 }
01578
01579 return g_string_free (str, FALSE);
01580 }
01581
01582 static void
01583 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01584 GValue *return_value,
01585 guint n_param_values,
01586 const GValue *param_values,
01587 gpointer invocation_hint,
01588 gpointer marshal_data)
01589 {
01590
01591
01592
01593
01594
01595 #define MAX_SIGNATURE_ARGS 20
01596 GValueArray *value_array;
01597 GSignalCMarshaller c_marshaller;
01598 DBusGProxy *proxy;
01599 DBusMessage *message;
01600 GArray *gsignature;
01601 const GType *types;
01602 DBusGProxyPrivate *priv;
01603
01604 g_assert (n_param_values == 3);
01605
01606 proxy = g_value_get_object (¶m_values[0]);
01607 message = g_value_get_boxed (¶m_values[1]);
01608 gsignature = g_value_get_pointer (¶m_values[2]);
01609
01610 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
01611 g_return_if_fail (message != NULL);
01612 g_return_if_fail (gsignature != NULL);
01613
01614 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01615
01616 c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len,
01617 (GType*) gsignature->data);
01618
01619 g_return_if_fail (c_marshaller != NULL);
01620
01621 {
01622 DBusGValueMarshalCtx context;
01623 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
01624 context.proxy = proxy;
01625
01626 types = (const GType*) gsignature->data;
01627 value_array = _dbus_gvalue_demarshal_message (&context, message,
01628 gsignature->len, types, NULL);
01629 }
01630
01631 if (value_array == NULL)
01632 return;
01633
01634 g_value_array_prepend (value_array, NULL);
01635 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy));
01636 g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy);
01637
01638 (* c_marshaller) (closure, return_value, value_array->n_values,
01639 value_array->values, invocation_hint, marshal_data);
01640
01641 g_value_array_free (value_array);
01642 }
01643
01644 static void
01645 dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
01646 DBusMessage *message)
01647 {
01648 const char *interface;
01649 const char *signal;
01650 char *name;
01651 GQuark q;
01652 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01653 GArray *msg_gsignature = NULL;
01654
01655 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
01656
01657 interface = dbus_message_get_interface (message);
01658 signal = dbus_message_get_member (message);
01659
01660 g_assert (interface != NULL);
01661 g_assert (signal != NULL);
01662
01663 name = create_signal_name (interface, signal);
01664
01665
01666
01667
01668
01669 q = g_quark_try_string (name);
01670
01671 if (q != 0)
01672 {
01673 GArray *gsignature;
01674 guint i;
01675
01676 gsignature = g_datalist_id_get_data (&priv->signal_signatures, q);
01677 if (gsignature == NULL)
01678 goto out;
01679
01680 msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message),
01681 TRUE);
01682 for (i = 0; i < gsignature->len; i++)
01683 {
01684 if (msg_gsignature->len == i
01685 || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i))
01686 goto mismatch;
01687 }
01688 if (msg_gsignature->len != i)
01689 goto mismatch;
01690
01691 g_signal_emit (proxy,
01692 signals[RECEIVED],
01693 q,
01694 message,
01695 msg_gsignature);
01696 }
01697
01698 out:
01699 g_free (name);
01700 if (msg_gsignature)
01701 g_array_free (msg_gsignature, TRUE);
01702 return;
01703 mismatch:
01704 #if 0
01705
01706 g_warning ("Unexpected message signature '%s' for signal '%s'\n",
01707 dbus_message_get_signature (message),
01708 name);
01709 #endif
01710 goto out;
01711 }
01712
01713 typedef struct
01714 {
01715 DBusGProxy *proxy;
01716 guint call_id;
01717 DBusGProxyCallNotify func;
01718 void *data;
01719 GDestroyNotify free_data_func;
01720 } GPendingNotifyClosure;
01721
01722 static void
01723 d_pending_call_notify (DBusPendingCall *dcall,
01724 void *data)
01725 {
01726 GPendingNotifyClosure *closure = data;
01727
01728 (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
01729 }
01730
01731 static void
01732 d_pending_call_free (void *data)
01733 {
01734 GPendingNotifyClosure *closure = data;
01735
01736 if (closure->free_data_func)
01737 (* closure->free_data_func) (closure->data);
01738
01739 g_free (closure);
01740 }
01741
01742 #define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
01743 do { \
01744 GType valtype; \
01745 int i = 0; \
01746 VALARRAY = g_value_array_new (6); \
01747 valtype = FIRST_ARG_TYPE; \
01748 while (valtype != G_TYPE_INVALID) \
01749 { \
01750 const char *collect_err; \
01751 GValue *val; \
01752 g_value_array_append (VALARRAY, NULL); \
01753 val = g_value_array_get_nth (VALARRAY, i); \
01754 g_value_init (val, valtype); \
01755 collect_err = NULL; \
01756 G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
01757 valtype = va_arg (ARGS, GType); \
01758 i++; \
01759 } \
01760 } while (0)
01761
01762 DBusGProxyCall *
01763 manager_begin_bus_call (DBusGProxyManager *manager,
01764 const char *method,
01765 DBusGProxyCallNotify notify,
01766 gpointer user_data,
01767 GDestroyNotify destroy,
01768 GType first_arg_type,
01769 ...)
01770 {
01771 DBusGProxyCall *call;
01772 DBusGProxyPrivate *priv;
01773 va_list args;
01774 GValueArray *arg_values;
01775
01776 va_start (args, first_arg_type);
01777
01778 if (!manager->bus_proxy)
01779 {
01780 manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
01781 "name", DBUS_SERVICE_DBUS,
01782 "path", DBUS_PATH_DBUS,
01783 "interface", DBUS_INTERFACE_DBUS,
01784 NULL);
01785 priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy);
01786 priv->manager = manager;
01787 }
01788
01789 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
01790
01791 call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values,-1));
01792
01793 g_value_array_free (arg_values);
01794
01795 va_end (args);
01796
01797 return call;
01798 }
01799
01821 GType
01822 dbus_g_proxy_get_type (void)
01823 {
01824 static GType object_type = 0;
01825
01826 if (!object_type)
01827 {
01828 static const GTypeInfo object_info =
01829 {
01830 sizeof (DBusGProxyClass),
01831 (GBaseInitFunc) NULL,
01832 (GBaseFinalizeFunc) NULL,
01833 (GClassInitFunc) dbus_g_proxy_class_init,
01834 NULL,
01835 NULL,
01836 sizeof (DBusGProxy),
01837 0,
01838 (GInstanceInitFunc) dbus_g_proxy_init,
01839 };
01840
01841 object_type = g_type_register_static (G_TYPE_OBJECT,
01842 "DBusGProxy",
01843 &object_info, 0);
01844 }
01845
01846 return object_type;
01847 }
01848
01849 static DBusGProxy*
01850 dbus_g_proxy_new (DBusGConnection *connection,
01851 const char *name,
01852 const char *path_name,
01853 const char *interface_name)
01854 {
01855 DBusGProxy *proxy;
01856
01857 g_assert (connection != NULL);
01858
01859 proxy = g_object_new (DBUS_TYPE_G_PROXY,
01860 "name", name,
01861 "path", path_name,
01862 "interface", interface_name,
01863 "connection", connection, NULL);
01864
01865 return proxy;
01866 }
01867
01896 DBusGProxy*
01897 dbus_g_proxy_new_for_name (DBusGConnection *connection,
01898 const char *name,
01899 const char *path_name,
01900 const char *interface_name)
01901 {
01902 g_return_val_if_fail (connection != NULL, NULL);
01903 g_return_val_if_fail (name != NULL, NULL);
01904 g_return_val_if_fail (path_name != NULL, NULL);
01905 g_return_val_if_fail (interface_name != NULL, NULL);
01906
01907 return dbus_g_proxy_new (connection, name,
01908 path_name, interface_name);
01909 }
01910
01936 DBusGProxy*
01937 dbus_g_proxy_new_for_name_owner (DBusGConnection *connection,
01938 const char *name,
01939 const char *path_name,
01940 const char *interface_name,
01941 GError **error)
01942 {
01943 DBusGProxy *proxy;
01944 char *unique_name;
01945
01946 g_return_val_if_fail (connection != NULL, NULL);
01947 g_return_val_if_fail (name != NULL, NULL);
01948 g_return_val_if_fail (path_name != NULL, NULL);
01949 g_return_val_if_fail (interface_name != NULL, NULL);
01950
01951 if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error)))
01952 return NULL;
01953
01954 proxy = dbus_g_proxy_new (connection, unique_name,
01955 path_name, interface_name);
01956 g_free (unique_name);
01957 return proxy;
01958 }
01959
01971 DBusGProxy*
01972 dbus_g_proxy_new_from_proxy (DBusGProxy *proxy,
01973 const char *interface,
01974 const char *path)
01975 {
01976 DBusGProxyPrivate *priv;
01977
01978 g_return_val_if_fail (proxy != NULL, NULL);
01979
01980 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01981
01982 if (interface == NULL)
01983 interface = priv->interface;
01984 if (path == NULL)
01985 path = priv->path;
01986
01987 return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection),
01988 priv->name,
01989 path, interface);
01990 }
01991
02006 DBusGProxy*
02007 dbus_g_proxy_new_for_peer (DBusGConnection *connection,
02008 const char *path_name,
02009 const char *interface_name)
02010 {
02011 DBusGProxy *proxy;
02012
02013 g_return_val_if_fail (connection != NULL, NULL);
02014 g_return_val_if_fail (path_name != NULL, NULL);
02015 g_return_val_if_fail (interface_name != NULL, NULL);
02016
02017 proxy = dbus_g_proxy_new (connection, NULL,
02018 path_name, interface_name);
02019
02020 return proxy;
02021 }
02022
02036 const char*
02037 dbus_g_proxy_get_bus_name (DBusGProxy *proxy)
02038 {
02039 DBusGProxyPrivate *priv;
02040
02041 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02042 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02043
02044 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02045
02046 return priv->name;
02047 }
02048
02057 const char*
02058 dbus_g_proxy_get_interface (DBusGProxy *proxy)
02059 {
02060 DBusGProxyPrivate *priv;
02061
02062 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02063 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02064
02065 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02066
02067 return priv->interface;
02068 }
02069
02077 void
02078 dbus_g_proxy_set_interface (DBusGProxy *proxy,
02079 const char *interface_name)
02080 {
02081 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02082
02083
02084
02085 dbus_g_proxy_manager_unregister (priv->manager, proxy);
02086 g_free (priv->interface);
02087 priv->interface = g_strdup (interface_name);
02088 dbus_g_proxy_manager_register (priv->manager, proxy);
02089 }
02090
02098 const char*
02099 dbus_g_proxy_get_path (DBusGProxy *proxy)
02100 {
02101 DBusGProxyPrivate *priv;
02102
02103 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02104 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02105
02106 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02107
02108 return priv->path;
02109 }
02110
02111 static DBusMessage *
02112 dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy,
02113 const char *method,
02114 GValueArray *args)
02115 {
02116 DBusMessage *message;
02117 DBusMessageIter msgiter;
02118 guint i;
02119 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02120
02121 message = dbus_message_new_method_call (priv->name,
02122 priv->path,
02123 priv->interface,
02124 method);
02125 if (message == NULL)
02126 goto oom;
02127
02128 dbus_message_iter_init_append (message, &msgiter);
02129 for (i = 0; i < args->n_values; i++)
02130 {
02131 GValue *gvalue;
02132
02133 gvalue = g_value_array_get_nth (args, i);
02134
02135 if (!_dbus_gvalue_marshal (&msgiter, gvalue))
02136 g_assert_not_reached ();
02137 }
02138 return message;
02139 oom:
02140 return NULL;
02141 }
02142
02143 static guint
02144 dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
02145 const char *method,
02146 DBusGProxyCallNotify notify,
02147 gpointer user_data,
02148 GDestroyNotify destroy,
02149 GValueArray *args,
02150 int timeout)
02151 {
02152 DBusMessage *message;
02153 DBusPendingCall *pending;
02154 GPendingNotifyClosure *closure;
02155 guint call_id;
02156 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02157
02158 pending = NULL;
02159
02160 message = dbus_g_proxy_marshal_args_to_message (proxy, method, args);
02161 if (!message)
02162 goto oom;
02163
02164 if (!dbus_connection_send_with_reply (priv->manager->connection,
02165 message,
02166 &pending,
02167 timeout))
02168 goto oom;
02169 dbus_message_unref (message);
02170 g_assert (pending != NULL);
02171
02172 call_id = ++priv->call_id_counter;
02173
02174 if (notify != NULL)
02175 {
02176 closure = g_new (GPendingNotifyClosure, 1);
02177 closure->proxy = proxy;
02178 closure->call_id = call_id;
02179 closure->func = notify;
02180 closure->data = user_data;
02181 closure->free_data_func = destroy;
02182 dbus_pending_call_set_notify (pending, d_pending_call_notify,
02183 closure,
02184 d_pending_call_free);
02185 }
02186
02187 g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending);
02188
02189 return call_id;
02190 oom:
02191 g_error ("Out of memory");
02192 return 0;
02193 }
02194
02195 static gboolean
02196 dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
02197 guint call_id,
02198 GError **error,
02199 GType first_arg_type,
02200 va_list args)
02201 {
02202 DBusMessage *reply;
02203 DBusMessageIter msgiter;
02204 DBusError derror;
02205 va_list args_unwind;
02206 guint over;
02207 int n_retvals_processed;
02208 gboolean ret;
02209 GType valtype;
02210 DBusPendingCall *pending;
02211 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02212
02213 reply = NULL;
02214 ret = FALSE;
02215 n_retvals_processed = 0;
02216 over = 0;
02217
02218 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02219
02220 dbus_pending_call_block (pending);
02221 reply = dbus_pending_call_steal_reply (pending);
02222
02223 g_assert (reply != NULL);
02224
02225 dbus_error_init (&derror);
02226
02227 switch (dbus_message_get_type (reply))
02228 {
02229 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
02230 dbus_message_iter_init (reply, &msgiter);
02231 valtype = first_arg_type;
02232 while (valtype != G_TYPE_INVALID)
02233 {
02234 int arg_type;
02235 gpointer return_storage;
02236 GValue gvalue = { 0, };
02237 DBusGValueMarshalCtx context;
02238
02239 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
02240 context.proxy = proxy;
02241
02242 arg_type = dbus_message_iter_get_arg_type (&msgiter);
02243 if (arg_type == DBUS_TYPE_INVALID)
02244 {
02245 g_set_error (error, DBUS_GERROR,
02246 DBUS_GERROR_INVALID_ARGS,
02247 _("Too few arguments in reply"));
02248 goto out;
02249 }
02250
02251 return_storage = va_arg (args, gpointer);
02252 if (return_storage == NULL)
02253 goto next;
02254
02255
02256
02257
02258 if (arg_type == DBUS_TYPE_VARIANT
02259 && g_type_is_a (valtype, G_TYPE_VALUE))
02260 {
02261 if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL))
02262 {
02263 g_set_error (error,
02264 DBUS_GERROR,
02265 DBUS_GERROR_INVALID_ARGS,
02266 _("Couldn't convert argument, expected \"%s\""),
02267 g_type_name (valtype));
02268 goto out;
02269 }
02270 }
02271 else
02272 {
02273 g_value_init (&gvalue, valtype);
02274
02275 if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error))
02276 goto out;
02277
02278
02279 if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage))
02280 g_assert_not_reached ();
02281
02282 }
02283
02284 next:
02285 n_retvals_processed++;
02286 dbus_message_iter_next (&msgiter);
02287 valtype = va_arg (args, GType);
02288 }
02289
02290 while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID)
02291 {
02292 over++;
02293 dbus_message_iter_next (&msgiter);
02294 }
02295
02296 if (over > 0)
02297 {
02298 g_set_error (error, DBUS_GERROR,
02299 DBUS_GERROR_INVALID_ARGS,
02300 _("Too many arguments in reply; expected %d, got %d"),
02301 n_retvals_processed, over);
02302 goto out;
02303 }
02304 break;
02305 case DBUS_MESSAGE_TYPE_ERROR:
02306 dbus_set_error_from_message (&derror, reply);
02307 dbus_set_g_error (error, &derror);
02308 dbus_error_free (&derror);
02309 goto out;
02310 break;
02311 default:
02312 dbus_set_error (&derror, DBUS_ERROR_FAILED,
02313 "Reply was neither a method return nor an exception");
02314 dbus_set_g_error (error, &derror);
02315 dbus_error_free (&derror);
02316 goto out;
02317 break;
02318 }
02319
02320 ret = TRUE;
02321 out:
02322 va_end (args);
02323
02324 if (ret == FALSE)
02325 {
02326 int i;
02327 for (i = 0; i < n_retvals_processed; i++)
02328 {
02329 gpointer retval;
02330
02331 retval = va_arg (args_unwind, gpointer);
02332
02333 g_free (retval);
02334 }
02335 }
02336 va_end (args_unwind);
02337
02338 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02339
02340 if (reply)
02341 dbus_message_unref (reply);
02342 return ret;
02343 }
02344
02367 DBusGProxyCall *
02368 dbus_g_proxy_begin_call (DBusGProxy *proxy,
02369 const char *method,
02370 DBusGProxyCallNotify notify,
02371 gpointer user_data,
02372 GDestroyNotify destroy,
02373 GType first_arg_type,
02374 ...)
02375 {
02376 guint call_id;
02377 va_list args;
02378 GValueArray *arg_values;
02379
02380 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02381 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02382
02383 va_start (args, first_arg_type);
02384
02385 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02386
02387 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,-1);
02388
02389 g_value_array_free (arg_values);
02390
02391 va_end (args);
02392
02393 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02394 }
02395
02419 DBusGProxyCall *
02420 dbus_g_proxy_begin_call_with_timeout (DBusGProxy *proxy,
02421 const char *method,
02422 DBusGProxyCallNotify notify,
02423 gpointer user_data,
02424 GDestroyNotify destroy,
02425 int timeout,
02426 GType first_arg_type,
02427 ...)
02428 {
02429 guint call_id;
02430 va_list args;
02431 GValueArray *arg_values;
02432
02433 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02434 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02435
02436 va_start (args, first_arg_type);
02437
02438 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02439
02440 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,timeout);
02441
02442 g_value_array_free (arg_values);
02443
02444 va_end (args);
02445
02446 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02447 }
02448
02471 gboolean
02472 dbus_g_proxy_end_call (DBusGProxy *proxy,
02473 DBusGProxyCall *call,
02474 GError **error,
02475 GType first_arg_type,
02476 ...)
02477 {
02478 gboolean ret;
02479 va_list args;
02480
02481 va_start (args, first_arg_type);
02482
02483 ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
02484
02485 va_end (args);
02486
02487 return ret;
02488 }
02489
02506 gboolean
02507 dbus_g_proxy_call (DBusGProxy *proxy,
02508 const char *method,
02509 GError **error,
02510 GType first_arg_type,
02511 ...)
02512 {
02513 gboolean ret;
02514 guint call_id;
02515 va_list args;
02516 GValueArray *in_args;
02517
02518 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02519 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02520
02521 va_start (args, first_arg_type);
02522
02523 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02524
02525 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,-1);
02526
02527 g_value_array_free (in_args);
02528
02529 first_arg_type = va_arg (args, GType);
02530 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02531
02532 va_end (args);
02533
02534 return ret;
02535 }
02536
02554 gboolean
02555 dbus_g_proxy_call_with_timeout (DBusGProxy *proxy,
02556 const char *method,
02557 int timeout,
02558 GError **error,
02559 GType first_arg_type,
02560 ...)
02561 {
02562 gboolean ret;
02563 guint call_id;
02564 va_list args;
02565 GValueArray *in_args;
02566
02567 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02568 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02569
02570 va_start (args, first_arg_type);
02571
02572 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02573
02574 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,timeout);
02575
02576 g_value_array_free (in_args);
02577
02578 first_arg_type = va_arg (args, GType);
02579 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02580
02581 va_end (args);
02582
02583 return ret;
02584 }
02585
02598 void
02599 dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
02600 const char *method,
02601 GType first_arg_type,
02602 ...)
02603 {
02604 DBusMessage *message;
02605 va_list args;
02606 GValueArray *in_args;
02607 DBusGProxyPrivate *priv;
02608
02609 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02610 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02611
02612 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02613
02614 va_start (args, first_arg_type);
02615 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02616
02617 message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args);
02618
02619 g_value_array_free (in_args);
02620 va_end (args);
02621
02622 if (!message)
02623 goto oom;
02624
02625 dbus_message_set_no_reply (message, TRUE);
02626
02627 if (!dbus_connection_send (priv->manager->connection,
02628 message,
02629 NULL))
02630 goto oom;
02631 dbus_message_unref (message);
02632 return;
02633
02634 oom:
02635 g_error ("Out of memory");
02636 }
02637
02648 void
02649 dbus_g_proxy_cancel_call (DBusGProxy *proxy,
02650 DBusGProxyCall *call)
02651 {
02652 guint call_id;
02653 DBusPendingCall *pending;
02654 DBusGProxyPrivate *priv;
02655
02656 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02657 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02658
02659 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02660
02661 call_id = DBUS_G_PROXY_CALL_TO_ID (call);
02662
02663 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02664 g_return_if_fail (pending != NULL);
02665
02666 dbus_pending_call_cancel (pending);
02667
02668 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02669 }
02670
02691 void
02692 dbus_g_proxy_send (DBusGProxy *proxy,
02693 DBusMessage *message,
02694 dbus_uint32_t *client_serial)
02695 {
02696 DBusGProxyPrivate *priv;
02697
02698 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02699 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02700
02701 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02702
02703 if (priv->name)
02704 {
02705 if (!dbus_message_set_destination (message, priv->name))
02706 g_error ("Out of memory");
02707 }
02708 if (priv->path)
02709 {
02710 if (!dbus_message_set_path (message, priv->path))
02711 g_error ("Out of memory");
02712 }
02713 if (priv->interface)
02714 {
02715 if (!dbus_message_set_interface (message, priv->interface))
02716 g_error ("Out of memory");
02717 }
02718
02719 if (!dbus_connection_send (priv->manager->connection, message, client_serial))
02720 g_error ("Out of memory\n");
02721 }
02722
02723 static void
02724 array_free_all (gpointer array)
02725 {
02726 g_array_free (array, TRUE);
02727 }
02728
02739 void
02740 dbus_g_proxy_add_signal (DBusGProxy *proxy,
02741 const char *signal_name,
02742 GType first_type,
02743 ...)
02744 {
02745 GQuark q;
02746 char *name;
02747 GArray *gtypesig;
02748 GType gtype;
02749 va_list args;
02750 DBusGProxyPrivate *priv;
02751
02752 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02753 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02754 g_return_if_fail (signal_name != NULL);
02755
02756 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02757
02758 name = create_signal_name (priv->interface, signal_name);
02759
02760 q = g_quark_from_string (name);
02761
02762 g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL);
02763
02764 gtypesig = g_array_new (FALSE, TRUE, sizeof (GType));
02765
02766 va_start (args, first_type);
02767 gtype = first_type;
02768 while (gtype != G_TYPE_INVALID)
02769 {
02770 g_array_append_val (gtypesig, gtype);
02771 gtype = va_arg (args, GType);
02772 }
02773 va_end (args);
02774
02775 #ifndef G_DISABLE_CHECKS
02776 if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL)
02777 g_warning ("No marshaller for signature of signal '%s'", signal_name);
02778 #endif
02779
02780
02781 g_datalist_id_set_data_full (&priv->signal_signatures,
02782 q, gtypesig,
02783 array_free_all);
02784
02785 g_free (name);
02786 }
02787
02800 void
02801 dbus_g_proxy_connect_signal (DBusGProxy *proxy,
02802 const char *signal_name,
02803 GCallback handler,
02804 void *data,
02805 GClosureNotify free_data_func)
02806 {
02807 char *name;
02808 GClosure *closure;
02809 GQuark q;
02810 DBusGProxyPrivate *priv;
02811
02812 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02813 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02814 g_return_if_fail (signal_name != NULL);
02815 g_return_if_fail (handler != NULL);
02816
02817 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02818 name = create_signal_name (priv->interface, signal_name);
02819
02820 q = g_quark_try_string (name);
02821
02822 #ifndef G_DISABLE_CHECKS
02823 if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL)
02824 {
02825 g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name);
02826 g_free (name);
02827 return;
02828 }
02829 #endif
02830
02831 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
02832
02833 g_signal_connect_closure_by_id (G_OBJECT (proxy),
02834 signals[RECEIVED],
02835 q,
02836 closure, FALSE);
02837
02838 g_free (name);
02839 }
02840
02851 void
02852 dbus_g_proxy_disconnect_signal (DBusGProxy *proxy,
02853 const char *signal_name,
02854 GCallback handler,
02855 void *data)
02856 {
02857 char *name;
02858 GQuark q;
02859 DBusGProxyPrivate *priv;
02860
02861 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02862 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02863 g_return_if_fail (signal_name != NULL);
02864 g_return_if_fail (handler != NULL);
02865
02866 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02867 name = create_signal_name (priv->interface, signal_name);
02868
02869 q = g_quark_try_string (name);
02870
02871 if (q != 0)
02872 {
02873 g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
02874 G_SIGNAL_MATCH_DETAIL |
02875 G_SIGNAL_MATCH_FUNC |
02876 G_SIGNAL_MATCH_DATA,
02877 signals[RECEIVED],
02878 q,
02879 NULL,
02880 G_CALLBACK (handler), data);
02881 }
02882 else
02883 {
02884 g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
02885 name);
02886 }
02887
02888 g_free (name);
02889 }
02890
02893 #ifdef DBUS_BUILD_TESTS
02894
02900 gboolean
02901 _dbus_g_proxy_test (void)
02902 {
02903
02904
02905 return TRUE;
02906 }
02907
02908 #endif