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
00063 dbus_bool_t
00064 _dbus_server_init_base (DBusServer *server,
00065 const DBusServerVTable *vtable,
00066 const DBusString *address)
00067 {
00068 server->vtable = vtable;
00069 server->refcount = 1;
00070
00071 server->address = NULL;
00072 server->watches = NULL;
00073 server->timeouts = NULL;
00074
00075 if (!_dbus_string_copy_data (address, &server->address))
00076 goto failed;
00077
00078 server->watches = _dbus_watch_list_new ();
00079 if (server->watches == NULL)
00080 goto failed;
00081
00082 server->timeouts = _dbus_timeout_list_new ();
00083 if (server->timeouts == NULL)
00084 goto failed;
00085
00086 _dbus_data_slot_list_init (&server->slot_list);
00087
00088 _dbus_verbose ("Initialized server on address %s\n", server->address);
00089
00090 return TRUE;
00091
00092 failed:
00093 if (server->watches)
00094 {
00095 _dbus_watch_list_free (server->watches);
00096 server->watches = NULL;
00097 }
00098 if (server->timeouts)
00099 {
00100 _dbus_timeout_list_free (server->timeouts);
00101 server->timeouts = NULL;
00102 }
00103 if (server->address)
00104 {
00105 dbus_free (server->address);
00106 server->address = NULL;
00107 }
00108
00109 return FALSE;
00110 }
00111
00118 void
00119 _dbus_server_finalize_base (DBusServer *server)
00120 {
00121
00122 _dbus_data_slot_list_free (&server->slot_list);
00123
00124 dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00125
00126 if (!server->disconnected)
00127 dbus_server_disconnect (server);
00128
00129 _dbus_watch_list_free (server->watches);
00130 _dbus_timeout_list_free (server->timeouts);
00131
00132 dbus_free (server->address);
00133
00134 dbus_free_string_array (server->auth_mechanisms);
00135 }
00136
00144 dbus_bool_t
00145 _dbus_server_add_watch (DBusServer *server,
00146 DBusWatch *watch)
00147 {
00148 return _dbus_watch_list_add_watch (server->watches, watch);
00149 }
00150
00157 void
00158 _dbus_server_remove_watch (DBusServer *server,
00159 DBusWatch *watch)
00160 {
00161 _dbus_watch_list_remove_watch (server->watches, watch);
00162 }
00163
00173 void
00174 _dbus_server_toggle_watch (DBusServer *server,
00175 DBusWatch *watch,
00176 dbus_bool_t enabled)
00177 {
00178 if (server->watches)
00179 _dbus_watch_list_toggle_watch (server->watches,
00180 watch, enabled);
00181 }
00182
00192 dbus_bool_t
00193 _dbus_server_add_timeout (DBusServer *server,
00194 DBusTimeout *timeout)
00195 {
00196 return _dbus_timeout_list_add_timeout (server->timeouts, timeout);
00197 }
00198
00205 void
00206 _dbus_server_remove_timeout (DBusServer *server,
00207 DBusTimeout *timeout)
00208 {
00209 _dbus_timeout_list_remove_timeout (server->timeouts, timeout);
00210 }
00211
00221 void
00222 _dbus_server_toggle_timeout (DBusServer *server,
00223 DBusTimeout *timeout,
00224 dbus_bool_t enabled)
00225 {
00226 if (server->timeouts)
00227 _dbus_timeout_list_toggle_timeout (server->timeouts,
00228 timeout, enabled);
00229 }
00230
00231
00269 DBusServer*
00270 dbus_server_listen (const char *address,
00271 DBusError *error)
00272 {
00273 DBusServer *server;
00274 DBusAddressEntry **entries;
00275 int len, i;
00276 const char *address_problem_type;
00277 const char *address_problem_field;
00278 const char *address_problem_other;
00279
00280 _dbus_return_val_if_fail (address != NULL, NULL);
00281 _dbus_return_val_if_error_is_set (error, NULL);
00282
00283 if (!dbus_parse_address (address, &entries, &len, error))
00284 return NULL;
00285
00286 server = NULL;
00287 address_problem_type = NULL;
00288 address_problem_field = NULL;
00289 address_problem_other = NULL;
00290
00291 for (i = 0; i < len; i++)
00292 {
00293 const char *method = dbus_address_entry_get_method (entries[i]);
00294
00295 if (strcmp (method, "unix") == 0)
00296 {
00297 const char *path = dbus_address_entry_get_value (entries[i], "path");
00298 const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
00299 const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
00300
00301 if (path == NULL && tmpdir == NULL && abstract == NULL)
00302 {
00303 address_problem_type = "unix";
00304 address_problem_field = "path or tmpdir or abstract";
00305 goto bad_address;
00306 }
00307
00308 if ((path && tmpdir) ||
00309 (path && abstract) ||
00310 (tmpdir && abstract))
00311 {
00312 address_problem_other = "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time";
00313 goto bad_address;
00314 }
00315
00316 if (tmpdir != NULL)
00317 {
00318 DBusString full_path;
00319 DBusString filename;
00320
00321 if (!_dbus_string_init (&full_path))
00322 {
00323 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00324 goto out;
00325 }
00326
00327 if (!_dbus_string_init (&filename))
00328 {
00329 _dbus_string_free (&full_path);
00330 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00331 goto out;
00332 }
00333
00334 if (!_dbus_string_append (&filename,
00335 "dbus-") ||
00336 !_dbus_generate_random_ascii (&filename, 10) ||
00337 !_dbus_string_append (&full_path, tmpdir) ||
00338 !_dbus_concat_dir_and_file (&full_path, &filename))
00339 {
00340 _dbus_string_free (&full_path);
00341 _dbus_string_free (&filename);
00342 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00343 goto out;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 server =
00356 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
00357 #ifdef HAVE_ABSTRACT_SOCKETS
00358 TRUE,
00359 #else
00360 FALSE,
00361 #endif
00362 error);
00363
00364 _dbus_string_free (&full_path);
00365 _dbus_string_free (&filename);
00366 }
00367 else
00368 {
00369 if (path)
00370 server = _dbus_server_new_for_domain_socket (path, FALSE, error);
00371 else
00372 server = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
00373 }
00374 }
00375 else if (strcmp (method, "tcp") == 0)
00376 {
00377 const char *host = dbus_address_entry_get_value (entries[i], "host");
00378 const char *port = dbus_address_entry_get_value (entries[i], "port");
00379 DBusString str;
00380 long lport;
00381 dbus_bool_t sresult;
00382
00383 if (port == NULL)
00384 {
00385 address_problem_type = "tcp";
00386 address_problem_field = "port";
00387 goto bad_address;
00388 }
00389
00390 _dbus_string_init_const (&str, port);
00391 sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
00392 _dbus_string_free (&str);
00393
00394 if (sresult == FALSE || lport <= 0 || lport > 65535)
00395 {
00396 address_problem_other = "Port is not an integer between 0 and 65535";
00397 goto bad_address;
00398 }
00399
00400 server = _dbus_server_new_for_tcp_socket (host, lport, error);
00401
00402 if (server)
00403 break;
00404 }
00405 #ifdef DBUS_BUILD_TESTS
00406 else if (strcmp (method, "debug-pipe") == 0)
00407 {
00408 const char *name = dbus_address_entry_get_value (entries[i], "name");
00409
00410 if (name == NULL)
00411 {
00412 address_problem_type = "debug-pipe";
00413 address_problem_field = "name";
00414 goto bad_address;
00415 }
00416
00417 server = _dbus_server_debug_pipe_new (name, error);
00418 }
00419 #endif
00420 else
00421 {
00422 address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
00423 goto bad_address;
00424 }
00425
00426 if (server)
00427 break;
00428 }
00429
00430 out:
00431
00432 dbus_address_entries_free (entries);
00433 return server;
00434
00435 bad_address:
00436 dbus_address_entries_free (entries);
00437 if (address_problem_type != NULL)
00438 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00439 "Server address of type %s was missing argument %s",
00440 address_problem_type, address_problem_field);
00441 else
00442 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00443 "Could not parse server address: %s",
00444 address_problem_other);
00445
00446 return NULL;
00447 }
00448
00455 DBusServer *
00456 dbus_server_ref (DBusServer *server)
00457 {
00458 _dbus_return_val_if_fail (server != NULL, NULL);
00459
00460 server->refcount += 1;
00461
00462 return server;
00463 }
00464
00473 void
00474 dbus_server_unref (DBusServer *server)
00475 {
00476 _dbus_return_if_fail (server != NULL);
00477
00478 _dbus_assert (server->refcount > 0);
00479
00480 server->refcount -= 1;
00481 if (server->refcount == 0)
00482 {
00483 _dbus_assert (server->vtable->finalize != NULL);
00484
00485 (* server->vtable->finalize) (server);
00486 }
00487 }
00488
00497 void
00498 dbus_server_disconnect (DBusServer *server)
00499 {
00500 _dbus_return_if_fail (server != NULL);
00501
00502 _dbus_assert (server->vtable->disconnect != NULL);
00503
00504 if (server->disconnected)
00505 return;
00506
00507 (* server->vtable->disconnect) (server);
00508 server->disconnected = TRUE;
00509 }
00510
00516 dbus_bool_t
00517 dbus_server_get_is_connected (DBusServer *server)
00518 {
00519 _dbus_return_val_if_fail (server != NULL, FALSE);
00520
00521 return !server->disconnected;
00522 }
00523
00531 char*
00532 dbus_server_get_address (DBusServer *server)
00533 {
00534 _dbus_return_val_if_fail (server != NULL, NULL);
00535
00536 return _dbus_strdup (server->address);
00537 }
00538
00551 void
00552 dbus_server_set_new_connection_function (DBusServer *server,
00553 DBusNewConnectionFunction function,
00554 void *data,
00555 DBusFreeFunction free_data_function)
00556 {
00557 _dbus_return_if_fail (server != NULL);
00558
00559 if (server->new_connection_free_data_function != NULL)
00560 (* server->new_connection_free_data_function) (server->new_connection_data);
00561
00562 server->new_connection_function = function;
00563 server->new_connection_data = data;
00564 server->new_connection_free_data_function = free_data_function;
00565 }
00566
00583 dbus_bool_t
00584 dbus_server_set_watch_functions (DBusServer *server,
00585 DBusAddWatchFunction add_function,
00586 DBusRemoveWatchFunction remove_function,
00587 DBusWatchToggledFunction toggled_function,
00588 void *data,
00589 DBusFreeFunction free_data_function)
00590 {
00591 _dbus_return_val_if_fail (server != NULL, FALSE);
00592
00593 return _dbus_watch_list_set_functions (server->watches,
00594 add_function,
00595 remove_function,
00596 toggled_function,
00597 data,
00598 free_data_function);
00599 }
00600
00616 dbus_bool_t
00617 dbus_server_set_timeout_functions (DBusServer *server,
00618 DBusAddTimeoutFunction add_function,
00619 DBusRemoveTimeoutFunction remove_function,
00620 DBusTimeoutToggledFunction toggled_function,
00621 void *data,
00622 DBusFreeFunction free_data_function)
00623 {
00624 _dbus_return_val_if_fail (server != NULL, FALSE);
00625
00626 return _dbus_timeout_list_set_functions (server->timeouts,
00627 add_function, remove_function,
00628 toggled_function,
00629 data, free_data_function);
00630 }
00631
00642 dbus_bool_t
00643 dbus_server_set_auth_mechanisms (DBusServer *server,
00644 const char **mechanisms)
00645 {
00646 char **copy;
00647
00648 _dbus_return_val_if_fail (server != NULL, FALSE);
00649
00650 if (mechanisms != NULL)
00651 {
00652 copy = _dbus_dup_string_array (mechanisms);
00653 if (copy == NULL)
00654 return FALSE;
00655 }
00656 else
00657 copy = NULL;
00658
00659 dbus_free_string_array (server->auth_mechanisms);
00660 server->auth_mechanisms = copy;
00661
00662 return TRUE;
00663 }
00664
00665
00666 static DBusDataSlotAllocator slot_allocator;
00667 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
00668
00683 dbus_bool_t
00684 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
00685 {
00686 return _dbus_data_slot_allocator_alloc (&slot_allocator,
00687 _DBUS_LOCK_NAME (server_slots),
00688 slot_p);
00689 }
00690
00702 void
00703 dbus_server_free_data_slot (dbus_int32_t *slot_p)
00704 {
00705 _dbus_return_if_fail (*slot_p >= 0);
00706
00707 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00708 }
00709
00723 dbus_bool_t
00724 dbus_server_set_data (DBusServer *server,
00725 int slot,
00726 void *data,
00727 DBusFreeFunction free_data_func)
00728 {
00729 DBusFreeFunction old_free_func;
00730 void *old_data;
00731 dbus_bool_t retval;
00732
00733 _dbus_return_val_if_fail (server != NULL, FALSE);
00734
00735 #if 0
00736 dbus_mutex_lock (server->mutex);
00737 #endif
00738
00739 retval = _dbus_data_slot_list_set (&slot_allocator,
00740 &server->slot_list,
00741 slot, data, free_data_func,
00742 &old_free_func, &old_data);
00743
00744 #if 0
00745 dbus_mutex_unlock (server->mutex);
00746 #endif
00747
00748 if (retval)
00749 {
00750
00751 if (old_free_func)
00752 (* old_free_func) (old_data);
00753 }
00754
00755 return retval;
00756 }
00757
00766 void*
00767 dbus_server_get_data (DBusServer *server,
00768 int slot)
00769 {
00770 void *res;
00771
00772 _dbus_return_val_if_fail (server != NULL, NULL);
00773
00774 #if 0
00775 dbus_mutex_lock (server->mutex);
00776 #endif
00777
00778 res = _dbus_data_slot_list_get (&slot_allocator,
00779 &server->slot_list,
00780 slot);
00781
00782 #if 0
00783 dbus_mutex_unlock (server->mutex);
00784 #endif
00785
00786 return res;
00787 }
00788
00791 #ifdef DBUS_BUILD_TESTS
00792 #include "dbus-test.h"
00793
00794 dbus_bool_t
00795 _dbus_server_test (void)
00796 {
00797 const char *valid_addresses[] = {
00798 "tcp:port=1234",
00799 "unix:path=./boogie",
00800 "tcp:host=localhost,port=1234",
00801 "tcp:host=localhost,port=1234;tcp:port=5678",
00802 "tcp:port=1234;unix:path=./boogie",
00803 };
00804
00805 DBusServer *server;
00806 int i;
00807
00808 for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
00809 {
00810 server = dbus_server_listen (valid_addresses[i], NULL);
00811 if (server == NULL)
00812 _dbus_assert_not_reached ("Failed to listen for valid address.");
00813
00814 dbus_server_unref (server);
00815
00816
00817 server = dbus_server_listen (valid_addresses[i], NULL);
00818 if (server == NULL)
00819 _dbus_assert_not_reached ("Failed to listen for valid address.");
00820
00821 dbus_server_disconnect (server);
00822
00823 dbus_server_unref (server);
00824 }
00825
00826 return TRUE;
00827 }
00828
00829 #endif