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 _dbus_mutex_new_at_location (&server->mutex);
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 _dbus_mutex_free_at_location (&server->mutex);
00164 server->mutex = NULL;
00165 if (server->watches)
00166 {
00167 _dbus_watch_list_free (server->watches);
00168 server->watches = NULL;
00169 }
00170 if (server->timeouts)
00171 {
00172 _dbus_timeout_list_free (server->timeouts);
00173 server->timeouts = NULL;
00174 }
00175 if (server->address)
00176 {
00177 dbus_free (server->address);
00178 server->address = NULL;
00179 }
00180 _dbus_string_free (&server->guid_hex);
00181
00182 return FALSE;
00183 }
00184
00191 void
00192 _dbus_server_finalize_base (DBusServer *server)
00193 {
00194
00195
00196
00197 #ifndef DBUS_DISABLE_CHECKS
00198 _dbus_assert (!server->have_server_lock);
00199 #endif
00200 _dbus_assert (server->disconnected);
00201
00202
00203 _dbus_data_slot_list_free (&server->slot_list);
00204
00205 dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00206
00207 _dbus_watch_list_free (server->watches);
00208 _dbus_timeout_list_free (server->timeouts);
00209
00210 _dbus_mutex_free_at_location (&server->mutex);
00211
00212 dbus_free (server->address);
00213
00214 dbus_free_string_array (server->auth_mechanisms);
00215
00216 _dbus_string_free (&server->guid_hex);
00217 }
00218
00219
00220 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00221 DBusWatch *watch);
00222 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00223 DBusWatch *watch);
00224 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00225 DBusWatch *watch,
00226 dbus_bool_t enabled);
00227
00228 static dbus_bool_t
00229 protected_change_watch (DBusServer *server,
00230 DBusWatch *watch,
00231 DBusWatchAddFunction add_function,
00232 DBusWatchRemoveFunction remove_function,
00233 DBusWatchToggleFunction toggle_function,
00234 dbus_bool_t enabled)
00235 {
00236 DBusWatchList *watches;
00237 dbus_bool_t retval;
00238
00239 HAVE_LOCK_CHECK (server);
00240
00241
00242
00243
00244
00245
00246 watches = server->watches;
00247 if (watches)
00248 {
00249 server->watches = NULL;
00250 _dbus_server_ref_unlocked (server);
00251 SERVER_UNLOCK (server);
00252
00253 if (add_function)
00254 retval = (* add_function) (watches, watch);
00255 else if (remove_function)
00256 {
00257 retval = TRUE;
00258 (* remove_function) (watches, watch);
00259 }
00260 else
00261 {
00262 retval = TRUE;
00263 (* toggle_function) (watches, watch, enabled);
00264 }
00265
00266 SERVER_LOCK (server);
00267 server->watches = watches;
00268 _dbus_server_unref_unlocked (server);
00269
00270 return retval;
00271 }
00272 else
00273 return FALSE;
00274 }
00275
00283 dbus_bool_t
00284 _dbus_server_add_watch (DBusServer *server,
00285 DBusWatch *watch)
00286 {
00287 HAVE_LOCK_CHECK (server);
00288 return protected_change_watch (server, watch,
00289 _dbus_watch_list_add_watch,
00290 NULL, NULL, FALSE);
00291 }
00292
00299 void
00300 _dbus_server_remove_watch (DBusServer *server,
00301 DBusWatch *watch)
00302 {
00303 HAVE_LOCK_CHECK (server);
00304 protected_change_watch (server, watch,
00305 NULL,
00306 _dbus_watch_list_remove_watch,
00307 NULL, FALSE);
00308 }
00309
00319 void
00320 _dbus_server_toggle_watch (DBusServer *server,
00321 DBusWatch *watch,
00322 dbus_bool_t enabled)
00323 {
00324 _dbus_assert (watch != NULL);
00325
00326 HAVE_LOCK_CHECK (server);
00327 protected_change_watch (server, watch,
00328 NULL, NULL,
00329 _dbus_watch_list_toggle_watch,
00330 enabled);
00331 }
00332
00333
00334 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00335 DBusTimeout *timeout);
00336 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00337 DBusTimeout *timeout);
00338 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00339 DBusTimeout *timeout,
00340 dbus_bool_t enabled);
00341
00342
00343 static dbus_bool_t
00344 protected_change_timeout (DBusServer *server,
00345 DBusTimeout *timeout,
00346 DBusTimeoutAddFunction add_function,
00347 DBusTimeoutRemoveFunction remove_function,
00348 DBusTimeoutToggleFunction toggle_function,
00349 dbus_bool_t enabled)
00350 {
00351 DBusTimeoutList *timeouts;
00352 dbus_bool_t retval;
00353
00354 HAVE_LOCK_CHECK (server);
00355
00356
00357
00358
00359
00360 timeouts = server->timeouts;
00361 if (timeouts)
00362 {
00363 server->timeouts = NULL;
00364 _dbus_server_ref_unlocked (server);
00365 SERVER_UNLOCK (server);
00366
00367 if (add_function)
00368 retval = (* add_function) (timeouts, timeout);
00369 else if (remove_function)
00370 {
00371 retval = TRUE;
00372 (* remove_function) (timeouts, timeout);
00373 }
00374 else
00375 {
00376 retval = TRUE;
00377 (* toggle_function) (timeouts, timeout, enabled);
00378 }
00379
00380 SERVER_LOCK (server);
00381 server->timeouts = timeouts;
00382 _dbus_server_unref_unlocked (server);
00383
00384 return retval;
00385 }
00386 else
00387 return FALSE;
00388 }
00389
00399 dbus_bool_t
00400 _dbus_server_add_timeout (DBusServer *server,
00401 DBusTimeout *timeout)
00402 {
00403 return protected_change_timeout (server, timeout,
00404 _dbus_timeout_list_add_timeout,
00405 NULL, NULL, FALSE);
00406 }
00407
00414 void
00415 _dbus_server_remove_timeout (DBusServer *server,
00416 DBusTimeout *timeout)
00417 {
00418 protected_change_timeout (server, timeout,
00419 NULL,
00420 _dbus_timeout_list_remove_timeout,
00421 NULL, FALSE);
00422 }
00423
00433 void
00434 _dbus_server_toggle_timeout (DBusServer *server,
00435 DBusTimeout *timeout,
00436 dbus_bool_t enabled)
00437 {
00438 protected_change_timeout (server, timeout,
00439 NULL, NULL,
00440 _dbus_timeout_list_toggle_timeout,
00441 enabled);
00442 }
00443
00444
00482 DBusServer*
00483 dbus_server_listen (const char *address,
00484 DBusError *error)
00485 {
00486 DBusServer *server;
00487 DBusAddressEntry **entries;
00488 int len, i;
00489 const char *address_problem_type;
00490 const char *address_problem_field;
00491 const char *address_problem_other;
00492
00493 _dbus_return_val_if_fail (address != NULL, NULL);
00494 _dbus_return_val_if_error_is_set (error, NULL);
00495
00496 if (!dbus_parse_address (address, &entries, &len, error))
00497 return NULL;
00498
00499 server = NULL;
00500 address_problem_type = NULL;
00501 address_problem_field = NULL;
00502 address_problem_other = NULL;
00503
00504 for (i = 0; i < len; i++)
00505 {
00506 const char *method;
00507
00508 method = dbus_address_entry_get_method (entries[i]);
00509
00510 if (strcmp (method, "unix") == 0)
00511 {
00512 const char *path = dbus_address_entry_get_value (entries[i], "path");
00513 const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
00514 const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
00515
00516 if (path == NULL && tmpdir == NULL && abstract == NULL)
00517 {
00518 address_problem_type = "unix";
00519 address_problem_field = "path or tmpdir or abstract";
00520 goto bad_address;
00521 }
00522
00523 if ((path && tmpdir) ||
00524 (path && abstract) ||
00525 (tmpdir && abstract))
00526 {
00527 address_problem_other = "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time";
00528 goto bad_address;
00529 }
00530
00531 if (tmpdir != NULL)
00532 {
00533 DBusString full_path;
00534 DBusString filename;
00535
00536 if (!_dbus_string_init (&full_path))
00537 {
00538 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00539 goto out;
00540 }
00541
00542 if (!_dbus_string_init (&filename))
00543 {
00544 _dbus_string_free (&full_path);
00545 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00546 goto out;
00547 }
00548
00549 if (!_dbus_string_append (&filename,
00550 "dbus-") ||
00551 !_dbus_generate_random_ascii (&filename, 10) ||
00552 !_dbus_string_append (&full_path, tmpdir) ||
00553 !_dbus_concat_dir_and_file (&full_path, &filename))
00554 {
00555 _dbus_string_free (&full_path);
00556 _dbus_string_free (&filename);
00557 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00558 goto out;
00559 }
00560
00561
00562
00563 server =
00564 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
00565 #ifdef HAVE_ABSTRACT_SOCKETS
00566 TRUE,
00567 #else
00568 FALSE,
00569 #endif
00570 error);
00571
00572 _dbus_string_free (&full_path);
00573 _dbus_string_free (&filename);
00574 }
00575 else
00576 {
00577 if (path)
00578 server = _dbus_server_new_for_domain_socket (path, FALSE, error);
00579 else
00580 server = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
00581 }
00582 }
00583 else if (strcmp (method, "tcp") == 0)
00584 {
00585 const char *host = dbus_address_entry_get_value (entries[i], "host");
00586 const char *port = dbus_address_entry_get_value (entries[i], "port");
00587 DBusString str;
00588 long lport;
00589 dbus_bool_t sresult;
00590
00591 if (port == NULL)
00592 {
00593 address_problem_type = "tcp";
00594 address_problem_field = "port";
00595 goto bad_address;
00596 }
00597
00598 _dbus_string_init_const (&str, port);
00599 sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
00600 _dbus_string_free (&str);
00601
00602 if (sresult == FALSE || lport <= 0 || lport > 65535)
00603 {
00604 address_problem_other = "Port is not an integer between 0 and 65535";
00605 goto bad_address;
00606 }
00607
00608 server = _dbus_server_new_for_tcp_socket (host, lport, error);
00609
00610 if (server)
00611 break;
00612 }
00613 #ifdef DBUS_BUILD_TESTS
00614 else if (strcmp (method, "debug-pipe") == 0)
00615 {
00616 const char *name = dbus_address_entry_get_value (entries[i], "name");
00617
00618 if (name == NULL)
00619 {
00620 address_problem_type = "debug-pipe";
00621 address_problem_field = "name";
00622 goto bad_address;
00623 }
00624
00625 server = _dbus_server_debug_pipe_new (name, error);
00626 }
00627 #endif
00628 else
00629 {
00630 address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
00631 goto bad_address;
00632 }
00633
00634 if (server)
00635 break;
00636 }
00637
00638 out:
00639
00640 dbus_address_entries_free (entries);
00641 return server;
00642
00643 bad_address:
00644 dbus_address_entries_free (entries);
00645 if (address_problem_type != NULL)
00646 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00647 "Server address of type %s was missing argument %s",
00648 address_problem_type, address_problem_field);
00649 else
00650 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00651 "Could not parse server address: %s",
00652 address_problem_other);
00653
00654 return NULL;
00655 }
00656
00663 DBusServer *
00664 dbus_server_ref (DBusServer *server)
00665 {
00666 _dbus_return_val_if_fail (server != NULL, NULL);
00667 _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
00668
00669 #ifdef DBUS_HAVE_ATOMIC_INT
00670 _dbus_atomic_inc (&server->refcount);
00671 #else
00672 SERVER_LOCK (server);
00673 _dbus_assert (server->refcount.value > 0);
00674
00675 server->refcount.value += 1;
00676 SERVER_UNLOCK (server);
00677 #endif
00678
00679 return server;
00680 }
00681
00690 void
00691 dbus_server_unref (DBusServer *server)
00692 {
00693 dbus_bool_t last_unref;
00694
00695 _dbus_return_if_fail (server != NULL);
00696 _dbus_return_if_fail (server->refcount.value > 0);
00697
00698 #ifdef DBUS_HAVE_ATOMIC_INT
00699 last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00700 #else
00701 SERVER_LOCK (server);
00702
00703 _dbus_assert (server->refcount.value > 0);
00704
00705 server->refcount.value -= 1;
00706 last_unref = (server->refcount.value == 0);
00707
00708 SERVER_UNLOCK (server);
00709 #endif
00710
00711 if (last_unref)
00712 {
00713
00714 _dbus_assert (server->disconnected);
00715
00716 _dbus_assert (server->vtable->finalize != NULL);
00717
00718 (* server->vtable->finalize) (server);
00719 }
00720 }
00721
00727 void
00728 _dbus_server_ref_unlocked (DBusServer *server)
00729 {
00730 _dbus_assert (server != NULL);
00731 _dbus_assert (server->refcount.value > 0);
00732
00733 HAVE_LOCK_CHECK (server);
00734
00735 #ifdef DBUS_HAVE_ATOMIC_INT
00736 _dbus_atomic_inc (&server->refcount);
00737 #else
00738 _dbus_assert (server->refcount.value > 0);
00739
00740 server->refcount.value += 1;
00741 #endif
00742 }
00743
00749 void
00750 _dbus_server_unref_unlocked (DBusServer *server)
00751 {
00752 dbus_bool_t last_unref;
00753
00754 _dbus_assert (server != NULL);
00755 _dbus_assert (server->refcount.value > 0);
00756
00757 HAVE_LOCK_CHECK (server);
00758
00759 #ifdef DBUS_HAVE_ATOMIC_INT
00760 last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00761 #else
00762 _dbus_assert (server->refcount.value > 0);
00763
00764 server->refcount.value -= 1;
00765 last_unref = (server->refcount.value == 0);
00766 #endif
00767
00768 if (last_unref)
00769 {
00770 _dbus_assert (server->disconnected);
00771
00772 SERVER_UNLOCK (server);
00773
00774 _dbus_assert (server->vtable->finalize != NULL);
00775
00776 (* server->vtable->finalize) (server);
00777 }
00778 }
00779
00788 void
00789 dbus_server_disconnect (DBusServer *server)
00790 {
00791 _dbus_return_if_fail (server != NULL);
00792 _dbus_return_if_fail (server->refcount.value > 0);
00793
00794 SERVER_LOCK (server);
00795 _dbus_server_ref_unlocked (server);
00796
00797 _dbus_assert (server->vtable->disconnect != NULL);
00798
00799 if (!server->disconnected)
00800 {
00801
00802 server->disconnected = TRUE;
00803
00804 (* server->vtable->disconnect) (server);
00805 }
00806
00807 SERVER_UNLOCK (server);
00808 dbus_server_unref (server);
00809 }
00810
00816 dbus_bool_t
00817 dbus_server_get_is_connected (DBusServer *server)
00818 {
00819 dbus_bool_t retval;
00820
00821 _dbus_return_val_if_fail (server != NULL, FALSE);
00822
00823 SERVER_LOCK (server);
00824 retval = !server->disconnected;
00825 SERVER_UNLOCK (server);
00826
00827 return retval;
00828 }
00829
00837 char*
00838 dbus_server_get_address (DBusServer *server)
00839 {
00840 char *retval;
00841
00842 _dbus_return_val_if_fail (server != NULL, NULL);
00843
00844 SERVER_LOCK (server);
00845 retval = _dbus_strdup (server->address);
00846 SERVER_UNLOCK (server);
00847
00848 return retval;
00849 }
00850
00863 void
00864 dbus_server_set_new_connection_function (DBusServer *server,
00865 DBusNewConnectionFunction function,
00866 void *data,
00867 DBusFreeFunction free_data_function)
00868 {
00869 DBusFreeFunction old_free_function;
00870 void *old_data;
00871
00872 _dbus_return_if_fail (server != NULL);
00873
00874 SERVER_LOCK (server);
00875 old_free_function = server->new_connection_free_data_function;
00876 old_data = server->new_connection_data;
00877
00878 server->new_connection_function = function;
00879 server->new_connection_data = data;
00880 server->new_connection_free_data_function = free_data_function;
00881 SERVER_UNLOCK (server);
00882
00883 if (old_free_function != NULL)
00884 (* old_free_function) (old_data);
00885 }
00886
00903 dbus_bool_t
00904 dbus_server_set_watch_functions (DBusServer *server,
00905 DBusAddWatchFunction add_function,
00906 DBusRemoveWatchFunction remove_function,
00907 DBusWatchToggledFunction toggled_function,
00908 void *data,
00909 DBusFreeFunction free_data_function)
00910 {
00911 dbus_bool_t result;
00912 DBusWatchList *watches;
00913
00914 _dbus_return_val_if_fail (server != NULL, FALSE);
00915
00916 SERVER_LOCK (server);
00917 watches = server->watches;
00918 server->watches = NULL;
00919 if (watches)
00920 {
00921 SERVER_UNLOCK (server);
00922 result = _dbus_watch_list_set_functions (watches,
00923 add_function,
00924 remove_function,
00925 toggled_function,
00926 data,
00927 free_data_function);
00928 SERVER_LOCK (server);
00929 }
00930 else
00931 {
00932 _dbus_warn ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00933 result = FALSE;
00934 }
00935 server->watches = watches;
00936 SERVER_UNLOCK (server);
00937
00938 return result;
00939 }
00940
00956 dbus_bool_t
00957 dbus_server_set_timeout_functions (DBusServer *server,
00958 DBusAddTimeoutFunction add_function,
00959 DBusRemoveTimeoutFunction remove_function,
00960 DBusTimeoutToggledFunction toggled_function,
00961 void *data,
00962 DBusFreeFunction free_data_function)
00963 {
00964 dbus_bool_t result;
00965 DBusTimeoutList *timeouts;
00966
00967 _dbus_return_val_if_fail (server != NULL, FALSE);
00968
00969 SERVER_LOCK (server);
00970 timeouts = server->timeouts;
00971 server->timeouts = NULL;
00972 if (timeouts)
00973 {
00974 SERVER_UNLOCK (server);
00975 result = _dbus_timeout_list_set_functions (timeouts,
00976 add_function,
00977 remove_function,
00978 toggled_function,
00979 data,
00980 free_data_function);
00981 SERVER_LOCK (server);
00982 }
00983 else
00984 {
00985 _dbus_warn ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00986 result = FALSE;
00987 }
00988 server->timeouts = timeouts;
00989 SERVER_UNLOCK (server);
00990
00991 return result;
00992 }
00993
01004 dbus_bool_t
01005 dbus_server_set_auth_mechanisms (DBusServer *server,
01006 const char **mechanisms)
01007 {
01008 char **copy;
01009
01010 _dbus_return_val_if_fail (server != NULL, FALSE);
01011
01012 SERVER_LOCK (server);
01013
01014 if (mechanisms != NULL)
01015 {
01016 copy = _dbus_dup_string_array (mechanisms);
01017 if (copy == NULL)
01018 return FALSE;
01019 }
01020 else
01021 copy = NULL;
01022
01023 dbus_free_string_array (server->auth_mechanisms);
01024 server->auth_mechanisms = copy;
01025
01026 SERVER_UNLOCK (server);
01027
01028 return TRUE;
01029 }
01030
01031
01032 static DBusDataSlotAllocator slot_allocator;
01033 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01034
01049 dbus_bool_t
01050 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01051 {
01052 return _dbus_data_slot_allocator_alloc (&slot_allocator,
01053 (DBusMutex **)&_DBUS_LOCK_NAME (server_slots),
01054 slot_p);
01055 }
01056
01068 void
01069 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01070 {
01071 _dbus_return_if_fail (*slot_p >= 0);
01072
01073 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01074 }
01075
01089 dbus_bool_t
01090 dbus_server_set_data (DBusServer *server,
01091 int slot,
01092 void *data,
01093 DBusFreeFunction free_data_func)
01094 {
01095 DBusFreeFunction old_free_func;
01096 void *old_data;
01097 dbus_bool_t retval;
01098
01099 _dbus_return_val_if_fail (server != NULL, FALSE);
01100
01101 SERVER_LOCK (server);
01102
01103 retval = _dbus_data_slot_list_set (&slot_allocator,
01104 &server->slot_list,
01105 slot, data, free_data_func,
01106 &old_free_func, &old_data);
01107
01108
01109 SERVER_UNLOCK (server);
01110
01111 if (retval)
01112 {
01113
01114 if (old_free_func)
01115 (* old_free_func) (old_data);
01116 }
01117
01118 return retval;
01119 }
01120
01129 void*
01130 dbus_server_get_data (DBusServer *server,
01131 int slot)
01132 {
01133 void *res;
01134
01135 _dbus_return_val_if_fail (server != NULL, NULL);
01136
01137 SERVER_LOCK (server);
01138
01139 res = _dbus_data_slot_list_get (&slot_allocator,
01140 &server->slot_list,
01141 slot);
01142
01143 SERVER_UNLOCK (server);
01144
01145 return res;
01146 }
01147
01150 #ifdef DBUS_BUILD_TESTS
01151 #include "dbus-test.h"
01152
01153 dbus_bool_t
01154 _dbus_server_test (void)
01155 {
01156 const char *valid_addresses[] = {
01157 "tcp:port=1234",
01158 "unix:path=./boogie",
01159 "tcp:host=localhost,port=1234",
01160 "tcp:host=localhost,port=1234;tcp:port=5678",
01161 "tcp:port=1234;unix:path=./boogie",
01162 };
01163
01164 DBusServer *server;
01165 int i;
01166
01167 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01168 {
01169 server = dbus_server_listen (valid_addresses[i], NULL);
01170 if (server == NULL)
01171 _dbus_assert_not_reached ("Failed to listen for valid address.");
01172
01173 dbus_server_disconnect (server);
01174 dbus_server_unref (server);
01175
01176
01177 server = dbus_server_listen (valid_addresses[i], NULL);
01178 if (server == NULL)
01179 _dbus_assert_not_reached ("Failed to listen for valid address.");
01180
01181 dbus_server_disconnect (server);
01182 dbus_server_unref (server);
01183 }
01184
01185 return TRUE;
01186 }
01187
01188 #endif