D-Bus
1.6.8
|
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 <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-server-debug-pipe.h" 00028 #include "dbus-transport-socket.h" 00029 #include "dbus-connection-internal.h" 00030 #include "dbus-hash.h" 00031 #include "dbus-string.h" 00032 #include "dbus-protocol.h" 00033 00034 #ifdef DBUS_BUILD_TESTS 00035 00050 typedef struct DBusServerDebugPipe DBusServerDebugPipe; 00051 00056 struct DBusServerDebugPipe 00057 { 00058 DBusServer base; 00060 char *name; 00062 dbus_bool_t disconnected; 00063 }; 00064 00065 /* FIXME not threadsafe (right now the test suite doesn't use threads anyhow ) */ 00066 static DBusHashTable *server_pipe_hash; 00067 static int server_pipe_hash_refcount = 0; 00068 00069 static dbus_bool_t 00070 pipe_hash_ref (void) 00071 { 00072 if (!server_pipe_hash) 00073 { 00074 _dbus_assert (server_pipe_hash_refcount == 0); 00075 00076 server_pipe_hash = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL); 00077 00078 if (!server_pipe_hash) 00079 return FALSE; 00080 } 00081 00082 server_pipe_hash_refcount = 1; 00083 00084 return TRUE; 00085 } 00086 00087 static void 00088 pipe_hash_unref (void) 00089 { 00090 _dbus_assert (server_pipe_hash != NULL); 00091 _dbus_assert (server_pipe_hash_refcount > 0); 00092 00093 server_pipe_hash_refcount -= 1; 00094 if (server_pipe_hash_refcount == 0) 00095 { 00096 _dbus_hash_table_unref (server_pipe_hash); 00097 server_pipe_hash = NULL; 00098 } 00099 } 00100 00101 static void 00102 debug_finalize (DBusServer *server) 00103 { 00104 DBusServerDebugPipe *debug_server = (DBusServerDebugPipe*) server; 00105 00106 pipe_hash_unref (); 00107 00108 _dbus_server_finalize_base (server); 00109 00110 dbus_free (debug_server->name); 00111 dbus_free (server); 00112 } 00113 00114 static void 00115 debug_disconnect (DBusServer *server) 00116 { 00117 ((DBusServerDebugPipe*)server)->disconnected = TRUE; 00118 } 00119 00120 static DBusServerVTable debug_vtable = { 00121 debug_finalize, 00122 debug_disconnect 00123 }; 00124 00132 DBusServer* 00133 _dbus_server_debug_pipe_new (const char *server_name, 00134 DBusError *error) 00135 { 00136 DBusServerDebugPipe *debug_server; 00137 DBusString address; 00138 DBusString name_str; 00139 00140 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00141 00142 if (!pipe_hash_ref ()) 00143 return NULL; 00144 00145 if (_dbus_hash_table_lookup_string (server_pipe_hash, server_name) != NULL) 00146 { 00147 dbus_set_error (error, DBUS_ERROR_ADDRESS_IN_USE, NULL); 00148 pipe_hash_unref (); 00149 return NULL; 00150 } 00151 00152 debug_server = dbus_new0 (DBusServerDebugPipe, 1); 00153 if (debug_server == NULL) 00154 goto nomem_0; 00155 00156 if (!_dbus_string_init (&address)) 00157 goto nomem_1; 00158 00159 _dbus_string_init_const (&name_str, server_name); 00160 if (!_dbus_string_append (&address, "debug-pipe:name=") || 00161 !_dbus_address_append_escaped (&address, &name_str)) 00162 goto nomem_2; 00163 00164 debug_server->name = _dbus_strdup (server_name); 00165 if (debug_server->name == NULL) 00166 goto nomem_2; 00167 00168 if (!_dbus_server_init_base (&debug_server->base, 00169 &debug_vtable, &address)) 00170 goto nomem_3; 00171 00172 if (!_dbus_hash_table_insert_string (server_pipe_hash, 00173 debug_server->name, 00174 debug_server)) 00175 goto nomem_4; 00176 00177 _dbus_string_free (&address); 00178 00179 /* server keeps the pipe hash ref */ 00180 00181 _dbus_server_trace_ref (&debug_server->base, 0, 1, "debug_pipe_new"); 00182 return (DBusServer *)debug_server; 00183 00184 nomem_4: 00185 _dbus_server_finalize_base (&debug_server->base); 00186 nomem_3: 00187 dbus_free (debug_server->name); 00188 nomem_2: 00189 _dbus_string_free (&address); 00190 nomem_1: 00191 dbus_free (debug_server); 00192 nomem_0: 00193 pipe_hash_unref (); 00194 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00195 return NULL; 00196 } 00197 00207 DBusTransport* 00208 _dbus_transport_debug_pipe_new (const char *server_name, 00209 DBusError *error) 00210 { 00211 DBusTransport *client_transport; 00212 DBusTransport *server_transport; 00213 DBusConnection *connection; 00214 int client_fd, server_fd; 00215 DBusServer *server; 00216 DBusString address; 00217 00218 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00219 00220 if (server_pipe_hash == NULL) 00221 { 00222 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); 00223 return NULL; 00224 } 00225 00226 server = _dbus_hash_table_lookup_string (server_pipe_hash, 00227 server_name); 00228 if (server == NULL || 00229 ((DBusServerDebugPipe*)server)->disconnected) 00230 { 00231 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); 00232 return NULL; 00233 } 00234 00235 if (!_dbus_string_init (&address)) 00236 { 00237 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00238 return NULL; 00239 } 00240 00241 if (!_dbus_string_append (&address, "debug-pipe:name=") || 00242 !_dbus_string_append (&address, server_name)) 00243 { 00244 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00245 _dbus_string_free (&address); 00246 return NULL; 00247 } 00248 00249 if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE, 00250 NULL)) 00251 { 00252 _dbus_verbose ("failed to create full duplex pipe\n"); 00253 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe"); 00254 _dbus_string_free (&address); 00255 return NULL; 00256 } 00257 00258 client_transport = _dbus_transport_new_for_socket (client_fd, 00259 NULL, &address); 00260 if (client_transport == NULL) 00261 { 00262 _dbus_close_socket (client_fd, NULL); 00263 _dbus_close_socket (server_fd, NULL); 00264 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00265 _dbus_string_free (&address); 00266 return NULL; 00267 } 00268 00269 _dbus_string_free (&address); 00270 00271 client_fd = -1; 00272 00273 server_transport = _dbus_transport_new_for_socket (server_fd, 00274 &server->guid_hex, NULL); 00275 if (server_transport == NULL) 00276 { 00277 _dbus_transport_unref (client_transport); 00278 _dbus_close_socket (server_fd, NULL); 00279 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00280 return NULL; 00281 } 00282 00283 server_fd = -1; 00284 00285 if (!_dbus_transport_set_auth_mechanisms (server_transport, 00286 (const char**) server->auth_mechanisms)) 00287 { 00288 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00289 _dbus_transport_unref (server_transport); 00290 _dbus_transport_unref (client_transport); 00291 return NULL; 00292 } 00293 00294 connection = _dbus_connection_new_for_transport (server_transport); 00295 _dbus_transport_unref (server_transport); 00296 server_transport = NULL; 00297 00298 if (connection == NULL) 00299 { 00300 _dbus_transport_unref (client_transport); 00301 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00302 return NULL; 00303 } 00304 00305 /* See if someone wants to handle this new connection, 00306 * self-referencing for paranoia 00307 */ 00308 if (server->new_connection_function) 00309 { 00310 dbus_server_ref (server); 00311 (* server->new_connection_function) (server, connection, 00312 server->new_connection_data); 00313 dbus_server_unref (server); 00314 } 00315 00316 /* If no one grabbed a reference, the connection will die, 00317 * and the client transport will get an immediate disconnect 00318 */ 00319 _dbus_connection_close_if_only_one_ref (connection); 00320 dbus_connection_unref (connection); 00321 00322 return client_transport; 00323 } 00324 00336 DBusServerListenResult 00337 _dbus_server_listen_debug_pipe (DBusAddressEntry *entry, 00338 DBusServer **server_p, 00339 DBusError *error) 00340 { 00341 const char *method; 00342 00343 *server_p = NULL; 00344 00345 method = dbus_address_entry_get_method (entry); 00346 00347 if (strcmp (method, "debug-pipe") == 0) 00348 { 00349 const char *name = dbus_address_entry_get_value (entry, "name"); 00350 00351 if (name == NULL) 00352 { 00353 _dbus_set_bad_address(error, "debug-pipe", "name", 00354 NULL); 00355 return DBUS_SERVER_LISTEN_BAD_ADDRESS; 00356 } 00357 00358 *server_p = _dbus_server_debug_pipe_new (name, error); 00359 00360 if (*server_p) 00361 { 00362 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00363 return DBUS_SERVER_LISTEN_OK; 00364 } 00365 else 00366 { 00367 _DBUS_ASSERT_ERROR_IS_SET(error); 00368 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; 00369 } 00370 } 00371 else 00372 { 00373 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00374 return DBUS_SERVER_LISTEN_NOT_HANDLED; 00375 } 00376 } 00377 00386 DBusTransportOpenResult 00387 _dbus_transport_open_debug_pipe (DBusAddressEntry *entry, 00388 DBusTransport **transport_p, 00389 DBusError *error) 00390 { 00391 const char *method; 00392 00393 method = dbus_address_entry_get_method (entry); 00394 _dbus_assert (method != NULL); 00395 00396 if (strcmp (method, "debug-pipe") == 0) 00397 { 00398 const char *name = dbus_address_entry_get_value (entry, "name"); 00399 00400 if (name == NULL) 00401 { 00402 _dbus_set_bad_address (error, "debug-pipe", "name", 00403 NULL); 00404 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 00405 } 00406 00407 *transport_p = _dbus_transport_debug_pipe_new (name, error); 00408 00409 if (*transport_p == NULL) 00410 { 00411 _DBUS_ASSERT_ERROR_IS_SET (error); 00412 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 00413 } 00414 else 00415 { 00416 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00417 return DBUS_TRANSPORT_OPEN_OK; 00418 } 00419 } 00420 else 00421 { 00422 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00423 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 00424 } 00425 } 00426 00427 00430 #endif /* DBUS_BUILD_TESTS */ 00431