Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-server-debug-pipe.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-server-debug-pipe.c In-proc debug server implementation 
00003  *
00004  * Copyright (C) 2003  CodeFactory AB
00005  * Copyright (C) 2003  Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 1.2
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /* FIXME not threadsafe (right now the test suite doesn't use threads anyhow ) */
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   /* server keeps the pipe hash ref */
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   /* See if someone wants to handle this new connection,
00303    * self-referencing for paranoia
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   /* If no one grabbed a reference, the connection will die,
00314    * and the client transport will get an immediate disconnect
00315    */
00316   dbus_connection_unref (connection);
00317 
00318   return client_transport;
00319 }
00320 
00321 
00324 #endif /* DBUS_BUILD_TESTS */
00325 

Generated on Wed Oct 22 14:05:03 2003 for D-BUS by doxygen1.3-rc3