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