D-Bus
1.4.18
|
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 00307 void 00308 _dbus_server_toggle_all_watches (DBusServer *server, 00309 dbus_bool_t enabled) 00310 { 00311 _dbus_watch_list_toggle_all_watches (server->watches, 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 HAVE_LOCK_CHECK (server); 00438 00439 #ifdef DBUS_DISABLE_ASSERT 00440 _dbus_atomic_inc (&server->refcount); 00441 #else 00442 { 00443 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00444 00445 _dbus_assert (old_refcount > 0); 00446 } 00447 #endif 00448 } 00449 00455 void 00456 _dbus_server_unref_unlocked (DBusServer *server) 00457 { 00458 dbus_int32_t old_refcount; 00459 00460 /* Keep this in sync with dbus_server_unref */ 00461 00462 _dbus_assert (server != NULL); 00463 00464 HAVE_LOCK_CHECK (server); 00465 00466 old_refcount = _dbus_atomic_dec (&server->refcount); 00467 _dbus_assert (old_refcount > 0); 00468 00469 if (old_refcount == 1) 00470 { 00471 _dbus_assert (server->disconnected); 00472 00473 SERVER_UNLOCK (server); 00474 00475 _dbus_assert (server->vtable->finalize != NULL); 00476 00477 (* server->vtable->finalize) (server); 00478 } 00479 } 00480 00502 static const struct { 00503 DBusServerListenResult (* func) (DBusAddressEntry *entry, 00504 DBusServer **server_p, 00505 DBusError *error); 00506 } listen_funcs[] = { 00507 { _dbus_server_listen_socket } 00508 , { _dbus_server_listen_platform_specific } 00509 #ifdef DBUS_BUILD_TESTS 00510 , { _dbus_server_listen_debug_pipe } 00511 #endif 00512 }; 00513 00534 DBusServer* 00535 dbus_server_listen (const char *address, 00536 DBusError *error) 00537 { 00538 DBusServer *server; 00539 DBusAddressEntry **entries; 00540 int len, i; 00541 DBusError first_connect_error = DBUS_ERROR_INIT; 00542 dbus_bool_t handled_once; 00543 00544 _dbus_return_val_if_fail (address != NULL, NULL); 00545 _dbus_return_val_if_error_is_set (error, NULL); 00546 00547 if (!dbus_parse_address (address, &entries, &len, error)) 00548 return NULL; 00549 00550 server = NULL; 00551 handled_once = FALSE; 00552 00553 for (i = 0; i < len; i++) 00554 { 00555 int j; 00556 00557 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j) 00558 { 00559 DBusServerListenResult result; 00560 DBusError tmp_error = DBUS_ERROR_INIT; 00561 00562 result = (* listen_funcs[j].func) (entries[i], 00563 &server, 00564 &tmp_error); 00565 00566 if (result == DBUS_SERVER_LISTEN_OK) 00567 { 00568 _dbus_assert (server != NULL); 00569 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00570 handled_once = TRUE; 00571 goto out; 00572 } 00573 else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED) 00574 { 00575 _dbus_assert (server == NULL); 00576 dbus_set_error (error, 00577 DBUS_ERROR_ADDRESS_IN_USE, 00578 "Address '%s' already used", 00579 dbus_address_entry_get_method (entries[0])); 00580 handled_once = TRUE; 00581 goto out; 00582 } 00583 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS) 00584 { 00585 _dbus_assert (server == NULL); 00586 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00587 dbus_move_error (&tmp_error, error); 00588 handled_once = TRUE; 00589 goto out; 00590 } 00591 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED) 00592 { 00593 _dbus_assert (server == NULL); 00594 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00595 00596 /* keep trying addresses */ 00597 } 00598 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT) 00599 { 00600 _dbus_assert (server == NULL); 00601 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00602 if (!dbus_error_is_set (&first_connect_error)) 00603 dbus_move_error (&tmp_error, &first_connect_error); 00604 else 00605 dbus_error_free (&tmp_error); 00606 00607 handled_once = TRUE; 00608 00609 /* keep trying addresses */ 00610 } 00611 } 00612 00613 _dbus_assert (server == NULL); 00614 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00615 } 00616 00617 out: 00618 00619 if (!handled_once) 00620 { 00621 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00622 if (len > 0) 00623 dbus_set_error (error, 00624 DBUS_ERROR_BAD_ADDRESS, 00625 "Unknown address type '%s'", 00626 dbus_address_entry_get_method (entries[0])); 00627 else 00628 dbus_set_error (error, 00629 DBUS_ERROR_BAD_ADDRESS, 00630 "Empty address '%s'", 00631 address); 00632 } 00633 00634 dbus_address_entries_free (entries); 00635 00636 if (server == NULL) 00637 { 00638 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) || 00639 dbus_error_is_set (error)); 00640 00641 if (error && dbus_error_is_set (error)) 00642 { 00643 /* already set the error */ 00644 } 00645 else 00646 { 00647 /* didn't set the error but either error should be 00648 * NULL or first_connect_error should be set. 00649 */ 00650 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error)); 00651 dbus_move_error (&first_connect_error, error); 00652 } 00653 00654 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */ 00655 _DBUS_ASSERT_ERROR_IS_SET (error); 00656 00657 return NULL; 00658 } 00659 else 00660 { 00661 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00662 return server; 00663 } 00664 } 00665 00672 DBusServer * 00673 dbus_server_ref (DBusServer *server) 00674 { 00675 _dbus_return_val_if_fail (server != NULL, NULL); 00676 00677 #ifdef DBUS_DISABLE_CHECKS 00678 _dbus_atomic_inc (&server->refcount); 00679 #else 00680 { 00681 dbus_int32_t old_refcount; 00682 00683 /* can't get the refcount without a side-effect */ 00684 old_refcount = _dbus_atomic_inc (&server->refcount); 00685 00686 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00687 { 00688 /* undo side-effect first */ 00689 _dbus_atomic_dec (&server->refcount); 00690 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00691 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00692 __FILE__, __LINE__); 00693 return NULL; 00694 } 00695 } 00696 #endif 00697 00698 return server; 00699 } 00700 00709 void 00710 dbus_server_unref (DBusServer *server) 00711 { 00712 dbus_int32_t old_refcount; 00713 00714 /* keep this in sync with unref_unlocked */ 00715 00716 _dbus_return_if_fail (server != NULL); 00717 00718 /* can't get the refcount without a side-effect */ 00719 old_refcount = _dbus_atomic_dec (&server->refcount); 00720 00721 #ifndef DBUS_DISABLE_CHECKS 00722 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00723 { 00724 /* undo side-effect first */ 00725 _dbus_atomic_inc (&server->refcount); 00726 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00727 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00728 __FILE__, __LINE__); 00729 return; 00730 } 00731 #endif 00732 00733 if (old_refcount == 1) 00734 { 00735 /* lock not held! */ 00736 _dbus_assert (server->disconnected); 00737 00738 _dbus_assert (server->vtable->finalize != NULL); 00739 00740 (* server->vtable->finalize) (server); 00741 } 00742 } 00743 00752 void 00753 dbus_server_disconnect (DBusServer *server) 00754 { 00755 _dbus_return_if_fail (server != NULL); 00756 00757 #ifdef DBUS_DISABLE_CHECKS 00758 _dbus_atomic_inc (&server->refcount); 00759 #else 00760 { 00761 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00762 00763 _dbus_return_if_fail (old_refcount > 0); 00764 } 00765 #endif 00766 00767 SERVER_LOCK (server); 00768 00769 _dbus_assert (server->vtable->disconnect != NULL); 00770 00771 if (!server->disconnected) 00772 { 00773 /* this has to be first so recursive calls to disconnect don't happen */ 00774 server->disconnected = TRUE; 00775 00776 (* server->vtable->disconnect) (server); 00777 } 00778 00779 SERVER_UNLOCK (server); 00780 dbus_server_unref (server); 00781 } 00782 00788 dbus_bool_t 00789 dbus_server_get_is_connected (DBusServer *server) 00790 { 00791 dbus_bool_t retval; 00792 00793 _dbus_return_val_if_fail (server != NULL, FALSE); 00794 00795 SERVER_LOCK (server); 00796 retval = !server->disconnected; 00797 SERVER_UNLOCK (server); 00798 00799 return retval; 00800 } 00801 00809 char* 00810 dbus_server_get_address (DBusServer *server) 00811 { 00812 char *retval; 00813 00814 _dbus_return_val_if_fail (server != NULL, NULL); 00815 00816 SERVER_LOCK (server); 00817 retval = _dbus_strdup (server->address); 00818 SERVER_UNLOCK (server); 00819 00820 return retval; 00821 } 00822 00845 char* 00846 dbus_server_get_id (DBusServer *server) 00847 { 00848 char *retval; 00849 00850 _dbus_return_val_if_fail (server != NULL, NULL); 00851 00852 SERVER_LOCK (server); 00853 retval = NULL; 00854 _dbus_string_copy_data (&server->guid_hex, &retval); 00855 SERVER_UNLOCK (server); 00856 00857 return retval; 00858 } 00859 00880 void 00881 dbus_server_set_new_connection_function (DBusServer *server, 00882 DBusNewConnectionFunction function, 00883 void *data, 00884 DBusFreeFunction free_data_function) 00885 { 00886 DBusFreeFunction old_free_function; 00887 void *old_data; 00888 00889 _dbus_return_if_fail (server != NULL); 00890 00891 SERVER_LOCK (server); 00892 old_free_function = server->new_connection_free_data_function; 00893 old_data = server->new_connection_data; 00894 00895 server->new_connection_function = function; 00896 server->new_connection_data = data; 00897 server->new_connection_free_data_function = free_data_function; 00898 SERVER_UNLOCK (server); 00899 00900 if (old_free_function != NULL) 00901 (* old_free_function) (old_data); 00902 } 00903 00920 dbus_bool_t 00921 dbus_server_set_watch_functions (DBusServer *server, 00922 DBusAddWatchFunction add_function, 00923 DBusRemoveWatchFunction remove_function, 00924 DBusWatchToggledFunction toggled_function, 00925 void *data, 00926 DBusFreeFunction free_data_function) 00927 { 00928 dbus_bool_t result; 00929 DBusWatchList *watches; 00930 00931 _dbus_return_val_if_fail (server != NULL, FALSE); 00932 00933 SERVER_LOCK (server); 00934 watches = server->watches; 00935 server->watches = NULL; 00936 if (watches) 00937 { 00938 SERVER_UNLOCK (server); 00939 result = _dbus_watch_list_set_functions (watches, 00940 add_function, 00941 remove_function, 00942 toggled_function, 00943 data, 00944 free_data_function); 00945 SERVER_LOCK (server); 00946 } 00947 else 00948 { 00949 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00950 result = FALSE; 00951 } 00952 server->watches = watches; 00953 SERVER_UNLOCK (server); 00954 00955 return result; 00956 } 00957 00973 dbus_bool_t 00974 dbus_server_set_timeout_functions (DBusServer *server, 00975 DBusAddTimeoutFunction add_function, 00976 DBusRemoveTimeoutFunction remove_function, 00977 DBusTimeoutToggledFunction toggled_function, 00978 void *data, 00979 DBusFreeFunction free_data_function) 00980 { 00981 dbus_bool_t result; 00982 DBusTimeoutList *timeouts; 00983 00984 _dbus_return_val_if_fail (server != NULL, FALSE); 00985 00986 SERVER_LOCK (server); 00987 timeouts = server->timeouts; 00988 server->timeouts = NULL; 00989 if (timeouts) 00990 { 00991 SERVER_UNLOCK (server); 00992 result = _dbus_timeout_list_set_functions (timeouts, 00993 add_function, 00994 remove_function, 00995 toggled_function, 00996 data, 00997 free_data_function); 00998 SERVER_LOCK (server); 00999 } 01000 else 01001 { 01002 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 01003 result = FALSE; 01004 } 01005 server->timeouts = timeouts; 01006 SERVER_UNLOCK (server); 01007 01008 return result; 01009 } 01010 01024 dbus_bool_t 01025 dbus_server_set_auth_mechanisms (DBusServer *server, 01026 const char **mechanisms) 01027 { 01028 char **copy; 01029 01030 _dbus_return_val_if_fail (server != NULL, FALSE); 01031 01032 SERVER_LOCK (server); 01033 01034 if (mechanisms != NULL) 01035 { 01036 copy = _dbus_dup_string_array (mechanisms); 01037 if (copy == NULL) 01038 return FALSE; 01039 } 01040 else 01041 copy = NULL; 01042 01043 dbus_free_string_array (server->auth_mechanisms); 01044 server->auth_mechanisms = copy; 01045 01046 SERVER_UNLOCK (server); 01047 01048 return TRUE; 01049 } 01050 01051 01052 static DBusDataSlotAllocator slot_allocator; 01053 _DBUS_DEFINE_GLOBAL_LOCK (server_slots); 01054 01069 dbus_bool_t 01070 dbus_server_allocate_data_slot (dbus_int32_t *slot_p) 01071 { 01072 return _dbus_data_slot_allocator_alloc (&slot_allocator, 01073 (DBusMutex **)&_DBUS_LOCK_NAME (server_slots), 01074 slot_p); 01075 } 01076 01088 void 01089 dbus_server_free_data_slot (dbus_int32_t *slot_p) 01090 { 01091 _dbus_return_if_fail (*slot_p >= 0); 01092 01093 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 01094 } 01095 01109 dbus_bool_t 01110 dbus_server_set_data (DBusServer *server, 01111 int slot, 01112 void *data, 01113 DBusFreeFunction free_data_func) 01114 { 01115 DBusFreeFunction old_free_func; 01116 void *old_data; 01117 dbus_bool_t retval; 01118 01119 _dbus_return_val_if_fail (server != NULL, FALSE); 01120 01121 SERVER_LOCK (server); 01122 01123 retval = _dbus_data_slot_list_set (&slot_allocator, 01124 &server->slot_list, 01125 slot, data, free_data_func, 01126 &old_free_func, &old_data); 01127 01128 01129 SERVER_UNLOCK (server); 01130 01131 if (retval) 01132 { 01133 /* Do the actual free outside the server lock */ 01134 if (old_free_func) 01135 (* old_free_func) (old_data); 01136 } 01137 01138 return retval; 01139 } 01140 01149 void* 01150 dbus_server_get_data (DBusServer *server, 01151 int slot) 01152 { 01153 void *res; 01154 01155 _dbus_return_val_if_fail (server != NULL, NULL); 01156 01157 SERVER_LOCK (server); 01158 01159 res = _dbus_data_slot_list_get (&slot_allocator, 01160 &server->slot_list, 01161 slot); 01162 01163 SERVER_UNLOCK (server); 01164 01165 return res; 01166 } 01167 01170 #ifdef DBUS_BUILD_TESTS 01171 #include "dbus-test.h" 01172 #include <string.h> 01173 01174 dbus_bool_t 01175 _dbus_server_test (void) 01176 { 01177 const char *valid_addresses[] = { 01178 "tcp:port=1234", 01179 "tcp:host=localhost,port=1234", 01180 "tcp:host=localhost,port=1234;tcp:port=5678", 01181 #ifdef DBUS_UNIX 01182 "unix:path=./boogie", 01183 "tcp:port=1234;unix:path=./boogie", 01184 #endif 01185 }; 01186 01187 DBusServer *server; 01188 int i; 01189 01190 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) 01191 { 01192 DBusError error = DBUS_ERROR_INIT; 01193 char *address; 01194 char *id; 01195 01196 server = dbus_server_listen (valid_addresses[i], &error); 01197 if (server == NULL) 01198 { 01199 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); 01200 dbus_error_free (&error); 01201 _dbus_assert_not_reached ("Failed to listen for valid address."); 01202 } 01203 01204 id = dbus_server_get_id (server); 01205 _dbus_assert (id != NULL); 01206 address = dbus_server_get_address (server); 01207 _dbus_assert (address != NULL); 01208 01209 if (strstr (address, id) == NULL) 01210 { 01211 _dbus_warn ("server id '%s' is not in the server address '%s'\n", 01212 id, address); 01213 _dbus_assert_not_reached ("bad server id or address"); 01214 } 01215 01216 dbus_free (id); 01217 dbus_free (address); 01218 01219 dbus_server_disconnect (server); 01220 dbus_server_unref (server); 01221 } 01222 01223 return TRUE; 01224 } 01225 01226 #endif /* DBUS_BUILD_TESTS */