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 "dbus-server.h"
00025 #include "dbus-server-unix.h"
00026 #include "dbus-string.h"
00027 #ifdef DBUS_BUILD_TESTS
00028 #include "dbus-server-debug-pipe.h"
00029 #endif
00030 #include "dbus-address.h"
00031 #include "dbus-protocol.h"
00032
00055 static void
00056 init_guid (DBusGUID *guid)
00057 {
00058 long now;
00059 char *p;
00060 int ts_size;
00061
00062 _dbus_get_current_time (&now, NULL);
00063
00064 guid->as_uint32s[0] = now;
00065
00066 ts_size = sizeof (guid->as_uint32s[0]);
00067 p = ((char*)guid->as_bytes) + ts_size;
00068
00069 _dbus_generate_random_bytes_buffer (p,
00070 sizeof (guid->as_bytes) - ts_size);
00071 }
00072
00073
00074
00075
00076 static char*
00077 copy_address_with_guid_appended (const DBusString *address,
00078 const DBusString *guid_hex)
00079 {
00080 DBusString with_guid;
00081 char *retval;
00082
00083 if (!_dbus_string_init (&with_guid))
00084 return NULL;
00085
00086 if (!_dbus_string_copy (address, 0, &with_guid,
00087 _dbus_string_get_length (&with_guid)) ||
00088 !_dbus_string_append (&with_guid, ",guid=") ||
00089 !_dbus_string_copy (guid_hex, 0,
00090 &with_guid, _dbus_string_get_length (&with_guid)))
00091 {
00092 _dbus_string_free (&with_guid);
00093 return NULL;
00094 }
00095
00096 retval = NULL;
00097 _dbus_string_steal_data (&with_guid, &retval);
00098
00099 _dbus_string_free (&with_guid);
00100
00101 return retval;
00102 }
00103
00113 dbus_bool_t
00114 _dbus_server_init_base (DBusServer *server,
00115 const DBusServerVTable *vtable,
00116 const DBusString *address)
00117 {
00118 DBusString guid_raw;
00119
00120 server->vtable = vtable;
00121 server->refcount.value = 1;
00122
00123 server->address = NULL;
00124 server->watches = NULL;
00125 server->timeouts = NULL;
00126
00127 if (!_dbus_string_init (&server->guid_hex))
00128 return FALSE;
00129
00130 init_guid (&server->guid);
00131
00132 _dbus_string_init_const_len (&guid_raw, (signed char*) server->guid.as_bytes,
00133 sizeof (server->guid.as_bytes));
00134 if (!_dbus_string_hex_encode (&guid_raw, 0,
00135 &server->guid_hex,
00136 _dbus_string_get_length (&server->guid_hex)))
00137 goto failed;
00138
00139 server->address = copy_address_with_guid_appended (address,
00140 &server->guid_hex);
00141 if (server->address == NULL)
00142 goto failed;
00143
00144 server->mutex = _dbus_mutex_new ();
00145 if (server->mutex == NULL)
00146 goto failed;
00147
00148 server->watches = _dbus_watch_list_new ();
00149 if (server->watches == NULL)
00150 goto failed;
00151
00152 server->timeouts = _dbus_timeout_list_new ();
00153 if (server->timeouts == NULL)
00154 goto failed;
00155
00156 _dbus_data_slot_list_init (&server->slot_list);
00157
00158 _dbus_verbose ("Initialized server on address %s\n", server->address);
00159
00160 return TRUE;
00161
00162 failed:
00163 if (server->mutex)
00164 {
00165 _dbus_mutex_free (server->mutex);
00166 server->mutex = NULL;
00167 }
00168 if (server->watches)
00169 {
00170 _dbus_watch_list_free (server->watches);
00171 server->watches = NULL;
00172 }
00173 if (server->timeouts)
00174 {
00175 _dbus_timeout_list_free (server->timeouts);
00176 server->timeouts = NULL;
00177 }
00178 if (server->address)
00179 {
00180 dbus_free (server->address);
00181 server->address = NULL;
00182 }
00183 _dbus_string_free (&server->guid_hex);
00184
00185 return FALSE;
00186 }
00187
00194 void
00195 _dbus_server_finalize_base (DBusServer *server)
00196 {
00197
00198
00199
00200 #ifndef DBUS_DISABLE_CHECKS
00201 _dbus_assert (!server->have_server_lock);
00202 #endif
00203 _dbus_assert (server->disconnected);
00204
00205
00206 _dbus_data_slot_list_free (&server->slot_list);
00207
00208 dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00209
00210 _dbus_watch_list_free (server->watches);
00211 _dbus_timeout_list_free (server->timeouts);
00212
00213 _dbus_mutex_free (server->mutex);
00214
00215 dbus_free (server->address);
00216
00217 dbus_free_string_array (server->auth_mechanisms);
00218
00219 _dbus_string_free (&server->guid_hex);
00220 }
00221
00222
00223 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00224 DBusWatch *watch);
00225 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00226 DBusWatch *watch);
00227 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00228 DBusWatch *watch,
00229 dbus_bool_t enabled);
00230
00231 static dbus_bool_t
00232 protected_change_watch (DBusServer *server,
00233 DBusWatch *watch,
00234 DBusWatchAddFunction add_function,
00235 DBusWatchRemoveFunction remove_function,
00236 DBusWatchToggleFunction toggle_function,
00237 dbus_bool_t enabled)
00238 {
00239 DBusWatchList *watches;
00240 dbus_bool_t retval;
00241
00242 HAVE_LOCK_CHECK (server);
00243
00244
00245
00246
00247
00248
00249 watches = server->watches;
00250 if (watches)
00251 {
00252 server->watches = NULL;
00253 _dbus_server_ref_unlocked (server);
00254 SERVER_UNLOCK (server);
00255
00256 if (add_function)
00257 retval = (* add_function) (watches, watch);
00258 else if (remove_function)
00259 {
00260 retval = TRUE;
00261 (* remove_function) (watches, watch);
00262 }
00263 else
00264 {
00265 retval = TRUE;
00266 (* toggle_function) (watches, watch, enabled);
00267 }
00268
00269 SERVER_LOCK (server);
00270 server->watches = watches;
00271 _dbus_server_unref_unlocked (server);
00272
00273 return retval;
00274 }
00275 else
00276 return FALSE;
00277 }
00278
00286 dbus_bool_t
00287 _dbus_server_add_watch (DBusServer *server,
00288 DBusWatch *watch)
00289 {
00290 HAVE_LOCK_CHECK (server);
00291 return protected_change_watch (server, watch,
00292 _dbus_watch_list_add_watch,
00293 NULL, NULL, FALSE);
00294 }
00295
00302 void
00303 _dbus_server_remove_watch (DBusServer *server,
00304 DBusWatch *watch)
00305 {
00306 HAVE_LOCK_CHECK (server);
00307 protected_change_watch (server, watch,
00308 NULL,
00309 _dbus_watch_list_remove_watch,
00310 NULL, FALSE);
00311 }
00312
00322 void
00323 _dbus_server_toggle_watch (DBusServer *server,
00324 DBusWatch *watch,
00325 dbus_bool_t enabled)
00326 {
00327 _dbus_assert (watch != NULL);
00328
00329 HAVE_LOCK_CHECK (server);
00330 protected_change_watch (server, watch,
00331 NULL, NULL,
00332 _dbus_watch_list_toggle_watch,
00333 enabled);
00334 }
00335
00336
00337 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00338 DBusTimeout *timeout);
00339 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00340 DBusTimeout *timeout);
00341 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00342 DBusTimeout *timeout,
00343 dbus_bool_t enabled);
00344
00345
00346 static dbus_bool_t
00347 protected_change_timeout (DBusServer *server,
00348 DBusTimeout *timeout,
00349 DBusTimeoutAddFunction add_function,
00350 DBusTimeoutRemoveFunction remove_function,
00351 DBusTimeoutToggleFunction toggle_function,
00352 dbus_bool_t enabled)
00353 {
00354 DBusTimeoutList *timeouts;
00355 dbus_bool_t retval;
00356
00357 HAVE_LOCK_CHECK (server);
00358
00359
00360
00361
00362
00363 timeouts = server->timeouts;
00364 if (timeouts)
00365 {
00366 server->timeouts = NULL;
00367 _dbus_server_ref_unlocked (server);
00368 SERVER_UNLOCK (server);
00369
00370 if (add_function)
00371 retval = (* add_function) (timeouts, timeout);
00372 else if (remove_function)
00373 {
00374 retval = TRUE;
00375 (* remove_function) (timeouts, timeout);
00376 }
00377 else
00378 {
00379 retval = TRUE;
00380 (* toggle_function) (timeouts, timeout, enabled);
00381 }
00382
00383 SERVER_LOCK (server);
00384 server->timeouts = timeouts;
00385 _dbus_server_unref_unlocked (server);
00386
00387 return retval;
00388 }
00389 else
00390 return FALSE;
00391 }
00392
00402 dbus_bool_t
00403 _dbus_server_add_timeout (DBusServer *server,
00404 DBusTimeout *timeout)
00405 {
00406 return protected_change_timeout (server, timeout,
00407 _dbus_timeout_list_add_timeout,
00408 NULL, NULL, FALSE);
00409 }
00410
00417 void
00418 _dbus_server_remove_timeout (DBusServer *server,
00419 DBusTimeout *timeout)
00420 {
00421 protected_change_timeout (server, timeout,
00422 NULL,
00423 _dbus_timeout_list_remove_timeout,
00424 NULL, FALSE);
00425 }
00426
00436 void
00437 _dbus_server_toggle_timeout (DBusServer *server,
00438 DBusTimeout *timeout,
00439 dbus_bool_t enabled)
00440 {
00441 protected_change_timeout (server, timeout,
00442 NULL, NULL,
00443 _dbus_timeout_list_toggle_timeout,
00444 enabled);
00445 }
00446
00447
00485 DBusServer*
00486 dbus_server_listen (const char *address,
00487 DBusError *error)
00488 {
00489 DBusServer *server;
00490 DBusAddressEntry **entries;
00491 int len, i;
00492 const char *address_problem_type;
00493 const char *address_problem_field;
00494 const char *address_problem_other;
00495
00496 _dbus_return_val_if_fail (address != NULL, NULL);
00497 _dbus_return_val_if_error_is_set (error, NULL);
00498
00499 if (!dbus_parse_address (address, &entries, &len, error))
00500 return NULL;
00501
00502 server = NULL;
00503 address_problem_type = NULL;
00504 address_problem_field = NULL;
00505 address_problem_other = NULL;
00506
00507 for (i = 0; i < len; i++)
00508 {
00509 const char *method;
00510
00511 method = dbus_address_entry_get_method (entries[i]);
00512
00513 if (strcmp (method, "unix") == 0)
00514 {
00515 const char *path = dbus_address_entry_get_value (entries[i], "path");
00516 const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
00517 const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
00518
00519 if (path == NULL && tmpdir == NULL && abstract == NULL)
00520 {
00521 address_problem_type = "unix";
00522 address_problem_field = "path or tmpdir or abstract";
00523 goto bad_address;
00524 }
00525
00526 if ((path && tmpdir) ||
00527 (path && abstract) ||
00528 (tmpdir && abstract))
00529 {
00530 address_problem_other = "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time";
00531 goto bad_address;
00532 }
00533
00534 if (tmpdir != NULL)
00535 {
00536 DBusString full_path;
00537 DBusString filename;
00538
00539 if (!_dbus_string_init (&full_path))
00540 {
00541 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00542 goto out;
00543 }
00544
00545 if (!_dbus_string_init (&filename))
00546 {
00547 _dbus_string_free (&full_path);
00548 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00549 goto out;
00550 }
00551
00552 if (!_dbus_string_append (&filename,
00553 "dbus-") ||
00554 !_dbus_generate_random_ascii (&filename, 10) ||
00555 !_dbus_string_append (&full_path, tmpdir) ||
00556 !_dbus_concat_dir_and_file (&full_path, &filename))
00557 {
00558 _dbus_string_free (&full_path);
00559 _dbus_string_free (&filename);
00560 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00561 goto out;
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 server =
00574 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
00575 #ifdef HAVE_ABSTRACT_SOCKETS
00576 TRUE,
00577 #else
00578 FALSE,
00579 #endif
00580 error);
00581
00582 _dbus_string_free (&full_path);
00583 _dbus_string_free (&filename);
00584 }
00585 else
00586 {
00587 if (path)
00588 server = _dbus_server_new_for_domain_socket (path, FALSE, error);
00589 else
00590 server = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
00591 }
00592 }
00593 else if (strcmp (method, "tcp") == 0)
00594 {
00595 const char *host = dbus_address_entry_get_value (entries[i], "host");
00596 const char *port = dbus_address_entry_get_value (entries[i], "port");
00597 DBusString str;
00598 long lport;
00599 dbus_bool_t sresult;
00600
00601 if (port == NULL)
00602 {
00603 address_problem_type = "tcp";
00604 address_problem_field = "port";
00605 goto bad_address;
00606 }
00607
00608 _dbus_string_init_const (&str, port);
00609 sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
00610 _dbus_string_free (&str);
00611
00612 if (sresult == FALSE || lport <= 0 || lport > 65535)
00613 {
00614 address_problem_other = "Port is not an integer between 0 and 65535";
00615 goto bad_address;
00616 }
00617
00618 server = _dbus_server_new_for_tcp_socket (host, lport, error);
00619
00620 if (server)
00621 break;
00622 }
00623 #ifdef DBUS_BUILD_TESTS
00624 else if (strcmp (method, "debug-pipe") == 0)
00625 {
00626 const char *name = dbus_address_entry_get_value (entries[i], "name");
00627
00628 if (name == NULL)
00629 {
00630 address_problem_type = "debug-pipe";
00631 address_problem_field = "name";
00632 goto bad_address;
00633 }
00634
00635 server = _dbus_server_debug_pipe_new (name, error);
00636 }
00637 #endif
00638 else
00639 {
00640 address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
00641 goto bad_address;
00642 }
00643
00644 if (server)
00645 break;
00646 }
00647
00648 out:
00649
00650 dbus_address_entries_free (entries);
00651 return server;
00652
00653 bad_address:
00654 dbus_address_entries_free (entries);
00655 if (address_problem_type != NULL)
00656 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00657 "Server address of type %s was missing argument %s",
00658 address_problem_type, address_problem_field);
00659 else
00660 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00661 "Could not parse server address: %s",
00662 address_problem_other);
00663
00664 return NULL;
00665 }
00666
00673 DBusServer *
00674 dbus_server_ref (DBusServer *server)
00675 {
00676 _dbus_return_val_if_fail (server != NULL, NULL);
00677 _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
00678
00679 #ifdef DBUS_HAVE_ATOMIC_INT
00680 _dbus_atomic_inc (&server->refcount);
00681 #else
00682 SERVER_LOCK (server);
00683 _dbus_assert (server->refcount.value > 0);
00684
00685 server->refcount.value += 1;
00686 SERVER_UNLOCK (server);
00687 #endif
00688
00689 return server;
00690 }
00691
00700 void
00701 dbus_server_unref (DBusServer *server)
00702 {
00703 dbus_bool_t last_unref;
00704
00705 _dbus_return_if_fail (server != NULL);
00706 _dbus_return_if_fail (server->refcount.value > 0);
00707
00708 #ifdef DBUS_HAVE_ATOMIC_INT
00709 last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00710 #else
00711 SERVER_LOCK (server);
00712
00713 _dbus_assert (server->refcount.value > 0);
00714
00715 server->refcount.value -= 1;
00716 last_unref = (server->refcount.value == 0);
00717
00718 SERVER_UNLOCK (server);
00719 #endif
00720
00721 if (last_unref)
00722 {
00723
00724 _dbus_assert (server->disconnected);
00725
00726 _dbus_assert (server->vtable->finalize != NULL);
00727
00728 (* server->vtable->finalize) (server);
00729 }
00730 }
00731
00737 void
00738 _dbus_server_ref_unlocked (DBusServer *server)
00739 {
00740 _dbus_assert (server != NULL);
00741 _dbus_assert (server->refcount.value > 0);
00742
00743 HAVE_LOCK_CHECK (server);
00744
00745 #ifdef DBUS_HAVE_ATOMIC_INT
00746 _dbus_atomic_inc (&server->refcount);
00747 #else
00748 _dbus_assert (server->refcount.value > 0);
00749
00750 server->refcount.value += 1;
00751 #endif
00752 }
00753
00759 void
00760 _dbus_server_unref_unlocked (DBusServer *server)
00761 {
00762 dbus_bool_t last_unref;
00763
00764 _dbus_assert (server != NULL);
00765 _dbus_assert (server->refcount.value > 0);
00766
00767 HAVE_LOCK_CHECK (server);
00768
00769 #ifdef DBUS_HAVE_ATOMIC_INT
00770 last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00771 #else
00772 _dbus_assert (server->refcount.value > 0);
00773
00774 server->refcount.value -= 1;
00775 last_unref = (server->refcount.value == 0);
00776 #endif
00777
00778 if (last_unref)
00779 {
00780 _dbus_assert (server->disconnected);
00781
00782 SERVER_UNLOCK (server);
00783
00784 _dbus_assert (server->vtable->finalize != NULL);
00785
00786 (* server->vtable->finalize) (server);
00787 }
00788 }
00789
00798 void
00799 dbus_server_disconnect (DBusServer *server)
00800 {
00801 _dbus_return_if_fail (server != NULL);
00802 _dbus_return_if_fail (server->refcount.value > 0);
00803
00804 SERVER_LOCK (server);
00805 _dbus_server_ref_unlocked (server);
00806
00807 _dbus_assert (server->vtable->disconnect != NULL);
00808
00809 if (!server->disconnected)
00810 {
00811
00812 server->disconnected = TRUE;
00813
00814 (* server->vtable->disconnect) (server);
00815 }
00816
00817 SERVER_UNLOCK (server);
00818 dbus_server_unref (server);
00819 }
00820
00826 dbus_bool_t
00827 dbus_server_get_is_connected (DBusServer *server)
00828 {
00829 dbus_bool_t retval;
00830
00831 _dbus_return_val_if_fail (server != NULL, FALSE);
00832
00833 SERVER_LOCK (server);
00834 retval = !server->disconnected;
00835 SERVER_UNLOCK (server);
00836
00837 return retval;
00838 }
00839
00847 char*
00848 dbus_server_get_address (DBusServer *server)
00849 {
00850 char *retval;
00851
00852 _dbus_return_val_if_fail (server != NULL, NULL);
00853
00854 SERVER_LOCK (server);
00855 retval = _dbus_strdup (server->address);
00856 SERVER_UNLOCK (server);
00857
00858 return retval;
00859 }
00860
00873 void
00874 dbus_server_set_new_connection_function (DBusServer *server,
00875 DBusNewConnectionFunction function,
00876 void *data,
00877 DBusFreeFunction free_data_function)
00878 {
00879 DBusFreeFunction old_free_function;
00880 void *old_data;
00881
00882 _dbus_return_if_fail (server != NULL);
00883
00884 SERVER_LOCK (server);
00885 old_free_function = server->new_connection_free_data_function;
00886 old_data = server->new_connection_data;
00887
00888 server->new_connection_function = function;
00889 server->new_connection_data = data;
00890 server->new_connection_free_data_function = free_data_function;
00891 SERVER_UNLOCK (server);
00892
00893 if (old_free_function != NULL)
00894 (* old_free_function) (old_data);
00895 }
00896
00913 dbus_bool_t
00914 dbus_server_set_watch_functions (DBusServer *server,
00915 DBusAddWatchFunction add_function,
00916 DBusRemoveWatchFunction remove_function,
00917 DBusWatchToggledFunction toggled_function,
00918 void *data,
00919 DBusFreeFunction free_data_function)
00920 {
00921 dbus_bool_t result;
00922 DBusWatchList *watches;
00923
00924 _dbus_return_val_if_fail (server != NULL, FALSE);
00925
00926 SERVER_LOCK (server);
00927 watches = server->watches;
00928 server->watches = NULL;
00929 if (watches)
00930 {
00931 SERVER_UNLOCK (server);
00932 result = _dbus_watch_list_set_functions (watches,
00933 add_function,
00934 remove_function,
00935 toggled_function,
00936 data,
00937 free_data_function);
00938 SERVER_LOCK (server);
00939 }
00940 else
00941 {
00942 _dbus_warn ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00943 result = FALSE;
00944 }
00945 server->watches = watches;
00946 SERVER_UNLOCK (server);
00947
00948 return result;
00949 }
00950
00966 dbus_bool_t
00967 dbus_server_set_timeout_functions (DBusServer *server,
00968 DBusAddTimeoutFunction add_function,
00969 DBusRemoveTimeoutFunction remove_function,
00970 DBusTimeoutToggledFunction toggled_function,
00971 void *data,
00972 DBusFreeFunction free_data_function)
00973 {
00974 dbus_bool_t result;
00975 DBusTimeoutList *timeouts;
00976
00977 _dbus_return_val_if_fail (server != NULL, FALSE);
00978
00979 SERVER_LOCK (server);
00980 timeouts = server->timeouts;
00981 server->timeouts = NULL;
00982 if (timeouts)
00983 {
00984 SERVER_UNLOCK (server);
00985 result = _dbus_timeout_list_set_functions (timeouts,
00986 add_function,
00987 remove_function,
00988 toggled_function,
00989 data,
00990 free_data_function);
00991 SERVER_LOCK (server);
00992 }
00993 else
00994 {
00995 _dbus_warn ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00996 result = FALSE;
00997 }
00998 server->timeouts = timeouts;
00999 SERVER_UNLOCK (server);
01000
01001 return result;
01002 }
01003
01014 dbus_bool_t
01015 dbus_server_set_auth_mechanisms (DBusServer *server,
01016 const char **mechanisms)
01017 {
01018 char **copy;
01019
01020 _dbus_return_val_if_fail (server != NULL, FALSE);
01021
01022 SERVER_LOCK (server);
01023
01024 if (mechanisms != NULL)
01025 {
01026 copy = _dbus_dup_string_array (mechanisms);
01027 if (copy == NULL)
01028 return FALSE;
01029 }
01030 else
01031 copy = NULL;
01032
01033 dbus_free_string_array (server->auth_mechanisms);
01034 server->auth_mechanisms = copy;
01035
01036 SERVER_UNLOCK (server);
01037
01038 return TRUE;
01039 }
01040
01041
01042 static DBusDataSlotAllocator slot_allocator;
01043 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01044
01059 dbus_bool_t
01060 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01061 {
01062 return _dbus_data_slot_allocator_alloc (&slot_allocator,
01063 _DBUS_LOCK_NAME (server_slots),
01064 slot_p);
01065 }
01066
01078 void
01079 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01080 {
01081 _dbus_return_if_fail (*slot_p >= 0);
01082
01083 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01084 }
01085
01099 dbus_bool_t
01100 dbus_server_set_data (DBusServer *server,
01101 int slot,
01102 void *data,
01103 DBusFreeFunction free_data_func)
01104 {
01105 DBusFreeFunction old_free_func;
01106 void *old_data;
01107 dbus_bool_t retval;
01108
01109 _dbus_return_val_if_fail (server != NULL, FALSE);
01110
01111 SERVER_LOCK (server);
01112
01113 retval = _dbus_data_slot_list_set (&slot_allocator,
01114 &server->slot_list,
01115 slot, data, free_data_func,
01116 &old_free_func, &old_data);
01117
01118
01119 SERVER_UNLOCK (server);
01120
01121 if (retval)
01122 {
01123
01124 if (old_free_func)
01125 (* old_free_func) (old_data);
01126 }
01127
01128 return retval;
01129 }
01130
01139 void*
01140 dbus_server_get_data (DBusServer *server,
01141 int slot)
01142 {
01143 void *res;
01144
01145 _dbus_return_val_if_fail (server != NULL, NULL);
01146
01147 SERVER_LOCK (server);
01148
01149 res = _dbus_data_slot_list_get (&slot_allocator,
01150 &server->slot_list,
01151 slot);
01152
01153 SERVER_UNLOCK (server);
01154
01155 return res;
01156 }
01157
01160 #ifdef DBUS_BUILD_TESTS
01161 #include "dbus-test.h"
01162
01163 dbus_bool_t
01164 _dbus_server_test (void)
01165 {
01166 const char *valid_addresses[] = {
01167 "tcp:port=1234",
01168 "unix:path=./boogie",
01169 "tcp:host=localhost,port=1234",
01170 "tcp:host=localhost,port=1234;tcp:port=5678",
01171 "tcp:port=1234;unix:path=./boogie",
01172 };
01173
01174 DBusServer *server;
01175 int i;
01176
01177 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01178 {
01179 server = dbus_server_listen (valid_addresses[i], NULL);
01180 if (server == NULL)
01181 _dbus_assert_not_reached ("Failed to listen for valid address.");
01182
01183 dbus_server_disconnect (server);
01184 dbus_server_unref (server);
01185
01186
01187 server = dbus_server_listen (valid_addresses[i], NULL);
01188 if (server == NULL)
01189 _dbus_assert_not_reached ("Failed to listen for valid address.");
01190
01191 dbus_server_disconnect (server);
01192 dbus_server_unref (server);
01193 }
01194
01195 return TRUE;
01196 }
01197
01198 #endif