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 "dbus-internals.h"
00026 #include "dbus-server-debug-pipe.h"
00027 #include "dbus-transport-unix.h"
00028 #include "dbus-connection-internal.h"
00029 #include "dbus-hash.h"
00030
00031 #ifdef DBUS_BUILD_TESTS
00032
00047 typedef struct DBusServerDebugPipe DBusServerDebugPipe;
00048
00053 struct DBusServerDebugPipe
00054 {
00055 DBusServer base;
00057 char *name;
00059 dbus_bool_t disconnected;
00060 };
00061
00062
00063 static DBusHashTable *server_pipe_hash;
00064 static int server_pipe_hash_refcount = 0;
00065
00066 static dbus_bool_t
00067 pipe_hash_ref (void)
00068 {
00069 if (!server_pipe_hash)
00070 {
00071 _dbus_assert (server_pipe_hash_refcount == 0);
00072
00073 server_pipe_hash = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL);
00074
00075 if (!server_pipe_hash)
00076 return FALSE;
00077 }
00078
00079 server_pipe_hash_refcount = 1;
00080
00081 return TRUE;
00082 }
00083
00084 static void
00085 pipe_hash_unref (void)
00086 {
00087 _dbus_assert (server_pipe_hash != NULL);
00088 _dbus_assert (server_pipe_hash_refcount > 0);
00089
00090 server_pipe_hash_refcount -= 1;
00091 if (server_pipe_hash_refcount == 0)
00092 {
00093 _dbus_hash_table_unref (server_pipe_hash);
00094 server_pipe_hash = NULL;
00095 }
00096 }
00097
00098 static void
00099 debug_finalize (DBusServer *server)
00100 {
00101 DBusServerDebugPipe *debug_server = (DBusServerDebugPipe*) server;
00102
00103 pipe_hash_unref ();
00104
00105 _dbus_server_finalize_base (server);
00106
00107 dbus_free (debug_server->name);
00108 dbus_free (server);
00109 }
00110
00111 static void
00112 debug_disconnect (DBusServer *server)
00113 {
00114 ((DBusServerDebugPipe*)server)->disconnected = TRUE;
00115 }
00116
00117 static DBusServerVTable debug_vtable = {
00118 debug_finalize,
00119 debug_disconnect
00120 };
00121
00129 DBusServer*
00130 _dbus_server_debug_pipe_new (const char *server_name,
00131 DBusError *error)
00132 {
00133 DBusServerDebugPipe *debug_server;
00134 DBusString address;
00135
00136 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00137
00138 if (!pipe_hash_ref ())
00139 return NULL;
00140
00141 if (_dbus_hash_table_lookup_string (server_pipe_hash, server_name) != NULL)
00142 {
00143 dbus_set_error (error, DBUS_ERROR_ADDRESS_IN_USE, NULL);
00144 pipe_hash_unref ();
00145 return NULL;
00146 }
00147
00148 debug_server = dbus_new0 (DBusServerDebugPipe, 1);
00149 if (debug_server == NULL)
00150 goto nomem_0;
00151
00152 if (!_dbus_string_init (&address))
00153 goto nomem_1;
00154
00155 if (!_dbus_string_append (&address, "debug-pipe:name=") ||
00156 !_dbus_string_append (&address, server_name))
00157 goto nomem_2;
00158
00159 debug_server->name = _dbus_strdup (server_name);
00160 if (debug_server->name == NULL)
00161 goto nomem_2;
00162
00163 if (!_dbus_server_init_base (&debug_server->base,
00164 &debug_vtable, &address))
00165 goto nomem_3;
00166
00167 if (!_dbus_hash_table_insert_string (server_pipe_hash,
00168 debug_server->name,
00169 debug_server))
00170 goto nomem_4;
00171
00172 _dbus_string_free (&address);
00173
00174
00175
00176 return (DBusServer *)debug_server;
00177
00178 nomem_4:
00179 _dbus_server_finalize_base (&debug_server->base);
00180 nomem_3:
00181 dbus_free (debug_server->name);
00182 nomem_2:
00183 _dbus_string_free (&address);
00184 nomem_1:
00185 dbus_free (debug_server);
00186 nomem_0:
00187 pipe_hash_unref ();
00188 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00189 return NULL;
00190 }
00191
00201 DBusTransport*
00202 _dbus_transport_debug_pipe_new (const char *server_name,
00203 DBusError *error)
00204 {
00205 DBusTransport *client_transport;
00206 DBusTransport *server_transport;
00207 DBusConnection *connection;
00208 int client_fd, server_fd;
00209 DBusServer *server;
00210 DBusString address;
00211
00212 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00213
00214 if (server_pipe_hash == NULL)
00215 {
00216 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
00217 return NULL;
00218 }
00219
00220 server = _dbus_hash_table_lookup_string (server_pipe_hash,
00221 server_name);
00222 if (server == NULL ||
00223 ((DBusServerDebugPipe*)server)->disconnected)
00224 {
00225 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
00226 return NULL;
00227 }
00228
00229 if (!_dbus_string_init (&address))
00230 {
00231 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00232 return NULL;
00233 }
00234
00235 if (!_dbus_string_append (&address, "debug-pipe:name=") ||
00236 !_dbus_string_append (&address, server_name))
00237 {
00238 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00239 _dbus_string_free (&address);
00240 return NULL;
00241 }
00242
00243 if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE,
00244 NULL))
00245 {
00246 _dbus_verbose ("failed to create full duplex pipe\n");
00247 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe");
00248 _dbus_string_free (&address);
00249 return NULL;
00250 }
00251
00252 _dbus_fd_set_close_on_exec (client_fd);
00253 _dbus_fd_set_close_on_exec (server_fd);
00254
00255 client_transport = _dbus_transport_new_for_fd (client_fd,
00256 FALSE, &address);
00257 if (client_transport == NULL)
00258 {
00259 _dbus_close (client_fd, NULL);
00260 _dbus_close (server_fd, NULL);
00261 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00262 _dbus_string_free (&address);
00263 return NULL;
00264 }
00265
00266 _dbus_string_free (&address);
00267
00268 client_fd = -1;
00269
00270 server_transport = _dbus_transport_new_for_fd (server_fd,
00271 TRUE, NULL);
00272 if (server_transport == NULL)
00273 {
00274 _dbus_transport_unref (client_transport);
00275 _dbus_close (server_fd, NULL);
00276 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00277 return NULL;
00278 }
00279
00280 server_fd = -1;
00281
00282 if (!_dbus_transport_set_auth_mechanisms (server_transport,
00283 (const char**) server->auth_mechanisms))
00284 {
00285 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00286 _dbus_transport_unref (server_transport);
00287 _dbus_transport_unref (client_transport);
00288 return FALSE;
00289 }
00290
00291 connection = _dbus_connection_new_for_transport (server_transport);
00292 _dbus_transport_unref (server_transport);
00293 server_transport = NULL;
00294
00295 if (connection == NULL)
00296 {
00297 _dbus_transport_unref (client_transport);
00298 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00299 return NULL;
00300 }
00301
00302
00303
00304
00305 if (server->new_connection_function)
00306 {
00307 dbus_server_ref (server);
00308 (* server->new_connection_function) (server, connection,
00309 server->new_connection_data);
00310 dbus_server_unref (server);
00311 }
00312
00313
00314
00315
00316 dbus_connection_unref (connection);
00317
00318 return client_transport;
00319 }
00320
00321
00324 #endif
00325