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