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_invalidate (socket_server->watch[i]);
00240 _dbus_watch_unref (socket_server->watch[i]);
00241 socket_server->watch[i] = NULL;
00242 }
00243
00244 _dbus_close_socket (socket_server->fds[i], NULL);
00245 socket_server->fds[i] = -1;
00246 }
00247
00248 if (socket_server->socket_name != NULL)
00249 {
00250 DBusString tmp;
00251 _dbus_string_init_const (&tmp, socket_server->socket_name);
00252 _dbus_delete_file (&tmp, NULL);
00253 }
00254
00255 if (server->published_address)
00256 _dbus_daemon_unpublish_session_bus_address();
00257
00258 HAVE_LOCK_CHECK (server);
00259 }
00260
00261 static const DBusServerVTable socket_vtable = {
00262 socket_finalize,
00263 socket_disconnect
00264 };
00265
00281 DBusServer*
00282 _dbus_server_new_for_socket (int *fds,
00283 int n_fds,
00284 const DBusString *address,
00285 DBusNonceFile *noncefile)
00286 {
00287 DBusServerSocket *socket_server;
00288 DBusServer *server;
00289 int i;
00290
00291 socket_server = dbus_new0 (DBusServerSocket, 1);
00292 if (socket_server == NULL)
00293 return NULL;
00294
00295 socket_server->noncefile = noncefile;
00296
00297 socket_server->fds = dbus_new (int, n_fds);
00298 if (!socket_server->fds)
00299 goto failed_0;
00300
00301 socket_server->watch = dbus_new0 (DBusWatch *, n_fds);
00302 if (!socket_server->watch)
00303 goto failed_1;
00304
00305 for (i = 0 ; i < n_fds ; i++)
00306 {
00307 DBusWatch *watch;
00308
00309 watch = _dbus_watch_new (fds[i],
00310 DBUS_WATCH_READABLE,
00311 TRUE,
00312 socket_handle_watch, socket_server,
00313 NULL);
00314 if (watch == NULL)
00315 goto failed_2;
00316
00317 socket_server->n_fds++;
00318 socket_server->fds[i] = fds[i];
00319 socket_server->watch[i] = watch;
00320 }
00321
00322 if (!_dbus_server_init_base (&socket_server->base,
00323 &socket_vtable, address))
00324 goto failed_2;
00325
00326 server = (DBusServer*)socket_server;
00327
00328 SERVER_LOCK (server);
00329
00330 for (i = 0 ; i < n_fds ; i++)
00331 {
00332 if (!_dbus_server_add_watch (&socket_server->base,
00333 socket_server->watch[i]))
00334 {
00335 int j;
00336 for (j = 0 ; j < i ; j++)
00337 _dbus_server_remove_watch (server,
00338 socket_server->watch[j]);
00339
00340 SERVER_UNLOCK (server);
00341 _dbus_server_finalize_base (&socket_server->base);
00342 goto failed_2;
00343 }
00344 }
00345
00346 SERVER_UNLOCK (server);
00347
00348 return (DBusServer*) socket_server;
00349
00350 failed_2:
00351 for (i = 0 ; i < n_fds ; i++)
00352 {
00353 if (socket_server->watch[i] != NULL)
00354 {
00355 _dbus_watch_unref (socket_server->watch[i]);
00356 socket_server->watch[i] = NULL;
00357 }
00358 }
00359 dbus_free (socket_server->watch);
00360
00361 failed_1:
00362 dbus_free (socket_server->fds);
00363
00364 failed_0:
00365 dbus_free (socket_server);
00366 return NULL;
00367 }
00368
00388 DBusServer*
00389 _dbus_server_new_for_tcp_socket (const char *host,
00390 const char *bind,
00391 const char *port,
00392 const char *family,
00393 DBusError *error,
00394 dbus_bool_t use_nonce)
00395 {
00396 DBusServer *server;
00397 int *listen_fds = NULL;
00398 int nlisten_fds = 0, i;
00399 DBusString address;
00400 DBusString host_str;
00401 DBusString port_str;
00402 DBusNonceFile *noncefile;
00403
00404 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00405
00406 noncefile = NULL;
00407
00408 if (!_dbus_string_init (&address))
00409 {
00410 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00411 return NULL;
00412 }
00413
00414 if (!_dbus_string_init (&port_str))
00415 {
00416 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00417 goto failed_0;
00418 }
00419
00420 if (host == NULL)
00421 host = "localhost";
00422
00423 if (port == NULL)
00424 port = "0";
00425
00426 if (bind == NULL)
00427 bind = host;
00428 else if (strcmp (bind, "*") == 0)
00429 bind = NULL;
00430
00431 nlisten_fds =_dbus_listen_tcp_socket (bind, port, family,
00432 &port_str,
00433 &listen_fds, error);
00434 if (nlisten_fds <= 0)
00435 {
00436 _DBUS_ASSERT_ERROR_IS_SET(error);
00437 goto failed_1;
00438 }
00439
00440 _dbus_string_init_const (&host_str, host);
00441 if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") ||
00442 !_dbus_address_append_escaped (&address, &host_str) ||
00443 !_dbus_string_append (&address, ",port=") ||
00444 !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
00445 {
00446 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00447 goto failed_2;
00448 }
00449 if (family &&
00450 (!_dbus_string_append (&address, ",family=") ||
00451 !_dbus_string_append (&address, family)))
00452 {
00453 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00454 goto failed_2;
00455 }
00456
00457 if (use_nonce)
00458 {
00459 noncefile = dbus_new0 (DBusNonceFile, 1);
00460 if (noncefile == NULL)
00461 {
00462 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00463 goto failed_2;
00464 }
00465
00466 if (!_dbus_noncefile_create (noncefile, error))
00467 goto failed_3;
00468
00469 if (!_dbus_string_append (&address, ",noncefile=") ||
00470 !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile)))
00471 {
00472 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00473 goto failed_4;
00474 }
00475
00476 }
00477
00478 server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile);
00479 if (server == NULL)
00480 {
00481 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00482 goto failed_4;
00483 }
00484
00485 _dbus_string_free (&port_str);
00486 _dbus_string_free (&address);
00487 dbus_free(listen_fds);
00488
00489 return server;
00490
00491 failed_4:
00492 _dbus_noncefile_delete (noncefile, NULL);
00493
00494 failed_3:
00495 dbus_free (noncefile);
00496
00497 failed_2:
00498 for (i = 0 ; i < nlisten_fds ; i++)
00499 _dbus_close_socket (listen_fds[i], NULL);
00500 dbus_free(listen_fds);
00501
00502 failed_1:
00503 _dbus_string_free (&port_str);
00504
00505 failed_0:
00506 _dbus_string_free (&address);
00507
00508 return NULL;
00509 }
00510
00523 DBusServerListenResult
00524 _dbus_server_listen_socket (DBusAddressEntry *entry,
00525 DBusServer **server_p,
00526 DBusError *error)
00527 {
00528 const char *method;
00529
00530 *server_p = NULL;
00531
00532 method = dbus_address_entry_get_method (entry);
00533
00534 if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0)
00535 {
00536 const char *host;
00537 const char *port;
00538 const char *bind;
00539 const char *family;
00540
00541 host = dbus_address_entry_get_value (entry, "host");
00542 bind = dbus_address_entry_get_value (entry, "bind");
00543 port = dbus_address_entry_get_value (entry, "port");
00544 family = dbus_address_entry_get_value (entry, "family");
00545
00546 *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
00547 family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE);
00548
00549 if (*server_p)
00550 {
00551 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00552 return DBUS_SERVER_LISTEN_OK;
00553 }
00554 else
00555 {
00556 _DBUS_ASSERT_ERROR_IS_SET(error);
00557 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00558 }
00559 }
00560 else
00561 {
00562 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00563 return DBUS_SERVER_LISTEN_NOT_HANDLED;
00564 }
00565 }
00566
00576 void
00577 _dbus_server_socket_own_filename (DBusServer *server,
00578 char *filename)
00579 {
00580 DBusServerSocket *socket_server = (DBusServerSocket*) server;
00581
00582 socket_server->socket_name = filename;
00583 }
00584
00585