D-Bus 1.4.0
|
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 00108 if (!_dbus_string_init (&server->guid_hex)) 00109 return FALSE; 00110 00111 _dbus_generate_uuid (&server->guid); 00112 00113 if (!_dbus_uuid_encode (&server->guid, &server->guid_hex)) 00114 goto failed; 00115 00116 server->address = copy_address_with_guid_appended (address, 00117 &server->guid_hex); 00118 if (server->address == NULL) 00119 goto failed; 00120 00121 _dbus_mutex_new_at_location (&server->mutex); 00122 if (server->mutex == NULL) 00123 goto failed; 00124 00125 server->watches = _dbus_watch_list_new (); 00126 if (server->watches == NULL) 00127 goto failed; 00128 00129 server->timeouts = _dbus_timeout_list_new (); 00130 if (server->timeouts == NULL) 00131 goto failed; 00132 00133 _dbus_data_slot_list_init (&server->slot_list); 00134 00135 _dbus_verbose ("Initialized server on address %s\n", server->address); 00136 00137 return TRUE; 00138 00139 failed: 00140 _dbus_mutex_free_at_location (&server->mutex); 00141 server->mutex = NULL; 00142 if (server->watches) 00143 { 00144 _dbus_watch_list_free (server->watches); 00145 server->watches = NULL; 00146 } 00147 if (server->timeouts) 00148 { 00149 _dbus_timeout_list_free (server->timeouts); 00150 server->timeouts = NULL; 00151 } 00152 if (server->address) 00153 { 00154 dbus_free (server->address); 00155 server->address = NULL; 00156 } 00157 _dbus_string_free (&server->guid_hex); 00158 00159 return FALSE; 00160 } 00161 00168 void 00169 _dbus_server_finalize_base (DBusServer *server) 00170 { 00171 /* We don't have the lock, but nobody should be accessing 00172 * concurrently since they don't have a ref 00173 */ 00174 #ifndef DBUS_DISABLE_CHECKS 00175 _dbus_assert (!server->have_server_lock); 00176 #endif 00177 _dbus_assert (server->disconnected); 00178 00179 /* calls out to application code... */ 00180 _dbus_data_slot_list_free (&server->slot_list); 00181 00182 dbus_server_set_new_connection_function (server, NULL, NULL, NULL); 00183 00184 _dbus_watch_list_free (server->watches); 00185 _dbus_timeout_list_free (server->timeouts); 00186 00187 _dbus_mutex_free_at_location (&server->mutex); 00188 00189 dbus_free (server->address); 00190 00191 dbus_free_string_array (server->auth_mechanisms); 00192 00193 _dbus_string_free (&server->guid_hex); 00194 } 00195 00196 00198 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00199 DBusWatch *watch); 00201 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00202 DBusWatch *watch); 00204 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00205 DBusWatch *watch, 00206 dbus_bool_t enabled); 00207 00208 static dbus_bool_t 00209 protected_change_watch (DBusServer *server, 00210 DBusWatch *watch, 00211 DBusWatchAddFunction add_function, 00212 DBusWatchRemoveFunction remove_function, 00213 DBusWatchToggleFunction toggle_function, 00214 dbus_bool_t enabled) 00215 { 00216 DBusWatchList *watches; 00217 dbus_bool_t retval; 00218 00219 HAVE_LOCK_CHECK (server); 00220 00221 /* This isn't really safe or reasonable; a better pattern is the "do 00222 * everything, then drop lock and call out" one; but it has to be 00223 * propagated up through all callers 00224 */ 00225 00226 watches = server->watches; 00227 if (watches) 00228 { 00229 server->watches = NULL; 00230 _dbus_server_ref_unlocked (server); 00231 SERVER_UNLOCK (server); 00232 00233 if (add_function) 00234 retval = (* add_function) (watches, watch); 00235 else if (remove_function) 00236 { 00237 retval = TRUE; 00238 (* remove_function) (watches, watch); 00239 } 00240 else 00241 { 00242 retval = TRUE; 00243 (* toggle_function) (watches, watch, enabled); 00244 } 00245 00246 SERVER_LOCK (server); 00247 server->watches = watches; 00248 _dbus_server_unref_unlocked (server); 00249 00250 return retval; 00251 } 00252 else 00253 return FALSE; 00254 } 00255 00263 dbus_bool_t 00264 _dbus_server_add_watch (DBusServer *server, 00265 DBusWatch *watch) 00266 { 00267 HAVE_LOCK_CHECK (server); 00268 return protected_change_watch (server, watch, 00269 _dbus_watch_list_add_watch, 00270 NULL, NULL, FALSE); 00271 } 00272 00279 void 00280 _dbus_server_remove_watch (DBusServer *server, 00281 DBusWatch *watch) 00282 { 00283 HAVE_LOCK_CHECK (server); 00284 protected_change_watch (server, watch, 00285 NULL, 00286 _dbus_watch_list_remove_watch, 00287 NULL, FALSE); 00288 } 00289 00299 void 00300 _dbus_server_toggle_watch (DBusServer *server, 00301 DBusWatch *watch, 00302 dbus_bool_t enabled) 00303 { 00304 _dbus_assert (watch != NULL); 00305 00306 HAVE_LOCK_CHECK (server); 00307 protected_change_watch (server, watch, 00308 NULL, NULL, 00309 _dbus_watch_list_toggle_watch, 00310 enabled); 00311 } 00312 00314 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00315 DBusTimeout *timeout); 00317 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00318 DBusTimeout *timeout); 00320 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00321 DBusTimeout *timeout, 00322 dbus_bool_t enabled); 00323 00324 00325 static dbus_bool_t 00326 protected_change_timeout (DBusServer *server, 00327 DBusTimeout *timeout, 00328 DBusTimeoutAddFunction add_function, 00329 DBusTimeoutRemoveFunction remove_function, 00330 DBusTimeoutToggleFunction toggle_function, 00331 dbus_bool_t enabled) 00332 { 00333 DBusTimeoutList *timeouts; 00334 dbus_bool_t retval; 00335 00336 HAVE_LOCK_CHECK (server); 00337 00338 /* This isn't really safe or reasonable; a better pattern is the "do everything, then 00339 * drop lock and call out" one; but it has to be propagated up through all callers 00340 */ 00341 00342 timeouts = server->timeouts; 00343 if (timeouts) 00344 { 00345 server->timeouts = NULL; 00346 _dbus_server_ref_unlocked (server); 00347 SERVER_UNLOCK (server); 00348 00349 if (add_function) 00350 retval = (* add_function) (timeouts, timeout); 00351 else if (remove_function) 00352 { 00353 retval = TRUE; 00354 (* remove_function) (timeouts, timeout); 00355 } 00356 else 00357 { 00358 retval = TRUE; 00359 (* toggle_function) (timeouts, timeout, enabled); 00360 } 00361 00362 SERVER_LOCK (server); 00363 server->timeouts = timeouts; 00364 _dbus_server_unref_unlocked (server); 00365 00366 return retval; 00367 } 00368 else 00369 return FALSE; 00370 } 00371 00381 dbus_bool_t 00382 _dbus_server_add_timeout (DBusServer *server, 00383 DBusTimeout *timeout) 00384 { 00385 return protected_change_timeout (server, timeout, 00386 _dbus_timeout_list_add_timeout, 00387 NULL, NULL, FALSE); 00388 } 00389 00396 void 00397 _dbus_server_remove_timeout (DBusServer *server, 00398 DBusTimeout *timeout) 00399 { 00400 protected_change_timeout (server, timeout, 00401 NULL, 00402 _dbus_timeout_list_remove_timeout, 00403 NULL, FALSE); 00404 } 00405 00415 void 00416 _dbus_server_toggle_timeout (DBusServer *server, 00417 DBusTimeout *timeout, 00418 dbus_bool_t enabled) 00419 { 00420 protected_change_timeout (server, timeout, 00421 NULL, NULL, 00422 _dbus_timeout_list_toggle_timeout, 00423 enabled); 00424 } 00425 00426 00432 void 00433 _dbus_server_ref_unlocked (DBusServer *server) 00434 { 00435 _dbus_assert (server != NULL); 00436 _dbus_assert (server->refcount.value > 0); 00437 00438 HAVE_LOCK_CHECK (server); 00439 00440 #ifdef DBUS_HAVE_ATOMIC_INT 00441 _dbus_atomic_inc (&server->refcount); 00442 #else 00443 _dbus_assert (server->refcount.value > 0); 00444 00445 server->refcount.value += 1; 00446 #endif 00447 } 00448 00454 void 00455 _dbus_server_unref_unlocked (DBusServer *server) 00456 { 00457 dbus_bool_t last_unref; 00458 00459 /* Keep this in sync with dbus_server_unref */ 00460 00461 _dbus_assert (server != NULL); 00462 _dbus_assert (server->refcount.value > 0); 00463 00464 HAVE_LOCK_CHECK (server); 00465 00466 #ifdef DBUS_HAVE_ATOMIC_INT 00467 last_unref = (_dbus_atomic_dec (&server->refcount) == 1); 00468 #else 00469 _dbus_assert (server->refcount.value > 0); 00470 00471 server->refcount.value -= 1; 00472 last_unref = (server->refcount.value == 0); 00473 #endif 00474 00475 if (last_unref) 00476 { 00477 _dbus_assert (server->disconnected); 00478 00479 SERVER_UNLOCK (server); 00480 00481 _dbus_assert (server->vtable->finalize != NULL); 00482 00483 (* server->vtable->finalize) (server); 00484 } 00485 } 00486 00508 static const struct { 00509 DBusServerListenResult (* func) (DBusAddressEntry *entry, 00510 DBusServer **server_p, 00511 DBusError *error); 00512 } listen_funcs[] = { 00513 { _dbus_server_listen_socket } 00514 , { _dbus_server_listen_platform_specific } 00515 #ifdef DBUS_BUILD_TESTS 00516 , { _dbus_server_listen_debug_pipe } 00517 #endif 00518 }; 00519 00540 DBusServer* 00541 dbus_server_listen (const char *address, 00542 DBusError *error) 00543 { 00544 DBusServer *server; 00545 DBusAddressEntry **entries; 00546 int len, i; 00547 DBusError first_connect_error = DBUS_ERROR_INIT; 00548 dbus_bool_t handled_once; 00549 00550 _dbus_return_val_if_fail (address != NULL, NULL); 00551 _dbus_return_val_if_error_is_set (error, NULL); 00552 00553 if (!dbus_parse_address (address, &entries, &len, error)) 00554 return NULL; 00555 00556 server = NULL; 00557 handled_once = FALSE; 00558 00559 for (i = 0; i < len; i++) 00560 { 00561 int j; 00562 00563 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j) 00564 { 00565 DBusServerListenResult result; 00566 DBusError tmp_error = DBUS_ERROR_INIT; 00567 00568 result = (* listen_funcs[j].func) (entries[i], 00569 &server, 00570 &tmp_error); 00571 00572 if (result == DBUS_SERVER_LISTEN_OK) 00573 { 00574 _dbus_assert (server != NULL); 00575 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00576 handled_once = TRUE; 00577 goto out; 00578 } 00579 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS) 00580 { 00581 _dbus_assert (server == NULL); 00582 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00583 dbus_move_error (&tmp_error, error); 00584 handled_once = TRUE; 00585 goto out; 00586 } 00587 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED) 00588 { 00589 _dbus_assert (server == NULL); 00590 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00591 00592 /* keep trying addresses */ 00593 } 00594 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT) 00595 { 00596 _dbus_assert (server == NULL); 00597 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00598 if (!dbus_error_is_set (&first_connect_error)) 00599 dbus_move_error (&tmp_error, &first_connect_error); 00600 else 00601 dbus_error_free (&tmp_error); 00602 00603 handled_once = TRUE; 00604 00605 /* keep trying addresses */ 00606 } 00607 } 00608 00609 _dbus_assert (server == NULL); 00610 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00611 } 00612 00613 out: 00614 00615 if (!handled_once) 00616 { 00617 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00618 if (len > 0) 00619 dbus_set_error (error, 00620 DBUS_ERROR_BAD_ADDRESS, 00621 "Unknown address type '%s'", 00622 dbus_address_entry_get_method (entries[0])); 00623 else 00624 dbus_set_error (error, 00625 DBUS_ERROR_BAD_ADDRESS, 00626 "Empty address '%s'", 00627 address); 00628 } 00629 00630 dbus_address_entries_free (entries); 00631 00632 if (server == NULL) 00633 { 00634 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) || 00635 dbus_error_is_set (error)); 00636 00637 if (error && dbus_error_is_set (error)) 00638 { 00639 /* already set the error */ 00640 } 00641 else 00642 { 00643 /* didn't set the error but either error should be 00644 * NULL or first_connect_error should be set. 00645 */ 00646 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error)); 00647 dbus_move_error (&first_connect_error, error); 00648 } 00649 00650 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */ 00651 _DBUS_ASSERT_ERROR_IS_SET (error); 00652 00653 return NULL; 00654 } 00655 else 00656 { 00657 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00658 return server; 00659 } 00660 } 00661 00668 DBusServer * 00669 dbus_server_ref (DBusServer *server) 00670 { 00671 _dbus_return_val_if_fail (server != NULL, NULL); 00672 _dbus_return_val_if_fail (server->refcount.value > 0, NULL); 00673 00674 #ifdef DBUS_HAVE_ATOMIC_INT 00675 _dbus_atomic_inc (&server->refcount); 00676 #else 00677 SERVER_LOCK (server); 00678 _dbus_assert (server->refcount.value > 0); 00679 00680 server->refcount.value += 1; 00681 SERVER_UNLOCK (server); 00682 #endif 00683 00684 return server; 00685 } 00686 00695 void 00696 dbus_server_unref (DBusServer *server) 00697 { 00698 dbus_bool_t last_unref; 00699 00700 /* keep this in sync with unref_unlocked */ 00701 00702 _dbus_return_if_fail (server != NULL); 00703 _dbus_return_if_fail (server->refcount.value > 0); 00704 00705 #ifdef DBUS_HAVE_ATOMIC_INT 00706 last_unref = (_dbus_atomic_dec (&server->refcount) == 1); 00707 #else 00708 SERVER_LOCK (server); 00709 00710 _dbus_assert (server->refcount.value > 0); 00711 00712 server->refcount.value -= 1; 00713 last_unref = (server->refcount.value == 0); 00714 00715 SERVER_UNLOCK (server); 00716 #endif 00717 00718 if (last_unref) 00719 { 00720 /* lock not held! */ 00721 _dbus_assert (server->disconnected); 00722 00723 _dbus_assert (server->vtable->finalize != NULL); 00724 00725 (* server->vtable->finalize) (server); 00726 } 00727 } 00728 00737 void 00738 dbus_server_disconnect (DBusServer *server) 00739 { 00740 _dbus_return_if_fail (server != NULL); 00741 _dbus_return_if_fail (server->refcount.value > 0); 00742 00743 SERVER_LOCK (server); 00744 _dbus_server_ref_unlocked (server); 00745 00746 _dbus_assert (server->vtable->disconnect != NULL); 00747 00748 if (!server->disconnected) 00749 { 00750 /* this has to be first so recursive calls to disconnect don't happen */ 00751 server->disconnected = TRUE; 00752 00753 (* server->vtable->disconnect) (server); 00754 } 00755 00756 SERVER_UNLOCK (server); 00757 dbus_server_unref (server); 00758 } 00759 00765 dbus_bool_t 00766 dbus_server_get_is_connected (DBusServer *server) 00767 { 00768 dbus_bool_t retval; 00769 00770 _dbus_return_val_if_fail (server != NULL, FALSE); 00771 00772 SERVER_LOCK (server); 00773 retval = !server->disconnected; 00774 SERVER_UNLOCK (server); 00775 00776 return retval; 00777 } 00778 00786 char* 00787 dbus_server_get_address (DBusServer *server) 00788 { 00789 char *retval; 00790 00791 _dbus_return_val_if_fail (server != NULL, NULL); 00792 00793 SERVER_LOCK (server); 00794 retval = _dbus_strdup (server->address); 00795 SERVER_UNLOCK (server); 00796 00797 return retval; 00798 } 00799 00822 char* 00823 dbus_server_get_id (DBusServer *server) 00824 { 00825 char *retval; 00826 00827 _dbus_return_val_if_fail (server != NULL, NULL); 00828 00829 SERVER_LOCK (server); 00830 retval = NULL; 00831 _dbus_string_copy_data (&server->guid_hex, &retval); 00832 SERVER_UNLOCK (server); 00833 00834 return retval; 00835 } 00836 00857 void 00858 dbus_server_set_new_connection_function (DBusServer *server, 00859 DBusNewConnectionFunction function, 00860 void *data, 00861 DBusFreeFunction free_data_function) 00862 { 00863 DBusFreeFunction old_free_function; 00864 void *old_data; 00865 00866 _dbus_return_if_fail (server != NULL); 00867 00868 SERVER_LOCK (server); 00869 old_free_function = server->new_connection_free_data_function; 00870 old_data = server->new_connection_data; 00871 00872 server->new_connection_function = function; 00873 server->new_connection_data = data; 00874 server->new_connection_free_data_function = free_data_function; 00875 SERVER_UNLOCK (server); 00876 00877 if (old_free_function != NULL) 00878 (* old_free_function) (old_data); 00879 } 00880 00897 dbus_bool_t 00898 dbus_server_set_watch_functions (DBusServer *server, 00899 DBusAddWatchFunction add_function, 00900 DBusRemoveWatchFunction remove_function, 00901 DBusWatchToggledFunction toggled_function, 00902 void *data, 00903 DBusFreeFunction free_data_function) 00904 { 00905 dbus_bool_t result; 00906 DBusWatchList *watches; 00907 00908 _dbus_return_val_if_fail (server != NULL, FALSE); 00909 00910 SERVER_LOCK (server); 00911 watches = server->watches; 00912 server->watches = NULL; 00913 if (watches) 00914 { 00915 SERVER_UNLOCK (server); 00916 result = _dbus_watch_list_set_functions (watches, 00917 add_function, 00918 remove_function, 00919 toggled_function, 00920 data, 00921 free_data_function); 00922 SERVER_LOCK (server); 00923 } 00924 else 00925 { 00926 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00927 result = FALSE; 00928 } 00929 server->watches = watches; 00930 SERVER_UNLOCK (server); 00931 00932 return result; 00933 } 00934 00950 dbus_bool_t 00951 dbus_server_set_timeout_functions (DBusServer *server, 00952 DBusAddTimeoutFunction add_function, 00953 DBusRemoveTimeoutFunction remove_function, 00954 DBusTimeoutToggledFunction toggled_function, 00955 void *data, 00956 DBusFreeFunction free_data_function) 00957 { 00958 dbus_bool_t result; 00959 DBusTimeoutList *timeouts; 00960 00961 _dbus_return_val_if_fail (server != NULL, FALSE); 00962 00963 SERVER_LOCK (server); 00964 timeouts = server->timeouts; 00965 server->timeouts = NULL; 00966 if (timeouts) 00967 { 00968 SERVER_UNLOCK (server); 00969 result = _dbus_timeout_list_set_functions (timeouts, 00970 add_function, 00971 remove_function, 00972 toggled_function, 00973 data, 00974 free_data_function); 00975 SERVER_LOCK (server); 00976 } 00977 else 00978 { 00979 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00980 result = FALSE; 00981 } 00982 server->timeouts = timeouts; 00983 SERVER_UNLOCK (server); 00984 00985 return result; 00986 } 00987 01001 dbus_bool_t 01002 dbus_server_set_auth_mechanisms (DBusServer *server, 01003 const char **mechanisms) 01004 { 01005 char **copy; 01006 01007 _dbus_return_val_if_fail (server != NULL, FALSE); 01008 01009 SERVER_LOCK (server); 01010 01011 if (mechanisms != NULL) 01012 { 01013 copy = _dbus_dup_string_array (mechanisms); 01014 if (copy == NULL) 01015 return FALSE; 01016 } 01017 else 01018 copy = NULL; 01019 01020 dbus_free_string_array (server->auth_mechanisms); 01021 server->auth_mechanisms = copy; 01022 01023 SERVER_UNLOCK (server); 01024 01025 return TRUE; 01026 } 01027 01028 01029 static DBusDataSlotAllocator slot_allocator; 01030 _DBUS_DEFINE_GLOBAL_LOCK (server_slots); 01031 01046 dbus_bool_t 01047 dbus_server_allocate_data_slot (dbus_int32_t *slot_p) 01048 { 01049 return _dbus_data_slot_allocator_alloc (&slot_allocator, 01050 (DBusMutex **)&_DBUS_LOCK_NAME (server_slots), 01051 slot_p); 01052 } 01053 01065 void 01066 dbus_server_free_data_slot (dbus_int32_t *slot_p) 01067 { 01068 _dbus_return_if_fail (*slot_p >= 0); 01069 01070 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 01071 } 01072 01086 dbus_bool_t 01087 dbus_server_set_data (DBusServer *server, 01088 int slot, 01089 void *data, 01090 DBusFreeFunction free_data_func) 01091 { 01092 DBusFreeFunction old_free_func; 01093 void *old_data; 01094 dbus_bool_t retval; 01095 01096 _dbus_return_val_if_fail (server != NULL, FALSE); 01097 01098 SERVER_LOCK (server); 01099 01100 retval = _dbus_data_slot_list_set (&slot_allocator, 01101 &server->slot_list, 01102 slot, data, free_data_func, 01103 &old_free_func, &old_data); 01104 01105 01106 SERVER_UNLOCK (server); 01107 01108 if (retval) 01109 { 01110 /* Do the actual free outside the server lock */ 01111 if (old_free_func) 01112 (* old_free_func) (old_data); 01113 } 01114 01115 return retval; 01116 } 01117 01126 void* 01127 dbus_server_get_data (DBusServer *server, 01128 int slot) 01129 { 01130 void *res; 01131 01132 _dbus_return_val_if_fail (server != NULL, NULL); 01133 01134 SERVER_LOCK (server); 01135 01136 res = _dbus_data_slot_list_get (&slot_allocator, 01137 &server->slot_list, 01138 slot); 01139 01140 SERVER_UNLOCK (server); 01141 01142 return res; 01143 } 01144 01147 #ifdef DBUS_BUILD_TESTS 01148 #include "dbus-test.h" 01149 #include <string.h> 01150 01151 dbus_bool_t 01152 _dbus_server_test (void) 01153 { 01154 const char *valid_addresses[] = { 01155 "tcp:port=1234", 01156 "tcp:host=localhost,port=1234", 01157 "tcp:host=localhost,port=1234;tcp:port=5678", 01158 #ifdef DBUS_UNIX 01159 "unix:path=./boogie", 01160 "tcp:port=1234;unix:path=./boogie", 01161 #endif 01162 }; 01163 01164 DBusServer *server; 01165 int i; 01166 01167 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) 01168 { 01169 DBusError error = DBUS_ERROR_INIT; 01170 char *address; 01171 char *id; 01172 01173 server = dbus_server_listen (valid_addresses[i], &error); 01174 if (server == NULL) 01175 { 01176 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); 01177 dbus_error_free (&error); 01178 _dbus_assert_not_reached ("Failed to listen for valid address."); 01179 } 01180 01181 id = dbus_server_get_id (server); 01182 _dbus_assert (id != NULL); 01183 address = dbus_server_get_address (server); 01184 _dbus_assert (address != NULL); 01185 01186 if (strstr (address, id) == NULL) 01187 { 01188 _dbus_warn ("server id '%s' is not in the server address '%s'\n", 01189 id, address); 01190 _dbus_assert_not_reached ("bad server id or address"); 01191 } 01192 01193 dbus_free (id); 01194 dbus_free (address); 01195 01196 dbus_server_disconnect (server); 01197 dbus_server_unref (server); 01198 } 01199 01200 return TRUE; 01201 } 01202 01203 #endif /* DBUS_BUILD_TESTS */