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 DBusGProxyManager *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 DBusGProxyManager *
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 return manager;
00168 }
00169
00170 static void
00171 dbus_gproxy_manager_unref (DBusGProxyManager *manager)
00172 {
00173 g_assert (manager != NULL);
00174 g_assert (manager->refcount > 0);
00175
00176 LOCK_MANAGER (manager);
00177 manager->refcount -= 1;
00178 if (manager->refcount == 0)
00179 {
00180 UNLOCK_MANAGER (manager);
00181
00182 if (manager->proxy_lists)
00183 {
00184
00185
00186
00187 g_assert (g_hash_table_size (manager->proxy_lists) == 0);
00188
00189 g_hash_table_destroy (manager->proxy_lists);
00190 manager->proxy_lists = NULL;
00191 }
00192
00193 g_static_mutex_free (&manager->lock);
00194
00195 g_static_mutex_lock (&connection_gproxy_lock);
00196
00197 dbus_connection_remove_filter (manager->connection, dbus_gproxy_manager_filter,
00198 manager);
00199
00200 dbus_connection_set_data (manager->connection,
00201 gproxy_manager_slot,
00202 NULL, NULL);
00203
00204 g_static_mutex_unlock (&connection_gproxy_lock);
00205
00206 dbus_connection_unref (manager->connection);
00207 g_free (manager);
00208
00209 dbus_connection_free_data_slot (&gproxy_manager_slot);
00210 }
00211 else
00212 {
00213 UNLOCK_MANAGER (manager);
00214 }
00215 }
00216
00217 static guint
00218 tristring_hash (gconstpointer key)
00219 {
00220 const char *p = key;
00221 guint h = *p;
00222
00223 if (h)
00224 {
00225 for (p += 1; *p != '\0'; p++)
00226 h = (h << 5) - h + *p;
00227 }
00228
00229
00230 for (p += 1; *p != '\0'; p++)
00231 h = (h << 5) - h + *p;
00232
00233
00234 for (p += 1; *p != '\0'; p++)
00235 h = (h << 5) - h + *p;
00236
00237 return h;
00238 }
00239
00240 static gboolean
00241 strequal_len (const char *a,
00242 const char *b,
00243 size_t *lenp)
00244 {
00245 size_t a_len;
00246 size_t b_len;
00247
00248 a_len = strlen (a);
00249 b_len = strlen (b);
00250
00251 if (a_len != b_len)
00252 return FALSE;
00253
00254 if (memcmp (a, b, a_len) != 0)
00255 return FALSE;
00256
00257 *lenp = a_len;
00258
00259 return TRUE;
00260 }
00261
00262 static gboolean
00263 tristring_equal (gconstpointer a,
00264 gconstpointer b)
00265 {
00266 const char *ap = a;
00267 const char *bp = b;
00268 size_t len;
00269
00270 if (!strequal_len (ap, bp, &len))
00271 return FALSE;
00272
00273 ap += len + 1;
00274 bp += len + 1;
00275
00276 if (!strequal_len (ap, bp, &len))
00277 return FALSE;
00278
00279 ap += len + 1;
00280 bp += len + 1;
00281
00282 if (strcmp (ap, bp) != 0)
00283 return FALSE;
00284
00285 return TRUE;
00286 }
00287
00288 static char*
00289 tristring_alloc_from_strings (size_t padding_before,
00290 const char *service,
00291 const char *path,
00292 const char *interface)
00293 {
00294 size_t service_len, iface_len, path_len, len;
00295 char *tri;
00296
00297 if (service)
00298 service_len = strlen (service);
00299 else
00300 service_len = 0;
00301
00302 path_len = strlen (path);
00303
00304 iface_len = strlen (interface);
00305
00306 tri = g_malloc (padding_before + service_len + path_len + iface_len + 3);
00307
00308 len = padding_before;
00309
00310 if (service)
00311 memcpy (&tri[len], service, service_len);
00312
00313 len += service_len;
00314 tri[len] = '\0';
00315 len += 1;
00316
00317 g_assert (len == (padding_before + service_len + 1));
00318
00319 memcpy (&tri[len], path, path_len);
00320 len += path_len;
00321 tri[len] = '\0';
00322 len += 1;
00323
00324 g_assert (len == (padding_before + service_len + path_len + 2));
00325
00326 memcpy (&tri[len], interface, iface_len);
00327 len += iface_len;
00328 tri[len] = '\0';
00329 len += 1;
00330
00331 g_assert (len == (padding_before + service_len + path_len + iface_len + 3));
00332
00333 return tri;
00334 }
00335
00336 static char*
00337 tristring_from_proxy (DBusGProxy *proxy)
00338 {
00339 return tristring_alloc_from_strings (0,
00340 proxy->service,
00341 proxy->path,
00342 proxy->interface);
00343 }
00344
00345 static char*
00346 tristring_from_message (DBusMessage *message)
00347 {
00348 return tristring_alloc_from_strings (0,
00349 dbus_message_get_sender (message),
00350 dbus_message_get_path (message),
00351 dbus_message_get_interface (message));
00352 }
00353
00354 static DBusGProxyList*
00355 gproxy_list_new (DBusGProxy *first_proxy)
00356 {
00357 DBusGProxyList *list;
00358
00359 list = (void*) tristring_alloc_from_strings (G_STRUCT_OFFSET (DBusGProxyList, name),
00360 first_proxy->service,
00361 first_proxy->path,
00362 first_proxy->interface);
00363 list->proxies = NULL;
00364
00365 return list;
00366 }
00367
00368 static void
00369 gproxy_list_free (DBusGProxyList *list)
00370 {
00371
00372
00373
00374 g_slist_free (list->proxies);
00375
00376 g_free (list);
00377 }
00378
00379 static char*
00380 gproxy_get_match_rule (DBusGProxy *proxy)
00381 {
00382
00383
00384 if (proxy->service)
00385 return g_strdup_printf ("type='signal',sender='%s',path='%s',interface='%s'",
00386 proxy->service, proxy->path, proxy->interface);
00387 else
00388 return g_strdup_printf ("type='signal',path='%s',interface='%s'",
00389 proxy->path, proxy->interface);
00390 }
00391
00392 static void
00393 dbus_gproxy_manager_register (DBusGProxyManager *manager,
00394 DBusGProxy *proxy)
00395 {
00396 DBusGProxyList *list;
00397
00398 LOCK_MANAGER (manager);
00399
00400 if (manager->proxy_lists == NULL)
00401 {
00402 list = NULL;
00403 manager->proxy_lists = g_hash_table_new_full (tristring_hash,
00404 tristring_equal,
00405 NULL,
00406 (GFreeFunc) gproxy_list_free);
00407 }
00408 else
00409 {
00410 char *tri;
00411
00412 tri = tristring_from_proxy (proxy);
00413
00414 list = g_hash_table_lookup (manager->proxy_lists, tri);
00415
00416 g_free (tri);
00417 }
00418
00419 if (list == NULL)
00420 {
00421 list = gproxy_list_new (proxy);
00422
00423 g_hash_table_replace (manager->proxy_lists,
00424 list->name, list);
00425 }
00426
00427 if (list->proxies == NULL)
00428 {
00429
00430
00431
00432
00433 char *rule;
00434
00435 rule = gproxy_get_match_rule (proxy);
00436
00437
00438
00439
00440 dbus_bus_add_match (manager->connection,
00441 rule, NULL);
00442
00443 g_free (rule);
00444 }
00445
00446 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00447
00448 list->proxies = g_slist_prepend (list->proxies, proxy);
00449
00450 UNLOCK_MANAGER (manager);
00451 }
00452
00453 static void
00454 dbus_gproxy_manager_unregister (DBusGProxyManager *manager,
00455 DBusGProxy *proxy)
00456 {
00457 DBusGProxyList *list;
00458 char *tri;
00459
00460 LOCK_MANAGER (manager);
00461
00462 #ifndef G_DISABLE_CHECKS
00463 if (manager->proxy_lists == NULL)
00464 {
00465 g_warning ("Trying to unregister a proxy but there aren't any registered");
00466 return;
00467 }
00468 #endif
00469
00470 tri = tristring_from_proxy (proxy);
00471
00472 list = g_hash_table_lookup (manager->proxy_lists, tri);
00473
00474 #ifndef G_DISABLE_CHECKS
00475 if (list == NULL)
00476 {
00477 g_warning ("Trying to unregister a proxy but it isn't registered");
00478 return;
00479 }
00480 #endif
00481
00482 g_assert (g_slist_find (list->proxies, proxy) != NULL);
00483
00484 list->proxies = g_slist_remove (list->proxies, proxy);
00485
00486 g_assert (g_slist_find (list->proxies, proxy) == NULL);
00487
00488 if (list->proxies == NULL)
00489 {
00490 g_hash_table_remove (manager->proxy_lists,
00491 tri);
00492 list = NULL;
00493 }
00494
00495 if (g_hash_table_size (manager->proxy_lists) == 0)
00496 {
00497 g_hash_table_destroy (manager->proxy_lists);
00498 manager->proxy_lists = NULL;
00499 }
00500
00501 g_free (tri);
00502
00503 UNLOCK_MANAGER (manager);
00504 }
00505
00506 static void
00507 list_proxies_foreach (gpointer key,
00508 gpointer value,
00509 gpointer user_data)
00510 {
00511 DBusGProxyList *list;
00512 GSList **ret;
00513 GSList *tmp;
00514
00515 list = value;
00516 ret = user_data;
00517
00518 tmp = list->proxies;
00519 while (tmp != NULL)
00520 {
00521 DBusGProxy *proxy = DBUS_GPROXY (tmp->data);
00522
00523 g_object_ref (proxy);
00524 *ret = g_slist_prepend (*ret, proxy);
00525
00526 tmp = tmp->next;
00527 }
00528 }
00529
00530 static GSList*
00531 dbus_gproxy_manager_list_all (DBusGProxyManager *manager)
00532 {
00533 GSList *ret;
00534
00535 ret = NULL;
00536
00537 if (manager->proxy_lists)
00538 {
00539 g_hash_table_foreach (manager->proxy_lists,
00540 list_proxies_foreach,
00541 &ret);
00542 }
00543
00544 return ret;
00545 }
00546
00547 static DBusHandlerResult
00548 dbus_gproxy_manager_filter (DBusConnection *connection,
00549 DBusMessage *message,
00550 void *user_data)
00551 {
00552 DBusGProxyManager *manager;
00553
00554 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
00555 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00556
00557 manager = user_data;
00558
00559 dbus_gproxy_manager_ref (manager);
00560
00561 LOCK_MANAGER (manager);
00562
00563 if (dbus_message_is_signal (message,
00564 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
00565 "Disconnected"))
00566 {
00567
00568
00569
00570 GSList *all;
00571 GSList *tmp;
00572
00573 all = dbus_gproxy_manager_list_all (manager);
00574
00575 tmp = all;
00576 while (tmp != NULL)
00577 {
00578 DBusGProxy *proxy;
00579
00580 proxy = DBUS_GPROXY (tmp->data);
00581
00582 UNLOCK_MANAGER (manager);
00583 dbus_gproxy_destroy (proxy);
00584 g_object_unref (G_OBJECT (proxy));
00585 LOCK_MANAGER (manager);
00586
00587 tmp = tmp->next;
00588 }
00589
00590 g_slist_free (all);
00591
00592 #ifndef G_DISABLE_CHECKS
00593 if (manager->proxy_lists != NULL)
00594 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.");
00595 #endif
00596 }
00597 else
00598 {
00599 char *tri;
00600 DBusGProxyList *list;
00601
00602 tri = tristring_from_message (message);
00603
00604 if (manager->proxy_lists)
00605 list = g_hash_table_lookup (manager->proxy_lists, tri);
00606 else
00607 list = NULL;
00608
00609 #if 0
00610 g_print ("proxy got %s,%s,%s = list %p\n",
00611 tri,
00612 tri + strlen (tri) + 1,
00613 tri + strlen (tri) + 1 + strlen (tri + strlen (tri) + 1) + 1,
00614 list);
00615 #endif
00616
00617 g_free (tri);
00618
00619
00620
00621 if (list != NULL)
00622 {
00623 GSList *tmp;
00624 GSList *copy;
00625
00626 copy = g_slist_copy (list->proxies);
00627 g_slist_foreach (copy, (GFunc) g_object_ref, NULL);
00628
00629 tmp = copy;
00630 while (tmp != NULL)
00631 {
00632 DBusGProxy *proxy;
00633
00634 proxy = DBUS_GPROXY (tmp->data);
00635
00636 UNLOCK_MANAGER (manager);
00637 dbus_gproxy_emit_received (proxy, message);
00638 g_object_unref (G_OBJECT (proxy));
00639 LOCK_MANAGER (manager);
00640
00641 tmp = tmp->next;
00642 }
00643
00644 g_slist_free (copy);
00645 }
00646 }
00647
00648 UNLOCK_MANAGER (manager);
00649 dbus_gproxy_manager_unref (manager);
00650
00651
00652
00653
00654 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663 enum
00664 {
00665 DESTROY,
00666 RECEIVED,
00667 LAST_SIGNAL
00668 };
00669
00670 static void *parent_class;
00671 static guint signals[LAST_SIGNAL] = { 0 };
00672
00673 static void
00674 dbus_gproxy_init (DBusGProxy *proxy)
00675 {
00676
00677 }
00678
00679 static void
00680 dbus_gproxy_class_init (DBusGProxyClass *klass)
00681 {
00682 GObjectClass *object_class = G_OBJECT_CLASS (klass);
00683
00684 parent_class = g_type_class_peek_parent (klass);
00685
00686 object_class->finalize = dbus_gproxy_finalize;
00687 object_class->dispose = dbus_gproxy_dispose;
00688
00689 signals[DESTROY] =
00690 g_signal_new ("destroy",
00691 G_OBJECT_CLASS_TYPE (object_class),
00692 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
00693 0,
00694 NULL, NULL,
00695 g_cclosure_marshal_VOID__VOID,
00696 G_TYPE_NONE, 0);
00697
00698 signals[RECEIVED] =
00699 g_signal_new ("received",
00700 G_OBJECT_CLASS_TYPE (object_class),
00701 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
00702 0,
00703 NULL, NULL,
00704 g_cclosure_marshal_VOID__BOXED,
00705 G_TYPE_NONE, 1,
00706 DBUS_TYPE_MESSAGE);
00707 }
00708
00709
00710 static void
00711 dbus_gproxy_dispose (GObject *object)
00712 {
00713 DBusGProxy *proxy;
00714
00715 proxy = DBUS_GPROXY (object);
00716
00717 g_signal_emit (object, signals[DESTROY], 0);
00718
00719 G_OBJECT_CLASS (parent_class)->dispose (object);
00720 }
00721
00722 static void
00723 dbus_gproxy_finalize (GObject *object)
00724 {
00725 DBusGProxy *proxy;
00726
00727 proxy = DBUS_GPROXY (object);
00728
00729 if (proxy->manager)
00730 {
00731 dbus_gproxy_manager_unregister (proxy->manager, proxy);
00732 dbus_gproxy_manager_unref (proxy->manager);
00733 }
00734
00735 g_free (proxy->service);
00736 g_free (proxy->path);
00737 g_free (proxy->interface);
00738
00739 G_OBJECT_CLASS (parent_class)->finalize (object);
00740 }
00741
00742 static void
00743 dbus_gproxy_destroy (DBusGProxy *proxy)
00744 {
00745
00746
00747
00748 g_object_run_dispose (G_OBJECT (proxy));
00749 }
00750
00751 static char*
00752 create_signal_detail (const char *interface,
00753 const char *signal)
00754 {
00755 GString *str;
00756
00757 str = g_string_new (interface);
00758
00759 g_string_append (str, ".");
00760
00761 g_string_append (str, signal);
00762
00763 return g_string_free (str, FALSE);
00764 }
00765
00766 static void
00767 dbus_gproxy_emit_received (DBusGProxy *proxy,
00768 DBusMessage *message)
00769 {
00770 const char *interface;
00771 const char *signal;
00772 char *detail;
00773 GQuark q;
00774
00775 interface = dbus_message_get_interface (message);
00776 signal = dbus_message_get_member (message);
00777
00778 g_assert (interface != NULL);
00779 g_assert (signal != NULL);
00780
00781 detail = create_signal_detail (interface, signal);
00782
00783
00784
00785
00786
00787 q = g_quark_try_string (detail);
00788
00789 if (q != 0)
00790 g_signal_emit (G_OBJECT (proxy),
00791 signals[RECEIVED],
00792 q,
00793 message);
00794
00795 g_free (detail);
00796 }
00797
00809 GType
00810 dbus_gproxy_get_type (void)
00811 {
00812 static GType object_type = 0;
00813
00814 if (!object_type)
00815 {
00816 static const GTypeInfo object_info =
00817 {
00818 sizeof (DBusGProxyClass),
00819 (GBaseInitFunc) NULL,
00820 (GBaseFinalizeFunc) NULL,
00821 (GClassInitFunc) dbus_gproxy_class_init,
00822 NULL,
00823 NULL,
00824 sizeof (DBusGProxy),
00825 0,
00826 (GInstanceInitFunc) dbus_gproxy_init,
00827 };
00828
00829 object_type = g_type_register_static (G_TYPE_OBJECT,
00830 "DBusGProxy",
00831 &object_info, 0);
00832 }
00833
00834 return object_type;
00835 }
00836
00837 static DBusGProxy*
00838 dbus_gproxy_new (DBusConnection *connection,
00839 const char *service_name,
00840 const char *path_name,
00841 const char *interface_name)
00842 {
00843 DBusGProxy *proxy;
00844
00845 g_assert (connection != NULL);
00846
00847 proxy = g_object_new (DBUS_TYPE_GPROXY, NULL);
00848
00849
00850
00851
00852
00853 proxy->manager = dbus_gproxy_manager_get (connection);
00854
00855 proxy->service = g_strdup (service_name);
00856 proxy->path = g_strdup (path_name);
00857 proxy->interface = g_strdup (interface_name);
00858
00859 dbus_gproxy_manager_register (proxy->manager, proxy);
00860
00861 return proxy;
00862 }
00863
00886 DBusGProxy*
00887 dbus_gproxy_new_for_service (DBusConnection *connection,
00888 const char *service_name,
00889 const char *path_name,
00890 const char *interface_name)
00891 {
00892 DBusGProxy *proxy;
00893
00894 g_return_val_if_fail (connection != NULL, NULL);
00895 g_return_val_if_fail (service_name != NULL, NULL);
00896 g_return_val_if_fail (path_name != NULL, NULL);
00897 g_return_val_if_fail (interface_name != NULL, NULL);
00898
00899 proxy = dbus_gproxy_new (connection, service_name,
00900 path_name, interface_name);
00901
00902 return proxy;
00903 }
00904
00928 DBusGProxy*
00929 dbus_gproxy_new_for_service_owner (DBusConnection *connection,
00930 const char *service_name,
00931 const char *path_name,
00932 const char *interface_name,
00933 GError **error)
00934 {
00935 g_return_val_if_fail (connection != NULL, NULL);
00936 g_return_val_if_fail (service_name != NULL, NULL);
00937 g_return_val_if_fail (path_name != NULL, NULL);
00938 g_return_val_if_fail (interface_name != NULL, NULL);
00939
00940
00941 }
00942
00957 DBusGProxy*
00958 dbus_gproxy_new_for_peer (DBusConnection *connection,
00959 const char *path_name,
00960 const char *interface_name)
00961 {
00962 DBusGProxy *proxy;
00963
00964 g_return_val_if_fail (connection != NULL, NULL);
00965 g_return_val_if_fail (path_name != NULL, NULL);
00966 g_return_val_if_fail (interface_name != NULL, NULL);
00967
00968 proxy = dbus_gproxy_new (connection, NULL,
00969 path_name, interface_name);
00970
00971 return proxy;
00972 }
00973
00993 DBusPendingCall*
00994 dbus_gproxy_begin_call (DBusGProxy *proxy,
00995 const char *method,
00996 int first_arg_type,
00997 ...)
00998 {
00999 DBusPendingCall *pending;
01000 DBusMessage *message;
01001 va_list args;
01002
01003 g_return_val_if_fail (DBUS_IS_GPROXY (proxy), NULL);
01004
01005 message = dbus_message_new_method_call (proxy->service,
01006 proxy->path,
01007 proxy->interface,
01008 method);
01009 if (message == NULL)
01010 goto oom;
01011
01012 va_start (args, first_arg_type);
01013 if (!dbus_message_append_args_valist (message, first_arg_type,
01014 args))
01015 goto oom;
01016 va_end (args);
01017
01018 if (!dbus_connection_send_with_reply (proxy->manager->connection,
01019 message,
01020 &pending,
01021 -1))
01022 goto oom;
01023
01024 return pending;
01025
01026 oom:
01027
01028
01029
01030
01031
01032 g_error ("Out of memory");
01033 return NULL;
01034 }
01035
01061 gboolean
01062 dbus_gproxy_end_call (DBusGProxy *proxy,
01063 DBusPendingCall *pending,
01064 GError **error,
01065 int first_arg_type,
01066 ...)
01067 {
01068 DBusMessage *message;
01069 va_list args;
01070 DBusError derror;
01071
01072 g_return_val_if_fail (DBUS_IS_GPROXY (proxy), FALSE);
01073 g_return_val_if_fail (pending != NULL, FALSE);
01074
01075 dbus_pending_call_block (pending);
01076 message = dbus_pending_call_get_reply (pending);
01077
01078 g_assert (message != NULL);
01079
01080 dbus_error_init (&derror);
01081
01082 switch (dbus_message_get_type (message))
01083 {
01084 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
01085 va_start (args, first_arg_type);
01086 if (!dbus_message_get_args_valist (message, &derror, first_arg_type, args))
01087 {
01088 va_end (args);
01089 goto error;
01090 }
01091 va_end (args);
01092
01093 return TRUE;
01094
01095 case DBUS_MESSAGE_TYPE_ERROR:
01096 dbus_set_error_from_message (&derror, message);
01097 goto error;
01098
01099 default:
01100 dbus_set_error (&derror, DBUS_ERROR_FAILED,
01101 "Reply was neither a method return nor an exception");
01102 goto error;
01103 }
01104
01105 error:
01106 dbus_set_g_error (error, &derror);
01107 dbus_error_free (&derror);
01108 return FALSE;
01109 }
01110
01122 void
01123 dbus_gproxy_call_no_reply (DBusGProxy *proxy,
01124 const char *method,
01125 int first_arg_type,
01126 ...)
01127 {
01128 DBusMessage *message;
01129 va_list args;
01130
01131 g_return_if_fail (DBUS_IS_GPROXY (proxy));
01132
01133 message = dbus_message_new_method_call (proxy->service,
01134 proxy->path,
01135 proxy->interface,
01136 method);
01137 if (message == NULL)
01138 goto oom;
01139
01140 dbus_message_set_no_reply (message, TRUE);
01141
01142 va_start (args, first_arg_type);
01143 if (!dbus_message_append_args_valist (message, first_arg_type,
01144 args))
01145 goto oom;
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