Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-gproxy.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-gcall.c convenience routines for calling methods, etc. 00003 * 00004 * Copyright (C) 2003, 2004 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 /* Lock controlling get/set manager as data on each connection */ 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 /* Proxy managers keep the connection alive, which means that 00145 * DBusGProxy indirectly does. To free a connection you have to free 00146 * all the proxies referring to it. 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 /* can't have any proxies left since they hold 00191 * a reference to the proxy manager. 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 /* skip nul and do the next substring */ 00236 for (p += 1; *p != '\0'; p++) 00237 h = (h << 5) - h + *p; 00238 00239 /* skip nul again and another substring */ 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 /* we don't hold a reference to the proxies in the list, 00378 * as they ref the GProxyManager 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 /* FIXME Escaping is required here */ 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 /* We have to add the match rule to the server, 00436 * but FIXME only if the server is a message bus, 00437 * not if it's a peer. 00438 */ 00439 char *rule; 00440 00441 rule = g_proxy_get_match_rule (proxy); 00442 00443 /* We don't check for errors; it's not like anyone would handle them, 00444 * and we don't want a round trip here. 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 /* Destroy all the proxies, quite possibly resulting in unreferencing 00574 * the proxy manager and the connection as well. 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 /* Emit the signal */ 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 /* "Handling" signals doesn't make sense, they are for everyone 00658 * who cares 00659 */ 00660 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00661 } 00662 00663 00664 00665 /* ---------- DBusGProxy -------------- */ 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 /* Nothing */ 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 /* FIXME do we need the GTK_IN_DESTRUCTION style flag 00752 * from GtkObject? 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 /* If the quark isn't preexisting, there's no way there 00790 * are any handlers connected. We don't want to create 00791 * extra quarks for every possible signal. 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, /* class_finalize */ 00829 NULL, /* class_data */ 00830 sizeof (DBusGProxy), 00831 0, /* n_preallocs */ 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 /* These should all be construct-only mandatory properties, 00856 * for now we just don't let people use g_object_new(). 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 /* FIXME we should create a pending call that's 01090 * immediately completed with an error status without 01091 * ever going on the wire. 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_get_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 return TRUE; 01156 01157 case DBUS_MESSAGE_TYPE_ERROR: 01158 dbus_set_error_from_message (&derror, message); 01159 goto error; 01160 01161 default: 01162 dbus_set_error (&derror, DBUS_ERROR_FAILED, 01163 "Reply was neither a method return nor an exception"); 01164 goto error; 01165 } 01166 01167 error: 01168 dbus_set_g_error (error, &derror); 01169 dbus_error_free (&derror); 01170 return FALSE; 01171 } 01172 01184 void 01185 dbus_g_proxy_call_no_reply (DBusGProxy *proxy, 01186 const char *method, 01187 int first_arg_type, 01188 ...) 01189 { 01190 DBusMessage *message; 01191 va_list args; 01192 01193 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); 01194 01195 message = dbus_message_new_method_call (proxy->service, 01196 proxy->path, 01197 proxy->interface, 01198 method); 01199 if (message == NULL) 01200 goto oom; 01201 01202 dbus_message_set_no_reply (message, TRUE); 01203 01204 va_start (args, first_arg_type); 01205 if (!dbus_message_append_args_valist (message, first_arg_type, 01206 args)) 01207 goto oom; 01208 va_end (args); 01209 01210 if (!dbus_connection_send (proxy->manager->connection, 01211 message, 01212 NULL)) 01213 goto oom; 01214 01215 return; 01216 01217 oom: 01218 g_error ("Out of memory"); 01219 } 01220 01239 void 01240 dbus_g_proxy_send (DBusGProxy *proxy, 01241 DBusMessage *message, 01242 dbus_uint32_t *client_serial) 01243 { 01244 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); 01245 01246 if (proxy->service) 01247 { 01248 if (!dbus_message_set_destination (message, proxy->service)) 01249 g_error ("Out of memory"); 01250 } 01251 if (proxy->path) 01252 { 01253 if (!dbus_message_set_path (message, proxy->path)) 01254 g_error ("Out of memory"); 01255 } 01256 if (proxy->interface) 01257 { 01258 if (!dbus_message_set_interface (message, proxy->interface)) 01259 g_error ("Out of memory"); 01260 } 01261 01262 if (!dbus_connection_send (proxy->manager->connection, message, client_serial)) 01263 g_error ("Out of memory\n"); 01264 } 01265 01281 void 01282 dbus_g_proxy_connect_signal (DBusGProxy *proxy, 01283 const char *signal_name, 01284 GCallback handler, 01285 void *data, 01286 GClosureNotify free_data_func) 01287 { 01288 GClosure *closure; 01289 char *detail; 01290 01291 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); 01292 g_return_if_fail (signal_name != NULL); 01293 g_return_if_fail (handler != NULL); 01294 01295 detail = create_signal_detail (proxy->interface, signal_name); 01296 01297 closure = g_cclosure_new (G_CALLBACK (handler), data, free_data_func); 01298 g_signal_connect_closure_by_id (G_OBJECT (proxy), 01299 signals[RECEIVED], 01300 g_quark_from_string (detail), 01301 closure, FALSE); 01302 01303 g_free (detail); 01304 } 01305 01315 void 01316 dbus_g_proxy_disconnect_signal (DBusGProxy *proxy, 01317 const char *signal_name, 01318 GCallback handler, 01319 void *data) 01320 { 01321 char *detail; 01322 GQuark q; 01323 01324 g_return_if_fail (DBUS_IS_G_PROXY (proxy)); 01325 g_return_if_fail (signal_name != NULL); 01326 g_return_if_fail (handler != NULL); 01327 01328 detail = create_signal_detail (proxy->interface, signal_name); 01329 q = g_quark_try_string (detail); 01330 g_free (detail); 01331 01332 #ifndef G_DISABLE_CHECKS 01333 if (q == 0) 01334 { 01335 g_warning ("%s: No signal handlers for %s found on this DBusGProxy", 01336 G_GNUC_FUNCTION, signal_name); 01337 return; 01338 } 01339 #endif 01340 01341 g_signal_handlers_disconnect_matched (G_OBJECT (proxy), 01342 G_SIGNAL_MATCH_DETAIL | 01343 G_SIGNAL_MATCH_FUNC | 01344 G_SIGNAL_MATCH_DATA, 01345 signals[RECEIVED], 01346 q, 01347 NULL, 01348 G_CALLBACK (handler), data); 01349 } 01350 01353 #ifdef DBUS_BUILD_TESTS 01354 01360 gboolean 01361 _dbus_g_proxy_test (void) 01362 { 01363 01364 01365 return TRUE; 01366 } 01367 01368 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Oct 12 02:07:53 2004 for D-BUS by doxygen 1.3.7