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