00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00071
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;
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
00196
00197
00198 #ifndef DBUS_DISABLE_CHECKS
00199 _dbus_assert (!server->have_server_lock);
00200 #endif
00201 _dbus_assert (server->disconnected);
00202
00203
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
00246
00247
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
00323 void
00324 _dbus_server_toggle_watch (DBusServer *server,
00325 DBusWatch *watch,
00326 dbus_bool_t enabled)
00327 {
00328 _dbus_assert (watch != NULL);
00329
00330 HAVE_LOCK_CHECK (server);
00331 protected_change_watch (server, watch,
00332 NULL, NULL,
00333 _dbus_watch_list_toggle_watch,
00334 enabled);
00335 }
00336
00338 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00339 DBusTimeout *timeout);
00341 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00342 DBusTimeout *timeout);
00344 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00345 DBusTimeout *timeout,
00346 dbus_bool_t enabled);
00347
00348
00349 static dbus_bool_t
00350 protected_change_timeout (DBusServer *server,
00351 DBusTimeout *timeout,
00352 DBusTimeoutAddFunction add_function,
00353 DBusTimeoutRemoveFunction remove_function,
00354 DBusTimeoutToggleFunction toggle_function,
00355 dbus_bool_t enabled)
00356 {
00357 DBusTimeoutList *timeouts;
00358 dbus_bool_t retval;
00359
00360 HAVE_LOCK_CHECK (server);
00361
00362
00363
00364
00365
00366 timeouts = server->timeouts;
00367 if (timeouts)
00368 {
00369 server->timeouts = NULL;
00370 _dbus_server_ref_unlocked (server);
00371 SERVER_UNLOCK (server);
00372
00373 if (add_function)
00374 retval = (* add_function) (timeouts, timeout);
00375 else if (remove_function)
00376 {
00377 retval = TRUE;
00378 (* remove_function) (timeouts, timeout);
00379 }
00380 else
00381 {
00382 retval = TRUE;
00383 (* toggle_function) (timeouts, timeout, enabled);
00384 }
00385
00386 SERVER_LOCK (server);
00387 server->timeouts = timeouts;
00388 _dbus_server_unref_unlocked (server);
00389
00390 return retval;
00391 }
00392 else
00393 return FALSE;
00394 }
00395
00405 dbus_bool_t
00406 _dbus_server_add_timeout (DBusServer *server,
00407 DBusTimeout *timeout)
00408 {
00409 return protected_change_timeout (server, timeout,
00410 _dbus_timeout_list_add_timeout,
00411 NULL, NULL, FALSE);
00412 }
00413
00420 void
00421 _dbus_server_remove_timeout (DBusServer *server,
00422 DBusTimeout *timeout)
00423 {
00424 protected_change_timeout (server, timeout,
00425 NULL,
00426 _dbus_timeout_list_remove_timeout,
00427 NULL, FALSE);
00428 }
00429
00439 void
00440 _dbus_server_toggle_timeout (DBusServer *server,
00441 DBusTimeout *timeout,
00442 dbus_bool_t enabled)
00443 {
00444 protected_change_timeout (server, timeout,
00445 NULL, NULL,
00446 _dbus_timeout_list_toggle_timeout,
00447 enabled);
00448 }
00449
00450
00456 void
00457 _dbus_server_ref_unlocked (DBusServer *server)
00458 {
00459 dbus_int32_t old_refcount;
00460
00461 _dbus_assert (server != NULL);
00462 HAVE_LOCK_CHECK (server);
00463
00464 old_refcount = _dbus_atomic_inc (&server->refcount);
00465 _dbus_assert (old_refcount > 0);
00466 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1,
00467 "ref_unlocked");
00468 }
00469
00475 void
00476 _dbus_server_unref_unlocked (DBusServer *server)
00477 {
00478 dbus_int32_t old_refcount;
00479
00480
00481
00482 _dbus_assert (server != NULL);
00483
00484 HAVE_LOCK_CHECK (server);
00485
00486 old_refcount = _dbus_atomic_dec (&server->refcount);
00487 _dbus_assert (old_refcount > 0);
00488
00489 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1,
00490 "unref_unlocked");
00491
00492 if (old_refcount == 1)
00493 {
00494 _dbus_assert (server->disconnected);
00495
00496 SERVER_UNLOCK (server);
00497
00498 _dbus_assert (server->vtable->finalize != NULL);
00499
00500 (* server->vtable->finalize) (server);
00501 }
00502 }
00503
00525 static const struct {
00526 DBusServerListenResult (* func) (DBusAddressEntry *entry,
00527 DBusServer **server_p,
00528 DBusError *error);
00529 } listen_funcs[] = {
00530 { _dbus_server_listen_socket }
00531 , { _dbus_server_listen_platform_specific }
00532 #ifdef DBUS_BUILD_TESTS
00533 , { _dbus_server_listen_debug_pipe }
00534 #endif
00535 };
00536
00557 DBusServer*
00558 dbus_server_listen (const char *address,
00559 DBusError *error)
00560 {
00561 DBusServer *server;
00562 DBusAddressEntry **entries;
00563 int len, i;
00564 DBusError first_connect_error = DBUS_ERROR_INIT;
00565 dbus_bool_t handled_once;
00566
00567 _dbus_return_val_if_fail (address != NULL, NULL);
00568 _dbus_return_val_if_error_is_set (error, NULL);
00569
00570 if (!dbus_parse_address (address, &entries, &len, error))
00571 return NULL;
00572
00573 server = NULL;
00574 handled_once = FALSE;
00575
00576 for (i = 0; i < len; i++)
00577 {
00578 int j;
00579
00580 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
00581 {
00582 DBusServerListenResult result;
00583 DBusError tmp_error = DBUS_ERROR_INIT;
00584
00585 result = (* listen_funcs[j].func) (entries[i],
00586 &server,
00587 &tmp_error);
00588
00589 if (result == DBUS_SERVER_LISTEN_OK)
00590 {
00591 _dbus_assert (server != NULL);
00592 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00593 handled_once = TRUE;
00594 goto out;
00595 }
00596 else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
00597 {
00598 _dbus_assert (server == NULL);
00599 dbus_set_error (error,
00600 DBUS_ERROR_ADDRESS_IN_USE,
00601 "Address '%s' already used",
00602 dbus_address_entry_get_method (entries[0]));
00603 handled_once = TRUE;
00604 goto out;
00605 }
00606 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
00607 {
00608 _dbus_assert (server == NULL);
00609 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00610 dbus_move_error (&tmp_error, error);
00611 handled_once = TRUE;
00612 goto out;
00613 }
00614 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
00615 {
00616 _dbus_assert (server == NULL);
00617 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00618
00619
00620 }
00621 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
00622 {
00623 _dbus_assert (server == NULL);
00624 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00625 if (!dbus_error_is_set (&first_connect_error))
00626 dbus_move_error (&tmp_error, &first_connect_error);
00627 else
00628 dbus_error_free (&tmp_error);
00629
00630 handled_once = TRUE;
00631
00632
00633 }
00634 }
00635
00636 _dbus_assert (server == NULL);
00637 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00638 }
00639
00640 out:
00641
00642 if (!handled_once)
00643 {
00644 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00645 if (len > 0)
00646 dbus_set_error (error,
00647 DBUS_ERROR_BAD_ADDRESS,
00648 "Unknown address type '%s'",
00649 dbus_address_entry_get_method (entries[0]));
00650 else
00651 dbus_set_error (error,
00652 DBUS_ERROR_BAD_ADDRESS,
00653 "Empty address '%s'",
00654 address);
00655 }
00656
00657 dbus_address_entries_free (entries);
00658
00659 if (server == NULL)
00660 {
00661 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
00662 dbus_error_is_set (error));
00663
00664 if (error && dbus_error_is_set (error))
00665 {
00666
00667 }
00668 else
00669 {
00670
00671
00672
00673 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
00674 dbus_move_error (&first_connect_error, error);
00675 }
00676
00677 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error);
00678 _DBUS_ASSERT_ERROR_IS_SET (error);
00679
00680 return NULL;
00681 }
00682 else
00683 {
00684 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00685 return server;
00686 }
00687 }
00688
00695 DBusServer *
00696 dbus_server_ref (DBusServer *server)
00697 {
00698 dbus_int32_t old_refcount;
00699
00700 _dbus_return_val_if_fail (server != NULL, NULL);
00701
00702
00703 old_refcount = _dbus_atomic_inc (&server->refcount);
00704
00705 #ifndef DBUS_DISABLE_CHECKS
00706 if (_DBUS_UNLIKELY (old_refcount <= 0))
00707 {
00708
00709 _dbus_atomic_dec (&server->refcount);
00710 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
00711 _DBUS_FUNCTION_NAME, "old_refcount > 0",
00712 __FILE__, __LINE__);
00713 return NULL;
00714 }
00715 #endif
00716
00717 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref");
00718
00719 return server;
00720 }
00721
00730 void
00731 dbus_server_unref (DBusServer *server)
00732 {
00733 dbus_int32_t old_refcount;
00734
00735
00736
00737 _dbus_return_if_fail (server != NULL);
00738
00739
00740 old_refcount = _dbus_atomic_dec (&server->refcount);
00741
00742 #ifndef DBUS_DISABLE_CHECKS
00743 if (_DBUS_UNLIKELY (old_refcount <= 0))
00744 {
00745
00746 _dbus_atomic_inc (&server->refcount);
00747 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
00748 _DBUS_FUNCTION_NAME, "old_refcount > 0",
00749 __FILE__, __LINE__);
00750 return;
00751 }
00752 #endif
00753
00754 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref");
00755
00756 if (old_refcount == 1)
00757 {
00758
00759 _dbus_assert (server->disconnected);
00760
00761 _dbus_assert (server->vtable->finalize != NULL);
00762
00763 (* server->vtable->finalize) (server);
00764 }
00765 }
00766
00775 void
00776 dbus_server_disconnect (DBusServer *server)
00777 {
00778 _dbus_return_if_fail (server != NULL);
00779
00780 #ifdef DBUS_DISABLE_CHECKS
00781 _dbus_atomic_inc (&server->refcount);
00782 #else
00783 {
00784 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
00785
00786 _dbus_return_if_fail (old_refcount > 0);
00787 }
00788 #endif
00789
00790 SERVER_LOCK (server);
00791
00792 _dbus_assert (server->vtable->disconnect != NULL);
00793
00794 if (!server->disconnected)
00795 {
00796
00797 server->disconnected = TRUE;
00798
00799 (* server->vtable->disconnect) (server);
00800 }
00801
00802 SERVER_UNLOCK (server);
00803 dbus_server_unref (server);
00804 }
00805
00811 dbus_bool_t
00812 dbus_server_get_is_connected (DBusServer *server)
00813 {
00814 dbus_bool_t retval;
00815
00816 _dbus_return_val_if_fail (server != NULL, FALSE);
00817
00818 SERVER_LOCK (server);
00819 retval = !server->disconnected;
00820 SERVER_UNLOCK (server);
00821
00822 return retval;
00823 }
00824
00832 char*
00833 dbus_server_get_address (DBusServer *server)
00834 {
00835 char *retval;
00836
00837 _dbus_return_val_if_fail (server != NULL, NULL);
00838
00839 SERVER_LOCK (server);
00840 retval = _dbus_strdup (server->address);
00841 SERVER_UNLOCK (server);
00842
00843 return retval;
00844 }
00845
00868 char*
00869 dbus_server_get_id (DBusServer *server)
00870 {
00871 char *retval;
00872
00873 _dbus_return_val_if_fail (server != NULL, NULL);
00874
00875 SERVER_LOCK (server);
00876 retval = NULL;
00877 _dbus_string_copy_data (&server->guid_hex, &retval);
00878 SERVER_UNLOCK (server);
00879
00880 return retval;
00881 }
00882
00903 void
00904 dbus_server_set_new_connection_function (DBusServer *server,
00905 DBusNewConnectionFunction function,
00906 void *data,
00907 DBusFreeFunction free_data_function)
00908 {
00909 DBusFreeFunction old_free_function;
00910 void *old_data;
00911
00912 _dbus_return_if_fail (server != NULL);
00913
00914 SERVER_LOCK (server);
00915 old_free_function = server->new_connection_free_data_function;
00916 old_data = server->new_connection_data;
00917
00918 server->new_connection_function = function;
00919 server->new_connection_data = data;
00920 server->new_connection_free_data_function = free_data_function;
00921 SERVER_UNLOCK (server);
00922
00923 if (old_free_function != NULL)
00924 (* old_free_function) (old_data);
00925 }
00926
00943 dbus_bool_t
00944 dbus_server_set_watch_functions (DBusServer *server,
00945 DBusAddWatchFunction add_function,
00946 DBusRemoveWatchFunction remove_function,
00947 DBusWatchToggledFunction toggled_function,
00948 void *data,
00949 DBusFreeFunction free_data_function)
00950 {
00951 dbus_bool_t result;
00952 DBusWatchList *watches;
00953
00954 _dbus_return_val_if_fail (server != NULL, FALSE);
00955
00956 SERVER_LOCK (server);
00957 watches = server->watches;
00958 server->watches = NULL;
00959 if (watches)
00960 {
00961 SERVER_UNLOCK (server);
00962 result = _dbus_watch_list_set_functions (watches,
00963 add_function,
00964 remove_function,
00965 toggled_function,
00966 data,
00967 free_data_function);
00968 SERVER_LOCK (server);
00969 }
00970 else
00971 {
00972 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00973 result = FALSE;
00974 }
00975 server->watches = watches;
00976 SERVER_UNLOCK (server);
00977
00978 return result;
00979 }
00980
00996 dbus_bool_t
00997 dbus_server_set_timeout_functions (DBusServer *server,
00998 DBusAddTimeoutFunction add_function,
00999 DBusRemoveTimeoutFunction remove_function,
01000 DBusTimeoutToggledFunction toggled_function,
01001 void *data,
01002 DBusFreeFunction free_data_function)
01003 {
01004 dbus_bool_t result;
01005 DBusTimeoutList *timeouts;
01006
01007 _dbus_return_val_if_fail (server != NULL, FALSE);
01008
01009 SERVER_LOCK (server);
01010 timeouts = server->timeouts;
01011 server->timeouts = NULL;
01012 if (timeouts)
01013 {
01014 SERVER_UNLOCK (server);
01015 result = _dbus_timeout_list_set_functions (timeouts,
01016 add_function,
01017 remove_function,
01018 toggled_function,
01019 data,
01020 free_data_function);
01021 SERVER_LOCK (server);
01022 }
01023 else
01024 {
01025 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
01026 result = FALSE;
01027 }
01028 server->timeouts = timeouts;
01029 SERVER_UNLOCK (server);
01030
01031 return result;
01032 }
01033
01047 dbus_bool_t
01048 dbus_server_set_auth_mechanisms (DBusServer *server,
01049 const char **mechanisms)
01050 {
01051 char **copy;
01052
01053 _dbus_return_val_if_fail (server != NULL, FALSE);
01054
01055 SERVER_LOCK (server);
01056
01057 if (mechanisms != NULL)
01058 {
01059 copy = _dbus_dup_string_array (mechanisms);
01060 if (copy == NULL)
01061 return FALSE;
01062 }
01063 else
01064 copy = NULL;
01065
01066 dbus_free_string_array (server->auth_mechanisms);
01067 server->auth_mechanisms = copy;
01068
01069 SERVER_UNLOCK (server);
01070
01071 return TRUE;
01072 }
01073
01074
01075 static DBusDataSlotAllocator slot_allocator;
01076 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01077
01092 dbus_bool_t
01093 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01094 {
01095 return _dbus_data_slot_allocator_alloc (&slot_allocator,
01096 (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots),
01097 slot_p);
01098 }
01099
01111 void
01112 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01113 {
01114 _dbus_return_if_fail (*slot_p >= 0);
01115
01116 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01117 }
01118
01132 dbus_bool_t
01133 dbus_server_set_data (DBusServer *server,
01134 int slot,
01135 void *data,
01136 DBusFreeFunction free_data_func)
01137 {
01138 DBusFreeFunction old_free_func;
01139 void *old_data;
01140 dbus_bool_t retval;
01141
01142 _dbus_return_val_if_fail (server != NULL, FALSE);
01143
01144 SERVER_LOCK (server);
01145
01146 retval = _dbus_data_slot_list_set (&slot_allocator,
01147 &server->slot_list,
01148 slot, data, free_data_func,
01149 &old_free_func, &old_data);
01150
01151
01152 SERVER_UNLOCK (server);
01153
01154 if (retval)
01155 {
01156
01157 if (old_free_func)
01158 (* old_free_func) (old_data);
01159 }
01160
01161 return retval;
01162 }
01163
01172 void*
01173 dbus_server_get_data (DBusServer *server,
01174 int slot)
01175 {
01176 void *res;
01177
01178 _dbus_return_val_if_fail (server != NULL, NULL);
01179
01180 SERVER_LOCK (server);
01181
01182 res = _dbus_data_slot_list_get (&slot_allocator,
01183 &server->slot_list,
01184 slot);
01185
01186 SERVER_UNLOCK (server);
01187
01188 return res;
01189 }
01190
01193 #ifdef DBUS_BUILD_TESTS
01194 #include "dbus-test.h"
01195 #include <string.h>
01196
01197 dbus_bool_t
01198 _dbus_server_test (void)
01199 {
01200 const char *valid_addresses[] = {
01201 "tcp:port=1234",
01202 "tcp:host=localhost,port=1234",
01203 "tcp:host=localhost,port=1234;tcp:port=5678",
01204 #ifdef DBUS_UNIX
01205 "unix:path=./boogie",
01206 "tcp:port=1234;unix:path=./boogie",
01207 #endif
01208 };
01209
01210 DBusServer *server;
01211 int i;
01212
01213 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01214 {
01215 DBusError error = DBUS_ERROR_INIT;
01216 char *address;
01217 char *id;
01218
01219 server = dbus_server_listen (valid_addresses[i], &error);
01220 if (server == NULL)
01221 {
01222 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
01223 dbus_error_free (&error);
01224 _dbus_assert_not_reached ("Failed to listen for valid address.");
01225 }
01226
01227 id = dbus_server_get_id (server);
01228 _dbus_assert (id != NULL);
01229 address = dbus_server_get_address (server);
01230 _dbus_assert (address != NULL);
01231
01232 if (strstr (address, id) == NULL)
01233 {
01234 _dbus_warn ("server id '%s' is not in the server address '%s'\n",
01235 id, address);
01236 _dbus_assert_not_reached ("bad server id or address");
01237 }
01238
01239 dbus_free (id);
01240 dbus_free (address);
01241
01242 dbus_server_disconnect (server);
01243 dbus_server_unref (server);
01244 }
01245
01246 return TRUE;
01247 }
01248
01249 #endif