D-Bus 1.4.10
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server.c DBusServer object 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-server.h" 00026 #include "dbus-server-unix.h" 00027 #include "dbus-server-socket.h" 00028 #include "dbus-string.h" 00029 #ifdef DBUS_BUILD_TESTS 00030 #include "dbus-server-debug-pipe.h" 00031 #endif 00032 #include "dbus-address.h" 00033 #include "dbus-protocol.h" 00034 00056 /* this is a little fragile since it assumes the address doesn't 00057 * already have a guid, but it shouldn't 00058 */ 00059 static char* 00060 copy_address_with_guid_appended (const DBusString *address, 00061 const DBusString *guid_hex) 00062 { 00063 DBusString with_guid; 00064 char *retval; 00065 00066 if (!_dbus_string_init (&with_guid)) 00067 return NULL; 00068 00069 if (!_dbus_string_copy (address, 0, &with_guid, 00070 _dbus_string_get_length (&with_guid)) || 00071 !_dbus_string_append (&with_guid, ",guid=") || 00072 !_dbus_string_copy (guid_hex, 0, 00073 &with_guid, _dbus_string_get_length (&with_guid))) 00074 { 00075 _dbus_string_free (&with_guid); 00076 return NULL; 00077 } 00078 00079 retval = NULL; 00080 _dbus_string_steal_data (&with_guid, &retval); 00081 00082 _dbus_string_free (&with_guid); 00083 00084 return retval; /* may be NULL if steal_data failed */ 00085 } 00086 00096 dbus_bool_t 00097 _dbus_server_init_base (DBusServer *server, 00098 const DBusServerVTable *vtable, 00099 const DBusString *address) 00100 { 00101 server->vtable = vtable; 00102 server->refcount.value = 1; 00103 00104 server->address = NULL; 00105 server->watches = NULL; 00106 server->timeouts = NULL; 00107 server->published_address = FALSE; 00108 00109 if (!_dbus_string_init (&server->guid_hex)) 00110 return FALSE; 00111 00112 _dbus_generate_uuid (&server->guid); 00113 00114 if (!_dbus_uuid_encode (&server->guid, &server->guid_hex)) 00115 goto failed; 00116 00117 server->address = copy_address_with_guid_appended (address, 00118 &server->guid_hex); 00119 if (server->address == NULL) 00120 goto failed; 00121 00122 _dbus_mutex_new_at_location (&server->mutex); 00123 if (server->mutex == NULL) 00124 goto failed; 00125 00126 server->watches = _dbus_watch_list_new (); 00127 if (server->watches == NULL) 00128 goto failed; 00129 00130 server->timeouts = _dbus_timeout_list_new (); 00131 if (server->timeouts == NULL) 00132 goto failed; 00133 00134 _dbus_data_slot_list_init (&server->slot_list); 00135 00136 _dbus_verbose ("Initialized server on address %s\n", server->address); 00137 00138 return TRUE; 00139 00140 failed: 00141 _dbus_mutex_free_at_location (&server->mutex); 00142 server->mutex = NULL; 00143 if (server->watches) 00144 { 00145 _dbus_watch_list_free (server->watches); 00146 server->watches = NULL; 00147 } 00148 if (server->timeouts) 00149 { 00150 _dbus_timeout_list_free (server->timeouts); 00151 server->timeouts = NULL; 00152 } 00153 if (server->address) 00154 { 00155 dbus_free (server->address); 00156 server->address = NULL; 00157 } 00158 _dbus_string_free (&server->guid_hex); 00159 00160 return FALSE; 00161 } 00162 00169 void 00170 _dbus_server_finalize_base (DBusServer *server) 00171 { 00172 /* We don't have the lock, but nobody should be accessing 00173 * concurrently since they don't have a ref 00174 */ 00175 #ifndef DBUS_DISABLE_CHECKS 00176 _dbus_assert (!server->have_server_lock); 00177 #endif 00178 _dbus_assert (server->disconnected); 00179 00180 /* calls out to application code... */ 00181 _dbus_data_slot_list_free (&server->slot_list); 00182 00183 dbus_server_set_new_connection_function (server, NULL, NULL, NULL); 00184 00185 _dbus_watch_list_free (server->watches); 00186 _dbus_timeout_list_free (server->timeouts); 00187 00188 _dbus_mutex_free_at_location (&server->mutex); 00189 00190 dbus_free (server->address); 00191 00192 dbus_free_string_array (server->auth_mechanisms); 00193 00194 _dbus_string_free (&server->guid_hex); 00195 } 00196 00197 00199 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00200 DBusWatch *watch); 00202 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00203 DBusWatch *watch); 00205 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00206 DBusWatch *watch, 00207 dbus_bool_t enabled); 00208 00209 static dbus_bool_t 00210 protected_change_watch (DBusServer *server, 00211 DBusWatch *watch, 00212 DBusWatchAddFunction add_function, 00213 DBusWatchRemoveFunction remove_function, 00214 DBusWatchToggleFunction toggle_function, 00215 dbus_bool_t enabled) 00216 { 00217 DBusWatchList *watches; 00218 dbus_bool_t retval; 00219 00220 HAVE_LOCK_CHECK (server); 00221 00222 /* This isn't really safe or reasonable; a better pattern is the "do 00223 * everything, then drop lock and call out" one; but it has to be 00224 * propagated up through all callers 00225 */ 00226 00227 watches = server->watches; 00228 if (watches) 00229 { 00230 server->watches = NULL; 00231 _dbus_server_ref_unlocked (server); 00232 SERVER_UNLOCK (server); 00233 00234 if (add_function) 00235 retval = (* add_function) (watches, watch); 00236 else if (remove_function) 00237 { 00238 retval = TRUE; 00239 (* remove_function) (watches, watch); 00240 } 00241 else 00242 { 00243 retval = TRUE; 00244 (* toggle_function) (watches, watch, enabled); 00245 } 00246 00247 SERVER_LOCK (server); 00248 server->watches = watches; 00249 _dbus_server_unref_unlocked (server); 00250 00251 return retval; 00252 } 00253 else 00254 return FALSE; 00255 } 00256 00264 dbus_bool_t 00265 _dbus_server_add_watch (DBusServer *server, 00266 DBusWatch *watch) 00267 { 00268 HAVE_LOCK_CHECK (server); 00269 return protected_change_watch (server, watch, 00270 _dbus_watch_list_add_watch, 00271 NULL, NULL, FALSE); 00272 } 00273 00280 void 00281 _dbus_server_remove_watch (DBusServer *server, 00282 DBusWatch *watch) 00283 { 00284 HAVE_LOCK_CHECK (server); 00285 protected_change_watch (server, watch, 00286 NULL, 00287 _dbus_watch_list_remove_watch, 00288 NULL, FALSE); 00289 } 00290 00300 void 00301 _dbus_server_toggle_watch (DBusServer *server, 00302 DBusWatch *watch, 00303 dbus_bool_t enabled) 00304 { 00305 _dbus_assert (watch != NULL); 00306 00307 HAVE_LOCK_CHECK (server); 00308 protected_change_watch (server, watch, 00309 NULL, NULL, 00310 _dbus_watch_list_toggle_watch, 00311 enabled); 00312 } 00313 00315 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00316 DBusTimeout *timeout); 00318 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00319 DBusTimeout *timeout); 00321 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00322 DBusTimeout *timeout, 00323 dbus_bool_t enabled); 00324 00325 00326 static dbus_bool_t 00327 protected_change_timeout (DBusServer *server, 00328 DBusTimeout *timeout, 00329 DBusTimeoutAddFunction add_function, 00330 DBusTimeoutRemoveFunction remove_function, 00331 DBusTimeoutToggleFunction toggle_function, 00332 dbus_bool_t enabled) 00333 { 00334 DBusTimeoutList *timeouts; 00335 dbus_bool_t retval; 00336 00337 HAVE_LOCK_CHECK (server); 00338 00339 /* This isn't really safe or reasonable; a better pattern is the "do everything, then 00340 * drop lock and call out" one; but it has to be propagated up through all callers 00341 */ 00342 00343 timeouts = server->timeouts; 00344 if (timeouts) 00345 { 00346 server->timeouts = NULL; 00347 _dbus_server_ref_unlocked (server); 00348 SERVER_UNLOCK (server); 00349 00350 if (add_function) 00351 retval = (* add_function) (timeouts, timeout); 00352 else if (remove_function) 00353 { 00354 retval = TRUE; 00355 (* remove_function) (timeouts, timeout); 00356 } 00357 else 00358 { 00359 retval = TRUE; 00360 (* toggle_function) (timeouts, timeout, enabled); 00361 } 00362 00363 SERVER_LOCK (server); 00364 server->timeouts = timeouts; 00365 _dbus_server_unref_unlocked (server); 00366 00367 return retval; 00368 } 00369 else 00370 return FALSE; 00371 } 00372 00382 dbus_bool_t 00383 _dbus_server_add_timeout (DBusServer *server, 00384 DBusTimeout *timeout) 00385 { 00386 return protected_change_timeout (server, timeout, 00387 _dbus_timeout_list_add_timeout, 00388 NULL, NULL, FALSE); 00389 } 00390 00397 void 00398 _dbus_server_remove_timeout (DBusServer *server, 00399 DBusTimeout *timeout) 00400 { 00401 protected_change_timeout (server, timeout, 00402 NULL, 00403 _dbus_timeout_list_remove_timeout, 00404 NULL, FALSE); 00405 } 00406 00416 void 00417 _dbus_server_toggle_timeout (DBusServer *server, 00418 DBusTimeout *timeout, 00419 dbus_bool_t enabled) 00420 { 00421 protected_change_timeout (server, timeout, 00422 NULL, NULL, 00423 _dbus_timeout_list_toggle_timeout, 00424 enabled); 00425 } 00426 00427 00433 void 00434 _dbus_server_ref_unlocked (DBusServer *server) 00435 { 00436 _dbus_assert (server != NULL); 00437 _dbus_assert (server->refcount.value > 0); 00438 00439 HAVE_LOCK_CHECK (server); 00440 00441 #ifdef DBUS_HAVE_ATOMIC_INT 00442 _dbus_atomic_inc (&server->refcount); 00443 #else 00444 _dbus_assert (server->refcount.value > 0); 00445 00446 server->refcount.value += 1; 00447 #endif 00448 } 00449 00455 void 00456 _dbus_server_unref_unlocked (DBusServer *server) 00457 { 00458 dbus_bool_t last_unref; 00459 00460 /* Keep this in sync with dbus_server_unref */ 00461 00462 _dbus_assert (server != NULL); 00463 _dbus_assert (server->refcount.value > 0); 00464 00465 HAVE_LOCK_CHECK (server); 00466 00467 #ifdef DBUS_HAVE_ATOMIC_INT 00468 last_unref = (_dbus_atomic_dec (&server->refcount) == 1); 00469 #else 00470 _dbus_assert (server->refcount.value > 0); 00471 00472 server->refcount.value -= 1; 00473 last_unref = (server->refcount.value == 0); 00474 #endif 00475 00476 if (last_unref) 00477 { 00478 _dbus_assert (server->disconnected); 00479 00480 SERVER_UNLOCK (server); 00481 00482 _dbus_assert (server->vtable->finalize != NULL); 00483 00484 (* server->vtable->finalize) (server); 00485 } 00486 } 00487 00509 static const struct { 00510 DBusServerListenResult (* func) (DBusAddressEntry *entry, 00511 DBusServer **server_p, 00512 DBusError *error); 00513 } listen_funcs[] = { 00514 { _dbus_server_listen_socket } 00515 , { _dbus_server_listen_platform_specific } 00516 #ifdef DBUS_BUILD_TESTS 00517 , { _dbus_server_listen_debug_pipe } 00518 #endif 00519 }; 00520 00541 DBusServer* 00542 dbus_server_listen (const char *address, 00543 DBusError *error) 00544 { 00545 DBusServer *server; 00546 DBusAddressEntry **entries; 00547 int len, i; 00548 DBusError first_connect_error = DBUS_ERROR_INIT; 00549 dbus_bool_t handled_once; 00550 00551 _dbus_return_val_if_fail (address != NULL, NULL); 00552 _dbus_return_val_if_error_is_set (error, NULL); 00553 00554 if (!dbus_parse_address (address, &entries, &len, error)) 00555 return NULL; 00556 00557 server = NULL; 00558 handled_once = FALSE; 00559 00560 for (i = 0; i < len; i++) 00561 { 00562 int j; 00563 00564 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j) 00565 { 00566 DBusServerListenResult result; 00567 DBusError tmp_error = DBUS_ERROR_INIT; 00568 00569 result = (* listen_funcs[j].func) (entries[i], 00570 &server, 00571 &tmp_error); 00572 00573 if (result == DBUS_SERVER_LISTEN_OK) 00574 { 00575 _dbus_assert (server != NULL); 00576 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00577 handled_once = TRUE; 00578 goto out; 00579 } 00580 else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED) 00581 { 00582 _dbus_assert (server == NULL); 00583 dbus_set_error (error, 00584 DBUS_ERROR_ADDRESS_IN_USE, 00585 "Address '%s' already used", 00586 dbus_address_entry_get_method (entries[0])); 00587 handled_once = TRUE; 00588 goto out; 00589 } 00590 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS) 00591 { 00592 _dbus_assert (server == NULL); 00593 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00594 dbus_move_error (&tmp_error, error); 00595 handled_once = TRUE; 00596 goto out; 00597 } 00598 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED) 00599 { 00600 _dbus_assert (server == NULL); 00601 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00602 00603 /* keep trying addresses */ 00604 } 00605 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT) 00606 { 00607 _dbus_assert (server == NULL); 00608 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00609 if (!dbus_error_is_set (&first_connect_error)) 00610 dbus_move_error (&tmp_error, &first_connect_error); 00611 else 00612 dbus_error_free (&tmp_error); 00613 00614 handled_once = TRUE; 00615 00616 /* keep trying addresses */ 00617 } 00618 } 00619 00620 _dbus_assert (server == NULL); 00621 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00622 } 00623 00624 out: 00625 00626 if (!handled_once) 00627 { 00628 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00629 if (len > 0) 00630 dbus_set_error (error, 00631 DBUS_ERROR_BAD_ADDRESS, 00632 "Unknown address type '%s'", 00633 dbus_address_entry_get_method (entries[0])); 00634 else 00635 dbus_set_error (error, 00636 DBUS_ERROR_BAD_ADDRESS, 00637 "Empty address '%s'", 00638 address); 00639 } 00640 00641 dbus_address_entries_free (entries); 00642 00643 if (server == NULL) 00644 { 00645 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) || 00646 dbus_error_is_set (error)); 00647 00648 if (error && dbus_error_is_set (error)) 00649 { 00650 /* already set the error */ 00651 } 00652 else 00653 { 00654 /* didn't set the error but either error should be 00655 * NULL or first_connect_error should be set. 00656 */ 00657 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error)); 00658 dbus_move_error (&first_connect_error, error); 00659 } 00660 00661 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */ 00662 _DBUS_ASSERT_ERROR_IS_SET (error); 00663 00664 return NULL; 00665 } 00666 else 00667 { 00668 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00669 return server; 00670 } 00671 } 00672 00679 DBusServer * 00680 dbus_server_ref (DBusServer *server) 00681 { 00682 _dbus_return_val_if_fail (server != NULL, NULL); 00683 _dbus_return_val_if_fail (server->refcount.value > 0, NULL); 00684 00685 #ifdef DBUS_HAVE_ATOMIC_INT 00686 _dbus_atomic_inc (&server->refcount); 00687 #else 00688 SERVER_LOCK (server); 00689 _dbus_assert (server->refcount.value > 0); 00690 00691 server->refcount.value += 1; 00692 SERVER_UNLOCK (server); 00693 #endif 00694 00695 return server; 00696 } 00697 00706 void 00707 dbus_server_unref (DBusServer *server) 00708 { 00709 dbus_bool_t last_unref; 00710 00711 /* keep this in sync with unref_unlocked */ 00712 00713 _dbus_return_if_fail (server != NULL); 00714 _dbus_return_if_fail (server->refcount.value > 0); 00715 00716 #ifdef DBUS_HAVE_ATOMIC_INT 00717 last_unref = (_dbus_atomic_dec (&server->refcount) == 1); 00718 #else 00719 SERVER_LOCK (server); 00720 00721 _dbus_assert (server->refcount.value > 0); 00722 00723 server->refcount.value -= 1; 00724 last_unref = (server->refcount.value == 0); 00725 00726 SERVER_UNLOCK (server); 00727 #endif 00728 00729 if (last_unref) 00730 { 00731 /* lock not held! */ 00732 _dbus_assert (server->disconnected); 00733 00734 _dbus_assert (server->vtable->finalize != NULL); 00735 00736 (* server->vtable->finalize) (server); 00737 } 00738 } 00739 00748 void 00749 dbus_server_disconnect (DBusServer *server) 00750 { 00751 _dbus_return_if_fail (server != NULL); 00752 _dbus_return_if_fail (server->refcount.value > 0); 00753 00754 SERVER_LOCK (server); 00755 _dbus_server_ref_unlocked (server); 00756 00757 _dbus_assert (server->vtable->disconnect != NULL); 00758 00759 if (!server->disconnected) 00760 { 00761 /* this has to be first so recursive calls to disconnect don't happen */ 00762 server->disconnected = TRUE; 00763 00764 (* server->vtable->disconnect) (server); 00765 } 00766 00767 SERVER_UNLOCK (server); 00768 dbus_server_unref (server); 00769 } 00770 00776 dbus_bool_t 00777 dbus_server_get_is_connected (DBusServer *server) 00778 { 00779 dbus_bool_t retval; 00780 00781 _dbus_return_val_if_fail (server != NULL, FALSE); 00782 00783 SERVER_LOCK (server); 00784 retval = !server->disconnected; 00785 SERVER_UNLOCK (server); 00786 00787 return retval; 00788 } 00789 00797 char* 00798 dbus_server_get_address (DBusServer *server) 00799 { 00800 char *retval; 00801 00802 _dbus_return_val_if_fail (server != NULL, NULL); 00803 00804 SERVER_LOCK (server); 00805 retval = _dbus_strdup (server->address); 00806 SERVER_UNLOCK (server); 00807 00808 return retval; 00809 } 00810 00833 char* 00834 dbus_server_get_id (DBusServer *server) 00835 { 00836 char *retval; 00837 00838 _dbus_return_val_if_fail (server != NULL, NULL); 00839 00840 SERVER_LOCK (server); 00841 retval = NULL; 00842 _dbus_string_copy_data (&server->guid_hex, &retval); 00843 SERVER_UNLOCK (server); 00844 00845 return retval; 00846 } 00847 00868 void 00869 dbus_server_set_new_connection_function (DBusServer *server, 00870 DBusNewConnectionFunction function, 00871 void *data, 00872 DBusFreeFunction free_data_function) 00873 { 00874 DBusFreeFunction old_free_function; 00875 void *old_data; 00876 00877 _dbus_return_if_fail (server != NULL); 00878 00879 SERVER_LOCK (server); 00880 old_free_function = server->new_connection_free_data_function; 00881 old_data = server->new_connection_data; 00882 00883 server->new_connection_function = function; 00884 server->new_connection_data = data; 00885 server->new_connection_free_data_function = free_data_function; 00886 SERVER_UNLOCK (server); 00887 00888 if (old_free_function != NULL) 00889 (* old_free_function) (old_data); 00890 } 00891 00908 dbus_bool_t 00909 dbus_server_set_watch_functions (DBusServer *server, 00910 DBusAddWatchFunction add_function, 00911 DBusRemoveWatchFunction remove_function, 00912 DBusWatchToggledFunction toggled_function, 00913 void *data, 00914 DBusFreeFunction free_data_function) 00915 { 00916 dbus_bool_t result; 00917 DBusWatchList *watches; 00918 00919 _dbus_return_val_if_fail (server != NULL, FALSE); 00920 00921 SERVER_LOCK (server); 00922 watches = server->watches; 00923 server->watches = NULL; 00924 if (watches) 00925 { 00926 SERVER_UNLOCK (server); 00927 result = _dbus_watch_list_set_functions (watches, 00928 add_function, 00929 remove_function, 00930 toggled_function, 00931 data, 00932 free_data_function); 00933 SERVER_LOCK (server); 00934 } 00935 else 00936 { 00937 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00938 result = FALSE; 00939 } 00940 server->watches = watches; 00941 SERVER_UNLOCK (server); 00942 00943 return result; 00944 } 00945 00961 dbus_bool_t 00962 dbus_server_set_timeout_functions (DBusServer *server, 00963 DBusAddTimeoutFunction add_function, 00964 DBusRemoveTimeoutFunction remove_function, 00965 DBusTimeoutToggledFunction toggled_function, 00966 void *data, 00967 DBusFreeFunction free_data_function) 00968 { 00969 dbus_bool_t result; 00970 DBusTimeoutList *timeouts; 00971 00972 _dbus_return_val_if_fail (server != NULL, FALSE); 00973 00974 SERVER_LOCK (server); 00975 timeouts = server->timeouts; 00976 server->timeouts = NULL; 00977 if (timeouts) 00978 { 00979 SERVER_UNLOCK (server); 00980 result = _dbus_timeout_list_set_functions (timeouts, 00981 add_function, 00982 remove_function, 00983 toggled_function, 00984 data, 00985 free_data_function); 00986 SERVER_LOCK (server); 00987 } 00988 else 00989 { 00990 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00991 result = FALSE; 00992 } 00993 server->timeouts = timeouts; 00994 SERVER_UNLOCK (server); 00995 00996 return result; 00997 } 00998 01012 dbus_bool_t 01013 dbus_server_set_auth_mechanisms (DBusServer *server, 01014 const char **mechanisms) 01015 { 01016 char **copy; 01017 01018 _dbus_return_val_if_fail (server != NULL, FALSE); 01019 01020 SERVER_LOCK (server); 01021 01022 if (mechanisms != NULL) 01023 { 01024 copy = _dbus_dup_string_array (mechanisms); 01025 if (copy == NULL) 01026 return FALSE; 01027 } 01028 else 01029 copy = NULL; 01030 01031 dbus_free_string_array (server->auth_mechanisms); 01032 server->auth_mechanisms = copy; 01033 01034 SERVER_UNLOCK (server); 01035 01036 return TRUE; 01037 } 01038 01039 01040 static DBusDataSlotAllocator slot_allocator; 01041 _DBUS_DEFINE_GLOBAL_LOCK (server_slots); 01042 01057 dbus_bool_t 01058 dbus_server_allocate_data_slot (dbus_int32_t *slot_p) 01059 { 01060 return _dbus_data_slot_allocator_alloc (&slot_allocator, 01061 (DBusMutex **)&_DBUS_LOCK_NAME (server_slots), 01062 slot_p); 01063 } 01064 01076 void 01077 dbus_server_free_data_slot (dbus_int32_t *slot_p) 01078 { 01079 _dbus_return_if_fail (*slot_p >= 0); 01080 01081 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 01082 } 01083 01097 dbus_bool_t 01098 dbus_server_set_data (DBusServer *server, 01099 int slot, 01100 void *data, 01101 DBusFreeFunction free_data_func) 01102 { 01103 DBusFreeFunction old_free_func; 01104 void *old_data; 01105 dbus_bool_t retval; 01106 01107 _dbus_return_val_if_fail (server != NULL, FALSE); 01108 01109 SERVER_LOCK (server); 01110 01111 retval = _dbus_data_slot_list_set (&slot_allocator, 01112 &server->slot_list, 01113 slot, data, free_data_func, 01114 &old_free_func, &old_data); 01115 01116 01117 SERVER_UNLOCK (server); 01118 01119 if (retval) 01120 { 01121 /* Do the actual free outside the server lock */ 01122 if (old_free_func) 01123 (* old_free_func) (old_data); 01124 } 01125 01126 return retval; 01127 } 01128 01137 void* 01138 dbus_server_get_data (DBusServer *server, 01139 int slot) 01140 { 01141 void *res; 01142 01143 _dbus_return_val_if_fail (server != NULL, NULL); 01144 01145 SERVER_LOCK (server); 01146 01147 res = _dbus_data_slot_list_get (&slot_allocator, 01148 &server->slot_list, 01149 slot); 01150 01151 SERVER_UNLOCK (server); 01152 01153 return res; 01154 } 01155 01158 #ifdef DBUS_BUILD_TESTS 01159 #include "dbus-test.h" 01160 #include <string.h> 01161 01162 dbus_bool_t 01163 _dbus_server_test (void) 01164 { 01165 const char *valid_addresses[] = { 01166 "tcp:port=1234", 01167 "tcp:host=localhost,port=1234", 01168 "tcp:host=localhost,port=1234;tcp:port=5678", 01169 #ifdef DBUS_UNIX 01170 "unix:path=./boogie", 01171 "tcp:port=1234;unix:path=./boogie", 01172 #endif 01173 }; 01174 01175 DBusServer *server; 01176 int i; 01177 01178 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) 01179 { 01180 DBusError error = DBUS_ERROR_INIT; 01181 char *address; 01182 char *id; 01183 01184 server = dbus_server_listen (valid_addresses[i], &error); 01185 if (server == NULL) 01186 { 01187 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); 01188 dbus_error_free (&error); 01189 _dbus_assert_not_reached ("Failed to listen for valid address."); 01190 } 01191 01192 id = dbus_server_get_id (server); 01193 _dbus_assert (id != NULL); 01194 address = dbus_server_get_address (server); 01195 _dbus_assert (address != NULL); 01196 01197 if (strstr (address, id) == NULL) 01198 { 01199 _dbus_warn ("server id '%s' is not in the server address '%s'\n", 01200 id, address); 01201 _dbus_assert_not_reached ("bad server id or address"); 01202 } 01203 01204 dbus_free (id); 01205 dbus_free (address); 01206 01207 dbus_server_disconnect (server); 01208 dbus_server_unref (server); 01209 } 01210 01211 return TRUE; 01212 } 01213 01214 #endif /* DBUS_BUILD_TESTS */