2003-02-16 Anders Carlsson <andersca@codefactory.se>
[platform/upstream/dbus.git] / dbus / dbus-server-debug.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-server-debug.h In-proc debug server implementation 
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-server-debug.h"
26 #include "dbus-transport-debug.h"
27 #include "dbus-connection-internal.h"
28 #include "dbus-hash.h"
29
30 #ifdef DBUS_BUILD_TESTS
31
32 /**
33  * @defgroup DBusServerDebug DBusServerDebug
34  * @ingroup  DBusInternals
35  * @brief In-process debug server used in unit tests.
36  *
37  * Types and functions related to DBusServerDebug.
38  * This is used for unit testing.
39  *
40  * @{
41  */
42
43 /**
44  * Default timeout interval when reading or writing.
45  */
46 #define DEFAULT_INTERVAL 10
47
48 /**
49  * Opaque object representing a debug server implementation.
50  */
51 typedef struct DBusServerDebug DBusServerDebug;
52
53 /**
54  * Implementation details of DBusServerDebug. All members
55  * are private.
56  */
57 struct DBusServerDebug
58 {
59   DBusServer base;  /**< Parent class members. */
60
61   char *name; /**< Server name. */
62 };
63
64 /* Not thread safe, but OK since we don't use
65  * threads in the bus
66  */
67 static DBusHashTable *server_hash;
68
69 static void
70 debug_finalize (DBusServer *server)
71 {
72 }
73
74 static void
75 debug_handle_watch (DBusServer  *server,
76                     DBusWatch   *watch,
77                     unsigned int flags)
78 {
79 }
80
81 static void
82 debug_disconnect (DBusServer *server)
83 {
84 }
85
86 static DBusServerVTable debug_vtable = {
87   debug_finalize,
88   debug_handle_watch,
89   debug_disconnect
90 };
91
92 /**
93  * Looks up a server by its name.
94  *
95  * @param server_name the server name.
96  * @returns the server, or #NULL if none exists.
97  */
98 DBusServer*
99 _dbus_server_debug_lookup (const char *server_name)
100 {
101   if (!server_hash)
102     return NULL;
103
104   return _dbus_hash_table_lookup_string (server_hash, server_name);
105 }
106
107 /**
108  * Creates a new debug server.
109  *
110  * @param server_name the name of the server.
111  * @param result address where a result code can be returned.
112  * @returns a new server, or #NULL on failure.
113  */
114 DBusServer*
115 _dbus_server_debug_new (const char     *server_name,
116                         DBusResultCode *result)
117 {
118   DBusServerDebug *debug_server;
119
120   if (!server_hash)
121     {
122       server_hash = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL);
123
124       if (!server_hash)
125         {
126           dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
127           return NULL;
128         }
129     }
130
131   if (_dbus_hash_table_lookup_string (server_hash, server_name) != NULL)
132     {
133       dbus_set_result (result, DBUS_RESULT_ADDRESS_IN_USE);
134       return NULL;
135     }
136   
137   debug_server = dbus_new0 (DBusServerDebug, 1);
138
139   if (debug_server == NULL)
140     return NULL;
141
142   debug_server->name = _dbus_strdup (server_name);
143   if (debug_server->name == NULL)
144     {
145       dbus_free (debug_server->name);
146       dbus_free (debug_server);
147
148       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
149     }
150   
151   if (!_dbus_server_init_base (&debug_server->base,
152                                &debug_vtable))
153     {
154       dbus_free (debug_server->name);      
155       dbus_free (debug_server);
156
157       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
158
159       return NULL;
160     }
161
162   if (!_dbus_hash_table_insert_string (server_hash,
163                                        debug_server->name,
164                                        debug_server))
165     {
166       _dbus_server_finalize_base (&debug_server->base);
167       dbus_free (debug_server->name);      
168       dbus_free (debug_server);
169
170       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
171
172       return NULL;
173     }
174   
175   dbus_set_result (result, DBUS_RESULT_SUCCESS);
176   
177   return (DBusServer *)debug_server;
178 }
179
180 typedef struct
181 {
182   DBusServer *server;
183   DBusTransport *transport;
184   
185 } ServerAndTransport;
186
187 static void
188 handle_new_client (void *data)
189 {
190   ServerAndTransport *st = data;
191   DBusTransport *transport;
192   DBusConnection *connection;
193   
194   transport = _dbus_transport_debug_server_new (st->transport);
195   if (transport == NULL)
196     {
197       return;
198     }
199
200   connection = _dbus_connection_new_for_transport (transport);
201   _dbus_transport_unref (transport);
202
203   if (connection == NULL)
204     return;
205
206   /* See if someone wants to handle this new connection,
207    * self-referencing for paranoia
208    */
209   if (st->server->new_connection_function)
210     {
211       dbus_server_ref (st->server);
212       
213       (* st->server->new_connection_function) (st->server, connection,
214                                                st->server->new_connection_data);
215       dbus_server_unref (st->server);
216     }
217   
218   /* If no one grabbed a reference, the connection will die. */
219   dbus_connection_unref (connection);
220 }
221
222 /**
223  * Tells the server to accept a transport so the transport
224  * can send messages to it.
225  *
226  * @param server the server
227  * @param transport the transport
228  * @returns #TRUE on success.
229  */
230 dbus_bool_t
231 _dbus_server_debug_accept_transport (DBusServer     *server,
232                                      DBusTransport  *transport)
233 {
234   DBusTimeout *timeout = NULL;
235   ServerAndTransport *st = NULL;
236
237   st = dbus_new (ServerAndTransport, 1);
238   if (st == NULL)
239     return FALSE;
240
241   st->transport = transport;
242   st->server = server;
243   
244   timeout = _dbus_timeout_new (DEFAULT_INTERVAL, handle_new_client, st, dbus_free);
245
246   if (timeout == NULL)
247     goto failed;
248
249   if (!_dbus_server_add_timeout (server, timeout))
250     goto failed;
251
252   return TRUE;
253
254  failed:
255   dbus_free (st);
256   if (timeout)
257     _dbus_timeout_unref (timeout);
258   return FALSE;
259 }
260
261 /** @} */
262
263 #endif /* DBUS_BUILD_TESTS */
264