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