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_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
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
00111 dbus_bool_t
00112 _dbus_server_init_base (DBusServer *server,
00113 const DBusServerVTable *vtable,
00114 const DBusString *address,
00115 DBusError *error)
00116 {
00117 server->vtable = vtable;
00118
00119 #ifdef DBUS_DISABLE_ASSERT
00120 _dbus_atomic_inc (&server->refcount);
00121 #else
00122 {
00123 dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
00124
00125 _dbus_assert (old_refcount == 0);
00126 }
00127 #endif
00128
00129 server->address = NULL;
00130 server->watches = NULL;
00131 server->timeouts = NULL;
00132 server->published_address = FALSE;
00133
00134 if (!_dbus_string_init (&server->guid_hex))
00135 {
00136 _DBUS_SET_OOM (error);
00137 return FALSE;
00138 }
00139
00140 if (!_dbus_generate_uuid (&server->guid, error))
00141 goto failed;
00142
00143 if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
00144 goto oom;
00145
00146 server->address = copy_address_with_guid_appended (address,
00147 &server->guid_hex);
00148 if (server->address == NULL)
00149 goto oom;
00150
00151 _dbus_rmutex_new_at_location (&server->mutex);
00152 if (server->mutex == NULL)
00153 goto oom;
00154
00155 server->watches = _dbus_watch_list_new ();
00156 if (server->watches == NULL)
00157 goto oom;
00158
00159 server->timeouts = _dbus_timeout_list_new ();
00160 if (server->timeouts == NULL)
00161 goto oom;
00162
00163 _dbus_data_slot_list_init (&server->slot_list);
00164
00165 _dbus_verbose ("Initialized server on address %s\n", server->address);
00166
00167 return TRUE;
00168
00169 oom:
00170 _DBUS_SET_OOM (error);
00171 failed:
00172 _dbus_rmutex_free_at_location (&server->mutex);
00173 server->mutex = NULL;
00174 if (server->watches)
00175 {
00176 _dbus_watch_list_free (server->watches);
00177 server->watches = NULL;
00178 }
00179 if (server->timeouts)
00180 {
00181 _dbus_timeout_list_free (server->timeouts);
00182 server->timeouts = NULL;
00183 }
00184 if (server->address)
00185 {
00186 dbus_free (server->address);
00187 server->address = NULL;
00188 }
00189 _dbus_string_free (&server->guid_hex);
00190
00191 return FALSE;
00192 }
00193
00200 void
00201 _dbus_server_finalize_base (DBusServer *server)
00202 {
00203
00204
00205
00206 #ifndef DBUS_DISABLE_CHECKS
00207 _dbus_assert (!server->have_server_lock);
00208 #endif
00209 _dbus_assert (server->disconnected);
00210
00211
00212 _dbus_data_slot_list_free (&server->slot_list);
00213
00214 dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00215
00216 _dbus_watch_list_free (server->watches);
00217 _dbus_timeout_list_free (server->timeouts);
00218
00219 _dbus_rmutex_free_at_location (&server->mutex);
00220
00221 dbus_free (server->address);
00222
00223 dbus_free_string_array (server->auth_mechanisms);
00224
00225 _dbus_string_free (&server->guid_hex);
00226 }
00227
00228
00230 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00231 DBusWatch *watch);
00233 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00234 DBusWatch *watch);
00236 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00237 DBusWatch *watch,
00238 dbus_bool_t enabled);
00239
00240 static dbus_bool_t
00241 protected_change_watch (DBusServer *server,
00242 DBusWatch *watch,
00243 DBusWatchAddFunction add_function,
00244 DBusWatchRemoveFunction remove_function,
00245 DBusWatchToggleFunction toggle_function,
00246 dbus_bool_t enabled)
00247 {
00248 DBusWatchList *watches;
00249 dbus_bool_t retval;
00250
00251 HAVE_LOCK_CHECK (server);
00252
00253
00254
00255
00256
00257
00258 watches = server->watches;
00259 if (watches)
00260 {
00261 server->watches = NULL;
00262 _dbus_server_ref_unlocked (server);
00263 SERVER_UNLOCK (server);
00264
00265 if (add_function)
00266 retval = (* add_function) (watches, watch);
00267 else if (remove_function)
00268 {
00269 retval = TRUE;
00270 (* remove_function) (watches, watch);
00271 }
00272 else
00273 {
00274 retval = TRUE;
00275 (* toggle_function) (watches, watch, enabled);
00276 }
00277
00278 SERVER_LOCK (server);
00279 server->watches = watches;
00280 _dbus_server_unref_unlocked (server);
00281
00282 return retval;
00283 }
00284 else
00285 return FALSE;
00286 }
00287
00295 dbus_bool_t
00296 _dbus_server_add_watch (DBusServer *server,
00297 DBusWatch *watch)
00298 {
00299 HAVE_LOCK_CHECK (server);
00300 return protected_change_watch (server, watch,
00301 _dbus_watch_list_add_watch,
00302 NULL, NULL, FALSE);
00303 }
00304
00311 void
00312 _dbus_server_remove_watch (DBusServer *server,
00313 DBusWatch *watch)
00314 {
00315 HAVE_LOCK_CHECK (server);
00316 protected_change_watch (server, watch,
00317 NULL,
00318 _dbus_watch_list_remove_watch,
00319 NULL, FALSE);
00320 }
00321
00329 void
00330 _dbus_server_toggle_all_watches (DBusServer *server,
00331 dbus_bool_t enabled)
00332 {
00333 _dbus_watch_list_toggle_all_watches (server->watches, enabled);
00334 }
00335
00337 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00338 DBusTimeout *timeout);
00340 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00341 DBusTimeout *timeout);
00343 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00344 DBusTimeout *timeout,
00345 dbus_bool_t enabled);
00346
00347
00348 static dbus_bool_t
00349 protected_change_timeout (DBusServer *server,
00350 DBusTimeout *timeout,
00351 DBusTimeoutAddFunction add_function,
00352 DBusTimeoutRemoveFunction remove_function,
00353 DBusTimeoutToggleFunction toggle_function,
00354 dbus_bool_t enabled)
00355 {
00356 DBusTimeoutList *timeouts;
00357 dbus_bool_t retval;
00358
00359 HAVE_LOCK_CHECK (server);
00360
00361
00362
00363
00364
00365 timeouts = server->timeouts;
00366 if (timeouts)
00367 {
00368 server->timeouts = NULL;
00369 _dbus_server_ref_unlocked (server);
00370 SERVER_UNLOCK (server);
00371
00372 if (add_function)
00373 retval = (* add_function) (timeouts, timeout);
00374 else if (remove_function)
00375 {
00376 retval = TRUE;
00377 (* remove_function) (timeouts, timeout);
00378 }
00379 else
00380 {
00381 retval = TRUE;
00382 (* toggle_function) (timeouts, timeout, enabled);
00383 }
00384
00385 SERVER_LOCK (server);
00386 server->timeouts = timeouts;
00387 _dbus_server_unref_unlocked (server);
00388
00389 return retval;
00390 }
00391 else
00392 return FALSE;
00393 }
00394
00404 dbus_bool_t
00405 _dbus_server_add_timeout (DBusServer *server,
00406 DBusTimeout *timeout)
00407 {
00408 return protected_change_timeout (server, timeout,
00409 _dbus_timeout_list_add_timeout,
00410 NULL, NULL, FALSE);
00411 }
00412
00419 void
00420 _dbus_server_remove_timeout (DBusServer *server,
00421 DBusTimeout *timeout)
00422 {
00423 protected_change_timeout (server, timeout,
00424 NULL,
00425 _dbus_timeout_list_remove_timeout,
00426 NULL, FALSE);
00427 }
00428
00438 void
00439 _dbus_server_toggle_timeout (DBusServer *server,
00440 DBusTimeout *timeout,
00441 dbus_bool_t enabled)
00442 {
00443 protected_change_timeout (server, timeout,
00444 NULL, NULL,
00445 _dbus_timeout_list_toggle_timeout,
00446 enabled);
00447 }
00448
00449
00455 void
00456 _dbus_server_ref_unlocked (DBusServer *server)
00457 {
00458 dbus_int32_t old_refcount;
00459
00460 _dbus_assert (server != NULL);
00461 HAVE_LOCK_CHECK (server);
00462
00463 old_refcount = _dbus_atomic_inc (&server->refcount);
00464 _dbus_assert (old_refcount > 0);
00465 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1,
00466 "ref_unlocked");
00467 }
00468
00474 void
00475 _dbus_server_unref_unlocked (DBusServer *server)
00476 {
00477 dbus_int32_t old_refcount;
00478
00479
00480
00481 _dbus_assert (server != NULL);
00482
00483 HAVE_LOCK_CHECK (server);
00484
00485 old_refcount = _dbus_atomic_dec (&server->refcount);
00486 _dbus_assert (old_refcount > 0);
00487
00488 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1,
00489 "unref_unlocked");
00490
00491 if (old_refcount == 1)
00492 {
00493 _dbus_assert (server->disconnected);
00494
00495 SERVER_UNLOCK (server);
00496
00497 _dbus_assert (server->vtable->finalize != NULL);
00498
00499 (* server->vtable->finalize) (server);
00500 }
00501 }
00502
00524 static const struct {
00525 DBusServerListenResult (* func) (DBusAddressEntry *entry,
00526 DBusServer **server_p,
00527 DBusError *error);
00528 } listen_funcs[] = {
00529 { _dbus_server_listen_socket }
00530 , { _dbus_server_listen_platform_specific }
00531 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00532 , { _dbus_server_listen_debug_pipe }
00533 #endif
00534 };
00535
00556 DBusServer*
00557 dbus_server_listen (const char *address,
00558 DBusError *error)
00559 {
00560 DBusServer *server;
00561 DBusAddressEntry **entries;
00562 int len, i;
00563 DBusError first_connect_error = DBUS_ERROR_INIT;
00564 dbus_bool_t handled_once;
00565
00566 _dbus_return_val_if_fail (address != NULL, NULL);
00567 _dbus_return_val_if_error_is_set (error, NULL);
00568
00569 if (!dbus_parse_address (address, &entries, &len, error))
00570 return NULL;
00571
00572 server = NULL;
00573 handled_once = FALSE;
00574
00575 for (i = 0; i < len; i++)
00576 {
00577 int j;
00578
00579 for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
00580 {
00581 DBusServerListenResult result;
00582 DBusError tmp_error = DBUS_ERROR_INIT;
00583
00584 result = (* listen_funcs[j].func) (entries[i],
00585 &server,
00586 &tmp_error);
00587
00588 if (result == DBUS_SERVER_LISTEN_OK)
00589 {
00590 _dbus_assert (server != NULL);
00591 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00592 handled_once = TRUE;
00593 goto out;
00594 }
00595 else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
00596 {
00597 _dbus_assert (server == NULL);
00598 dbus_set_error (error,
00599 DBUS_ERROR_ADDRESS_IN_USE,
00600 "Address '%s' already used",
00601 dbus_address_entry_get_method (entries[0]));
00602 handled_once = TRUE;
00603 goto out;
00604 }
00605 else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
00606 {
00607 _dbus_assert (server == NULL);
00608 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00609 dbus_move_error (&tmp_error, error);
00610 handled_once = TRUE;
00611 goto out;
00612 }
00613 else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
00614 {
00615 _dbus_assert (server == NULL);
00616 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00617
00618
00619 }
00620 else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
00621 {
00622 _dbus_assert (server == NULL);
00623 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00624 if (!dbus_error_is_set (&first_connect_error))
00625 dbus_move_error (&tmp_error, &first_connect_error);
00626 else
00627 dbus_error_free (&tmp_error);
00628
00629 handled_once = TRUE;
00630
00631
00632 }
00633 }
00634
00635 _dbus_assert (server == NULL);
00636 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00637 }
00638
00639 out:
00640
00641 if (!handled_once)
00642 {
00643 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00644 if (len > 0)
00645 dbus_set_error (error,
00646 DBUS_ERROR_BAD_ADDRESS,
00647 "Unknown address type '%s'",
00648 dbus_address_entry_get_method (entries[0]));
00649 else
00650 dbus_set_error (error,
00651 DBUS_ERROR_BAD_ADDRESS,
00652 "Empty address '%s'",
00653 address);
00654 }
00655
00656 dbus_address_entries_free (entries);
00657
00658 if (server == NULL)
00659 {
00660 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
00661 dbus_error_is_set (error));
00662
00663 if (error && dbus_error_is_set (error))
00664 {
00665
00666 }
00667 else
00668 {
00669
00670
00671
00672 _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
00673 dbus_move_error (&first_connect_error, error);
00674 }
00675
00676 _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error);
00677 _DBUS_ASSERT_ERROR_IS_SET (error);
00678
00679 return NULL;
00680 }
00681 else
00682 {
00683 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00684 return server;
00685 }
00686 }
00687
00694 DBusServer *
00695 dbus_server_ref (DBusServer *server)
00696 {
00697 dbus_int32_t old_refcount;
00698
00699 _dbus_return_val_if_fail (server != NULL, NULL);
00700
00701 old_refcount = _dbus_atomic_inc (&server->refcount);
00702
00703 #ifndef DBUS_DISABLE_CHECKS
00704 if (_DBUS_UNLIKELY (old_refcount <= 0))
00705 {
00706 _dbus_atomic_dec (&server->refcount);
00707 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
00708 _DBUS_FUNCTION_NAME, "old_refcount > 0",
00709 __FILE__, __LINE__);
00710 return NULL;
00711 }
00712 #endif
00713
00714 _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref");
00715
00716 return server;
00717 }
00718
00727 void
00728 dbus_server_unref (DBusServer *server)
00729 {
00730 dbus_int32_t old_refcount;
00731
00732
00733
00734 _dbus_return_if_fail (server != NULL);
00735
00736 old_refcount = _dbus_atomic_dec (&server->refcount);
00737
00738 #ifndef DBUS_DISABLE_CHECKS
00739 if (_DBUS_UNLIKELY (old_refcount <= 0))
00740 {
00741
00742
00743
00744
00745
00746
00747
00748 _dbus_atomic_inc (&server->refcount);
00749 _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
00750 _DBUS_FUNCTION_NAME, "old_refcount > 0",
00751 __FILE__, __LINE__);
00752 return;
00753 }
00754 #endif
00755
00756 _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref");
00757
00758 if (old_refcount == 1)
00759 {
00760
00761 _dbus_assert (server->disconnected);
00762
00763 _dbus_assert (server->vtable->finalize != NULL);
00764
00765 (* server->vtable->finalize) (server);
00766 }
00767 }
00768
00777 void
00778 dbus_server_disconnect (DBusServer *server)
00779 {
00780 _dbus_return_if_fail (server != NULL);
00781
00782 dbus_server_ref (server);
00783 SERVER_LOCK (server);
00784
00785 _dbus_assert (server->vtable->disconnect != NULL);
00786
00787 if (!server->disconnected)
00788 {
00789
00790 server->disconnected = TRUE;
00791
00792 (* server->vtable->disconnect) (server);
00793 }
00794
00795 SERVER_UNLOCK (server);
00796 dbus_server_unref (server);
00797 }
00798
00804 dbus_bool_t
00805 dbus_server_get_is_connected (DBusServer *server)
00806 {
00807 dbus_bool_t retval;
00808
00809 _dbus_return_val_if_fail (server != NULL, FALSE);
00810
00811 SERVER_LOCK (server);
00812 retval = !server->disconnected;
00813 SERVER_UNLOCK (server);
00814
00815 return retval;
00816 }
00817
00825 char*
00826 dbus_server_get_address (DBusServer *server)
00827 {
00828 char *retval;
00829
00830 _dbus_return_val_if_fail (server != NULL, NULL);
00831
00832 SERVER_LOCK (server);
00833 retval = _dbus_strdup (server->address);
00834 SERVER_UNLOCK (server);
00835
00836 return retval;
00837 }
00838
00861 char*
00862 dbus_server_get_id (DBusServer *server)
00863 {
00864 char *retval;
00865
00866 _dbus_return_val_if_fail (server != NULL, NULL);
00867
00868 SERVER_LOCK (server);
00869 retval = NULL;
00870 _dbus_string_copy_data (&server->guid_hex, &retval);
00871 SERVER_UNLOCK (server);
00872
00873 return retval;
00874 }
00875
00896 void
00897 dbus_server_set_new_connection_function (DBusServer *server,
00898 DBusNewConnectionFunction function,
00899 void *data,
00900 DBusFreeFunction free_data_function)
00901 {
00902 DBusFreeFunction old_free_function;
00903 void *old_data;
00904
00905 _dbus_return_if_fail (server != NULL);
00906
00907 SERVER_LOCK (server);
00908 old_free_function = server->new_connection_free_data_function;
00909 old_data = server->new_connection_data;
00910
00911 server->new_connection_function = function;
00912 server->new_connection_data = data;
00913 server->new_connection_free_data_function = free_data_function;
00914 SERVER_UNLOCK (server);
00915
00916 if (old_free_function != NULL)
00917 (* old_free_function) (old_data);
00918 }
00919
00936 dbus_bool_t
00937 dbus_server_set_watch_functions (DBusServer *server,
00938 DBusAddWatchFunction add_function,
00939 DBusRemoveWatchFunction remove_function,
00940 DBusWatchToggledFunction toggled_function,
00941 void *data,
00942 DBusFreeFunction free_data_function)
00943 {
00944 dbus_bool_t result;
00945 DBusWatchList *watches;
00946
00947 _dbus_return_val_if_fail (server != NULL, FALSE);
00948
00949 SERVER_LOCK (server);
00950 watches = server->watches;
00951 server->watches = NULL;
00952 if (watches)
00953 {
00954 SERVER_UNLOCK (server);
00955 result = _dbus_watch_list_set_functions (watches,
00956 add_function,
00957 remove_function,
00958 toggled_function,
00959 data,
00960 free_data_function);
00961 SERVER_LOCK (server);
00962 }
00963 else
00964 {
00965 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00966 result = FALSE;
00967 }
00968 server->watches = watches;
00969 SERVER_UNLOCK (server);
00970
00971 return result;
00972 }
00973
00989 dbus_bool_t
00990 dbus_server_set_timeout_functions (DBusServer *server,
00991 DBusAddTimeoutFunction add_function,
00992 DBusRemoveTimeoutFunction remove_function,
00993 DBusTimeoutToggledFunction toggled_function,
00994 void *data,
00995 DBusFreeFunction free_data_function)
00996 {
00997 dbus_bool_t result;
00998 DBusTimeoutList *timeouts;
00999
01000 _dbus_return_val_if_fail (server != NULL, FALSE);
01001
01002 SERVER_LOCK (server);
01003 timeouts = server->timeouts;
01004 server->timeouts = NULL;
01005 if (timeouts)
01006 {
01007 SERVER_UNLOCK (server);
01008 result = _dbus_timeout_list_set_functions (timeouts,
01009 add_function,
01010 remove_function,
01011 toggled_function,
01012 data,
01013 free_data_function);
01014 SERVER_LOCK (server);
01015 }
01016 else
01017 {
01018 _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
01019 result = FALSE;
01020 }
01021 server->timeouts = timeouts;
01022 SERVER_UNLOCK (server);
01023
01024 return result;
01025 }
01026
01040 dbus_bool_t
01041 dbus_server_set_auth_mechanisms (DBusServer *server,
01042 const char **mechanisms)
01043 {
01044 char **copy;
01045
01046 _dbus_return_val_if_fail (server != NULL, FALSE);
01047
01048 SERVER_LOCK (server);
01049
01050 if (mechanisms != NULL)
01051 {
01052 copy = _dbus_dup_string_array (mechanisms);
01053 if (copy == NULL)
01054 {
01055 SERVER_UNLOCK (server);
01056 return FALSE;
01057 }
01058 }
01059 else
01060 copy = NULL;
01061
01062 dbus_free_string_array (server->auth_mechanisms);
01063 server->auth_mechanisms = copy;
01064
01065 SERVER_UNLOCK (server);
01066
01067 return TRUE;
01068 }
01069
01070 static DBusDataSlotAllocator slot_allocator =
01071 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (server_slots));
01072
01087 dbus_bool_t
01088 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01089 {
01090 return _dbus_data_slot_allocator_alloc (&slot_allocator,
01091 slot_p);
01092 }
01093
01105 void
01106 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01107 {
01108 _dbus_return_if_fail (*slot_p >= 0);
01109
01110 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01111 }
01112
01126 dbus_bool_t
01127 dbus_server_set_data (DBusServer *server,
01128 int slot,
01129 void *data,
01130 DBusFreeFunction free_data_func)
01131 {
01132 DBusFreeFunction old_free_func;
01133 void *old_data;
01134 dbus_bool_t retval;
01135
01136 _dbus_return_val_if_fail (server != NULL, FALSE);
01137
01138 SERVER_LOCK (server);
01139
01140 retval = _dbus_data_slot_list_set (&slot_allocator,
01141 &server->slot_list,
01142 slot, data, free_data_func,
01143 &old_free_func, &old_data);
01144
01145
01146 SERVER_UNLOCK (server);
01147
01148 if (retval)
01149 {
01150
01151 if (old_free_func)
01152 (* old_free_func) (old_data);
01153 }
01154
01155 return retval;
01156 }
01157
01166 void*
01167 dbus_server_get_data (DBusServer *server,
01168 int slot)
01169 {
01170 void *res;
01171
01172 _dbus_return_val_if_fail (server != NULL, NULL);
01173
01174 SERVER_LOCK (server);
01175
01176 res = _dbus_data_slot_list_get (&slot_allocator,
01177 &server->slot_list,
01178 slot);
01179
01180 SERVER_UNLOCK (server);
01181
01182 return res;
01183 }
01184
01187 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01188 #include "dbus-test.h"
01189 #include <string.h>
01190
01191 dbus_bool_t
01192 _dbus_server_test (void)
01193 {
01194 const char *valid_addresses[] = {
01195 "tcp:port=1234",
01196 "tcp:host=localhost,port=1234",
01197 "tcp:host=localhost,port=1234;tcp:port=5678",
01198 #ifdef DBUS_UNIX
01199 "unix:path=./boogie",
01200 "tcp:port=1234;unix:path=./boogie",
01201 #endif
01202 };
01203
01204 DBusServer *server;
01205 int i;
01206
01207 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01208 {
01209 DBusError error = DBUS_ERROR_INIT;
01210 char *address;
01211 char *id;
01212
01213 server = dbus_server_listen (valid_addresses[i], &error);
01214 if (server == NULL)
01215 {
01216 _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
01217 dbus_error_free (&error);
01218 _dbus_assert_not_reached ("Failed to listen for valid address.");
01219 }
01220
01221 id = dbus_server_get_id (server);
01222 _dbus_assert (id != NULL);
01223 address = dbus_server_get_address (server);
01224 _dbus_assert (address != NULL);
01225
01226 if (strstr (address, id) == NULL)
01227 {
01228 _dbus_warn ("server id '%s' is not in the server address '%s'\n",
01229 id, address);
01230 _dbus_assert_not_reached ("bad server id or address");
01231 }
01232
01233 dbus_free (id);
01234 dbus_free (address);
01235
01236 dbus_server_disconnect (server);
01237 dbus_server_unref (server);
01238 }
01239
01240 return TRUE;
01241 }
01242
01243 #endif