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