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