00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
00180
00181 return (DBusServer *)debug_server;
00182
00183 nomem_4:
00184 _dbus_server_finalize_base (&debug_server->base);
00185 nomem_3:
00186 dbus_free (debug_server->name);
00187 nomem_2:
00188 _dbus_string_free (&address);
00189 nomem_1:
00190 dbus_free (debug_server);
00191 nomem_0:
00192 pipe_hash_unref ();
00193 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00194 return NULL;
00195 }
00196
00206 DBusTransport*
00207 _dbus_transport_debug_pipe_new (const char *server_name,
00208 DBusError *error)
00209 {
00210 DBusTransport *client_transport;
00211 DBusTransport *server_transport;
00212 DBusConnection *connection;
00213 int client_fd, server_fd;
00214 DBusServer *server;
00215 DBusString address;
00216
00217 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00218
00219 if (server_pipe_hash == NULL)
00220 {
00221 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
00222 return NULL;
00223 }
00224
00225 server = _dbus_hash_table_lookup_string (server_pipe_hash,
00226 server_name);
00227 if (server == NULL ||
00228 ((DBusServerDebugPipe*)server)->disconnected)
00229 {
00230 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
00231 return NULL;
00232 }
00233
00234 if (!_dbus_string_init (&address))
00235 {
00236 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00237 return NULL;
00238 }
00239
00240 if (!_dbus_string_append (&address, "debug-pipe:name=") ||
00241 !_dbus_string_append (&address, server_name))
00242 {
00243 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00244 _dbus_string_free (&address);
00245 return NULL;
00246 }
00247
00248 if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE,
00249 NULL))
00250 {
00251 _dbus_verbose ("failed to create full duplex pipe\n");
00252 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe");
00253 _dbus_string_free (&address);
00254 return NULL;
00255 }
00256
00257 client_transport = _dbus_transport_new_for_socket (client_fd,
00258 NULL, &address);
00259 if (client_transport == NULL)
00260 {
00261 _dbus_close_socket (client_fd, NULL);
00262 _dbus_close_socket (server_fd, NULL);
00263 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00264 _dbus_string_free (&address);
00265 return NULL;
00266 }
00267
00268 _dbus_string_free (&address);
00269
00270 client_fd = -1;
00271
00272 server_transport = _dbus_transport_new_for_socket (server_fd,
00273 &server->guid_hex, NULL);
00274 if (server_transport == NULL)
00275 {
00276 _dbus_transport_unref (client_transport);
00277 _dbus_close_socket (server_fd, NULL);
00278 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00279 return NULL;
00280 }
00281
00282 server_fd = -1;
00283
00284 if (!_dbus_transport_set_auth_mechanisms (server_transport,
00285 (const char**) server->auth_mechanisms))
00286 {
00287 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00288 _dbus_transport_unref (server_transport);
00289 _dbus_transport_unref (client_transport);
00290 return NULL;
00291 }
00292
00293 connection = _dbus_connection_new_for_transport (server_transport);
00294 _dbus_transport_unref (server_transport);
00295 server_transport = NULL;
00296
00297 if (connection == NULL)
00298 {
00299 _dbus_transport_unref (client_transport);
00300 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00301 return NULL;
00302 }
00303
00304
00305
00306
00307 if (server->new_connection_function)
00308 {
00309 dbus_server_ref (server);
00310 (* server->new_connection_function) (server, connection,
00311 server->new_connection_data);
00312 dbus_server_unref (server);
00313 }
00314
00315
00316
00317
00318 _dbus_connection_close_if_only_one_ref (connection);
00319 dbus_connection_unref (connection);
00320
00321 return client_transport;
00322 }
00323
00335 DBusServerListenResult
00336 _dbus_server_listen_debug_pipe (DBusAddressEntry *entry,
00337 DBusServer **server_p,
00338 DBusError *error)
00339 {
00340 const char *method;
00341
00342 *server_p = NULL;
00343
00344 method = dbus_address_entry_get_method (entry);
00345
00346 if (strcmp (method, "debug-pipe") == 0)
00347 {
00348 const char *name = dbus_address_entry_get_value (entry, "name");
00349
00350 if (name == NULL)
00351 {
00352 _dbus_set_bad_address(error, "debug-pipe", "name",
00353 NULL);
00354 return DBUS_SERVER_LISTEN_BAD_ADDRESS;
00355 }
00356
00357 *server_p = _dbus_server_debug_pipe_new (name, error);
00358
00359 if (*server_p)
00360 {
00361 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00362 return DBUS_SERVER_LISTEN_OK;
00363 }
00364 else
00365 {
00366 _DBUS_ASSERT_ERROR_IS_SET(error);
00367 return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
00368 }
00369 }
00370 else
00371 {
00372 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
00373 return DBUS_SERVER_LISTEN_NOT_HANDLED;
00374 }
00375 }
00376
00385 DBusTransportOpenResult
00386 _dbus_transport_open_debug_pipe (DBusAddressEntry *entry,
00387 DBusTransport **transport_p,
00388 DBusError *error)
00389 {
00390 const char *method;
00391
00392 method = dbus_address_entry_get_method (entry);
00393 _dbus_assert (method != NULL);
00394
00395 if (strcmp (method, "debug-pipe") == 0)
00396 {
00397 const char *name = dbus_address_entry_get_value (entry, "name");
00398
00399 if (name == NULL)
00400 {
00401 _dbus_set_bad_address (error, "debug-pipe", "name",
00402 NULL);
00403 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
00404 }
00405
00406 *transport_p = _dbus_transport_debug_pipe_new (name, error);
00407
00408 if (*transport_p == NULL)
00409 {
00410 _DBUS_ASSERT_ERROR_IS_SET (error);
00411 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
00412 }
00413 else
00414 {
00415 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00416 return DBUS_TRANSPORT_OPEN_OK;
00417 }
00418 }
00419 else
00420 {
00421 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00422 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
00423 }
00424 }
00425
00426
00429 #endif
00430