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