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-internals.h"
00025 #include "dbus-server-unix.h"
00026 #include "dbus-transport-unix.h"
00027 #include "dbus-connection-internal.h"
00028 #include "dbus-string.h"
00029 #include <sys/types.h>
00030 #include <unistd.h>
00031
00043 typedef struct DBusServerUnix DBusServerUnix;
00044
00049 struct DBusServerUnix
00050 {
00051 DBusServer base;
00052 int fd;
00053 DBusWatch *watch;
00054 char *socket_name;
00055 };
00056
00057 static void
00058 unix_finalize (DBusServer *server)
00059 {
00060 DBusServerUnix *unix_server = (DBusServerUnix*) server;
00061
00062 _dbus_server_finalize_base (server);
00063
00064 if (unix_server->watch)
00065 {
00066 _dbus_watch_unref (unix_server->watch);
00067 unix_server->watch = NULL;
00068 }
00069
00070 dbus_free (unix_server->socket_name);
00071 dbus_free (server);
00072 }
00073
00082
00083 static dbus_bool_t
00084 handle_new_client_fd_and_unlock (DBusServer *server,
00085 int client_fd)
00086 {
00087 DBusConnection *connection;
00088 DBusTransport *transport;
00089 DBusNewConnectionFunction new_connection_function;
00090 void *new_connection_data;
00091
00092 _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
00093
00094 HAVE_LOCK_CHECK (server);
00095
00096 if (!_dbus_set_fd_nonblocking (client_fd, NULL))
00097 {
00098 SERVER_UNLOCK (server);
00099 return TRUE;
00100 }
00101
00102 transport = _dbus_transport_new_for_fd (client_fd, &server->guid_hex, NULL);
00103 if (transport == NULL)
00104 {
00105 close (client_fd);
00106 SERVER_UNLOCK (server);
00107 return FALSE;
00108 }
00109
00110 if (!_dbus_transport_set_auth_mechanisms (transport,
00111 (const char **) server->auth_mechanisms))
00112 {
00113 _dbus_transport_unref (transport);
00114 SERVER_UNLOCK (server);
00115 return FALSE;
00116 }
00117
00118
00119
00120
00121
00122 connection = _dbus_connection_new_for_transport (transport);
00123 _dbus_transport_unref (transport);
00124 transport = NULL;
00125
00126 if (connection == NULL)
00127 {
00128 SERVER_UNLOCK (server);
00129 return FALSE;
00130 }
00131
00132
00133
00134
00135 new_connection_function = server->new_connection_function;
00136 new_connection_data = server->new_connection_data;
00137
00138 _dbus_server_ref_unlocked (server);
00139 SERVER_UNLOCK (server);
00140
00141 if (new_connection_function)
00142 {
00143 (* new_connection_function) (server, connection,
00144 new_connection_data);
00145 dbus_server_unref (server);
00146 }
00147
00148
00149 dbus_connection_unref (connection);
00150
00151 return TRUE;
00152 }
00153
00154 static dbus_bool_t
00155 unix_handle_watch (DBusWatch *watch,
00156 unsigned int flags,
00157 void *data)
00158 {
00159 DBusServer *server = data;
00160 DBusServerUnix *unix_server = data;
00161
00162 SERVER_LOCK (server);
00163
00164 _dbus_assert (watch == unix_server->watch);
00165
00166 _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00167
00168 if (flags & DBUS_WATCH_READABLE)
00169 {
00170 int client_fd;
00171 int listen_fd;
00172
00173 listen_fd = dbus_watch_get_fd (watch);
00174
00175 client_fd = _dbus_accept (listen_fd);
00176
00177 if (client_fd < 0)
00178 {
00179
00180
00181 if (errno == EAGAIN || errno == EWOULDBLOCK)
00182 _dbus_verbose ("No client available to accept after all\n");
00183 else
00184 _dbus_verbose ("Failed to accept a client connection: %s\n",
00185 _dbus_strerror (errno));
00186
00187 SERVER_UNLOCK (server);
00188 }
00189 else
00190 {
00191 _dbus_fd_set_close_on_exec (client_fd);
00192
00193 if (!handle_new_client_fd_and_unlock (server, client_fd))
00194 _dbus_verbose ("Rejected client connection due to lack of memory\n");
00195 }
00196 }
00197
00198 if (flags & DBUS_WATCH_ERROR)
00199 _dbus_verbose ("Error on server listening socket\n");
00200
00201 if (flags & DBUS_WATCH_HANGUP)
00202 _dbus_verbose ("Hangup on server listening socket\n");
00203
00204 return TRUE;
00205 }
00206
00207 static void
00208 unix_disconnect (DBusServer *server)
00209 {
00210 DBusServerUnix *unix_server = (DBusServerUnix*) server;
00211
00212 HAVE_LOCK_CHECK (server);
00213
00214 if (unix_server->watch)
00215 {
00216 _dbus_server_remove_watch (server,
00217 unix_server->watch);
00218 _dbus_watch_unref (unix_server->watch);
00219 unix_server->watch = NULL;
00220 }
00221
00222 close (unix_server->fd);
00223 unix_server->fd = -1;
00224
00225 if (unix_server->socket_name != NULL)
00226 {
00227 DBusString tmp;
00228 _dbus_string_init_const (&tmp, unix_server->socket_name);
00229 _dbus_delete_file (&tmp, NULL);
00230 }
00231
00232 HAVE_LOCK_CHECK (server);
00233 }
00234
00235 static const DBusServerVTable unix_vtable = {
00236 unix_finalize,
00237 unix_disconnect
00238 };
00239
00253 DBusServer*
00254 _dbus_server_new_for_fd (int fd,
00255 const DBusString *address)
00256 {
00257 DBusServerUnix *unix_server;
00258 DBusServer *server;
00259 DBusWatch *watch;
00260
00261 unix_server = dbus_new0 (DBusServerUnix, 1);
00262 if (unix_server == NULL)
00263 return NULL;
00264
00265 watch = _dbus_watch_new (fd,
00266 DBUS_WATCH_READABLE,
00267 TRUE,
00268 unix_handle_watch, unix_server,
00269 NULL);
00270 if (watch == NULL)
00271 {
00272 dbus_free (unix_server);
00273 return NULL;
00274 }
00275
00276 if (!_dbus_server_init_base (&unix_server->base,
00277 &unix_vtable, address))
00278 {
00279 _dbus_watch_unref (watch);
00280 dbus_free (unix_server);
00281 return NULL;
00282 }
00283
00284 server = (DBusServer*) unix_server;
00285
00286 SERVER_LOCK (server);
00287
00288 if (!_dbus_server_add_watch (&unix_server->base,
00289 watch))
00290 {
00291 SERVER_UNLOCK (server);
00292 _dbus_server_finalize_base (&unix_server->base);
00293 _dbus_watch_unref (watch);
00294 dbus_free (unix_server);
00295 return NULL;
00296 }
00297
00298 unix_server->fd = fd;
00299 unix_server->watch = watch;
00300
00301 SERVER_UNLOCK (server);
00302
00303 return (DBusServer*) unix_server;
00304 }
00305
00314 DBusServer*
00315 _dbus_server_new_for_domain_socket (const char *path,
00316 dbus_bool_t abstract,
00317 DBusError *error)
00318 {
00319 DBusServer *server;
00320 DBusServerUnix *unix_server;
00321 int listen_fd;
00322 DBusString address;
00323 char *path_copy;
00324 DBusString path_str;
00325
00326 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00327
00328 if (!_dbus_string_init (&address))
00329 {
00330 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00331 return NULL;
00332 }
00333
00334 _dbus_string_init_const (&path_str, path);
00335 if ((abstract &&
00336 !_dbus_string_append (&address, "unix:abstract=")) ||
00337 (!abstract &&
00338 !_dbus_string_append (&address, "unix:path=")) ||
00339 !_dbus_address_append_escaped (&address, &path_str))
00340 {
00341 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00342 goto failed_0;
00343 }
00344
00345 path_copy = _dbus_strdup (path);
00346 if (path_copy == NULL)
00347 {
00348 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00349 goto failed_0;
00350 }
00351
00352 listen_fd = _dbus_listen_unix_socket (path, abstract, error);
00353 _dbus_fd_set_close_on_exec (listen_fd);
00354
00355 if (listen_fd < 0)
00356 {
00357 _DBUS_ASSERT_ERROR_IS_SET (error);
00358 goto failed_1;
00359 }
00360
00361 server = _dbus_server_new_for_fd (listen_fd, &address);
00362 if (server == NULL)
00363 {
00364 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00365 goto failed_2;
00366 }
00367
00368 unix_server = (DBusServerUnix*) server;
00369 unix_server->socket_name = path_copy;
00370
00371 _dbus_string_free (&address);
00372
00373 return server;
00374
00375 failed_2:
00376 _dbus_close (listen_fd, NULL);
00377 failed_1:
00378 dbus_free (path_copy);
00379 failed_0:
00380 _dbus_string_free (&address);
00381
00382 return NULL;
00383 }
00384
00394 DBusServer*
00395 _dbus_server_new_for_tcp_socket (const char *host,
00396 dbus_uint32_t port,
00397 DBusError *error)
00398 {
00399 DBusServer *server;
00400 int listen_fd;
00401 DBusString address;
00402 DBusString host_str;
00403
00404 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00405
00406 if (!_dbus_string_init (&address))
00407 {
00408 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00409 return NULL;
00410 }
00411
00412 if (host == NULL)
00413 host = "localhost";
00414
00415 _dbus_string_init_const (&host_str, host);
00416 if (!_dbus_string_append (&address, "tcp:host=") ||
00417 !_dbus_address_append_escaped (&address, &host_str) ||
00418 !_dbus_string_append (&address, ",port=") ||
00419 !_dbus_string_append_int (&address, port))
00420 {
00421 _dbus_string_free (&address);
00422 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00423 return NULL;
00424 }
00425
00426 listen_fd = _dbus_listen_tcp_socket (host, port, error);
00427 _dbus_fd_set_close_on_exec (listen_fd);
00428
00429 if (listen_fd < 0)
00430 {
00431 _dbus_string_free (&address);
00432 return NULL;
00433 }
00434
00435 server = _dbus_server_new_for_fd (listen_fd, &address);
00436 if (server == NULL)
00437 {
00438 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00439 close (listen_fd);
00440 _dbus_string_free (&address);
00441 return NULL;
00442 }
00443
00444 _dbus_string_free (&address);
00445
00446 return server;
00447
00448
00449 }
00450