|
D-Bus
1.6.30
|
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 #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_BUILD_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 /* can't get the refcount without a side-effect */ 00694 old_refcount = _dbus_atomic_inc (&server->refcount); 00695 00696 #ifndef DBUS_DISABLE_CHECKS 00697 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00698 { 00699 /* undo side-effect first */ 00700 _dbus_atomic_dec (&server->refcount); 00701 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00702 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00703 __FILE__, __LINE__); 00704 return NULL; 00705 } 00706 #endif 00707 00708 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref"); 00709 00710 return server; 00711 } 00712 00721 void 00722 dbus_server_unref (DBusServer *server) 00723 { 00724 dbus_int32_t old_refcount; 00725 00726 /* keep this in sync with unref_unlocked */ 00727 00728 _dbus_return_if_fail (server != NULL); 00729 00730 /* can't get the refcount without a side-effect */ 00731 old_refcount = _dbus_atomic_dec (&server->refcount); 00732 00733 #ifndef DBUS_DISABLE_CHECKS 00734 if (_DBUS_UNLIKELY (old_refcount <= 0)) 00735 { 00736 /* undo side-effect first */ 00737 _dbus_atomic_inc (&server->refcount); 00738 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format, 00739 _DBUS_FUNCTION_NAME, "old_refcount > 0", 00740 __FILE__, __LINE__); 00741 return; 00742 } 00743 #endif 00744 00745 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref"); 00746 00747 if (old_refcount == 1) 00748 { 00749 /* lock not held! */ 00750 _dbus_assert (server->disconnected); 00751 00752 _dbus_assert (server->vtable->finalize != NULL); 00753 00754 (* server->vtable->finalize) (server); 00755 } 00756 } 00757 00766 void 00767 dbus_server_disconnect (DBusServer *server) 00768 { 00769 _dbus_return_if_fail (server != NULL); 00770 00771 #ifdef DBUS_DISABLE_CHECKS 00772 _dbus_atomic_inc (&server->refcount); 00773 #else 00774 { 00775 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount); 00776 00777 _dbus_return_if_fail (old_refcount > 0); 00778 } 00779 #endif 00780 00781 SERVER_LOCK (server); 00782 00783 _dbus_assert (server->vtable->disconnect != NULL); 00784 00785 if (!server->disconnected) 00786 { 00787 /* this has to be first so recursive calls to disconnect don't happen */ 00788 server->disconnected = TRUE; 00789 00790 (* server->vtable->disconnect) (server); 00791 } 00792 00793 SERVER_UNLOCK (server); 00794 dbus_server_unref (server); 00795 } 00796 00802 dbus_bool_t 00803 dbus_server_get_is_connected (DBusServer *server) 00804 { 00805 dbus_bool_t retval; 00806 00807 _dbus_return_val_if_fail (server != NULL, FALSE); 00808 00809 SERVER_LOCK (server); 00810 retval = !server->disconnected; 00811 SERVER_UNLOCK (server); 00812 00813 return retval; 00814 } 00815 00823 char* 00824 dbus_server_get_address (DBusServer *server) 00825 { 00826 char *retval; 00827 00828 _dbus_return_val_if_fail (server != NULL, NULL); 00829 00830 SERVER_LOCK (server); 00831 retval = _dbus_strdup (server->address); 00832 SERVER_UNLOCK (server); 00833 00834 return retval; 00835 } 00836 00859 char* 00860 dbus_server_get_id (DBusServer *server) 00861 { 00862 char *retval; 00863 00864 _dbus_return_val_if_fail (server != NULL, NULL); 00865 00866 SERVER_LOCK (server); 00867 retval = NULL; 00868 _dbus_string_copy_data (&server->guid_hex, &retval); 00869 SERVER_UNLOCK (server); 00870 00871 return retval; 00872 } 00873 00894 void 00895 dbus_server_set_new_connection_function (DBusServer *server, 00896 DBusNewConnectionFunction function, 00897 void *data, 00898 DBusFreeFunction free_data_function) 00899 { 00900 DBusFreeFunction old_free_function; 00901 void *old_data; 00902 00903 _dbus_return_if_fail (server != NULL); 00904 00905 SERVER_LOCK (server); 00906 old_free_function = server->new_connection_free_data_function; 00907 old_data = server->new_connection_data; 00908 00909 server->new_connection_function = function; 00910 server->new_connection_data = data; 00911 server->new_connection_free_data_function = free_data_function; 00912 SERVER_UNLOCK (server); 00913 00914 if (old_free_function != NULL) 00915 (* old_free_function) (old_data); 00916 } 00917 00934 dbus_bool_t 00935 dbus_server_set_watch_functions (DBusServer *server, 00936 DBusAddWatchFunction add_function, 00937 DBusRemoveWatchFunction remove_function, 00938 DBusWatchToggledFunction toggled_function, 00939 void *data, 00940 DBusFreeFunction free_data_function) 00941 { 00942 dbus_bool_t result; 00943 DBusWatchList *watches; 00944 00945 _dbus_return_val_if_fail (server != NULL, FALSE); 00946 00947 SERVER_LOCK (server); 00948 watches = server->watches; 00949 server->watches = NULL; 00950 if (watches) 00951 { 00952 SERVER_UNLOCK (server); 00953 result = _dbus_watch_list_set_functions (watches, 00954 add_function, 00955 remove_function, 00956 toggled_function, 00957 data, 00958 free_data_function); 00959 SERVER_LOCK (server); 00960 } 00961 else 00962 { 00963 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 00964 result = FALSE; 00965 } 00966 server->watches = watches; 00967 SERVER_UNLOCK (server); 00968 00969 return result; 00970 } 00971 00987 dbus_bool_t 00988 dbus_server_set_timeout_functions (DBusServer *server, 00989 DBusAddTimeoutFunction add_function, 00990 DBusRemoveTimeoutFunction remove_function, 00991 DBusTimeoutToggledFunction toggled_function, 00992 void *data, 00993 DBusFreeFunction free_data_function) 00994 { 00995 dbus_bool_t result; 00996 DBusTimeoutList *timeouts; 00997 00998 _dbus_return_val_if_fail (server != NULL, FALSE); 00999 01000 SERVER_LOCK (server); 01001 timeouts = server->timeouts; 01002 server->timeouts = NULL; 01003 if (timeouts) 01004 { 01005 SERVER_UNLOCK (server); 01006 result = _dbus_timeout_list_set_functions (timeouts, 01007 add_function, 01008 remove_function, 01009 toggled_function, 01010 data, 01011 free_data_function); 01012 SERVER_LOCK (server); 01013 } 01014 else 01015 { 01016 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME); 01017 result = FALSE; 01018 } 01019 server->timeouts = timeouts; 01020 SERVER_UNLOCK (server); 01021 01022 return result; 01023 } 01024 01038 dbus_bool_t 01039 dbus_server_set_auth_mechanisms (DBusServer *server, 01040 const char **mechanisms) 01041 { 01042 char **copy; 01043 01044 _dbus_return_val_if_fail (server != NULL, FALSE); 01045 01046 SERVER_LOCK (server); 01047 01048 if (mechanisms != NULL) 01049 { 01050 copy = _dbus_dup_string_array (mechanisms); 01051 if (copy == NULL) 01052 return FALSE; 01053 } 01054 else 01055 copy = NULL; 01056 01057 dbus_free_string_array (server->auth_mechanisms); 01058 server->auth_mechanisms = copy; 01059 01060 SERVER_UNLOCK (server); 01061 01062 return TRUE; 01063 } 01064 01065 01066 static DBusDataSlotAllocator slot_allocator; 01067 _DBUS_DEFINE_GLOBAL_LOCK (server_slots); 01068 01083 dbus_bool_t 01084 dbus_server_allocate_data_slot (dbus_int32_t *slot_p) 01085 { 01086 return _dbus_data_slot_allocator_alloc (&slot_allocator, 01087 (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots), 01088 slot_p); 01089 } 01090 01102 void 01103 dbus_server_free_data_slot (dbus_int32_t *slot_p) 01104 { 01105 _dbus_return_if_fail (*slot_p >= 0); 01106 01107 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 01108 } 01109 01123 dbus_bool_t 01124 dbus_server_set_data (DBusServer *server, 01125 int slot, 01126 void *data, 01127 DBusFreeFunction free_data_func) 01128 { 01129 DBusFreeFunction old_free_func; 01130 void *old_data; 01131 dbus_bool_t retval; 01132 01133 _dbus_return_val_if_fail (server != NULL, FALSE); 01134 01135 SERVER_LOCK (server); 01136 01137 retval = _dbus_data_slot_list_set (&slot_allocator, 01138 &server->slot_list, 01139 slot, data, free_data_func, 01140 &old_free_func, &old_data); 01141 01142 01143 SERVER_UNLOCK (server); 01144 01145 if (retval) 01146 { 01147 /* Do the actual free outside the server lock */ 01148 if (old_free_func) 01149 (* old_free_func) (old_data); 01150 } 01151 01152 return retval; 01153 } 01154 01163 void* 01164 dbus_server_get_data (DBusServer *server, 01165 int slot) 01166 { 01167 void *res; 01168 01169 _dbus_return_val_if_fail (server != NULL, NULL); 01170 01171 SERVER_LOCK (server); 01172 01173 res = _dbus_data_slot_list_get (&slot_allocator, 01174 &server->slot_list, 01175 slot); 01176 01177 SERVER_UNLOCK (server); 01178 01179 return res; 01180 } 01181 01184 #ifdef DBUS_BUILD_TESTS 01185 #include "dbus-test.h" 01186 #include <string.h> 01187 01188 dbus_bool_t 01189 _dbus_server_test (void) 01190 { 01191 const char *valid_addresses[] = { 01192 "tcp:port=1234", 01193 "tcp:host=localhost,port=1234", 01194 "tcp:host=localhost,port=1234;tcp:port=5678", 01195 #ifdef DBUS_UNIX 01196 "unix:path=./boogie", 01197 "tcp:port=1234;unix:path=./boogie", 01198 #endif 01199 }; 01200 01201 DBusServer *server; 01202 int i; 01203 01204 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) 01205 { 01206 DBusError error = DBUS_ERROR_INIT; 01207 char *address; 01208 char *id; 01209 01210 server = dbus_server_listen (valid_addresses[i], &error); 01211 if (server == NULL) 01212 { 01213 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); 01214 dbus_error_free (&error); 01215 _dbus_assert_not_reached ("Failed to listen for valid address."); 01216 } 01217 01218 id = dbus_server_get_id (server); 01219 _dbus_assert (id != NULL); 01220 address = dbus_server_get_address (server); 01221 _dbus_assert (address != NULL); 01222 01223 if (strstr (address, id) == NULL) 01224 { 01225 _dbus_warn ("server id '%s' is not in the server address '%s'\n", 01226 id, address); 01227 _dbus_assert_not_reached ("bad server id or address"); 01228 } 01229 01230 dbus_free (id); 01231 dbus_free (address); 01232 01233 dbus_server_disconnect (server); 01234 dbus_server_unref (server); 01235 } 01236 01237 return TRUE; 01238 } 01239 01240 #endif /* DBUS_BUILD_TESTS */
1.7.6.1