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 <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-server-socket.h"
00027 #include "dbus-transport-socket.h"
00028 #include "dbus-connection-internal.h"
00029 #include "dbus-memory.h"
00030 #include "dbus-nonce.h"
00031 #include "dbus-string.h"
00032
00044 typedef struct DBusServerSocket DBusServerSocket;
00045
00050 struct DBusServerSocket
00051 {
00052 DBusServer base;
00053 int n_fds;
00054 int *fds;
00055 DBusWatch **watch;
00056 char *socket_name;
00057 DBusNonceFile *noncefile;
00058 };
00059
00060 static void
00061 socket_finalize (DBusServer *server)
00062 {
00063 DBusServerSocket *socket_server = (DBusServerSocket*) server;
00064 int i;
00065
00066 _dbus_server_finalize_base (server);
00067
00068 for (i = 0 ; i < socket_server->n_fds ; i++)
00069 if (socket_server->watch[i])
00070 {
00071 _dbus_watch_unref (socket_server->watch[i]);
00072 socket_server->watch[i] = NULL;
00073 }
00074
00075 dbus_free (socket_server->fds);
00076 dbus_free (socket_server->watch);
00077 dbus_free (socket_server->socket_name);
00078 if (socket_server->noncefile)
00079 _dbus_noncefile_delete (socket_server->noncefile, NULL);
00080 dbus_free (socket_server->noncefile);
00081 dbus_free (server);
00082 }
00083
00084
00085 static dbus_bool_t
00086 handle_new_client_fd_and_unlock (DBusServer *server,
00087 int client_fd)
00088 {
00089 DBusConnection *connection;
00090 DBusTransport *transport;
00091 DBusNewConnectionFunction new_connection_function;
00092 DBusServerSocket* socket_server;
00093 void *new_connection_data;
00094
00095 socket_server = (DBusServerSocket*)server;
00096 _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
00097
00098 HAVE_LOCK_CHECK (server);
00099
00100 if (!_dbus_set_fd_nonblocking (client_fd, NULL))
00101 {
00102 SERVER_UNLOCK (server);
00103 return TRUE;
00104 }
00105
00106 transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, FALSE);
00107 if (transport == NULL)
00108 {
00109 _dbus_close_socket (client_fd, NULL);
00110 SERVER_UNLOCK (server);
00111 return FALSE;
00112 }
00113
00114 if (!_dbus_transport_set_auth_mechanisms (transport,
00115 (const char **) server->auth_mechanisms))
00116 {
00117 _dbus_transport_unref (transport);
00118 SERVER_UNLOCK (server);
00119 return FALSE;
00120 }
00121
00122
00123
00124
00125
00126 connection = _dbus_connection_new_for_transport (transport);
00127 _dbus_transport_unref (transport);
00128 transport = NULL;
00129
00130 if (connection == NULL)
00131 {
00132 SERVER_UNLOCK (server);
00133 return FALSE;
00134 }
00135
00136
00137
00138
00139 new_connection_function = server->new_connection_function;
00140 new_connection_data = server->new_connection_data;
00141
00142 _dbus_server_ref_unlocked (server);
00143 SERVER_UNLOCK (server);
00144
00145 if (new_connection_function)
00146 {
00147 (* new_connection_function) (server, connection,
00148 new_connection_data);
00149 }
00150 dbus_server_unref (server);
00151
00152
00153 _dbus_connection_close_if_only_one_ref (connection);
00154 dbus_connection_unref (connection);
00155
00156 return TRUE;
00157 }
00158
00159 static dbus_bool_t
00160 socket_handle_watch (DBusWatch *watch,
00161 unsigned int flags,
00162 void *data)
00163 {
00164 DBusServer *server = data;
00165 DBusServerSocket *socket_server = data;
00166
00167 #ifndef DBUS_DISABLE_ASSERT
00168 int i;
00169 dbus_bool_t found = FALSE;
00170 #endif
00171
00172 SERVER_LOCK (server);
00173
00174 #ifndef DBUS_DISABLE_ASSERT
00175 for (i = 0 ; i < socket_server->n_fds ; i++)
00176 {
00177 if (socket_server->watch[i] == watch)
00178 found = TRUE;
00179 }
00180 _dbus_assert (found);
00181 #endif
00182
00183 _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00184
00185 if (flags & DBUS_WATCH_READABLE)
00186 {
00187 int client_fd;
00188 int listen_fd;
00189
00190 listen_fd = dbus_watch_get_socket (watch);
00191
00192 if (socket_server->noncefile)
00193 client_fd = _dbus_accept_with_noncefile (listen_fd, socket_server->noncefile);
00194 else
00195 client_fd = _dbus_accept (listen_fd);
00196
00197 if (client_fd < 0)
00198 {
00199
00200
00201 if (_dbus_get_is_errno_eagain_or_ewouldblock ())
00202 _dbus_verbose ("No client available to accept after all\n");
00203 else
00204 _dbus_verbose ("Failed to accept a client connection: %s\n",
00205 _dbus_strerror_from_errno ());
00206
00207 SERVER_UNLOCK (server);
00208 }
00209 else
00210 {
00211 if (!handle_new_client_fd_and_unlock (server, client_fd))
00212 _dbus_verbose ("Rejected client connection due to lack of memory\n");
00213 }
00214 }
00215
00216 if (flags & DBUS_WATCH_ERROR)
00217 _dbus_verbose ("Error on server listening socket\n");
00218
00219 if (flags & DBUS_WATCH_HANGUP)
00220 _dbus_verbose ("Hangup on server listening socket\n");
00221
00222 return TRUE;
00223 }
00224
00225 static void
00226 socket_disconnect (DBusServer *server)
00227 {
00228 DBusServerSocket *socket_server = (DBusServerSocket*) server;
00229 int i;
00230
00231 HAVE_LOCK_CHECK (server);
00232
00233 for (i = 0 ; i < socket_server->n_fds ; i++)
00234 {
00235 if (socket_server->watch[i])
00236 {
00237 _dbus_server_remove_watch (server,
00238 socket_server->watch[i]);
00239 _dbus_watch_unref (socket_server->watch[i]);
00240 socket_server->watch[i] = NULL;
00241 }
00242
00243 _dbus_close_socket (socket_server->fds[i], NULL);
00244 socket_server->fds[i] = -1;
00245 }
00246
00247 if (socket_server->socket_name != NULL)
00248 {
00249 DBusString tmp;
00250 _dbus_string_init_const (&tmp, socket_server->socket_name);
00251 _dbus_delete_file (&tmp, NULL);
00252 }
00253
00254 if (server->published_address)
00255 _dbus_daemon_unpublish_session_bus_address();
00256
00257 HAVE_LOCK_CHECK (server);
00258 }
00259
00260 static const DBusServerVTable socket_vtable = {
00261 socket_finalize,
00262 socket_disconnect
00263 };
00264
00280 DBusServer*
00281 _dbus_server_new_for_socket (int *fds,
00282 int n_fds,
00283 const DBusString *address,
00284 DBusNonceFile *noncefile)
00285 {
00286 DBusServerSocket *socket_server;
00287 DBusServer *server;
00288 int i;
00289
00290 socket_server = dbus_new0 (DBusServerSocket, 1);
00291 if (socket_server == NULL)
00292 return NULL;
00293
00294 socket_server->noncefile = noncefile;
00295
00296 socket_server->fds = dbus_new (int, n_fds);
00297 if (!socket_server->fds)
00298 goto failed_0;
00299
00300 socket_server->watch = dbus_new0 (DBusWatch *, n_fds);
00301 if (!socket_server->watch)
00302 goto failed_1;
00303
00304 for (i = 0 ; i < n_fds ; i++)
00305 {
00306 DBusWatch *watch;
00307
00308 watch = _dbus_watch_new (fds[i],
00309 DBUS_WATCH_READABLE,
00310 TRUE,
00311 socket_handle_watch, socket_server,
00312 NULL);
00313 if (watch == NULL)
00314 goto failed_2;
00315
00316 socket_server->n_fds++;
00317 socket_server->fds[i] = fds[i];
00318 socket_server->watch[i] = watch;
00319 }
00320
00321 if (!_dbus_server_init_base (&socket_server->base,
00322 &socket_vtable, address))
00323 goto failed_2;
00324
00325 server = (DBusServer*)socket_server;
00326
00327 SERVER_LOCK (server);
00328
00329 for (i = 0 ; i < n_fds ; i++)
00330 {
00331 if (!_dbus_server_add_watch (&socket_server->base,
00332 socket_server->watch[i]))
00333 {
00334 int j;
00335 for (j = 0 ; j < i ; j++)
00336 _dbus_server_remove_watch (server,
00337 socket_server->watch[j]);
00338
00339 SERVER_UNLOCK (server);
00340 _dbus_server_finalize_base (&socket_server->base);
00341 goto failed_2;
00342 }
00343 }
00344
00345 SERVER_UNLOCK (server);
00346
00347 return (DBusServer*) socket_server;
00348
00349 failed_2:
00350 for (i = 0 ; i < n_fds ; i++)
00351 {
00352 if (socket_server->watch[i] != NULL)
00353 {
00354 _dbus_watch_unref (socket_server->watch[i]);
00355 socket_server->watch[i] = NULL;
00356 }
00357 }
00358 dbus_free (socket_server->watch);
00359
00360 failed_1:
00361 dbus_free (socket_server->fds);
00362
00363 failed_0:
00364 dbus_free (socket_server);
00365 return NULL;
00366 }
00367
00387 DBusServer*
00388 _dbus_server_new_for_tcp_socket (const char *host,
00389 const char *bind,
00390 const char *port,
00391 const char *family,
00392 DBusError *error,
00393 dbus_bool_t use_nonce)
00394 {
00395 DBusServer *server;
00396 int *listen_fds = NULL;
00397 int nlisten_fds = 0, i;
00398 DBusString address;
00399 DBusString host_str;
00400 DBusString port_str;
00401 DBusNonceFile *noncefile;
00402
00403 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00404
00405 noncefile = NULL;
00406
00407 if (!_dbus_string_init (&address))
00408 {
00409 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00410 return NULL;
00411 }
00412
00413 if (!_dbus_string_init (&port_str))
00414 {
00415 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00416 goto failed_0;
00417 }
00418
00419 if (host == NULL)
00420 host = "localhost";
00421
00422 if (port == NULL)
00423 port = "0";
00424
00425 if (bind == NULL)
00426 bind = host;
00427 else if (strcmp (bind, "*") == 0)
00428 bind = NULL;
00429
00430 nlisten_fds =_dbus_listen_tcp_socket (bind, port, family,
00431 &port_str,
00432 &listen_fds, error);
00433 if (nlisten_fds <= 0)
00434 {
00435 _DBUS_ASSERT_ERROR_IS_SET(error);
00436 goto failed_1;
00437 }
00438
00439 _dbus_string_init_const (&host_str, host);
00440 if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") ||
00441 !_dbus_address_append_escaped (&address, &host_str) ||
00442 !_dbus_string_append (&address, ",port=") ||
00443 !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
00444 {
00445 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00446 goto failed_2;
00447 }
00448 if (family &&
00449 (!_dbus_string_append (&address, ",family=") ||
00450 !_dbus_string_append (&address, family)))
00451 {
00452 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00453 goto failed_2;
00454 }
00455
00456 if (use_nonce)
00457 {
00458 noncefile = dbus_new0 (DBusNonceFile, 1);
00459 if (noncefile == NULL)
00460 {
00461 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00462 goto failed_2;
00463 }
00464
00465 if (!_dbus_noncefile_create (noncefile, error))
00466 goto failed_3;
00467
00468 if (!_dbus_string_append (&address, ",noncefile=") ||
00469 !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile)))
00470 {
00471 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00472 goto failed_4;
00473 }
00474
00475 }
00476
00477 server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile);
00478 if (server == NULL)
00479 {
00480 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00481 goto failed_4;
00482 }
00483
00484 _dbus_string_free (&port_str);
00485 _dbus_string_free (&address);
00486 dbus_free(listen_fds);
00487
00488 return server;
00489
00490 failed_4:
00491 _dbus_noncefile_delete (noncefile, NULL);
00492
00493 failed_3:
00494 dbus_free (noncefile);
00495
00496 failed_2:
00497 for (i = 0 ; i < nlisten_fds ; i++)
00498 _dbus_close_socket (listen_fds[i], NULL);
00499 dbus_free(listen_fds);
00500
00501 failed_1:
00502 _dbus_string_free (&port_str);
00503
00504 failed_0:
00505 _dbus_string_free (&address);
00506
00507 return NULL;
00508 }
00509
00522 DBusServerListenResult
00523 _dbus_server_listen_socket (DBusAddressEntry *entry,
00524 DBusServer **server_p,
00525 DBusError *error)
00526 {
00527 const char *method;
00528
00529 *server_p = NULL;
00530
00531 method = dbus_address_entry_get_method (entry);
00532
00533 if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0)
00534 {
00535 const char *host;
00536 const char *port;
00537 const char *bind;
00538 const char *family;
00539
00540 host = dbus_address_entry_get_value (entry, "host");
00541 bind = dbus_address_entry_get_value (entry, "bind");
00542 port = dbus_address_entry_get_value (entry, "port");
00543 family = dbus_address_entry_get_value (entry, "family");
00544
00545 *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
00546 family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE);
00547
00548 if (*server_p)
00549 {
00550 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00551 return DBUS_SERVER_LISTEN_OK;
00552 }
00553 else
00554 {
00555 _DBUS_ASSERT_ERROR_IS_SET(error);
00556 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00557 }
00558 }
00559 else
00560 {
00561 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00562 return DBUS_SERVER_LISTEN_NOT_HANDLED;
00563 }
00564 }
00565
00575 void
00576 _dbus_server_socket_own_filename (DBusServer *server,
00577 char *filename)
00578 {
00579 DBusServerSocket *socket_server = (DBusServerSocket*) server;
00580
00581 socket_server->socket_name = filename;
00582 }
00583
00584