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 #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 /* FIXME not threadsafe (right now the test suite doesn't use threads anyhow ) */
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   /* server keeps the pipe hash ref */
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   /* See if someone wants to handle this new connection,
00304    * self-referencing for paranoia
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   /* If no one grabbed a reference, the connection will die,
00315    * and the client transport will get an immediate disconnect
00316    */
00317   dbus_connection_unref (connection);
00318 
00319   return client_transport;
00320 }
00321 
00322 
00325 #endif /* DBUS_BUILD_TESTS */
00326 

Generated on Tue Feb 10 18:14:07 2004 for D-BUS by doxygen 1.3.5