D-Bus 1.2.24
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-server-debug-pipe.c In-proc debug server implementation 00003 * 00004 * Copyright (C) 2003 CodeFactory AB 00005 * Copyright (C) 2003, 2004 Red Hat, Inc. 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include "dbus-internals.h" 00026 #include "dbus-server-debug-pipe.h" 00027 #include "dbus-transport-socket.h" 00028 #include "dbus-connection-internal.h" 00029 #include "dbus-hash.h" 00030 #include "dbus-string.h" 00031 #include "dbus-protocol.h" 00032 00033 #ifdef DBUS_BUILD_TESTS 00034 00049 typedef struct DBusServerDebugPipe DBusServerDebugPipe; 00050 00055 struct DBusServerDebugPipe 00056 { 00057 DBusServer base; 00059 char *name; 00061 dbus_bool_t disconnected; 00062 }; 00063 00064 /* FIXME not threadsafe (right now the test suite doesn't use threads anyhow ) */ 00065 static DBusHashTable *server_pipe_hash; 00066 static int server_pipe_hash_refcount = 0; 00067 00068 static dbus_bool_t 00069 pipe_hash_ref (void) 00070 { 00071 if (!server_pipe_hash) 00072 { 00073 _dbus_assert (server_pipe_hash_refcount == 0); 00074 00075 server_pipe_hash = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL); 00076 00077 if (!server_pipe_hash) 00078 return FALSE; 00079 } 00080 00081 server_pipe_hash_refcount = 1; 00082 00083 return TRUE; 00084 } 00085 00086 static void 00087 pipe_hash_unref (void) 00088 { 00089 _dbus_assert (server_pipe_hash != NULL); 00090 _dbus_assert (server_pipe_hash_refcount > 0); 00091 00092 server_pipe_hash_refcount -= 1; 00093 if (server_pipe_hash_refcount == 0) 00094 { 00095 _dbus_hash_table_unref (server_pipe_hash); 00096 server_pipe_hash = NULL; 00097 } 00098 } 00099 00100 static void 00101 debug_finalize (DBusServer *server) 00102 { 00103 DBusServerDebugPipe *debug_server = (DBusServerDebugPipe*) server; 00104 00105 pipe_hash_unref (); 00106 00107 _dbus_server_finalize_base (server); 00108 00109 dbus_free (debug_server->name); 00110 dbus_free (server); 00111 } 00112 00113 static void 00114 debug_disconnect (DBusServer *server) 00115 { 00116 ((DBusServerDebugPipe*)server)->disconnected = TRUE; 00117 } 00118 00119 static DBusServerVTable debug_vtable = { 00120 debug_finalize, 00121 debug_disconnect 00122 }; 00123 00131 DBusServer* 00132 _dbus_server_debug_pipe_new (const char *server_name, 00133 DBusError *error) 00134 { 00135 DBusServerDebugPipe *debug_server; 00136 DBusString address; 00137 DBusString name_str; 00138 00139 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00140 00141 if (!pipe_hash_ref ()) 00142 return NULL; 00143 00144 if (_dbus_hash_table_lookup_string (server_pipe_hash, server_name) != NULL) 00145 { 00146 dbus_set_error (error, DBUS_ERROR_ADDRESS_IN_USE, NULL); 00147 pipe_hash_unref (); 00148 return NULL; 00149 } 00150 00151 debug_server = dbus_new0 (DBusServerDebugPipe, 1); 00152 if (debug_server == NULL) 00153 goto nomem_0; 00154 00155 if (!_dbus_string_init (&address)) 00156 goto nomem_1; 00157 00158 _dbus_string_init_const (&name_str, server_name); 00159 if (!_dbus_string_append (&address, "debug-pipe:name=") || 00160 !_dbus_address_append_escaped (&address, &name_str)) 00161 goto nomem_2; 00162 00163 debug_server->name = _dbus_strdup (server_name); 00164 if (debug_server->name == NULL) 00165 goto nomem_2; 00166 00167 if (!_dbus_server_init_base (&debug_server->base, 00168 &debug_vtable, &address)) 00169 goto nomem_3; 00170 00171 if (!_dbus_hash_table_insert_string (server_pipe_hash, 00172 debug_server->name, 00173 debug_server)) 00174 goto nomem_4; 00175 00176 _dbus_string_free (&address); 00177 00178 /* server keeps the pipe hash ref */ 00179 00180 return (DBusServer *)debug_server; 00181 00182 nomem_4: 00183 _dbus_server_finalize_base (&debug_server->base); 00184 nomem_3: 00185 dbus_free (debug_server->name); 00186 nomem_2: 00187 _dbus_string_free (&address); 00188 nomem_1: 00189 dbus_free (debug_server); 00190 nomem_0: 00191 pipe_hash_unref (); 00192 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00193 return NULL; 00194 } 00195 00205 DBusTransport* 00206 _dbus_transport_debug_pipe_new (const char *server_name, 00207 DBusError *error) 00208 { 00209 DBusTransport *client_transport; 00210 DBusTransport *server_transport; 00211 DBusConnection *connection; 00212 int client_fd, server_fd; 00213 DBusServer *server; 00214 DBusString address; 00215 00216 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00217 00218 if (server_pipe_hash == NULL) 00219 { 00220 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); 00221 return NULL; 00222 } 00223 00224 server = _dbus_hash_table_lookup_string (server_pipe_hash, 00225 server_name); 00226 if (server == NULL || 00227 ((DBusServerDebugPipe*)server)->disconnected) 00228 { 00229 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); 00230 return NULL; 00231 } 00232 00233 if (!_dbus_string_init (&address)) 00234 { 00235 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00236 return NULL; 00237 } 00238 00239 if (!_dbus_string_append (&address, "debug-pipe:name=") || 00240 !_dbus_string_append (&address, server_name)) 00241 { 00242 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00243 _dbus_string_free (&address); 00244 return NULL; 00245 } 00246 00247 if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE, 00248 NULL)) 00249 { 00250 _dbus_verbose ("failed to create full duplex pipe\n"); 00251 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe"); 00252 _dbus_string_free (&address); 00253 return NULL; 00254 } 00255 00256 _dbus_fd_set_close_on_exec (client_fd); 00257 _dbus_fd_set_close_on_exec (server_fd); 00258 00259 client_transport = _dbus_transport_new_for_socket (client_fd, 00260 NULL, &address); 00261 if (client_transport == NULL) 00262 { 00263 _dbus_close_socket (client_fd, NULL); 00264 _dbus_close_socket (server_fd, NULL); 00265 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00266 _dbus_string_free (&address); 00267 return NULL; 00268 } 00269 00270 _dbus_string_free (&address); 00271 00272 client_fd = -1; 00273 00274 server_transport = _dbus_transport_new_for_socket (server_fd, 00275 &server->guid_hex, NULL); 00276 if (server_transport == NULL) 00277 { 00278 _dbus_transport_unref (client_transport); 00279 _dbus_close_socket (server_fd, NULL); 00280 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00281 return NULL; 00282 } 00283 00284 server_fd = -1; 00285 00286 if (!_dbus_transport_set_auth_mechanisms (server_transport, 00287 (const char**) server->auth_mechanisms)) 00288 { 00289 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00290 _dbus_transport_unref (server_transport); 00291 _dbus_transport_unref (client_transport); 00292 return NULL; 00293 } 00294 00295 connection = _dbus_connection_new_for_transport (server_transport); 00296 _dbus_transport_unref (server_transport); 00297 server_transport = NULL; 00298 00299 if (connection == NULL) 00300 { 00301 _dbus_transport_unref (client_transport); 00302 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00303 return NULL; 00304 } 00305 00306 /* See if someone wants to handle this new connection, 00307 * self-referencing for paranoia 00308 */ 00309 if (server->new_connection_function) 00310 { 00311 dbus_server_ref (server); 00312 (* server->new_connection_function) (server, connection, 00313 server->new_connection_data); 00314 dbus_server_unref (server); 00315 } 00316 00317 /* If no one grabbed a reference, the connection will die, 00318 * and the client transport will get an immediate disconnect 00319 */ 00320 _dbus_connection_close_if_only_one_ref (connection); 00321 dbus_connection_unref (connection); 00322 00323 return client_transport; 00324 } 00325 00337 DBusServerListenResult 00338 _dbus_server_listen_debug_pipe (DBusAddressEntry *entry, 00339 DBusServer **server_p, 00340 DBusError *error) 00341 { 00342 const char *method; 00343 00344 *server_p = NULL; 00345 00346 method = dbus_address_entry_get_method (entry); 00347 00348 if (strcmp (method, "debug-pipe") == 0) 00349 { 00350 const char *name = dbus_address_entry_get_value (entry, "name"); 00351 00352 if (name == NULL) 00353 { 00354 _dbus_set_bad_address(error, "debug-pipe", "name", 00355 NULL); 00356 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00357 } 00358 00359 *server_p = _dbus_server_debug_pipe_new (name, error); 00360 00361 if (*server_p) 00362 { 00363 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00364 return DBUS_SERVER_LISTEN_OK; 00365 } 00366 else 00367 { 00368 _DBUS_ASSERT_ERROR_IS_SET(error); 00369 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00370 } 00371 } 00372 else 00373 { 00374 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00375 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00376 } 00377 } 00378 00387 DBusTransportOpenResult 00388 _dbus_transport_open_debug_pipe (DBusAddressEntry *entry, 00389 DBusTransport **transport_p, 00390 DBusError *error) 00391 { 00392 const char *method; 00393 00394 method = dbus_address_entry_get_method (entry); 00395 _dbus_assert (method != NULL); 00396 00397 if (strcmp (method, "debug-pipe") == 0) 00398 { 00399 const char *name = dbus_address_entry_get_value (entry, "name"); 00400 00401 if (name == NULL) 00402 { 00403 _dbus_set_bad_address (error, "debug-pipe", "name", 00404 NULL); 00405 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00406 } 00407 00408 *transport_p = _dbus_transport_debug_pipe_new (name, error); 00409 00410 if (*transport_p == NULL) 00411 { 00412 _DBUS_ASSERT_ERROR_IS_SET (error); 00413 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00414 } 00415 else 00416 { 00417 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00418 return DBUS_TRANSPORT_OPEN_OK; 00419 } 00420 } 00421 else 00422 { 00423 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00424 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00425 } 00426 } 00427 00428 00431 #endif /* DBUS_BUILD_TESTS */ 00432