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