00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "dbus-glib.h"
00024 #include <string.h>
00025
00032 typedef struct DBusGProxyManager DBusGProxyManager;
00033
00037 struct DBusGProxy
00038 {
00039 GObject parent;
00041 DBusGProxyManager *manager;
00042 char *service;
00043 char *path;
00044 char *interface;
00045 };
00046
00050 struct DBusGProxyClass
00051 {
00052 GObjectClass parent_class;
00053 };
00054
00055 static void dbus_gproxy_init (DBusGProxy *proxy);
00056 static void dbus_gproxy_class_init (DBusGProxyClass *klass);
00057 static void dbus_gproxy_finalize (GObject *object);
00058 static void dbus_gproxy_dispose (GObject *object);
00059 static void dbus_gproxy_destroy (DBusGProxy *proxy);
00060 static void dbus_gproxy_emit_received (DBusGProxy *proxy,
00061 DBusMessage *message);
00062
00063
00068 typedef struct
00069 {
00070 GSList *proxies;
00071
00072 char name[4];
00077 } DBusGProxyList;
00078
00084 struct DBusGProxyManager
00085 {
00086 GStaticMutex lock;
00087 int refcount;
00088 DBusConnection *connection;
00090 GHashTable *proxy_lists;
00094 };
00095
00096 static void dbus_gproxy_manager_ref (DBusGProxyManager *manager);
00097 static DBusHandlerResult dbus_gproxy_manager_filter (DBusConnection *connection,
00098 DBusMessage *message,
00099 void *user_data);
00100
00102 #define LOCK_MANAGER(mgr) (g_static_mutex_lock (&(mgr)->lock))
00103
00104 #define UNLOCK_MANAGER(mgr) (g_static_mutex_unlock (&(mgr)->lock))
00105
00106 static int gproxy_manager_slot = -1;
00107
00108
00109 static GStaticMutex connection_gproxy_lock = G_STATIC_MUTEX_INIT;
00110
00111 static DBusGProxyManager*
00112 dbus_gproxy_manager_get (DBusConnection *connection)
00113 {
00114 DBusGProxyManager *manager;
00115
00116 dbus_connection_allocate_data_slot (&gproxy_manager_slot);
00117 if (gproxy_manager_slot < 0)
00118 g_error ("out of memory");
00119
00120 g_static_mutex_lock (&connection_gproxy_lock);
00121
00122 manager = dbus_connection_get_data (connection, gproxy_manager_slot);
00123 if (manager != NULL)
00124 {
00125 dbus_connection_free_data_slot (&gproxy_manager_slot);
00126 dbus_gproxy_manager_ref (manager);
00127 g_static_mutex_unlock (&connection_gproxy_lock);
00128 return manager;
00129 }
00130
00131 manager = g_new0 (DBusGProxyManager, 1);
00132
00133 manager->refcount = 1;
00134 manager->connection = connection;
00135
00136 g_static_mutex_init (&manager->lock);
00137
00138
00139
00140
00141
00142 dbus_connection_ref (manager->connection);
00143
00144 dbus_connection_set_data (connection, gproxy_manager_slot,
00145 manager, NULL);
00146
00147 dbus_connection_add_filter (connection, dbus_gproxy_manager_filter,
00148 manager, NULL);
00149
00150 g_static_mutex_unlock (&connection_gproxy_lock);
00151
00152 return manager;
00153 }
00154
00155 static void
00156 dbus_gproxy_manager_ref (DBusGProxyManager *manager)
00157 {
00158 g_assert (manager != NULL);
00159 g_assert (manager->refcount > 0);
00160
00161 LOCK_MANAGER (manager);
00162
00163 manager->refcount += 1;
00164
00165 UNLOCK_MANAGER (manager);
00166 }
00167
00168 static void
00169 dbus_gproxy_manager_unref (DBusGProxyManager *manager)
00170 {
00171 g_assert (manager != NULL);
00172 g_assert (manager->refcount > 0);
00173
00174 LOCK_MANAGER (manager);
00175 manager->refcount -= 1;
00176 if (manager->refcount == 0)
00177 {
00178 UNLOCK_MANAGER (manager);
00179
00180 if (manager->proxy_lists)
00181 {
00182
00183
00184
00185 g_assert (g_hash_table_size (manager->proxy_lists) == 0);
00186
00187 g_hash_table_destroy (manager->proxy_lists);
00188 manager->proxy_lists = NULL;
00189 }
00190
00191 g_static_mutex_free (&manager->lock);
00192
00193 g_static_mutex_lock (&connection_gproxy_lock);
00194
00195 dbus_connection_remove_filter (manager->connection, dbus_gproxy_manager_filter,
00196 manager);
00197
00198 dbus_connection_set_data (manager->connection,
00199 gproxy_manager_slot,
00200 NULL, NULL);
00201
00202 g_static_mutex_unlock (&connection_gproxy_lock);
00203
00204 dbus_connection_unref (manager->connection);
00205 g_free (manager);
00206
00207 dbus_connection_free_data_slot (&gproxy_manager_slot);
00208 }
00209 else
00210 {
00211 UNLOCK_MANAGER (manager);
00212 }
00213 }
00214
00215 static guint
00216 tristring_hash (gconstpointer key)
00217 {
00218 const char *p = key;
00219 guint h = *p;
00220
00221 if (h)
00222 {
00223 for (p += 1; *p != '\0'; p++)
00224 h = (h << 5) - h + *p;
00225 }
00226
00227
00228 for (p += 1; *p != '\0'; p++)
00229 h = (h << 5) - h + *p;
00230
00231
00232 for (p += 1; *p != '\0'; p++)
00233 h = (h << 5) - h + *p;
00234
00235 return h;
00236 }
00237
00238 static gboolean
00239 strequal_len (const char *a,
00240 const char *b,
00241 size_t *lenp)
00242 {
00243 size_t a_len;
00244 size_t b_len;
00245
00246 a_len = strlen (a);
00247 b_len = strlen (b);
00248
00249 if (a_len != b_len)
00250 return FALSE;
00251
00252 if (memcmp (a, b, a_len) != 0)
00253 return FALSE;
00254
00255 *lenp = a_len;
00256
00257 return TRUE;
00258 }
00259
00260 static gboolean
00261 tristring_equal (gconstpointer a,
00262 gconstpointer b)
00263 {
00264 const char *ap = a;
00265 const char *bp = b;
00266 size_t len;
00267
00268 if (!strequal_len (ap, bp, &len))
00269 return FALSE;
00270
00271 ap += len + 1;
00272 bp += len + 1;
00273
00274 if (!strequal_len (ap, bp, &len))
00275 return FALSE;
00276
00277 ap += len + 1;
00278 bp += len + 1;
00279
00280 if (strcmp (ap, bp) != 0)
00281 return FALSE;
00282
00283 return TRUE;
00284 }
00285
00286 static char*
00287 tristring_alloc_from_strings (size_t padding_before,
00288 const char *service,
00289 const char *path,
00290 const char *interface)
00291 {
00292 size_t service_len, iface_len, path_len, len;
00293 char *tri;
00294
00295 if (service)
00296 service_len = strlen (service);
00297 else
00298 service_len = 0;
00299
00300 path_len = strlen (path);
00301
00302 iface_len = strlen (interface);
00303
00304 tri = g_malloc (padding_before + service_len + path_len + iface_len + 3);
00305
00306 len = padding_before;
00307
00308 if (service)
00309 memcpy (&tri[len], service, service_len);
00310
00311 len += service_len;
00312 tri[len] = '\0';
00313 len += 1;
00314
00315 g_assert (len == (padding_before + service_len + 1));
00316
00317 memcpy (&tri[len], path, path_len);
00318 len += path_len;
00319 tri[len] = '\0';
00320 len += 1;
00321
00322 g_assert (len == (padding_before + service_len + path_len + 2));
00323
00324 memcpy (&tri[len], interface, iface_len);
00325 len += iface_len;
00326 tri[len] = '\0';
00327 len += 1;
00328
00329 g_assert (len == (padding_before + service_len + path_len + iface_len + 3));
00330
00331 return tri;
00332 }
00333
00334 static char*
00335 tristring_from_proxy (DBusGProxy *proxy)
00336 {
00337 return tristring_alloc_from_strings (0,
00338 proxy->service,
00339 proxy->path,
00340 proxy->interface);
00341 }
00342
00343 static char*
00344 tristring_from_message (DBusMessage *message)
00345 {
00346 return tristring_alloc_from_strings (0,
00347 dbus_message_get_sender (message),
00348 dbus_message_get_path (message),
00349 dbus_message_get_interface (message));
00350 }
00351
00352 static DBusGProxyList*
00353 gproxy_list_new (DBusGProxy *first_proxy)
00354 {
00355 DBusGProxyList *list;
00356
00357 list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name),
00358 first_proxy->service,
00359 first_proxy->path,
00360 first_proxy->interface);
00361 list->proxies = NULL;
00362
00363 return list;
00364 }
00365
00366 static void
00367 gproxy_list_free (DBusGProxyList *list)
00368 {
00369
00370
00371
00372 g_slist_free (list->proxies);
00373
00374 g_free (list);
00375 }
00376
00377 static char*
00378 gproxy_get_match_rule (DBusGProxy *proxy)
00379 {
00380
00381
00382 if (proxy->service)
00383 return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'",
00384 proxy->service, proxy->path, proxy->interface);
00385 else
00386 return g_strdup_printf ("type='signal',path='%s',interface='%s'",
00387 proxy->path, proxy->interface);
00388 }
00389
00390 static void
00391 dbus_gproxy_manager_register (DBusGProxyManager *manager,
00392 DBusGProxy *proxy)
00393 {
00394 DBusGProxyList *list;
00395
00396 LOCK_MANAGER (manager);
00397
00398 if (manager->proxy_lists == NULL)
00399 {
00400 list = NULL;
00401 manager->proxy_lists = g_hash_table_new_full (tristring_hash,
00402 tristring_equal,
00403 NULL,
00404 (GFreeFunc) gproxy_list_free);
00405 }
00406 else
00407 {
00408 char *tri;
00409
00410 tri = tristring_from_proxy (proxy);
00411
00412 list = g_hash_table_lookup (manager->proxy_lists, tri);
00413
00414 g_free (tri);
00415 }
00416
00417 if (list == NULL)
00418 {
00419 list = gproxy_list_new (proxy);
00420
00421 g_hash_table_replace (manager->proxy_lists,
00422 list->name, list);
00423 }
00424
00425 if (list->proxies == NULL)
00426 {
00427
00428
00429
00430
00431 char *rule;
00432
00433 rule = gproxy_get_match_rule (proxy);
00434
00435
00436
00437
00438 dbus_bus_add_match (manager->connection,
00439 rule, NULL);
00440
00441 g_free (rule);
00442 }
00443
00444 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00445
00446 list->proxies = g_slist_prepend (list->proxies, proxy);
00447
00448 UNLOCK_MANAGER (manager);
00449 }
00450
00451 static void
00452 dbus_gproxy_manager_unregister (DBusGProxyManager *manager,
00453 DBusGProxy *proxy)
00454 {
00455 DBusGProxyList *list;
00456 char *tri;
00457
00458 LOCK_MANAGER (manager);
00459
00460 #ifndef G_DISABLE_CHECKS
00461 if (manager->proxy_lists == NULL)
00462 {
00463 g_warning ("Trying to unregister a proxy but there aren't any registered");
00464 return;
00465 }
00466 #endif
00467
00468 tri = tristring_from_proxy (proxy);
00469
00470 list = g_hash_table_lookup (manager->proxy_lists, tri);
00471
00472 #ifndef G_DISABLE_CHECKS
00473 if (list == NULL)
00474 {
00475 g_warning ("Trying to unregister a proxy but it isn't registered");
00476 return;
00477 }
00478 #endif
00479
00480 g_assert (g_slist_find (list->proxies, proxy) != NULL);
00481
00482 list->proxies = g_slist_remove (list->proxies, proxy);
00483
00484 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00485
00486 if (list->proxies == NULL)
00487 {
00488 g_hash_table_remove (manager->proxy_lists,
00489 tri);
00490 list = NULL;
00491 }
00492
00493 if (g_hash_table_size (manager->proxy_lists) == 0)
00494 {
00495 g_hash_table_destroy (manager->proxy_lists);
00496 manager->proxy_lists = NULL;
00497 }
00498
00499 g_free (tri);
00500
00501 UNLOCK_MANAGER (manager);
00502 }
00503
00504 static void
00505 list_proxies_foreach (gpointer key,
00506 gpointer value,
00507 gpointer user_data)
00508 {
00509 DBusGProxyList *list;
00510 GSList **ret;
00511 GSList *tmp;
00512
00513 list = value;
00514 ret = user_data;
00515
00516 tmp = list->proxies;
00517 while (tmp != NULL)
00518 {
00519 DBusGProxy *proxy = DBUS_GPROXY (tmp->data);
00520
00521 g_object_ref (proxy);
00522 *ret = g_slist_prepend (*ret, proxy);
00523
00524 tmp = tmp->next;
00525 }
00526 }
00527
00528 static GSList*
00529 dbus_gproxy_manager_list_all (DBusGProxyManager *manager)
00530 {
00531 GSList *ret;
00532
00533 ret = NULL;
00534
00535 if (manager->proxy_lists)
00536 {
00537 g_hash_table_foreach (manager->proxy_lists,
00538 list_proxies_foreach,
00539 &ret);
00540 }
00541
00542 return ret;
00543 }
00544
00545 static DBusHandlerResult
00546 dbus_gproxy_manager_filter (DBusConnection *connection,
00547 DBusMessage *message,
00548 void *user_data)
00549 {
00550 DBusGProxyManager *manager;
00551
00552 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
00553 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00554
00555 manager = user_data;
00556
00557 dbus_gproxy_manager_ref (manager);
00558
00559 LOCK_MANAGER (manager);
00560
00561 if (dbus_message_is_signal (message,
00562 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
00563 "Disconnected"))
00564 {
00565
00566
00567
00568 GSList *all;
00569 GSList *tmp;
00570
00571 all = dbus_gproxy_manager_list_all (manager);
00572
00573 tmp = all;
00574 while (tmp != NULL)
00575 {
00576 DBusGProxy *proxy;
00577
00578 proxy = DBUS_GPROXY (tmp->data);
00579
00580 UNLOCK_MANAGER (manager);
00581 dbus_gproxy_destroy (proxy);
00582 g_object_unref (G_OBJECT (proxy));
00583 LOCK_MANAGER (manager);
00584
00585 tmp = tmp->next;
00586 }
00587
00588 g_slist_free (all);
00589
00590 #ifndef G_DISABLE_CHECKS
00591 if (manager->proxy_lists != NULL)
00592 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.");
00593 #endif
00594 }
00595 else
00596 {
00597 char *tri;
00598 DBusGProxyList *list;
00599
00600 tri = tristring_from_message (message);
00601
00602 if (manager->proxy_lists)
00603 list = g_hash_table_lookup (manager->proxy_lists, tri);
00604 else
00605 list = NULL;
00606
00607 #if 0
00608 g_print ("proxy got %s,%s,%s = list %p\n",
00609 tri,
00610 tri + strlen (tri) + 1,
00611 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
00612 list);
00613 #endif
00614
00615 g_free (tri);
00616
00617
00618
00619 if (list != NULL)
00620 {
00621 GSList *tmp;
00622 GSList *copy;
00623
00624 copy = g_slist_copy (list->proxies);
00625 g_slist_foreach (copy, (GFunc) g_object_ref, NULL);
00626
00627 tmp = copy;
00628 while (tmp != NULL)
00629 {
00630 DBusGProxy *proxy;
00631
00632 proxy = DBUS_GPROXY (tmp->data);
00633
00634 UNLOCK_MANAGER (manager);
00635 dbus_gproxy_emit_received (proxy, message);
00636 g_object_unref (G_OBJECT (proxy));
00637 LOCK_MANAGER (manager);
00638
00639 tmp = tmp->next;
00640 }
00641
00642 g_slist_free (copy);
00643 }
00644 }
00645
00646 UNLOCK_MANAGER (manager);
00647 dbus_gproxy_manager_unref (manager);
00648
00649
00650
00651
00652 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661 enum
00662 {
00663 DESTROY,
00664 RECEIVED,
00665 LAST_SIGNAL
00666 };
00667
00668 static void *parent_class;
00669 static guint signals[LAST_SIGNAL] = { 0 };
00670
00671 static void
00672 dbus_gproxy_init (DBusGProxy *proxy)
00673 {
00674
00675 }
00676
00677 static void
00678 dbus_gproxy_class_init (DBusGProxyClass *klass)
00679 {
00680 GObjectClass *object_class = G_OBJECT_CLASS (klass);
00681
00682 parent_class = g_type_class_peek_parent (klass);
00683
00684 object_class->finalize = dbus_gproxy_finalize;
00685 object_class->dispose = dbus_gproxy_dispose;
00686
00687 signals[DESTROY] =
00688 g_signal_new ("destroy",
00689 G_OBJECT_CLASS_TYPE (object_class),
00690 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
00691 0,
00692 NULL, NULL,
00693 g_cclosure_marshal_VOID__VOID,
00694 G_TYPE_NONE, 0);
00695
00696 signals[RECEIVED] =
00697 g_signal_new ("received",
00698 G_OBJECT_CLASS_TYPE (object_class),
00699 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
00700 0,
00701 NULL, NULL,
00702 g_cclosure_marshal_VOID__BOXED,
00703 G_TYPE_NONE, 1,
00704 DBUS_TYPE_MESSAGE);
00705 }
00706
00707
00708 static void
00709 dbus_gproxy_dispose (GObject *object)
00710 {
00711 DBusGProxy *proxy;
00712
00713 proxy = DBUS_GPROXY (object);
00714
00715 g_signal_emit (object, signals[DESTROY], 0);
00716
00717 G_OBJECT_CLASS (parent_class)->dispose (object);
00718 }
00719
00720 static void
00721 dbus_gproxy_finalize (GObject *object)
00722 {
00723 DBusGProxy *proxy;
00724
00725 proxy = DBUS_GPROXY (object);
00726
00727 if (proxy->manager)
00728 {
00729 dbus_gproxy_manager_unregister (proxy->manager, proxy);
00730 dbus_gproxy_manager_unref (proxy->manager);
00731 }
00732
00733 g_free (proxy->service);
00734 g_free (proxy->path);
00735 g_free (proxy->interface);
00736
00737 G_OBJECT_CLASS (parent_class)->finalize (object);
00738 }
00739
00740 static void
00741 dbus_gproxy_destroy (DBusGProxy *proxy)
00742 {
00743
00744
00745
00746 g_object_run_dispose (G_OBJECT (proxy));
00747 }
00748
00749 static char*
00750 create_signal_detail (const char *interface,
00751 const char *signal)
00752 {
00753 GString *str;
00754
00755 str = g_string_new (interface);
00756
00757 g_string_append (str, ".");
00758
00759 g_string_append (str, signal);
00760
00761 return g_string_free (str, FALSE);
00762 }
00763
00764 static void
00765 dbus_gproxy_emit_received (DBusGProxy *proxy,
00766 DBusMessage *message)
00767 {
00768 const char *interface;
00769 const char *signal;
00770 char *detail;
00771 GQuark q;
00772
00773 interface = dbus_message_get_interface (message);
00774 signal = dbus_message_get_member (message);
00775
00776 g_assert (interface != NULL);
00777 g_assert (signal != NULL);
00778
00779 detail = create_signal_detail (interface, signal);
00780
00781
00782
00783
00784
00785 q = g_quark_try_string (detail);
00786
00787 if (q != 0)
00788 g_signal_emit (G_OBJECT (proxy),
00789 signals[RECEIVED],
00790 q,
00791 message);
00792
00793 g_free (detail);
00794 }
00795
00807 GType
00808 dbus_gproxy_get_type (void)
00809 {
00810 static GType object_type = 0;
00811
00812 if (!object_type)
00813 {
00814 static const GTypeInfo object_info =
00815 {
00816 sizeof (DBusGProxyClass),
00817 (GBaseInitFunc) NULL,
00818 (GBaseFinalizeFunc) NULL,
00819 (GClassInitFunc) dbus_gproxy_class_init,
00820 NULL,
00821 NULL,
00822 sizeof (DBusGProxy),
00823 0,
00824 (GInstanceInitFunc) dbus_gproxy_init,
00825 };
00826
00827 object_type = g_type_register_static (G_TYPE_OBJECT,
00828 "DBusGProxy",
00829 &object_info, 0);
00830 }
00831
00832 return object_type;
00833 }
00834
00835 static DBusGProxy*
00836 dbus_gproxy_new (DBusConnection *connection,
00837 const char *service_name,
00838 const char *path_name,
00839 const char *interface_name)
00840 {
00841 DBusGProxy *proxy;
00842
00843 g_assert (connection != NULL);
00844
00845 proxy = g_object_new (DBUS_TYPE_GPROXY, NULL);
00846
00847
00848
00849
00850
00851 proxy->manager = dbus_gproxy_manager_get (connection);
00852
00853 proxy->service = g_strdup (service_name);
00854 proxy->path = g_strdup (path_name);
00855 proxy->interface = g_strdup (interface_name);
00856
00857 dbus_gproxy_manager_register (proxy->manager, proxy);
00858
00859 return proxy;
00860 }
00861
00884 DBusGProxy*
00885 dbus_gproxy_new_for_service (DBusConnection *connection,
00886 const char *service_name,
00887 const char *path_name,
00888 const char *interface_name)
00889 {
00890 DBusGProxy *proxy;
00891
00892 g_return_val_if_fail (connection != NULL, NULL);
00893 g_return_val_if_fail (service_name != NULL, NULL);
00894 g_return_val_if_fail (path_name != NULL, NULL);
00895 g_return_val_if_fail (interface_name != NULL, NULL);
00896
00897 proxy = dbus_gproxy_new (connection, service_name,
00898 path_name, interface_name);
00899
00900 return proxy;
00901 }
00902
00926 DBusGProxy*
00927 dbus_gproxy_new_for_service_owner (DBusConnection *connection,
00928 const char *service_name,
00929 const char *path_name,
00930 const char *interface_name,
00931 GError **error)
00932 {
00933 g_return_val_if_fail (connection != NULL, NULL);
00934 g_return_val_if_fail (service_name != NULL, NULL);
00935 g_return_val_if_fail (path_name != NULL, NULL);
00936 g_return_val_if_fail (interface_name != NULL, NULL);
00937
00938
00939 }
00940
00955 DBusGProxy*
00956 dbus_gproxy_new_for_peer (DBusConnection *connection,
00957 const char *path_name,
00958 const char *interface_name)
00959 {
00960 DBusGProxy *proxy;
00961
00962 g_return_val_if_fail (connection != NULL, NULL);
00963 g_return_val_if_fail (path_name != NULL, NULL);
00964 g_return_val_if_fail (interface_name != NULL, NULL);
00965
00966 proxy = dbus_gproxy_new (connection, NULL,
00967 path_name, interface_name);
00968
00969 return proxy;
00970 }
00971
00991 DBusPendingCall*
00992 dbus_gproxy_begin_call (DBusGProxy *proxy,
00993 const char *method,
00994 int first_arg_type,
00995 ...)
00996 {
00997 DBusPendingCall *pending;
00998 DBusMessage *message;
00999 va_list args;
01000
01001 g_return_val_if_fail (DBUS_IS_GPROXY (proxy), NULL);
01002
01003 message = dbus_message_new_method_call (proxy->service,
01004 proxy->path,
01005 proxy->interface,
01006 method);
01007 if (message == NULL)
01008 goto oom;
01009
01010 va_start (args, first_arg_type);
01011 if (!dbus_message_append_args_valist (message, first_arg_type,
01012 args))
01013 goto oom;
01014 va_end (args);
01015
01016 if (!dbus_connection_send_with_reply (proxy->manager->connection,
01017 message,
01018 &pending,
01019 -1))
01020 goto oom;
01021
01022 return pending;
01023
01024 oom:
01025
01026
01027
01028
01029
01030 g_error ("Out of memory");
01031 return NULL;
01032 }
01033
01059 gboolean
01060 dbus_gproxy_end_call (DBusGProxy *proxy,
01061 DBusPendingCall *pending,
01062 GError **error,
01063 int first_arg_type,
01064 ...)
01065 {
01066 DBusMessage *message;
01067 va_list args;
01068 DBusError derror;
01069
01070 g_return_val_if_fail (DBUS_IS_GPROXY (proxy), FALSE);
01071 g_return_val_if_fail (pending != NULL, FALSE);
01072
01073 dbus_pending_call_block (pending);
01074 message = dbus_pending_call_get_reply (pending);
01075
01076 g_assert (message != NULL);
01077
01078 dbus_error_init (&derror);
01079
01080 switch (dbus_message_get_type (message))
01081 {
01082 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
01083 va_start (args, first_arg_type);
01084 if (!dbus_message_get_args_valist (message, &derror, first_arg_type, args))
01085 {
01086 va_end (args);
01087 goto error;
01088 }
01089 va_end (args);
01090
01091 return TRUE;
01092
01093 case DBUS_MESSAGE_TYPE_ERROR:
01094 dbus_set_error_from_message (&derror, message);
01095 goto error;
01096
01097 default:
01098 dbus_set_error (&derror, DBUS_ERROR_FAILED,
01099 "Reply was neither a method return nor an exception");
01100 goto error;
01101 }
01102
01103 error:
01104 dbus_set_g_error (error, &derror);
01105 dbus_error_free (&derror);
01106 return FALSE;
01107 }
01108
01120 void
01121 dbus_gproxy_call_no_reply (DBusGProxy *proxy,
01122 const char *method,
01123 int first_arg_type,
01124 ...)
01125 {
01126 DBusMessage *message;
01127 va_list args;
01128
01129 g_return_if_fail (DBUS_IS_GPROXY (proxy));
01130
01131 message = dbus_message_new_method_call (proxy->service,
01132 proxy->path,
01133 proxy->interface,
01134 method);
01135 if (message == NULL)
01136 goto oom;
01137
01138 dbus_message_set_no_reply (message, TRUE);
01139
01140 va_start (args, first_arg_type);
01141 if (!dbus_message_append_args_valist (message, first_arg_type,
01142 args)) {
01143 va_end (args);
01144 goto oom;
01145 }
01146 va_end (args);
01147
01148 if (!dbus_connection_send (proxy->manager->connection,
01149 message,
01150 NULL))
01151 goto oom;
01152
01153 return;
01154
01155 oom:
01156 g_error ("Out of memory");
01157 }
01158
01177 void
01178 dbus_gproxy_send (DBusGProxy *proxy,
01179 DBusMessage *message,
01180 dbus_uint32_t *client_serial)
01181 {
01182 g_return_if_fail (DBUS_IS_GPROXY (proxy));
01183
01184 if (proxy->service)
01185 {
01186 if (!dbus_message_set_destination (message, proxy->service))
01187 g_error ("Out of memory");
01188 }
01189 if (proxy->path)
01190 {
01191 if (!dbus_message_set_path (message, proxy->path))
01192 g_error ("Out of memory");
01193 }
01194 if (proxy->interface)
01195 {
01196 if (!dbus_message_set_interface (message, proxy->interface))
01197 g_error ("Out of memory");
01198 }
01199
01200 if (!dbus_connection_send (proxy->manager->connection, message, client_serial))
01201 g_error ("Out of memory\n");
01202 }
01203
01204 void
01205 dbus_gproxy_connect_signal (DBusGProxy *proxy,
01206 const char *signal_name,
01207 DBusGProxySignalHandler handler,
01208 void *data,
01209 GClosureNotify free_data_func)
01210 {
01211 GClosure *closure;
01212 char *detail;
01213
01214 g_return_if_fail (DBUS_IS_GPROXY (proxy));
01215 g_return_if_fail (signal_name != NULL);
01216 g_return_if_fail (handler != NULL);
01217
01218 detail = create_signal_detail (proxy->interface, signal_name);
01219
01220 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func);
01221 g_signal_connect_closure_by_id (G_OBJECT (proxy),
01222 signals[RECEIVED],
01223 g_quark_from_string (detail),
01224 closure, FALSE);
01225
01226 g_free (detail);
01227 }
01228
01229 void
01230 dbus_gproxy_disconnect_signal (DBusGProxy *proxy,
01231 const char *signal_name,
01232 DBusGProxySignalHandler handler,
01233 void *data)
01234 {
01235 char *detail;
01236 GQuark q;
01237
01238 g_return_if_fail (DBUS_IS_GPROXY (proxy));
01239 g_return_if_fail (signal_name != NULL);
01240 g_return_if_fail (handler != NULL);
01241
01242 detail = create_signal_detail (proxy->interface, signal_name);
01243 q = g_quark_try_string (detail);
01244 g_free (detail);
01245
01246 #ifndef G_DISABLE_CHECKS
01247 if (q == 0)
01248 {
01249 g_warning ("%s: No signal handlers for %s found on this DBusGProxy",
01250 G_GNUC_FUNCTION, signal_name);
01251 return;
01252 }
01253 #endif
01254
01255 g_signal_handlers_disconnect_matched (G_OBJECT (proxy),
01256 G_SIGNAL_MATCH_DETAIL |
01257 G_SIGNAL_MATCH_FUNC |
01258 G_SIGNAL_MATCH_DATA,
01259 signals[RECEIVED],
01260 q,
01261 NULL,
01262 G_CALLBACK (handler), data);
01263 }
01264
01267 #ifdef DBUS_BUILD_TESTS
01268
01274 dbus_bool_t
01275 _dbus_gproxy_test (void)
01276 {
01277
01278
01279 return TRUE;
01280 }
01281
01282 #endif