|
D-Bus
1.8.20
|
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_ENABLE_EMBEDDED_TESTS 00030 #include "dbus-server-debug-pipe.h" 00031 #endif 00032 #include "dbus-address.h" 00033 #include "dbus-protocol.h" 00034 00056 #ifndef _dbus_server_trace_ref 00057 void 00058 _dbus_server_trace_ref (DBusServer *server, 00059 int old_refcount, 00060 int new_refcount, 00061 const char *why) 00062 { 00063 static int enabled = -1; 00064 00065 _dbus_trace_ref ("DBusServer", server, old_refcount, new_refcount, why, 00066 "DBUS_SERVER_TRACE", &enabled); 00067 } 00068 #endif 00069 00070 /* this is a little fragile since it assumes the address doesn't 00071 * already have a guid, but it shouldn't 00072 */ 00073 static char* 00074 copy_address_with_guid_appended (const DBusString *address, 00075 const DBusString *guid_hex) 00076 { 00077 DBusString with_guid; 00078 char *retval; 00079 00080 if (!_dbus_string_init (&with_guid)) 00081 return NULL; 00082 00083 if (!_dbus_string_copy (address, 0, &with_guid, 00084 _dbus_string_get_length (&with_guid)) || 00085 !_dbus_string_append (&with_guid, ",guid=") || 00086 !_dbus_string_copy (guid_hex, 0, 00087 &with_guid, _dbus_string_get_length (&with_guid))) 00088 { 00089 _dbus_string_free (&with_guid); 00090 return NULL; 00091 } 00092 00093 retval = NULL; 00094 _dbus_string_steal_data (&with_guid, &retval); 00095 00096 _dbus_string_free (&with_guid); 00097 00098 return retval; /* may be NULL if steal_data failed */ 00099 } 00100 00110 dbus_bool_t 00111 _dbus_server_init_base (DBusServer *server, 00112 const DBusServerVTable *vtable, 00113 const DBusString *address) 00114 { 00115 server->vtable = vtable; 00116 00117 #ifdef DBUS_DISABLE_ASSERT 00118 _dbus_atomic_inc (&server->refcount); 00119 #else 00120 { 00121 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00122 00123 _dbus_assert (old_refcount == 0); 00124 } 00125 #endif 00126 00127 server->address = NULL; 00128 server->watches = NULL; 00129 server->timeouts = NULL; 00130 server->published_address = FALSE; 00131 00132 if (!_dbus_string_init (&server->guid_hex)) 00133 return FALSE; 00134 00135 _dbus_generate_uuid (&server->guid); 00136 00137 if (!_dbus_uuid_encode (&server->guid, &server->guid_hex)) 00138 goto failed; 00139 00140 server->address = copy_address_with_guid_appended (address, 00141 &server->guid_hex); 00142 if (server->address == NULL) 00143 goto failed; 00144 00145 _dbus_rmutex_new_at_location (&server->mutex); 00146 if (server->mutex == NULL) 00147 goto failed; 00148 00149 server->watches = _dbus_watch_list_new (); 00150 if (server->watches == NULL) 00151 goto failed; 00152 00153 server->timeouts = _dbus_timeout_list_new (); 00154 if (server->timeouts == NULL) 00155 goto failed; 00156 00157 _dbus_data_slot_list_init (&server->slot_list); 00158 00159 _dbus_verbose ("Initialized server on address %s\n", server->address); 00160 00161 return TRUE; 00162 00163 failed: 00164 _dbus_rmutex_free_at_location (&server->mutex); 00165 server->mutex = NULL; 00166 if (server->watches) 00167 { 00168 _dbus_watch_list_free (server->watches); 00169 server->watches = NULL; 00170 } 00171 if (server->timeouts) 00172 { 00173 _dbus_timeout_list_free (server->timeouts); 00174 server->timeouts = NULL; 00175 } 00176 if (server->address) 00177 { 00178 dbus_free (server->address); 00179 server->address = NULL; 00180 } 00181 _dbus_string_free (&server->guid_hex); 00182 00183 return FALSE; 00184 } 00185 00192 void 00193 _dbus_server_finalize_base (DBusServer *server) 00194 { 00195 /* We don't have the lock, but nobody should be accessing 00196 * concurrently since they don't have a ref 00197 */ 00198 #ifndef DBUS_DISABLE_CHECKS 00199 _dbus_assert (!server->have_server_lock); 00200 #endif 00201 _dbus_assert (server->disconnected); 00202 00203 /* calls out to application code... */ 00204 _dbus_data_slot_list_free (&server->slot_list); 00205 00206 dbus_server_set_new_connection_function (server, NULL, NULL, NULL); 00207 00208 _dbus_watch_list_free (server->watches); 00209 _dbus_timeout_list_free (server->timeouts); 00210 00211 _dbus_rmutex_free_at_location (&server->mutex); 00212 00213 dbus_free (server->address); 00214 00215 dbus_free_string_array (server->auth_mechanisms); 00216 00217 _dbus_string_free (&server->guid_hex); 00218 } 00219 00220 00222 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00223 DBusWatch *watch); 00225 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00226 DBusWatch *watch); 00228 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00229 DBusWatch *watch, 00230 dbus_bool_t enabled); 00231 00232 static dbus_bool_t 00233 protected_change_watch (DBusServer *server, 00234 DBusWatch *watch, 00235 DBusWatchAddFunction add_function, 00236 DBusWatchRemoveFunction remove_function, 00237 DBusWatchToggleFunction toggle_function, 00238 dbus_bool_t enabled) 00239 { 00240 DBusWatchList *watches; 00241 dbus_bool_t retval; 00242 00243 HAVE_LOCK_CHECK (server); 00244 00245 /* This isn't really safe or reasonable; a better pattern is the "do 00246 * everything, then drop lock and call out" one; but it has to be 00247 * propagated up through all callers 00248 */ 00249 00250 watches = server->watches; 00251 if (watches) 00252 { 00253 server->watches = NULL; 00254 _dbus_server_ref_unlocked (server); 00255 SERVER_UNLOCK (server); 00256 00257 if (add_function) 00258 retval = (* add_function) (watches, watch); 00259 else if (remove_function) 00260 { 00261 retval = TRUE; 00262 (* remove_function) (watches, watch); 00263 } 00264 else 00265 { 00266 retval = TRUE; 00267 (* toggle_function) (watches, watch, enabled); 00268 } 00269 00270 SERVER_LOCK (server); 00271 server->watches = watches; 00272 _dbus_server_unref_unlocked (server); 00273 00274 return retval; 00275 } 00276 else 00277 return FALSE; 00278 } 00279 00287 dbus_bool_t 00288 _dbus_server_add_watch (DBusServer *server, 00289 DBusWatch *watch) 00290 { 00291 HAVE_LOCK_CHECK (server); 00292 return protected_change_watch (server, watch, 00293 _dbus_watch_list_add_watch, 00294 NULL, NULL, FALSE); 00295 } 00296 00303 void 00304 _dbus_server_remove_watch (DBusServer *server, 00305 DBusWatch *watch) 00306 { 00307 HAVE_LOCK_CHECK (server); 00308 protected_change_watch (server, watch, 00309 NULL, 00310 _dbus_watch_list_remove_watch, 00311 NULL, FALSE); 00312 } 00313 00321 void 00322 _dbus_server_toggle_all_watches (DBusServer *server, 00323 dbus_bool_t enabled) 00324 { 00325 _dbus_watch_list_toggle_all_watches (server->watches, enabled); 00326 } 00327 00329 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00330 DBusTimeout *timeout); 00332 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00333 DBusTimeout *timeout); 00335 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00336 DBusTimeout *timeout, 00337 dbus_bool_t enabled); 00338 00339 00340 static dbus_bool_t 00341 protected_change_timeout (DBusServer *server, 00342 DBusTimeout *timeout, 00343 DBusTimeoutAddFunction add_function, 00344 DBusTimeoutRemoveFunction remove_function, 00345 DBusTimeoutToggleFunction toggle_function, 00346 dbus_bool_t enabled) 00347 { 00348 DBusTimeoutList *timeouts; 00349 dbus_bool_t retval; 00350 00351 HAVE_LOCK_CHECK (server); 00352 00353 /* This isn't really safe or reasonable; a better pattern is the "do everything, then 00354 * drop lock and call out" one; but it has to be propagated up through all callers 00355 */ 00356 00357 timeouts = server->timeouts; 00358 if (timeouts) 00359 { 00360 server->timeouts = NULL; 00361 _dbus_server_ref_unlocked (server); 00362 SERVER_UNLOCK (server); 00363 00364 if (add_function) 00365 retval = (* add_function) (timeouts, timeout); 00366 else if (remove_function) 00367 { 00368 retval = TRUE; 00369 (* remove_function) (timeouts, timeout); 00370 } 00371 else 00372 { 00373 retval = TRUE; 00374 (* toggle_function) (timeouts, timeout, enabled); 00375 } 00376 00377 SERVER_LOCK (server); 00378 server->timeouts = timeouts; 00379 _dbus_server_unref_unlocked (server); 00380 00381 return retval; 00382 } 00383 else 00384 return FALSE; 00385 } 00386 00396 dbus_bool_t 00397 _dbus_server_add_timeout (DBusServer *server, 00398 DBusTimeout *timeout) 00399 { 00400 return protected_change_timeout (server, timeout, 00401 _dbus_timeout_list_add_timeout, 00402 NULL, NULL, FALSE); 00403 } 00404 00411 void 00412 _dbus_server_remove_timeout (DBusServer *server, 00413 DBusTimeout *timeout) 00414 { 00415 protected_change_timeout (server, timeout, 00416 NULL, 00417 _dbus_timeout_list_remove_timeout, 00418 NULL, FALSE); 00419 } 00420 00430 void 00431 _dbus_server_toggle_timeout (DBusServer *server, 00432 DBusTimeout *timeout, 00433 dbus_bool_t enabled) 00434 { 00435 protected_change_timeout (server, timeout, 00436 NULL, NULL, 00437 _dbus_timeout_list_toggle_timeout, 00438 enabled); 00439 } 00440 00441 00447 void 00448 _dbus_server_ref_unlocked (DBusServer *server) 00449 { 00450 dbus_int32_t old_refcount; 00451 00452 _dbus_assert (server != NULL); 00453 HAVE_LOCK_CHECK (server); 00454 00455 old_refcount = _dbus_atomic_inc (&server->refcount); 00456 _dbus_assert (old_refcount > 0); 00457 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, 00458 "ref_unlocked"); 00459 } 00460 00466 void 00467 _dbus_server_unref_unlocked (DBusServer *server) 00468 { 00469 dbus_int32_t old_refcount; 00470 00471 /* Keep this in sync with dbus_server_unref */ 00472 00473 _dbus_assert (server != NULL); 00474 00475 HAVE_LOCK_CHECK (server); 00476 00477 old_refcount = _dbus_atomic_dec (&server->refcount); 00478 _dbus_assert (old_refcount > 0); 00479 00480 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, 00481 "unref_unlocked"); 00482 00483 if (old_refcount == 1) 00484 { 00485 _dbus_assert (server->disconnected); 00486 00487 SERVER_UNLOCK (server); 00488 00489 _dbus_assert (server->vtable->finalize != NULL); 00490 00491 (* server->vtable->finalize) (server); 00492 } 00493 } 00494 00516 static const struct { 00517 DBusServerListenResult (* func) (DBusAddressEntry *entry, 00518 DBusServer **server_p, 00519 DBusError *error); 00520 } listen_funcs[] = { 00521 { _dbus_server_listen_socket } 00522 , { _dbus_server_listen_platform_specific } 00523 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00524 , { _dbus_server_listen_debug_pipe } 00525 #endif 00526 }; 00527 00548 DBusServer* 00549 dbus_server_listen (const char *address, 00550 DBusError *error) 00551 { 00552 DBusServer *server; 00553 DBusAddressEntry **entries; 00554 int len, i; 00555 DBusError first_connect_error = DBUS_ERROR_INIT; 00556 dbus_bool_t handled_once; 00557 00558 _dbus_return_val_if_fail (address != NULL, NULL); 00559 _dbus_return_val_if_error_is_set (error, NULL); 00560 00561 if (!dbus_parse_address (address, &entries, &len, error)) 00562 return NULL; 00563 00564 server = NULL; 00565 handled_once = FALSE; 00566 00567 for (i = 0; i < len; i++) 00568 { 00569 int j; 00570 00571 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j) 00572 { 00573 DBusServerListenResult result; 00574 DBusError tmp_error = DBUS_ERROR_INIT; 00575 00576 result = (* listen_funcs[j].func) (entries[i], 00577 &server, 00578 &tmp_error); 00579 00580 if (result == DBUS_SERVER_LISTEN_OK) 00581 { 00582 _dbus_assert (server != NULL); 00583 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00584 handled_once = TRUE; 00585 goto out; 00586 } 00587 else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED) 00588 { 00589 _dbus_assert (server == NULL); 00590 dbus_set_error (error, 00591 DBUS_ERROR_ADDRESS_IN_USE, 00592 "Address '%s' already used", 00593 dbus_address_entry_get_method (entries[0])); 00594 handled_once = TRUE; 00595 goto out; 00596 } 00597 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS) 00598 { 00599 _dbus_assert (server == NULL); 00600 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00601 dbus_move_error (&tmp_error, error); 00602 handled_once = TRUE; 00603 goto out; 00604 } 00605 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED) 00606 { 00607 _dbus_assert (server == NULL); 00608 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 00609 00610 /* keep trying addresses */ 00611 } 00612 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT) 00613 { 00614 _dbus_assert (server == NULL); 00615 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 00616 if (!dbus_error_is_set (&first_connect_error)) 00617 dbus_move_error (&tmp_error, &first_connect_error); 00618 else 00619 dbus_error_free (&tmp_error); 00620 00621 handled_once = TRUE; 00622 00623 /* keep trying addresses */ 00624 } 00625 } 00626 00627 _dbus_assert (server == NULL); 00628 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00629 } 00630 00631 out: 00632 00633 if (!handled_once) 00634 { 00635 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00636 if (len > 0) 00637 dbus_set_error (error, 00638 DBUS_ERROR_BAD_ADDRESS, 00639 "Unknown address type '%s'", 00640 dbus_address_entry_get_method (entries[0])); 00641 else 00642 dbus_set_error (error, 00643 DBUS_ERROR_BAD_ADDRESS, 00644 "Empty address '%s'", 00645 address); 00646 } 00647 00648 dbus_address_entries_free (entries); 00649 00650 if (server == NULL) 00651 { 00652 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) || 00653 dbus_error_is_set (error)); 00654 00655 if (error && dbus_error_is_set (error)) 00656 { 00657 /* already set the error */ 00658 } 00659 else 00660 { 00661 /* didn't set the error but either error should be 00662 * NULL or first_connect_error should be set. 00663 */ 00664 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error)); 00665 dbus_move_error (&first_connect_error, error); 00666 } 00667 00668 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */ 00669 _DBUS_ASSERT_ERROR_IS_SET (error); 00670 00671 return NULL; 00672 } 00673 else 00674 { 00675 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00676 return server; 00677 } 00678 } 00679 00686 DBusServer * 00687 dbus_server_ref (DBusServer *server) 00688 { 00689 dbus_int32_t old_refcount; 00690 00691 _dbus_return_val_if_fail (server != NULL, NULL); 00692 00693 old_refcount = _dbus_atomic_inc (&server->refcount); 00694 00695 #ifndef DBUS_DISABLE_CHECKS 00696 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00697 { 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 #endif 00705 00706 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref"); 00707 00708 return server; 00709 } 00710 00719 void 00720 dbus_server_unref (DBusServer *server) 00721 { 00722 dbus_int32_t old_refcount; 00723 00724 /* keep this in sync with unref_unlocked */ 00725 00726 _dbus_return_if_fail (server != NULL); 00727 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 * please do not try to simplify the code here by using 00735 * _dbus_atomic_get(), why we don't use it is 00736 * because it issues another atomic operation even though 00737 * DBUS_DISABLE_CHECKS defined. 00738 * Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68303 00739 */ 00740 _dbus_atomic_inc (&server->refcount); 00741 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00742 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00743 __FILE__, __LINE__); 00744 return; 00745 } 00746 #endif 00747 00748 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref"); 00749 00750 if (old_refcount == 1) 00751 { 00752 /* lock not held! */ 00753 _dbus_assert (server->disconnected); 00754 00755 _dbus_assert (server->vtable->finalize != NULL); 00756 00757 (* server->vtable->finalize) (server); 00758 } 00759 } 00760 00769 void 00770 dbus_server_disconnect (DBusServer *server) 00771 { 00772 _dbus_return_if_fail (server != NULL); 00773 00774 dbus_server_ref (server); 00775 SERVER_LOCK (server); 00776 00777 _dbus_assert (server->vtable->disconnect != NULL); 00778 00779 if (!server->disconnected) 00780 { 00781 /* this has to be first so recursive calls to disconnect don't happen */ 00782 server->disconnected = TRUE; 00783 00784 (* server->vtable->disconnect) (server); 00785 } 00786 00787 SERVER_UNLOCK (server); 00788 dbus_server_unref (server); 00789 } 00790 00796 dbus_bool_t 00797 dbus_server_get_is_connected (DBusServer *server) 00798 { 00799 dbus_bool_t retval; 00800 00801 _dbus_return_val_if_fail (server != NULL, FALSE); 00802 00803 SERVER_LOCK (server); 00804 retval = !server->disconnected; 00805 SERVER_UNLOCK (server); 00806 00807 return retval; 00808 } 00809 00817 char* 00818 dbus_server_get_address (DBusServer *server) 00819 { 00820 char *retval; 00821 00822 _dbus_return_val_if_fail (server != NULL, NULL); 00823 00824 SERVER_LOCK (server); 00825 retval = _dbus_strdup (server->address); 00826 SERVER_UNLOCK (server); 00827 00828 return retval; 00829 } 00830 00853 char* 00854 dbus_server_get_id (DBusServer *server) 00855 { 00856 char *retval; 00857 00858 _dbus_return_val_if_fail (server != NULL, NULL); 00859 00860 SERVER_LOCK (server); 00861 retval = NULL; 00862 _dbus_string_copy_data (&server->guid_hex, &retval); 00863 SERVER_UNLOCK (server); 00864 00865 return retval; 00866 } 00867 00888 void 00889 dbus_server_set_new_connection_function (DBusServer *server, 00890 DBusNewConnectionFunction function, 00891 void *data, 00892 DBusFreeFunction free_data_function) 00893 { 00894 DBusFreeFunction old_free_function; 00895 void *old_data; 00896 00897 _dbus_return_if_fail (server != NULL); 00898 00899 SERVER_LOCK (server); 00900 old_free_function = server->new_connection_free_data_function; 00901 old_data = server->new_connection_data; 00902 00903 server->new_connection_function = function; 00904 server->new_connection_data = data; 00905 server->new_connection_free_data_function = free_data_function; 00906 SERVER_UNLOCK (server); 00907 00908 if (old_free_function != NULL) 00909 (* old_free_function) (old_data); 00910 } 00911 00928 dbus_bool_t 00929 dbus_server_set_watch_functions (DBusServer *server, 00930 DBusAddWatchFunction add_function, 00931 DBusRemoveWatchFunction remove_function, 00932 DBusWatchToggledFunction toggled_function, 00933 void *data, 00934 DBusFreeFunction free_data_function) 00935 { 00936 dbus_bool_t result; 00937 DBusWatchList *watches; 00938 00939 _dbus_return_val_if_fail (server != NULL, FALSE); 00940 00941 SERVER_LOCK (server); 00942 watches = server->watches; 00943 server->watches = NULL; 00944 if (watches) 00945 { 00946 SERVER_UNLOCK (server); 00947 result = _dbus_watch_list_set_functions (watches, 00948 add_function, 00949 remove_function, 00950 toggled_function, 00951 data, 00952 free_data_function); 00953 SERVER_LOCK (server); 00954 } 00955 else 00956 { 00957 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00958 result = FALSE; 00959 } 00960 server->watches = watches; 00961 SERVER_UNLOCK (server); 00962 00963 return result; 00964 } 00965 00981 dbus_bool_t 00982 dbus_server_set_timeout_functions (DBusServer *server, 00983 DBusAddTimeoutFunction add_function, 00984 DBusRemoveTimeoutFunction remove_function, 00985 DBusTimeoutToggledFunction toggled_function, 00986 void *data, 00987 DBusFreeFunction free_data_function) 00988 { 00989 dbus_bool_t result; 00990 DBusTimeoutList *timeouts; 00991 00992 _dbus_return_val_if_fail (server != NULL, FALSE); 00993 00994 SERVER_LOCK (server); 00995 timeouts = server->timeouts; 00996 server->timeouts = NULL; 00997 if (timeouts) 00998 { 00999 SERVER_UNLOCK (server); 01000 result = _dbus_timeout_list_set_functions (timeouts, 01001 add_function, 01002 remove_function, 01003 toggled_function, 01004 data, 01005 free_data_function); 01006 SERVER_LOCK (server); 01007 } 01008 else 01009 { 01010 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 01011 result = FALSE; 01012 } 01013 server->timeouts = timeouts; 01014 SERVER_UNLOCK (server); 01015 01016 return result; 01017 } 01018 01032 dbus_bool_t 01033 dbus_server_set_auth_mechanisms (DBusServer *server, 01034 const char **mechanisms) 01035 { 01036 char **copy; 01037 01038 _dbus_return_val_if_fail (server != NULL, FALSE); 01039 01040 SERVER_LOCK (server); 01041 01042 if (mechanisms != NULL) 01043 { 01044 copy = _dbus_dup_string_array (mechanisms); 01045 if (copy == NULL) 01046 { 01047 SERVER_UNLOCK (server); 01048 return FALSE; 01049 } 01050 } 01051 else 01052 copy = NULL; 01053 01054 dbus_free_string_array (server->auth_mechanisms); 01055 server->auth_mechanisms = copy; 01056 01057 SERVER_UNLOCK (server); 01058 01059 return TRUE; 01060 } 01061 01062 static DBusDataSlotAllocator slot_allocator = 01063 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (server_slots)); 01064 01079 dbus_bool_t 01080 dbus_server_allocate_data_slot (dbus_int32_t *slot_p) 01081 { 01082 return _dbus_data_slot_allocator_alloc (&slot_allocator, 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_ENABLE_EMBEDDED_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_ENABLE_EMBEDDED_TESTS */
1.7.6.1