D-Bus
1.4.16
|
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 00103 #ifdef DBUS_DISABLE_ASSERT 00104 _dbus_atomic_inc (&server->refcount); 00105 #else 00106 { 00107 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00108 00109 _dbus_assert (old_refcount == 0); 00110 } 00111 #endif 00112 00113 server->address = NULL; 00114 server->watches = NULL; 00115 server->timeouts = NULL; 00116 server->published_address = FALSE; 00117 00118 if (!_dbus_string_init (&server->guid_hex)) 00119 return FALSE; 00120 00121 _dbus_generate_uuid (&server->guid); 00122 00123 if (!_dbus_uuid_encode (&server->guid, &server->guid_hex)) 00124 goto failed; 00125 00126 server->address = copy_address_with_guid_appended (address, 00127 &server->guid_hex); 00128 if (server->address == NULL) 00129 goto failed; 00130 00131 _dbus_mutex_new_at_location (&server->mutex); 00132 if (server->mutex == NULL) 00133 goto failed; 00134 00135 server->watches = _dbus_watch_list_new (); 00136 if (server->watches == NULL) 00137 goto failed; 00138 00139 server->timeouts = _dbus_timeout_list_new (); 00140 if (server->timeouts == NULL) 00141 goto failed; 00142 00143 _dbus_data_slot_list_init (&server->slot_list); 00144 00145 _dbus_verbose ("Initialized server on address %s\n", server->address); 00146 00147 return TRUE; 00148 00149 failed: 00150 _dbus_mutex_free_at_location (&server->mutex); 00151 server->mutex = NULL; 00152 if (server->watches) 00153 { 00154 _dbus_watch_list_free (server->watches); 00155 server->watches = NULL; 00156 } 00157 if (server->timeouts) 00158 { 00159 _dbus_timeout_list_free (server->timeouts); 00160 server->timeouts = NULL; 00161 } 00162 if (server->address) 00163 { 00164 dbus_free (server->address); 00165 server->address = NULL; 00166 } 00167 _dbus_string_free (&server->guid_hex); 00168 00169 return FALSE; 00170 } 00171 00178 void 00179 _dbus_server_finalize_base (DBusServer *server) 00180 { 00181 /* We don't have the lock, but nobody should be accessing 00182 * concurrently since they don't have a ref 00183 */ 00184 #ifndef DBUS_DISABLE_CHECKS 00185 _dbus_assert (!server->have_server_lock); 00186 #endif 00187 _dbus_assert (server->disconnected); 00188 00189 /* calls out to application code... */ 00190 _dbus_data_slot_list_free (&server->slot_list); 00191 00192 dbus_server_set_new_connection_function (server, NULL, NULL, NULL); 00193 00194 _dbus_watch_list_free (server->watches); 00195 _dbus_timeout_list_free (server->timeouts); 00196 00197 _dbus_mutex_free_at_location (&server->mutex); 00198 00199 dbus_free (server->address); 00200 00201 dbus_free_string_array (server->auth_mechanisms); 00202 00203 _dbus_string_free (&server->guid_hex); 00204 } 00205 00206 00208 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00209 DBusWatch *watch); 00211 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00212 DBusWatch *watch); 00214 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00215 DBusWatch *watch, 00216 dbus_bool_t enabled); 00217 00218 static dbus_bool_t 00219 protected_change_watch (DBusServer *server, 00220 DBusWatch *watch, 00221 DBusWatchAddFunction add_function, 00222 DBusWatchRemoveFunction remove_function, 00223 DBusWatchToggleFunction toggle_function, 00224 dbus_bool_t enabled) 00225 { 00226 DBusWatchList *watches; 00227 dbus_bool_t retval; 00228 00229 HAVE_LOCK_CHECK (server); 00230 00231 /* This isn't really safe or reasonable; a better pattern is the "do 00232 * everything, then drop lock and call out" one; but it has to be 00233 * propagated up through all callers 00234 */ 00235 00236 watches = server->watches; 00237 if (watches) 00238 { 00239 server->watches = NULL; 00240 _dbus_server_ref_unlocked (server); 00241 SERVER_UNLOCK (server); 00242 00243 if (add_function) 00244 retval = (* add_function) (watches, watch); 00245 else if (remove_function) 00246 { 00247 retval = TRUE; 00248 (* remove_function) (watches, watch); 00249 } 00250 else 00251 { 00252 retval = TRUE; 00253 (* toggle_function) (watches, watch, enabled); 00254 } 00255 00256 SERVER_LOCK (server); 00257 server->watches = watches; 00258 _dbus_server_unref_unlocked (server); 00259 00260 return retval; 00261 } 00262 else 00263 return FALSE; 00264 } 00265 00273 dbus_bool_t 00274 _dbus_server_add_watch (DBusServer *server, 00275 DBusWatch *watch) 00276 { 00277 HAVE_LOCK_CHECK (server); 00278 return protected_change_watch (server, watch, 00279 _dbus_watch_list_add_watch, 00280 NULL, NULL, FALSE); 00281 } 00282 00289 void 00290 _dbus_server_remove_watch (DBusServer *server, 00291 DBusWatch *watch) 00292 { 00293 HAVE_LOCK_CHECK (server); 00294 protected_change_watch (server, watch, 00295 NULL, 00296 _dbus_watch_list_remove_watch, 00297 NULL, FALSE); 00298 } 00299 00309 void 00310 _dbus_server_toggle_watch (DBusServer *server, 00311 DBusWatch *watch, 00312 dbus_bool_t enabled) 00313 { 00314 _dbus_assert (watch != NULL); 00315 00316 HAVE_LOCK_CHECK (server); 00317 protected_change_watch (server, watch, 00318 NULL, NULL, 00319 _dbus_watch_list_toggle_watch, 00320 enabled); 00321 } 00322 00324 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00325 DBusTimeout *timeout); 00327 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00328 DBusTimeout *timeout); 00330 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00331 DBusTimeout *timeout, 00332 dbus_bool_t enabled); 00333 00334 00335 static dbus_bool_t 00336 protected_change_timeout (DBusServer *server, 00337 DBusTimeout *timeout, 00338 DBusTimeoutAddFunction add_function, 00339 DBusTimeoutRemoveFunction remove_function, 00340 DBusTimeoutToggleFunction toggle_function, 00341 dbus_bool_t enabled) 00342 { 00343 DBusTimeoutList *timeouts; 00344 dbus_bool_t retval; 00345 00346 HAVE_LOCK_CHECK (server); 00347 00348 /* This isn't really safe or reasonable; a better pattern is the "do everything, then 00349 * drop lock and call out" one; but it has to be propagated up through all callers 00350 */ 00351 00352 timeouts = server->timeouts; 00353 if (timeouts) 00354 { 00355 server->timeouts = NULL; 00356 _dbus_server_ref_unlocked (server); 00357 SERVER_UNLOCK (server); 00358 00359 if (add_function) 00360 retval = (* add_function) (timeouts, timeout); 00361 else if (remove_function) 00362 { 00363 retval = TRUE; 00364 (* remove_function) (timeouts, timeout); 00365 } 00366 else 00367 { 00368 retval = TRUE; 00369 (* toggle_function) (timeouts, timeout, enabled); 00370 } 00371 00372 SERVER_LOCK (server); 00373 server->timeouts = timeouts; 00374 _dbus_server_unref_unlocked (server); 00375 00376 return retval; 00377 } 00378 else 00379 return FALSE; 00380 } 00381 00391 dbus_bool_t 00392 _dbus_server_add_timeout (DBusServer *server, 00393 DBusTimeout *timeout) 00394 { 00395 return protected_change_timeout (server, timeout, 00396 _dbus_timeout_list_add_timeout, 00397 NULL, NULL, FALSE); 00398 } 00399 00406 void 00407 _dbus_server_remove_timeout (DBusServer *server, 00408 DBusTimeout *timeout) 00409 { 00410 protected_change_timeout (server, timeout, 00411 NULL, 00412 _dbus_timeout_list_remove_timeout, 00413 NULL, FALSE); 00414 } 00415 00425 void 00426 _dbus_server_toggle_timeout (DBusServer *server, 00427 DBusTimeout *timeout, 00428 dbus_bool_t enabled) 00429 { 00430 protected_change_timeout (server, timeout, 00431 NULL, NULL, 00432 _dbus_timeout_list_toggle_timeout, 00433 enabled); 00434 } 00435 00436 00442 void 00443 _dbus_server_ref_unlocked (DBusServer *server) 00444 { 00445 _dbus_assert (server != NULL); 00446 HAVE_LOCK_CHECK (server); 00447 00448 #ifdef DBUS_DISABLE_ASSERT 00449 _dbus_atomic_inc (&server->refcount); 00450 #else 00451 { 00452 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00453 00454 _dbus_assert (old_refcount > 0); 00455 } 00456 #endif 00457 } 00458 00464 void 00465 _dbus_server_unref_unlocked (DBusServer *server) 00466 { 00467 dbus_int32_t old_refcount; 00468 00469 /* Keep this in sync with dbus_server_unref */ 00470 00471 _dbus_assert (server != NULL); 00472 00473 HAVE_LOCK_CHECK (server); 00474 00475 old_refcount = _dbus_atomic_dec (&server->refcount); 00476 _dbus_assert (old_refcount > 0); 00477 00478 if (old_refcount == 1) 00479 { 00480 _dbus_assert (server->disconnected); 00481 00482 SERVER_UNLOCK (server); 00483 00484 _dbus_assert (server->vtable->finalize != NULL); 00485 00486 (* server->vtable->finalize) (server); 00487 } 00488 } 00489 00511 static const struct { 00512 DBusServerListenResult (* func) (DBusAddressEntry *entry, 00513 DBusServer **server_p, 00514 DBusError *error); 00515 } listen_funcs[] = { 00516 { _dbus_server_listen_socket } 00517 , { _dbus_server_listen_platform_specific } 00518 #ifdef DBUS_BUILD_TESTS 00519 , { _dbus_server_listen_debug_pipe } 00520 #endif 00521 }; 00522 00543 DBusServer* 00544 dbus_server_listen (const char *address, 00545 DBusError *error) 00546 { 00547 DBusServer *server; 00548 DBusAddressEntry **entries; 00549 int len, i; 00550 DBusError first_connect_error = DBUS_ERROR_INIT; 00551 dbus_bool_t handled_once; 00552 00553 _dbus_return_val_if_fail (address != NULL, NULL); 00554 _dbus_return_val_if_error_is_set (error, NULL); 00555 00556 if (!dbus_parse_address (address, &entries, &len, error)) 00557 return NULL; 00558 00559 server = NULL; 00560 handled_once = FALSE; 00561 00562 for (i = 0; i < len; i++) 00563 { 00564 int j; 00565 00566 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j) 00567 { 00568 DBusServerListenResult result; 00569 DBusError tmp_error = DBUS_ERROR_INIT; 00570 00571 result = (* listen_funcs[j].func) (entries[i], 00572 &server, 00573 &tmp_error); 00574 00575 if (result == DBUS_SERVER_LISTEN_OK) 00576 { 00577 _dbus_assert (server != NULL); 00578 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00579 handled_once = TRUE; 00580 goto out; 00581 } 00582 else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED) 00583 { 00584 _dbus_assert (server == NULL); 00585 dbus_set_error (error, 00586 DBUS_ERROR_ADDRESS_IN_USE, 00587 "Address '%s' already used", 00588 dbus_address_entry_get_method (entries[0])); 00589 handled_once = TRUE; 00590 goto out; 00591 } 00592 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS) 00593 { 00594 _dbus_assert (server == NULL); 00595 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00596 dbus_move_error (&tmp_error, error); 00597 handled_once = TRUE; 00598 goto out; 00599 } 00600 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED) 00601 { 00602 _dbus_assert (server == NULL); 00603 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00604 00605 /* keep trying addresses */ 00606 } 00607 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT) 00608 { 00609 _dbus_assert (server == NULL); 00610 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00611 if (!dbus_error_is_set (&first_connect_error)) 00612 dbus_move_error (&tmp_error, &first_connect_error); 00613 else 00614 dbus_error_free (&tmp_error); 00615 00616 handled_once = TRUE; 00617 00618 /* keep trying addresses */ 00619 } 00620 } 00621 00622 _dbus_assert (server == NULL); 00623 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00624 } 00625 00626 out: 00627 00628 if (!handled_once) 00629 { 00630 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00631 if (len > 0) 00632 dbus_set_error (error, 00633 DBUS_ERROR_BAD_ADDRESS, 00634 "Unknown address type '%s'", 00635 dbus_address_entry_get_method (entries[0])); 00636 else 00637 dbus_set_error (error, 00638 DBUS_ERROR_BAD_ADDRESS, 00639 "Empty address '%s'", 00640 address); 00641 } 00642 00643 dbus_address_entries_free (entries); 00644 00645 if (server == NULL) 00646 { 00647 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) || 00648 dbus_error_is_set (error)); 00649 00650 if (error && dbus_error_is_set (error)) 00651 { 00652 /* already set the error */ 00653 } 00654 else 00655 { 00656 /* didn't set the error but either error should be 00657 * NULL or first_connect_error should be set. 00658 */ 00659 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error)); 00660 dbus_move_error (&first_connect_error, error); 00661 } 00662 00663 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */ 00664 _DBUS_ASSERT_ERROR_IS_SET (error); 00665 00666 return NULL; 00667 } 00668 else 00669 { 00670 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00671 return server; 00672 } 00673 } 00674 00681 DBusServer * 00682 dbus_server_ref (DBusServer *server) 00683 { 00684 _dbus_return_val_if_fail (server != NULL, NULL); 00685 00686 #ifdef DBUS_DISABLE_CHECKS 00687 _dbus_atomic_inc (&server->refcount); 00688 #else 00689 { 00690 dbus_int32_t old_refcount; 00691 00692 /* can't get the refcount without a side-effect */ 00693 old_refcount = _dbus_atomic_inc (&server->refcount); 00694 00695 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00696 { 00697 /* undo side-effect first */ 00698 _dbus_atomic_dec (&server->refcount); 00699 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00700 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00701 __FILE__, __LINE__); 00702 return NULL; 00703 } 00704 } 00705 #endif 00706 00707 return server; 00708 } 00709 00718 void 00719 dbus_server_unref (DBusServer *server) 00720 { 00721 dbus_int32_t old_refcount; 00722 00723 /* keep this in sync with unref_unlocked */ 00724 00725 _dbus_return_if_fail (server != NULL); 00726 00727 /* can't get the refcount without a side-effect */ 00728 old_refcount = _dbus_atomic_dec (&server->refcount); 00729 00730 #ifndef DBUS_DISABLE_CHECKS 00731 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00732 { 00733 /* undo side-effect first */ 00734 _dbus_atomic_inc (&server->refcount); 00735 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00736 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00737 __FILE__, __LINE__); 00738 return; 00739 } 00740 #endif 00741 00742 if (old_refcount == 1) 00743 { 00744 /* lock not held! */ 00745 _dbus_assert (server->disconnected); 00746 00747 _dbus_assert (server->vtable->finalize != NULL); 00748 00749 (* server->vtable->finalize) (server); 00750 } 00751 } 00752 00761 void 00762 dbus_server_disconnect (DBusServer *server) 00763 { 00764 _dbus_return_if_fail (server != NULL); 00765 00766 #ifdef DBUS_DISABLE_CHECKS 00767 _dbus_atomic_inc (&server->refcount); 00768 #else 00769 { 00770 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00771 00772 _dbus_return_if_fail (old_refcount > 0); 00773 } 00774 #endif 00775 00776 SERVER_LOCK (server); 00777 00778 _dbus_assert (server->vtable->disconnect != NULL); 00779 00780 if (!server->disconnected) 00781 { 00782 /* this has to be first so recursive calls to disconnect don't happen */ 00783 server->disconnected = TRUE; 00784 00785 (* server->vtable->disconnect) (server); 00786 } 00787 00788 SERVER_UNLOCK (server); 00789 dbus_server_unref (server); 00790 } 00791 00797 dbus_bool_t 00798 dbus_server_get_is_connected (DBusServer *server) 00799 { 00800 dbus_bool_t retval; 00801 00802 _dbus_return_val_if_fail (server != NULL, FALSE); 00803 00804 SERVER_LOCK (server); 00805 retval = !server->disconnected; 00806 SERVER_UNLOCK (server); 00807 00808 return retval; 00809 } 00810 00818 char* 00819 dbus_server_get_address (DBusServer *server) 00820 { 00821 char *retval; 00822 00823 _dbus_return_val_if_fail (server != NULL, NULL); 00824 00825 SERVER_LOCK (server); 00826 retval = _dbus_strdup (server->address); 00827 SERVER_UNLOCK (server); 00828 00829 return retval; 00830 } 00831 00854 char* 00855 dbus_server_get_id (DBusServer *server) 00856 { 00857 char *retval; 00858 00859 _dbus_return_val_if_fail (server != NULL, NULL); 00860 00861 SERVER_LOCK (server); 00862 retval = NULL; 00863 _dbus_string_copy_data (&server->guid_hex, &retval); 00864 SERVER_UNLOCK (server); 00865 00866 return retval; 00867 } 00868 00889 void 00890 dbus_server_set_new_connection_function (DBusServer *server, 00891 DBusNewConnectionFunction function, 00892 void *data, 00893 DBusFreeFunction free_data_function) 00894 { 00895 DBusFreeFunction old_free_function; 00896 void *old_data; 00897 00898 _dbus_return_if_fail (server != NULL); 00899 00900 SERVER_LOCK (server); 00901 old_free_function = server->new_connection_free_data_function; 00902 old_data = server->new_connection_data; 00903 00904 server->new_connection_function = function; 00905 server->new_connection_data = data; 00906 server->new_connection_free_data_function = free_data_function; 00907 SERVER_UNLOCK (server); 00908 00909 if (old_free_function != NULL) 00910 (* old_free_function) (old_data); 00911 } 00912 00929 dbus_bool_t 00930 dbus_server_set_watch_functions (DBusServer *server, 00931 DBusAddWatchFunction add_function, 00932 DBusRemoveWatchFunction remove_function, 00933 DBusWatchToggledFunction toggled_function, 00934 void *data, 00935 DBusFreeFunction free_data_function) 00936 { 00937 dbus_bool_t result; 00938 DBusWatchList *watches; 00939 00940 _dbus_return_val_if_fail (server != NULL, FALSE); 00941 00942 SERVER_LOCK (server); 00943 watches = server->watches; 00944 server->watches = NULL; 00945 if (watches) 00946 { 00947 SERVER_UNLOCK (server); 00948 result = _dbus_watch_list_set_functions (watches, 00949 add_function, 00950 remove_function, 00951 toggled_function, 00952 data, 00953 free_data_function); 00954 SERVER_LOCK (server); 00955 } 00956 else 00957 { 00958 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00959 result = FALSE; 00960 } 00961 server->watches = watches; 00962 SERVER_UNLOCK (server); 00963 00964 return result; 00965 } 00966 00982 dbus_bool_t 00983 dbus_server_set_timeout_functions (DBusServer *server, 00984 DBusAddTimeoutFunction add_function, 00985 DBusRemoveTimeoutFunction remove_function, 00986 DBusTimeoutToggledFunction toggled_function, 00987 void *data, 00988 DBusFreeFunction free_data_function) 00989 { 00990 dbus_bool_t result; 00991 DBusTimeoutList *timeouts; 00992 00993 _dbus_return_val_if_fail (server != NULL, FALSE); 00994 00995 SERVER_LOCK (server); 00996 timeouts = server->timeouts; 00997 server->timeouts = NULL; 00998 if (timeouts) 00999 { 01000 SERVER_UNLOCK (server); 01001 result = _dbus_timeout_list_set_functions (timeouts, 01002 add_function, 01003 remove_function, 01004 toggled_function, 01005 data, 01006 free_data_function); 01007 SERVER_LOCK (server); 01008 } 01009 else 01010 { 01011 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 01012 result = FALSE; 01013 } 01014 server->timeouts = timeouts; 01015 SERVER_UNLOCK (server); 01016 01017 return result; 01018 } 01019 01033 dbus_bool_t 01034 dbus_server_set_auth_mechanisms (DBusServer *server, 01035 const char **mechanisms) 01036 { 01037 char **copy; 01038 01039 _dbus_return_val_if_fail (server != NULL, FALSE); 01040 01041 SERVER_LOCK (server); 01042 01043 if (mechanisms != NULL) 01044 { 01045 copy = _dbus_dup_string_array (mechanisms); 01046 if (copy == NULL) 01047 return FALSE; 01048 } 01049 else 01050 copy = NULL; 01051 01052 dbus_free_string_array (server->auth_mechanisms); 01053 server->auth_mechanisms = copy; 01054 01055 SERVER_UNLOCK (server); 01056 01057 return TRUE; 01058 } 01059 01060 01061 static DBusDataSlotAllocator slot_allocator; 01062 _DBUS_DEFINE_GLOBAL_LOCK (server_slots); 01063 01078 dbus_bool_t 01079 dbus_server_allocate_data_slot (dbus_int32_t *slot_p) 01080 { 01081 return _dbus_data_slot_allocator_alloc (&slot_allocator, 01082 (DBusMutex **)&_DBUS_LOCK_NAME (server_slots), 01083 slot_p); 01084 } 01085 01097 void 01098 dbus_server_free_data_slot (dbus_int32_t *slot_p) 01099 { 01100 _dbus_return_if_fail (*slot_p >= 0); 01101 01102 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 01103 } 01104 01118 dbus_bool_t 01119 dbus_server_set_data (DBusServer *server, 01120 int slot, 01121 void *data, 01122 DBusFreeFunction free_data_func) 01123 { 01124 DBusFreeFunction old_free_func; 01125 void *old_data; 01126 dbus_bool_t retval; 01127 01128 _dbus_return_val_if_fail (server != NULL, FALSE); 01129 01130 SERVER_LOCK (server); 01131 01132 retval = _dbus_data_slot_list_set (&slot_allocator, 01133 &server->slot_list, 01134 slot, data, free_data_func, 01135 &old_free_func, &old_data); 01136 01137 01138 SERVER_UNLOCK (server); 01139 01140 if (retval) 01141 { 01142 /* Do the actual free outside the server lock */ 01143 if (old_free_func) 01144 (* old_free_func) (old_data); 01145 } 01146 01147 return retval; 01148 } 01149 01158 void* 01159 dbus_server_get_data (DBusServer *server, 01160 int slot) 01161 { 01162 void *res; 01163 01164 _dbus_return_val_if_fail (server != NULL, NULL); 01165 01166 SERVER_LOCK (server); 01167 01168 res = _dbus_data_slot_list_get (&slot_allocator, 01169 &server->slot_list, 01170 slot); 01171 01172 SERVER_UNLOCK (server); 01173 01174 return res; 01175 } 01176 01179 #ifdef DBUS_BUILD_TESTS 01180 #include "dbus-test.h" 01181 #include <string.h> 01182 01183 dbus_bool_t 01184 _dbus_server_test (void) 01185 { 01186 const char *valid_addresses[] = { 01187 "tcp:port=1234", 01188 "tcp:host=localhost,port=1234", 01189 "tcp:host=localhost,port=1234;tcp:port=5678", 01190 #ifdef DBUS_UNIX 01191 "unix:path=./boogie", 01192 "tcp:port=1234;unix:path=./boogie", 01193 #endif 01194 }; 01195 01196 DBusServer *server; 01197 int i; 01198 01199 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) 01200 { 01201 DBusError error = DBUS_ERROR_INIT; 01202 char *address; 01203 char *id; 01204 01205 server = dbus_server_listen (valid_addresses[i], &error); 01206 if (server == NULL) 01207 { 01208 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); 01209 dbus_error_free (&error); 01210 _dbus_assert_not_reached ("Failed to listen for valid address."); 01211 } 01212 01213 id = dbus_server_get_id (server); 01214 _dbus_assert (id != NULL); 01215 address = dbus_server_get_address (server); 01216 _dbus_assert (address != NULL); 01217 01218 if (strstr (address, id) == NULL) 01219 { 01220 _dbus_warn ("server id '%s' is not in the server address '%s'\n", 01221 id, address); 01222 _dbus_assert_not_reached ("bad server id or address"); 01223 } 01224 01225 dbus_free (id); 01226 dbus_free (address); 01227 01228 dbus_server_disconnect (server); 01229 dbus_server_unref (server); 01230 } 01231 01232 return TRUE; 01233 } 01234 01235 #endif /* DBUS_BUILD_TESTS */