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 DBusSocket *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 DBusSocket client_fd)
00088 {
00089 DBusConnection *connection;
00090 DBusTransport *transport;
00091 DBusNewConnectionFunction new_connection_function;
00092 void *new_connection_data;
00093
00094 _dbus_verbose ("Creating new client connection with fd %" DBUS_SOCKET_FORMAT "\n",
00095 _dbus_socket_printable (client_fd));
00096
00097 HAVE_LOCK_CHECK (server);
00098
00099 if (!_dbus_set_socket_nonblocking (client_fd, NULL))
00100 {
00101 SERVER_UNLOCK (server);
00102 return TRUE;
00103 }
00104
00105 transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, NULL);
00106 if (transport == NULL)
00107 {
00108 _dbus_close_socket (client_fd, NULL);
00109 SERVER_UNLOCK (server);
00110 return FALSE;
00111 }
00112
00113 if (!_dbus_transport_set_auth_mechanisms (transport,
00114 (const char **) server->auth_mechanisms))
00115 {
00116 _dbus_transport_unref (transport);
00117 SERVER_UNLOCK (server);
00118 return FALSE;
00119 }
00120
00121
00122
00123
00124
00125 connection = _dbus_connection_new_for_transport (transport);
00126 _dbus_transport_unref (transport);
00127 transport = NULL;
00128
00129 if (connection == NULL)
00130 {
00131 SERVER_UNLOCK (server);
00132 return FALSE;
00133 }
00134
00135
00136
00137
00138 new_connection_function = server->new_connection_function;
00139 new_connection_data = server->new_connection_data;
00140
00141 _dbus_server_ref_unlocked (server);
00142 SERVER_UNLOCK (server);
00143
00144 if (new_connection_function)
00145 {
00146 (* new_connection_function) (server, connection,
00147 new_connection_data);
00148 }
00149 dbus_server_unref (server);
00150
00151
00152 _dbus_connection_close_if_only_one_ref (connection);
00153 dbus_connection_unref (connection);
00154
00155 return TRUE;
00156 }
00157
00158 static dbus_bool_t
00159 socket_handle_watch (DBusWatch *watch,
00160 unsigned int flags,
00161 void *data)
00162 {
00163 DBusServer *server = data;
00164 DBusServerSocket *socket_server = data;
00165
00166 #ifndef DBUS_DISABLE_ASSERT
00167 int i;
00168 dbus_bool_t found = FALSE;
00169 #endif
00170
00171 SERVER_LOCK (server);
00172
00173 #ifndef DBUS_DISABLE_ASSERT
00174 for (i = 0 ; i < socket_server->n_fds ; i++)
00175 {
00176 if (socket_server->watch[i] == watch)
00177 found = TRUE;
00178 }
00179 _dbus_assert (found);
00180 #endif
00181
00182 _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00183
00184 if (flags & DBUS_WATCH_READABLE)
00185 {
00186 DBusSocket client_fd;
00187 DBusSocket listen_fd;
00188 int saved_errno;
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 saved_errno = _dbus_save_socket_errno ();
00198
00199 if (!_dbus_socket_is_valid (client_fd))
00200 {
00201
00202
00203 if (_dbus_get_is_errno_eagain_or_ewouldblock (saved_errno))
00204 _dbus_verbose ("No client available to accept after all\n");
00205 else
00206 _dbus_verbose ("Failed to accept a client connection: %s\n",
00207 _dbus_strerror (saved_errno));
00208
00209 SERVER_UNLOCK (server);
00210 }
00211 else
00212 {
00213 if (!handle_new_client_fd_and_unlock (server, client_fd))
00214 _dbus_verbose ("Rejected client connection due to lack of memory\n");
00215 }
00216 }
00217
00218 if (flags & DBUS_WATCH_ERROR)
00219 _dbus_verbose ("Error on server listening socket\n");
00220
00221 if (flags & DBUS_WATCH_HANGUP)
00222 _dbus_verbose ("Hangup on server listening socket\n");
00223
00224 return TRUE;
00225 }
00226
00227 static void
00228 socket_disconnect (DBusServer *server)
00229 {
00230 DBusServerSocket *socket_server = (DBusServerSocket*) server;
00231 int i;
00232
00233 HAVE_LOCK_CHECK (server);
00234
00235 for (i = 0 ; i < socket_server->n_fds ; i++)
00236 {
00237 if (socket_server->watch[i])
00238 {
00239 _dbus_server_remove_watch (server,
00240 socket_server->watch[i]);
00241 _dbus_watch_invalidate (socket_server->watch[i]);
00242 _dbus_watch_unref (socket_server->watch[i]);
00243 socket_server->watch[i] = NULL;
00244 }
00245
00246 _dbus_close_socket (socket_server->fds[i], NULL);
00247 _dbus_socket_invalidate (&socket_server->fds[i]);
00248 }
00249
00250 if (socket_server->socket_name != NULL)
00251 {
00252 DBusString tmp;
00253 _dbus_string_init_const (&tmp, socket_server->socket_name);
00254 _dbus_delete_file (&tmp, NULL);
00255 }
00256
00257 if (server->published_address)
00258 _dbus_daemon_unpublish_session_bus_address();
00259
00260 HAVE_LOCK_CHECK (server);
00261 }
00262
00263 static const DBusServerVTable socket_vtable = {
00264 socket_finalize,
00265 socket_disconnect
00266 };
00267
00284 DBusServer*
00285 _dbus_server_new_for_socket (DBusSocket *fds,
00286 int n_fds,
00287 const DBusString *address,
00288 DBusNonceFile *noncefile,
00289 DBusError *error)
00290 {
00291 DBusServerSocket *socket_server;
00292 DBusServer *server;
00293 int i;
00294
00295 socket_server = dbus_new0 (DBusServerSocket, 1);
00296 if (socket_server == NULL)
00297 goto failed_0;
00298
00299 socket_server->noncefile = noncefile;
00300
00301 socket_server->fds = dbus_new (DBusSocket, n_fds);
00302 if (!socket_server->fds)
00303 goto failed_0;
00304
00305 socket_server->watch = dbus_new0 (DBusWatch *, n_fds);
00306 if (!socket_server->watch)
00307 goto failed_1;
00308
00309 for (i = 0 ; i < n_fds ; i++)
00310 {
00311 DBusWatch *watch;
00312
00313 watch = _dbus_watch_new (_dbus_socket_get_pollable (fds[i]),
00314 DBUS_WATCH_READABLE,
00315 TRUE,
00316 socket_handle_watch, socket_server,
00317 NULL);
00318 if (watch == NULL)
00319 goto failed_2;
00320
00321 socket_server->n_fds++;
00322 socket_server->fds[i] = fds[i];
00323 socket_server->watch[i] = watch;
00324 }
00325
00326 if (!_dbus_server_init_base (&socket_server->base,
00327 &socket_vtable, address,
00328 error))
00329 goto failed_2;
00330
00331 server = (DBusServer*)socket_server;
00332
00333 SERVER_LOCK (server);
00334
00335 for (i = 0 ; i < n_fds ; i++)
00336 {
00337 if (!_dbus_server_add_watch (&socket_server->base,
00338 socket_server->watch[i]))
00339 {
00340 int j;
00341 for (j = 0 ; j < i ; j++)
00342 _dbus_server_remove_watch (server,
00343 socket_server->watch[j]);
00344
00345 SERVER_UNLOCK (server);
00346 _dbus_server_finalize_base (&socket_server->base);
00347 goto failed_2;
00348 }
00349 }
00350
00351 SERVER_UNLOCK (server);
00352
00353 _dbus_server_trace_ref (&socket_server->base, 0, 1, "new_for_socket");
00354 return (DBusServer*) socket_server;
00355
00356 failed_2:
00357 for (i = 0 ; i < n_fds ; i++)
00358 {
00359 if (socket_server->watch[i] != NULL)
00360 {
00361 _dbus_watch_unref (socket_server->watch[i]);
00362 socket_server->watch[i] = NULL;
00363 }
00364 }
00365 dbus_free (socket_server->watch);
00366
00367 failed_1:
00368 dbus_free (socket_server->fds);
00369
00370 failed_0:
00371 dbus_free (socket_server);
00372
00373 if (error != NULL && !dbus_error_is_set (error))
00374 _DBUS_SET_OOM (error);
00375
00376 return NULL;
00377 }
00378
00398 DBusServer*
00399 _dbus_server_new_for_tcp_socket (const char *host,
00400 const char *bind,
00401 const char *port,
00402 const char *family,
00403 DBusError *error,
00404 dbus_bool_t use_nonce)
00405 {
00406 DBusServer *server;
00407 DBusSocket *listen_fds = NULL;
00408 int nlisten_fds = 0, i;
00409 DBusString address;
00410 DBusString host_str;
00411 DBusString port_str;
00412 DBusNonceFile *noncefile;
00413
00414 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00415
00416 noncefile = NULL;
00417
00418 if (!_dbus_string_init (&address))
00419 {
00420 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00421 return NULL;
00422 }
00423
00424 if (!_dbus_string_init (&port_str))
00425 {
00426 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00427 goto failed_0;
00428 }
00429
00430 if (host == NULL)
00431 host = "localhost";
00432
00433 if (port == NULL)
00434 port = "0";
00435
00436 if (bind == NULL)
00437 bind = host;
00438 else if (strcmp (bind, "*") == 0)
00439 bind = NULL;
00440
00441 nlisten_fds =_dbus_listen_tcp_socket (bind, port, family,
00442 &port_str,
00443 &listen_fds, error);
00444 if (nlisten_fds <= 0)
00445 {
00446 _DBUS_ASSERT_ERROR_IS_SET(error);
00447 goto failed_1;
00448 }
00449
00450 _dbus_string_init_const (&host_str, host);
00451 if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") ||
00452 !_dbus_address_append_escaped (&address, &host_str) ||
00453 !_dbus_string_append (&address, ",port=") ||
00454 !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
00455 {
00456 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00457 goto failed_2;
00458 }
00459 if (family &&
00460 (!_dbus_string_append (&address, ",family=") ||
00461 !_dbus_string_append (&address, family)))
00462 {
00463 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00464 goto failed_2;
00465 }
00466
00467 if (use_nonce)
00468 {
00469 noncefile = dbus_new0 (DBusNonceFile, 1);
00470 if (noncefile == NULL)
00471 {
00472 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00473 goto failed_2;
00474 }
00475
00476 if (!_dbus_noncefile_create (noncefile, error))
00477 goto failed_3;
00478
00479 if (!_dbus_string_append (&address, ",noncefile=") ||
00480 !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile)))
00481 {
00482 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00483 goto failed_4;
00484 }
00485
00486 }
00487
00488 server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile, error);
00489 if (server == NULL)
00490 {
00491 if (noncefile != NULL)
00492 goto failed_4;
00493 else
00494 goto failed_2;
00495 }
00496
00497 _dbus_string_free (&port_str);
00498 _dbus_string_free (&address);
00499 dbus_free(listen_fds);
00500
00501 return server;
00502
00503 failed_4:
00504 _dbus_noncefile_delete (noncefile, NULL);
00505
00506 failed_3:
00507 dbus_free (noncefile);
00508
00509 failed_2:
00510 for (i = 0 ; i < nlisten_fds ; i++)
00511 _dbus_close_socket (listen_fds[i], NULL);
00512 dbus_free(listen_fds);
00513
00514 failed_1:
00515 _dbus_string_free (&port_str);
00516
00517 failed_0:
00518 _dbus_string_free (&address);
00519
00520 return NULL;
00521 }
00522
00535 DBusServerListenResult
00536 _dbus_server_listen_socket (DBusAddressEntry *entry,
00537 DBusServer **server_p,
00538 DBusError *error)
00539 {
00540 const char *method;
00541
00542 *server_p = NULL;
00543
00544 method = dbus_address_entry_get_method (entry);
00545
00546 if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0)
00547 {
00548 const char *host;
00549 const char *port;
00550 const char *bind;
00551 const char *family;
00552
00553 host = dbus_address_entry_get_value (entry, "host");
00554 bind = dbus_address_entry_get_value (entry, "bind");
00555 port = dbus_address_entry_get_value (entry, "port");
00556 family = dbus_address_entry_get_value (entry, "family");
00557
00558 *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
00559 family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE);
00560
00561 if (*server_p)
00562 {
00563 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00564 return DBUS_SERVER_LISTEN_OK;
00565 }
00566 else
00567 {
00568 _DBUS_ASSERT_ERROR_IS_SET(error);
00569 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00570 }
00571 }
00572 else
00573 {
00574 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00575 return DBUS_SERVER_LISTEN_NOT_HANDLED;
00576 }
00577 }
00578
00588 void
00589 _dbus_server_socket_own_filename (DBusServer *server,
00590 char *filename)
00591 {
00592 DBusServerSocket *socket_server = (DBusServerSocket*) server;
00593
00594 socket_server->socket_name = filename;
00595 }
00596
00597