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 if (unix_server->watch)
00063 _dbus_watch_unref (unix_server->watch);
00064
00065 dbus_free (unix_server->socket_name);
00066
00067 _dbus_server_finalize_base (server);
00068
00069 dbus_free (server);
00070 }
00071
00077
00078 static dbus_bool_t
00079 handle_new_client_fd (DBusServer *server,
00080 int client_fd)
00081 {
00082 DBusConnection *connection;
00083 DBusTransport *transport;
00084
00085 _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
00086
00087 if (!_dbus_set_fd_nonblocking (client_fd, NULL))
00088 return TRUE;
00089
00090 transport = _dbus_transport_new_for_fd (client_fd, TRUE, NULL);
00091 if (transport == NULL)
00092 {
00093 close (client_fd);
00094 return FALSE;
00095 }
00096
00097 if (!_dbus_transport_set_auth_mechanisms (transport,
00098 (const char **) server->auth_mechanisms))
00099 {
00100 _dbus_transport_unref (transport);
00101 return FALSE;
00102 }
00103
00104
00105
00106
00107
00108 connection = _dbus_connection_new_for_transport (transport);
00109 _dbus_transport_unref (transport);
00110
00111 if (connection == NULL)
00112 return FALSE;
00113
00114
00115
00116
00117 if (server->new_connection_function)
00118 {
00119 dbus_server_ref (server);
00120
00121 (* server->new_connection_function) (server, connection,
00122 server->new_connection_data);
00123 dbus_server_unref (server);
00124 }
00125
00126
00127 dbus_connection_unref (connection);
00128
00129 return TRUE;
00130 }
00131
00132 static dbus_bool_t
00133 unix_handle_watch (DBusWatch *watch,
00134 unsigned int flags,
00135 void *data)
00136 {
00137 DBusServer *server = data;
00138 DBusServerUnix *unix_server = data;
00139
00140 _dbus_assert (watch == unix_server->watch);
00141
00142 _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
00143
00144 if (flags & DBUS_WATCH_READABLE)
00145 {
00146 int client_fd;
00147 int listen_fd;
00148
00149 listen_fd = dbus_watch_get_fd (watch);
00150
00151 client_fd = _dbus_accept (listen_fd);
00152
00153 if (client_fd < 0)
00154 {
00155
00156
00157 if (errno == EAGAIN || errno == EWOULDBLOCK)
00158 _dbus_verbose ("No client available to accept after all\n");
00159 else
00160 _dbus_verbose ("Failed to accept a client connection: %s\n",
00161 _dbus_strerror (errno));
00162 }
00163 else
00164 {
00165 _dbus_fd_set_close_on_exec (client_fd);
00166
00167 if (!handle_new_client_fd (server, client_fd))
00168 _dbus_verbose ("Rejected client connection due to lack of memory\n");
00169 }
00170 }
00171
00172 if (flags & DBUS_WATCH_ERROR)
00173 _dbus_verbose ("Error on server listening socket\n");
00174
00175 if (flags & DBUS_WATCH_HANGUP)
00176 _dbus_verbose ("Hangup on server listening socket\n");
00177
00178 return TRUE;
00179 }
00180
00181 static void
00182 unix_disconnect (DBusServer *server)
00183 {
00184 DBusServerUnix *unix_server = (DBusServerUnix*) server;
00185
00186 if (unix_server->watch)
00187 {
00188 _dbus_server_remove_watch (server,
00189 unix_server->watch);
00190 _dbus_watch_unref (unix_server->watch);
00191 unix_server->watch = NULL;
00192 }
00193
00194 close (unix_server->fd);
00195 unix_server->fd = -1;
00196
00197 if (unix_server->socket_name != NULL)
00198 {
00199 DBusString tmp;
00200 _dbus_string_init_const (&tmp, unix_server->socket_name);
00201 _dbus_delete_file (&tmp, NULL);
00202 }
00203 }
00204
00205 static DBusServerVTable unix_vtable = {
00206 unix_finalize,
00207 unix_disconnect
00208 };
00209
00223 DBusServer*
00224 _dbus_server_new_for_fd (int fd,
00225 const DBusString *address)
00226 {
00227 DBusServerUnix *unix_server;
00228 DBusWatch *watch;
00229
00230 unix_server = dbus_new0 (DBusServerUnix, 1);
00231 if (unix_server == NULL)
00232 return NULL;
00233
00234 watch = _dbus_watch_new (fd,
00235 DBUS_WATCH_READABLE,
00236 TRUE,
00237 unix_handle_watch, unix_server,
00238 NULL);
00239 if (watch == NULL)
00240 {
00241 dbus_free (unix_server);
00242 return NULL;
00243 }
00244
00245 if (!_dbus_server_init_base (&unix_server->base,
00246 &unix_vtable, address))
00247 {
00248 _dbus_watch_unref (watch);
00249 dbus_free (unix_server);
00250 return NULL;
00251 }
00252
00253 if (!_dbus_server_add_watch (&unix_server->base,
00254 watch))
00255 {
00256 _dbus_server_finalize_base (&unix_server->base);
00257 _dbus_watch_unref (watch);
00258 dbus_free (unix_server);
00259 return NULL;
00260 }
00261
00262 unix_server->fd = fd;
00263 unix_server->watch = watch;
00264
00265 return (DBusServer*) unix_server;
00266 }
00267
00276 DBusServer*
00277 _dbus_server_new_for_domain_socket (const char *path,
00278 dbus_bool_t abstract,
00279 DBusError *error)
00280 {
00281 DBusServer *server;
00282 DBusServerUnix *unix_server;
00283 int listen_fd;
00284 DBusString address;
00285 char *path_copy;
00286
00287 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00288
00289 if (!_dbus_string_init (&address))
00290 {
00291 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00292 return NULL;
00293 }
00294
00295 if ((abstract &&
00296 !_dbus_string_append (&address, "unix:abstract=")) ||
00297 (!abstract &&
00298 !_dbus_string_append (&address, "unix:path=")) ||
00299 !_dbus_string_append (&address, path))
00300 {
00301 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00302 goto failed_0;
00303 }
00304
00305 path_copy = _dbus_strdup (path);
00306 if (path_copy == NULL)
00307 {
00308 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00309 goto failed_0;
00310 }
00311
00312 listen_fd = _dbus_listen_unix_socket (path, abstract, error);
00313 _dbus_fd_set_close_on_exec (listen_fd);
00314
00315 if (listen_fd < 0)
00316 {
00317 _DBUS_ASSERT_ERROR_IS_SET (error);
00318 goto failed_1;
00319 }
00320
00321 server = _dbus_server_new_for_fd (listen_fd, &address);
00322 if (server == NULL)
00323 {
00324 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00325 goto failed_2;
00326 }
00327
00328 unix_server = (DBusServerUnix*) server;
00329 unix_server->socket_name = path_copy;
00330
00331 _dbus_string_free (&address);
00332
00333 return server;
00334
00335 failed_2:
00336 _dbus_close (listen_fd, NULL);
00337 failed_1:
00338 dbus_free (path_copy);
00339 failed_0:
00340 _dbus_string_free (&address);
00341
00342 return NULL;
00343 }
00344
00354 DBusServer*
00355 _dbus_server_new_for_tcp_socket (const char *host,
00356 dbus_uint32_t port,
00357 DBusError *error)
00358 {
00359 DBusServer *server;
00360 int listen_fd;
00361 DBusString address;
00362
00363 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00364
00365 if (!_dbus_string_init (&address))
00366 {
00367 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00368 return NULL;
00369 }
00370
00371 if (!_dbus_string_append (&address, "tcp:host=") ||
00372 !_dbus_string_append (&address, host) ||
00373 !_dbus_string_append (&address, ",port=") ||
00374 !_dbus_string_append_int (&address, port))
00375 {
00376 _dbus_string_free (&address);
00377 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00378 return NULL;
00379 }
00380
00381 listen_fd = _dbus_listen_tcp_socket (host, port, error);
00382 _dbus_fd_set_close_on_exec (listen_fd);
00383
00384 if (listen_fd < 0)
00385 {
00386 _dbus_string_free (&address);
00387 return NULL;
00388 }
00389
00390 server = _dbus_server_new_for_fd (listen_fd, &address);
00391 if (server == NULL)
00392 {
00393 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00394 close (listen_fd);
00395 _dbus_string_free (&address);
00396 return NULL;
00397 }
00398
00399 _dbus_string_free (&address);
00400
00401 return server;
00402
00403
00404 }
00405