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 if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
00808 g_warning ("Couldn't get name owner (%s): %s",
00809 dbus_g_error_get_name (error),
00810 error->message);
00811 else
00812 g_warning ("Couldn't get name owner (code %d): %s",
00813 error->code, error->message);
00814 g_clear_error (&error);
00815 goto out;
00816 }
00817 else
00818 {
00819 dbus_g_proxy_manager_monitor_name_owner (priv->manager, owner, priv->name);
00820 priv->associated = TRUE;
00821 }
00822
00823 out:
00824 priv->name_call = NULL;
00825 UNLOCK_MANAGER (priv->manager);
00826 g_free (owner);
00827 }
00828
00829 static char *
00830 get_name_owner (DBusConnection *connection,
00831 const char *name,
00832 GError **error)
00833 {
00834 DBusError derror;
00835 DBusMessage *request, *reply;
00836 char *base_name;
00837
00838 dbus_error_init (&derror);
00839
00840 base_name = NULL;
00841 reply = NULL;
00842
00843 request = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
00844 DBUS_PATH_DBUS,
00845 DBUS_INTERFACE_DBUS,
00846 "GetNameOwner");
00847 if (request == NULL)
00848 g_error ("Out of memory");
00849
00850 if (!dbus_message_append_args (request,
00851 DBUS_TYPE_STRING, &name,
00852 DBUS_TYPE_INVALID))
00853 g_error ("Out of memory");
00854
00855 reply =
00856 dbus_connection_send_with_reply_and_block (connection,
00857 request,
00858 2000, &derror);
00859 if (reply == NULL)
00860 goto error;
00861
00862 if (dbus_set_error_from_message (&derror, reply))
00863 goto error;
00864
00865 if (!dbus_message_get_args (reply, &derror,
00866 DBUS_TYPE_STRING, &base_name,
00867 DBUS_TYPE_INVALID))
00868 goto error;
00869
00870 base_name = g_strdup (base_name);
00871 goto out;
00872
00873 error:
00874 g_assert (dbus_error_is_set (&derror));
00875 dbus_set_g_error (error, &derror);
00876 dbus_error_free (&derror);
00877
00878 out:
00879 if (request)
00880 dbus_message_unref (request);
00881 if (reply)
00882 dbus_message_unref (reply);
00883
00884 return base_name;
00885 }
00886
00887
00888 static void
00889 dbus_g_proxy_manager_register (DBusGProxyManager *manager,
00890 DBusGProxy *proxy)
00891 {
00892 DBusGProxyList *list;
00893 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00894
00895 LOCK_MANAGER (manager);
00896
00897 if (manager->proxy_lists == NULL)
00898 {
00899 g_assert (manager->owner_names == NULL);
00900
00901 list = NULL;
00902 manager->proxy_lists = g_hash_table_new_full (tristring_hash,
00903 tristring_equal,
00904 NULL,
00905 (GFreeFunc) g_proxy_list_free);
00906 manager->owner_names = g_hash_table_new_full (g_str_hash,
00907 g_str_equal,
00908 g_free,
00909 NULL);
00910
00911
00912
00913 dbus_bus_add_match (manager->connection,
00914 "type='signal',sender='" DBUS_SERVICE_DBUS
00915 "',path='" DBUS_PATH_DBUS
00916 "',interface='" DBUS_INTERFACE_DBUS
00917 "',member='NameOwnerChanged'",
00918 NULL);
00919 }
00920 else
00921 {
00922 char *tri;
00923
00924 tri = tristring_from_proxy (proxy);
00925
00926 list = g_hash_table_lookup (manager->proxy_lists, tri);
00927
00928 g_free (tri);
00929 }
00930
00931 if (list == NULL)
00932 {
00933 list = g_proxy_list_new (proxy);
00934
00935 g_hash_table_replace (manager->proxy_lists,
00936 list->name, list);
00937 }
00938
00939 if (list->proxies == NULL && priv->name)
00940 {
00941
00942
00943
00944
00945 char *rule;
00946
00947 rule = g_proxy_get_match_rule (proxy);
00948
00949
00950
00951
00952 dbus_bus_add_match (manager->connection,
00953 rule, NULL);
00954
00955 g_free (rule);
00956 }
00957
00958 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00959
00960 list->proxies = g_slist_prepend (list->proxies, proxy);
00961
00962 if (!priv->for_owner)
00963 {
00964 const char *owner;
00965 DBusGProxyNameOwnerInfo *info;
00966
00967 if (!dbus_g_proxy_manager_lookup_name_owner (manager, priv->name, &info, &owner))
00968 {
00969 priv->name_call = manager_begin_bus_call (manager, "GetNameOwner",
00970 got_name_owner_cb,
00971 proxy, NULL,
00972 G_TYPE_STRING,
00973 priv->name,
00974 G_TYPE_INVALID);
00975
00976 priv->associated = FALSE;
00977 }
00978 else
00979 {
00980 info->refcount++;
00981 priv->associated = TRUE;
00982 }
00983 }
00984
00985 UNLOCK_MANAGER (manager);
00986 }
00987
00988 static void
00989 dbus_g_proxy_manager_unregister (DBusGProxyManager *manager,
00990 DBusGProxy *proxy)
00991 {
00992 DBusGProxyList *list;
00993 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
00994 char *tri;
00995
00996 LOCK_MANAGER (manager);
00997
00998 #ifndef G_DISABLE_CHECKS
00999 if (manager->proxy_lists == NULL)
01000 {
01001 g_warning ("Trying to unregister a proxy but there aren't any registered");
01002 return;
01003 }
01004 #endif
01005
01006 tri = tristring_from_proxy (proxy);
01007
01008 list = g_hash_table_lookup (manager->proxy_lists, tri);
01009
01010 #ifndef G_DISABLE_CHECKS
01011 if (list == NULL)
01012 {
01013 g_warning ("Trying to unregister a proxy but it isn't registered");
01014 return;
01015 }
01016 #endif
01017
01018 g_assert (g_slist_find (list->proxies, proxy) != NULL);
01019
01020 list->proxies = g_slist_remove (list->proxies, proxy);
01021
01022 g_assert (g_slist_find (list->proxies, proxy) == NULL);
01023
01024 if (!priv->for_owner)
01025 {
01026 if (!priv->associated)
01027 {
01028 GSList *link;
01029
01030 if (priv->name_call != 0)
01031 {
01032 dbus_g_proxy_cancel_call (manager->bus_proxy, priv->name_call);
01033 priv->name_call = 0;
01034 }
01035 else
01036 {
01037 link = g_slist_find (manager->unassociated_proxies, proxy);
01038 g_assert (link != NULL);
01039
01040 manager->unassociated_proxies = g_slist_delete_link (manager->unassociated_proxies, link);
01041 }
01042 }
01043 else
01044 {
01045 g_assert (priv->name_call == 0);
01046
01047 dbus_g_proxy_manager_unmonitor_name_owner (manager, priv->name);
01048 }
01049 }
01050
01051 if (list->proxies == NULL)
01052 {
01053 char *rule;
01054 g_hash_table_remove (manager->proxy_lists,
01055 tri);
01056 list = NULL;
01057
01058 rule = g_proxy_get_match_rule (proxy);
01059 dbus_bus_remove_match (manager->connection,
01060 rule, NULL);
01061 g_free (rule);
01062 }
01063
01064 if (g_hash_table_size (manager->proxy_lists) == 0)
01065 {
01066 g_hash_table_destroy (manager->proxy_lists);
01067 manager->proxy_lists = NULL;
01068
01069
01070 dbus_bus_remove_match (manager->connection,
01071 "type='signal',sender='" DBUS_SERVICE_DBUS
01072 "',path='" DBUS_PATH_DBUS
01073 "',interface='" DBUS_INTERFACE_DBUS
01074 "',member='NameOwnerChanged'",
01075 NULL);
01076 }
01077
01078 g_free (tri);
01079
01080 UNLOCK_MANAGER (manager);
01081 }
01082
01083 static void
01084 list_proxies_foreach (gpointer key,
01085 gpointer value,
01086 gpointer user_data)
01087 {
01088 DBusGProxyList *list;
01089 GSList **ret;
01090 GSList *tmp;
01091
01092 list = value;
01093 ret = user_data;
01094
01095 tmp = list->proxies;
01096 while (tmp != NULL)
01097 {
01098 DBusGProxy *proxy = DBUS_G_PROXY (tmp->data);
01099
01100 g_object_ref (proxy);
01101 *ret = g_slist_prepend (*ret, proxy);
01102
01103 tmp = tmp->next;
01104 }
01105 }
01106
01107 static GSList*
01108 dbus_g_proxy_manager_list_all (DBusGProxyManager *manager)
01109 {
01110 GSList *ret;
01111
01112 ret = NULL;
01113
01114 if (manager->proxy_lists)
01115 {
01116 g_hash_table_foreach (manager->proxy_lists,
01117 list_proxies_foreach,
01118 &ret);
01119 }
01120
01121 return ret;
01122 }
01123
01124 static DBusHandlerResult
01125 dbus_g_proxy_manager_filter (DBusConnection *connection,
01126 DBusMessage *message,
01127 void *user_data)
01128 {
01129 DBusGProxyManager *manager;
01130
01131 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
01132 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01133
01134 manager = user_data;
01135
01136 dbus_g_proxy_manager_ref (manager);
01137
01138 LOCK_MANAGER (manager);
01139
01140 if (dbus_message_is_signal (message,
01141 DBUS_INTERFACE_LOCAL,
01142 "Disconnected"))
01143 {
01144
01145
01146
01147 GSList *all;
01148 GSList *tmp;
01149
01150 all = dbus_g_proxy_manager_list_all (manager);
01151
01152 tmp = all;
01153 while (tmp != NULL)
01154 {
01155 DBusGProxy *proxy;
01156
01157 proxy = DBUS_G_PROXY (tmp->data);
01158
01159 UNLOCK_MANAGER (manager);
01160 dbus_g_proxy_destroy (proxy);
01161 g_object_unref (G_OBJECT (proxy));
01162 LOCK_MANAGER (manager);
01163
01164 tmp = tmp->next;
01165 }
01166
01167 g_slist_free (all);
01168
01169 #ifndef G_DISABLE_CHECKS
01170 if (manager->proxy_lists != NULL)
01171 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.");
01172 #endif
01173 }
01174 else
01175 {
01176 char *tri;
01177 GSList *full_list;
01178 GSList *owned_names;
01179 GSList *tmp;
01180 const char *sender;
01181
01182
01183 if (dbus_message_is_signal (message,
01184 DBUS_INTERFACE_DBUS,
01185 "NameOwnerChanged"))
01186 {
01187 const char *name;
01188 const char *prev_owner;
01189 const char *new_owner;
01190 DBusError derr;
01191
01192 dbus_error_init (&derr);
01193 if (!dbus_message_get_args (message,
01194 &derr,
01195 DBUS_TYPE_STRING,
01196 &name,
01197 DBUS_TYPE_STRING,
01198 &prev_owner,
01199 DBUS_TYPE_STRING,
01200 &new_owner,
01201 DBUS_TYPE_INVALID))
01202 {
01203
01204 dbus_error_free (&derr);
01205 }
01206 else if (manager->owner_names != NULL)
01207 {
01208 dbus_g_proxy_manager_replace_name_owner (manager, name, prev_owner, new_owner);
01209 }
01210 }
01211
01212 sender = dbus_message_get_sender (message);
01213
01214
01215 g_assert (dbus_message_get_path (message) != NULL);
01216 g_assert (dbus_message_get_interface (message) != NULL);
01217 g_assert (dbus_message_get_member (message) != NULL);
01218
01219 tri = tristring_from_message (message);
01220
01221 if (manager->proxy_lists)
01222 {
01223 DBusGProxyList *owner_list;
01224 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01225 if (owner_list)
01226 full_list = g_slist_copy (owner_list->proxies);
01227 else
01228 full_list = NULL;
01229 }
01230 else
01231 full_list = NULL;
01232
01233 g_free (tri);
01234
01235 if (manager->owner_names && sender)
01236 {
01237 owned_names = g_hash_table_lookup (manager->owner_names, sender);
01238 for (tmp = owned_names; tmp; tmp = tmp->next)
01239 {
01240 DBusGProxyList *owner_list;
01241 DBusGProxyNameOwnerInfo *nameinfo;
01242
01243 nameinfo = tmp->data;
01244 g_assert (nameinfo->refcount > 0);
01245 tri = tristring_alloc_from_strings (0, nameinfo->name,
01246 dbus_message_get_path (message),
01247 dbus_message_get_interface (message));
01248
01249 owner_list = g_hash_table_lookup (manager->proxy_lists, tri);
01250 if (owner_list != NULL)
01251 full_list = g_slist_concat (full_list, g_slist_copy (owner_list->proxies));
01252 g_free (tri);
01253 }
01254 }
01255
01256 #if 0
01257 g_print ("proxy got %s,%s,%s = list %p\n",
01258 tri,
01259 tri + strlen (tri) + 1,
01260 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
01261 list);
01262 #endif
01263
01264
01265
01266 g_slist_foreach (full_list, (GFunc) g_object_ref, NULL);
01267
01268 for (tmp = full_list; tmp; tmp = tmp->next)
01269 {
01270 DBusGProxy *proxy;
01271
01272 proxy = DBUS_G_PROXY (tmp->data);
01273
01274 UNLOCK_MANAGER (manager);
01275 dbus_g_proxy_emit_remote_signal (proxy, message);
01276 g_object_unref (G_OBJECT (proxy));
01277 LOCK_MANAGER (manager);
01278 }
01279 g_slist_free (full_list);
01280 }
01281
01282 UNLOCK_MANAGER (manager);
01283 dbus_g_proxy_manager_unref (manager);
01284
01285
01286
01287
01288 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01289 }
01290
01291
01292
01293
01294 #define DBUS_G_PROXY_DESTROYED(proxy) (DBUS_G_PROXY_GET_PRIVATE(proxy)->manager == NULL)
01295
01296 static void
01297 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01298 GValue *return_value,
01299 guint n_param_values,
01300 const GValue *param_values,
01301 gpointer invocation_hint,
01302 gpointer marshal_data);
01303 enum
01304 {
01305 PROP_0,
01306 PROP_NAME,
01307 PROP_PATH,
01308 PROP_INTERFACE,
01309 PROP_CONNECTION
01310 };
01311
01312 enum
01313 {
01314 DESTROY,
01315 RECEIVED,
01316 LAST_SIGNAL
01317 };
01318
01319 static void *parent_class;
01320 static guint signals[LAST_SIGNAL] = { 0 };
01321
01322 static void
01323 dbus_g_proxy_init (DBusGProxy *proxy)
01324 {
01325 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01326
01327 g_datalist_init (&priv->signal_signatures);
01328 priv->pending_calls = g_hash_table_new_full (NULL, NULL, NULL,
01329 (GDestroyNotify) dbus_pending_call_unref);
01330 priv->name_call = 0;
01331 priv->associated = FALSE;
01332 }
01333
01334 static GObject *
01335 dbus_g_proxy_constructor (GType type,
01336 guint n_construct_properties,
01337 GObjectConstructParam *construct_properties)
01338 {
01339 DBusGProxy *proxy;
01340 DBusGProxyClass *klass;
01341 GObjectClass *parent_class;
01342 DBusGProxyPrivate *priv;
01343
01344 klass = DBUS_G_PROXY_CLASS (g_type_class_peek (DBUS_TYPE_G_PROXY));
01345
01346 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
01347
01348 proxy = DBUS_G_PROXY (parent_class->constructor (type, n_construct_properties,
01349 construct_properties));
01350
01351 priv = DBUS_G_PROXY_GET_PRIVATE (proxy);
01352
01353
01354
01355
01356
01357
01358 g_assert (priv->path != NULL);
01359 g_assert (priv->interface != NULL);
01360
01361 if (priv->manager != NULL)
01362 {
01363 dbus_g_proxy_manager_register (priv->manager, proxy);
01364 }
01365
01366 return G_OBJECT (proxy);
01367 }
01368
01369 static void
01370 dbus_g_proxy_class_init (DBusGProxyClass *klass)
01371 {
01372 GObjectClass *object_class = G_OBJECT_CLASS (klass);
01373
01374 parent_class = g_type_class_peek_parent (klass);
01375
01376 g_type_class_add_private (klass, sizeof (DBusGProxyPrivate));
01377
01378 object_class->set_property = dbus_g_proxy_set_property;
01379 object_class->get_property = dbus_g_proxy_get_property;
01380
01381 g_object_class_install_property (object_class,
01382 PROP_NAME,
01383 g_param_spec_string ("name",
01384 "name",
01385 "name",
01386 NULL,
01387 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01388
01389 g_object_class_install_property (object_class,
01390 PROP_PATH,
01391 g_param_spec_string ("path",
01392 "path",
01393 "path",
01394 NULL,
01395 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01396
01397 g_object_class_install_property (object_class,
01398 PROP_INTERFACE,
01399 g_param_spec_string ("interface",
01400 "interface",
01401 "interface",
01402 NULL,
01403 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01404
01405 g_object_class_install_property (object_class,
01406 PROP_CONNECTION,
01407 g_param_spec_boxed ("connection",
01408 "connection",
01409 "connection",
01410 DBUS_TYPE_G_CONNECTION,
01411 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
01412
01413 object_class->finalize = dbus_g_proxy_finalize;
01414 object_class->dispose = dbus_g_proxy_dispose;
01415 object_class->constructor = dbus_g_proxy_constructor;
01416
01417 signals[DESTROY] =
01418 g_signal_new ("destroy",
01419 G_OBJECT_CLASS_TYPE (object_class),
01420 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
01421 0,
01422 NULL, NULL,
01423 g_cclosure_marshal_VOID__VOID,
01424 G_TYPE_NONE, 0);
01425
01426 signals[RECEIVED] =
01427 g_signal_new ("received",
01428 G_OBJECT_CLASS_TYPE (object_class),
01429 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
01430 0,
01431 NULL, NULL,
01432 marshal_dbus_message_to_g_marshaller,
01433 G_TYPE_NONE, 2, DBUS_TYPE_MESSAGE, G_TYPE_POINTER);
01434 }
01435
01436 static gboolean
01437 cancel_pending_call (gpointer key, gpointer val, gpointer data)
01438 {
01439 DBusPendingCall *pending = val;
01440
01441 dbus_pending_call_cancel (pending);
01442
01443 return TRUE;
01444 }
01445
01446 static void
01447 dbus_g_proxy_dispose (GObject *object)
01448 {
01449 DBusGProxy *proxy = DBUS_G_PROXY (object);
01450 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01451
01452 if (priv->pending_calls == NULL)
01453 {
01454 return;
01455 }
01456
01457
01458 g_hash_table_foreach_remove (priv->pending_calls, cancel_pending_call, NULL);
01459 g_hash_table_destroy (priv->pending_calls);
01460 priv->pending_calls = NULL;
01461
01462 if (priv->manager && proxy != priv->manager->bus_proxy)
01463 {
01464 dbus_g_proxy_manager_unregister (priv->manager, proxy);
01465 dbus_g_proxy_manager_unref (priv->manager);
01466 }
01467 priv->manager = NULL;
01468
01469 g_datalist_clear (&priv->signal_signatures);
01470
01471 g_signal_emit (object, signals[DESTROY], 0);
01472
01473 G_OBJECT_CLASS (parent_class)->dispose (object);
01474 }
01475
01476 static void
01477 dbus_g_proxy_finalize (GObject *object)
01478 {
01479 DBusGProxy *proxy = DBUS_G_PROXY (object);
01480 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01481
01482 g_return_if_fail (DBUS_G_PROXY_DESTROYED (proxy));
01483
01484 g_free (priv->name);
01485 g_free (priv->path);
01486 g_free (priv->interface);
01487
01488 G_OBJECT_CLASS (parent_class)->finalize (object);
01489 }
01490
01491 static void
01492 dbus_g_proxy_destroy (DBusGProxy *proxy)
01493 {
01494
01495
01496
01497 g_object_run_dispose (G_OBJECT (proxy));
01498 }
01499
01500 static void
01501 dbus_g_proxy_set_property (GObject *object,
01502 guint prop_id,
01503 const GValue *value,
01504 GParamSpec *pspec)
01505 {
01506 DBusGProxy *proxy = DBUS_G_PROXY (object);
01507 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01508 DBusGConnection *connection;
01509
01510 switch (prop_id)
01511 {
01512 case PROP_NAME:
01513 priv->name = g_strdup (g_value_get_string (value));
01514 if (priv->name)
01515 priv->for_owner = (priv->name[0] == ':');
01516 else
01517 priv->for_owner = TRUE;
01518 break;
01519 case PROP_PATH:
01520 priv->path = g_strdup (g_value_get_string (value));
01521 break;
01522 case PROP_INTERFACE:
01523 priv->interface = g_strdup (g_value_get_string (value));
01524 break;
01525 case PROP_CONNECTION:
01526 connection = g_value_get_boxed (value);
01527 if (connection != NULL)
01528 {
01529 priv->manager = dbus_g_proxy_manager_get (DBUS_CONNECTION_FROM_G_CONNECTION (connection));
01530 }
01531 break;
01532 default:
01533 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01534 break;
01535 }
01536 }
01537
01538 static void
01539 dbus_g_proxy_get_property (GObject *object,
01540 guint prop_id,
01541 GValue *value,
01542 GParamSpec *pspec)
01543 {
01544 DBusGProxy *proxy = DBUS_G_PROXY (object);
01545 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01546
01547 switch (prop_id)
01548 {
01549 case PROP_NAME:
01550 g_value_set_string (value, priv->name);
01551 break;
01552 case PROP_PATH:
01553 g_value_set_string (value, priv->path);
01554 break;
01555 case PROP_INTERFACE:
01556 g_value_set_string (value, priv->interface);
01557 break;
01558 case PROP_CONNECTION:
01559 g_value_set_boxed (value, DBUS_G_CONNECTION_FROM_CONNECTION(priv->manager->connection));
01560 break;
01561 default:
01562 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
01563 break;
01564 }
01565 }
01566
01567
01568
01569
01570
01571
01572 static char*
01573 create_signal_name (const char *interface,
01574 const char *signal)
01575 {
01576 GString *str;
01577 char *p;
01578
01579 str = g_string_new (interface);
01580
01581 g_string_append (str, "-");
01582
01583 g_string_append (str, signal);
01584
01585
01586 p = str->str;
01587 while (*p)
01588 {
01589 if (*p == '.')
01590 *p = '-';
01591 ++p;
01592 }
01593
01594 return g_string_free (str, FALSE);
01595 }
01596
01597 static void
01598 marshal_dbus_message_to_g_marshaller (GClosure *closure,
01599 GValue *return_value,
01600 guint n_param_values,
01601 const GValue *param_values,
01602 gpointer invocation_hint,
01603 gpointer marshal_data)
01604 {
01605
01606
01607
01608
01609
01610 #define MAX_SIGNATURE_ARGS 20
01611 GValueArray *value_array;
01612 GSignalCMarshaller c_marshaller;
01613 DBusGProxy *proxy;
01614 DBusMessage *message;
01615 GArray *gsignature;
01616 const GType *types;
01617 DBusGProxyPrivate *priv;
01618
01619 g_assert (n_param_values == 3);
01620
01621 proxy = g_value_get_object (¶m_values[0]);
01622 message = g_value_get_boxed (¶m_values[1]);
01623 gsignature = g_value_get_pointer (¶m_values[2]);
01624
01625 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
01626 g_return_if_fail (message != NULL);
01627 g_return_if_fail (gsignature != NULL);
01628
01629 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01630
01631 c_marshaller = _dbus_gobject_lookup_marshaller (G_TYPE_NONE, gsignature->len,
01632 (GType*) gsignature->data);
01633
01634 g_return_if_fail (c_marshaller != NULL);
01635
01636 {
01637 DBusGValueMarshalCtx context;
01638 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
01639 context.proxy = proxy;
01640
01641 types = (const GType*) gsignature->data;
01642 value_array = _dbus_gvalue_demarshal_message (&context, message,
01643 gsignature->len, types, NULL);
01644 }
01645
01646 if (value_array == NULL)
01647 return;
01648
01649 g_value_array_prepend (value_array, NULL);
01650 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_FROM_INSTANCE (proxy));
01651 g_value_set_instance (g_value_array_get_nth (value_array, 0), proxy);
01652
01653 (* c_marshaller) (closure, return_value, value_array->n_values,
01654 value_array->values, invocation_hint, marshal_data);
01655
01656 g_value_array_free (value_array);
01657 }
01658
01659 static void
01660 dbus_g_proxy_emit_remote_signal (DBusGProxy *proxy,
01661 DBusMessage *message)
01662 {
01663 const char *interface;
01664 const char *signal;
01665 char *name;
01666 GQuark q;
01667 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01668 GArray *msg_gsignature = NULL;
01669
01670 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
01671
01672 interface = dbus_message_get_interface (message);
01673 signal = dbus_message_get_member (message);
01674
01675 g_assert (interface != NULL);
01676 g_assert (signal != NULL);
01677
01678 name = create_signal_name (interface, signal);
01679
01680
01681
01682
01683
01684 q = g_quark_try_string (name);
01685
01686 if (q != 0)
01687 {
01688 GArray *gsignature;
01689 guint i;
01690
01691 gsignature = g_datalist_id_get_data (&priv->signal_signatures, q);
01692 if (gsignature == NULL)
01693 goto out;
01694
01695 msg_gsignature = _dbus_gtypes_from_arg_signature (dbus_message_get_signature (message),
01696 TRUE);
01697 for (i = 0; i < gsignature->len; i++)
01698 {
01699 if (msg_gsignature->len == i
01700 || g_array_index (gsignature, GType, i) != g_array_index (msg_gsignature, GType, i))
01701 goto mismatch;
01702 }
01703 if (msg_gsignature->len != i)
01704 goto mismatch;
01705
01706 g_signal_emit (proxy,
01707 signals[RECEIVED],
01708 q,
01709 message,
01710 msg_gsignature);
01711 }
01712
01713 out:
01714 g_free (name);
01715 if (msg_gsignature)
01716 g_array_free (msg_gsignature, TRUE);
01717 return;
01718 mismatch:
01719 #if 0
01720
01721 g_warning ("Unexpected message signature '%s' for signal '%s'\n",
01722 dbus_message_get_signature (message),
01723 name);
01724 #endif
01725 goto out;
01726 }
01727
01728 typedef struct
01729 {
01730 DBusGProxy *proxy;
01731 guint call_id;
01732 DBusGProxyCallNotify func;
01733 void *data;
01734 GDestroyNotify free_data_func;
01735 } GPendingNotifyClosure;
01736
01737 static void
01738 d_pending_call_notify (DBusPendingCall *dcall,
01739 void *data)
01740 {
01741 GPendingNotifyClosure *closure = data;
01742
01743 (* closure->func) (closure->proxy, DBUS_G_PROXY_ID_TO_CALL (closure->call_id), closure->data);
01744 }
01745
01746 static void
01747 d_pending_call_free (void *data)
01748 {
01749 GPendingNotifyClosure *closure = data;
01750
01751 if (closure->free_data_func)
01752 (* closure->free_data_func) (closure->data);
01753
01754 g_free (closure);
01755 }
01756
01757 #define DBUS_G_VALUE_ARRAY_COLLECT_ALL(VALARRAY, FIRST_ARG_TYPE, ARGS) \
01758 do { \
01759 GType valtype; \
01760 int i = 0; \
01761 VALARRAY = g_value_array_new (6); \
01762 valtype = FIRST_ARG_TYPE; \
01763 while (valtype != G_TYPE_INVALID) \
01764 { \
01765 const char *collect_err; \
01766 GValue *val; \
01767 g_value_array_append (VALARRAY, NULL); \
01768 val = g_value_array_get_nth (VALARRAY, i); \
01769 g_value_init (val, valtype); \
01770 collect_err = NULL; \
01771 G_VALUE_COLLECT (val, ARGS, G_VALUE_NOCOPY_CONTENTS, &collect_err); \
01772 valtype = va_arg (ARGS, GType); \
01773 i++; \
01774 } \
01775 } while (0)
01776
01777 DBusGProxyCall *
01778 manager_begin_bus_call (DBusGProxyManager *manager,
01779 const char *method,
01780 DBusGProxyCallNotify notify,
01781 gpointer user_data,
01782 GDestroyNotify destroy,
01783 GType first_arg_type,
01784 ...)
01785 {
01786 DBusGProxyCall *call;
01787 DBusGProxyPrivate *priv;
01788 va_list args;
01789 GValueArray *arg_values;
01790
01791 va_start (args, first_arg_type);
01792
01793 if (!manager->bus_proxy)
01794 {
01795 manager->bus_proxy = g_object_new (DBUS_TYPE_G_PROXY,
01796 "name", DBUS_SERVICE_DBUS,
01797 "path", DBUS_PATH_DBUS,
01798 "interface", DBUS_INTERFACE_DBUS,
01799 NULL);
01800 priv = DBUS_G_PROXY_GET_PRIVATE(manager->bus_proxy);
01801 priv->manager = manager;
01802 }
01803
01804 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
01805
01806 call = DBUS_G_PROXY_ID_TO_CALL (dbus_g_proxy_begin_call_internal (manager->bus_proxy, method, notify, user_data, destroy, arg_values,-1));
01807
01808 g_value_array_free (arg_values);
01809
01810 va_end (args);
01811
01812 return call;
01813 }
01814
01836 GType
01837 dbus_g_proxy_get_type (void)
01838 {
01839 static GType object_type = 0;
01840
01841 if (!object_type)
01842 {
01843 static const GTypeInfo object_info =
01844 {
01845 sizeof (DBusGProxyClass),
01846 (GBaseInitFunc) NULL,
01847 (GBaseFinalizeFunc) NULL,
01848 (GClassInitFunc) dbus_g_proxy_class_init,
01849 NULL,
01850 NULL,
01851 sizeof (DBusGProxy),
01852 0,
01853 (GInstanceInitFunc) dbus_g_proxy_init,
01854 };
01855
01856 object_type = g_type_register_static (G_TYPE_OBJECT,
01857 "DBusGProxy",
01858 &object_info, 0);
01859 }
01860
01861 return object_type;
01862 }
01863
01864 static DBusGProxy*
01865 dbus_g_proxy_new (DBusGConnection *connection,
01866 const char *name,
01867 const char *path_name,
01868 const char *interface_name)
01869 {
01870 DBusGProxy *proxy;
01871
01872 g_assert (connection != NULL);
01873
01874 proxy = g_object_new (DBUS_TYPE_G_PROXY,
01875 "name", name,
01876 "path", path_name,
01877 "interface", interface_name,
01878 "connection", connection, NULL);
01879
01880 return proxy;
01881 }
01882
01911 DBusGProxy*
01912 dbus_g_proxy_new_for_name (DBusGConnection *connection,
01913 const char *name,
01914 const char *path_name,
01915 const char *interface_name)
01916 {
01917 g_return_val_if_fail (connection != NULL, NULL);
01918 g_return_val_if_fail (name != NULL, NULL);
01919 g_return_val_if_fail (path_name != NULL, NULL);
01920 g_return_val_if_fail (interface_name != NULL, NULL);
01921
01922 return dbus_g_proxy_new (connection, name,
01923 path_name, interface_name);
01924 }
01925
01951 DBusGProxy*
01952 dbus_g_proxy_new_for_name_owner (DBusGConnection *connection,
01953 const char *name,
01954 const char *path_name,
01955 const char *interface_name,
01956 GError **error)
01957 {
01958 DBusGProxy *proxy;
01959 char *unique_name;
01960
01961 g_return_val_if_fail (connection != NULL, NULL);
01962 g_return_val_if_fail (name != NULL, NULL);
01963 g_return_val_if_fail (path_name != NULL, NULL);
01964 g_return_val_if_fail (interface_name != NULL, NULL);
01965
01966 if (!(unique_name = get_name_owner (DBUS_CONNECTION_FROM_G_CONNECTION (connection), name, error)))
01967 return NULL;
01968
01969 proxy = dbus_g_proxy_new (connection, unique_name,
01970 path_name, interface_name);
01971 g_free (unique_name);
01972 return proxy;
01973 }
01974
01986 DBusGProxy*
01987 dbus_g_proxy_new_from_proxy (DBusGProxy *proxy,
01988 const char *interface,
01989 const char *path)
01990 {
01991 DBusGProxyPrivate *priv;
01992
01993 g_return_val_if_fail (proxy != NULL, NULL);
01994
01995 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
01996
01997 if (interface == NULL)
01998 interface = priv->interface;
01999 if (path == NULL)
02000 path = priv->path;
02001
02002 return dbus_g_proxy_new (DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection),
02003 priv->name,
02004 path, interface);
02005 }
02006
02021 DBusGProxy*
02022 dbus_g_proxy_new_for_peer (DBusGConnection *connection,
02023 const char *path_name,
02024 const char *interface_name)
02025 {
02026 DBusGProxy *proxy;
02027
02028 g_return_val_if_fail (connection != NULL, NULL);
02029 g_return_val_if_fail (path_name != NULL, NULL);
02030 g_return_val_if_fail (interface_name != NULL, NULL);
02031
02032 proxy = dbus_g_proxy_new (connection, NULL,
02033 path_name, interface_name);
02034
02035 return proxy;
02036 }
02037
02051 const char*
02052 dbus_g_proxy_get_bus_name (DBusGProxy *proxy)
02053 {
02054 DBusGProxyPrivate *priv;
02055
02056 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02057 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02058
02059 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02060
02061 return priv->name;
02062 }
02063
02072 const char*
02073 dbus_g_proxy_get_interface (DBusGProxy *proxy)
02074 {
02075 DBusGProxyPrivate *priv;
02076
02077 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02078 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02079
02080 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02081
02082 return priv->interface;
02083 }
02084
02092 void
02093 dbus_g_proxy_set_interface (DBusGProxy *proxy,
02094 const char *interface_name)
02095 {
02096 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02097
02098
02099
02100 dbus_g_proxy_manager_unregister (priv->manager, proxy);
02101 g_free (priv->interface);
02102 priv->interface = g_strdup (interface_name);
02103 dbus_g_proxy_manager_register (priv->manager, proxy);
02104 }
02105
02113 const char*
02114 dbus_g_proxy_get_path (DBusGProxy *proxy)
02115 {
02116 DBusGProxyPrivate *priv;
02117
02118 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02119 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02120
02121 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02122
02123 return priv->path;
02124 }
02125
02126 static DBusMessage *
02127 dbus_g_proxy_marshal_args_to_message (DBusGProxy *proxy,
02128 const char *method,
02129 GValueArray *args)
02130 {
02131 DBusMessage *message;
02132 DBusMessageIter msgiter;
02133 guint i;
02134 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02135
02136 message = dbus_message_new_method_call (priv->name,
02137 priv->path,
02138 priv->interface,
02139 method);
02140 if (message == NULL)
02141 goto oom;
02142
02143 dbus_message_iter_init_append (message, &msgiter);
02144 for (i = 0; i < args->n_values; i++)
02145 {
02146 GValue *gvalue;
02147
02148 gvalue = g_value_array_get_nth (args, i);
02149
02150 if (!_dbus_gvalue_marshal (&msgiter, gvalue))
02151 g_assert_not_reached ();
02152 }
02153 return message;
02154 oom:
02155 return NULL;
02156 }
02157
02158 static guint
02159 dbus_g_proxy_begin_call_internal (DBusGProxy *proxy,
02160 const char *method,
02161 DBusGProxyCallNotify notify,
02162 gpointer user_data,
02163 GDestroyNotify destroy,
02164 GValueArray *args,
02165 int timeout)
02166 {
02167 DBusMessage *message;
02168 DBusPendingCall *pending;
02169 GPendingNotifyClosure *closure;
02170 guint call_id;
02171 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02172
02173 pending = NULL;
02174
02175 message = dbus_g_proxy_marshal_args_to_message (proxy, method, args);
02176 if (!message)
02177 goto oom;
02178
02179 if (!dbus_connection_send_with_reply (priv->manager->connection,
02180 message,
02181 &pending,
02182 timeout))
02183 goto oom;
02184 dbus_message_unref (message);
02185 if (pending == NULL)
02186 {
02187 g_debug ("Disconnected");
02188 return 0;
02189 }
02190
02191 call_id = ++priv->call_id_counter;
02192
02193 if (notify != NULL)
02194 {
02195 closure = g_new (GPendingNotifyClosure, 1);
02196 closure->proxy = proxy;
02197 closure->call_id = call_id;
02198 closure->func = notify;
02199 closure->data = user_data;
02200 closure->free_data_func = destroy;
02201 dbus_pending_call_set_notify (pending, d_pending_call_notify,
02202 closure,
02203 d_pending_call_free);
02204 }
02205
02206 g_hash_table_insert (priv->pending_calls, GUINT_TO_POINTER (call_id), pending);
02207
02208 return call_id;
02209 oom:
02210 g_error ("Out of memory");
02211 return 0;
02212 }
02213
02214 static gboolean
02215 dbus_g_proxy_end_call_internal (DBusGProxy *proxy,
02216 guint call_id,
02217 GError **error,
02218 GType first_arg_type,
02219 va_list args)
02220 {
02221 DBusMessage *reply;
02222 DBusMessageIter msgiter;
02223 DBusError derror;
02224 va_list args_unwind;
02225 guint over;
02226 int n_retvals_processed;
02227 gboolean ret;
02228 GType valtype;
02229 DBusPendingCall *pending;
02230 DBusGProxyPrivate *priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02231
02232 reply = NULL;
02233 ret = FALSE;
02234 n_retvals_processed = 0;
02235 over = 0;
02236
02237 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02238
02239 dbus_pending_call_block (pending);
02240 reply = dbus_pending_call_steal_reply (pending);
02241
02242 g_assert (reply != NULL);
02243
02244 dbus_error_init (&derror);
02245
02246 switch (dbus_message_get_type (reply))
02247 {
02248 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
02249 dbus_message_iter_init (reply, &msgiter);
02250 valtype = first_arg_type;
02251 while (valtype != G_TYPE_INVALID)
02252 {
02253 int arg_type;
02254 gpointer return_storage;
02255 GValue gvalue = { 0, };
02256 DBusGValueMarshalCtx context;
02257
02258 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (priv->manager->connection);
02259 context.proxy = proxy;
02260
02261 arg_type = dbus_message_iter_get_arg_type (&msgiter);
02262 if (arg_type == DBUS_TYPE_INVALID)
02263 {
02264 g_set_error (error, DBUS_GERROR,
02265 DBUS_GERROR_INVALID_ARGS,
02266 _("Too few arguments in reply"));
02267 goto out;
02268 }
02269
02270 return_storage = va_arg (args, gpointer);
02271 if (return_storage == NULL)
02272 goto next;
02273
02274
02275
02276
02277 if (arg_type == DBUS_TYPE_VARIANT
02278 && g_type_is_a (valtype, G_TYPE_VALUE))
02279 {
02280 if (!_dbus_gvalue_demarshal_variant (&context, &msgiter, (GValue*) return_storage, NULL))
02281 {
02282 g_set_error (error,
02283 DBUS_GERROR,
02284 DBUS_GERROR_INVALID_ARGS,
02285 _("Couldn't convert argument, expected \"%s\""),
02286 g_type_name (valtype));
02287 goto out;
02288 }
02289 }
02290 else
02291 {
02292 g_value_init (&gvalue, valtype);
02293
02294 if (!_dbus_gvalue_demarshal (&context, &msgiter, &gvalue, error))
02295 goto out;
02296
02297
02298 if (!_dbus_gvalue_store (&gvalue, (gpointer*) return_storage))
02299 g_assert_not_reached ();
02300
02301 }
02302
02303 next:
02304 n_retvals_processed++;
02305 dbus_message_iter_next (&msgiter);
02306 valtype = va_arg (args, GType);
02307 }
02308
02309 while (dbus_message_iter_get_arg_type (&msgiter) != DBUS_TYPE_INVALID)
02310 {
02311 over++;
02312 dbus_message_iter_next (&msgiter);
02313 }
02314
02315 if (over > 0)
02316 {
02317 g_set_error (error, DBUS_GERROR,
02318 DBUS_GERROR_INVALID_ARGS,
02319 _("Too many arguments in reply; expected %d, got %d"),
02320 n_retvals_processed, over);
02321 goto out;
02322 }
02323 break;
02324 case DBUS_MESSAGE_TYPE_ERROR:
02325 dbus_set_error_from_message (&derror, reply);
02326 dbus_set_g_error (error, &derror);
02327 dbus_error_free (&derror);
02328 goto out;
02329 break;
02330 default:
02331 dbus_set_error (&derror, DBUS_ERROR_FAILED,
02332 "Reply was neither a method return nor an exception");
02333 dbus_set_g_error (error, &derror);
02334 dbus_error_free (&derror);
02335 goto out;
02336 break;
02337 }
02338
02339 ret = TRUE;
02340 out:
02341 va_end (args);
02342
02343 if (ret == FALSE)
02344 {
02345 int i;
02346 for (i = 0; i < n_retvals_processed; i++)
02347 {
02348 gpointer retval;
02349
02350 retval = va_arg (args_unwind, gpointer);
02351
02352 g_free (retval);
02353 }
02354 }
02355 va_end (args_unwind);
02356
02357 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02358
02359 if (reply)
02360 dbus_message_unref (reply);
02361 return ret;
02362 }
02363
02386 DBusGProxyCall *
02387 dbus_g_proxy_begin_call (DBusGProxy *proxy,
02388 const char *method,
02389 DBusGProxyCallNotify notify,
02390 gpointer user_data,
02391 GDestroyNotify destroy,
02392 GType first_arg_type,
02393 ...)
02394 {
02395 guint call_id;
02396 va_list args;
02397 GValueArray *arg_values;
02398
02399 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02400 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02401
02402 va_start (args, first_arg_type);
02403
02404 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02405
02406 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,-1);
02407
02408 g_value_array_free (arg_values);
02409
02410 va_end (args);
02411
02412 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02413 }
02414
02438 DBusGProxyCall *
02439 dbus_g_proxy_begin_call_with_timeout (DBusGProxy *proxy,
02440 const char *method,
02441 DBusGProxyCallNotify notify,
02442 gpointer user_data,
02443 GDestroyNotify destroy,
02444 int timeout,
02445 GType first_arg_type,
02446 ...)
02447 {
02448 guint call_id;
02449 va_list args;
02450 GValueArray *arg_values;
02451
02452 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), NULL);
02453 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), NULL);
02454
02455 va_start (args, first_arg_type);
02456
02457 DBUS_G_VALUE_ARRAY_COLLECT_ALL (arg_values, first_arg_type, args);
02458
02459 call_id = dbus_g_proxy_begin_call_internal (proxy, method, notify, user_data, destroy, arg_values,timeout);
02460
02461 g_value_array_free (arg_values);
02462
02463 va_end (args);
02464
02465 return DBUS_G_PROXY_ID_TO_CALL (call_id);
02466 }
02467
02490 gboolean
02491 dbus_g_proxy_end_call (DBusGProxy *proxy,
02492 DBusGProxyCall *call,
02493 GError **error,
02494 GType first_arg_type,
02495 ...)
02496 {
02497 gboolean ret;
02498 va_list args;
02499
02500 va_start (args, first_arg_type);
02501
02502 ret = dbus_g_proxy_end_call_internal (proxy, GPOINTER_TO_UINT (call), error, first_arg_type, args);
02503
02504 va_end (args);
02505
02506 return ret;
02507 }
02508
02525 gboolean
02526 dbus_g_proxy_call (DBusGProxy *proxy,
02527 const char *method,
02528 GError **error,
02529 GType first_arg_type,
02530 ...)
02531 {
02532 gboolean ret;
02533 guint call_id;
02534 va_list args;
02535 GValueArray *in_args;
02536
02537 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02538 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02539
02540 va_start (args, first_arg_type);
02541
02542 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02543
02544 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,-1);
02545
02546 g_value_array_free (in_args);
02547
02548 if (call_id > 0)
02549 {
02550 first_arg_type = va_arg (args, GType);
02551 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02552 }
02553 else
02554 {
02555 g_set_error (error, DBUS_GERROR,
02556 DBUS_GERROR_FAILED,
02557 _("Disconnection or out-of-memory"));
02558 ret = FALSE;
02559 }
02560
02561 va_end (args);
02562
02563 return ret;
02564 }
02565
02583 gboolean
02584 dbus_g_proxy_call_with_timeout (DBusGProxy *proxy,
02585 const char *method,
02586 int timeout,
02587 GError **error,
02588 GType first_arg_type,
02589 ...)
02590 {
02591 gboolean ret;
02592 guint call_id;
02593 va_list args;
02594 GValueArray *in_args;
02595
02596 g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
02597 g_return_val_if_fail (!DBUS_G_PROXY_DESTROYED (proxy), FALSE);
02598
02599 va_start (args, first_arg_type);
02600
02601 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02602
02603 call_id = dbus_g_proxy_begin_call_internal (proxy, method, NULL, NULL, NULL, in_args,timeout);
02604
02605 g_value_array_free (in_args);
02606
02607 first_arg_type = va_arg (args, GType);
02608 ret = dbus_g_proxy_end_call_internal (proxy, call_id, error, first_arg_type, args);
02609
02610 va_end (args);
02611
02612 return ret;
02613 }
02614
02627 void
02628 dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
02629 const char *method,
02630 GType first_arg_type,
02631 ...)
02632 {
02633 DBusMessage *message;
02634 va_list args;
02635 GValueArray *in_args;
02636 DBusGProxyPrivate *priv;
02637
02638 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02639 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02640
02641 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02642
02643 va_start (args, first_arg_type);
02644 DBUS_G_VALUE_ARRAY_COLLECT_ALL (in_args, first_arg_type, args);
02645
02646 message = dbus_g_proxy_marshal_args_to_message (proxy, method, in_args);
02647
02648 g_value_array_free (in_args);
02649 va_end (args);
02650
02651 if (!message)
02652 goto oom;
02653
02654 dbus_message_set_no_reply (message, TRUE);
02655
02656 if (!dbus_connection_send (priv->manager->connection,
02657 message,
02658 NULL))
02659 goto oom;
02660 dbus_message_unref (message);
02661 return;
02662
02663 oom:
02664 g_error ("Out of memory");
02665 }
02666
02677 void
02678 dbus_g_proxy_cancel_call (DBusGProxy *proxy,
02679 DBusGProxyCall *call)
02680 {
02681 guint call_id;
02682 DBusPendingCall *pending;
02683 DBusGProxyPrivate *priv;
02684
02685 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02686 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02687
02688 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02689
02690 call_id = DBUS_G_PROXY_CALL_TO_ID (call);
02691
02692 pending = g_hash_table_lookup (priv->pending_calls, GUINT_TO_POINTER (call_id));
02693 g_return_if_fail (pending != NULL);
02694
02695 dbus_pending_call_cancel (pending);
02696
02697 g_hash_table_remove (priv->pending_calls, GUINT_TO_POINTER (call_id));
02698 }
02699
02720 void
02721 dbus_g_proxy_send (DBusGProxy *proxy,
02722 DBusMessage *message,
02723 dbus_uint32_t *client_serial)
02724 {
02725 DBusGProxyPrivate *priv;
02726
02727 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02728 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02729
02730 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02731
02732 if (priv->name)
02733 {
02734 if (!dbus_message_set_destination (message, priv->name))
02735 g_error ("Out of memory");
02736 }
02737 if (priv->path)
02738 {
02739 if (!dbus_message_set_path (message, priv->path))
02740 g_error ("Out of memory");
02741 }
02742 if (priv->interface)
02743 {
02744 if (!dbus_message_set_interface (message, priv->interface))
02745 g_error ("Out of memory");
02746 }
02747
02748 if (!dbus_connection_send (priv->manager->connection, message, client_serial))
02749 g_error ("Out of memory\n");
02750 }
02751
02752 static void
02753 array_free_all (gpointer array)
02754 {
02755 g_array_free (array, TRUE);
02756 }
02757
02768 void
02769 dbus_g_proxy_add_signal (DBusGProxy *proxy,
02770 const char *signal_name,
02771 GType first_type,
02772 ...)
02773 {
02774 GQuark q;
02775 char *name;
02776 GArray *gtypesig;
02777 GType gtype;
02778 va_list args;
02779 DBusGProxyPrivate *priv;
02780
02781 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02782 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02783 g_return_if_fail (signal_name != NULL);
02784
02785 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02786
02787 name = create_signal_name (priv->interface, signal_name);
02788
02789 q = g_quark_from_string (name);
02790
02791 g_return_if_fail (g_datalist_id_get_data (&priv->signal_signatures, q) == NULL);
02792
02793 gtypesig = g_array_new (FALSE, TRUE, sizeof (GType));
02794
02795 va_start (args, first_type);
02796 gtype = first_type;
02797 while (gtype != G_TYPE_INVALID)
02798 {
02799 g_array_append_val (gtypesig, gtype);
02800 gtype = va_arg (args, GType);
02801 }
02802 va_end (args);
02803
02804 #ifndef G_DISABLE_CHECKS
02805 if (_dbus_gobject_lookup_marshaller (G_TYPE_NONE, gtypesig->len, (const GType*) gtypesig->data) == NULL)
02806 g_warning ("No marshaller for signature of signal '%s'", signal_name);
02807 #endif
02808
02809
02810 g_datalist_id_set_data_full (&priv->signal_signatures,
02811 q, gtypesig,
02812 array_free_all);
02813
02814 g_free (name);
02815 }
02816
02829 void
02830 dbus_g_proxy_connect_signal (DBusGProxy *proxy,
02831 const char *signal_name,
02832 GCallback handler,
02833 void *data,
02834 GClosureNotify free_data_func)
02835 {
02836 char *name;
02837 GClosure *closure;
02838 GQuark q;
02839 DBusGProxyPrivate *priv;
02840
02841 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02842 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02843 g_return_if_fail (signal_name != NULL);
02844 g_return_if_fail (handler != NULL);
02845
02846 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02847 name = create_signal_name (priv->interface, signal_name);
02848
02849 q = g_quark_try_string (name);
02850
02851 #ifndef G_DISABLE_CHECKS
02852 if (q == 0 || g_datalist_id_get_data (&priv->signal_signatures, q) == NULL)
02853 {
02854 g_warning ("Must add the signal '%s' with dbus_g_proxy_add_signal() prior to connecting to it\n", name);
02855 g_free (name);
02856 return;
02857 }
02858 #endif
02859
02860 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
02861
02862 g_signal_connect_closure_by_id (G_OBJECT (proxy),
02863 signals[RECEIVED],
02864 q,
02865 closure, FALSE);
02866
02867 g_free (name);
02868 }
02869
02880 void
02881 dbus_g_proxy_disconnect_signal (DBusGProxy *proxy,
02882 const char *signal_name,
02883 GCallback handler,
02884 void *data)
02885 {
02886 char *name;
02887 GQuark q;
02888 DBusGProxyPrivate *priv;
02889
02890 g_return_if_fail (DBUS_IS_G_PROXY (proxy));
02891 g_return_if_fail (!DBUS_G_PROXY_DESTROYED (proxy));
02892 g_return_if_fail (signal_name != NULL);
02893 g_return_if_fail (handler != NULL);
02894
02895 priv = DBUS_G_PROXY_GET_PRIVATE(proxy);
02896 name = create_signal_name (priv->interface, signal_name);
02897
02898 q = g_quark_try_string (name);
02899
02900 if (q != 0)
02901 {
02902 g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
02903 G_SIGNAL_MATCH_DETAIL |
02904 G_SIGNAL_MATCH_FUNC |
02905 G_SIGNAL_MATCH_DATA,
02906 signals[RECEIVED],
02907 q,
02908 NULL,
02909 G_CALLBACK (handler), data);
02910 }
02911 else
02912 {
02913 g_warning ("Attempt to disconnect from signal '%s' which is not registered\n",
02914 name);
02915 }
02916
02917 g_free (name);
02918 }
02919
02922 #ifdef DBUS_BUILD_TESTS
02923
02929 gboolean
02930 _dbus_g_proxy_test (void)
02931 {
02932
02933
02934 return TRUE;
02935 }
02936
02937 #endif